From 0afa489d9c9c0a0ac99e553af0cffe2cb3a4047e Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 13 Dec 2024 13:20:42 -0700 Subject: [PATCH 001/276] WIP - create webserver state machine --- Firmware/RTK_Everywhere/Form.ino | 202 +++++++++++++++++++++-- Firmware/RTK_Everywhere/Network.ino | 33 ++-- Firmware/RTK_Everywhere/States.ino | 7 +- Firmware/RTK_Everywhere/WiFi.ino | 3 - Firmware/RTK_Everywhere/menuCommands.ino | 2 - Firmware/RTK_Everywhere/menuFirmware.ino | 6 +- Firmware/RTK_Everywhere/settings.h | 19 +++ 7 files changed, 234 insertions(+), 38 deletions(-) diff --git a/Firmware/RTK_Everywhere/Form.ino b/Firmware/RTK_Everywhere/Form.ino index 4f3fe7a9c..0d972a3c9 100644 --- a/Firmware/RTK_Everywhere/Form.ino +++ b/Firmware/RTK_Everywhere/Form.ino @@ -6,6 +6,16 @@ Form.ino #ifdef COMPILE_AP +static const char *const webconfigStateNames[] = { + "WEBCONFIG_STATE_OFF", "WEBCONFIG_STATE_WAIT_FOR_NETWORK", "WEBCONFIG_STATE_NETWORK_CONNECTED", + "WEBCONFIG_STATE_STARTED", "WEBCONFIG_STATE_RUNNING", +}; + +static const int webconfigStateEntries = sizeof(webconfigStateNames) / sizeof(webconfigStateNames[0]); + +static NetPriority_t webconfigPriority = NETWORK_OFFLINE; +static WebConfigState webconfigState; + // Once connected to the access point for WiFi Config, the ESP32 sends current setting values in one long string to // websocket After user clicks 'save', data is validated via main.js and a long string of values is returned. @@ -250,6 +260,171 @@ class CaptiveRequestHandler : public RequestHandler } }; +// State machine to handle the starting/stopping of the web server +void updateWebServer() +{ + if (!inMainMenu) + { + // Walk the state machine + switch (webconfigState) + { + default: + systemPrintf("ERROR: Unknown WebConfig state (%d)\r\n", webconfigState); + + // Stop the machine + webconfigStop(); + break; + + // Wait for a request from a user + case WEBCONFIG_STATE_OFF: + if (webconfigRequest == true) + otaSetState(WEBCONFIG_STATE_WAIT_FOR_NETWORK); + break; + + // Wait for connection to the network + case WEBCONFIG_STATE_WAIT_FOR_NETWORK: + // Determine if the request has been canceled while waiting + if (webconfigRequest == false) + webconfigUpdateStop(); + + // Wait until the network is connected to the media + else if (networkIsConnected(&webconfigPriority)) + { + if (settings.debugWebConfig) + systemPrintln("Web config connected to network"); + + webconfigSetState(WEBCONFIG_STATE_NETWORK_CONNECTED); + } + break; + + // Start the web server + case WEBCONFIG_STATE_NETWORK_CONNECTED: + + // Determine if the network has failed + if (!networkIsConnected(&webconfigPriority)) + webconfigStop(); + if (settings.debugWebConfig) + systemPrintln("Web config starting web server"); + + if (startWebServer(false, settings.httpPort) == true) + webconfigSetState(WEBCONFIG_STATE_STARTED); + + break; + + // Wait for web server to start + case WEBCONFIG_STATE_STARTED: + // Determine if the network has failed + if (!networkIsConnected(&webconfigPriority)) + webconfigStop(); + if (settings.debugWebConfig) + systemPrintln("Web config waiting for web server to start"); + + //... + webconfigSetState(WEBCONFIG_STATE_RUNNING); + + break; + + // Allow web services + case WEBCONFIG_STATE_RUNNING: + // Determine if the network has failed + if (!networkIsConnected(&webconfigPriority)) + webconfigStop(); + + // TODO how does the system indicate we need to shut down the web server? + if (inWiFiConfigMode() == false) + { + webconfigRequest = false; // Tell the network layer we no longer need access + webconfigStop(); + } + + //... + + break; + } + } +} + +// Stop the web config state machine +void webconfigStop() +{ + if (settings.debugWebConfig) + systemPrintln("webconfigStop called"); + + if (webconfigState != WEBCONFIG_STATE_OFF) + { + stop_wsserver(); // Release socket resources + stopWebServer(); // Release web server resources + + // Stop network + systemPrintln("Web Config releasing network request"); + + webconfigRequested = false; // Let the network know we no longer need it + + // Stop the machine + webconfigSetState(WEBCONFIG_STATE_OFF); + } +}; + +// Set the next webconfig state +void webconfigSetState(WebConfigState newState) +{ + char string1[40]; + char string2[40]; + const char *arrow = nullptr; + const char *asterisk = nullptr; + const char *initialState = nullptr; + const char *endingState = nullptr; + + // Display the state transition + if (settings.debugWebConfig) + { + arrow = ""; + asterisk = ""; + initialState = ""; + if (newState == otaState) + asterisk = "*"; + else + { + initialState = webconfigGetStateName(webconfigState, string1); + arrow = " --> "; + } + } + + // Set the new state + webconfigState = newState; + if (settings.debugWebConfig) + { + // Display the new firmware update state + endingState = webconfigGetStateName(newState, string2); + if (!online.rtc) + systemPrintf("%s%s%s%s\r\n", asterisk, initialState, arrow, endingState); + else + { + // Timestamp the state change + // 1 2 + // 12345678901234567890123456 + // YYYY-mm-dd HH:MM:SS.xxxrn0 + struct tm timeinfo = rtc.getTimeStruct(); + char s[30]; + strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", &timeinfo); + systemPrintf("%s%s%s%s, %s.%03ld\r\n", asterisk, initialState, arrow, endingState, s, rtc.getMillis()); + } + } + + // Validate the state + if (newState >= WEBCONFIG_STATE_MAX) + reportFatalError("Invalid web config state"); +} + +// Get the webconfig state name +const char *webconfigGetStateName(WebConfigState state, char *string) +{ + if (state < WEBCONFIG_STATE_MAX) + return webconfigStateNames[state]; + sprintf(string, "Unknown state (%d)", state); + return string; +} + // Start webserver in AP mode bool startWebServer(bool startWiFi = true, int httpPort = 80) { @@ -259,15 +434,15 @@ bool startWebServer(bool startWiFi = true, int httpPort = 80) for (int serverIndex = 0; serverIndex < NTRIP_SERVER_MAX; serverIndex++) ntripServerStop(serverIndex, true); // Do not allocate new wifiClient - if (startWiFi) - if (wifiStartAP() == false) - break; + // if (startWiFi) + // if (wifiStartAP() == false) + // break; - // Start the multicast DNS server - if (startWiFi == true) - networkMulticastDNSSwitch(NETWORK_WIFI); - else - networkMulticastDNSSwitch(NETWORK_ETHERNET); + // // Start the multicast DNS server + // if (startWiFi == true) + // networkMulticastDNSSwitch(NETWORK_WIFI); + // else + // networkMulticastDNSSwitch(NETWORK_ETHERNET); // Freed by stopWebServer if (online.psram == true) @@ -565,6 +740,11 @@ void stopWebServer() if (task.updateWebServerTaskRunning) task.updateWebServerTaskStopRequest = true; + // Wait for task to stop running + do + delay(10); + while (task.updateWebServerTaskRunning); + if (webserver != nullptr) { webserver->close(); @@ -586,10 +766,6 @@ void stopWebServer() free(incomingSettings); incomingSettings = nullptr; } - - do - delay(10); - while (task.updateWebServerTaskRunning); } void notFound() @@ -825,7 +1001,7 @@ static void handleFirmwareFileUpload() } } -// Report back to the web config page with a CSV that contains the either CURRENT or +// Report back to the web config page with a CSV that contains the either CURRENT or // the latest version as obtained by the OTA state machine void createFirmwareVersionString(char *settingsCSV) { diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 02fd095db..71ba2b2c6 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -770,7 +770,7 @@ void networkMarkOnline(NetIndex_t index) //---------------------------------------- // Change multicast DNS to a given network -// +// //---------------------------------------- void networkMulticastDNSSwitch(NetIndex_t startIndex) { @@ -780,7 +780,7 @@ void networkMulticastDNSSwitch(NetIndex_t startIndex) networkMulticastDNSStop(index); // Start mDNS on the requested network - networkMulticastDNSStart(startIndex); //Start DNS on the selected network, either WiFi or Ethernet + networkMulticastDNSStart(startIndex); // Start DNS on the selected network, either WiFi or Ethernet } //---------------------------------------- @@ -1333,18 +1333,14 @@ void networkUpdate() if (networkConsumers() == 0 && networkIsOnline() == true) { - if (systemState == STATE_WIFI_CONFIG) - { - // The STATE_WIFI_CONFIG is in control of WiFi. Don't allow the network layer to shut it down - // As OTA exits, we need to keep AP running if we are in Web Config mode - // We don't want to make STATE_WIFI_CONFIG a consumer until startWebServer() uses the network layer - } - else - { - // Shutdown all networks - for (int index = 0; index < NETWORK_OFFLINE; index++) - networkStop(index, settings.debugNetworkLayer); - } + // The STATE_WIFI_CONFIG is in control of WiFi. Don't allow the network layer to shut it down + // As OTA exits, we need to keep AP running if we are in Web Config mode + // We don't want to make STATE_WIFI_CONFIG a consumer until startWebServer() uses the network layer + // To do that, startWebServer() needs a state machine to wait for the network to come online + + // Shutdown all networks + for (int index = 0; index < NETWORK_OFFLINE; index++) + networkStop(index, settings.debugNetworkLayer); } // Allow consumers to start networks @@ -1545,6 +1541,13 @@ uint8_t networkConsumers() consumerType |= (1 << 8); } + // Network needed for Web Config + if (inWiFiConfigMode() == true) + { + consumerCount++; + consumerType |= (1 << 9); + } + // Debug if (settings.debugNetworkLayer) { @@ -1576,6 +1579,8 @@ uint8_t networkConsumers() systemPrint("OTA Version Check, "); if (consumerType & (1 << 8)) systemPrint("OTA Scheduled Check, "); + if (consumerType & (1 << 9)) + systemPrint("WiFi Config Mode, "); } systemPrintln(); diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 9ad80df2c..2424c9d53 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -414,12 +414,13 @@ void stateUpdate() displayWiFiConfigNotStarted(); // Display immediately during SD cluster pause - WIFI_STOP(); // Notify the network layer that it should stop so we can take over control of WiFi + //WIFI_STOP(); // Notify the network layer that it should stop so we can take over control of WiFi bluetoothStop(); espnowStop(); tasksStopGnssUart(); // Delete serial tasks if running - if (!startWebServer()) // Start web server in WiFi mode and show config html page + // if (!startWebServer()) // Start web server in WiFi mode and show config html page + if (!startWebServer(false, settings.httpPort)) // Start the web server. Network layer starts WiFi. changeState(STATE_ROVER_NOT_STARTED); else { @@ -479,7 +480,7 @@ void stateUpdate() sendStringToWebsocket(settingsCSV); - otaReportedVersion[0] = '\0'; //Zero out the reported version + otaReportedVersion[0] = '\0'; //Zero out the reported version to stop future reports } } diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index e23b3ac38..75b62abb7 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -561,9 +561,6 @@ NETWORK_POLL_SEQUENCE wifiStopSequence[] = { //---------------------------------------- void wifiStop() { - // Stop the web server - stopWebServer(); - // Stop the DNS server if we were using the captive portal if (((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) && settings.enableCaptivePortal) dnsServer.stop(); diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index 290c4f0ee..32ba3ada5 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -1362,8 +1362,6 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting // Notify the network layer we need access, and let OTA state machine take over otaRequestFirmwareUpdate = true; - otaForcedUpdate(); // otaForcedUpdate will call wifiConnect if needed. Also does previouslyConnected check - // We get here if WiFi failed to connect sendStringToWebsocket((char *)"gettingNewFirmware,ERROR,"); knownSetting = true; diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index 907bf595b..ab3e8f946 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -513,7 +513,7 @@ void otaUpdateFirmware() #endif // COMPILE_NETWORK } -// Start WiFi outside of the network layer and perform the over-the-air update +// Start WiFi STA outside of the network layer and perform the over-the-air update void otaForcedUpdate() { #ifdef COMPILE_NETWORK @@ -522,7 +522,7 @@ void otaForcedUpdate() if (!networkIsOnline()) { if (wifiNetworkCount() == 0) - systemPrintln("Error: Please enter at least one SSID before getting keys"); + systemPrintln("Error: Please enter at least one SSID before updating firmware"); else systemPrintln("Error: Network not available!"); } @@ -535,7 +535,7 @@ void otaForcedUpdate() true)) // Use WIFI_AP_STA if already in WIFI_AP mode otaUpdateFirmware(); - // Update failed. + // If we're here, the update failed // If we were in WIFI_AP mode, return to WIFI_AP mode if (wasInAPmode) wifiSetApMode(); diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index efd1f3307..33279290c 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -557,6 +557,25 @@ enum OtaState #endif // COMPILE_OTA_AUTO +#ifdef COMPILE_AP + +// Web Config state machine to allow web server access to network layer +enum WebConfigState +{ + WEBCONFIG_STATE_OFF = 0, + WEBCONFIG_STATE_WAIT_FOR_NETWORK, + WEBCONFIG_STATE_NETWORK_CONNECTED, + WEBCONFIG_STATE_STARTED, + WEBCONFIG_STATE_RUNNING, + + // Add new states here + WEBCONFIG_STATE_MAX +}; + +#endif // COMPILE_OTA_AUTO + + + // Regional Support // Some regions have both L-Band and IP. More just have IP. // Do we want the user to be able to specify which region they are in? From 33d0fbf6dfa87773681f09956d2e51c775081726 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 16 Dec 2024 17:04:30 +0000 Subject: [PATCH 002/276] Update non-release-build.yml to match compile-rtk-everywhere.yml --- .github/workflows/non-release-build.yml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/workflows/non-release-build.yml b/.github/workflows/non-release-build.yml index 9e82f6fd3..b02507457 100644 --- a/.github/workflows/non-release-build.yml +++ b/.github/workflows/non-release-build.yml @@ -10,7 +10,7 @@ env: POINTPERFECT_LBAND_TOKEN: ${{ secrets.POINTPERFECT_LBAND_TOKEN }} POINTPERFECT_IP_TOKEN: ${{ secrets.POINTPERFECT_IP_TOKEN }} POINTPERFECT_LBAND_IP_TOKEN: ${{ secrets.POINTPERFECT_LBAND_IP_TOKEN }} - CORE_VERSION: 3.0.1 + CORE_VERSION: 3.0.7 jobs: build: @@ -78,7 +78,7 @@ jobs: run: arduino-cli lib install ArduinoJson@7.0.4 ESP32Time@2.0.0 - ESP32_BleSerial@1.0.4 + ESP32_BleSerial@2.0.1 "ESP32-OTA-Pull"@1.0.0 JC_Button@2.1.2 PubSubClient@2.8.0 @@ -88,18 +88,14 @@ jobs: "SparkFun u-blox GNSS v3"@3.1.8 "SparkFun Qwiic OLED Arduino Library"@1.0.13 SSLClientESP32@2.0.0 - "SparkFun Extensible Message Parser"@1.0.0 + "SparkFun Extensible Message Parser"@1.0.2 "SparkFun BQ40Z50 Battery Manager Arduino Library"@1.0.0 "ArduinoMqttClient"@0.1.8 "SparkFun u-blox PointPerfect Library"@1.11.4 "SparkFun IM19 IMU Arduino Library"@1.0.1 "SparkFun UM980 Triband RTK GNSS Arduino Library"@1.0.4 - - # https://github.com/avinabmalla/ESP32_BleSerial/issues/15 - - name: Patch ESP32_BleSerial BLECharacteristic - run: | - cd Firmware/RTK_Everywhere/Patch/ - cp BleSerial.cpp /home/runner/Arduino/libraries/ESP32_BleSerial/src/BleSerial.cpp + "SparkFun LG290P Quadband RTK GNSS Arduino Library"@1.0.0 + "SparkFun I2C Expander Arduino Library"@1.0.1 - name: Patch libmbedtls run: | @@ -109,6 +105,11 @@ jobs: cp libmbedcrypto.a /home/runner/.arduino15/packages/esp32/tools/esp32-arduino-libs/${{ env.ESP_IDF }}/esp32/lib/libmbedcrypto.a cp libmbedx509.a /home/runner/.arduino15/packages/esp32/tools/esp32-arduino-libs/${{ env.ESP_IDF }}/esp32/lib/libmbedx509.a + - name: Patch NetworkEvents + run: | + cd Firmware/RTK_Everywhere/Patch/ + cp NetworkEvents.* /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/libraries/Network/src/ + - name: Setup Python uses: actions/setup-python@v4 with: @@ -139,12 +140,12 @@ jobs: - name: Copy custom RTKEverywhere.csv run: - cp Firmware/RTKEverywhere.csv /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/tools/partitions/RTKEverywhere.csv + cp Firmware/RTKEverywhere_8MB.csv /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/tools/partitions/RTKEverywhere.csv - name: Compile Sketch run: arduino-cli compile --fqbn "esp32:esp32:esp32":DebugLevel=${{ env.DEBUG_LEVEL }},PSRAM=enabled ./Firmware/RTK_Everywhere/RTK_Everywhere.ino --build-property build.partitions=RTKEverywhere - --build-property upload.maximum_size=3145728 + --build-property upload.maximum_size=4055040 --build-property "compiler.cpp.extra_flags=-MMD -c \"-DPOINTPERFECT_LBAND_TOKEN=$POINTPERFECT_LBAND_TOKEN\" \"-DPOINTPERFECT_IP_TOKEN=$POINTPERFECT_IP_TOKEN\" \"-DPOINTPERFECT_LBAND_IP_TOKEN=$POINTPERFECT_LBAND_IP_TOKEN\" \"-DFIRMWARE_VERSION_MAJOR=$FIRMWARE_VERSION_MAJOR\" \"-DFIRMWARE_VERSION_MINOR=$FIRMWARE_VERSION_MINOR\" \"-DENABLE_DEVELOPER=${{ env.ENABLE_DEVELOPER }}\"" --export-binaries From a7b83b632612886f9a3eef6c8ed778471aca78db Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 16 Dec 2024 17:05:12 +0000 Subject: [PATCH 003/276] Use correct (8MB) partitions file during compile --- .github/workflows/compile-rtk-everywhere.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile-rtk-everywhere.yml b/.github/workflows/compile-rtk-everywhere.yml index 3ddb27a1d..fa7926c72 100644 --- a/.github/workflows/compile-rtk-everywhere.yml +++ b/.github/workflows/compile-rtk-everywhere.yml @@ -140,7 +140,7 @@ jobs: - name: Copy custom RTKEverywhere.csv run: - cp Firmware/RTKEverywhere.csv /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/tools/partitions/RTKEverywhere.csv + cp Firmware/RTKEverywhere_8MB.csv /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/tools/partitions/RTKEverywhere.csv - name: Compile Sketch run: arduino-cli compile --fqbn "esp32:esp32:esp32":DebugLevel=${{ env.DEBUG_LEVEL }},PSRAM=enabled ./Firmware/RTK_Everywhere/RTK_Everywhere.ino From 0e61f8ce9d5cf1b5d011f282fc814cdbff908ac7 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 17 Dec 2024 17:20:48 -0700 Subject: [PATCH 004/276] Don't save/reset LG290P until end of configuration --- Firmware/RTK_Everywhere/GNSS_LG290P.h | 2 +- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 38 ++++++++++++++++--------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.h b/Firmware/RTK_Everywhere/GNSS_LG290P.h index 500a5b761..9c4b96db9 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.h +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.h @@ -154,7 +154,7 @@ class GNSS_LG290P : GNSS void debuggingEnable(); - bool disableSurveyIn(); + bool disableSurveyIn(bool saveAndReset); void enableGgaForNtrip(); diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index db91ea72a..4e5e93ef5 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -37,7 +37,7 @@ void GNSS_LG290P::baseRtcmLowDataRate() settings.lg290pMessageRatesRTCMBase[x] = 0; settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-1005")] = - 10; // 1005 0.1Hz - Exclude antenna height + 10; // 1005 0.1Hz - Exclude antenna height settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-107X")] = 2; // 1074 0.5Hz settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-108X")] = 2; // 1084 0.5Hz settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-109X")] = 2; // 1094 0.5Hz @@ -286,7 +286,7 @@ bool GNSS_LG290P::configureRover() } // Set the fix rate. Default on LG290P is 10Hz so set accordingly. - response &= setRate(settings.measurementRateMs / 1000.0); + response &= setRate(settings.measurementRateMs / 1000.0); // May require save/reset if (settings.debugGnss && response == false) systemPrintln("Rover: Set rate failed"); @@ -358,7 +358,7 @@ bool GNSS_LG290P::configureBase() // response &= _lg290p->setModeBase(); // Wait for save and reset // Ignore result for now. enterConfigMode disables NMEA, which causes the built-in write/save/reset methods to // fail because NMEA is not present. - _lg290p->setModeBase(); // Wait for save and reset + _lg290p->setModeBase(false); // Don't save and reset if (settings.debugGnss && response == false) systemPrintln("Base: Set mode base failed"); @@ -372,7 +372,7 @@ bool GNSS_LG290P::configureBase() // response &= disableSurveyIn(); // Wait for save and reset // Ignore result for now. enterConfigMode disables NMEA, which causes the built-in write/save/reset methods to // fail because NMEA is not present. - disableSurveyIn(); // Wait for save and reset + disableSurveyIn(false); // Don't save and reset if (settings.debugGnss && response == false) systemPrintln("Base: disable survey in failed"); } @@ -452,7 +452,7 @@ bool GNSS_LG290P::exitConfigMode() //---------------------------------------- // Disable Survey-In //---------------------------------------- -bool GNSS_LG290P::disableSurveyIn() +bool GNSS_LG290P::disableSurveyIn(bool saveAndReset) { bool response = false; if (online.gnss) @@ -460,12 +460,16 @@ bool GNSS_LG290P::disableSurveyIn() response = _lg290p->sendOkCommand("$PQTMCFGSVIN", ",W,0,0,0,0,0,0"); // Disable survey mode if (settings.debugGnss && response == false) systemPrintln("disableSurveyIn: sendOkCommand failed"); - response &= saveConfiguration(); - if (settings.debugGnss && response == false) - systemPrintln("disableSurveyIn: save failed"); - response &= softwareReset(); - if (settings.debugGnss && response == false) - systemPrintln("disableSurveyIn: reset failed"); + + if (saveAndReset) + { + response &= saveConfiguration(); + if (settings.debugGnss && response == false) + systemPrintln("disableSurveyIn: save failed"); + response &= softwareReset(); + if (settings.debugGnss && response == false) + systemPrintln("disableSurveyIn: reset failed"); + } } return (response); @@ -547,6 +551,8 @@ bool GNSS_LG290P::enableRTCMBase() bool response = true; bool enableMSM = false; // Goes true if we need to enable MSM output reporting + Serial.println("\r\n Enabling RTCM"); + for (int messageNumber = 0; messageNumber < MAX_LG290P_RTCM_MSG; messageNumber++) { // Setting RTCM-1005 must have only the rate @@ -583,6 +589,10 @@ bool GNSS_LG290P::enableRTCMBase() if (enableMSM == true) { + if(settings.debugGnss) + + systemPrintln("Enabling RTCM MSM output"); + // PQTMCFGRTCM fails to respond with OK over UART2 of LG290P, so don't look for it _lg290p->sendOkCommand( "PQTMCFGRTCM,W,7,0,-90,07,06,2,1"); // Enable MSM7, output regular intervals, interval (seconds) @@ -738,7 +748,8 @@ bool GNSS_LG290P::fixedBaseStart() if (settings.fixedBaseCoordinateType == COORD_TYPE_ECEF) { - _lg290p->setSurveyFixedMode(settings.fixedEcefX, settings.fixedEcefY, settings.fixedEcefZ); + // Waits for save and reset + response &= _lg290p->setSurveyFixedMode(settings.fixedEcefX, settings.fixedEcefY, settings.fixedEcefZ); } else if (settings.fixedBaseCoordinateType == COORD_TYPE_GEODETIC) { @@ -755,7 +766,8 @@ bool GNSS_LG290P::fixedBaseStart() // Convert LLA to ECEF geodeticToEcef(settings.fixedLat, settings.fixedLong, totalFixedAltitude, &ecefX, &ecefY, &ecefZ); - _lg290p->setSurveyFixedMode(ecefX, ecefY, ecefZ); + // Waits for save and reset + response &= _lg290p->setSurveyFixedMode(ecefX, ecefY, ecefZ); } return (response); From 90c76d58e29050e93c729932f7aee04daf375601 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 17 Dec 2024 17:21:58 -0700 Subject: [PATCH 005/276] Correctly set MSM enable --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index 4e5e93ef5..6a8405e68 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -583,7 +583,7 @@ bool GNSS_LG290P::enableRTCMBase() } // If any message is enabled, enable MSM output - if (lgMessagesRTCM[messageNumber].msgTextName, settings.lg290pMessageRatesRTCMRover[messageNumber] == true) + if (settings.lg290pMessageRatesRTCMRover[messageNumber] == true) enableMSM = true; } From efd7b2a18dd6cb25be86a8f06126c30cf45f5e1c Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 18 Dec 2024 14:20:02 -0700 Subject: [PATCH 006/276] Rename define --- Firmware/RTK_Everywhere/Tasks.ino | 12 ++++++------ Firmware/RTK_Everywhere/menuSystem.ino | 8 ++++---- Firmware/RTK_Everywhere/settings.h | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index 896d894e6..37b846191 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -289,18 +289,18 @@ void sendGnssBuffer() { if (gnss->pushRawData(bluetoothOutgoingToGnss, bluetoothOutgoingToGnssHead)) { - if ((settings.debugCorrections || PERIODIC_DISPLAY(PD_ZED_DATA_TX)) && !inMainMenu) + if ((settings.debugCorrections || PERIODIC_DISPLAY(PD_GNSS_DATA_TX)) && !inMainMenu) { - PERIODIC_CLEAR(PD_ZED_DATA_TX); + PERIODIC_CLEAR(PD_GNSS_DATA_TX); systemPrintf("Sent %d BT bytes to GNSS\r\n", bluetoothOutgoingToGnssHead); } } } else { - if ((settings.debugCorrections || PERIODIC_DISPLAY(PD_ZED_DATA_TX)) && !inMainMenu) + if ((settings.debugCorrections || PERIODIC_DISPLAY(PD_GNSS_DATA_TX)) && !inMainMenu) { - PERIODIC_CLEAR(PD_ZED_DATA_TX); + PERIODIC_CLEAR(PD_GNSS_DATA_TX); systemPrintf("%d BT bytes NOT sent due to priority\r\n", bluetoothOutgoingToGnssHead); } } @@ -573,9 +573,9 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type) int32_t use; // Display the message - if ((settings.enablePrintLogFileMessages || PERIODIC_DISPLAY(PD_ZED_DATA_RX)) && (!parse->crc) && (!inMainMenu)) + if ((settings.enablePrintLogFileMessages || PERIODIC_DISPLAY(PD_GNSS_DATA_RX)) && (!parse->crc) && (!inMainMenu)) { - PERIODIC_CLEAR(PD_ZED_DATA_RX); + PERIODIC_CLEAR(PD_GNSS_DATA_RX); if (settings.enablePrintLogFileMessages) { printTimeStamp(); diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index 4bec7b477..9d963bcaa 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -1147,10 +1147,10 @@ void menuPeriodicPrint() systemPrintf("%s\r\n", PERIODIC_SETTING(PD_WIFI_STATE) ? "Enabled" : "Disabled"); systemPrint("8) ZED RX data: "); - systemPrintf("%s\r\n", PERIODIC_SETTING(PD_ZED_DATA_RX) ? "Enabled" : "Disabled"); + systemPrintf("%s\r\n", PERIODIC_SETTING(PD_GNSS_DATA_RX) ? "Enabled" : "Disabled"); systemPrint("9) ZED TX data: "); - systemPrintf("%s\r\n", PERIODIC_SETTING(PD_ZED_DATA_TX) ? "Enabled" : "Disabled"); + systemPrintf("%s\r\n", PERIODIC_SETTING(PD_GNSS_DATA_TX) ? "Enabled" : "Disabled"); systemPrintln("----- Software -----"); @@ -1270,9 +1270,9 @@ void menuPeriodicPrint() else if (incoming == 7) PERIODIC_TOGGLE(PD_WIFI_STATE); else if (incoming == 8) - PERIODIC_TOGGLE(PD_ZED_DATA_RX); + PERIODIC_TOGGLE(PD_GNSS_DATA_RX); else if (incoming == 9) - PERIODIC_TOGGLE(PD_ZED_DATA_TX); + PERIODIC_TOGGLE(PD_GNSS_DATA_TX); else if (incoming == 20) { diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index efd1f3307..d014f925e 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -301,8 +301,8 @@ enum PeriodDisplayValues PD_CELLULAR_STATE, // 28 PD_WIFI_STATE, // 29 - PD_ZED_DATA_RX, // 30 - PD_ZED_DATA_TX, // 31 + PD_GNSS_DATA_RX, // 30 + PD_GNSS_DATA_TX, // 31 PD_MQTT_CLIENT_DATA, // 32 PD_MQTT_CLIENT_STATE, // 33 From 1a0baed6ec73b093dae12ec4fa498a75b24a389d Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 18 Dec 2024 15:09:10 -0700 Subject: [PATCH 007/276] Use getSatellitesInViewCount() Fix #505. In Base mode, getSatellitesInViewCount is correctly calculated where as getSatellitesUsedCount is always zero. --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 7 ++++--- Firmware/RTK_Everywhere/menuSystem.ino | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index 6a8405e68..c5517344b 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -1111,9 +1111,10 @@ uint8_t GNSS_LG290P::getRtcmMessageNumberByName(const char *msgName) uint8_t GNSS_LG290P::getSatellitesInView() { if (online.gnss) - // return (_lg290p->getSatellitesInView()); - // Use getSatellitesUsed until SIV works correctly - return (_lg290p->getSatellitesUsedCount()); + return (_lg290p->getSatellitesInViewCount() - 4); + // As of v1.0.1 of the LG290P library, getSatellitesInViewCount is reporting staillites that + // have 0 in view ("00"). NAVIC and QZSS satellites are the most common problem. Artificially + // reducing until a fix is in place. return 0; } diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index 9d963bcaa..99fbd2642 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -1146,10 +1146,10 @@ void menuPeriodicPrint() systemPrint("7) WiFi state: "); systemPrintf("%s\r\n", PERIODIC_SETTING(PD_WIFI_STATE) ? "Enabled" : "Disabled"); - systemPrint("8) ZED RX data: "); + systemPrint("8) GNSS RX data: "); systemPrintf("%s\r\n", PERIODIC_SETTING(PD_GNSS_DATA_RX) ? "Enabled" : "Disabled"); - systemPrint("9) ZED TX data: "); + systemPrint("9) GNSS TX data: "); systemPrintf("%s\r\n", PERIODIC_SETTING(PD_GNSS_DATA_TX) ? "Enabled" : "Disabled"); systemPrintln("----- Software -----"); From 46ac60483f725b8f38878a60d874c8fd9868c95f Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 18 Dec 2024 15:13:11 -0700 Subject: [PATCH 008/276] Increase version --- .github/workflows/compile-rtk-everywhere.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile-rtk-everywhere.yml b/.github/workflows/compile-rtk-everywhere.yml index 3ddb27a1d..d0877b82e 100644 --- a/.github/workflows/compile-rtk-everywhere.yml +++ b/.github/workflows/compile-rtk-everywhere.yml @@ -6,7 +6,7 @@ on: env: FILENAME_PREFIX: RTK_Everywhere_Firmware FIRMWARE_VERSION_MAJOR: 2 - FIRMWARE_VERSION_MINOR: 0 + FIRMWARE_VERSION_MINOR: 1 POINTPERFECT_LBAND_TOKEN: ${{ secrets.POINTPERFECT_LBAND_TOKEN }} POINTPERFECT_IP_TOKEN: ${{ secrets.POINTPERFECT_IP_TOKEN }} POINTPERFECT_LBAND_IP_TOKEN: ${{ secrets.POINTPERFECT_LBAND_IP_TOKEN }} From 17f672165d00ed833b5f8e0ee9e6387cd5f1db5b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 18 Dec 2024 22:14:57 +0000 Subject: [PATCH 009/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index d9349d220..aeab7dea6 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x92, 0xA5, 0x5C, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0x60, 0x49, 0x63, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0x1B, 0xB9, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x1D, 0xDF, 0x73, 0xC7, 0xE6, 0x60, 0x8C, 0x6D, 0x3E, 0x12, 0x42, 0xC8, 0x5E, 0x02, 0x24, 0xE1, 0x9E, 0x40, 0xB8, 0x98, 0xCC, 0x4C, 0x26, 0x27, 0xCB, 0x36, 0x6E, 0x61, 0x7A, 0x63, @@ -1020,7 +1020,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x92, 0xA5, 0x5C, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0x60, 0x49, 0x63, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xE9, 0x72, 0xDB, 0x48, 0x93, 0xE0, 0xFF, 0x7E, 0x8A, 0xFA, 0x38, 0x3B, 0x63, 0x69, 0x46, 0xA4, 0x78, 0x48, 0xB2, 0xAC, 0xB6, 0x15, 0xA1, 0xCB, 0xB6, 0xF6, 0x93, 0x6C, 0x8E, 0x28, 0x7F, 0x7D, 0x6C, 0xEC, 0x76, 0x40, From c63f338937c0c651cdb46d62f7e41d4325735fbd Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 18 Dec 2024 16:03:45 -0700 Subject: [PATCH 010/276] getSatellitesInViewCount is correct --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index c5517344b..4e54add90 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -1111,10 +1111,7 @@ uint8_t GNSS_LG290P::getRtcmMessageNumberByName(const char *msgName) uint8_t GNSS_LG290P::getSatellitesInView() { if (online.gnss) - return (_lg290p->getSatellitesInViewCount() - 4); - // As of v1.0.1 of the LG290P library, getSatellitesInViewCount is reporting staillites that - // have 0 in view ("00"). NAVIC and QZSS satellites are the most common problem. Artificially - // reducing until a fix is in place. + return (_lg290p->getSatellitesInViewCount()); return 0; } From 204fb9bd9970fa3381c11917a7fbbd786a7560f8 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 18 Dec 2024 16:07:48 -0700 Subject: [PATCH 011/276] Allow RC firmware Fix #393 --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 2 -- Firmware/RTK_Everywhere/menuFirmware.ino | 37 ++++++++++++++---------- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index 4e54add90..0a6f4a818 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -551,8 +551,6 @@ bool GNSS_LG290P::enableRTCMBase() bool response = true; bool enableMSM = false; // Goes true if we need to enable MSM output reporting - Serial.println("\r\n Enabling RTCM"); - for (int messageNumber = 0; messageNumber < MAX_LG290P_RTCM_MSG; messageNumber++) { // Setting RTCM-1005 must have only the rate diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index aa39a92a6..199762037 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -461,6 +461,9 @@ bool otaCheckVersion(char *versionAvailable, uint8_t versionAvailableLength) // Call getVersion after original inquiry String otaVersion = ota.GetVersion(); otaVersion.toCharArray(versionAvailable, versionAvailableLength); + + if (settings.debugFirmwareUpdate) + systemPrintf("Reported version available: %s\r\n", versionAvailable); } else if (response == ESP32OTAPull::HTTP_FAILED) { @@ -809,7 +812,9 @@ void otaUpdateStop() if (otaState != OTA_STATE_OFF) { // Stop network - systemPrintln("Firmware update releasing network request"); + if (settings.debugFirmwareUpdate) + systemPrintln("Firmware update releasing network request"); + online.otaFirmwareUpdate = false; otaRequestFirmwareUpdate = false; // Let the network know we no longer need it @@ -882,34 +887,36 @@ void otaUpdate() if (settings.debugFirmwareUpdate) systemPrintln("Firmware update checking SparkFun released firmware version"); - // Only update to production firmware, disable release candidates - enableRCFirmware = 0; + // If we are using auto updates, only update to production firmware, disable release candidates + if (settings.enableAutoFirmwareUpdate) + enableRCFirmware = 0; // Get firmware version from server otaReportedVersion[0] = 0; if (otaCheckVersion(otaReportedVersion, sizeof(otaReportedVersion))) { - // If we are doing just a version check, set version number, turn off network request and stop machine - if (otaRequestFirmwareVersionCheck == true) - { - otaRequestFirmwareVersionCheck = false; - otaUpdateStop(); - return; - } - // Create a string of the unit's current firmware version char currentVersion[21]; getFirmwareVersion(currentVersion, sizeof(currentVersion), enableRCFirmware); - // If we are doing a scheduled automatic update or a manually requested update, continue through the - // state machine - // We got a version number, now determine if it's newer or not + // Allow update if locally compiled developer version if ((isReportedVersionNewer(otaReportedVersion, ¤tVersion[1]) == true) || (currentVersion[0] == 'd') || (FIRMWARE_VERSION_MAJOR == 99)) { - // Allow update if locally compiled developer version systemPrintf("Version Check: New firmware version available: %s\r\n", otaReportedVersion); + + // If we are doing just a version check, set version number, turn off network request and stop + // machine + if (otaRequestFirmwareVersionCheck == true) + { + otaRequestFirmwareVersionCheck = false; + otaUpdateStop(); + return; + } + + // If we are doing a scheduled automatic update or a manually requested update, continue through the + // state machine otaSetState(OTA_STATE_UPDATE_FIRMWARE); } else From ac4ba63f5e2444244527d410f75597d5cb2ef1c6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 18 Dec 2024 23:12:09 +0000 Subject: [PATCH 012/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index aeab7dea6..6d4924c8a 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x60, 0x49, 0x63, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0xC8, 0x56, 0x63, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0x1B, 0xB9, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x1D, 0xDF, 0x73, 0xC7, 0xE6, 0x60, 0x8C, 0x6D, 0x3E, 0x12, 0x42, 0xC8, 0x5E, 0x02, 0x24, 0xE1, 0x9E, 0x40, 0xB8, 0x98, 0xCC, 0x4C, 0x26, 0x27, 0xCB, 0x36, 0x6E, 0x61, 0x7A, 0x63, @@ -1020,7 +1020,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x60, 0x49, 0x63, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0xC8, 0x56, 0x63, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xE9, 0x72, 0xDB, 0x48, 0x93, 0xE0, 0xFF, 0x7E, 0x8A, 0xFA, 0x38, 0x3B, 0x63, 0x69, 0x46, 0xA4, 0x78, 0x48, 0xB2, 0xAC, 0xB6, 0x15, 0xA1, 0xCB, 0xB6, 0xF6, 0x93, 0x6C, 0x8E, 0x28, 0x7F, 0x7D, 0x6C, 0xEC, 0x76, 0x40, From 8e3c909cb5a1e22e25cdad7ff2ffcfb2cb0a5f2e Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 18 Dec 2024 20:15:33 -0700 Subject: [PATCH 013/276] Rename INO --- .../{Form.ino => WebServer.ino} | 188 +++++++++--------- 1 file changed, 98 insertions(+), 90 deletions(-) rename Firmware/RTK_Everywhere/{Form.ino => WebServer.ino} (92%) diff --git a/Firmware/RTK_Everywhere/Form.ino b/Firmware/RTK_Everywhere/WebServer.ino similarity index 92% rename from Firmware/RTK_Everywhere/Form.ino rename to Firmware/RTK_Everywhere/WebServer.ino index 0d972a3c9..4882f7698 100644 --- a/Firmware/RTK_Everywhere/Form.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -6,15 +6,15 @@ Form.ino #ifdef COMPILE_AP -static const char *const webconfigStateNames[] = { - "WEBCONFIG_STATE_OFF", "WEBCONFIG_STATE_WAIT_FOR_NETWORK", "WEBCONFIG_STATE_NETWORK_CONNECTED", - "WEBCONFIG_STATE_STARTED", "WEBCONFIG_STATE_RUNNING", +static const char *const webserverStateNames[] = { + "WEBSERVER_STATE_OFF", "WEBSERVER_STATE_WAIT_FOR_NETWORK", "WEBSERVER_STATE_NETWORK_CONNECTED", + "WEBSERVER_STATE_STARTED", "WEBSERVER_STATE_RUNNING", }; -static const int webconfigStateEntries = sizeof(webconfigStateNames) / sizeof(webconfigStateNames[0]); +static const int webserverStateEntries = sizeof(webserverStateNames) / sizeof(webserverStateNames[0]); static NetPriority_t webconfigPriority = NETWORK_OFFLINE; -static WebConfigState webconfigState; +static webserverState webserverState; // Once connected to the access point for WiFi Config, the ESP32 sends current setting values in one long string to // websocket After user clicks 'save', data is validated via main.js and a long string of values is returned. @@ -63,7 +63,7 @@ void sendStringToWebsocket(const char *stringToSend) } else { - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("sendStringToWebsocket: %s\r\n", stringToSend); } } @@ -80,7 +80,7 @@ static esp_err_t ws_handler(httpd_req_t *req) // TODO: do we need to be cleverer about this? last_ws_fd = httpd_req_to_sockfd(req); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("Handshake done, the new ws connection was opened with fd %d\r\n", last_ws_fd); websocketConnected = true; @@ -101,7 +101,7 @@ static esp_err_t ws_handler(httpd_req_t *req) systemPrintf("httpd_ws_recv_frame failed to get frame len with %d\r\n", ret); return ret; } - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("frame len is %d\r\n", ws_pkt.len); if (ws_pkt.len) { @@ -126,7 +126,7 @@ static esp_err_t ws_handler(httpd_req_t *req) return ret; } } - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("Packet type: %d\r\n", ws_pkt.type); // HTTPD_WS_TYPE_CONTINUE = 0x0, // HTTPD_WS_TYPE_TEXT = 0x1, @@ -137,7 +137,7 @@ static esp_err_t ws_handler(httpd_req_t *req) if (ws_pkt.type == HTTPD_WS_TYPE_TEXT) { - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("Got packet with message: %s\r\n", ws_pkt.payload); if (currentlyParsingData == false) @@ -152,7 +152,7 @@ static esp_err_t ws_handler(httpd_req_t *req) } else if (ws_pkt.type == HTTPD_WS_TYPE_CLOSE) { - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("Client closed or refreshed the web page"); createSettingsString(settingsCSV); @@ -182,7 +182,7 @@ static void start_wsserver(void) config.stack_size = updateWebSocketStackSize; // Start the httpd server - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("Starting wsserver on port: %d\r\n", config.server_port); if (wsserver == nullptr) @@ -191,7 +191,7 @@ static void start_wsserver(void) if (httpd_start(wsserver, &config) == ESP_OK) { // Registering the ws handler - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("Registering URI handlers"); httpd_register_uri_handler(*wsserver, &ws); return; @@ -200,19 +200,6 @@ static void start_wsserver(void) systemPrintln("Error starting wsserver!"); } -void stop_wsserver() -{ - createSettingsString(settingsCSV); - websocketConnected = false; - - if (*wsserver) - { - // Stop the httpd server - esp_err_t ret = httpd_stop(*wsserver); - //*wsserver = nullptr; - } -} - // ===== Request Handler class used to answer more complex requests ===== // https://github.com/espressif/arduino-esp32/blob/master/libraries/WebServer/examples/WebServer/WebServer.ino class CaptiveRequestHandler : public RequestHandler @@ -223,7 +210,7 @@ class CaptiveRequestHandler : public RequestHandler "/check_network_status.txt"}; CaptiveRequestHandler() { - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("CaptiveRequestHandler is registered"); } virtual ~CaptiveRequestHandler() @@ -243,7 +230,7 @@ class CaptiveRequestHandler : public RequestHandler bool handle(WebServer &server, HTTPMethod requestMethod, String requestUri) { String logmessage = "Captive Portal Client:" + server.client().remoteIP().toString() + " " + requestUri; - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln(logmessage); String response = "RTK Config"; response += "
"; @@ -261,80 +248,80 @@ class CaptiveRequestHandler : public RequestHandler }; // State machine to handle the starting/stopping of the web server -void updateWebServer() +void websServerUpdate() { if (!inMainMenu) { // Walk the state machine - switch (webconfigState) + switch (webserverState) { default: - systemPrintf("ERROR: Unknown WebConfig state (%d)\r\n", webconfigState); + systemPrintf("ERROR: Unknown WebConfig state (%d)\r\n", webserverState); // Stop the machine - webconfigStop(); + webServerStop(); break; // Wait for a request from a user - case WEBCONFIG_STATE_OFF: + case WEBSERVER_STATE_OFF: if (webconfigRequest == true) - otaSetState(WEBCONFIG_STATE_WAIT_FOR_NETWORK); + webServerSetState(WEBSERVER_STATE_WAIT_FOR_NETWORK); break; // Wait for connection to the network - case WEBCONFIG_STATE_WAIT_FOR_NETWORK: + case WEBSERVER_STATE_WAIT_FOR_NETWORK: // Determine if the request has been canceled while waiting if (webconfigRequest == false) - webconfigUpdateStop(); + webServerStop(); // Wait until the network is connected to the media else if (networkIsConnected(&webconfigPriority)) { - if (settings.debugWebConfig) + if (settings.debugWebServer) systemPrintln("Web config connected to network"); - webconfigSetState(WEBCONFIG_STATE_NETWORK_CONNECTED); + webServerSetState(WEBSERVER_STATE_NETWORK_CONNECTED); } break; // Start the web server - case WEBCONFIG_STATE_NETWORK_CONNECTED: + case WEBSERVER_STATE_NETWORK_CONNECTED: // Determine if the network has failed if (!networkIsConnected(&webconfigPriority)) - webconfigStop(); - if (settings.debugWebConfig) + webServerStop(); + if (settings.debugWebServer) systemPrintln("Web config starting web server"); - if (startWebServer(false, settings.httpPort) == true) - webconfigSetState(WEBCONFIG_STATE_STARTED); + if (webServerStart(false, settings.httpPort) == true) + webServerSetState(WEBSERVER_STATE_STARTED); break; // Wait for web server to start - case WEBCONFIG_STATE_STARTED: + case WEBSERVER_STATE_STARTED: // Determine if the network has failed if (!networkIsConnected(&webconfigPriority)) - webconfigStop(); - if (settings.debugWebConfig) + webServerStop(); + if (settings.debugWebServer) systemPrintln("Web config waiting for web server to start"); //... - webconfigSetState(WEBCONFIG_STATE_RUNNING); + webServerSetState(WEBSERVER_STATE_RUNNING); break; // Allow web services - case WEBCONFIG_STATE_RUNNING: + case WEBSERVER_STATE_RUNNING: // Determine if the network has failed if (!networkIsConnected(&webconfigPriority)) - webconfigStop(); + webServerStop(); // TODO how does the system indicate we need to shut down the web server? if (inWiFiConfigMode() == false) { webconfigRequest = false; // Tell the network layer we no longer need access - webconfigStop(); + webServerStop(); } //... @@ -345,28 +332,43 @@ void updateWebServer() } // Stop the web config state machine -void webconfigStop() +void webServerStop() { - if (settings.debugWebConfig) - systemPrintln("webconfigStop called"); + webconfigRequest = false; //Notify the web config state machine to start up - if (webconfigState != WEBCONFIG_STATE_OFF) + if (settings.debugWebServer) + systemPrintln("webServerStop called"); + + if (webserverState != WEBSERVER_STATE_OFF) { - stop_wsserver(); // Release socket resources - stopWebServer(); // Release web server resources + webServerStopSockets(); // Release socket resources + webServerStop(); // Release web server resources // Stop network systemPrintln("Web Config releasing network request"); - webconfigRequested = false; // Let the network know we no longer need it + webserverRequested = false; // Let the network know we no longer need it // Stop the machine - webconfigSetState(WEBCONFIG_STATE_OFF); + webServerSetState(WEBSERVER_STATE_OFF); } -}; +} + +void webServerStopSockets() +{ + createSettingsString(settingsCSV); + websocketConnected = false; + + if (*wsserver) + { + // Stop the httpd server + esp_err_t ret = httpd_stop(*wsserver); + //*wsserver = nullptr; + } +} // Set the next webconfig state -void webconfigSetState(WebConfigState newState) +void webServerSetState(webserverState newState) { char string1[40]; char string2[40]; @@ -376,26 +378,26 @@ void webconfigSetState(WebConfigState newState) const char *endingState = nullptr; // Display the state transition - if (settings.debugWebConfig) + if (settings.debugWebServer) { arrow = ""; asterisk = ""; initialState = ""; - if (newState == otaState) + if (newState == webserverState) asterisk = "*"; else { - initialState = webconfigGetStateName(webconfigState, string1); + initialState = webServerGetStateName(webserverState, string1); arrow = " --> "; } } // Set the new state - webconfigState = newState; - if (settings.debugWebConfig) + webserverState = newState; + if (settings.debugWebServer) { // Display the new firmware update state - endingState = webconfigGetStateName(newState, string2); + endingState = webServerGetStateName(newState, string2); if (!online.rtc) systemPrintf("%s%s%s%s\r\n", asterisk, initialState, arrow, endingState); else @@ -412,21 +414,27 @@ void webconfigSetState(WebConfigState newState) } // Validate the state - if (newState >= WEBCONFIG_STATE_MAX) + if (newState >= WEBSERVER_STATE_MAX) reportFatalError("Invalid web config state"); } // Get the webconfig state name -const char *webconfigGetStateName(WebConfigState state, char *string) +const char *webServerGetStateName(webserverState state, char *string) { - if (state < WEBCONFIG_STATE_MAX) - return webconfigStateNames[state]; + if (state < WEBSERVER_STATE_MAX) + return webserverStateNames[state]; sprintf(string, "Unknown state (%d)", state); return string; } +bool webServerIsStarted() +{ + if() +} + + // Start webserver in AP mode -bool startWebServer(bool startWiFi = true, int httpPort = 80) +bool webServerStart(bool startWiFi = true, int httpPort = 80) { do { @@ -444,7 +452,7 @@ bool startWebServer(bool startWiFi = true, int httpPort = 80) // else // networkMulticastDNSSwitch(NETWORK_ETHERNET); - // Freed by stopWebServer + // Freed by webServerStop if (online.psram == true) incomingSettings = (char *)ps_malloc(AP_CONFIG_SETTING_SIZE); else @@ -458,7 +466,7 @@ bool startWebServer(bool startWiFi = true, int httpPort = 80) memset(incomingSettings, 0, AP_CONFIG_SETTING_SIZE); // Pre-load settings CSV - // Freed by stopWebServer + // Freed by webServerStop if (online.psram == true) settingsCSV = (char *)ps_malloc(AP_CONFIG_SETTING_SIZE); else @@ -638,7 +646,7 @@ bool startWebServer(bool startWiFi = true, int httpPort = 80) // Handler for file manager webserver->on("/listfiles", HTTP_GET, []() { String logmessage = "Client:" + webserver->client().remoteIP().toString() + " " + webserver->uri(); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln(logmessage); String files; getFileList(files); @@ -648,11 +656,11 @@ bool startWebServer(bool startWiFi = true, int httpPort = 80) // Handler for supported messages list webserver->on("/listMessages", HTTP_GET, []() { String logmessage = "Client:" + webserver->client().remoteIP().toString() + " " + webserver->uri(); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln(logmessage); String messages; createMessageList(messages); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln(messages); webserver->send(200, "text/plain", messages); }); @@ -660,11 +668,11 @@ bool startWebServer(bool startWiFi = true, int httpPort = 80) // Handler for supported RTCM/Base messages list webserver->on("/listMessagesBase", HTTP_GET, []() { String logmessage = "Client:" + webserver->client().remoteIP().toString() + " " + webserver->uri(); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln(logmessage); String messageList; createMessageListBase(messageList); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln(messageList); webserver->send(200, "text/plain", messageList); }); @@ -684,14 +692,14 @@ bool startWebServer(bool startWiFi = true, int httpPort = 80) updateWebServerTaskPriority, &updateWebServerTaskHandle); // Task handle - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("Web Server Started"); reportHeapNow(false); // Start the web socket server on port 81 using start_wsserver(); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("Web Socket Server Started"); reportHeapNow(false); @@ -699,8 +707,8 @@ bool startWebServer(bool startWiFi = true, int httpPort = 80) } while (0); // Release the resources - stop_wsserver(); - stopWebServer(); + webServerStopSockets(); + webServerStop(); return false; } @@ -735,7 +743,7 @@ void updateWebServerTask(void *e) vTaskDelete(updateWebServerTaskHandle); } -void stopWebServer() +void webServerStop() { if (task.updateWebServerTaskRunning) task.updateWebServerTaskStopRequest = true; @@ -1016,13 +1024,13 @@ void createFirmwareVersionString(char *settingsCSV) // Compare the unit's version against the reported version from OTA if (isReportedVersionNewer(otaReportedVersion, currentVersion) == true) { - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("New version detected"); snprintf(newVersionCSV, sizeof(newVersionCSV), "%s,", otaReportedVersion); } else { - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("No new firmware available"); snprintf(newVersionCSV, sizeof(newVersionCSV), "CURRENT,"); } @@ -1123,7 +1131,7 @@ bool parseIncomingSettings() headPtr = commaPtr + 1; } - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("settingName: %s value: %s\r\n", settingName, valueStr); updateSettingWithValue(false, settingName, valueStr); @@ -1140,7 +1148,7 @@ bool parseIncomingSettings() if (counter < maxAttempts) { // Confirm receipt - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("Sending receipt confirmation of settings"); sendStringToWebsocket("confirmDataReceipt,1,"); } @@ -1203,7 +1211,7 @@ void getFileList(String &returnText) systemPrintf("sdCardSemaphore failed to yield, held by %s, Form.ino line %d\r\n", semaphoreHolder, __LINE__); } - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("returnText (%d bytes): %s\r\n", returnText.length(), returnText.c_str()); } @@ -1267,7 +1275,7 @@ void createMessageList(String &returnText) } #endif // COMPILE_MOSAICX5 - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("returnText (%d bytes): %s\r\n", returnText.length(), returnText.c_str()); } @@ -1319,7 +1327,7 @@ void createMessageListBase(String &returnText) } #endif // COMPILE_MOSAICX5 - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("returnText (%d bytes): %s\r\n", returnText.length(), returnText.c_str()); } From 4cac63702d0f62d6fc70d120bf885049c8e88345 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 18 Dec 2024 20:16:33 -0700 Subject: [PATCH 014/276] Rename to webserver --- Firmware/RTK_Everywhere/Developer.ino | 4 +-- Firmware/RTK_Everywhere/NVM.ino | 2 +- Firmware/RTK_Everywhere/Network.ino | 6 +++-- Firmware/RTK_Everywhere/States.ino | 10 ++++--- Firmware/RTK_Everywhere/menuCommands.ino | 34 ++++++++++++------------ Firmware/RTK_Everywhere/menuSystem.ino | 4 +-- Firmware/RTK_Everywhere/settings.h | 21 ++++++++------- 7 files changed, 43 insertions(+), 38 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 50ed9f0f1..39c9433dd 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -151,12 +151,12 @@ void httpClientValidateTables() {} #ifndef COMPILE_AP -bool startWebServer(bool startWiFi = true, int httpPort = 80) +bool webServerStart(bool startWiFi = true, int httpPort = 80) { systemPrintln("**AP not compiled**"); return false; } -void stopWebServer() {} +void webServerStop() {} bool parseIncomingSettings() {return false;} void sendStringToWebsocket(const char* stringToSend) {} diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index e017a398c..05d9db528 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -18,7 +18,7 @@ createSettingsString(); In menuCommands.ino Generates a CSV string of all settings and their values - if they are inWebConfig - Called by startWebServer, onWsEvent, updateSettingWithValue (when setting / resetting a profile), + Called by webServerStart, onWsEvent, updateSettingWithValue (when setting / resetting a profile), Calls the stringRecord methods - also in menuCommands.ino Note: there is a _lot_ of commonality between this and recordSystemSettingsToFile. It may be possible to share code between the two. diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 71ba2b2c6..b8f10748c 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1335,8 +1335,8 @@ void networkUpdate() // The STATE_WIFI_CONFIG is in control of WiFi. Don't allow the network layer to shut it down // As OTA exits, we need to keep AP running if we are in Web Config mode - // We don't want to make STATE_WIFI_CONFIG a consumer until startWebServer() uses the network layer - // To do that, startWebServer() needs a state machine to wait for the network to come online + // We don't want to make STATE_WIFI_CONFIG a consumer until webServerStart() uses the network layer + // To do that, webServerStart() needs a state machine to wait for the network to come online // Shutdown all networks for (int index = 0; index < NETWORK_OFFLINE; index++) @@ -1385,6 +1385,8 @@ void networkUpdate() udpServerUpdate(); // Turn on the UDP server as needed DMW_c("httpClientUpdate"); httpClientUpdate(); // Process any Point Perfect HTTP messages + DMW_c("webServerUpdate"); + webServerUpdate(); // Start webserver for web config as needed // Periodically display the network interface state displayIpAddress = PERIODIC_DISPLAY(PD_IP_ADDRESS); diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 2424c9d53..23f22f99c 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -473,14 +473,14 @@ void stateUpdate() // If a firmware version was requested, and obtained, report it back to the web page if (strlen(otaReportedVersion) > 0) { - if(settings.debugWebConfig) + if (settings.debugWebServer) systemPrintln("Webconfig: Reporting firmware version"); - + createFirmwareVersionString(settingsCSV); sendStringToWebsocket(settingsCSV); - otaReportedVersion[0] = '\0'; //Zero out the reported version to stop future reports + otaReportedVersion[0] = '\0'; // Zero out the reported version to stop future reports } } @@ -650,7 +650,7 @@ void stateUpdate() ethernetWebServerStartESP32W5500(); // Start Ethernet in dedicated configure-via-ethernet mode - if (!startWebServer(false, settings.httpPort)) // Start the web server + if (!webServerStart(false, settings.httpPort)) // Start the web server changeState(STATE_ROVER_NOT_STARTED); else changeState(STATE_CONFIG_VIA_ETH); @@ -774,6 +774,8 @@ const char *getState(SystemState state, char *buffer) return "STATE_DISPLAY_SETUP"; case (STATE_WIFI_CONFIG_NOT_STARTED): return "STATE_WIFI_CONFIG_NOT_STARTED"; + case (STATE_WIFI_CONFIG_WAIT_FOR_NETWORK): + return "STATE_WIFI_CONFIG_WAIT_FOR_NETWORK"; case (STATE_WIFI_CONFIG): return "STATE_WIFI_CONFIG"; case (STATE_TEST): diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index 32ba3ada5..b8514c368 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -1134,7 +1134,7 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting // This is one of the first settings to be received. If seen, remove the station files. removeFile(stationCoordinateECEFFileName); removeFile(stationCoordinateGeodeticFileName); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("Station coordinate files removed"); knownSetting = true; } @@ -1146,7 +1146,7 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting replaceCharacter((char *)settingValueStr, ' ', ','); // Replace all ' ' with ',' before recording to file recordLineToSD(stationCoordinateECEFFileName, settingValueStr); recordLineToLFS(stationCoordinateECEFFileName, settingValueStr); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("%s recorded\r\n", settingValueStr); knownSetting = true; } @@ -1155,7 +1155,7 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting replaceCharacter((char *)settingValueStr, ' ', ','); // Replace all ' ' with ',' before recording to file recordLineToSD(stationCoordinateGeodeticFileName, settingValueStr); recordLineToLFS(stationCoordinateGeodeticFileName, settingValueStr); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("%s recorded\r\n", settingValueStr); knownSetting = true; } @@ -1207,7 +1207,7 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting else if (strcmp(settingName, "exitAndReset") == 0) { // Confirm receipt - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("Sending reset confirmation"); sendStringToWebsocket((char *)"confirmReset,1,"); @@ -1239,7 +1239,7 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting else if (strcmp(settingName, "setProfile") == 0) { // Change to new profile - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("Changing to profile number %d\r\n", settingValue); changeProfileNumber(settingValue); @@ -1251,7 +1251,7 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting createSettingsString(settingsCSV); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) { systemPrintf("Sending profile %d\r\n", settingValue); systemPrintf("Profile contents: %s\r\n", settingsCSV); @@ -1274,7 +1274,7 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting createSettingsString(settingsCSV); - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) { systemPrintf("Sending reset profile %d\r\n", settingValue); systemPrintf("Profile contents: %s\r\n", settingsCSV); @@ -1308,7 +1308,7 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting } else if (strcmp(settingName, "checkNewFirmware") == 0) { - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("Checking for new OTA Pull firmware"); sendStringToWebsocket((char *)"checkingNewFirmware,1,"); // Tell the config page we received their request @@ -1328,13 +1328,13 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting // getFirmwareVersion(currentVersion, sizeof(currentVersion), enableRCFirmware); // if (isReportedVersionNewer(reportedVersion, currentVersion) == true) // { - // if (settings.debugWebConfig == true) + // if (settings.debugWebServer == true) // systemPrintln("New version detected"); // snprintf(newVersionCSV, sizeof(newVersionCSV), "newFirmwareVersion,%s,", reportedVersion); // } // else // { - // if (settings.debugWebConfig == true) + // if (settings.debugWebServer == true) // systemPrintln("No new firmware available"); // snprintf(newVersionCSV, sizeof(newVersionCSV), "newFirmwareVersion,CURRENT,"); // } @@ -1342,7 +1342,7 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting // else // { // // Failed to get version number - // if (settings.debugWebConfig == true) + // if (settings.debugWebServer == true) // systemPrintln("Sending error to AP config page"); // snprintf(newVersionCSV, sizeof(newVersionCSV), "newFirmwareVersion,ERROR,"); // } @@ -1352,7 +1352,7 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting } else if (strcmp(settingName, "getNewFirmware") == 0) { - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintln("Getting new OTA Pull firmware"); sendStringToWebsocket((char *)"gettingNewFirmware,1,"); @@ -2057,7 +2057,7 @@ void createSettingsString(char *newSettings) { trim(stationInfo); // Remove trailing whitespace - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("ECEF SD station %d - found: %s\r\n", index, stationInfo); replaceCharacter(stationInfo, ',', ' '); // Change all , to ' ' for easier parsing on the JS side @@ -2069,7 +2069,7 @@ void createSettingsString(char *newSettings) { trim(stationInfo); // Remove trailing whitespace - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("ECEF LFS station %d - found: %s\r\n", index, stationInfo); replaceCharacter(stationInfo, ',', ' '); // Change all , to ' ' for easier parsing on the JS side @@ -2095,7 +2095,7 @@ void createSettingsString(char *newSettings) { trim(stationInfo); // Remove trailing whitespace - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("Geo SD station %d - found: %s\r\n", index, stationInfo); replaceCharacter(stationInfo, ',', ' '); // Change all , to ' ' for easier parsing on the JS side @@ -2107,7 +2107,7 @@ void createSettingsString(char *newSettings) { trim(stationInfo); // Remove trailing whitespace - if (settings.debugWebConfig == true) + if (settings.debugWebServer == true) systemPrintf("Geo LFS station %d - found: %s\r\n", index, stationInfo); replaceCharacter(stationInfo, ',', ' '); // Change all , to ' ' for easier parsing on the JS side @@ -2840,7 +2840,7 @@ SettingValueResponse getSettingValue(bool inCommands, const char *settingName, c if (knownSetting == false) { - if (settings.debugWebConfig) + if (settings.debugWebServer) systemPrintf("getSettingValue() Unknown setting: %s\r\n", settingName); } diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index 4bec7b477..f9695d148 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -654,7 +654,7 @@ void menuDebugNetwork() // WiFi Config systemPrint("4) Debug Web Config: "); - systemPrintf("%s\r\n", settings.debugWebConfig ? "Enabled" : "Disabled"); + systemPrintf("%s\r\n", settings.debugWebServer ? "Enabled" : "Disabled"); // Network systemPrint("10) Debug network layer: "); @@ -716,7 +716,7 @@ void menuDebugNetwork() else if (incoming == 3) settings.debugWifiState ^= 1; else if (incoming == 4) - settings.debugWebConfig ^= 1; + settings.debugWebServer ^= 1; else if (incoming == 10) settings.debugNetworkLayer ^= 1; else if (incoming == 11) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 33279290c..58f97a91b 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -27,6 +27,7 @@ typedef enum STATE_BASE_FIXED_TRANSMITTING, STATE_DISPLAY_SETUP, STATE_WIFI_CONFIG_NOT_STARTED, + STATE_WIFI_CONFIG_WAIT_FOR_NETWORK, STATE_WIFI_CONFIG, STATE_TEST, STATE_TESTING, @@ -560,19 +561,19 @@ enum OtaState #ifdef COMPILE_AP // Web Config state machine to allow web server access to network layer -enum WebConfigState +enum webserverState { - WEBCONFIG_STATE_OFF = 0, - WEBCONFIG_STATE_WAIT_FOR_NETWORK, - WEBCONFIG_STATE_NETWORK_CONNECTED, - WEBCONFIG_STATE_STARTED, - WEBCONFIG_STATE_RUNNING, + WEBSERVER_STATE_OFF = 0, + WEBSERVER_STATE_WAIT_FOR_NETWORK, + WEBSERVER_STATE_NETWORK_CONNECTED, + WEBSERVER_STATE_STARTED, + WEBSERVER_STATE_RUNNING, // Add new states here - WEBCONFIG_STATE_MAX + WEBSERVER_STATE_MAX }; -#endif // COMPILE_OTA_AUTO +#endif // COMPILE_AP @@ -995,7 +996,7 @@ struct Settings uint16_t httpPort = 80; // WiFi - bool debugWebConfig = false; + bool debugWebServer = false; bool debugWifiState = false; bool enableCaptivePortal = true; uint8_t wifiChannel = 1; //Valid channels are 1 to 14 @@ -1597,7 +1598,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.httpPort, "httpPort", }, // WiFi - { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugWebConfig, "debugWebConfig", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugWebServer, "debugWebServer", }, { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugWifiState, "debugWifiState", }, { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enableCaptivePortal, "enableCaptivePortal", }, { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint8_t, 0, & settings.wifiChannel, "wifiChannel", }, From 35e6cf898557c66f9d231073d52beb5b12a41eaa Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 19 Dec 2024 08:08:39 +0000 Subject: [PATCH 015/276] Better GNSS UART task debug. Add PD_GNSS_DATA_RX_BYTE_COUNT --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 14 ++++++++++---- Firmware/RTK_Everywhere/Tasks.ino | 9 +++++++++ Firmware/RTK_Everywhere/menuSystem.ino | 5 +++++ Firmware/RTK_Everywhere/settings.h | 2 ++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 61e8251c9..98a8239e3 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2605,9 +2605,12 @@ void processUart1SBF(SEMP_PARSE_STATE *parse, uint16_t type) { GNSS_MOSAIC *mosaic = (GNSS_MOSAIC *)gnss; - // if ((settings.debugGnss == true) && !inMainMenu) - // systemPrintf("Processing SBF Block %d (%d bytes) from mosaic-X5\r\n", sempSbfGetBlockNumber(parse), - // parse->length); + if (((settings.debugGnss == true) || PERIODIC_DISPLAY(PD_GNSS_DATA_RX)) && !inMainMenu) + { + // Don't call PERIODIC_CLEAR(PD_GNSS_DATA_RX); here. Let processUart1Message do it via rtkParse + systemPrintf("Processing SBF Block %d (%d bytes) from mosaic-X5\r\n", sempSbfGetBlockNumber(parse), + parse->length); + } // If this is PVTGeodetic, extract some data if (sempSbfGetBlockNumber(parse) == 4007) @@ -2636,8 +2639,11 @@ void processUart1SBF(SEMP_PARSE_STATE *parse, uint16_t type) //---------------------------------------- void processUart1SPARTN(SEMP_PARSE_STATE *parse, uint16_t type) { - if ((settings.debugCorrections == true) && !inMainMenu) + if (((settings.debugGnss == true) || PERIODIC_DISPLAY(PD_GNSS_DATA_RX)) && !inMainMenu) + { + // Don't call PERIODIC_CLEAR(PD_GNSS_DATA_RX); here. Let processUart1Message do it via rtkParse systemPrintf("Pushing %d SPARTN (L-Band) bytes to PPL for mosaic-X5\r\n", parse->length); + } if (online.ppl == false && settings.debugCorrections == true && (!inMainMenu)) systemPrintln("Warning: PPL is offline"); diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index 37b846191..4814668ca 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -424,6 +424,14 @@ void gnssReadTask(void *e) if ((settings.enableTaskReports == true) && (!inMainMenu)) systemPrintf("SerialReadTask High watermark: %d\r\n", uxTaskGetStackHighWaterMark(nullptr)); + // Display the RX byte count + static uint32_t totalRxByteCount = 0; + if (PERIODIC_DISPLAY(PD_GNSS_DATA_RX_BYTE_COUNT)) + { + PERIODIC_CLEAR(PD_GNSS_DATA_RX_BYTE_COUNT); + systemPrintf("gnssReadTask total byte count: %d\r\n", totalRxByteCount); + } + // Two methods are accessing the hardware serial port (um980Config) at the // same time: gnssReadTask() (to harvest incoming serial data) and um980 (the unicore library to configure the // device) To allow the Unicore library to send/receive serial commands, we need to block the gnssReadTask @@ -454,6 +462,7 @@ void gnssReadTask(void *e) // Read the data from UART1 uint8_t incomingData[500]; int bytesIncoming = serialGNSS->read(incomingData, sizeof(incomingData)); + totalRxByteCount += bytesIncoming; for (int x = 0; x < bytesIncoming; x++) { diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index 99fbd2642..1fbde084e 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -1152,6 +1152,9 @@ void menuPeriodicPrint() systemPrint("9) GNSS TX data: "); systemPrintf("%s\r\n", PERIODIC_SETTING(PD_GNSS_DATA_TX) ? "Enabled" : "Disabled"); + systemPrint("10) GNSS RX byte count: "); + systemPrintf("%s\r\n", PERIODIC_SETTING(PD_GNSS_DATA_RX_BYTE_COUNT) ? "Enabled" : "Disabled"); + systemPrintln("----- Software -----"); systemPrintf("20) Periodic print: %llu (0x%016llx)\r\n", settings.periodicDisplay, settings.periodicDisplay); @@ -1273,6 +1276,8 @@ void menuPeriodicPrint() PERIODIC_TOGGLE(PD_GNSS_DATA_RX); else if (incoming == 9) PERIODIC_TOGGLE(PD_GNSS_DATA_TX); + else if (incoming == 10) + PERIODIC_TOGGLE(PD_GNSS_DATA_RX_BYTE_COUNT); else if (incoming == 20) { diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index d014f925e..8d25f4308 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -314,6 +314,8 @@ enum PeriodDisplayValues PD_PROVISIONING_STATE, // 36 PD_CORRECTION_SOURCE, // 37 + + PD_GNSS_DATA_RX_BYTE_COUNT, // 38 // Add new values before this line }; From 5cc0fd5254476c32b9dfd86265cca184eb782e01 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 19 Dec 2024 10:31:41 +0000 Subject: [PATCH 016/276] Decrease BluetoothSerial::flush delay to 2ms Fixes rolling [D][BluetoothSerial.cpp:793] waitForConnect(): connection closed! --- Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp b/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp index aed24de27..b752b6db1 100644 --- a/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp +++ b/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp @@ -881,7 +881,7 @@ size_t BluetoothSerial::write(const uint8_t *buffer, size_t size) { void BluetoothSerial::flush() { if (_spp_tx_queue != NULL) { while (uxQueueMessagesWaiting(_spp_tx_queue) > 0) { - delay(100); + delay(2); // https://github.com/espressif/arduino-esp32/pull/9905 } } } From da7d11493467dd29a40e8b5719263c4780d8fbb3 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 19 Dec 2024 15:18:27 -0700 Subject: [PATCH 017/276] Assign incoming TCP connection to the tcpServerClient array. Fixes #506 --- Firmware/RTK_Everywhere/TcpServer.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index 80cbbe931..6f518e615 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -440,18 +440,18 @@ void tcpServerUpdate() // Determine if the client data structure is in use if (!(tcpServerClientConnected & (1 << index))) { - NetworkClient client; + if(tcpServerClient[index] == nullptr) + tcpServerClient[index] = new NetworkClient; // Data structure not in use // Check for another TCP server client - client = tcpServer->accept(); + *tcpServerClient[index] = tcpServer->accept(); - // Done if no TCP server client found - if (!client) + // Exit if no TCP server client found + if (! *tcpServerClient[index]) break; // Start processing the new TCP server client connection - tcpServerClient[index] = new NetworkClient; tcpServerClientIpAddress[index] = tcpServerClient[index]->remoteIP(); tcpServerClientConnected = tcpServerClientConnected | (1 << index); tcpServerClientDataSent = tcpServerClientDataSent | (1 << index); From 1b822c4ebbbf0efbac003ce48e29324b83a89f47 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 19 Dec 2024 15:19:00 -0700 Subject: [PATCH 018/276] Add enableNtripCaster --- Firmware/RTK_Everywhere/Network.ino | 12 ++++-- Firmware/RTK_Everywhere/TcpServer.ino | 62 +++++++++++++++++++++++++-- Firmware/RTK_Everywhere/settings.h | 2 + 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 93f1e5872..49bccf50f 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -165,6 +165,9 @@ void menuTcpUdp() if (settings.enableUdpServer) systemPrintf("7) UDP Server Port: %ld\r\n", settings.udpServerPort); + if (settings.enableTcpServer) + systemPrintf("8) Enable NTRIP Caster: %s\r\n", settings.enableNtripCaster ? "Enabled" : "Disabled"); + //------------------------------ // Display the mDNS server menu items //------------------------------ @@ -223,8 +226,10 @@ void menuTcpUdp() //------------------------------ else if (incoming == 4) + { // Toggle TCP server settings.enableTcpServer ^= 1; + } else if (incoming == 5) { @@ -243,6 +248,8 @@ void menuTcpUdp() { getNewSetting("Enter the UDP port to use", 0, 65535, &settings.udpServerPort); } + else if (incoming == 8 && settings.enableTcpServer) + settings.enableNtripCaster ^= 1; //------------------------------ // Get the mDNS server parameters @@ -299,7 +306,7 @@ void networkBegin() ethernetStart(); #endif // COMPILE_ETHERNET - // WiFi and cellular networks are started/stopped as consumers come online/offline in networkUpdate() + // WiFi and cellular networks are started/stopped as consumers and come online/offline in networkUpdate() } //---------------------------------------- @@ -770,7 +777,6 @@ void networkMarkOnline(NetIndex_t index) //---------------------------------------- // Change multicast DNS to a given network -// //---------------------------------------- void networkMulticastDNSSwitch(NetIndex_t startIndex) { @@ -780,7 +786,7 @@ void networkMulticastDNSSwitch(NetIndex_t startIndex) networkMulticastDNSStop(index); // Start mDNS on the requested network - networkMulticastDNSStart(startIndex); //Start DNS on the selected network, either WiFi or Ethernet + networkMulticastDNSStart(startIndex); // Start DNS on the selected network, either WiFi or Ethernet } //---------------------------------------- diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index 6f518e615..05d5f5c9a 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -240,7 +240,13 @@ bool tcpServerStart() tcpServer->begin(); online.tcpServer = true; localIp = networkGetIpAddress(); - systemPrintf("TCP server online, IP address %s:%d\r\n", localIp.toString().c_str(), settings.tcpServerPort); + + if (settings.enableNtripCaster) + systemPrintf("TCP server online, IP address %s:%d, responding as NTRIP Caster\r\n", localIp.toString().c_str(), + settings.tcpServerPort); + else + systemPrintf("TCP server online, IP address %s:%d\r\n", localIp.toString().c_str(), settings.tcpServerPort); + return true; } @@ -453,14 +459,64 @@ void tcpServerUpdate() // Start processing the new TCP server client connection tcpServerClientIpAddress[index] = tcpServerClient[index]->remoteIP(); - tcpServerClientConnected = tcpServerClientConnected | (1 << index); - tcpServerClientDataSent = tcpServerClientDataSent | (1 << index); + if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu)) { PERIODIC_CLEAR(PD_TCP_SERVER_DATA); systemPrintf("TCP server client %d connected to %s\r\n", index, tcpServerClientIpAddress[index].toString().c_str()); } + + // If we are acting as an NTRIP Caster, intercept the initial communication from the client + // and respond accordingly + if (settings.enableNtripCaster) + { + // Read response from client + char response[512]; + int spot = 0; + while (tcpServerClient[index]->available()) + { + response[spot++] = tcpServerClient[index]->read(); + if (spot == sizeof(response)) + spot = 0; // Wrap + } + response[spot] = '\0'; // Terminate string + + if (strnstr(response, "GET / ", sizeof(response)) != NULL) // No mount point in header + { + if (settings.debugTcpServer) + systemPrintln("Mount point table requested."); + + // Respond with a single mountpoint + const char fakeSourceTable[] = + "SOURCETABLE 200 OK\r\nServer: SparkPNT Caster/1.0\r\nContent-Type: " + "text/plain\r\nContent-Length: 96\r\n\r\nSTR;SparkBase;none;RTCM " + "3.0;none;none;none;none;none;none;none;none;none;none;none;B;N;none;none"; + + tcpServerClient[index]->write(fakeSourceTable, strlen(fakeSourceTable)); + + tcpServerStopClient(index); // Disconnect from client + } + else if (strnstr(response, "GET /", sizeof(response)) != NULL) // Mount point in header + { + // NTRIP Client is sending us their mount point. Begin sending RTCM. + if (settings.debugTcpServer) + systemPrintln("NTRIP Client connected - Sending ICY 200 OK"); + + char confirmConnection[] = "ICY 200 OK\r\n"; + tcpServerClient[index]->write(confirmConnection, strlen(confirmConnection)); + } + else + { + // Unknown response + if (settings.debugTcpServer) + systemPrintf("Unknown response: %s\r\n", response); + } + } // settings.enableNtripCaster == true + + // Make client online after any NTRIP injections so ring buffer can start outputting data to it + tcpServerClientConnected = tcpServerClientConnected | (1 << index); + tcpServerClientDataSent = tcpServerClientDataSent | (1 << index); } } diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index d014f925e..b8a640745 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -1016,6 +1016,7 @@ struct Settings #endif // COMPILE_LG290P bool debugSettings = false; + bool enableNtripCaster = false; //When true, respond as a faux NTRIP Caster to incoming TCP connections // Add new settings to appropriate group above or create new group // Then also add to the same group in rtkSettingsEntries below @@ -1624,6 +1625,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = #endif // COMPILE_LG290P { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugSettings, "debugSettings", }, + { 1, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enableNtripCaster, "enableNtripCaster", }, // Add new settings to appropriate group above or create new group // Then also add to the same group in settings above From 05165232d63cbf582120ae0e32f5170f736c8cc9 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Dec 2024 07:40:30 +0000 Subject: [PATCH 019/276] Replace uart_set_rx_full_threshold with setRxFIFOFull --- Firmware/RTK_Everywhere/Begin.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Begin.ino b/Firmware/RTK_Everywhere/Begin.ino index 556441465..755ee031c 100644 --- a/Firmware/RTK_Everywhere/Begin.ino +++ b/Firmware/RTK_Everywhere/Begin.ino @@ -1061,8 +1061,7 @@ void pinGnssUartTask(void *pvParameters) // Reduce threshold value above which RX FIFO full interrupt is generated // Allows more time between when the UART interrupt occurs and when the FIFO buffer overruns - // serialGNSS->setRxFIFOFull(50); //Available in >v2.0.5 - uart_set_rx_full_threshold(2, settings.serialGNSSRxFullThreshold); // uart_num, threshold + serialGNSS->setRxFIFOFull(settings.serialGNSSRxFullThreshold); // Stop notification if (settings.printTaskStartStop) From 8c3f48cafd98ce9b02422b131ef1dbd77ca5f223 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Dec 2024 07:41:22 +0000 Subject: [PATCH 020/276] Increase btRead stack size. Don't include driver/uart.h --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 0819fdcd1..d7e510079 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -461,13 +461,12 @@ volatile bool forwardGnssDataToUsbSerial; #define platformPrefix platformPrefixTable[productVariant] // Sets the prefix for broadcast names -#include //Required for uart_set_rx_full_threshold() on cores > 2) From 44554ee0dd4cea4c529a447d10b25ca44b5ed5df Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Dec 2024 07:46:15 +0000 Subject: [PATCH 021/276] bluetoothAvailable - return int not bool --- Firmware/RTK_Everywhere/Bluetooth.ino | 10 +++++----- Firmware/RTK_Everywhere/Tasks.ino | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Firmware/RTK_Everywhere/Bluetooth.ino b/Firmware/RTK_Everywhere/Bluetooth.ino index 0d196ae67..f245545ab 100644 --- a/Firmware/RTK_Everywhere/Bluetooth.ino +++ b/Firmware/RTK_Everywhere/Bluetooth.ino @@ -199,7 +199,7 @@ uint8_t bluetoothCommandRead() } // Determine if data is available -bool bluetoothRxDataAvailable() +int bluetoothRxDataAvailable() { #ifdef COMPILE_BT if (settings.bluetoothRadioType == BLUETOOTH_RADIO_SPP_AND_BLE) @@ -217,20 +217,20 @@ bool bluetoothRxDataAvailable() return (0); #else // COMPILE_BT - return false; + return 0; #endif // COMPILE_BT } // Determine if data is available on the BLE Command interface -bool bluetoothCommandAvailable() +int bluetoothCommandAvailable() { #ifdef COMPILE_BT if (settings.bluetoothRadioType == BLUETOOTH_RADIO_SPP_AND_BLE || settings.bluetoothRadioType == BLUETOOTH_RADIO_BLE) return bluetoothSerialBleCommands->available(); - return (false); + return (0); #else // COMPILE_BT - return false; + return 0; #endif // COMPILE_BT } diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index 4814668ca..c754df710 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -159,7 +159,7 @@ void btReadTask(void *e) rxBytes = 0; if (bluetoothGetState() == BT_CONNECTED) { - while (btPrintEcho == false && bluetoothRxDataAvailable()) + while (btPrintEcho == false && (bluetoothRxDataAvailable() > 0)) { // Check stream for command characters byte incoming = bluetoothRead(); @@ -2118,7 +2118,7 @@ void bluetoothCommandTask(void *pvParameters) } // Check stream for incoming characters - if (bluetoothCommandAvailable()) + if (bluetoothCommandAvailable() > 0) { byte incoming = bluetoothCommandRead(); From c2bcb14505e507ac986abb39f67c0a599119acb2 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Dec 2024 07:49:37 +0000 Subject: [PATCH 022/276] Restructure bluetoothUpdate --- Firmware/RTK_Everywhere/Bluetooth.ino | 36 ++++++++++++++++----------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/Firmware/RTK_Everywhere/Bluetooth.ino b/Firmware/RTK_Everywhere/Bluetooth.ino index f245545ab..a63de0f94 100644 --- a/Firmware/RTK_Everywhere/Bluetooth.ino +++ b/Firmware/RTK_Everywhere/Bluetooth.ino @@ -42,7 +42,7 @@ BTSerialInterface *bluetoothSerialBleCommands; // Second BLE serial for CLI inte #define BLE_COMMAND_RX_UUID "7e400002-b5a3-f393-e0a9-e50e24dcca9e" #define BLE_COMMAND_TX_UUID "7e400003-b5a3-f393-e0a9-e50e24dcca9e" -TaskHandle_t bluetoothCommandTaskHandle; // Task to monitor incoming CLI from BLE +TaskHandle_t bluetoothCommandTaskHandle = nullptr; // Task to monitor incoming CLI from BLE #endif // COMPILE_BT @@ -54,24 +54,32 @@ TaskHandle_t bluetoothCommandTaskHandle; // Task to monitor incoming CLI from BL void bluetoothUpdate() { #ifdef COMPILE_BT - if (bluetoothIsConnected() == true && bluetoothState == BT_NOTCONNECTED) + static uint32_t lastCheck = millis(); // Check if connected every 100ms + if (millis() > (lastCheck + 100)) { - systemPrintln("BT client connected"); - bluetoothState = BT_CONNECTED; - // LED is controlled by tickerBluetoothLedUpdate() + lastCheck = millis(); - btPrintEchoExit = false; // Reset the exiting of config menus and/or command modes - } + // If bluetoothState == BT_OFF, don't call bluetoothIsConnected() - if (bluetoothIsConnected() == false && bluetoothState == BT_CONNECTED) - { - systemPrintln("BT client disconnected"); + if ((bluetoothState == BT_NOTCONNECTED) && (bluetoothIsConnected())) + { + systemPrintln("BT client connected"); + bluetoothState = BT_CONNECTED; + // LED is controlled by tickerBluetoothLedUpdate() - btPrintEcho = false; - btPrintEchoExit = true; // Force exit all config menus and/or command modes - printEndpoint = PRINT_ENDPOINT_SERIAL; + btPrintEchoExit = false; // Reset the exiting of config menus and/or command modes + } - bluetoothState = BT_NOTCONNECTED; + else if ((bluetoothState == BT_CONNECTED) && (!bluetoothIsConnected())) + { + systemPrintln("BT client disconnected"); + + btPrintEcho = false; + btPrintEchoExit = true; // Force exit all config menus and/or command modes + printEndpoint = PRINT_ENDPOINT_SERIAL; + + bluetoothState = BT_NOTCONNECTED; + } } #endif // COMPILE_BT } From da8f3fd8069c82ea0e6ae6b689d9cad13db8143f Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Dec 2024 07:50:53 +0000 Subject: [PATCH 023/276] Increase bluetoothCommandTask stack --- Firmware/RTK_Everywhere/Bluetooth.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/Bluetooth.ino b/Firmware/RTK_Everywhere/Bluetooth.ino index a63de0f94..f888fbcdb 100644 --- a/Firmware/RTK_Everywhere/Bluetooth.ino +++ b/Firmware/RTK_Everywhere/Bluetooth.ino @@ -558,7 +558,7 @@ void bluetoothStart() xTaskCreatePinnedToCore( bluetoothCommandTask, // Function to run "BluetoothCommandTask", // Just for humans - 4000, // Stack Size - must be ~4000 + 8192, // Stack Size - bleserial_multiple.ino uses 8192 nullptr, // Task input parameter 0, // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest &bluetoothCommandTaskHandle, // Task handle From e1d69e30c3550a4852eed2c0d13c96fdbfeef213 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Dec 2024 07:56:31 +0000 Subject: [PATCH 024/276] Set BleSerial led_pin to -1 --- Firmware/RTK_Everywhere/bluetoothSelect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/bluetoothSelect.h b/Firmware/RTK_Everywhere/bluetoothSelect.h index 9f55f190a..d3964d8a0 100644 --- a/Firmware/RTK_Everywhere/bluetoothSelect.h +++ b/Firmware/RTK_Everywhere/bluetoothSelect.h @@ -103,7 +103,7 @@ class BTLESerial : public virtual BTSerialInterface, public BleSerial bool begin(String deviceName, bool isMaster, bool disableBLE, uint16_t rxQueueSize, uint16_t txQueueSize, const char *serviceID, const char *rxID, const char *txID) { - BleSerial::begin(deviceName.c_str(), serviceID, rxID, txID); + BleSerial::begin(deviceName.c_str(), serviceID, rxID, txID, -1); // name, service_uuid, rx_uuid, tx_uuid, led_pin return true; } From 49a4ca96c5471fc0abe743527a9c66bfa7ab6d9e Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Dec 2024 08:07:23 +0000 Subject: [PATCH 025/276] Revert workflows to 16MB partitions --- .github/workflows/compile-rtk-everywhere.yml | 3 ++- .github/workflows/non-release-build.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/compile-rtk-everywhere.yml b/.github/workflows/compile-rtk-everywhere.yml index b1aa3895b..46a055a5d 100644 --- a/.github/workflows/compile-rtk-everywhere.yml +++ b/.github/workflows/compile-rtk-everywhere.yml @@ -140,7 +140,8 @@ jobs: - name: Copy custom RTKEverywhere.csv run: - cp Firmware/RTKEverywhere_8MB.csv /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/tools/partitions/RTKEverywhere.csv + # Use the 16MB partitions by default. 8MB (Postcard) partitions must be compiled separately + cp Firmware/RTKEverywhere.csv /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/tools/partitions/RTKEverywhere.csv - name: Compile Sketch run: arduino-cli compile --fqbn "esp32:esp32:esp32":DebugLevel=${{ env.DEBUG_LEVEL }},PSRAM=enabled ./Firmware/RTK_Everywhere/RTK_Everywhere.ino diff --git a/.github/workflows/non-release-build.yml b/.github/workflows/non-release-build.yml index b02507457..5b3a39881 100644 --- a/.github/workflows/non-release-build.yml +++ b/.github/workflows/non-release-build.yml @@ -140,7 +140,8 @@ jobs: - name: Copy custom RTKEverywhere.csv run: - cp Firmware/RTKEverywhere_8MB.csv /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/tools/partitions/RTKEverywhere.csv + # Use the 16MB partitions by default. 8MB (Postcard) partitions must be compiled separately + cp Firmware/RTKEverywhere.csv /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/tools/partitions/RTKEverywhere.csv - name: Compile Sketch run: arduino-cli compile --fqbn "esp32:esp32:esp32":DebugLevel=${{ env.DEBUG_LEVEL }},PSRAM=enabled ./Firmware/RTK_Everywhere/RTK_Everywhere.ino From eb71fd4c606880315f298a4b039d1e7b3dedae26 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Dec 2024 08:17:16 +0000 Subject: [PATCH 026/276] BluetoothSerial connected : only log_d if timeout > 0 --- .../RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp b/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp index b752b6db1..e941a8ca7 100644 --- a/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp +++ b/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp @@ -789,10 +789,12 @@ static bool waitForConnect(int timeout) { if ((rc & SPP_CONNECTED) != 0) { return true; } else if ((rc & SPP_CLOSED) != 0) { - log_d("connection closed!"); + if (timeout > 0) + log_d("connection closed!"); return false; } - log_d("timeout"); + if (timeout > 0) + log_d("timeout"); return false; } From 2a4632c7c1c689a11edb74277898303b534938fa Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Dec 2024 11:43:38 +0000 Subject: [PATCH 027/276] Add mosaic->configureGNSSCOM and mosaic->configureLBand Restart X5 L-Band when spartnCorrectionsReceived times out --- Firmware/RTK_Everywhere/GNSS_Mosaic.h | 6 +++ Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 59 +++++++++++++++++++++---- Firmware/RTK_Everywhere/menuPP.ino | 15 ++----- Firmware/RTK_Everywhere/menuSystem.ino | 2 +- 4 files changed, 62 insertions(+), 20 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.h b/Firmware/RTK_Everywhere/GNSS_Mosaic.h index 0c0be8097..216ae7a25 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.h +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.h @@ -617,6 +617,12 @@ class GNSS_MOSAIC : GNSS // Returns true if successfully configured and false upon failure bool configureBase(); + // Configure mosaic-X5 COM1 for Encapsulated RTCMv3 + SBF + NMEA, plus L-Band + bool configureGNSSCOM(bool enableLBand); + + // Configure mosaic-X5 L-Band + bool configureLBand(bool enableLBand, uint32_t LBandFreq = 0); + bool configureLogging(); // Configure specific aspects of the receiver for NTP mode diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 98a8239e3..49327803c 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -488,6 +488,46 @@ bool GNSS_MOSAIC::configureNtpMode() return false; } +//---------------------------------------- +// Configure mosaic-X5 COM1 for Encapsulated RTCMv3 + SBF + NMEA, plus L-Band +//---------------------------------------- +bool GNSS_MOSAIC::configureGNSSCOM(bool enableLBand) +{ + // Configure COM1. NMEA and RTCMv3 will be encapsulated in SBF format + String setting = String("sdio,COM1,auto,RTCMv3+SBF+NMEA+Encapsulate"); + if (enableLBand) + setting += String("+LBandBeam1"); + setting += String("\n\r"); + return sendWithResponse(setting, "DataInOut"); +} + +//---------------------------------------- +// Configure mosaic-X5 L-Band +//---------------------------------------- +bool GNSS_MOSAIC::configureLBand(bool enableLBand, uint32_t LBandFreq) +{ + bool result = sendWithResponse("slsm,off\n\r", "LBandSelectMode"); // Turn L-Band off + + if (!enableLBand) + return result; + + static uint32_t storedLBandFreq = 0; + if (LBandFreq > 0) + storedLBandFreq = LBandFreq; + + // US SPARTN 1.8 service is on 1556290000 Hz + // EU SPARTN 1.8 service is on 1545260000 Hz + result &= + sendWithResponse(String("slbb,User1," + String(storedLBandFreq) + ",baud2400,PPerfect,EU,Enabled\n\r"), + "LBandBeams"); // Set Freq, baud rate + result &= + sendWithResponse("slcs,5555,6959\n\r", "LBandCustomServiceID"); // 21845 = 0x5555; 26969 = 0x6959 + result &= sendWithResponse("slsm,manual,Inmarsat,User1,\n\r", + "LBandSelectMode"); // Set L-Band demodulator to manual + + return result; +} + //---------------------------------------- // Perform the GNSS configuration // Outputs: @@ -508,11 +548,7 @@ bool GNSS_MOSAIC::configureOnce() bool response = true; // Configure COM1. NMEA and RTCMv3 will be encapsulated in SBF format - String setting = String("sdio,COM1,auto,RTCMv3+SBF+NMEA+Encapsulate"); - if (settings.enablePointPerfectCorrections) - setting += String("+LBandBeam1"); - setting += String("\n\r"); - response &= sendWithResponse(setting, "DataInOut"); + response &= configureGNSSCOM(settings.enablePointPerfectCorrections); // COM2 is configured by setCorrRadioExtPort @@ -522,7 +558,7 @@ bool GNSS_MOSAIC::configureOnce() // Output SBF PVTGeodetic and ReceiverTime on their own stream - on COM1 only // TODO : make the interval adjustable // TODO : do we need to enable SBF LBandTrackerStatus so we can get CN0 ? - setting = String("sso,Stream" + String(MOSAIC_SBF_PVT_STREAM) + ",COM1,PVTGeodetic+ReceiverTime,msec500\n\r"); + String setting = String("sso,Stream" + String(MOSAIC_SBF_PVT_STREAM) + ",COM1,PVTGeodetic+ReceiverTime,msec500\n\r"); response &= sendWithResponse(setting, "SBFOutput"); // Output SBF InputLink on its own stream - at 1Hz - on COM1 only @@ -2300,6 +2336,7 @@ bool GNSS_MOSAIC::setTalkerGNGGA() //---------------------------------------- bool GNSS_MOSAIC::softwareReset() { + // We could restart L-Band here if needed, but gnss->softwareReset is never called on the X5 return false; } @@ -2441,8 +2478,14 @@ void GNSS_MOSAIC::update() } // Update spartnCorrectionsReceived - if (millis() > (lastSpartnReception + 5000)) - spartnCorrectionsReceived = false; + if (millis() > (lastSpartnReception + (settings.correctionsSourcesLifetime_s * 1000))) // Timeout + { + if (spartnCorrectionsReceived) // If corrections were being received + { + configureLBand(settings.enablePointPerfectCorrections); // Restart L-Band using stored frequency + spartnCorrectionsReceived = false; + } + } } //---------------------------------------- diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index 4d6f4b6c8..c94da7c00 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -870,17 +870,10 @@ void beginLBand() // If no SPARTN data is received, the L-Band may need a 'kick'. Turn L-Band off and back on again! GNSS_MOSAIC *mosaic = (GNSS_MOSAIC *)gnss; - result &= mosaic->sendWithResponse("slsm,off\n\r", "LBandSelectMode"); // Turn L-Band off - - // US SPARTN 1.8 service is on 1556290000 Hz - // EU SPARTN 1.8 service is on 1545260000 Hz - result &= - mosaic->sendWithResponse(String("slbb,User1," + String(LBandFreq) + ",baud2400,PPerfect,EU,Enabled\n\r"), - "LBandBeams"); // Set Freq, baud rate - result &= - mosaic->sendWithResponse("slcs,5555,6959\n\r", "LBandCustomServiceID"); // 21845 = 0x5555; 26969 = 0x6959 - result &= mosaic->sendWithResponse("slsm,manual,Inmarsat,User1,\n\r", - "LBandSelectMode"); // Set L-Band demodulator to manual + + result &= mosaic->configureGNSSCOM(true); // Ensure LBandBeam1 is enabled on COM1 + + result &= mosaic->configureLBand(true, LBandFreq); // Start L-Band if (result == false) systemPrintln("mosaic-X5 L-Band failed to configure"); diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index 1fbde084e..4ea5846a5 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -91,7 +91,7 @@ void menuSystem() else systemPrintln("Offline - "); - if (online.lbandCorrections == true) + if (online.ppl == true) systemPrint("Keys Good"); else systemPrint("No Keys"); From 7a81d5ccda5b7f7ea2772c07426b3ec2e88528e9 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Dec 2024 11:48:18 +0000 Subject: [PATCH 028/276] Add comment --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 49327803c..862694af1 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2337,6 +2337,7 @@ bool GNSS_MOSAIC::setTalkerGNGGA() bool GNSS_MOSAIC::softwareReset() { // We could restart L-Band here if needed, but gnss->softwareReset is never called on the X5 + // Instead, update() does it when spartnCorrectionsReceived times out return false; } From cfa8ba4f8995a2015add1af3c6f8fba67367db4c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Dec 2024 15:39:31 +0000 Subject: [PATCH 029/276] Revert BT stack increases --- Firmware/RTK_Everywhere/Bluetooth.ino | 2 +- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Bluetooth.ino b/Firmware/RTK_Everywhere/Bluetooth.ino index f888fbcdb..a63de0f94 100644 --- a/Firmware/RTK_Everywhere/Bluetooth.ino +++ b/Firmware/RTK_Everywhere/Bluetooth.ino @@ -558,7 +558,7 @@ void bluetoothStart() xTaskCreatePinnedToCore( bluetoothCommandTask, // Function to run "BluetoothCommandTask", // Just for humans - 8192, // Stack Size - bleserial_multiple.ino uses 8192 + 4000, // Stack Size - must be ~4000 nullptr, // Task input parameter 0, // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest &bluetoothCommandTaskHandle, // Task handle diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index d7e510079..52826ecbe 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -466,7 +466,7 @@ HardwareSerial *serial2GNSS; // Don't instantiate until we know what gnssPlatfor #define SERIAL_SIZE_TX 512 uint8_t wBuffer[SERIAL_SIZE_TX]; // Buffer for writing from incoming SPP to F9P -const int btReadTaskStackSize = 8192; // bleserial_multiple.ino uses 8192 +const int btReadTaskStackSize = 4000; // Array of start-of-sentence offsets into the ring buffer #define AMOUNT_OF_RING_BUFFER_DATA_TO_DISCARD (settings.gnssHandlerBufferSize >> 2) From 1f04176c56b1ec9cc64286e2f842651fb1f01045 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 20 Dec 2024 16:28:13 -0700 Subject: [PATCH 030/276] Start WiFi with either STA, AP, or AP+STA --- Firmware/RTK_Everywhere/Developer.ino | 7 +- Firmware/RTK_Everywhere/Network.ino | 135 +++++++++++----- Firmware/RTK_Everywhere/WiFi.ino | 196 ++++++++++++++--------- Firmware/RTK_Everywhere/menuFirmware.ino | 50 +++--- Firmware/RTK_Everywhere/settings.h | 41 +++-- 5 files changed, 264 insertions(+), 165 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 39c9433dd..79c4a5b02 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -151,12 +151,12 @@ void httpClientValidateTables() {} #ifndef COMPILE_AP -bool webServerStart(bool startWiFi = true, int httpPort = 80) +bool startWebServer(bool startWiFi = true, int httpPort = 80) { systemPrintln("**AP not compiled**"); return false; } -void webServerStop() {} +void stopWebServer() {} bool parseIncomingSettings() {return false;} void sendStringToWebsocket(const char* stringToSend) {} @@ -168,11 +168,10 @@ void sendStringToWebsocket(const char* stringToSend) {} //---------------------------------------- void menuWiFi() {systemPrintln("**WiFi not compiled**");} -bool wifiConnect(unsigned long timeout, bool useAPSTAMode, bool *wasInAPmode) {return false;} +bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) {return false;} int wifiNetworkCount() {return 0;} bool wifiIsRunning() {return false;} void wifiRestart() {} -void wifiSetApMode() {} #define WIFI_STOP() {} #endif // COMPILE_WIFI diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index b8f10748c..b069fb7b7 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -165,6 +165,9 @@ void menuTcpUdp() if (settings.enableUdpServer) systemPrintf("7) UDP Server Port: %ld\r\n", settings.udpServerPort); + if (settings.enableTcpServer) + systemPrintf("8) Enable NTRIP Caster: %s\r\n", settings.enableNtripCaster ? "Enabled" : "Disabled"); + //------------------------------ // Display the mDNS server menu items //------------------------------ @@ -223,8 +226,10 @@ void menuTcpUdp() //------------------------------ else if (incoming == 4) + { // Toggle TCP server settings.enableTcpServer ^= 1; + } else if (incoming == 5) { @@ -243,6 +248,8 @@ void menuTcpUdp() { getNewSetting("Enter the UDP port to use", 0, 65535, &settings.udpServerPort); } + else if (incoming == 8 && settings.enableTcpServer) + settings.enableNtripCaster ^= 1; //------------------------------ // Get the mDNS server parameters @@ -299,7 +306,7 @@ void networkBegin() ethernetStart(); #endif // COMPILE_ETHERNET - // WiFi and cellular networks are started/stopped as consumers come online/offline in networkUpdate() + // WiFi and cellular networks are started/stopped as consumers and come online/offline in networkUpdate() } //---------------------------------------- @@ -770,7 +777,6 @@ void networkMarkOnline(NetIndex_t index) //---------------------------------------- // Change multicast DNS to a given network -// //---------------------------------------- void networkMulticastDNSSwitch(NetIndex_t startIndex) { @@ -1323,34 +1329,54 @@ void networkUpdate() uint8_t priority; NETWORK_POLL_SEQUENCE *sequence; + int consumerCount = networkConsumers(); + + uint16_t consumerTypes = networkGetConsumerTypes(); + // If there are no consumers, do not start the network - if (networkConsumers() == 0 && networkIsOnline() == false) + if (consumerCount == 0 && networkIsOnline() == false) { return; } // If there are no consumers, but the network is online, shut down all networks - if (networkConsumers() == 0 && networkIsOnline() == true) + if (consumerCount == 0 && networkIsOnline() == true) { - - // The STATE_WIFI_CONFIG is in control of WiFi. Don't allow the network layer to shut it down - // As OTA exits, we need to keep AP running if we are in Web Config mode - // We don't want to make STATE_WIFI_CONFIG a consumer until webServerStart() uses the network layer - // To do that, webServerStart() needs a state machine to wait for the network to come online - - // Shutdown all networks - for (int index = 0; index < NETWORK_OFFLINE; index++) - networkStop(index, settings.debugNetworkLayer); + if (systemState == STATE_WIFI_CONFIG) + { + // The STATE_WIFI_CONFIG is in control of WiFi. Don't allow the network layer to shut it down + // As OTA exits, we need to keep AP running if we are in Web Config mode + // We don't want to make STATE_WIFI_CONFIG a consumer until startWebServer() uses the network layer + } + else + { + // Shutdown all networks + for (int index = 0; index < NETWORK_OFFLINE; index++) + networkStop(index, settings.debugNetworkLayer); + } } // Allow consumers to start networks // Each network is expected to shut itself down if it is unavailable or of a lower priority // so that a networkStart() succeeds. - if (networkConsumers() > 0 && networkIsOnline() == false) + if (consumerCount > 0 && networkIsOnline() == false) { - // Start network as needed - for (int index = 0; index < NETWORK_OFFLINE; index++) - networkStart(index, settings.debugNetworkLayer); + // Determine which type of network is needed + // If a consumer is requesting a particular type, it gets priority + + // WiFi STA + AP + if (((consumerTypes && (1 << NETCONSUMER_WIFI_STA)) && (consumerTypes && (1 << NETCONSUMER_WIFI_AP))) || + (consumerTypes && (1 << NETCONSUMER_WIFI_AP_STA))) + { + networkStart(NETWORK_WIFI, settings.debugNetworkLayer); + } + + else if (consumerTypes == NETCONSUMER_ANY) + { + // Start any network that is available, in order ethernet/wifi/cellular + for (int index = 0; index < NETWORK_OFFLINE; index++) + networkStart(index, settings.debugNetworkLayer); + } } // Walk the list of network priorities in descending order @@ -1385,8 +1411,6 @@ void networkUpdate() udpServerUpdate(); // Turn on the UDP server as needed DMW_c("httpClientUpdate"); httpClientUpdate(); // Process any Point Perfect HTTP messages - DMW_c("webServerUpdate"); - webServerUpdate(); // Start webserver for web config as needed // Periodically display the network interface state displayIpAddress = PERIODIC_DISPLAY(PD_IP_ADDRESS); @@ -1460,19 +1484,28 @@ void networkVerifyTables() #endif // COMPILE_NETWORK +// Return the bitfield containing +uint16_t networkGetConsumerTypes() +{ + return (networkConsumerTypes); +} + // Return the count of consumers (TCP, NTRIP Client, etc) that are enabled // From this number we can decide if the network (WiFi, ethernet, cellular, etc) needs to be started // ESP-NOW is an exception and is not considered a network consumer uint8_t networkConsumers() { uint8_t consumerCount = 0; - uint16_t consumerType = 0; + uint16_t consumerId = 0; // Used to debug print who is asking for access + + networkConsumerTypes = NETCONSUMER_NONE; // Network needed for NTRIP Client if ((inRoverMode() == true && settings.enableNtripClient == true) || online.ntripClient) { consumerCount++; - consumerType |= (1 << 0); + consumerId |= (1 << 0); + networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for NTRIP Server @@ -1489,35 +1522,42 @@ uint8_t networkConsumers() if ((inBaseMode() == true && settings.enableNtripServer == true) || ntripServerConnected) { consumerCount++; - consumerType |= (1 << 1); + consumerId |= (1 << 1); + + // TODO - Base type. If AP then limit to NETCONSUMER_WIFI_AP + networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for TCP Client if (settings.enableTcpClient == true || online.tcpClient) { consumerCount++; - consumerType |= (1 << 2); + consumerId |= (1 << 2); + networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for TCP Server if (settings.enableTcpServer == true || online.tcpServer) { consumerCount++; - consumerType |= (1 << 3); + consumerId |= (1 << 3); + networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for UDP Server if (settings.enableUdpServer == true || online.udpServer) { consumerCount++; - consumerType |= (1 << 4); + consumerId |= (1 << 4); + networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for PointPerfect ZTP or key update requested by scheduler, from menu, or display menu if (settings.requestKeyUpdate == true) { consumerCount++; - consumerType |= (1 << 5); + consumerId |= (1 << 5); + networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for PointPerfect Corrections MQTT client @@ -1526,28 +1566,37 @@ uint8_t networkConsumers() { // PointPerfect is enabled, allow MQTT to begin consumerCount++; - consumerType |= (1 << 6); + consumerId |= (1 << 6); + networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed to obtain the latest firmware version if (otaRequestFirmwareVersionCheck == true) { consumerCount++; - consumerType |= (1 << 7); + consumerId |= (1 << 7); + networkConsumerTypes |= (1 << NETCONSUMER_WIFI_STA); // OTA Pull library only supports WiFi } // Network needed to start a firmware update if (otaRequestFirmwareUpdate == true) { consumerCount++; - consumerType |= (1 << 8); + consumerId |= (1 << 8); + networkConsumerTypes |= (1 << NETCONSUMER_WIFI_STA); // OTA Pull library only supports WiFi } - // Network needed for Web Config - if (inWiFiConfigMode() == true) + // Network needed for web configuration + // if (webConfigRequested == true) + if (false) { consumerCount++; - consumerType |= (1 << 9); + consumerId |= (1 << 9); + + if (settings.wifiConfigOverAP == true) + networkConsumerTypes |= (1 << NETCONSUMER_WIFI_AP); // + else + networkConsumerTypes |= (1 << NETCONSUMER_WIFI_STA); // } // Debug @@ -1563,26 +1612,26 @@ uint8_t networkConsumers() { systemPrintf("- Consumers: ", consumerCount); - if (consumerType & (1 << 0)) + if (consumerId & (1 << 0)) systemPrint("Rover NTRIP Client, "); - if (consumerType & (1 << 1)) + if (consumerId & (1 << 1)) systemPrint("Base NTRIP Server, "); - if (consumerType & (1 << 2)) + if (consumerId & (1 << 2)) systemPrint("TCP Client, "); - if (consumerType & (1 << 3)) + if (consumerId & (1 << 3)) systemPrint("TCP Server, "); - if (consumerType & (1 << 4)) + if (consumerId & (1 << 4)) systemPrint("UDP Server, "); - if (consumerType & (1 << 5)) + if (consumerId & (1 << 5)) systemPrint("PPL Key Update Request, "); - if (consumerType & (1 << 6)) + if (consumerId & (1 << 6)) systemPrint("PPL MQTT Client, "); - if (consumerType & (1 << 7)) + if (consumerId & (1 << 7)) systemPrint("OTA Version Check, "); - if (consumerType & (1 << 8)) + if (consumerId & (1 << 8)) systemPrint("OTA Scheduled Check, "); - if (consumerType & (1 << 9)) - systemPrint("WiFi Config Mode, "); + if (consumerId & (1 << 9)) + systemPrint("Web Config, "); } systemPrintln(); diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 75b62abb7..7c1073df2 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -137,57 +137,58 @@ void menuWiFi() } //---------------------------------------- -// Connect to a remote WiFi access point +// Starts WiFi in STA, AP, or STA_AP mode depending on networkGetConsumerTypes() +// Returns true if STA connects, or if AP is started, or if STA_AP is successful //---------------------------------------- -bool wifiConnect(unsigned long timeout) +bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) { - return wifiConnect(timeout, false, nullptr); -} + // Is a change needed? + if (startWiFiStation && startWiFiAP && WiFi.getMode() == WIFI_AP_STA) + return (true); // There is nothing needing to be changed -//---------------------------------------- -// Attempts a connection to all provided SSIDs -// Returns true if successful -// Gives up if no SSID detected or connection times out -// If useAPSTAMode is true, do an extra check and go from WIFI_AP mode to WIFI_AP_STA mode -//---------------------------------------- -bool wifiConnect(unsigned long timeout, bool useAPSTAMode, bool *wasInAPmode) -{ - // If WiFi is already connected and AP_STA mode is not needed, then return true now - if (wifiIsRunning() && !useAPSTAMode) + if (startWiFiStation && WiFi.getMode() == WIFI_STA) + return (true); // There is nothing needing to be changed + + if (startWiFiAP && WiFi.getMode() == WIFI_AP) + return (true); // There is nothing needing to be changed + + wifiRunning = false; //Mark it as offline while we mess about + + wifi_mode_t wifiMode = WIFI_OFF; + wifi_interface_t wifiInterface = WIFI_IF_STA; + + if (networkGetConsumerTypes() == NETCONSUMER_WIFI_STA) + { + systemPrintln("Starting WiFi Station"); + wifiMode = WIFI_STA; + wifiInterface = WIFI_IF_STA; + } + else if (networkGetConsumerTypes() == NETCONSUMER_WIFI_AP) { - return (true); // Nothing to do + systemPrintln("Starting WiFi AP"); + wifiMode = WIFI_AP; + wifiInterface = WIFI_IF_AP; + } + else if (networkGetConsumerTypes() == NETCONSUMER_WIFI_AP_STA) + { + systemPrintln("Starting WiFi AP+Station"); + wifiMode = WIFI_AP_STA; + wifiInterface = WIFI_IF_AP_STA; } displayWiFiConnect(); - // If otaUpdate wants to use WIFI_AP_STA mode - if (useAPSTAMode && (wasInAPmode != nullptr)) - { - *wasInAPmode = (WiFi.getMode() == WIFI_AP); - - if (*wasInAPmode) - { - systemPrintln("wifiConnect: changing from WIFI_AP to WIFI_AP_STA"); - WiFi.mode(WIFI_AP_STA); // Change mode from WIFI_AP to WIFI_AP_STA - } - else - { - systemPrintln("wifiConnect: was not in WIFI_AP mode. Going to WIFI_STA"); - WiFi.mode(WIFI_STA); // Must have been off - or already in STA mode? - } - } - else + if (WiFi.mode(wifiMode) == false) // Start WiFi in the appropriate mode { - // Before we can issue esp_wifi_() commands WiFi must be started - if (WiFi.getMode() != WIFI_STA) - WiFi.mode(WIFI_STA); + systemPrintln("WiFi failed to set mode"); + return (false); } // Verify that the necessary protocols are set uint8_t protocols = 0; - esp_err_t response = esp_wifi_get_protocol(WIFI_IF_STA, &protocols); + esp_err_t response = esp_wifi_get_protocol(wifiInterface, &protocols); if (response != ESP_OK) - systemPrintf("wifiConnect: Failed to get protocols: %s\r\n", esp_err_to_name(response)); + systemPrintf("Failed to get protocols: %s\r\n", esp_err_to_name(response)); // If ESP-NOW is running, blend in ESP-NOW protocol. if (espnowState > ESPNOW_OFF) @@ -195,10 +196,10 @@ bool wifiConnect(unsigned long timeout, bool useAPSTAMode, bool *wasInAPmode) if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR)) { esp_err_t response = - esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | - WIFI_PROTOCOL_LR); // Enable WiFi + ESP-Now. + esp_wifi_set_protocol(wifiInterface, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | + WIFI_PROTOCOL_LR); // Enable WiFi + ESP-Now. if (response != ESP_OK) - systemPrintf("wifiConnect: Error setting WiFi + ESP-NOW protocols: %s\r\n", esp_err_to_name(response)); + systemPrintf("Error setting WiFi + ESP-NOW protocols: %s\r\n", esp_err_to_name(response)); } } else @@ -206,14 +207,52 @@ bool wifiConnect(unsigned long timeout, bool useAPSTAMode, bool *wasInAPmode) // Make sure default WiFi protocols are in place if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N)) { - esp_err_t response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | - WIFI_PROTOCOL_11N); // Enable WiFi. + esp_err_t response = esp_wifi_set_protocol(wifiInterface, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | + WIFI_PROTOCOL_11N); // Enable WiFi. if (response != ESP_OK) - systemPrintf("wifiConnect: Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); + systemPrintf("Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); + } + } + + // Start AP with fixed IP + if (wifiMode == WIFI_AP || wifiMode == WIFI_AP_STA) + { + IPAddress local_IP(192, 168, 4, 1); + IPAddress gateway(192, 168, 4, 1); + IPAddress subnet(255, 255, 255, 0); + + WiFi.softAPConfig(local_IP, gateway, subnet); + + const char *softApSsid = "RTK Config"; + if (WiFi.softAP(softApSsid) == false) // Must be short enough to fit OLED Width + { + systemPrintln("WiFi AP failed to start"); + return (false); + } + systemPrintf("WiFi AP '%s' started with IP: ", softApSsid); + systemPrintln(WiFi.softAPIP()); + + // Start DNS Server + if (dnsServer.start(53, "*", WiFi.softAPIP()) == false) + { + systemPrintln("WiFi DNS Server failed to start"); + return (false); + } + else + { + if (settings.debugWifiState == true) + systemPrintln("DNS Server started"); + } + + // If we're only here to start the AP, then we're done + if (wifiMode == WIFI_AP) + { + wifiRunning = true; + return true; } } - systemPrintln("Connecting WiFi... "); + systemPrintln("Connecting to WiFi... "); if (wifiMulti == nullptr) wifiMulti = new WiFiMulti; @@ -482,14 +521,43 @@ bool wifiForceStart() if (settings.debugWifiState == true) systemPrintln("Starting WiFi"); + // Determine which parts of WiFi need to be started + bool startWiFiStation = false; + bool startWiFiAP = false; + + // Only one bit is set, WiFi Station is default + if (networkGetConsumerTypes() == (1 << NETCONSUMER_ANY)) + startWiFiStation = true; + + // The consumers need both + else if (networkGetConsumerTypes() & ((1 << NETCONSUMER_AP) | (1 << NETCONSUMER_STA))) + { + startWiFiStation = true; + startWiFiAP = true; + } + + // The consumers need station + else if (networkGetConsumerTypes() & (1 << NETCONSUMER_STA)) + startWiFiStation = true; + + // The consumers need AP + else if (networkGetConsumerTypes() & (1 << NETCONSUMER_AP)) + startWiFiAP = true; + // Start WiFi - if (wifiConnect(settings.wifiConnectTimeoutMs)) + if (wifiConnect(startWiFiStation, startWiFiAP, settings.wifiConnectTimeoutMs)) { wifiResetTimeout(); if (settings.debugWifiState == true) systemPrintln("WiFi: Start timeout reset to zero"); } } + + // If we are in AP only mode, as long as the AP is started, returned true + if (WiFi.getMode() == WIFI_MODE_AP) + return (true); + + // If we are in STA or AP+STA mode, return if the station connected successfully wifiStatus = WiFi.status(); return (wifiStatus == WL_CONNECTED); } @@ -561,6 +629,9 @@ NETWORK_POLL_SEQUENCE wifiStopSequence[] = { //---------------------------------------- void wifiStop() { + // Stop the web server + stopWebServer(); + // Stop the DNS server if we were using the captive portal if (((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) && settings.enableCaptivePortal) dnsServer.stop(); @@ -613,14 +684,6 @@ void wifiStop(NetIndex_t index, uintptr_t parameter, bool debug) // WiFi Config Support Routines - compiled out //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -//---------------------------------------- -// Set AP mode -//---------------------------------------- -void wifiSetApMode() -{ - WiFi.mode(WIFI_AP); -} - //---------------------------------------- // Start the WiFi access point //---------------------------------------- @@ -654,33 +717,6 @@ bool wifiStartAP(bool forceAP) if (settings.debugWifiState == true) systemPrintln("WiFi protocols set"); } - - IPAddress local_IP(192, 168, 4, 1); - IPAddress gateway(192, 168, 4, 1); - IPAddress subnet(255, 255, 255, 0); - - WiFi.softAPConfig(local_IP, gateway, subnet); - - const char *softApSsid = "RTK Config"; - if (WiFi.softAP(softApSsid) == false) // Must be short enough to fit OLED Width - { - systemPrintln("WiFi AP failed to start"); - return (false); - } - systemPrintf("WiFi AP '%s' started with IP: ", softApSsid); - systemPrintln(WiFi.softAPIP()); - - // Start DNS Server - if (dnsServer.start(53, "*", WiFi.softAPIP()) == false) - { - systemPrintln("WiFi DNS Server failed to start"); - return (false); - } - else - { - if (settings.debugWifiState == true) - systemPrintln("DNS Server started"); - } } else { diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index ab3e8f946..5b9872613 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -461,6 +461,9 @@ bool otaCheckVersion(char *versionAvailable, uint8_t versionAvailableLength) // Call getVersion after original inquiry String otaVersion = ota.GetVersion(); otaVersion.toCharArray(versionAvailable, versionAvailableLength); + + if (settings.debugFirmwareUpdate) + systemPrintf("Reported version available: %s\r\n", versionAvailable); } else if (response == ESP32OTAPull::HTTP_FAILED) { @@ -513,7 +516,7 @@ void otaUpdateFirmware() #endif // COMPILE_NETWORK } -// Start WiFi STA outside of the network layer and perform the over-the-air update +// Start WiFi outside of the network layer and perform the over-the-air update void otaForcedUpdate() { #ifdef COMPILE_NETWORK @@ -535,11 +538,6 @@ void otaForcedUpdate() true)) // Use WIFI_AP_STA if already in WIFI_AP mode otaUpdateFirmware(); - // If we're here, the update failed - // If we were in WIFI_AP mode, return to WIFI_AP mode - if (wasInAPmode) - wifiSetApMode(); - if (systemState != STATE_WIFI_CONFIG) { // WIFI_STOP() turns off the entire radio including the webserver. We need to turn off Station mode @@ -809,7 +807,9 @@ void otaUpdateStop() if (otaState != OTA_STATE_OFF) { // Stop network - systemPrintln("Firmware update releasing network request"); + if (settings.debugFirmwareUpdate) + systemPrintln("Firmware update releasing network request"); + online.otaFirmwareUpdate = false; otaRequestFirmwareUpdate = false; // Let the network know we no longer need it @@ -882,41 +882,41 @@ void otaUpdate() if (settings.debugFirmwareUpdate) systemPrintln("Firmware update checking SparkFun released firmware version"); - // Only update to production firmware, disable release candidates - enableRCFirmware = 0; + // If we are using auto updates, only update to production firmware, disable release candidates + if (settings.enableAutoFirmwareUpdate) + enableRCFirmware = 0; // Get firmware version from server otaReportedVersion[0] = 0; if (otaCheckVersion(otaReportedVersion, sizeof(otaReportedVersion))) { - // If we are doing just a version check, set version number, turn off network request and stop machine - if (otaRequestFirmwareVersionCheck == true) - { - otaRequestFirmwareVersionCheck = false; - otaUpdateStop(); - return; - } - // Create a string of the unit's current firmware version char currentVersion[21]; getFirmwareVersion(currentVersion, sizeof(currentVersion), enableRCFirmware); - // If we are doing a scheduled automatic update or a manually requested update, continue through the - // state machine - // We got a version number, now determine if it's newer or not + // Allow update if locally compiled developer version if ((isReportedVersionNewer(otaReportedVersion, ¤tVersion[1]) == true) || (currentVersion[0] == 'd') || (FIRMWARE_VERSION_MAJOR == 99)) { - // Allow update if locally compiled developer version - if (settings.debugFirmwareUpdate) - systemPrintf("Firmware update detected new firmware version %s\r\n", otaReportedVersion); + systemPrintf("Version Check: New firmware version available: %s\r\n", otaReportedVersion); + + // If we are doing just a version check, set version number, turn off network request and stop + // machine + if (otaRequestFirmwareVersionCheck == true) + { + otaRequestFirmwareVersionCheck = false; + otaUpdateStop(); + return; + } + + // If we are doing a scheduled automatic update or a manually requested update, continue through the + // state machine otaSetState(OTA_STATE_UPDATE_FIRMWARE); } else { - if (settings.debugFirmwareUpdate) - systemPrintln("Firmware update, no new firmware available"); + systemPrintln("Version Check: Firmware is up to date. No new firmware available."); otaUpdateStop(); } } diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 58f97a91b..ffd11b3f2 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -614,6 +614,20 @@ const int numRegionalAreas = sizeof(Regional_Information_Table) / sizeof(Regiona #define NTRIP_SERVER_STRING_SIZE 50 +//Bitfield for describing the type of network the consumer needs +enum +{ + NETCONSUMER_NONE = 0, // No consumers + NETCONSUMER_WIFI_STA, // The consumer needs STA + NETCONSUMER_WIFI_AP, // The consumer needs AP + NETCONSUMER_WIFI_AP_STA, // The consumer needs STA and AP + NETCONSUMER_CELLULAR, // The consumer needs Cellular + NETCONSUMER_ETHERNET, // The consumer needs Ethernet + NETCONSUMER_ANY, // The consumer doesn't care what type of network access is granted + NETCONSUMER_UNKNOWN +}; +uint16_t networkConsumerTypes = NETCONSUMER_NONE; + // This is all the settings that can be set on RTK Product. It's recorded to NVM and the config file. // Avoid reordering. The order of these variables is mimicked in NVM/record/parse/create/update/get struct Settings @@ -1819,15 +1833,9 @@ typedef int8_t NetPriority_t; // Index into networkPriorityTable enum NetworkTypes { NETWORK_NONE = -1, // The values below must start at zero and be sequential - #ifdef COMPILE_ETHERNET - NETWORK_ETHERNET, - #endif // COMPILE_ETHERNET - #ifdef COMPILE_WIFI - NETWORK_WIFI = 1, - #endif // COMPILE_WIFI - #ifdef COMPILE_CELLULAR - NETWORK_CELLULAR, - #endif // COMPILE_CELLULAR + NETWORK_ETHERNET = 0, + NETWORK_WIFI = 1, + NETWORK_CELLULAR = 2, // Add new networks here NETWORK_MAX }; @@ -1868,21 +1876,28 @@ extern NETWORK_POLL_SEQUENCE laraOffSequence[]; extern NETWORK_POLL_SEQUENCE laraOnSequence[]; // List of networks -// Multiple networks may running in parallel with highest priority being -// set to the default network. The start routine is called as the priority -// drops to that level. The stop routine is called as the priority rises -// above that level. The priority will continue to fall or rise until a +// Only one network is turned on at a time. The start routine is called as the priority +// drops to that level. The stop routine is called as the priority rises +// above that level. The priority will continue to fall or rise until a // network is found that is online. const NETWORK_TABLE_ENTRY networkInterfaceTable[] = { // Interface Name Present Periodic State Boot Sequence Start Sequence Stop Sequence #ifdef COMPILE_ETHERNET {Ð, "Ethernet", &present.ethernet_ws5500, PD_ETHERNET_STATE, nullptr, nullptr, nullptr}, + #else + {nullptr, "Ethernet-NotCompiled", nullptr, PD_ETHERNET_STATE, nullptr, nullptr, nullptr}, #endif // COMPILE_ETHERNET + #ifdef COMPILE_WIFI {&WiFi.STA, "WiFi", nullptr, PD_WIFI_STATE, nullptr, wifiStartSequence, wifiStopSequence}, + #else + {nullptr, "WiFi-NotCompiled", nullptr, PD_WIFI_STATE, nullptr, nullptr, nullptr}, #endif // COMPILE_WIFI + #ifdef COMPILE_CELLULAR {&PPP, "Cellular", &present.cellular_lara, PD_CELLULAR_STATE, laraBootSequence, laraOnSequence, laraOffSequence}, + #else + {nullptr, "Cellular-NotCompiled", nullptr, PD_CELLULAR_STATE, nullptr, nullptr, nullptr}, #endif // COMPILE_CELLULAR }; const int networkInterfaceTableEntries = sizeof(networkInterfaceTable) / sizeof(networkInterfaceTable[0]); From d69519c76eb4f9b3fe1db640e3076d05d38fd259 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 20 Dec 2024 16:30:21 -0700 Subject: [PATCH 031/276] Merge WIP changes --- Firmware/RTK_Everywhere/Network.ino | 7 +- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 4 +- Firmware/RTK_Everywhere/States.ino | 34 +- Firmware/RTK_Everywhere/WebServer.ino | 695 +++++++++++---------- Firmware/RTK_Everywhere/WiFi.ino | 4 +- Firmware/RTK_Everywhere/settings.h | 2 +- 6 files changed, 385 insertions(+), 361 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index b069fb7b7..95816c038 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1411,6 +1411,8 @@ void networkUpdate() udpServerUpdate(); // Turn on the UDP server as needed DMW_c("httpClientUpdate"); httpClientUpdate(); // Process any Point Perfect HTTP messages + DMW_c("webServerUpdate"); + webServerUpdate(); // Start webServer for web config as needed // Periodically display the network interface state displayIpAddress = PERIODIC_DISPLAY(PD_IP_ADDRESS); @@ -1586,9 +1588,8 @@ uint8_t networkConsumers() networkConsumerTypes |= (1 << NETCONSUMER_WIFI_STA); // OTA Pull library only supports WiFi } - // Network needed for web configuration - // if (webConfigRequested == true) - if (false) + // Network needed for Web Config + if (inWiFiConfigMode() == true) { consumerCount++; consumerId |= (1 << 9); diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 0819fdcd1..4d6f73886 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -557,6 +557,8 @@ int incomingSettingsSpot; unsigned long timeSinceLastIncomingSetting; unsigned long lastDynamicDataUpdate; +bool webServerRequest = false; // Goes true when STATE_WIFI_CONFIG_NOT_STARTED is entered. Goes false when Rover/Base is started. + #ifdef COMPILE_WIFI #ifdef COMPILE_AP @@ -567,7 +569,7 @@ unsigned long lastDynamicDataUpdate; // https://github.com/espressif/arduino-esp32/blob/master/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino DNSServer *dnsserver; -WebServer *webserver; +WebServer *webServer; httpd_handle_t *wsserver = nullptr; // httpd_req_t *last_ws_req; diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 23f22f99c..fd2fb800f 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -7,6 +7,8 @@ static uint32_t lastStateTime = 0; +extern bool websocketConnected; + // Given the current state, see if conditions have moved us to a new state // A user pressing the mode button (change between rover/base) is handled by buttonCheckTask() void stateUpdate() @@ -413,16 +415,21 @@ void stateUpdate() baseStatusLedOff(); // Turn off the status LED displayWiFiConfigNotStarted(); // Display immediately during SD cluster pause - - //WIFI_STOP(); // Notify the network layer that it should stop so we can take over control of WiFi + + // TODO - Do we need to stop BT and ESP-NOW? bluetoothStop(); espnowStop(); + tasksStopGnssUart(); // Delete serial tasks if running - tasksStopGnssUart(); // Delete serial tasks if running - // if (!startWebServer()) // Start web server in WiFi mode and show config html page - if (!startWebServer(false, settings.httpPort)) // Start the web server. Network layer starts WiFi. - changeState(STATE_ROVER_NOT_STARTED); - else + webServerRequest = true; // Notify the network that we need access, start web server + + changeState(STATE_WIFI_CONFIG_WAIT_FOR_NETWORK); + } + break; + + case (STATE_WIFI_CONFIG_WAIT_FOR_NETWORK): { + // Wait while web server starts + if (webServerIsRunning() == true) { RTK_MODE(RTK_MODE_WIFI_CONFIG); changeState(STATE_WIFI_CONFIG); @@ -650,10 +657,15 @@ void stateUpdate() ethernetWebServerStartESP32W5500(); // Start Ethernet in dedicated configure-via-ethernet mode - if (!webServerStart(false, settings.httpPort)) // Start the web server - changeState(STATE_ROVER_NOT_STARTED); - else - changeState(STATE_CONFIG_VIA_ETH); + webServerRequest = true; // Notify the network that we need access, start web server + + // TODO add a state machine step for ethernet to wait for web server to start + // See wifi web server / web config + + // if (!webServerStart(false, settings.httpPort)) // Start the web server + // changeState(STATE_ROVER_NOT_STARTED); + // else + // changeState(STATE_CONFIG_VIA_ETH); } break; diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index 4882f7698..de4ac071a 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -6,15 +6,18 @@ Form.ino #ifdef COMPILE_AP -static const char *const webserverStateNames[] = { - "WEBSERVER_STATE_OFF", "WEBSERVER_STATE_WAIT_FOR_NETWORK", "WEBSERVER_STATE_NETWORK_CONNECTED", - "WEBSERVER_STATE_STARTED", "WEBSERVER_STATE_RUNNING", +static const char *const webServerStateNames[] = { + "WEBSERVER_STATE_OFF", + "WEBSERVER_STATE_WAIT_FOR_NETWORK", + "WEBSERVER_STATE_NETWORK_CONNECTED", + "WEBSERVER_STATE_STARTED", + "WEBSERVER_STATE_RUNNING", }; -static const int webserverStateEntries = sizeof(webserverStateNames) / sizeof(webserverStateNames[0]); +static const int webServerStateEntries = sizeof(webServerStateNames) / sizeof(webServerStateNames[0]); static NetPriority_t webconfigPriority = NETWORK_OFFLINE; -static webserverState webserverState; +static WebServerState webServerState; // Once connected to the access point for WiFi Config, the ESP32 sends current setting values in one long string to // websocket After user clicks 'save', data is validated via main.js and a long string of values is returned. @@ -40,7 +43,7 @@ void sendStringToWebsocket(const char *stringToSend) return; } - // To send content to the webserver, we would call: webserver->sendContent(stringToSend); + // To send content to the webServer, we would call: webServer->sendContent(stringToSend); // But here we want to send content to the websocket (wsserver)... httpd_ws_frame_t ws_pkt; @@ -175,7 +178,7 @@ static void start_wsserver(void) { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); - // Use different ports for websocket and webserver - use port 81 for the websocket - also defined in main.js + // Use different ports for websocket and webServer - use port 81 for the websocket - also defined in main.js config.server_port = 81; // Increase the stack size from 4K to ~15K @@ -204,7 +207,7 @@ static void start_wsserver(void) // https://github.com/espressif/arduino-esp32/blob/master/libraries/WebServer/examples/WebServer/WebServer.ino class CaptiveRequestHandler : public RequestHandler { - public: +public: // https://en.wikipedia.org/wiki/Captive_portal String urls[5] = {"/hotspot-detect.html", "/library/test/success.html", "/generate_204", "/ncsi.txt", "/check_network_status.txt"}; @@ -248,15 +251,15 @@ class CaptiveRequestHandler : public RequestHandler }; // State machine to handle the starting/stopping of the web server -void websServerUpdate() +void webServerUpdate() { if (!inMainMenu) { // Walk the state machine - switch (webserverState) + switch (webServerState) { default: - systemPrintf("ERROR: Unknown WebConfig state (%d)\r\n", webserverState); + systemPrintf("ERROR: Unknown WebConfig state (%d)\r\n", webServerState); // Stop the machine webServerStop(); @@ -264,14 +267,14 @@ void websServerUpdate() // Wait for a request from a user case WEBSERVER_STATE_OFF: - if (webconfigRequest == true) + if (webServerRequest == true) webServerSetState(WEBSERVER_STATE_WAIT_FOR_NETWORK); break; // Wait for connection to the network case WEBSERVER_STATE_WAIT_FOR_NETWORK: // Determine if the request has been canceled while waiting - if (webconfigRequest == false) + if (webServerRequest == false) webServerStop(); // Wait until the network is connected to the media @@ -291,9 +294,9 @@ void websServerUpdate() if (!networkIsConnected(&webconfigPriority)) webServerStop(); if (settings.debugWebServer) - systemPrintln("Web config starting web server"); + systemPrintln("Starting web server"); - if (webServerStart(false, settings.httpPort) == true) + if (web2(false, settings.httpPort) == true) webServerSetState(WEBSERVER_STATE_STARTED); break; @@ -320,7 +323,7 @@ void websServerUpdate() // TODO how does the system indicate we need to shut down the web server? if (inWiFiConfigMode() == false) { - webconfigRequest = false; // Tell the network layer we no longer need access + webServerRequest = false; // Tell the network layer we no longer need access webServerStop(); } @@ -334,20 +337,18 @@ void websServerUpdate() // Stop the web config state machine void webServerStop() { - webconfigRequest = false; //Notify the web config state machine to start up + webServerRequest = false; // Notify the network layer that access is no longer needed if (settings.debugWebServer) systemPrintln("webServerStop called"); - if (webserverState != WEBSERVER_STATE_OFF) + if (webServerState != WEBSERVER_STATE_OFF) { - webServerStopSockets(); // Release socket resources - webServerStop(); // Release web server resources + webServerStopSockets(); // Release socket resources + webServerReleaseResources(); // Release web server resources // Stop network - systemPrintln("Web Config releasing network request"); - - webserverRequested = false; // Let the network know we no longer need it + systemPrintln("Web Server releasing network request"); // Stop the machine webServerSetState(WEBSERVER_STATE_OFF); @@ -368,7 +369,7 @@ void webServerStopSockets() } // Set the next webconfig state -void webServerSetState(webserverState newState) +void webServerSetState(WebServerState newState) { char string1[40]; char string2[40]; @@ -383,17 +384,17 @@ void webServerSetState(webserverState newState) arrow = ""; asterisk = ""; initialState = ""; - if (newState == webserverState) + if (newState == webServerState) asterisk = "*"; else { - initialState = webServerGetStateName(webserverState, string1); + initialState = webServerGetStateName(webServerState, string1); arrow = " --> "; } } // Set the new state - webserverState = newState; + webServerState = newState; if (settings.debugWebServer) { // Display the new firmware update state @@ -419,299 +420,307 @@ void webServerSetState(webserverState newState) } // Get the webconfig state name -const char *webServerGetStateName(webserverState state, char *string) +const char *webServerGetStateName(WebServerState state, char *string) { if (state < WEBSERVER_STATE_MAX) - return webserverStateNames[state]; + return webServerStateNames[state]; sprintf(string, "Unknown state (%d)", state); return string; } -bool webServerIsStarted() +bool webServerIsRunning() { - if() + if (webServerState == WEBSERVER_STATE_RUNNING) + return (true); + return (false); } - -// Start webserver in AP mode -bool webServerStart(bool startWiFi = true, int httpPort = 80) +bool web2(bool startWiFi = true, int httpPort = 80) { - do - { - ntripClientStop(true); // Do not allocate new wifiClient - for (int serverIndex = 0; serverIndex < NTRIP_SERVER_MAX; serverIndex++) - ntripServerStop(serverIndex, true); // Do not allocate new wifiClient - - // if (startWiFi) - // if (wifiStartAP() == false) - // break; - - // // Start the multicast DNS server - // if (startWiFi == true) - // networkMulticastDNSSwitch(NETWORK_WIFI); - // else - // networkMulticastDNSSwitch(NETWORK_ETHERNET); - - // Freed by webServerStop - if (online.psram == true) - incomingSettings = (char *)ps_malloc(AP_CONFIG_SETTING_SIZE); - else - incomingSettings = (char *)malloc(AP_CONFIG_SETTING_SIZE); - - if (!incomingSettings) - { - systemPrintln("ERROR: Failed to allocate incomingSettings"); - break; - } - memset(incomingSettings, 0, AP_CONFIG_SETTING_SIZE); - - // Pre-load settings CSV - // Freed by webServerStop - if (online.psram == true) - settingsCSV = (char *)ps_malloc(AP_CONFIG_SETTING_SIZE); - else - settingsCSV = (char *)malloc(AP_CONFIG_SETTING_SIZE); - - if (!settingsCSV) - { - systemPrintln("ERROR: Failed to allocate settingsCSV"); - break; - } - createSettingsString(settingsCSV); - - // https://github.com/espressif/arduino-esp32/blob/master/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino - if (settings.enableCaptivePortal == true) - { - dnsserver = new DNSServer; - dnsserver->start(); - } - - webserver = new WebServer(httpPort); - // TODO: webserver = new WebServer(WiFi.localIP(), httpPort); - // TODO: webserver = new WebServer(ETH.localIP(), httpPort); - - if (!webserver) - { - systemPrintln("ERROR: Failed to allocate webserver"); - break; - } - - if (settings.enableCaptivePortal == true) - { - webserver->addHandler(new CaptiveRequestHandler()); - - // TODO: add a handler for /connecttest.txt - } - - // * index.html (not gz'd) - // * favicon.ico - - // * /src/bootstrap.bundle.min.js - Needed for popper - // * /src/bootstrap.min.css - // * /src/bootstrap.min.js - // * /src/jquery-3.6.0.min.js - // * /src/main.js (not gz'd) - // * /src/rtk-setup.png - // * /src/style.css - - // * /src/fonts/icomoon.eot - // * /src/fonts/icomoon.svg - // * /src/fonts/icomoon.ttf - // * /src/fonts/icomoon.woof - - // * /listfiles responds with a CSV of files and sizes in root - // * /listMessages responds with a CSV of messages supported by this platform - // * /listMessagesBase responds with a CSV of RTCM Base messages supported by this platform - // * /file allows the download or deletion of a file - - webserver->onNotFound(notFound); - - webserver->on("/", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/html", (const char *)index_html, sizeof(index_html)); - }); - - webserver->on("/favicon.ico", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/plain", (const char *)favicon_ico, sizeof(favicon_ico)); - }); - - webserver->on("/src/bootstrap.bundle.min.js", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/javascript", (const char *)bootstrap_bundle_min_js, - sizeof(bootstrap_bundle_min_js)); - }); - - webserver->on("/src/bootstrap.min.css", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/css", (const char *)bootstrap_min_css, sizeof(bootstrap_min_css)); - }); - - webserver->on("/src/bootstrap.min.js", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/javascript", (const char *)bootstrap_min_js, sizeof(bootstrap_min_js)); - }); - - webserver->on("/src/jquery-3.6.0.min.js", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/javascript", (const char *)jquery_js, sizeof(jquery_js)); - }); - - webserver->on("/src/main.js", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/javascript", (const char *)main_js, sizeof(main_js)); - }); - - webserver->on("/src/rtk-setup.png", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - if (productVariant == RTK_EVK) - webserver->send_P(200, "image/png", (const char *)rtkSetup_png, sizeof(rtkSetup_png)); - else - webserver->send_P(200, "image/png", (const char *)rtkSetupWiFi_png, sizeof(rtkSetupWiFi_png)); - }); - - // Battery icons - webserver->on("/src/BatteryBlank.png", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "image/png", (const char *)batteryBlank_png, sizeof(batteryBlank_png)); - }); - webserver->on("/src/Battery0.png", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "image/png", (const char *)battery0_png, sizeof(battery0_png)); - }); - webserver->on("/src/Battery1.png", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "image/png", (const char *)battery1_png, sizeof(battery1_png)); - }); - webserver->on("/src/Battery2.png", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "image/png", (const char *)battery2_png, sizeof(battery2_png)); - }); - webserver->on("/src/Battery3.png", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "image/png", (const char *)battery3_png, sizeof(battery3_png)); - }); - - webserver->on("/src/Battery0_Charging.png", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "image/png", (const char *)battery0_Charging_png, sizeof(battery0_Charging_png)); - }); - webserver->on("/src/Battery1_Charging.png", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "image/png", (const char *)battery1_Charging_png, sizeof(battery1_Charging_png)); - }); - webserver->on("/src/Battery2_Charging.png", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "image/png", (const char *)battery2_Charging_png, sizeof(battery2_Charging_png)); - }); - webserver->on("/src/Battery3_Charging.png", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "image/png", (const char *)battery3_Charging_png, sizeof(battery3_Charging_png)); - }); - - webserver->on("/src/style.css", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/css", (const char *)style_css, sizeof(style_css)); - }); - - webserver->on("/src/fonts/icomoon.eot", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/plain", (const char *)icomoon_eot, sizeof(icomoon_eot)); - }); - - webserver->on("/src/fonts/icomoon.svg", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/plain", (const char *)icomoon_svg, sizeof(icomoon_svg)); - }); - - webserver->on("/src/fonts/icomoon.ttf", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/plain", (const char *)icomoon_ttf, sizeof(icomoon_ttf)); - }); - - webserver->on("/src/fonts/icomoon.woof", HTTP_GET, []() { - webserver->sendHeader("Content-Encoding", "gzip"); - webserver->send_P(200, "text/plain", (const char *)icomoon_woof, sizeof(icomoon_woof)); - }); - - // Handler for the /uploadFile form POST - webserver->on( - "/uploadFile", HTTP_POST, []() { webserver->send(200, "text/plain", ""); }, - handleUpload); // Run handleUpload function when file manager file is uploaded - - // Handler for the /uploadFirmware form POST - webserver->on( - "/uploadFirmware", HTTP_POST, []() { webserver->send(200, "text/plain", ""); }, handleFirmwareFileUpload); - - // Handler for file manager - webserver->on("/listfiles", HTTP_GET, []() { - String logmessage = "Client:" + webserver->client().remoteIP().toString() + " " + webserver->uri(); - if (settings.debugWebServer == true) - systemPrintln(logmessage); - String files; - getFileList(files); - webserver->send(200, "text/plain", files); - }); - - // Handler for supported messages list - webserver->on("/listMessages", HTTP_GET, []() { - String logmessage = "Client:" + webserver->client().remoteIP().toString() + " " + webserver->uri(); - if (settings.debugWebServer == true) - systemPrintln(logmessage); - String messages; - createMessageList(messages); - if (settings.debugWebServer == true) - systemPrintln(messages); - webserver->send(200, "text/plain", messages); - }); - - // Handler for supported RTCM/Base messages list - webserver->on("/listMessagesBase", HTTP_GET, []() { - String logmessage = "Client:" + webserver->client().remoteIP().toString() + " " + webserver->uri(); - if (settings.debugWebServer == true) - systemPrintln(logmessage); - String messageList; - createMessageListBase(messageList); - if (settings.debugWebServer == true) - systemPrintln(messageList); - webserver->send(200, "text/plain", messageList); - }); - - // Handler for file manager - webserver->on("/file", HTTP_GET, handleFileManager); - - webserver->begin(); - - // Starts task for updating webserver with handleClient - if (task.updateWebServerTaskRunning == false) - xTaskCreate( - updateWebServerTask, - "UpdateWebServer", // Just for humans - updateWebServerTaskStackSize, // Stack Size - needs to be large enough to hold the file manager list - nullptr, // Task input parameter - updateWebServerTaskPriority, - &updateWebServerTaskHandle); // Task handle - - if (settings.debugWebServer == true) - systemPrintln("Web Server Started"); - reportHeapNow(false); - - // Start the web socket server on port 81 using - start_wsserver(); - - if (settings.debugWebServer == true) - systemPrintln("Web Socket Server Started"); - reportHeapNow(false); - - return true; - } while (0); - - // Release the resources - webServerStopSockets(); - webServerStop(); - return false; + return(false); } +// Start webServer in AP mode +// bool webServerStart(bool startWiFi = true, int httpPort = 80) +// { +// do +// { +// ntripClientStop(true); // Do not allocate new wifiClient +// for (int serverIndex = 0; serverIndex < NTRIP_SERVER_MAX; serverIndex++) +// ntripServerStop(serverIndex, true); // Do not allocate new wifiClient + +// // if (startWiFi) +// // if (wifiStartAP() == false) +// // break; + +// // // Start the multicast DNS server +// // if (startWiFi == true) +// // networkMulticastDNSSwitch(NETWORK_WIFI); +// // else +// // networkMulticastDNSSwitch(NETWORK_ETHERNET); + +// // Freed by webServerStop +// if (online.psram == true) +// incomingSettings = (char *)ps_malloc(AP_CONFIG_SETTING_SIZE); +// else +// incomingSettings = (char *)malloc(AP_CONFIG_SETTING_SIZE); + +// if (!incomingSettings) +// { +// systemPrintln("ERROR: Failed to allocate incomingSettings"); +// break; +// } +// memset(incomingSettings, 0, AP_CONFIG_SETTING_SIZE); + +// // Pre-load settings CSV +// // Freed by webServerStop +// if (online.psram == true) +// settingsCSV = (char *)ps_malloc(AP_CONFIG_SETTING_SIZE); +// else +// settingsCSV = (char *)malloc(AP_CONFIG_SETTING_SIZE); + +// if (!settingsCSV) +// { +// systemPrintln("ERROR: Failed to allocate settingsCSV"); +// break; +// } +// createSettingsString(settingsCSV); + +// // https://github.com/espressif/arduino-esp32/blob/master/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino +// if (settings.enableCaptivePortal == true) +// { +// dnsserver = new DNSServer; +// dnsserver->start(); +// } + +// webServer = new WebServer(httpPort); +// // TODO: webServer = new WebServer(WiFi.localIP(), httpPort); +// // TODO: webServer = new WebServer(ETH.localIP(), httpPort); + +// if (!webServer) +// { +// systemPrintln("ERROR: Failed to allocate webServer"); +// break; +// } + +// if (settings.enableCaptivePortal == true) +// { +// webServer->addHandler(new CaptiveRequestHandler()); + +// // TODO: add a handler for /connecttest.txt +// } + +// // * index.html (not gz'd) +// // * favicon.ico + +// // * /src/bootstrap.bundle.min.js - Needed for popper +// // * /src/bootstrap.min.css +// // * /src/bootstrap.min.js +// // * /src/jquery-3.6.0.min.js +// // * /src/main.js (not gz'd) +// // * /src/rtk-setup.png +// // * /src/style.css + +// // * /src/fonts/icomoon.eot +// // * /src/fonts/icomoon.svg +// // * /src/fonts/icomoon.ttf +// // * /src/fonts/icomoon.woof + +// // * /listfiles responds with a CSV of files and sizes in root +// // * /listMessages responds with a CSV of messages supported by this platform +// // * /listMessagesBase responds with a CSV of RTCM Base messages supported by this platform +// // * /file allows the download or deletion of a file + +// webServer->onNotFound(notFound); + +// webServer->on("/", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/html", (const char *)index_html, sizeof(index_html)); }); + +// webServer->on("/favicon.ico", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/plain", (const char *)favicon_ico, sizeof(favicon_ico)); }); + +// webServer->on("/src/bootstrap.bundle.min.js", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/javascript", (const char *)bootstrap_bundle_min_js, +// sizeof(bootstrap_bundle_min_js)); }); + +// webServer->on("/src/bootstrap.min.css", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/css", (const char *)bootstrap_min_css, sizeof(bootstrap_min_css)); }); + +// webServer->on("/src/bootstrap.min.js", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/javascript", (const char *)bootstrap_min_js, sizeof(bootstrap_min_js)); }); + +// webServer->on("/src/jquery-3.6.0.min.js", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/javascript", (const char *)jquery_js, sizeof(jquery_js)); }); + +// webServer->on("/src/main.js", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/javascript", (const char *)main_js, sizeof(main_js)); }); + +// webServer->on("/src/rtk-setup.png", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// if (productVariant == RTK_EVK) +// webServer->send_P(200, "image/png", (const char *)rtkSetup_png, sizeof(rtkSetup_png)); +// else +// webServer->send_P(200, "image/png", (const char *)rtkSetupWiFi_png, sizeof(rtkSetupWiFi_png)); }); + +// // Battery icons +// webServer->on("/src/BatteryBlank.png", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "image/png", (const char *)batteryBlank_png, sizeof(batteryBlank_png)); }); +// webServer->on("/src/Battery0.png", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "image/png", (const char *)battery0_png, sizeof(battery0_png)); }); +// webServer->on("/src/Battery1.png", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "image/png", (const char *)battery1_png, sizeof(battery1_png)); }); +// webServer->on("/src/Battery2.png", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "image/png", (const char *)battery2_png, sizeof(battery2_png)); }); +// webServer->on("/src/Battery3.png", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "image/png", (const char *)battery3_png, sizeof(battery3_png)); }); + +// webServer->on("/src/Battery0_Charging.png", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "image/png", (const char *)battery0_Charging_png, sizeof(battery0_Charging_png)); }); +// webServer->on("/src/Battery1_Charging.png", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "image/png", (const char *)battery1_Charging_png, sizeof(battery1_Charging_png)); }); +// webServer->on("/src/Battery2_Charging.png", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "image/png", (const char *)battery2_Charging_png, sizeof(battery2_Charging_png)); }); +// webServer->on("/src/Battery3_Charging.png", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "image/png", (const char *)battery3_Charging_png, sizeof(battery3_Charging_png)); }); + +// webServer->on("/src/style.css", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/css", (const char *)style_css, sizeof(style_css)); }); + +// webServer->on("/src/fonts/icomoon.eot", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/plain", (const char *)icomoon_eot, sizeof(icomoon_eot)); }); + +// webServer->on("/src/fonts/icomoon.svg", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/plain", (const char *)icomoon_svg, sizeof(icomoon_svg)); }); + +// webServer->on("/src/fonts/icomoon.ttf", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/plain", (const char *)icomoon_ttf, sizeof(icomoon_ttf)); }); + +// webServer->on("/src/fonts/icomoon.woof", HTTP_GET, []() +// { +// webServer->sendHeader("Content-Encoding", "gzip"); +// webServer->send_P(200, "text/plain", (const char *)icomoon_woof, sizeof(icomoon_woof)); }); + +// // Handler for the /uploadFile form POST +// webServer->on( +// "/uploadFile", HTTP_POST, []() +// { webServer->send(200, "text/plain", ""); }, +// handleUpload); // Run handleUpload function when file manager file is uploaded + +// // Handler for the /uploadFirmware form POST +// webServer->on( +// "/uploadFirmware", HTTP_POST, []() +// { webServer->send(200, "text/plain", ""); }, handleFirmwareFileUpload); + +// // Handler for file manager +// webServer->on("/listfiles", HTTP_GET, []() +// { +// String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); +// if (settings.debugWebServer == true) +// systemPrintln(logmessage); +// String files; +// getFileList(files); +// webServer->send(200, "text/plain", files); }); + +// // Handler for supported messages list +// webServer->on("/listMessages", HTTP_GET, []() +// { +// String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); +// if (settings.debugWebServer == true) +// systemPrintln(logmessage); +// String messages; +// createMessageList(messages); +// if (settings.debugWebServer == true) +// systemPrintln(messages); +// webServer->send(200, "text/plain", messages); }); + +// // Handler for supported RTCM/Base messages list +// webServer->on("/listMessagesBase", HTTP_GET, []() +// { +// String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); +// if (settings.debugWebServer == true) +// systemPrintln(logmessage); +// String messageList; +// createMessageListBase(messageList); +// if (settings.debugWebServer == true) +// systemPrintln(messageList); +// webServer->send(200, "text/plain", messageList); }); + +// // Handler for file manager +// webServer->on("/file", HTTP_GET, handleFileManager); + +// webServer->begin(); + +// // Starts task for updating webServer with handleClient +// if (task.updateWebServerTaskRunning == false) +// xTaskCreate( +// updateWebServerTask, +// "UpdateWebServer", // Just for humans +// updateWebServerTaskStackSize, // Stack Size - needs to be large enough to hold the file manager list +// nullptr, // Task input parameter +// updateWebServerTaskPriority, +// &updateWebServerTaskHandle); // Task handle + +// if (settings.debugWebServer == true) +// systemPrintln("Web Server Started"); +// reportHeapNow(false); + +// // Start the web socket server on port 81 using +// start_wsserver(); + +// if (settings.debugWebServer == true) +// systemPrintln("Web Socket Server Started"); +// reportHeapNow(false); + +// return true; +// } while (0); + +// // Release the resources +// webServerStopSockets(); +// webServerReleaseResources(); +// return false; +// } + void updateWebServerTask(void *e) { // Start notification @@ -730,7 +739,7 @@ void updateWebServerTask(void *e) systemPrintln("updateWebServerTask running"); } - webserver->handleClient(); + webServer->handleClient(); feedWdt(); taskYIELD(); @@ -743,7 +752,7 @@ void updateWebServerTask(void *e) vTaskDelete(updateWebServerTaskHandle); } -void webServerStop() +void webServerReleaseResources() { if (task.updateWebServerTaskRunning) task.updateWebServerTaskStopRequest = true; @@ -753,11 +762,11 @@ void webServerStop() delay(10); while (task.updateWebServerTaskRunning); - if (webserver != nullptr) + if (webServer != nullptr) { - webserver->close(); - free(webserver); - webserver = nullptr; + webServer->close(); + free(webServer); + webServer = nullptr; } // Stop the multicast DNS server @@ -778,9 +787,9 @@ void webServerStop() void notFound() { - String logmessage = "notFound: Client:" + webserver->client().remoteIP().toString() + " " + webserver->uri(); + String logmessage = "notFound: Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); systemPrintln(logmessage); - webserver->send(404, "text/plain", "Not found"); + webServer->send(404, "text/plain", "Not found"); } // Handler for firmware file downloads @@ -788,14 +797,14 @@ static void handleFileManager() { // This section does not tolerate semaphore transactions String logmessage = - "handleFileManager: Client:" + webserver->client().remoteIP().toString() + " " + webserver->uri(); + "handleFileManager: Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); - if (webserver->hasArg("name") && webserver->hasArg("action")) + if (webServer->hasArg("name") && webServer->hasArg("action")) { - String fileName = webserver->arg("name"); - String fileAction = webserver->arg("action"); + String fileName = webServer->arg("name"); + String fileAction = webServer->arg("action"); - logmessage = "Client:" + webserver->client().remoteIP().toString() + " " + webserver->uri() + + logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri() + "?name=" + fileName + "&action=" + fileAction; char slashFileName[60]; @@ -808,7 +817,7 @@ static void handleFileManager() logmessage += " ERROR: file "; logmessage += slashFileName; logmessage += " does not exist"; - webserver->send(400, "text/plain", "ERROR: file does not exist"); + webServer->send(400, "text/plain", "ERROR: file does not exist"); } else { @@ -818,7 +827,7 @@ static void handleFileManager() { logmessage += " downloaded"; - // This would be SO much easier with webserver->streamFile + // This would be SO much easier with webServer->streamFile // except streamFile only works with File - not SdFile... // TODO: if we ever upgrade to SD from SdFat, replace this with streamFile @@ -843,7 +852,7 @@ static void handleFileManager() else { // File is already in use. Wait your turn. - webserver->send(202, "text/plain", "ERROR: File already downloading"); + webServer->send(202, "text/plain", "ERROR: File already downloading"); } const size_t maxLen = 8192; @@ -868,15 +877,15 @@ static void handleFileManager() if (firstSend) // First send? { - webserver->setContentLength(dataAvailable); - webserver->sendHeader("Cache-Control", "no-cache"); - webserver->sendHeader("Content-Disposition", "attachment; filename=" + String(fileName)); - webserver->sendHeader("Access-Control-Allow-Origin", "*"); - webserver->send(200, "application/octet-stream", ""); + webServer->setContentLength(dataAvailable); + webServer->sendHeader("Cache-Control", "no-cache"); + webServer->sendHeader("Content-Disposition", "attachment; filename=" + String(fileName)); + webServer->sendHeader("Access-Control-Allow-Origin", "*"); + webServer->send(200, "application/octet-stream", ""); firstSend = false; } - webserver->sendContent((const char *)buf, sending); + webServer->sendContent((const char *)buf, sending); if (sending < maxLen) // Last send? { @@ -896,19 +905,19 @@ static void handleFileManager() { logmessage += " deleted"; sd->remove(slashFileName); - webserver->send(200, "text/plain", "Deleted File: " + fileName); + webServer->send(200, "text/plain", "Deleted File: " + fileName); } else { logmessage += " ERROR: invalid action param supplied"; - webserver->send(400, "text/plain", "ERROR: invalid action param supplied"); + webServer->send(400, "text/plain", "ERROR: invalid action param supplied"); } } systemPrintln(logmessage); } else { - webserver->send(400, "text/plain", "ERROR: name and action params required"); + webServer->send(400, "text/plain", "ERROR: name and action params required"); } } @@ -917,7 +926,7 @@ static void handleFirmwareFileUpload() { String fileName = ""; - HTTPUpload &upload = webserver->upload(); + HTTPUpload &upload = webServer->upload(); if (upload.status == UPLOAD_FILE_START) { @@ -942,21 +951,21 @@ static void handleFirmwareFileUpload() if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { Update.printError(Serial); - webserver->send(400, "text/plain", "OTA could not begin"); + webServer->send(400, "text/plain", "OTA could not begin"); return; } } else { systemPrintf("handleFirmwareFileUpload: Unknown: %s\r\n", fname); - webserver->send(400, "text/html", "Error: Unknown file type"); + webServer->send(400, "text/html", "Error: Unknown file type"); return; } } else { systemPrintf("handleFirmwareFileUpload: Unknown: %s\r\n", fname); - webserver->send(400, "text/html", "Error: Unknown file type"); + webServer->send(400, "text/html", "Error: Unknown file type"); return; } } @@ -966,7 +975,7 @@ static void handleFirmwareFileUpload() { if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) { - webserver->send(400, "text/plain", "OTA could not begin"); + webServer->send(400, "text/plain", "OTA could not begin"); return; } else @@ -996,7 +1005,7 @@ static void handleFirmwareFileUpload() if (!Update.end(true)) { Update.printError(Serial); - webserver->send(400, "text/plain", "Could not end OTA"); + webServer->send(400, "text/plain", "Could not end OTA"); return; } else @@ -1335,7 +1344,7 @@ void createMessageListBase(String &returnText) // https://github.com/espressif/arduino-esp32/blob/master/libraries/WebServer/examples/FSBrowser/FSBrowser.ino void handleUpload() { - HTTPUpload &upload = webserver->upload(); + HTTPUpload &upload = webServer->upload(); if (upload.status == UPLOAD_FILE_START) { @@ -1377,7 +1386,7 @@ void handleUpload() else { // File is already in use. Wait your turn. - webserver->send(202, "text/plain", "ERROR: File already uploading"); + webServer->send(202, "text/plain", "ERROR: File already uploading"); } systemPrintln(logmessage); @@ -1416,8 +1425,8 @@ void handleUpload() systemPrintln(logmessage); // Redirect to "/" - webserver->sendHeader("Location", "/"); - webserver->send(302, "text/plain", ""); + webServer->sendHeader("Location", "/"); + webServer->send(302, "text/plain", ""); } } diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 7c1073df2..4f347c220 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -478,7 +478,7 @@ const char *wifiPrintState(wl_status_t wifiStatus) //---------------------------------------- void wifiRestart() { - // Restart the AP webserver if we are in that state + // Restart the AP webServer if we are in that state if (systemState == STATE_WIFI_CONFIG) requestChangeState(STATE_WIFI_CONFIG_NOT_STARTED); else @@ -720,7 +720,7 @@ bool wifiStartAP(bool forceAP) } else { - // Start webserver on local WiFi instead of AP + // Start webServer on local WiFi instead of AP // Attempt to connect to local WiFi with increasing timeouts int x = 0; diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index ffd11b3f2..40f809f3c 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -561,7 +561,7 @@ enum OtaState #ifdef COMPILE_AP // Web Config state machine to allow web server access to network layer -enum webserverState +enum WebServerState { WEBSERVER_STATE_OFF = 0, WEBSERVER_STATE_WAIT_FOR_NETWORK, From 1f4e39eaf658dacb6da04d29b1e618fc5197e987 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 20 Dec 2024 16:56:31 -0700 Subject: [PATCH 032/276] More WIP - Removing old code. Getting StateMachine to see startWebServer() --- Firmware/RTK_Everywhere/Network.ino | 5 +- Firmware/RTK_Everywhere/WebServer.ino | 740 ++++++++++++----------- Firmware/RTK_Everywhere/WiFi.ino | 98 +-- Firmware/RTK_Everywhere/menuFirmware.ino | 36 -- Firmware/RTK_Everywhere/settings.h | 2 + 5 files changed, 440 insertions(+), 441 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 95816c038..ab3107112 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1493,14 +1493,15 @@ uint16_t networkGetConsumerTypes() } // Return the count of consumers (TCP, NTRIP Client, etc) that are enabled +// and set networkConsumerTypes bitfield // From this number we can decide if the network (WiFi, ethernet, cellular, etc) needs to be started -// ESP-NOW is an exception and is not considered a network consumer +// ESP-NOW is not considered a network consumer and is blended during wifiConnect() uint8_t networkConsumers() { uint8_t consumerCount = 0; uint16_t consumerId = 0; // Used to debug print who is asking for access - networkConsumerTypes = NETCONSUMER_NONE; + networkConsumerTypes = NETCONSUMER_NONE; // Clear bitfield // Network needed for NTRIP Client if ((inRoverMode() == true && settings.enableNtripClient == true) || online.ntripClient) diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index de4ac071a..88f744179 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -7,11 +7,8 @@ Form.ino #ifdef COMPILE_AP static const char *const webServerStateNames[] = { - "WEBSERVER_STATE_OFF", - "WEBSERVER_STATE_WAIT_FOR_NETWORK", - "WEBSERVER_STATE_NETWORK_CONNECTED", - "WEBSERVER_STATE_STARTED", - "WEBSERVER_STATE_RUNNING", + "WEBSERVER_STATE_OFF", "WEBSERVER_STATE_WAIT_FOR_NETWORK", "WEBSERVER_STATE_NETWORK_CONNECTED", + "WEBSERVER_STATE_STARTED", "WEBSERVER_STATE_RUNNING", }; static const int webServerStateEntries = sizeof(webServerStateNames) / sizeof(webServerStateNames[0]); @@ -207,7 +204,7 @@ static void start_wsserver(void) // https://github.com/espressif/arduino-esp32/blob/master/libraries/WebServer/examples/WebServer/WebServer.ino class CaptiveRequestHandler : public RequestHandler { -public: + public: // https://en.wikipedia.org/wiki/Captive_portal String urls[5] = {"/hotspot-detect.html", "/library/test/success.html", "/generate_204", "/ncsi.txt", "/check_network_status.txt"}; @@ -250,90 +247,293 @@ public: } }; -// State machine to handle the starting/stopping of the web server -void webServerUpdate() +// Start the webServer +bool webServerStart(bool startWiFi = true, int httpPort = 80) { - if (!inMainMenu) + do { - // Walk the state machine - switch (webServerState) - { - default: - systemPrintf("ERROR: Unknown WebConfig state (%d)\r\n", webServerState); - - // Stop the machine - webServerStop(); - break; + ntripClientStop(true); // Do not allocate new wifiClient + for (int serverIndex = 0; serverIndex < NTRIP_SERVER_MAX; serverIndex++) + ntripServerStop(serverIndex, true); // Do not allocate new wifiClient - // Wait for a request from a user - case WEBSERVER_STATE_OFF: - if (webServerRequest == true) - webServerSetState(WEBSERVER_STATE_WAIT_FOR_NETWORK); - break; + // if (startWiFi) + // if (wifiStartAP() == false) + // break; - // Wait for connection to the network - case WEBSERVER_STATE_WAIT_FOR_NETWORK: - // Determine if the request has been canceled while waiting - if (webServerRequest == false) - webServerStop(); + // // Start the multicast DNS server + // if (startWiFi == true) + // networkMulticastDNSSwitch(NETWORK_WIFI); + // else + // networkMulticastDNSSwitch(NETWORK_ETHERNET); - // Wait until the network is connected to the media - else if (networkIsConnected(&webconfigPriority)) - { - if (settings.debugWebServer) - systemPrintln("Web config connected to network"); + // Freed by webServerStop + if (online.psram == true) + incomingSettings = (char *)ps_malloc(AP_CONFIG_SETTING_SIZE); + else + incomingSettings = (char *)malloc(AP_CONFIG_SETTING_SIZE); - webServerSetState(WEBSERVER_STATE_NETWORK_CONNECTED); - } + if (!incomingSettings) + { + systemPrintln("ERROR: Failed to allocate incomingSettings"); break; + } + memset(incomingSettings, 0, AP_CONFIG_SETTING_SIZE); - // Start the web server - case WEBSERVER_STATE_NETWORK_CONNECTED: + // Pre-load settings CSV + // Freed by webServerStop + if (online.psram == true) + settingsCSV = (char *)ps_malloc(AP_CONFIG_SETTING_SIZE); + else + settingsCSV = (char *)malloc(AP_CONFIG_SETTING_SIZE); - // Determine if the network has failed - if (!networkIsConnected(&webconfigPriority)) - webServerStop(); - if (settings.debugWebServer) - systemPrintln("Starting web server"); + if (!settingsCSV) + { + systemPrintln("ERROR: Failed to allocate settingsCSV"); + break; + } + createSettingsString(settingsCSV); - if (web2(false, settings.httpPort) == true) - webServerSetState(WEBSERVER_STATE_STARTED); + // + https://github.com/espressif/arduino-esp32/blob/master/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino + if (settings.enableCaptivePortal == true) + { + dnsserver = new DNSServer; + dnsserver->start(); + } + + webServer = new WebServer(httpPort); + // TODO: webServer = new WebServer(WiFi.localIP(), httpPort); + // TODO: webServer = new WebServer(ETH.localIP(), httpPort); + if (!webServer) + { + systemPrintln("ERROR: Failed to allocate webServer"); break; + } - // Wait for web server to start - case WEBSERVER_STATE_STARTED: - // Determine if the network has failed - if (!networkIsConnected(&webconfigPriority)) - webServerStop(); - if (settings.debugWebServer) - systemPrintln("Web config waiting for web server to start"); + if (settings.enableCaptivePortal == true) + { + webServer->addHandler(new CaptiveRequestHandler()); - //... - webServerSetState(WEBSERVER_STATE_RUNNING); + // TODO: add a handler for /connecttest.txt + } - break; + // * index.html (not gz'd) + // * favicon.ico + + // * /src/bootstrap.bundle.min.js - Needed for popper + // * /src/bootstrap.min.css + // * /src/bootstrap.min.js + // * /src/jquery-3.6.0.min.js + // * /src/main.js (not gz'd) + // * /src/rtk-setup.png + // * /src/style.css + + // * /src/fonts/icomoon.eot + // * /src/fonts/icomoon.svg + // * /src/fonts/icomoon.ttf + // * /src/fonts/icomoon.woof + + // * /listfiles responds with a CSV of files and sizes in root + // * /listMessages responds with a CSV of messages supported by this platform + // * /listMessagesBase responds with a CSV of RTCM Base messages supported by this platform + // * /file allows the download or deletion of a file + + webServer->onNotFound(notFound); + + webServer->on("/", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/html", (const char *)index_html, sizeof(index_html)); }); + + webServer->on("/favicon.ico", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/plain", (const char *)favicon_ico, sizeof(favicon_ico)); }); + + webServer->on("/src/bootstrap.bundle.min.js", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/javascript", (const char *)bootstrap_bundle_min_js, + sizeof(bootstrap_bundle_min_js)); }); + + webServer->on("/src/bootstrap.min.css", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/css", (const char *)bootstrap_min_css, sizeof(bootstrap_min_css)); }); + + webServer->on("/src/bootstrap.min.js", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/javascript", (const char *)bootstrap_min_js, sizeof(bootstrap_min_js)); }); + + webServer->on("/src/jquery-3.6.0.min.js", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/javascript", (const char *)jquery_js, sizeof(jquery_js)); }); + + webServer->on("/src/main.js", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/javascript", (const char *)main_js, sizeof(main_js)); }); + + webServer->on("/src/rtk-setup.png", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + if (productVariant == RTK_EVK) + webServer->send_P(200, "image/png", (const char *)rtkSetup_png, sizeof(rtkSetup_png)); + else + webServer->send_P(200, "image/png", (const char *)rtkSetupWiFi_png, sizeof(rtkSetupWiFi_png)); }); + + // Battery icons + webServer->on("/src/BatteryBlank.png", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "image/png", (const char *)batteryBlank_png, sizeof(batteryBlank_png)); }); + webServer->on("/src/Battery0.png", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "image/png", (const char *)battery0_png, sizeof(battery0_png)); }); + webServer->on("/src/Battery1.png", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "image/png", (const char *)battery1_png, sizeof(battery1_png)); }); + webServer->on("/src/Battery2.png", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "image/png", (const char *)battery2_png, sizeof(battery2_png)); }); + webServer->on("/src/Battery3.png", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "image/png", (const char *)battery3_png, sizeof(battery3_png)); }); + + webServer->on("/src/Battery0_Charging.png", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "image/png", (const char *)battery0_Charging_png, sizeof(battery0_Charging_png)); + }); + webServer->on("/src/Battery1_Charging.png", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "image/png", (const char *)battery1_Charging_png, sizeof(battery1_Charging_png)); + }); + webServer->on("/src/Battery2_Charging.png", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "image/png", (const char *)battery2_Charging_png, sizeof(battery2_Charging_png)); + }); + webServer->on("/src/Battery3_Charging.png", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "image/png", (const char *)battery3_Charging_png, sizeof(battery3_Charging_png)); + }); + + webServer->on("/src/style.css", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/css", (const char *)style_css, sizeof(style_css)); }); + + webServer->on("/src/fonts/icomoon.eot", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/plain", (const char *)icomoon_eot, sizeof(icomoon_eot)); }); + + webServer->on("/src/fonts/icomoon.svg", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/plain", (const char *)icomoon_svg, sizeof(icomoon_svg)); }); + + webServer->on("/src/fonts/icomoon.ttf", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/plain", (const char *)icomoon_ttf, sizeof(icomoon_ttf)); }); + + webServer->on("/src/fonts/icomoon.woof", HTTP_GET, []() + { + webServer->sendHeader("Content-Encoding", "gzip"); + webServer->send_P(200, "text/plain", (const char *)icomoon_woof, sizeof(icomoon_woof)); }); + + // Handler for the /uploadFile form POST + webServer->on( + "/uploadFile", HTTP_POST, []() + { webServer->send(200, "text/plain", ""); }, + handleUpload); // Run handleUpload function when file manager file is uploaded + + // Handler for the /uploadFirmware form POST + webServer->on( + "/uploadFirmware", HTTP_POST, []() + { webServer->send(200, "text/plain", ""); }, handleFirmwareFileUpload); + + // Handler for file manager + webServer->on("/listfiles", HTTP_GET, []() + { + String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); + if (settings.debugWebServer == true) + systemPrintln(logmessage); + String files; + getFileList(files); + webServer->send(200, "text/plain", files); }); + + // Handler for supported messages list + webServer->on("/listMessages", HTTP_GET, []() + { + String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); + if (settings.debugWebServer == true) + systemPrintln(logmessage); + String messages; + createMessageList(messages); + if (settings.debugWebServer == true) + systemPrintln(messages); + webServer->send(200, "text/plain", messages); }); + + // Handler for supported RTCM/Base messages list + webServer->on("/listMessagesBase", HTTP_GET, []() + { + String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); + if (settings.debugWebServer == true) + systemPrintln(logmessage); + String messageList; + createMessageListBase(messageList); + if (settings.debugWebServer == true) + systemPrintln(messageList); + webServer->send(200, "text/plain", messageList); }); + + // Handler for file manager + webServer->on("/file", HTTP_GET, handleFileManager); + + webServer->begin(); + + // Starts task for updating webServer with handleClient + if (task.updateWebServerTaskRunning == false) + xTaskCreate( + updateWebServerTask, + "UpdateWebServer", // Just for humans + updateWebServerTaskStackSize, // Stack Size - needs to be large enough to hold the file manager list + nullptr, // Task input parameter + updateWebServerTaskPriority, + &updateWebServerTaskHandle); // Task handle - // Allow web services - case WEBSERVER_STATE_RUNNING: - // Determine if the network has failed - if (!networkIsConnected(&webconfigPriority)) - webServerStop(); + if (settings.debugWebServer == true) + systemPrintln("Web Server Started"); + reportHeapNow(false); - // TODO how does the system indicate we need to shut down the web server? - if (inWiFiConfigMode() == false) - { - webServerRequest = false; // Tell the network layer we no longer need access - webServerStop(); - } + // Start the web socket server on port 81 using + start_wsserver(); - //... + if (settings.debugWebServer == true) + systemPrintln("Web Socket Server Started"); + reportHeapNow(false); - break; - } - } + return true; + } while (0); + + // Release the resources + webServerStopSockets(); + webServerReleaseResources(); + return false; } + // Stop the web config state machine void webServerStop() { @@ -435,292 +635,6 @@ bool webServerIsRunning() return (false); } -bool web2(bool startWiFi = true, int httpPort = 80) -{ - return(false); -} - -// Start webServer in AP mode -// bool webServerStart(bool startWiFi = true, int httpPort = 80) -// { -// do -// { -// ntripClientStop(true); // Do not allocate new wifiClient -// for (int serverIndex = 0; serverIndex < NTRIP_SERVER_MAX; serverIndex++) -// ntripServerStop(serverIndex, true); // Do not allocate new wifiClient - -// // if (startWiFi) -// // if (wifiStartAP() == false) -// // break; - -// // // Start the multicast DNS server -// // if (startWiFi == true) -// // networkMulticastDNSSwitch(NETWORK_WIFI); -// // else -// // networkMulticastDNSSwitch(NETWORK_ETHERNET); - -// // Freed by webServerStop -// if (online.psram == true) -// incomingSettings = (char *)ps_malloc(AP_CONFIG_SETTING_SIZE); -// else -// incomingSettings = (char *)malloc(AP_CONFIG_SETTING_SIZE); - -// if (!incomingSettings) -// { -// systemPrintln("ERROR: Failed to allocate incomingSettings"); -// break; -// } -// memset(incomingSettings, 0, AP_CONFIG_SETTING_SIZE); - -// // Pre-load settings CSV -// // Freed by webServerStop -// if (online.psram == true) -// settingsCSV = (char *)ps_malloc(AP_CONFIG_SETTING_SIZE); -// else -// settingsCSV = (char *)malloc(AP_CONFIG_SETTING_SIZE); - -// if (!settingsCSV) -// { -// systemPrintln("ERROR: Failed to allocate settingsCSV"); -// break; -// } -// createSettingsString(settingsCSV); - -// // https://github.com/espressif/arduino-esp32/blob/master/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino -// if (settings.enableCaptivePortal == true) -// { -// dnsserver = new DNSServer; -// dnsserver->start(); -// } - -// webServer = new WebServer(httpPort); -// // TODO: webServer = new WebServer(WiFi.localIP(), httpPort); -// // TODO: webServer = new WebServer(ETH.localIP(), httpPort); - -// if (!webServer) -// { -// systemPrintln("ERROR: Failed to allocate webServer"); -// break; -// } - -// if (settings.enableCaptivePortal == true) -// { -// webServer->addHandler(new CaptiveRequestHandler()); - -// // TODO: add a handler for /connecttest.txt -// } - -// // * index.html (not gz'd) -// // * favicon.ico - -// // * /src/bootstrap.bundle.min.js - Needed for popper -// // * /src/bootstrap.min.css -// // * /src/bootstrap.min.js -// // * /src/jquery-3.6.0.min.js -// // * /src/main.js (not gz'd) -// // * /src/rtk-setup.png -// // * /src/style.css - -// // * /src/fonts/icomoon.eot -// // * /src/fonts/icomoon.svg -// // * /src/fonts/icomoon.ttf -// // * /src/fonts/icomoon.woof - -// // * /listfiles responds with a CSV of files and sizes in root -// // * /listMessages responds with a CSV of messages supported by this platform -// // * /listMessagesBase responds with a CSV of RTCM Base messages supported by this platform -// // * /file allows the download or deletion of a file - -// webServer->onNotFound(notFound); - -// webServer->on("/", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/html", (const char *)index_html, sizeof(index_html)); }); - -// webServer->on("/favicon.ico", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/plain", (const char *)favicon_ico, sizeof(favicon_ico)); }); - -// webServer->on("/src/bootstrap.bundle.min.js", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/javascript", (const char *)bootstrap_bundle_min_js, -// sizeof(bootstrap_bundle_min_js)); }); - -// webServer->on("/src/bootstrap.min.css", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/css", (const char *)bootstrap_min_css, sizeof(bootstrap_min_css)); }); - -// webServer->on("/src/bootstrap.min.js", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/javascript", (const char *)bootstrap_min_js, sizeof(bootstrap_min_js)); }); - -// webServer->on("/src/jquery-3.6.0.min.js", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/javascript", (const char *)jquery_js, sizeof(jquery_js)); }); - -// webServer->on("/src/main.js", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/javascript", (const char *)main_js, sizeof(main_js)); }); - -// webServer->on("/src/rtk-setup.png", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// if (productVariant == RTK_EVK) -// webServer->send_P(200, "image/png", (const char *)rtkSetup_png, sizeof(rtkSetup_png)); -// else -// webServer->send_P(200, "image/png", (const char *)rtkSetupWiFi_png, sizeof(rtkSetupWiFi_png)); }); - -// // Battery icons -// webServer->on("/src/BatteryBlank.png", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "image/png", (const char *)batteryBlank_png, sizeof(batteryBlank_png)); }); -// webServer->on("/src/Battery0.png", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "image/png", (const char *)battery0_png, sizeof(battery0_png)); }); -// webServer->on("/src/Battery1.png", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "image/png", (const char *)battery1_png, sizeof(battery1_png)); }); -// webServer->on("/src/Battery2.png", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "image/png", (const char *)battery2_png, sizeof(battery2_png)); }); -// webServer->on("/src/Battery3.png", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "image/png", (const char *)battery3_png, sizeof(battery3_png)); }); - -// webServer->on("/src/Battery0_Charging.png", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "image/png", (const char *)battery0_Charging_png, sizeof(battery0_Charging_png)); }); -// webServer->on("/src/Battery1_Charging.png", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "image/png", (const char *)battery1_Charging_png, sizeof(battery1_Charging_png)); }); -// webServer->on("/src/Battery2_Charging.png", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "image/png", (const char *)battery2_Charging_png, sizeof(battery2_Charging_png)); }); -// webServer->on("/src/Battery3_Charging.png", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "image/png", (const char *)battery3_Charging_png, sizeof(battery3_Charging_png)); }); - -// webServer->on("/src/style.css", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/css", (const char *)style_css, sizeof(style_css)); }); - -// webServer->on("/src/fonts/icomoon.eot", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/plain", (const char *)icomoon_eot, sizeof(icomoon_eot)); }); - -// webServer->on("/src/fonts/icomoon.svg", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/plain", (const char *)icomoon_svg, sizeof(icomoon_svg)); }); - -// webServer->on("/src/fonts/icomoon.ttf", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/plain", (const char *)icomoon_ttf, sizeof(icomoon_ttf)); }); - -// webServer->on("/src/fonts/icomoon.woof", HTTP_GET, []() -// { -// webServer->sendHeader("Content-Encoding", "gzip"); -// webServer->send_P(200, "text/plain", (const char *)icomoon_woof, sizeof(icomoon_woof)); }); - -// // Handler for the /uploadFile form POST -// webServer->on( -// "/uploadFile", HTTP_POST, []() -// { webServer->send(200, "text/plain", ""); }, -// handleUpload); // Run handleUpload function when file manager file is uploaded - -// // Handler for the /uploadFirmware form POST -// webServer->on( -// "/uploadFirmware", HTTP_POST, []() -// { webServer->send(200, "text/plain", ""); }, handleFirmwareFileUpload); - -// // Handler for file manager -// webServer->on("/listfiles", HTTP_GET, []() -// { -// String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); -// if (settings.debugWebServer == true) -// systemPrintln(logmessage); -// String files; -// getFileList(files); -// webServer->send(200, "text/plain", files); }); - -// // Handler for supported messages list -// webServer->on("/listMessages", HTTP_GET, []() -// { -// String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); -// if (settings.debugWebServer == true) -// systemPrintln(logmessage); -// String messages; -// createMessageList(messages); -// if (settings.debugWebServer == true) -// systemPrintln(messages); -// webServer->send(200, "text/plain", messages); }); - -// // Handler for supported RTCM/Base messages list -// webServer->on("/listMessagesBase", HTTP_GET, []() -// { -// String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); -// if (settings.debugWebServer == true) -// systemPrintln(logmessage); -// String messageList; -// createMessageListBase(messageList); -// if (settings.debugWebServer == true) -// systemPrintln(messageList); -// webServer->send(200, "text/plain", messageList); }); - -// // Handler for file manager -// webServer->on("/file", HTTP_GET, handleFileManager); - -// webServer->begin(); - -// // Starts task for updating webServer with handleClient -// if (task.updateWebServerTaskRunning == false) -// xTaskCreate( -// updateWebServerTask, -// "UpdateWebServer", // Just for humans -// updateWebServerTaskStackSize, // Stack Size - needs to be large enough to hold the file manager list -// nullptr, // Task input parameter -// updateWebServerTaskPriority, -// &updateWebServerTaskHandle); // Task handle - -// if (settings.debugWebServer == true) -// systemPrintln("Web Server Started"); -// reportHeapNow(false); - -// // Start the web socket server on port 81 using -// start_wsserver(); - -// if (settings.debugWebServer == true) -// systemPrintln("Web Socket Server Started"); -// reportHeapNow(false); - -// return true; -// } while (0); - -// // Release the resources -// webServerStopSockets(); -// webServerReleaseResources(); -// return false; -// } - void updateWebServerTask(void *e) { // Start notification @@ -752,6 +666,38 @@ void updateWebServerTask(void *e) vTaskDelete(updateWebServerTaskHandle); } +void stopWebServer() +{ + if (task.updateWebServerTaskRunning) + task.updateWebServerTaskStopRequest = true; + + if (webServer != nullptr) + { + webServer->close(); + free(webServer); + webServer = nullptr; + } + + // Stop the multicast DNS server + networkMulticastDNSStop(); + + if (settingsCSV != nullptr) + { + free(settingsCSV); + settingsCSV = nullptr; + } + + if (incomingSettings != nullptr) + { + free(incomingSettings); + incomingSettings = nullptr; + } + + do + delay(10); + while (task.updateWebServerTaskRunning); +} + void webServerReleaseResources() { if (task.updateWebServerTaskRunning) @@ -785,6 +731,90 @@ void webServerReleaseResources() } } + +// State machine to handle the starting/stopping of the web server +void webServerUpdate() +{ + if (!inMainMenu) + { + // Walk the state machine + switch (webServerState) + { + default: + systemPrintf("ERROR: Unknown WebConfig state (%d)\r\n", webServerState); + + // Stop the machine + webServerStop(); + break; + + // Wait for a request from a user + case WEBSERVER_STATE_OFF: + if (webServerRequest == true) + webServerSetState(WEBSERVER_STATE_WAIT_FOR_NETWORK); + break; + + // Wait for connection to the network + case WEBSERVER_STATE_WAIT_FOR_NETWORK: + // Determine if the request has been canceled while waiting + if (webServerRequest == false) + webServerStop(); + + // Wait until the network is connected to the media + else if (networkIsConnected(&webconfigPriority)) + { + if (settings.debugWebServer) + systemPrintln("Web config connected to network"); + + webServerSetState(WEBSERVER_STATE_NETWORK_CONNECTED); + } + break; + + // Start the web server + case WEBSERVER_STATE_NETWORK_CONNECTED: { + // Determine if the network has failed + if (!networkIsConnected(&webconfigPriority)) + webServerStop(); + if (settings.debugWebServer) + systemPrintln("Starting web server"); + + if (webServerStart(false, settings.httpPort) == true) + webServerSetState(WEBSERVER_STATE_STARTED); + } + break; + + // Wait for web server to start + case WEBSERVER_STATE_STARTED: + // Determine if the network has failed + if (!networkIsConnected(&webconfigPriority)) + webServerStop(); + if (settings.debugWebServer) + systemPrintln("Web config waiting for web server to start"); + + //... + webServerSetState(WEBSERVER_STATE_RUNNING); + + break; + + // Allow web services + case WEBSERVER_STATE_RUNNING: + // Determine if the network has failed + if (!networkIsConnected(&webconfigPriority)) + webServerStop(); + + // TODO how does the system indicate we need to shut down the web server? + if (inWiFiConfigMode() == false) + { + webServerRequest = false; // Tell the network layer we no longer need access + webServerStop(); + } + + //... + + break; + } + } +} + void notFound() { String logmessage = "notFound: Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 4f347c220..0a72ff72e 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -173,7 +173,7 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) { systemPrintln("Starting WiFi AP+Station"); wifiMode = WIFI_AP_STA; - wifiInterface = WIFI_IF_AP_STA; + wifiInterface = WIFI_IF_AP; // There is no WIFI_IF_AP_STA } displayWiFiConnect(); @@ -530,18 +530,18 @@ bool wifiForceStart() startWiFiStation = true; // The consumers need both - else if (networkGetConsumerTypes() & ((1 << NETCONSUMER_AP) | (1 << NETCONSUMER_STA))) + else if (networkGetConsumerTypes() & ((1 << NETCONSUMER_WIFI_AP) | (1 << NETCONSUMER_WIFI_STA))) { startWiFiStation = true; startWiFiAP = true; } // The consumers need station - else if (networkGetConsumerTypes() & (1 << NETCONSUMER_STA)) + else if (networkGetConsumerTypes() & (1 << NETCONSUMER_WIFI_STA)) startWiFiStation = true; // The consumers need AP - else if (networkGetConsumerTypes() & (1 << NETCONSUMER_AP)) + else if (networkGetConsumerTypes() & (1 << NETCONSUMER_WIFI_AP)) startWiFiAP = true; // Start WiFi @@ -698,50 +698,52 @@ bool wifiStartAP() //---------------------------------------- bool wifiStartAP(bool forceAP) { - if (settings.wifiConfigOverAP == true || forceAP) - { - // Stop any current WiFi activity - WIFI_STOP(); - - // Start in AP mode - WiFi.mode(WIFI_AP); - - // Before starting AP mode, be sure we have default WiFi protocols enabled. - // esp_wifi_set_protocol requires WiFi to be started - esp_err_t response = - esp_wifi_set_protocol(WIFI_IF_AP, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N); - if (response != ESP_OK) - systemPrintf("wifiStartAP: Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); - else - { - if (settings.debugWifiState == true) - systemPrintln("WiFi protocols set"); - } - } - else - { - // Start webServer on local WiFi instead of AP - - // Attempt to connect to local WiFi with increasing timeouts - int x = 0; - const int maxTries = 2; - for (; x < maxTries; x++) - { - if (wifiConnect(settings.wifiConnectTimeoutMs) == true) // Attempt to connect to any SSID on settings list - { - wifiDisplayState(); - break; - } - } - if (x == maxTries) - { - displayNoWiFi(2000); - return (wifiStartAP(true)); // Because there is no local WiFi available, force AP mode so user can still get - // access/configure it - } - } - - return (true); + //TODO delete + return (false); + // if (settings.wifiConfigOverAP == true || forceAP) + // { + // // Stop any current WiFi activity + // WIFI_STOP(); + + // // Start in AP mode + // WiFi.mode(WIFI_AP); + + // // Before starting AP mode, be sure we have default WiFi protocols enabled. + // // esp_wifi_set_protocol requires WiFi to be started + // esp_err_t response = + // esp_wifi_set_protocol(WIFI_IF_AP, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N); + // if (response != ESP_OK) + // systemPrintf("wifiStartAP: Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); + // else + // { + // if (settings.debugWifiState == true) + // systemPrintln("WiFi protocols set"); + // } + // } + // else + // { + // // Start webServer on local WiFi instead of AP + + // // Attempt to connect to local WiFi with increasing timeouts + // int x = 0; + // const int maxTries = 2; + // for (; x < maxTries; x++) + // { + // if (wifiConnect(settings.wifiConnectTimeoutMs) == true) // Attempt to connect to any SSID on settings list + // { + // wifiDisplayState(); + // break; + // } + // } + // if (x == maxTries) + // { + // displayNoWiFi(2000); + // return (wifiStartAP(true)); // Because there is no local WiFi available, force AP mode so user can still get + // // access/configure it + // } + // } + + // return (true); } #endif // COMPILE_WIFI diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index 5b9872613..bfff93793 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -516,42 +516,6 @@ void otaUpdateFirmware() #endif // COMPILE_NETWORK } -// Start WiFi outside of the network layer and perform the over-the-air update -void otaForcedUpdate() -{ -#ifdef COMPILE_NETWORK - bool wasInAPmode = false; - - if (!networkIsOnline()) - { - if (wifiNetworkCount() == 0) - systemPrintln("Error: Please enter at least one SSID before updating firmware"); - else - systemPrintln("Error: Network not available!"); - } - else - { - // Determine if WiFi is running - bool wifiRunning = WiFi.STA.started() || WiFi.STA.linkUp() || WiFi.STA.connected(); - - if ((networkIsOnline) || (wifiConnect(settings.wifiConnectTimeoutMs, true, &wasInAPmode) == - true)) // Use WIFI_AP_STA if already in WIFI_AP mode - otaUpdateFirmware(); - - if (systemState != STATE_WIFI_CONFIG) - { - // WIFI_STOP() turns off the entire radio including the webserver. We need to turn off Station mode - // only. For now, unit exits AP mode via reset so if we are in AP config mode, leave WiFi Station - // running. - - // If WiFi was originally off, turn it off again - if (wifiRunning == false) - WIFI_STOP(); - } - } -#endif // COMPILE_NETWORK -} - // Called while the OTA Pull update is happening void otaPullCallback(int bytesWritten, int totalLength) { diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 40f809f3c..b967f78d8 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -1050,6 +1050,7 @@ struct Settings #endif // COMPILE_LG290P bool debugSettings = false; + bool enableNtripCaster = false; // Add new settings to appropriate group above or create new group // Then also add to the same group in rtkSettingsEntries below @@ -1658,6 +1659,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = #endif // COMPILE_LG290P { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugSettings, "debugSettings", }, + { 1, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enableNtripCaster, "enableNtripCaster", }, // Add new settings to appropriate group above or create new group // Then also add to the same group in settings above From f58d875e24343d86c565f795f0125a56bb985579 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 20 Dec 2024 16:56:50 -0700 Subject: [PATCH 033/276] Remove unused functions. --- Firmware/RTK_Everywhere/WiFi.ino | 65 -------------------------------- 1 file changed, 65 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 0a72ff72e..d2ae92d90 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -680,70 +680,5 @@ void wifiStop(NetIndex_t index, uintptr_t parameter, bool debug) networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); } -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// WiFi Config Support Routines - compiled out -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - -//---------------------------------------- -// Start the WiFi access point -//---------------------------------------- -bool wifiStartAP() -{ - return (wifiStartAP(false)); // Don't force AP mode -} - -//---------------------------------------- -// Start the access point for user to connect to and configure device -// We can also start as a WiFi station and attempt to connect to local WiFi for config -//---------------------------------------- -bool wifiStartAP(bool forceAP) -{ - //TODO delete - return (false); - // if (settings.wifiConfigOverAP == true || forceAP) - // { - // // Stop any current WiFi activity - // WIFI_STOP(); - - // // Start in AP mode - // WiFi.mode(WIFI_AP); - - // // Before starting AP mode, be sure we have default WiFi protocols enabled. - // // esp_wifi_set_protocol requires WiFi to be started - // esp_err_t response = - // esp_wifi_set_protocol(WIFI_IF_AP, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N); - // if (response != ESP_OK) - // systemPrintf("wifiStartAP: Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); - // else - // { - // if (settings.debugWifiState == true) - // systemPrintln("WiFi protocols set"); - // } - // } - // else - // { - // // Start webServer on local WiFi instead of AP - - // // Attempt to connect to local WiFi with increasing timeouts - // int x = 0; - // const int maxTries = 2; - // for (; x < maxTries; x++) - // { - // if (wifiConnect(settings.wifiConnectTimeoutMs) == true) // Attempt to connect to any SSID on settings list - // { - // wifiDisplayState(); - // break; - // } - // } - // if (x == maxTries) - // { - // displayNoWiFi(2000); - // return (wifiStartAP(true)); // Because there is no local WiFi available, force AP mode so user can still get - // // access/configure it - // } - // } - - // return (true); -} #endif // COMPILE_WIFI From 2753918f0481fcbe69e2d9f66b3e6e3975ff8357 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 23 Dec 2024 11:38:19 +0000 Subject: [PATCH 034/276] Facet v2 - use present.button_powerLow not present.button_mode --- Firmware/RTK_Everywhere/Begin.ino | 2 -- 1 file changed, 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Begin.ino b/Firmware/RTK_Everywhere/Begin.ino index 755ee031c..086e33551 100644 --- a/Firmware/RTK_Everywhere/Begin.ino +++ b/Firmware/RTK_Everywhere/Begin.ino @@ -449,7 +449,6 @@ void beginBoard() present.display_i2c0 = true; present.display_type = DISPLAY_64x48; present.i2c0BusSpeed_400 = true; - present.button_mode = true; present.peripheralPowerControl = true; present.button_powerLow = true; // Button is pressed when low present.charger_mcp73833 = true; @@ -530,7 +529,6 @@ void beginBoard() present.display_i2c0 = true; present.display_type = DISPLAY_64x48; present.i2c0BusSpeed_400 = true; - present.button_mode = true; present.peripheralPowerControl = true; present.button_powerLow = true; // Button is pressed when low present.charger_mcp73833 = true; From 71e10b2cbe79fa6722a2de910b730b9bf9a84028 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 09:16:03 -0700 Subject: [PATCH 035/276] Fix upper limit text and typo Issue from RTK Firmware: https://github.com/sparkfun/SparkFun_RTK_Firmware/pull/783 --- Firmware/RTK_Everywhere/AP-Config/index.html | 2 +- Firmware/RTK_Everywhere/menuBase.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/index.html b/Firmware/RTK_Everywhere/AP-Config/index.html index e2ca23f02..5cd866cbf 100644 --- a/Firmware/RTK_Everywhere/AP-Config/index.html +++ b/Firmware/RTK_Everywhere/AP-Config/index.html @@ -547,7 +547,7 @@ + title="If the precise location of a base station is not known it may be obtained by ‘surveying’ the location. The base is fixed in one place and takes approximately 60 seconds worth of readings to obtain a best fit location based on the measurements. This method achieves ~30cm accurate position but can vary. Increasing the Minimum Observation Time and/or Required Mean Deviation will increase accuracy but only to a point. Better accuracy is achieved with long-term logging and post processing. Default: 60s and 5.0m. Limits: 60 to 600s, 1.0 to 5.0m.">
diff --git a/Firmware/RTK_Everywhere/menuBase.ino b/Firmware/RTK_Everywhere/menuBase.ino index cab608c01..6407a9048 100644 --- a/Firmware/RTK_Everywhere/menuBase.ino +++ b/Firmware/RTK_Everywhere/menuBase.ino @@ -247,7 +247,7 @@ void menuBase() else if (settings.fixedBase == false && incoming == 2 && (!present.gnss_mosaicX5)) { // Arbitrary 10 minute limit - getNewSetting("Enter the number of seconds for survey-in obseration time", 60, 60 * 10, + getNewSetting("Enter the number of seconds for survey-in observation time", 60, 60 * 10, &settings.observationSeconds); } else if (settings.fixedBase == false && incoming == 3 && From 313bcc14e91d3ea4296e49fd479477cd07aac03c Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 09:37:29 -0700 Subject: [PATCH 036/276] Rename TCP_CLIENT_STATE_WAIT_FOR_NETWORK --- Firmware/RTK_Everywhere/TcpClient.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/TcpClient.ino b/Firmware/RTK_Everywhere/TcpClient.ino index 6b895f848..5fbdce19c 100644 --- a/Firmware/RTK_Everywhere/TcpClient.ino +++ b/Firmware/RTK_Everywhere/TcpClient.ino @@ -128,14 +128,14 @@ TcpClient.ino enum tcpClientStates { TCP_CLIENT_STATE_OFF = 0, - TCP_CLIENT_STATE_NETWORK_STARTED, + TCP_CLIENT_STATE_WAIT_FOR_NETWORK, TCP_CLIENT_STATE_CLIENT_STARTING, TCP_CLIENT_STATE_CONNECTED, // Insert new states here TCP_CLIENT_STATE_MAX // Last entry in the state list }; -const char *const tcpClientStateName[] = {"TCP_CLIENT_STATE_OFF", "TCP_CLIENT_STATE_NETWORK_STARTED", +const char *const tcpClientStateName[] = {"TCP_CLIENT_STATE_OFF", "TCP_CLIENT_STATE_WAIT_FOR_NETWORK", "TCP_CLIENT_STATE_CLIENT_STARTING", "TCP_CLIENT_STATE_CONNECTED"}; const int tcpClientStateNameEntries = sizeof(tcpClientStateName) / sizeof(tcpClientStateName[0]); @@ -383,7 +383,7 @@ void tcpClientUpdate() | tcpClientStop | settings.enableTcpClient | | | V - +<----------TCP_CLIENT_STATE_NETWORK_STARTED + +<----------TCP_CLIENT_STATE_WAIT_FOR_NETWORK ^ | | | networkUserConnected | | @@ -410,12 +410,12 @@ void tcpClientUpdate() { timer = 0; tcpClientPriority = NETWORK_OFFLINE; - tcpClientSetState(TCP_CLIENT_STATE_NETWORK_STARTED); + tcpClientSetState(TCP_CLIENT_STATE_WAIT_FOR_NETWORK); } break; // Wait until the network is connected - case TCP_CLIENT_STATE_NETWORK_STARTED: + case TCP_CLIENT_STATE_WAIT_FOR_NETWORK: // Determine if the TCP client was turned off if (NEQ_RTK_MODE(tcpClientMode) || !settings.enableTcpClient) tcpClientStop(); From ef5382dae697d99f6f695e83a56a945457de7952 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 09:37:50 -0700 Subject: [PATCH 037/276] Rename TCP_SERVER_STATE_WAIT_FOR_NETWORK --- Firmware/RTK_Everywhere/TcpServer.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index 80cbbe931..747db7f0e 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -44,7 +44,7 @@ tcpServer.ino enum tcpServerStates { TCP_SERVER_STATE_OFF = 0, - TCP_SERVER_STATE_NETWORK_STARTED, + TCP_SERVER_STATE_WAIT_FOR_NETWORK, TCP_SERVER_STATE_RUNNING, // Insert new states here TCP_SERVER_STATE_MAX // Last entry in the state list @@ -52,7 +52,7 @@ enum tcpServerStates const char *const tcpServerStateName[] = { "TCP_SERVER_STATE_OFF", - "TCP_SERVER_STATE_NETWORK_STARTED", + "TCP_SERVER_STATE_WAIT_FOR_NETWORK", "TCP_SERVER_STATE_RUNNING", }; @@ -338,7 +338,7 @@ void tcpServerUpdate() | tcpServerStop | settings.enableTcpServer | | | V - +<----------TCP_SERVER_STATE_NETWORK_STARTED + +<----------TCP_SERVER_STATE_WAIT_FOR_NETWORK ^ | | | networkUserConnected | | @@ -364,12 +364,12 @@ void tcpServerUpdate() if (settings.debugTcpServer && (!inMainMenu)) systemPrintln("TCP server start"); tcpServerPriority = NETWORK_OFFLINE; - tcpServerSetState(TCP_SERVER_STATE_NETWORK_STARTED); + tcpServerSetState(TCP_SERVER_STATE_WAIT_FOR_NETWORK); } break; // Wait until the network is connected - case TCP_SERVER_STATE_NETWORK_STARTED: + case TCP_SERVER_STATE_WAIT_FOR_NETWORK: // Determine if the TCP server was turned off if (NEQ_RTK_MODE(tcpServerMode) || !settings.enableTcpServer) tcpServerStop(); From dce319528d827154258eb31b9f72ad221659cb06 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 09:38:04 -0700 Subject: [PATCH 038/276] Rename UDP_SERVER_STATE_WAIT_FOR_NETWORK --- Firmware/RTK_Everywhere/UdpServer.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/UdpServer.ino b/Firmware/RTK_Everywhere/UdpServer.ino index 8272bcba3..50a248e89 100644 --- a/Firmware/RTK_Everywhere/UdpServer.ino +++ b/Firmware/RTK_Everywhere/UdpServer.ino @@ -69,7 +69,7 @@ UdpServer.ino enum udpServerStates { UDP_SERVER_STATE_OFF = 0, - UDP_SERVER_STATE_NETWORK_STARTED, + UDP_SERVER_STATE_WAIT_FOR_NETWORK, UDP_SERVER_STATE_RUNNING, // Insert new states here UDP_SERVER_STATE_MAX // Last entry in the state list @@ -77,7 +77,7 @@ enum udpServerStates const char *const udpServerStateName[] = { "UDP_SERVER_STATE_OFF", - "UDP_SERVER_STATE_NETWORK_STARTED", + "UDP_SERVER_STATE_WAIT_FOR_NETWORK", "UDP_SERVER_STATE_RUNNING", }; @@ -297,7 +297,7 @@ void udpServerUpdate() | udpServerStop | settings.enableUdpServer | | | V - +<---------UDP_SERVER_STATE_NETWORK_STARTED + +<---------UDP_SERVER_STATE_WAIT_FOR_NETWORK ^ | | | networkUserConnected | | @@ -318,12 +318,12 @@ void udpServerUpdate() if (settings.debugUdpServer && (!inMainMenu)) systemPrintln("UDP server starting the network"); udpServerPriority = NETWORK_OFFLINE; - udpServerSetState(UDP_SERVER_STATE_NETWORK_STARTED); + udpServerSetState(UDP_SERVER_STATE_WAIT_FOR_NETWORK); } break; // Wait until the network is connected - case UDP_SERVER_STATE_NETWORK_STARTED: + case UDP_SERVER_STATE_WAIT_FOR_NETWORK: // Determine if the UDP server was turned off if (NEQ_RTK_MODE(udpServerMode) || !settings.enableUdpServer) udpServerStop(); From c7f90b81bd961a9d711eeb2041400b915901729f Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 09:43:23 -0700 Subject: [PATCH 039/276] Rename MQTT_CLIENT_WAIT_FOR_NETWORK --- Firmware/RTK_Everywhere/MQTT_Client.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/MQTT_Client.ino b/Firmware/RTK_Everywhere/MQTT_Client.ino index 64fc75483..ca9094f61 100644 --- a/Firmware/RTK_Everywhere/MQTT_Client.ino +++ b/Firmware/RTK_Everywhere/MQTT_Client.ino @@ -96,7 +96,7 @@ enum MQTTClientState { MQTT_CLIENT_OFF = 0, // Using Bluetooth or NTRIP server MQTT_CLIENT_ON, // WIFI_STATE_START state - MQTT_CLIENT_NETWORK_STARTED, // Connecting to WiFi access point or Ethernet + MQTT_CLIENT_WAIT_FOR_NETWORK, // Connecting to WiFi access point or Ethernet MQTT_CLIENT_CONNECTING_2_SERVER, // Connecting to the MQTT server MQTT_CLIENT_SERVICES_CONNECTED, // Connected to the MQTT services // Insert new states here @@ -106,7 +106,7 @@ enum MQTTClientState const char *const mqttClientStateName[] = { "MQTT_CLIENT_OFF", "MQTT_CLIENT_ON", - "MQTT_CLIENT_NETWORK_STARTED", + "MQTT_CLIENT_WAIT_FOR_NETWORK", "MQTT_CLIENT_CONNECTING_2_SERVER", "MQTT_CLIENT_SERVICES_CONNECTED", }; @@ -220,7 +220,7 @@ void mqttClientPrintStateSummary() break; case MQTT_CLIENT_ON: - case MQTT_CLIENT_NETWORK_STARTED: + case MQTT_CLIENT_WAIT_FOR_NETWORK: systemPrint("Disconnected"); break; @@ -716,13 +716,13 @@ void mqttClientUpdate() if ((millis() - mqttClientTimer) > mqttClientConnectionAttemptTimeout) { mqttClientPriority = NETWORK_OFFLINE; - mqttClientSetState(MQTT_CLIENT_NETWORK_STARTED); + mqttClientSetState(MQTT_CLIENT_WAIT_FOR_NETWORK); } break; } // Wait for a network media connection - case MQTT_CLIENT_NETWORK_STARTED: { + case MQTT_CLIENT_WAIT_FOR_NETWORK: { // Determine if MQTT was turned off if (NEQ_RTK_MODE(mqttClientMode) || !enableMqttClient) mqttClientStop(true); From e0945aa15398bf8f58d233a565ecc06669986185 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 09:44:18 -0700 Subject: [PATCH 040/276] Rename WAIT_FOR_NETWORK --- Firmware/RTK_Everywhere/NtripClient.ino | 16 +++++++++------- Firmware/RTK_Everywhere/NtripServer.ino | 14 +++++++------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Firmware/RTK_Everywhere/NtripClient.ino b/Firmware/RTK_Everywhere/NtripClient.ino index 652945d90..78f2d2dae 100644 --- a/Firmware/RTK_Everywhere/NtripClient.ino +++ b/Firmware/RTK_Everywhere/NtripClient.ino @@ -83,7 +83,7 @@ NtripClient.ino NTRIP Client States: NTRIP_CLIENT_OFF: Network off or using NTRIP server NTRIP_CLIENT_ON: WIFI_STATE_START state - NTRIP_CLIENT_NETWORK_STARTED: Connecting to the network + NTRIP_CLIENT_WAIT_FOR_NETWORK: Connecting to the network NTRIP_CLIENT_NETWORK_CONNECTED: Connected to the network NTRIP_CLIENT_CONNECTING: Attempting a connection to the NTRIP caster NTRIP_CLIENT_WAIT_RESPONSE: Wait for a response from the NTRIP caster @@ -97,7 +97,7 @@ NtripClient.ino | | | | ntripClientRestart() v Fail | - NTRIP_CLIENT_NETWORK_STARTED ------->+ + NTRIP_CLIENT_WAIT_FOR_NETWORK ------->+ | ^ | | v | @@ -153,7 +153,7 @@ enum NTRIPClientState { NTRIP_CLIENT_OFF = 0, // Using Bluetooth or NTRIP server NTRIP_CLIENT_ON, // WIFI_STATE_START state - NTRIP_CLIENT_NETWORK_STARTED, // Connecting to WiFi access point or Ethernet + NTRIP_CLIENT_WAIT_FOR_NETWORK, // Connecting to WiFi access point or Ethernet NTRIP_CLIENT_NETWORK_CONNECTED, // Connected to an access point or Ethernet NTRIP_CLIENT_CONNECTING, // Attempting a connection to the NTRIP caster NTRIP_CLIENT_WAIT_RESPONSE, // Wait for a response from the NTRIP caster @@ -164,7 +164,7 @@ enum NTRIPClientState const char *const ntripClientStateName[] = {"NTRIP_CLIENT_OFF", "NTRIP_CLIENT_ON", - "NTRIP_CLIENT_NETWORK_STARTED", + "NTRIP_CLIENT_WAIT_FOR_NETWORK", "NTRIP_CLIENT_NETWORK_CONNECTED", "NTRIP_CLIENT_CONNECTING", "NTRIP_CLIENT_WAIT_RESPONSE", @@ -357,7 +357,7 @@ void ntripClientPrintStateSummary() systemPrint("Disconnected"); break; case NTRIP_CLIENT_ON: - case NTRIP_CLIENT_NETWORK_STARTED: + case NTRIP_CLIENT_WAIT_FOR_NETWORK: case NTRIP_CLIENT_NETWORK_CONNECTED: case NTRIP_CLIENT_CONNECTING: case NTRIP_CLIENT_WAIT_RESPONSE: @@ -556,11 +556,11 @@ void ntripClientUpdate() // Start the network case NTRIP_CLIENT_ON: ntripClientPriority = NETWORK_OFFLINE; - ntripClientSetState(NTRIP_CLIENT_NETWORK_STARTED); + ntripClientSetState(NTRIP_CLIENT_WAIT_FOR_NETWORK); break; // Wait for a network media connection - case NTRIP_CLIENT_NETWORK_STARTED: + case NTRIP_CLIENT_WAIT_FOR_NETWORK: // Determine if the NTRIP client was turned off if (ntripClientForcedShutdown || NEQ_RTK_MODE(ntripClientMode) || !settings.enableNtripClient) ntripClientStop(true); @@ -592,6 +592,8 @@ void ntripClientUpdate() // Failed to connect to to the network, attempt to restart the network ntripClientStop(true); // Was ntripClientRestart(); - #StopVsRestart + + // If GGA transmission is enabled, wait for GNSS lock before connecting to NTRIP Caster // If GGA transmission is not enabled, start connecting to NTRIP Caster else if ((settings.ntripClient_TransmitGGA == false) || (gnss->isFixed() == true)) diff --git a/Firmware/RTK_Everywhere/NtripServer.ino b/Firmware/RTK_Everywhere/NtripServer.ino index 7eb7d9d35..197dcadd7 100644 --- a/Firmware/RTK_Everywhere/NtripServer.ino +++ b/Firmware/RTK_Everywhere/NtripServer.ino @@ -83,7 +83,7 @@ NtripServer.ino NTRIP Server States: NTRIP_SERVER_OFF: Network off or using NTRIP Client NTRIP_SERVER_ON: WIFI_STATE_START state - NTRIP_SERVER_NETWORK_STARTED: Connecting to the network + NTRIP_SERVER_WAIT_FOR_NETWORK: Connecting to the network NTRIP_SERVER_NETWORK_CONNECTED: Connected to the network NTRIP_SERVER_WAIT_GNSS_DATA: Waiting for correction data from GNSS NTRIP_SERVER_CONNECTING: Attempting a connection to the NTRIP caster @@ -98,7 +98,7 @@ NtripServer.ino | | | | | | ntripServerRestart() | v Fail | - | NTRIP_SERVER_NETWORK_STARTED ------------->+ + | NTRIP_SERVER_WAIT_FOR_NETWORK ------------->+ | | ^ | | | | v Fail | @@ -146,7 +146,7 @@ enum NTRIPServerState { NTRIP_SERVER_OFF = 0, // Using Bluetooth or NTRIP client NTRIP_SERVER_ON, // WIFI_STATE_START state - NTRIP_SERVER_NETWORK_STARTED, // Connecting to WiFi access point + NTRIP_SERVER_WAIT_FOR_NETWORK, // Connecting to WiFi access point NTRIP_SERVER_NETWORK_CONNECTED, // WiFi connected to an access point NTRIP_SERVER_WAIT_GNSS_DATA, // Waiting for correction data from GNSS NTRIP_SERVER_CONNECTING, // Attempting a connection to the NTRIP caster @@ -158,7 +158,7 @@ enum NTRIPServerState const char *const ntripServerStateName[] = {"NTRIP_SERVER_OFF", "NTRIP_SERVER_ON", - "NTRIP_SERVER_NETWORK_STARTED", + "NTRIP_SERVER_WAIT_FOR_NETWORK", "NTRIP_SERVER_NETWORK_CONNECTED", "NTRIP_SERVER_WAIT_GNSS_DATA", "NTRIP_SERVER_CONNECTING", @@ -293,7 +293,7 @@ void ntripServerPrintStateSummary(int serverIndex) systemPrint("Disconnected"); break; case NTRIP_SERVER_ON: - case NTRIP_SERVER_NETWORK_STARTED: + case NTRIP_SERVER_WAIT_FOR_NETWORK: case NTRIP_SERVER_NETWORK_CONNECTED: case NTRIP_SERVER_WAIT_GNSS_DATA: case NTRIP_SERVER_CONNECTING: @@ -593,11 +593,11 @@ void ntripServerUpdate(int serverIndex) // Start the network case NTRIP_SERVER_ON: ntripServerPriority = NETWORK_OFFLINE; - ntripServerSetState(ntripServer, NTRIP_SERVER_NETWORK_STARTED); + ntripServerSetState(ntripServer, NTRIP_SERVER_WAIT_FOR_NETWORK); break; // Wait for a network media connection - case NTRIP_SERVER_NETWORK_STARTED: + case NTRIP_SERVER_WAIT_FOR_NETWORK: // Determine if the NTRIP server was turned off if (NEQ_RTK_MODE(ntripServerMode) || (settings.enableNtripServer == false) || (settings.ntripServer_CasterHost[serverIndex][0] == 0) || From 3e2ec978134906b5de5ccd34dbe5c9d2178d21b1 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 11:10:27 -0700 Subject: [PATCH 041/276] Alphabetize online bools --- Firmware/RTK_Everywhere/settings.h | 48 ++++++++++++++---------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index b967f78d8..c424d8639 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -175,7 +175,6 @@ typedef struct uint8_t newProfile; // Only valid when newState == STATE_PROFILE } setupButton; - const SystemState platformPreviousStateTable[] = { STATE_ROVER_NOT_STARTED, // EVK @@ -511,7 +510,6 @@ typedef enum SETTING_KNOWN_STRING, } SettingValueResponse; - #define INCHES_IN_A_METER 39.37007874 #define FEET_IN_A_METER 3.280839895 @@ -560,7 +558,7 @@ enum OtaState #ifdef COMPILE_AP -// Web Config state machine to allow web server access to network layer +// State machine to allow web server access to network layer enum WebServerState { WEBSERVER_STATE_OFF = 0, @@ -575,8 +573,6 @@ enum WebServerState #endif // COMPILE_AP - - // Regional Support // Some regions have both L-Band and IP. More just have IP. // Do we want the user to be able to specify which region they are in? @@ -627,6 +623,7 @@ enum NETCONSUMER_UNKNOWN }; uint16_t networkConsumerTypes = NETCONSUMER_NONE; +uint16_t previousNetworkConsumerTypes = NETCONSUMER_NONE; // This is all the settings that can be set on RTK Product. It's recorded to NVM and the config file. // Avoid reordering. The order of these variables is mimicked in NVM/record/parse/create/update/get @@ -1796,34 +1793,35 @@ struct struct_present // Monitor which devices on the device are on or offline. struct struct_online { - bool microSD = false; + bool batteryCharger_mp2762a = false; + bool batteryFuelGauge = false; + bool bluetooth = false; + bool button = false; bool display = false; + bool ethernetNTPServer = false; // EthernetUDP + bool fs = false; bool gnss = false; + bool gpioExpander = false; + bool httpClient = false; + bool i2c = false; + bool lband_gnss = false; + bool lband_neo = false; + bool lbandCorrections = false; bool logging = false; - bool serialOutput = false; - bool fs = false; - bool rtc = false; - bool batteryFuelGauge = false; + bool loraRadio = false; + bool microSD = false; + bool mqttClient = false; bool ntripClient = false; bool ntripServer[NTRIP_SERVER_MAX] = {false, false, false, false}; - bool lband_neo = false; - bool lband_gnss = false; - bool lbandCorrections = false; - bool i2c = false; + bool otaFirmwareUpdate = false; + bool ppl = false; + bool psram = false; + bool rtc = false; + bool serialOutput = false; bool tcpClient = false; bool tcpServer = false; bool udpServer = false; - bool ethernetNTPServer = false; // EthernetUDP - bool otaFirmwareUpdate = false; - bool bluetooth = false; - bool mqttClient = false; - bool psram = false; - bool ppl = false; - bool batteryCharger_mp2762a = false; - bool httpClient = false; - bool loraRadio = false; - bool button = false; - bool gpioExpander = false; + bool webServer = false; } online; typedef uint8_t NetIndex_t; // Index into the networkInterfaceTable From 38123570d394973037a86dcd48db913f35631a43 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 11:10:48 -0700 Subject: [PATCH 042/276] Make compile guards work --- Firmware/RTK_Everywhere/Developer.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 79c4a5b02..40bd860c9 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -52,6 +52,8 @@ void networkMarkOffline(NetIndex_t index) {} void networkMarkOnline(NetIndex_t index) {} void networkUpdate() {} void networkVerifyTables() {} +uint16_t networkGetConsumerTypes() {return(0);} +uint8_t networkConsumers() {return(0);} //---------------------------------------- // NTRIP client @@ -151,12 +153,12 @@ void httpClientValidateTables() {} #ifndef COMPILE_AP -bool startWebServer(bool startWiFi = true, int httpPort = 80) +bool webServerStart(int httpPort = 80) { systemPrintln("**AP not compiled**"); return false; } -void stopWebServer() {} +void webServerStop() {} bool parseIncomingSettings() {return false;} void sendStringToWebsocket(const char* stringToSend) {} From acec805918cdb5c337bfc055f0309531333f941c Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 11:36:44 -0700 Subject: [PATCH 043/276] Use online.* and xNeedsNetwork to control network access. Avoid use of webServerRequest or other bools. --- Firmware/RTK_Everywhere/HTTP_Client.ino | 8 +- Firmware/RTK_Everywhere/MQTT_Client.ino | 8 + Firmware/RTK_Everywhere/Network.ino | 305 ++++++++++++++------ Firmware/RTK_Everywhere/NtripClient.ino | 8 + Firmware/RTK_Everywhere/NtripServer.ino | 16 ++ Firmware/RTK_Everywhere/RTK_Everywhere.ino | 12 +- Firmware/RTK_Everywhere/States.ino | 27 +- Firmware/RTK_Everywhere/TcpClient.ino | 8 + Firmware/RTK_Everywhere/TcpServer.ino | 8 + Firmware/RTK_Everywhere/UdpServer.ino | 8 + Firmware/RTK_Everywhere/WebServer.ino | 310 ++++++++++----------- Firmware/RTK_Everywhere/WiFi.ino | 39 ++- Firmware/RTK_Everywhere/menuFirmware.ino | 10 +- Firmware/RTK_Everywhere/menuPP.ino | 18 +- Firmware/RTK_Everywhere/menuSystem.ino | 2 +- Firmware/RTK_Everywhere/settings.h | 2 +- 16 files changed, 503 insertions(+), 286 deletions(-) diff --git a/Firmware/RTK_Everywhere/HTTP_Client.ino b/Firmware/RTK_Everywhere/HTTP_Client.ino index c646636c8..95e13444b 100644 --- a/Firmware/RTK_Everywhere/HTTP_Client.ino +++ b/Firmware/RTK_Everywhere/HTTP_Client.ino @@ -347,6 +347,7 @@ void httpClientUpdate() } reportHeapNow(settings.debugHttpClientState); + online.httpClient = true; httpClientSetState(HTTP_CLIENT_CONNECTED); break; } @@ -576,11 +577,4 @@ void httpClientValidateTables() reportFatalError("Fix httpClientStateNameEntries to match HTTPClientState"); } -bool httpClientIsConnected() -{ - if (httpClientState == HTTP_CLIENT_CONNECTED) - return true; - return false; -} - #endif // COMPILE_HTTP_CLIENT diff --git a/Firmware/RTK_Everywhere/MQTT_Client.ino b/Firmware/RTK_Everywhere/MQTT_Client.ino index ca9094f61..3bd1cf91c 100644 --- a/Firmware/RTK_Everywhere/MQTT_Client.ino +++ b/Firmware/RTK_Everywhere/MQTT_Client.ino @@ -663,6 +663,14 @@ void mqttClientStop(bool shutdown) mqttClientSetState(MQTT_CLIENT_ON); } +// Return true if we are in states that require network access +bool mqttClientNeedsNetwork() +{ + if (mqttClientState >= MQTT_CLIENT_WAIT_FOR_NETWORK && mqttClientState <= MQTT_CLIENT_SERVICES_CONNECTED) + return true; + return false; +} + // Check for the arrival of any correction data. Push it to the GNSS. // Stop task if the connection has dropped or if we receive no data for // MQTT_CLIENT_RECEIVE_DATA_TIMEOUT diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index ab3107112..8bc1614b8 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -128,6 +128,8 @@ NETWORK_POLL_SEQUENCE *networkSequence[NETWORK_OFFLINE]; NetMask_t networkMdnsRunning; // Non-zero when mDNS is running +bool networkShutdownRequest = false; // Used to notify consumers that the network layer needs to shut down + //---------------------------------------- // Menu for configuring TCP/UDP interfaces //---------------------------------------- @@ -1315,6 +1317,42 @@ void networkStartDelayed(NetIndex_t index, uintptr_t parameter, bool debug) } } +//---------------------------------------- +// Validate the network index +//---------------------------------------- +void networkValidateIndex(NetIndex_t index) +{ + // Validate the index + if (index >= NETWORK_OFFLINE) + { + systemPrintf("HALTED: Invalid index value %d, valid range (0 - %d)!\r\n", index, NETWORK_OFFLINE - 1); + reportFatalError("Invalid index value!"); + } +} + +//---------------------------------------- +// Validate the network priority +//---------------------------------------- +void networkValidatePriority(NetPriority_t priority) +{ + // Validate the priority + if (priority >= NETWORK_OFFLINE) + { + systemPrintf("HALTED: Invalid priority value %d, valid range (0 - %d)!\r\n", priority, NETWORK_OFFLINE - 1); + reportFatalError("Invalid priority value!"); + } +} + +//---------------------------------------- +// Verify the network layer tables +//---------------------------------------- +void networkVerifyTables() +{ + // Verify the table lengths + if (NETWORK_OFFLINE != NETWORK_MAX) + reportFatalError("Fix networkInterfaceTable to match NetworkType"); +} + //---------------------------------------- // Maintain the network connections //---------------------------------------- @@ -1342,18 +1380,32 @@ void networkUpdate() // If there are no consumers, but the network is online, shut down all networks if (consumerCount == 0 && networkIsOnline() == true) { - if (systemState == STATE_WIFI_CONFIG) - { - // The STATE_WIFI_CONFIG is in control of WiFi. Don't allow the network layer to shut it down - // As OTA exits, we need to keep AP running if we are in Web Config mode - // We don't want to make STATE_WIFI_CONFIG a consumer until startWebServer() uses the network layer - } - else - { - // Shutdown all networks - for (int index = 0; index < NETWORK_OFFLINE; index++) - networkStop(index, settings.debugNetworkLayer); - } + // Shutdown all networks + for (int index = 0; index < NETWORK_OFFLINE; index++) + networkStop(index, settings.debugNetworkLayer); + } + + // If the consumers have indicated a network type change (ie, must have WiFi AP even though STA is connected) + // then stop all networks and let the lower code restart the network accordingly + if (networkConsumerTypes != previousNetworkConsumerTypes) + { + // if (networkConsumersOnline() > 0 && networkShutdownRequest == false) + // { + // // Tell consumers to shut down + // networkShutdownRequest = true; + // if (settings.debugNetworkLayer) + // systemPrintln("Notifying consumers of impending network shutdown"); + // } + // else + // { + // // We're clear to shutdown + // if (settings.debugNetworkLayer) + // systemPrintln("Stopping all networks because of consumer type change"); + + // Shutdown all networks + for (int index = 0; index < NETWORK_OFFLINE; index++) + networkStop(index, settings.debugNetworkLayer); + // } } // Allow consumers to start networks @@ -1364,16 +1416,35 @@ void networkUpdate() // Determine which type of network is needed // If a consumer is requesting a particular type, it gets priority - // WiFi STA + AP - if (((consumerTypes && (1 << NETCONSUMER_WIFI_STA)) && (consumerTypes && (1 << NETCONSUMER_WIFI_AP))) || + // Consumer is requesting WiFi specifically + if ((consumerTypes && (1 << NETCONSUMER_WIFI_STA)) || (consumerTypes && (1 << NETCONSUMER_WIFI_AP)) || (consumerTypes && (1 << NETCONSUMER_WIFI_AP_STA))) { + if (settings.debugNetworkLayer) + systemPrintln("Starting WiFi Specific Network"); + networkStart(NETWORK_WIFI, settings.debugNetworkLayer); } + // We don't have this type of consumer yet but good to have... + else if (consumerTypes && (1 << NETCONSUMER_ETHERNET)) + { + networkStart(NETWORK_ETHERNET, settings.debugNetworkLayer); + } + + // We don't have this type of consumer yet but good to have... + else if (consumerTypes && (1 << NETCONSUMER_CELLULAR)) + { + networkStart(NETWORK_CELLULAR, settings.debugNetworkLayer); + } + + // Most consumers don't care and so they get whatever is available else if (consumerTypes == NETCONSUMER_ANY) { - // Start any network that is available, in order ethernet/wifi/cellular + if (settings.debugNetworkLayer) + systemPrintln("Starting any network"); + + // Start any network that is available, in the order Ethernet/WiFi/Cellular for (int index = 0; index < NETWORK_OFFLINE; index++) networkStart(index, settings.debugNetworkLayer); } @@ -1448,44 +1519,6 @@ void networkUpdate() } } -//---------------------------------------- -// Validate the network index -//---------------------------------------- -void networkValidateIndex(NetIndex_t index) -{ - // Validate the index - if (index >= NETWORK_OFFLINE) - { - systemPrintf("HALTED: Invalid index value %d, valid range (0 - %d)!\r\n", index, NETWORK_OFFLINE - 1); - reportFatalError("Invalid index value!"); - } -} - -//---------------------------------------- -// Validate the network priority -//---------------------------------------- -void networkValidatePriority(NetPriority_t priority) -{ - // Validate the priority - if (priority >= NETWORK_OFFLINE) - { - systemPrintf("HALTED: Invalid priority value %d, valid range (0 - %d)!\r\n", priority, NETWORK_OFFLINE - 1); - reportFatalError("Invalid priority value!"); - } -} - -//---------------------------------------- -// Verify the network layer tables -//---------------------------------------- -void networkVerifyTables() -{ - // Verify the table lengths - if (NETWORK_OFFLINE != NETWORK_MAX) - reportFatalError("Fix networkInterfaceTable to match NetworkType"); -} - -#endif // COMPILE_NETWORK - // Return the bitfield containing uint16_t networkGetConsumerTypes() { @@ -1501,10 +1534,14 @@ uint8_t networkConsumers() uint8_t consumerCount = 0; uint16_t consumerId = 0; // Used to debug print who is asking for access + previousNetworkConsumerTypes = networkConsumerTypes; networkConsumerTypes = NETCONSUMER_NONE; // Clear bitfield + // If a consumer is waiting for the network, or is currently consuming the network (is online) then increment + // consumer count + // Network needed for NTRIP Client - if ((inRoverMode() == true && settings.enableNtripClient == true) || online.ntripClient) + if (ntripClientNeedsNetwork() || online.ntripClient) { consumerCount++; consumerId |= (1 << 0); @@ -1512,17 +1549,17 @@ uint8_t networkConsumers() } // Network needed for NTRIP Server - bool ntripServerConnected = false; + bool ntripServerOnline = false; for (int index = 0; index < NTRIP_SERVER_MAX; index++) { if (online.ntripServer[index]) { - ntripServerConnected = true; + ntripServerOnline = true; break; } } - if ((inBaseMode() == true && settings.enableNtripServer == true) || ntripServerConnected) + if (ntripServerNeedsNetwork() || ntripServerOnline) { consumerCount++; consumerId |= (1 << 1); @@ -1532,7 +1569,7 @@ uint8_t networkConsumers() } // Network needed for TCP Client - if (settings.enableTcpClient == true || online.tcpClient) + if (tcpClientNeedsNetwork() || online.tcpClient) { consumerCount++; consumerId |= (1 << 2); @@ -1540,7 +1577,7 @@ uint8_t networkConsumers() } // Network needed for TCP Server - if (settings.enableTcpServer == true || online.tcpServer) + if (tcpServerNeedsNetwork() || online.tcpServer) { consumerCount++; consumerId |= (1 << 3); @@ -1548,7 +1585,7 @@ uint8_t networkConsumers() } // Network needed for UDP Server - if (settings.enableUdpServer == true || online.udpServer) + if (udpServerIsWaitingForNetwork() || online.udpServer) { consumerCount++; consumerId |= (1 << 4); @@ -1556,7 +1593,7 @@ uint8_t networkConsumers() } // Network needed for PointPerfect ZTP or key update requested by scheduler, from menu, or display menu - if (settings.requestKeyUpdate == true) + if (provisioningNeedsNetwork() || online.httpClient) { consumerCount++; consumerId |= (1 << 5); @@ -1564,8 +1601,7 @@ uint8_t networkConsumers() } // Network needed for PointPerfect Corrections MQTT client - if ((settings.enablePointPerfectCorrections == true && strlen(settings.pointPerfectCurrentKey) > 0) || - online.mqttClient) + if (mqttClientNeedsNetwork() || online.mqttClient) { // PointPerfect is enabled, allow MQTT to begin consumerCount++; @@ -1573,27 +1609,19 @@ uint8_t networkConsumers() networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } - // Network needed to obtain the latest firmware version - if (otaRequestFirmwareVersionCheck == true) + // Network needed to obtain the latest firmware version or do a firmware update + if (otaNeedsNetwork() || online.otaClient) { consumerCount++; consumerId |= (1 << 7); networkConsumerTypes |= (1 << NETCONSUMER_WIFI_STA); // OTA Pull library only supports WiFi } - // Network needed to start a firmware update - if (otaRequestFirmwareUpdate == true) - { - consumerCount++; - consumerId |= (1 << 8); - networkConsumerTypes |= (1 << NETCONSUMER_WIFI_STA); // OTA Pull library only supports WiFi - } - // Network needed for Web Config - if (inWiFiConfigMode() == true) + if (webServerNeedsNetwork() || online.webServer) { consumerCount++; - consumerId |= (1 << 9); + consumerId |= (1 << 8); if (settings.wifiConfigOverAP == true) networkConsumerTypes |= (1 << NETCONSUMER_WIFI_AP); // @@ -1629,10 +1657,8 @@ uint8_t networkConsumers() if (consumerId & (1 << 6)) systemPrint("PPL MQTT Client, "); if (consumerId & (1 << 7)) - systemPrint("OTA Version Check, "); + systemPrint("OTA Version Check or Update, "); if (consumerId & (1 << 8)) - systemPrint("OTA Scheduled Check, "); - if (consumerId & (1 << 9)) systemPrint("Web Config, "); } @@ -1642,3 +1668,126 @@ uint8_t networkConsumers() return (consumerCount); } + +// Return the count of consumers (TCP, NTRIP Client, etc) that are currently using the network +// This tells the network when it can shutdown to change (ie, move from STA to AP) +uint8_t networkConsumersOnline() +{ + uint8_t consumerCountOnline = 0; + uint16_t consumerId = 0; // Used to debug print who is asking for access + + // Network needed for NTRIP Client + if (online.ntripClient) + { + consumerCountOnline++; + consumerId |= (1 << 0); + } + + // Network needed for NTRIP Server + bool ntripServerConnected = false; + for (int index = 0; index < NTRIP_SERVER_MAX; index++) + { + if (online.ntripServer[index]) + { + ntripServerConnected = true; + break; + } + } + + if (ntripServerConnected) + { + consumerCountOnline++; + consumerId |= (1 << 1); + } + + // Network needed for TCP Client + if (online.tcpClient) + { + consumerCountOnline++; + consumerId |= (1 << 2); + } + + // Network needed for TCP Server + if (online.tcpServer) + { + consumerCountOnline++; + consumerId |= (1 << 3); + } + + // Network needed for UDP Server + if (online.udpServer) + { + consumerCountOnline++; + consumerId |= (1 << 4); + } + + // Network needed for PointPerfect ZTP or key update requested by scheduler, from menu, or display menu + if (online.httpClient) + { + consumerCountOnline++; + consumerId |= (1 << 5); + } + + // Network needed for PointPerfect Corrections MQTT client + if (online.mqttClient) + { + // PointPerfect is enabled, allow MQTT to begin + consumerCountOnline++; + consumerId |= (1 << 6); + } + + // Network needed to obtain the latest firmware version or do update + if (online.otaClient) + { + consumerCountOnline++; + consumerId |= (1 << 7); + } + + // Network needed for Web Config + if (online.webServer) + { + consumerCountOnline++; + consumerId |= (1 << 8); + } + + // Debug + if (settings.debugNetworkLayer) + { + static unsigned long lastPrint = 0; + + if (millis() - lastPrint > 2000) + { + lastPrint = millis(); + systemPrintf("Network consumer online count: %d ", consumerCountOnline); + if (consumerCountOnline > 0) + { + systemPrintf("- Consumers: ", consumerCountOnline); + + if (consumerId & (1 << 0)) + systemPrint("Rover NTRIP Client, "); + if (consumerId & (1 << 1)) + systemPrint("Base NTRIP Server, "); + if (consumerId & (1 << 2)) + systemPrint("TCP Client, "); + if (consumerId & (1 << 3)) + systemPrint("TCP Server, "); + if (consumerId & (1 << 4)) + systemPrint("UDP Server, "); + if (consumerId & (1 << 5)) + systemPrint("PPL Key Update Request, "); + if (consumerId & (1 << 6)) + systemPrint("PPL MQTT Client, "); + if (consumerId & (1 << 7)) + systemPrint("OTA Version Check or Update, "); + if (consumerId & (1 << 8)) + systemPrint("Web Config, "); + } + + systemPrintln(); + } + } + + return (consumerCountOnline); +} + +#endif // COMPILE_NETWORK \ No newline at end of file diff --git a/Firmware/RTK_Everywhere/NtripClient.ino b/Firmware/RTK_Everywhere/NtripClient.ino index 78f2d2dae..28a0a00e5 100644 --- a/Firmware/RTK_Everywhere/NtripClient.ino +++ b/Firmware/RTK_Everywhere/NtripClient.ino @@ -526,6 +526,14 @@ void ntripClientStop(bool shutdown) ntripClientSetState(NTRIP_CLIENT_ON); } +// Return true if we are in states that require network access +bool ntripClientNeedsNetwork() +{ + if (ntripClientState >= NTRIP_CLIENT_WAIT_FOR_NETWORK && ntripClientState <= NTRIP_CLIENT_CONNECTED) + return true; + return false; +} + // Check for the arrival of any correction data. Push it to the GNSS. // Stop task if the connection has dropped or if we receive no data for // NTRIP_CLIENT_RECEIVE_DATA_TIMEOUT diff --git a/Firmware/RTK_Everywhere/NtripServer.ino b/Firmware/RTK_Everywhere/NtripServer.ino index 197dcadd7..00c5e6a2a 100644 --- a/Firmware/RTK_Everywhere/NtripServer.ino +++ b/Firmware/RTK_Everywhere/NtripServer.ino @@ -559,6 +559,22 @@ void ntripServerStop(int serverIndex, bool shutdown) } } +// Return true if we are in states that require network access +// Walk through all servers to see if we need the network +bool ntripServerNeedsNetwork() +{ + NTRIP_SERVER_DATA *ntripServer; + + for (int serverIndex = 0; serverIndex < NTRIP_SERVER_MAX; serverIndex++) + { + ntripServer = &ntripServerArray[serverIndex]; + if (ntripServer->state >= NTRIP_SERVER_WAIT_FOR_NETWORK && ntripServer->state <= NTRIP_SERVER_CASTING) + return true; + } + + return false; +} + // Update the NTRIP server state machine void ntripServerUpdate(int serverIndex) { diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 4d6f73886..7a4c5bd08 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -475,7 +475,8 @@ const int btReadTaskStackSize = 4000; RING_BUFFER_OFFSET *rbOffsetArray = nullptr; uint16_t rbOffsetEntries; -uint8_t *ringBuffer; // Buffer for reading from GNSS receiver. At 230400bps, 23040 bytes/s. If SD blocks for 250ms, we need 23040 +uint8_t *ringBuffer; // Buffer for reading from GNSS receiver. At 230400bps, 23040 bytes/s. If SD blocks for 250ms, we + // need 23040 // * 0.25 = 5760 bytes worst case. const int gnssReadTaskStackSize = 8000; const size_t sempGnssReadBufferSize = 8000; // Make the SEMP buffer size the ~same @@ -557,8 +558,6 @@ int incomingSettingsSpot; unsigned long timeSinceLastIncomingSetting; unsigned long lastDynamicDataUpdate; -bool webServerRequest = false; // Goes true when STATE_WIFI_CONFIG_NOT_STARTED is entered. Goes false when Rover/Base is started. - #ifdef COMPILE_WIFI #ifdef COMPILE_AP @@ -1258,13 +1257,14 @@ void loop() printReports(); // Periodically print GNSS coordinates and accuracy if enabled DMW_c("otaAutoUpdate"); - otaUpdate(); // Initiate firmware version checks, scheduled automatic updates, or requested firmware over-the-air updates + otaUpdate(); // Initiate firmware version checks, scheduled automatic updates, or requested firmware over-the-air + // updates DMW_c("correctionUpdateSource"); correctionUpdateSource(); // Retire expired sources DMW_c("updateProvisioning"); - updateProvisioning(); // Check if we should attempt to connect to PointPerfect to get keys / certs / correction + provisioningUpdate(); // Check if we should attempt to connect to PointPerfect to get keys / certs / correction // topic etc. loopDelay(); // A small delay prevents panic if no other I2C or functions are called @@ -1288,7 +1288,7 @@ void logUpdate() systemTime_minutes = millis() / 1000L / 60; // If we are in AP config, don't touch the SD card - if (systemState == STATE_WIFI_CONFIG_NOT_STARTED || systemState == STATE_WIFI_CONFIG) + if (inWiFiConfigMode()) return; if (online.microSD == false) diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index fd2fb800f..533608acd 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -115,6 +115,8 @@ void stateUpdate() bluetoothStart(); // Turn on Bluetooth with 'Rover' name espnowStart(); // Start internal radio if enabled, otherwise disable + webServerStop(); // Stop the web config server + // Start the UART connected to the GNSS receiver for NMEA and UBX data (enables logging) if (tasksStartGnssUart() == false) displayRoverFail(1000); @@ -219,6 +221,8 @@ void stateUpdate() bluetoothStop(); bluetoothStart(); // Restart Bluetooth with 'Base' identifier + webServerStop(); // Stop the web config server + // Start the UART connected to the GNSS receiver for NMEA and UBX data (enables logging) if (tasksStartGnssUart() && gnss->configureBase()) { @@ -415,25 +419,16 @@ void stateUpdate() baseStatusLedOff(); // Turn off the status LED displayWiFiConfigNotStarted(); // Display immediately during SD cluster pause - - // TODO - Do we need to stop BT and ESP-NOW? + + // TODO - Do we need to stop BT and ESP-NOW during web config or can we leave it running? bluetoothStop(); espnowStop(); tasksStopGnssUart(); // Delete serial tasks if running - webServerRequest = true; // Notify the network that we need access, start web server - - changeState(STATE_WIFI_CONFIG_WAIT_FOR_NETWORK); - } - break; + webServerStart(); // Start the webserver state machine for web config - case (STATE_WIFI_CONFIG_WAIT_FOR_NETWORK): { - // Wait while web server starts - if (webServerIsRunning() == true) - { - RTK_MODE(RTK_MODE_WIFI_CONFIG); - changeState(STATE_WIFI_CONFIG); - } + RTK_MODE(RTK_MODE_WIFI_CONFIG); + changeState(STATE_WIFI_CONFIG); } break; @@ -657,7 +652,7 @@ void stateUpdate() ethernetWebServerStartESP32W5500(); // Start Ethernet in dedicated configure-via-ethernet mode - webServerRequest = true; // Notify the network that we need access, start web server + webServerStart(); // Start the webserver state machine for web config // TODO add a state machine step for ethernet to wait for web server to start // See wifi web server / web config @@ -786,8 +781,6 @@ const char *getState(SystemState state, char *buffer) return "STATE_DISPLAY_SETUP"; case (STATE_WIFI_CONFIG_NOT_STARTED): return "STATE_WIFI_CONFIG_NOT_STARTED"; - case (STATE_WIFI_CONFIG_WAIT_FOR_NETWORK): - return "STATE_WIFI_CONFIG_WAIT_FOR_NETWORK"; case (STATE_WIFI_CONFIG): return "STATE_WIFI_CONFIG"; case (STATE_TEST): diff --git a/Firmware/RTK_Everywhere/TcpClient.ino b/Firmware/RTK_Everywhere/TcpClient.ino index 5fbdce19c..20f7630b9 100644 --- a/Firmware/RTK_Everywhere/TcpClient.ino +++ b/Firmware/RTK_Everywhere/TcpClient.ino @@ -355,6 +355,14 @@ void tcpClientStop() tcpClientSetState(TCP_CLIENT_STATE_OFF); } +// Return true if we are in a state that requires network access +bool tcpClientNeedsNetwork() +{ + if (tcpClientState >= TCP_CLIENT_STATE_WAIT_FOR_NETWORK && tcpClientState <= TCP_CLIENT_STATE_CONNECTED) + return true; + return false; +} + // Update the TCP client state void tcpClientUpdate() { diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index 747db7f0e..b1af8da73 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -314,6 +314,14 @@ void tcpServerStopClient(int index) tcpServerClientWriteError = tcpServerClientWriteError & (~(1 << index)); } +// Return true if we are in a state that requires network access +bool tcpServerNeedsNetwork() +{ + if (tcpServerState >= TCP_SERVER_STATE_WAIT_FOR_NETWORK && tcpServerState <= TCP_SERVER_STATE_RUNNING) + return true; + return false; +} + // Update the TCP server state void tcpServerUpdate() { diff --git a/Firmware/RTK_Everywhere/UdpServer.ino b/Firmware/RTK_Everywhere/UdpServer.ino index 50a248e89..4fd544e4e 100644 --- a/Firmware/RTK_Everywhere/UdpServer.ino +++ b/Firmware/RTK_Everywhere/UdpServer.ino @@ -276,6 +276,14 @@ void udpServerStop() } } +// Return true if we are in a state that requires network access +bool udpServerIsWaitingForNetwork() +{ + if (udpServerState >= UDP_SERVER_STATE_WAIT_FOR_NETWORK && udpServerState <= UDP_SERVER_STATE_RUNNING) + return true; + return false; +} + // Update the UDP server state void udpServerUpdate() { diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index 88f744179..c0ad9ab6f 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -7,13 +7,15 @@ Form.ino #ifdef COMPILE_AP static const char *const webServerStateNames[] = { - "WEBSERVER_STATE_OFF", "WEBSERVER_STATE_WAIT_FOR_NETWORK", "WEBSERVER_STATE_NETWORK_CONNECTED", - "WEBSERVER_STATE_STARTED", "WEBSERVER_STATE_RUNNING", + "WEBSERVER_STATE_OFF", + "WEBSERVER_STATE_WAIT_FOR_NETWORK", + "WEBSERVER_STATE_NETWORK_CONNECTED", + "WEBSERVER_STATE_RUNNING", }; static const int webServerStateEntries = sizeof(webServerStateNames) / sizeof(webServerStateNames[0]); -static NetPriority_t webconfigPriority = NETWORK_OFFLINE; +static NetPriority_t webServerPriority = NETWORK_OFFLINE; static WebServerState webServerState; // Once connected to the access point for WiFi Config, the ESP32 sends current setting values in one long string to @@ -248,18 +250,16 @@ class CaptiveRequestHandler : public RequestHandler }; // Start the webServer -bool webServerStart(bool startWiFi = true, int httpPort = 80) +bool webServerAssignResources(int httpPort = 80) { do { - ntripClientStop(true); // Do not allocate new wifiClient - for (int serverIndex = 0; serverIndex < NTRIP_SERVER_MAX; serverIndex++) - ntripServerStop(serverIndex, true); // Do not allocate new wifiClient - - // if (startWiFi) - // if (wifiStartAP() == false) - // break; + // TODO Do we need to stop NTRIP Clients? Let them run while Web Config is running? + // ntripClientStop(true); // Do not allocate new wifiClient + // for (int serverIndex = 0; serverIndex < NTRIP_SERVER_MAX; serverIndex++) + // ntripServerStop(serverIndex, true); // Do not allocate new wifiClient + // TODO DNS should be started/stopped at the network layer // // Start the multicast DNS server // if (startWiFi == true) // networkMulticastDNSSwitch(NETWORK_WIFI); @@ -293,8 +293,8 @@ bool webServerStart(bool startWiFi = true, int httpPort = 80) } createSettingsString(settingsCSV); - // - https://github.com/espressif/arduino-esp32/blob/master/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino + // + https: // github.com/espressif/arduino-esp32/blob/master/libraries/DNSServer/examples/CaptivePortal/CaptivePortal.ino if (settings.enableCaptivePortal == true) { dnsserver = new DNSServer; @@ -341,142 +341,135 @@ bool webServerStart(bool startWiFi = true, int httpPort = 80) webServer->onNotFound(notFound); - webServer->on("/", HTTP_GET, []() - { + webServer->on("/", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "text/html", (const char *)index_html, sizeof(index_html)); }); + webServer->send_P(200, "text/html", (const char *)index_html, sizeof(index_html)); + }); - webServer->on("/favicon.ico", HTTP_GET, []() - { + webServer->on("/favicon.ico", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "text/plain", (const char *)favicon_ico, sizeof(favicon_ico)); }); + webServer->send_P(200, "text/plain", (const char *)favicon_ico, sizeof(favicon_ico)); + }); - webServer->on("/src/bootstrap.bundle.min.js", HTTP_GET, []() - { + webServer->on("/src/bootstrap.bundle.min.js", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); webServer->send_P(200, "text/javascript", (const char *)bootstrap_bundle_min_js, - sizeof(bootstrap_bundle_min_js)); }); + sizeof(bootstrap_bundle_min_js)); + }); - webServer->on("/src/bootstrap.min.css", HTTP_GET, []() - { + webServer->on("/src/bootstrap.min.css", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "text/css", (const char *)bootstrap_min_css, sizeof(bootstrap_min_css)); }); + webServer->send_P(200, "text/css", (const char *)bootstrap_min_css, sizeof(bootstrap_min_css)); + }); - webServer->on("/src/bootstrap.min.js", HTTP_GET, []() - { + webServer->on("/src/bootstrap.min.js", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "text/javascript", (const char *)bootstrap_min_js, sizeof(bootstrap_min_js)); }); + webServer->send_P(200, "text/javascript", (const char *)bootstrap_min_js, sizeof(bootstrap_min_js)); + }); - webServer->on("/src/jquery-3.6.0.min.js", HTTP_GET, []() - { + webServer->on("/src/jquery-3.6.0.min.js", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "text/javascript", (const char *)jquery_js, sizeof(jquery_js)); }); + webServer->send_P(200, "text/javascript", (const char *)jquery_js, sizeof(jquery_js)); + }); - webServer->on("/src/main.js", HTTP_GET, []() - { + webServer->on("/src/main.js", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "text/javascript", (const char *)main_js, sizeof(main_js)); }); + webServer->send_P(200, "text/javascript", (const char *)main_js, sizeof(main_js)); + }); - webServer->on("/src/rtk-setup.png", HTTP_GET, []() - { + webServer->on("/src/rtk-setup.png", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); if (productVariant == RTK_EVK) webServer->send_P(200, "image/png", (const char *)rtkSetup_png, sizeof(rtkSetup_png)); else - webServer->send_P(200, "image/png", (const char *)rtkSetupWiFi_png, sizeof(rtkSetupWiFi_png)); }); + webServer->send_P(200, "image/png", (const char *)rtkSetupWiFi_png, sizeof(rtkSetupWiFi_png)); + }); // Battery icons - webServer->on("/src/BatteryBlank.png", HTTP_GET, []() - { + webServer->on("/src/BatteryBlank.png", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "image/png", (const char *)batteryBlank_png, sizeof(batteryBlank_png)); }); - webServer->on("/src/Battery0.png", HTTP_GET, []() - { + webServer->send_P(200, "image/png", (const char *)batteryBlank_png, sizeof(batteryBlank_png)); + }); + webServer->on("/src/Battery0.png", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "image/png", (const char *)battery0_png, sizeof(battery0_png)); }); - webServer->on("/src/Battery1.png", HTTP_GET, []() - { + webServer->send_P(200, "image/png", (const char *)battery0_png, sizeof(battery0_png)); + }); + webServer->on("/src/Battery1.png", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "image/png", (const char *)battery1_png, sizeof(battery1_png)); }); - webServer->on("/src/Battery2.png", HTTP_GET, []() - { + webServer->send_P(200, "image/png", (const char *)battery1_png, sizeof(battery1_png)); + }); + webServer->on("/src/Battery2.png", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "image/png", (const char *)battery2_png, sizeof(battery2_png)); }); - webServer->on("/src/Battery3.png", HTTP_GET, []() - { + webServer->send_P(200, "image/png", (const char *)battery2_png, sizeof(battery2_png)); + }); + webServer->on("/src/Battery3.png", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "image/png", (const char *)battery3_png, sizeof(battery3_png)); }); + webServer->send_P(200, "image/png", (const char *)battery3_png, sizeof(battery3_png)); + }); - webServer->on("/src/Battery0_Charging.png", HTTP_GET, []() - { + webServer->on("/src/Battery0_Charging.png", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); webServer->send_P(200, "image/png", (const char *)battery0_Charging_png, sizeof(battery0_Charging_png)); - }); - webServer->on("/src/Battery1_Charging.png", HTTP_GET, []() - { + }); + webServer->on("/src/Battery1_Charging.png", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); webServer->send_P(200, "image/png", (const char *)battery1_Charging_png, sizeof(battery1_Charging_png)); - }); - webServer->on("/src/Battery2_Charging.png", HTTP_GET, []() - { + }); + webServer->on("/src/Battery2_Charging.png", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); webServer->send_P(200, "image/png", (const char *)battery2_Charging_png, sizeof(battery2_Charging_png)); - }); - webServer->on("/src/Battery3_Charging.png", HTTP_GET, []() - { + }); + webServer->on("/src/Battery3_Charging.png", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); webServer->send_P(200, "image/png", (const char *)battery3_Charging_png, sizeof(battery3_Charging_png)); - }); + }); - webServer->on("/src/style.css", HTTP_GET, []() - { + webServer->on("/src/style.css", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "text/css", (const char *)style_css, sizeof(style_css)); }); + webServer->send_P(200, "text/css", (const char *)style_css, sizeof(style_css)); + }); - webServer->on("/src/fonts/icomoon.eot", HTTP_GET, []() - { + webServer->on("/src/fonts/icomoon.eot", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "text/plain", (const char *)icomoon_eot, sizeof(icomoon_eot)); }); + webServer->send_P(200, "text/plain", (const char *)icomoon_eot, sizeof(icomoon_eot)); + }); - webServer->on("/src/fonts/icomoon.svg", HTTP_GET, []() - { + webServer->on("/src/fonts/icomoon.svg", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "text/plain", (const char *)icomoon_svg, sizeof(icomoon_svg)); }); + webServer->send_P(200, "text/plain", (const char *)icomoon_svg, sizeof(icomoon_svg)); + }); - webServer->on("/src/fonts/icomoon.ttf", HTTP_GET, []() - { + webServer->on("/src/fonts/icomoon.ttf", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "text/plain", (const char *)icomoon_ttf, sizeof(icomoon_ttf)); }); + webServer->send_P(200, "text/plain", (const char *)icomoon_ttf, sizeof(icomoon_ttf)); + }); - webServer->on("/src/fonts/icomoon.woof", HTTP_GET, []() - { + webServer->on("/src/fonts/icomoon.woof", HTTP_GET, []() { webServer->sendHeader("Content-Encoding", "gzip"); - webServer->send_P(200, "text/plain", (const char *)icomoon_woof, sizeof(icomoon_woof)); }); + webServer->send_P(200, "text/plain", (const char *)icomoon_woof, sizeof(icomoon_woof)); + }); // Handler for the /uploadFile form POST webServer->on( - "/uploadFile", HTTP_POST, []() - { webServer->send(200, "text/plain", ""); }, + "/uploadFile", HTTP_POST, []() { webServer->send(200, "text/plain", ""); }, handleUpload); // Run handleUpload function when file manager file is uploaded // Handler for the /uploadFirmware form POST webServer->on( - "/uploadFirmware", HTTP_POST, []() - { webServer->send(200, "text/plain", ""); }, handleFirmwareFileUpload); + "/uploadFirmware", HTTP_POST, []() { webServer->send(200, "text/plain", ""); }, handleFirmwareFileUpload); // Handler for file manager - webServer->on("/listfiles", HTTP_GET, []() - { + webServer->on("/listfiles", HTTP_GET, []() { String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); if (settings.debugWebServer == true) systemPrintln(logmessage); String files; getFileList(files); - webServer->send(200, "text/plain", files); }); + webServer->send(200, "text/plain", files); + }); // Handler for supported messages list - webServer->on("/listMessages", HTTP_GET, []() - { + webServer->on("/listMessages", HTTP_GET, []() { String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); if (settings.debugWebServer == true) systemPrintln(logmessage); @@ -484,11 +477,11 @@ bool webServerStart(bool startWiFi = true, int httpPort = 80) createMessageList(messages); if (settings.debugWebServer == true) systemPrintln(messages); - webServer->send(200, "text/plain", messages); }); + webServer->send(200, "text/plain", messages); + }); // Handler for supported RTCM/Base messages list - webServer->on("/listMessagesBase", HTTP_GET, []() - { + webServer->on("/listMessagesBase", HTTP_GET, []() { String logmessage = "Client:" + webServer->client().remoteIP().toString() + " " + webServer->uri(); if (settings.debugWebServer == true) systemPrintln(logmessage); @@ -496,7 +489,8 @@ bool webServerStart(bool startWiFi = true, int httpPort = 80) createMessageListBase(messageList); if (settings.debugWebServer == true) systemPrintln(messageList); - webServer->send(200, "text/plain", messageList); }); + webServer->send(200, "text/plain", messageList); + }); // Handler for file manager webServer->on("/file", HTTP_GET, handleFileManager); @@ -533,11 +527,20 @@ bool webServerStart(bool startWiFi = true, int httpPort = 80) return false; } +// Start the Web Server state machine +void webServerStart() +{ + // Display the heap state + reportHeapNow(settings.debugWebServer); + + systemPrintln("Web Server start"); + webServerSetState(WEBSERVER_STATE_WAIT_FOR_NETWORK); +} // Stop the web config state machine void webServerStop() { - webServerRequest = false; // Notify the network layer that access is no longer needed + online.webServer = false; if (settings.debugWebServer) systemPrintln("webServerStop called"); @@ -555,6 +558,14 @@ void webServerStop() } } +// Return true if we are in a state that requires network access +bool webServerNeedsNetwork() +{ + if (webServerState >= WEBSERVER_STATE_WAIT_FOR_NETWORK && webServerState <= WEBSERVER_STATE_RUNNING) + return true; + return false; +} + void webServerStopSockets() { createSettingsString(settingsCSV); @@ -731,87 +742,72 @@ void webServerReleaseResources() } } - // State machine to handle the starting/stopping of the web server void webServerUpdate() { - if (!inMainMenu) + // Shutdown the Web Server setting changes + // if (settings.enableNtripClient == false) + // { + // if (ntripClientState > NTRIP_CLIENT_OFF) + // { + // ntripClientStop(true); // Was false - #StopVsRestart + // ntripClientConnectionAttempts = 0; + // ntripClientConnectionAttemptTimeout = 0; + // ntripClientSetState(NTRIP_CLIENT_OFF); + // } + // } + + // Walk the state machine + switch (webServerState) { - // Walk the state machine - switch (webServerState) - { - default: - systemPrintf("ERROR: Unknown WebConfig state (%d)\r\n", webServerState); + default: + systemPrintf("ERROR: Unknown Web Server state (%d)\r\n", webServerState); - // Stop the machine - webServerStop(); - break; - - // Wait for a request from a user - case WEBSERVER_STATE_OFF: - if (webServerRequest == true) - webServerSetState(WEBSERVER_STATE_WAIT_FOR_NETWORK); - break; - - // Wait for connection to the network - case WEBSERVER_STATE_WAIT_FOR_NETWORK: - // Determine if the request has been canceled while waiting - if (webServerRequest == false) - webServerStop(); - - // Wait until the network is connected to the media - else if (networkIsConnected(&webconfigPriority)) - { - if (settings.debugWebServer) - systemPrintln("Web config connected to network"); + // Stop the machine + webServerStop(); + break; - webServerSetState(WEBSERVER_STATE_NETWORK_CONNECTED); - } - break; + case WEBSERVER_STATE_OFF: + // Wait until webServerStart() is called + break; - // Start the web server - case WEBSERVER_STATE_NETWORK_CONNECTED: { - // Determine if the network has failed - if (!networkIsConnected(&webconfigPriority)) - webServerStop(); + // Wait for connection to the network + case WEBSERVER_STATE_WAIT_FOR_NETWORK: + // Wait until the network is connected to the media + if (networkIsConnected(&webServerPriority)) + { if (settings.debugWebServer) - systemPrintln("Starting web server"); + systemPrintln("Web Server connected to network"); - if (webServerStart(false, settings.httpPort) == true) - webServerSetState(WEBSERVER_STATE_STARTED); + webServerSetState(WEBSERVER_STATE_NETWORK_CONNECTED); } break; - // Wait for web server to start - case WEBSERVER_STATE_STARTED: - // Determine if the network has failed - if (!networkIsConnected(&webconfigPriority)) - webServerStop(); - if (settings.debugWebServer) - systemPrintln("Web config waiting for web server to start"); + // Start the web server + case WEBSERVER_STATE_NETWORK_CONNECTED: { + // Determine if the network has failed + if (!networkIsConnected(&webServerPriority)) + webServerStop(); + if (settings.debugWebServer) + systemPrintln("Starting web server"); - //... + if (webServerAssignResources(settings.httpPort) == true) + { + online.webServer = true; webServerSetState(WEBSERVER_STATE_RUNNING); + } + } + break; - break; - - // Allow web services - case WEBSERVER_STATE_RUNNING: - // Determine if the network has failed - if (!networkIsConnected(&webconfigPriority)) - webServerStop(); - - // TODO how does the system indicate we need to shut down the web server? - if (inWiFiConfigMode() == false) - { - webServerRequest = false; // Tell the network layer we no longer need access - webServerStop(); - } + // Allow web services + case WEBSERVER_STATE_RUNNING: + // Determine if the network has failed + if (!networkIsConnected(&webServerPriority)) + webServerStop(); - //... + // This state is exited when webServerStop() is called - break; - } + break; } } diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index d2ae92d90..d5d0ce66f 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -152,30 +152,46 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) if (startWiFiAP && WiFi.getMode() == WIFI_AP) return (true); // There is nothing needing to be changed - wifiRunning = false; //Mark it as offline while we mess about - + wifiRunning = false; // Mark it as offline while we mess about + wifi_mode_t wifiMode = WIFI_OFF; wifi_interface_t wifiInterface = WIFI_IF_STA; - if (networkGetConsumerTypes() == NETCONSUMER_WIFI_STA) + if (networkGetConsumerTypes() == NETCONSUMER_ANY) { - systemPrintln("Starting WiFi Station"); + if (settings.debugWifiState == true) + systemPrintln("Starting WiFi Station due to NETCONSUMER_ANY"); + else + systemPrintln("Starting WiFi Station"); wifiMode = WIFI_STA; wifiInterface = WIFI_IF_STA; } - else if (networkGetConsumerTypes() == NETCONSUMER_WIFI_AP) - { - systemPrintln("Starting WiFi AP"); - wifiMode = WIFI_AP; - wifiInterface = WIFI_IF_AP; - } - else if (networkGetConsumerTypes() == NETCONSUMER_WIFI_AP_STA) + + // See if consumers are calling for AP+STA directly, or AP and STA individually + else if ((networkGetConsumerTypes() && (1 << NETCONSUMER_WIFI_AP_STA)) || + (networkGetConsumerTypes() && ((1 << NETCONSUMER_WIFI_AP) || (1 << NETCONSUMER_WIFI_STA)))) { systemPrintln("Starting WiFi AP+Station"); wifiMode = WIFI_AP_STA; wifiInterface = WIFI_IF_AP; // There is no WIFI_IF_AP_STA } + else if (networkGetConsumerTypes() && (1 << NETCONSUMER_WIFI_STA)) + { + if (settings.debugWifiState == true) + systemPrintln("Starting WiFi Station due to NETCONSUMER_WIFI_STA"); + else + systemPrintln("Starting WiFi Station"); + wifiMode = WIFI_STA; + wifiInterface = WIFI_IF_STA; + } + else if (networkGetConsumerTypes() && (1 << NETCONSUMER_WIFI_AP)) + { + systemPrintln("Starting WiFi AP"); + wifiMode = WIFI_AP; + wifiInterface = WIFI_IF_AP; + } + displayWiFiConnect(); if (WiFi.mode(wifiMode) == false) // Start WiFi in the appropriate mode @@ -680,5 +696,4 @@ void wifiStop(NetIndex_t index, uintptr_t parameter, bool debug) networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); } - #endif // COMPILE_WIFI diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index bfff93793..412e42124 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -774,7 +774,7 @@ void otaUpdateStop() if (settings.debugFirmwareUpdate) systemPrintln("Firmware update releasing network request"); - online.otaFirmwareUpdate = false; + online.otaClient = false; otaRequestFirmwareUpdate = false; // Let the network know we no longer need it @@ -854,6 +854,8 @@ void otaUpdate() otaReportedVersion[0] = 0; if (otaCheckVersion(otaReportedVersion, sizeof(otaReportedVersion))) { + online.otaClient = true; + // Create a string of the unit's current firmware version char currentVersion[21]; getFirmwareVersion(currentVersion, sizeof(currentVersion), enableRCFirmware); @@ -916,4 +918,10 @@ void otaVerifyTables() reportFatalError("Fix otaStateNames table to match OtaState"); } +bool otaNeedsNetwork() +{ + if (httpClientState >= OTA_STATE_WAIT_FOR_NETWORK && httpClientState <= OTA_STATE_UPDATE_FIRMWARE) + return true; + return false; +} #endif // COMPILE_OTA_AUTO diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index 4d6f4b6c8..af81423e5 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -1232,7 +1232,15 @@ void provisioningSetState(uint8_t newState) unsigned long provisioningStartTime_millis; const unsigned long provisioningTimeout_ms = 120000; -void updateProvisioning() +// Return true if we are in states that require network access +bool provisioningNeedsNetwork() +{ + if (provisioningState >= PROVISIONING_WAIT_FOR_NETWORK && provisioningState <= PROVISIONING_STARTED) + return true; + return false; +} + +void provisioningUpdate() { // Skip if in configure-via-ethernet mode if (configureViaEthernet) @@ -1253,17 +1261,15 @@ void updateProvisioning() } break; case PROVISIONING_WAIT_RTC: { - if ((online.rtc) - // If RTC is not online after provisioningTimeout_ms, try to provision anyway - || (millis() > (provisioningStartTime_millis + provisioningTimeout_ms)) || (settings.requestKeyUpdate)) + // If RTC is not online after provisioningTimeout_ms, try to provision anyway + if ((online.rtc) || (millis() > (provisioningStartTime_millis + provisioningTimeout_ms)) || + (settings.requestKeyUpdate)) provisioningSetState(PROVISIONING_NOT_STARTED); } break; case PROVISIONING_NOT_STARTED: { if (settings.enablePointPerfectCorrections && (settings.autoKeyRenewal || settings.requestKeyUpdate)) - { provisioningSetState(PROVISIONING_CHECK_REMAINING); - } } break; case PROVISIONING_CHECK_REMAINING: { diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index f9695d148..50b8c2411 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -653,7 +653,7 @@ void menuDebugNetwork() systemPrintf("%s\r\n", settings.debugWifiState ? "Enabled" : "Disabled"); // WiFi Config - systemPrint("4) Debug Web Config: "); + systemPrint("4) Debug Web Server: "); systemPrintf("%s\r\n", settings.debugWebServer ? "Enabled" : "Disabled"); // Network diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index c424d8639..7c4742c42 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -1813,7 +1813,7 @@ struct struct_online bool mqttClient = false; bool ntripClient = false; bool ntripServer[NTRIP_SERVER_MAX] = {false, false, false, false}; - bool otaFirmwareUpdate = false; + bool otaClient = false; bool ppl = false; bool psram = false; bool rtc = false; From bd10ce65d0cbc9ff883152da4ab2bca7911c755f Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 11:54:55 -0700 Subject: [PATCH 044/276] Fix typo --- Firmware/RTK_Everywhere/NtripClient.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/NtripClient.ino b/Firmware/RTK_Everywhere/NtripClient.ino index 28a0a00e5..6aafb6ffa 100644 --- a/Firmware/RTK_Everywhere/NtripClient.ino +++ b/Firmware/RTK_Everywhere/NtripClient.ino @@ -556,7 +556,7 @@ void ntripClientUpdate() switch (ntripClientState) { case NTRIP_CLIENT_OFF: - // Don't allow the client to restart if a forced shutdown occured + // Don't allow the client to restart if a forced shutdown occurred if (ntripClientForcedShutdown == false && EQ_RTK_MODE(ntripClientMode) && settings.enableNtripClient) ntripClientStart(); break; From a182041d6ecb5af204f3abdc0993d07548f0a1e3 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 11:55:24 -0700 Subject: [PATCH 045/276] Move state machine updates above network control --- Firmware/RTK_Everywhere/Network.ino | 49 +++++++++++++---------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 8bc1614b8..4e32f6011 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1367,15 +1367,30 @@ void networkUpdate() uint8_t priority; NETWORK_POLL_SEQUENCE *sequence; - int consumerCount = networkConsumers(); + // Update the network services + DMW_c("mqttClientUpdate"); + mqttClientUpdate(); // Process any Point Perfect MQTT messages + DMW_c("ntpServerUpdate"); + ntpServerUpdate(); // Process any received NTP requests + DMW_c("ntripClientUpdate"); + ntripClientUpdate(); // Check the NTRIP client connection and move data NTRIP --> ZED + DMW_c("ntripServerUpdate"); + ntripServerUpdate(); // Check the NTRIP server connection and move data ZED --> NTRIP + DMW_c("tcpClientUpdate"); + tcpClientUpdate(); // Turn on the TCP client as needed + DMW_c("tcpServerUpdate"); + tcpServerUpdate(); // Turn on the TCP server as needed + DMW_c("udpServerUpdate"); + udpServerUpdate(); // Turn on the UDP server as needed + DMW_c("httpClientUpdate"); + httpClientUpdate(); // Process any Point Perfect HTTP messages + DMW_c("webServerUpdate"); + webServerUpdate(); // Start webServer for web config as needed - uint16_t consumerTypes = networkGetConsumerTypes(); + //Once services have been updated, determine if the network needs to be started/stopped - // If there are no consumers, do not start the network - if (consumerCount == 0 && networkIsOnline() == false) - { - return; - } + int consumerCount = networkConsumers(); + uint16_t consumerTypes = networkGetConsumerTypes(); // If there are no consumers, but the network is online, shut down all networks if (consumerCount == 0 && networkIsOnline() == true) @@ -1465,26 +1480,6 @@ void networkUpdate() } } - // Update the network services - DMW_c("mqttClientUpdate"); - mqttClientUpdate(); // Process any Point Perfect MQTT messages - DMW_c("ntpServerUpdate"); - ntpServerUpdate(); // Process any received NTP requests - DMW_c("ntripClientUpdate"); - ntripClientUpdate(); // Check the NTRIP client connection and move data NTRIP --> ZED - DMW_c("ntripServerUpdate"); - ntripServerUpdate(); // Check the NTRIP server connection and move data ZED --> NTRIP - DMW_c("tcpClientUpdate"); - tcpClientUpdate(); // Turn on the TCP client as needed - DMW_c("tcpServerUpdate"); - tcpServerUpdate(); // Turn on the TCP server as needed - DMW_c("udpServerUpdate"); - udpServerUpdate(); // Turn on the UDP server as needed - DMW_c("httpClientUpdate"); - httpClientUpdate(); // Process any Point Perfect HTTP messages - DMW_c("webServerUpdate"); - webServerUpdate(); // Start webServer for web config as needed - // Periodically display the network interface state displayIpAddress = PERIODIC_DISPLAY(PD_IP_ADDRESS); for (int index = 0; index < NETWORK_OFFLINE; index++) From 7e097b0724e584a298b3014048d7e4e25d74a740 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 12:24:48 -0700 Subject: [PATCH 046/276] Fix otaState check --- Firmware/RTK_Everywhere/menuFirmware.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index 412e42124..2ef9cb712 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -920,7 +920,7 @@ void otaVerifyTables() bool otaNeedsNetwork() { - if (httpClientState >= OTA_STATE_WAIT_FOR_NETWORK && httpClientState <= OTA_STATE_UPDATE_FIRMWARE) + if (otaState >= OTA_STATE_WAIT_FOR_NETWORK && otaState <= OTA_STATE_UPDATE_FIRMWARE) return true; return false; } From ce8eb444c2e6b146aad027338659db4e3ee46045 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 14:17:16 -0700 Subject: [PATCH 047/276] Update comments --- Firmware/RTK_Everywhere/Network.ino | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 4e32f6011..d4737853f 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1387,7 +1387,7 @@ void networkUpdate() DMW_c("webServerUpdate"); webServerUpdate(); // Start webServer for web config as needed - //Once services have been updated, determine if the network needs to be started/stopped + // Once services have been updated, determine if the network needs to be started/stopped int consumerCount = networkConsumers(); uint16_t consumerTypes = networkGetConsumerTypes(); @@ -1395,6 +1395,9 @@ void networkUpdate() // If there are no consumers, but the network is online, shut down all networks if (consumerCount == 0 && networkIsOnline() == true) { + if (settings.debugNetworkLayer) + systemPrintln("Stopping all networks because there are no consumers"); + // Shutdown all networks for (int index = 0; index < NETWORK_OFFLINE; index++) networkStop(index, settings.debugNetworkLayer); @@ -1514,9 +1517,11 @@ void networkUpdate() } } -// Return the bitfield containing +// Return the bitfield containing the type of consumers currently using the network uint16_t networkGetConsumerTypes() { + networkConsumers(); // Updates networkConsumerTypes + return (networkConsumerTypes); } @@ -1532,7 +1537,7 @@ uint8_t networkConsumers() previousNetworkConsumerTypes = networkConsumerTypes; networkConsumerTypes = NETCONSUMER_NONE; // Clear bitfield - // If a consumer is waiting for the network, or is currently consuming the network (is online) then increment + // If a consumer needs the network or is currently consuming the network (is online) then increment // consumer count // Network needed for NTRIP Client From 58e0d208c92f55857f55b68cf5b6b39a37a68c9e Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 14:17:50 -0700 Subject: [PATCH 048/276] Remove network logic from wifiConnect --- Firmware/RTK_Everywhere/WiFi.ino | 47 ++++++++++++++------------------ 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index d5d0ce66f..cf52a98fc 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -157,35 +157,20 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) wifi_mode_t wifiMode = WIFI_OFF; wifi_interface_t wifiInterface = WIFI_IF_STA; - if (networkGetConsumerTypes() == NETCONSUMER_ANY) - { - if (settings.debugWifiState == true) - systemPrintln("Starting WiFi Station due to NETCONSUMER_ANY"); - else - systemPrintln("Starting WiFi Station"); - wifiMode = WIFI_STA; - wifiInterface = WIFI_IF_STA; - } - - // See if consumers are calling for AP+STA directly, or AP and STA individually - else if ((networkGetConsumerTypes() && (1 << NETCONSUMER_WIFI_AP_STA)) || - (networkGetConsumerTypes() && ((1 << NETCONSUMER_WIFI_AP) || (1 << NETCONSUMER_WIFI_STA)))) + // Establish what WiFi mode we need to be in + if (startWiFiStation && startWiFiAP) { systemPrintln("Starting WiFi AP+Station"); wifiMode = WIFI_AP_STA; wifiInterface = WIFI_IF_AP; // There is no WIFI_IF_AP_STA } - - else if (networkGetConsumerTypes() && (1 << NETCONSUMER_WIFI_STA)) + else if (startWiFiStation) { - if (settings.debugWifiState == true) - systemPrintln("Starting WiFi Station due to NETCONSUMER_WIFI_STA"); - else - systemPrintln("Starting WiFi Station"); + systemPrintln("Starting WiFi Station"); wifiMode = WIFI_STA; wifiInterface = WIFI_IF_STA; } - else if (networkGetConsumerTypes() && (1 << NETCONSUMER_WIFI_AP)) + else if (startWiFiAP) { systemPrintln("Starting WiFi AP"); wifiMode = WIFI_AP; @@ -534,31 +519,39 @@ bool wifiForceStart() // Determine if WiFi is already running if (!wifiRunning) { - if (settings.debugWifiState == true) - systemPrintln("Starting WiFi"); - // Determine which parts of WiFi need to be started bool startWiFiStation = false; bool startWiFiAP = false; + uint16_t consumerTypes = networkGetConsumerTypes(); + // Only one bit is set, WiFi Station is default - if (networkGetConsumerTypes() == (1 << NETCONSUMER_ANY)) + if (consumerTypes == (1 << NETCONSUMER_ANY)) + { startWiFiStation = true; + } // The consumers need both - else if (networkGetConsumerTypes() & ((1 << NETCONSUMER_WIFI_AP) | (1 << NETCONSUMER_WIFI_STA))) + else if (consumerTypes & ((1 << NETCONSUMER_WIFI_AP) | (1 << NETCONSUMER_WIFI_STA))) { startWiFiStation = true; startWiFiAP = true; } // The consumers need station - else if (networkGetConsumerTypes() & (1 << NETCONSUMER_WIFI_STA)) + else if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) + { startWiFiStation = true; + } // The consumers need AP - else if (networkGetConsumerTypes() & (1 << NETCONSUMER_WIFI_AP)) + else if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) + { startWiFiAP = true; + } + + else + systemPrintln("wifiForceStart(): Unknown NETCONSUMER combination"); // Start WiFi if (wifiConnect(startWiFiStation, startWiFiAP, settings.wifiConnectTimeoutMs)) From 3e9e91f217cb0f0d30b64ec990eea96306d2d2ce Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 14:21:13 -0700 Subject: [PATCH 049/276] Remove the creation of settings string when sockets are stopped --- Firmware/RTK_Everywhere/WebServer.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index c0ad9ab6f..ab52b9dff 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -568,7 +568,6 @@ bool webServerNeedsNetwork() void webServerStopSockets() { - createSettingsString(settingsCSV); websocketConnected = false; if (*wsserver) From 0fd577183260e5920d0008fd24db566ff8b428b4 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 16:24:16 -0700 Subject: [PATCH 050/276] Update comments --- Firmware/RTK_Everywhere/WebServer.ino | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index ab52b9dff..9e07b5992 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -249,16 +249,11 @@ class CaptiveRequestHandler : public RequestHandler } }; -// Start the webServer +// Create the web server and web sockets bool webServerAssignResources(int httpPort = 80) { do { - // TODO Do we need to stop NTRIP Clients? Let them run while Web Config is running? - // ntripClientStop(true); // Do not allocate new wifiClient - // for (int serverIndex = 0; serverIndex < NTRIP_SERVER_MAX; serverIndex++) - // ntripServerStop(serverIndex, true); // Do not allocate new wifiClient - // TODO DNS should be started/stopped at the network layer // // Start the multicast DNS server // if (startWiFi == true) @@ -744,18 +739,6 @@ void webServerReleaseResources() // State machine to handle the starting/stopping of the web server void webServerUpdate() { - // Shutdown the Web Server setting changes - // if (settings.enableNtripClient == false) - // { - // if (ntripClientState > NTRIP_CLIENT_OFF) - // { - // ntripClientStop(true); // Was false - #StopVsRestart - // ntripClientConnectionAttempts = 0; - // ntripClientConnectionAttemptTimeout = 0; - // ntripClientSetState(NTRIP_CLIENT_OFF); - // } - // } - // Walk the state machine switch (webServerState) { @@ -788,7 +771,7 @@ void webServerUpdate() if (!networkIsConnected(&webServerPriority)) webServerStop(); if (settings.debugWebServer) - systemPrintln("Starting web server"); + systemPrintln("Assigning web server resources"); if (webServerAssignResources(settings.httpPort) == true) { From 018e22f68fb45d993ede25e0ef8537f8a8149988 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 16:24:43 -0700 Subject: [PATCH 051/276] Mark network online if AP start successful --- Firmware/RTK_Everywhere/WiFi.ino | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index cf52a98fc..cac168283 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -508,14 +508,6 @@ bool wifiForceStart() { int wifiStatus; - if (wifiNetworkCount() == 0) - { - systemPrintln("Error: Please enter at least one SSID before using WiFi"); - displayNoSSIDs(2000); - WIFI_STOP(); - return false; - } - // Determine if WiFi is already running if (!wifiRunning) { @@ -532,7 +524,7 @@ bool wifiForceStart() } // The consumers need both - else if (consumerTypes & ((1 << NETCONSUMER_WIFI_AP) | (1 << NETCONSUMER_WIFI_STA))) + else if ((consumerTypes & (1 << NETCONSUMER_WIFI_AP)) && (consumerTypes & (1 << NETCONSUMER_WIFI_STA))) { startWiFiStation = true; startWiFiAP = true; @@ -553,6 +545,23 @@ bool wifiForceStart() else systemPrintln("wifiForceStart(): Unknown NETCONSUMER combination"); + if (wifiNetworkCount() == 0) + { + if (startWiFiStation == true && startWiFiAP == false) + { + systemPrintln("Error: Please enter at least one SSID before using WiFi"); + displayNoSSIDs(2000); + WIFI_STOP(); + return false; + } + else if (startWiFiStation == true && startWiFiAP == true) + { + systemPrintln("Error: No SSID available to start WiFi Station during AP"); + // Allow the system to continue in AP only mode + startWiFiStation = false; + } + } + // Start WiFi if (wifiConnect(startWiFiStation, startWiFiAP, settings.wifiConnectTimeoutMs)) { @@ -562,9 +571,12 @@ bool wifiForceStart() } } - // If we are in AP only mode, as long as the AP is started, returned true + // If we are in AP only mode, as long as the AP is started, return true if (WiFi.getMode() == WIFI_MODE_AP) + { + networkMarkOnline(NETWORK_WIFI); return (true); + } // If we are in STA or AP+STA mode, return if the station connected successfully wifiStatus = WiFi.status(); From 91dd88f10b99636f1e9b4881fe4a689efceb5248 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 16:26:00 -0700 Subject: [PATCH 052/276] Remove globals --- Firmware/RTK_Everywhere/Network.ino | 54 +++++++++++++++++++---------- Firmware/RTK_Everywhere/settings.h | 3 -- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index d4737853f..4d9d9ddb1 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1389,8 +1389,10 @@ void networkUpdate() // Once services have been updated, determine if the network needs to be started/stopped - int consumerCount = networkConsumers(); - uint16_t consumerTypes = networkGetConsumerTypes(); + static uint16_t previousConsumerTypes = NETCONSUMER_NONE; + static uint16_t consumerTypes = NETCONSUMER_NONE; + + int consumerCount = networkConsumers(&consumerTypes); // Update the current consumer types // If there are no consumers, but the network is online, shut down all networks if (consumerCount == 0 && networkIsOnline() == true) @@ -1405,8 +1407,10 @@ void networkUpdate() // If the consumers have indicated a network type change (ie, must have WiFi AP even though STA is connected) // then stop all networks and let the lower code restart the network accordingly - if (networkConsumerTypes != previousNetworkConsumerTypes) + if (consumerTypes != previousConsumerTypes) { + previousConsumerTypes = networkGetConsumerTypes(); // Update the previous consumer types + // if (networkConsumersOnline() > 0 && networkShutdownRequest == false) // { // // Tell consumers to shut down @@ -1424,6 +1428,10 @@ void networkUpdate() for (int index = 0; index < NETWORK_OFFLINE; index++) networkStop(index, settings.debugNetworkLayer); // } + + // Once we've stopped the networks, we need to update all the services to correctly mark any consumer types + // As it stands, the types are still residual from before the network stop + // } // Allow consumers to start networks @@ -1520,22 +1528,30 @@ void networkUpdate() // Return the bitfield containing the type of consumers currently using the network uint16_t networkGetConsumerTypes() { - networkConsumers(); // Updates networkConsumerTypes + uint16_t consumerTypes = 0; + + networkConsumers(&consumerTypes); - return (networkConsumerTypes); + return (consumerTypes); } // Return the count of consumers (TCP, NTRIP Client, etc) that are enabled -// and set networkConsumerTypes bitfield +// and set consumerTypes bitfield // From this number we can decide if the network (WiFi, ethernet, cellular, etc) needs to be started // ESP-NOW is not considered a network consumer and is blended during wifiConnect() uint8_t networkConsumers() +{ + uint16_t consumerTypes = 0; + + return (networkConsumers(&consumerTypes)); +} + +uint8_t networkConsumers(uint16_t *consumerTypes) { uint8_t consumerCount = 0; uint16_t consumerId = 0; // Used to debug print who is asking for access - previousNetworkConsumerTypes = networkConsumerTypes; - networkConsumerTypes = NETCONSUMER_NONE; // Clear bitfield + *consumerTypes = NETCONSUMER_NONE; // Clear bitfield // If a consumer needs the network or is currently consuming the network (is online) then increment // consumer count @@ -1545,7 +1561,7 @@ uint8_t networkConsumers() { consumerCount++; consumerId |= (1 << 0); - networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for NTRIP Server @@ -1565,7 +1581,7 @@ uint8_t networkConsumers() consumerId |= (1 << 1); // TODO - Base type. If AP then limit to NETCONSUMER_WIFI_AP - networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for TCP Client @@ -1573,7 +1589,7 @@ uint8_t networkConsumers() { consumerCount++; consumerId |= (1 << 2); - networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for TCP Server @@ -1581,7 +1597,7 @@ uint8_t networkConsumers() { consumerCount++; consumerId |= (1 << 3); - networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for UDP Server @@ -1589,7 +1605,7 @@ uint8_t networkConsumers() { consumerCount++; consumerId |= (1 << 4); - networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for PointPerfect ZTP or key update requested by scheduler, from menu, or display menu @@ -1597,7 +1613,7 @@ uint8_t networkConsumers() { consumerCount++; consumerId |= (1 << 5); - networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed for PointPerfect Corrections MQTT client @@ -1606,7 +1622,7 @@ uint8_t networkConsumers() // PointPerfect is enabled, allow MQTT to begin consumerCount++; consumerId |= (1 << 6); - networkConsumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access } // Network needed to obtain the latest firmware version or do a firmware update @@ -1614,7 +1630,7 @@ uint8_t networkConsumers() { consumerCount++; consumerId |= (1 << 7); - networkConsumerTypes |= (1 << NETCONSUMER_WIFI_STA); // OTA Pull library only supports WiFi + *consumerTypes |= (1 << NETCONSUMER_WIFI_STA); // OTA Pull library only supports WiFi } // Network needed for Web Config @@ -1623,10 +1639,12 @@ uint8_t networkConsumers() consumerCount++; consumerId |= (1 << 8); + // The web server takes precedence over other network consumers so that we can start in AP mode only as needed + // TODO Make web server over ethernet work here as well if (settings.wifiConfigOverAP == true) - networkConsumerTypes |= (1 << NETCONSUMER_WIFI_AP); // + *consumerTypes = (1 << NETCONSUMER_WIFI_AP); // Force into AP only mode else - networkConsumerTypes |= (1 << NETCONSUMER_WIFI_STA); // + *consumerTypes = (1 << NETCONSUMER_WIFI_STA); // Force into STA only mode } // Debug diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 7c4742c42..b231bdfc9 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -564,7 +564,6 @@ enum WebServerState WEBSERVER_STATE_OFF = 0, WEBSERVER_STATE_WAIT_FOR_NETWORK, WEBSERVER_STATE_NETWORK_CONNECTED, - WEBSERVER_STATE_STARTED, WEBSERVER_STATE_RUNNING, // Add new states here @@ -622,8 +621,6 @@ enum NETCONSUMER_ANY, // The consumer doesn't care what type of network access is granted NETCONSUMER_UNKNOWN }; -uint16_t networkConsumerTypes = NETCONSUMER_NONE; -uint16_t previousNetworkConsumerTypes = NETCONSUMER_NONE; // This is all the settings that can be set on RTK Product. It's recorded to NVM and the config file. // Avoid reordering. The order of these variables is mimicked in NVM/record/parse/create/update/get From 2861aa9ef39f03165e08f3d29b6997d894ba43e1 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 16:26:04 -0700 Subject: [PATCH 053/276] Update Developer.ino --- Firmware/RTK_Everywhere/Developer.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 40bd860c9..519699165 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -70,7 +70,7 @@ void ntripClientValidateTables() {} void ntripServerPrintStatus(int serverIndex) {systemPrintf("**NTRIP Server %d not compiled**\r\n", serverIndex);} void ntripServerProcessRTCM(int serverIndex, uint8_t incoming) {} -void ntripServerStop(int serverIndex, bool clientAllocated) {online.ntripServer[serverIndex] = false;} +void ntripServerStop(int serverIndex, bool shutdown) {online.ntripServer[serverIndex] = false;} void ntripServerUpdate() {} void ntripServerValidateTables() {} bool ntripServerIsCasting(int serverIndex) { From d0ccd686256f13dbc671c968e8f03a83dd9a13d7 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 16:43:19 -0700 Subject: [PATCH 054/276] Move state machine states into INOs --- Firmware/RTK_Everywhere/WebServer.ino | 26 ++++++++++++------- Firmware/RTK_Everywhere/menuFirmware.ino | 19 +++++++++++--- Firmware/RTK_Everywhere/settings.h | 33 ------------------------ 3 files changed, 32 insertions(+), 46 deletions(-) diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index 9e07b5992..56aa5b766 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -6,6 +6,19 @@ Form.ino #ifdef COMPILE_AP + +// State machine to allow web server access to network layer +enum WebServerState +{ + WEBSERVER_STATE_OFF = 0, + WEBSERVER_STATE_WAIT_FOR_NETWORK, + WEBSERVER_STATE_NETWORK_CONNECTED, + WEBSERVER_STATE_RUNNING, + + // Add new states here + WEBSERVER_STATE_MAX +}; + static const char *const webServerStateNames[] = { "WEBSERVER_STATE_OFF", "WEBSERVER_STATE_WAIT_FOR_NETWORK", @@ -16,7 +29,7 @@ static const char *const webServerStateNames[] = { static const int webServerStateEntries = sizeof(webServerStateNames) / sizeof(webServerStateNames[0]); static NetPriority_t webServerPriority = NETWORK_OFFLINE; -static WebServerState webServerState; +static uint8_t webServerState; // Once connected to the access point for WiFi Config, the ESP32 sends current setting values in one long string to // websocket After user clicks 'save', data is validated via main.js and a long string of values is returned. @@ -254,13 +267,6 @@ bool webServerAssignResources(int httpPort = 80) { do { - // TODO DNS should be started/stopped at the network layer - // // Start the multicast DNS server - // if (startWiFi == true) - // networkMulticastDNSSwitch(NETWORK_WIFI); - // else - // networkMulticastDNSSwitch(NETWORK_ETHERNET); - // Freed by webServerStop if (online.psram == true) incomingSettings = (char *)ps_malloc(AP_CONFIG_SETTING_SIZE); @@ -574,7 +580,7 @@ void webServerStopSockets() } // Set the next webconfig state -void webServerSetState(WebServerState newState) +void webServerSetState(uint8_t newState) { char string1[40]; char string2[40]; @@ -625,7 +631,7 @@ void webServerSetState(WebServerState newState) } // Get the webconfig state name -const char *webServerGetStateName(WebServerState state, char *string) +const char *webServerGetStateName(uint8_t state, char *string) { if (state < WEBSERVER_STATE_MAX) return webServerStateNames[state]; diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index 2ef9cb712..05871b922 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -10,6 +10,19 @@ menuFirmware.ino #ifdef COMPILE_OTA_AUTO +// Automatic over-the-air (OTA) firmware update support +enum OtaState +{ + OTA_STATE_OFF = 0, + OTA_STATE_WAIT_FOR_NETWORK, + OTA_STATE_GET_FIRMWARE_VERSION, + OTA_STATE_CHECK_FIRMWARE_VERSION, + OTA_STATE_UPDATE_FIRMWARE, + + // Add new states here + OTA_STATE_MAX +}; + static const char *const otaStateNames[] = {"OTA_STATE_OFF", "OTA_STATE_WAIT_FOR_NETWORK", "OTA_STATE_GET_FIRMWARE_VERSION", "OTA_STATE_CHECK_FIRMWARE_VERSION", "OTA_STATE_UPDATE_FIRMWARE"}; @@ -21,7 +34,7 @@ static const int otaStateEntries = sizeof(otaStateNames) / sizeof(otaStateNames[ static uint32_t otaLastUpdateCheck; static NetPriority_t otaPriority = NETWORK_OFFLINE; -static OtaState otaState; +static uint8_t otaState; #endif // COMPILE_OTA_AUTO @@ -703,7 +716,7 @@ int mapMonthName(char *mmm) #ifdef COMPILE_OTA_AUTO // Get the OTA state name -const char *otaGetStateName(OtaState state, char *string) +const char *otaGetStateName(uint8_t state, char *string) { if (state < OTA_STATE_MAX) return otaStateNames[state]; @@ -712,7 +725,7 @@ const char *otaGetStateName(OtaState state, char *string) } // Set the next OTA state -void otaSetState(OtaState newState) +void otaSetState(uint8_t newState) { char string1[40]; char string2[40]; diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index b231bdfc9..bc6750f57 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -539,39 +539,6 @@ const measurementScaleEntry measurementScaleTable[] = { }; const int measurementScaleEntries = sizeof(measurementScaleTable) / sizeof(measurementScaleTable[0]); -#ifdef COMPILE_OTA_AUTO - -// Automatic over-the-air (OTA) firmware update support -enum OtaState -{ - OTA_STATE_OFF = 0, - OTA_STATE_WAIT_FOR_NETWORK, - OTA_STATE_GET_FIRMWARE_VERSION, - OTA_STATE_CHECK_FIRMWARE_VERSION, - OTA_STATE_UPDATE_FIRMWARE, - - // Add new states here - OTA_STATE_MAX -}; - -#endif // COMPILE_OTA_AUTO - -#ifdef COMPILE_AP - -// State machine to allow web server access to network layer -enum WebServerState -{ - WEBSERVER_STATE_OFF = 0, - WEBSERVER_STATE_WAIT_FOR_NETWORK, - WEBSERVER_STATE_NETWORK_CONNECTED, - WEBSERVER_STATE_RUNNING, - - // Add new states here - WEBSERVER_STATE_MAX -}; - -#endif // COMPILE_AP - // Regional Support // Some regions have both L-Band and IP. More just have IP. // Do we want the user to be able to specify which region they are in? From a4df5c3bcd8b5386affbd28799fd3172bef333b8 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 16:47:36 -0700 Subject: [PATCH 055/276] Allow UART task to run during WebConfig --- Firmware/RTK_Everywhere/States.ino | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 533608acd..88b58da2d 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -418,12 +418,18 @@ void stateUpdate() baseStatusLedOff(); // Turn off the status LED - displayWiFiConfigNotStarted(); // Display immediately during SD cluster pause + displayWiFiConfigNotStarted(); // Display immediately while we wait for server to start // TODO - Do we need to stop BT and ESP-NOW during web config or can we leave it running? - bluetoothStop(); - espnowStop(); - tasksStopGnssUart(); // Delete serial tasks if running + //bluetoothStop(); + //espnowStop(); + + //tasksStopGnssUart(); // Delete serial tasks if running + + // Stop any running NTRIP Client or Server + ntripClientStop(true); // Do not allocate new wifiClient + for (int serverIndex = 0; serverIndex < NTRIP_SERVER_MAX; serverIndex++) + ntripServerStop(serverIndex, true); // Do not allocate new wifiClient webServerStart(); // Start the webserver state machine for web config From 738aff67758b057de94f9c9f677877d1fb505824 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 27 Dec 2024 16:47:54 -0700 Subject: [PATCH 056/276] Add DNS note --- Firmware/RTK_Everywhere/Network.ino | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 4d9d9ddb1..e111e34ae 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1428,10 +1428,6 @@ void networkUpdate() for (int index = 0; index < NETWORK_OFFLINE; index++) networkStop(index, settings.debugNetworkLayer); // } - - // Once we've stopped the networks, we need to update all the services to correctly mark any consumer types - // As it stands, the types are still residual from before the network stop - // } // Allow consumers to start networks @@ -1450,12 +1446,14 @@ void networkUpdate() systemPrintln("Starting WiFi Specific Network"); networkStart(NETWORK_WIFI, settings.debugNetworkLayer); + //networkMulticastDNSSwitch(NETWORK_WIFI); This should be taken care of by networkMarkOnline() } // We don't have this type of consumer yet but good to have... else if (consumerTypes && (1 << NETCONSUMER_ETHERNET)) { networkStart(NETWORK_ETHERNET, settings.debugNetworkLayer); + //networkMulticastDNSSwitch(NETWORK_ETHERNET); } // We don't have this type of consumer yet but good to have... From 49e4f38ae8b3edc8879fc7c74b4fc82078eaf346 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 30 Dec 2024 08:47:33 -0700 Subject: [PATCH 057/276] Fix PPS pin on Postcard Fix #508 --- Firmware/RTK_Everywhere/Begin.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Begin.ino b/Firmware/RTK_Everywhere/Begin.ino index 086e33551..ea70c0923 100644 --- a/Firmware/RTK_Everywhere/Begin.ino +++ b/Firmware/RTK_Everywhere/Begin.ino @@ -709,14 +709,14 @@ void beginBoard() pin_GnssUart_TX = 22; pin_GNSS_Reset = 33; - pin_GNSS_TimePulse = 8; // PPS on LG290P + pin_GNSS_TimePulse = 36; // PPS on LG290P pin_SCK = 32; pin_POCI = 25; pin_PICO = 26; pin_microSD_CS = 27; - pin_gpioExpanderInterrupt = 14; // Pin 'AOI' on Portability Shield + pin_gpioExpanderInterrupt = 14; // Pin 'AOI' (Analog Output Input) on Portability Shield pin_bluetoothStatusLED = 4; // Blue LED pin_gnssStatusLED = 0; // Green LED From a19d54f69896dae5cde8a0abccbbdb895be19dc9 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 30 Dec 2024 13:35:25 -0700 Subject: [PATCH 058/276] Rename udpServerNeedsNetwork --- Firmware/RTK_Everywhere/Network.ino | 2 +- Firmware/RTK_Everywhere/UdpServer.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index e111e34ae..1fcbbff7b 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1599,7 +1599,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) } // Network needed for UDP Server - if (udpServerIsWaitingForNetwork() || online.udpServer) + if (udpServerNeedsNetwork() || online.udpServer) { consumerCount++; consumerId |= (1 << 4); diff --git a/Firmware/RTK_Everywhere/UdpServer.ino b/Firmware/RTK_Everywhere/UdpServer.ino index 4fd544e4e..033e3ceb1 100644 --- a/Firmware/RTK_Everywhere/UdpServer.ino +++ b/Firmware/RTK_Everywhere/UdpServer.ino @@ -277,7 +277,7 @@ void udpServerStop() } // Return true if we are in a state that requires network access -bool udpServerIsWaitingForNetwork() +bool udpServerNeedsNetwork() { if (udpServerState >= UDP_SERVER_STATE_WAIT_FOR_NETWORK && udpServerState <= UDP_SERVER_STATE_RUNNING) return true; From 350bcbb07e4c1a05703c77fa523088a9d336f95d Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 2 Jan 2025 12:59:12 -0700 Subject: [PATCH 059/276] Update from RC --- .github/workflows/compile-rtk-everywhere.yml | 3 +- .github/workflows/non-release-build.yml | 22 ++-- Firmware/RTK_Everywhere/Begin.ino | 9 +- Firmware/RTK_Everywhere/Bluetooth.ino | 46 ++++--- Firmware/RTK_Everywhere/GNSS_LG290P.h | 2 +- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 42 +++--- Firmware/RTK_Everywhere/GNSS_Mosaic.h | 6 + Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 74 +++++++++-- Firmware/RTK_Everywhere/Network.ino | 124 ++++++++++++++++++ Firmware/RTK_Everywhere/RTK_Everywhere.ino | 1 - Firmware/RTK_Everywhere/States.ino | 10 ++ Firmware/RTK_Everywhere/Tasks.ino | 25 ++-- Firmware/RTK_Everywhere/TcpServer.ino | 72 ++++++++-- Firmware/RTK_Everywhere/bluetoothSelect.h | 2 +- Firmware/RTK_Everywhere/form.h | 4 +- Firmware/RTK_Everywhere/menuCommands.ino | 5 +- Firmware/RTK_Everywhere/menuFirmware.ino | 7 + Firmware/RTK_Everywhere/menuPP.ino | 15 +-- Firmware/RTK_Everywhere/menuSystem.ino | 19 ++- Firmware/RTK_Everywhere/settings.h | 10 +- .../src/BluetoothSerial/BluetoothSerial.cpp | 8 +- 21 files changed, 393 insertions(+), 113 deletions(-) diff --git a/.github/workflows/compile-rtk-everywhere.yml b/.github/workflows/compile-rtk-everywhere.yml index 3ddb27a1d..46a055a5d 100644 --- a/.github/workflows/compile-rtk-everywhere.yml +++ b/.github/workflows/compile-rtk-everywhere.yml @@ -6,7 +6,7 @@ on: env: FILENAME_PREFIX: RTK_Everywhere_Firmware FIRMWARE_VERSION_MAJOR: 2 - FIRMWARE_VERSION_MINOR: 0 + FIRMWARE_VERSION_MINOR: 1 POINTPERFECT_LBAND_TOKEN: ${{ secrets.POINTPERFECT_LBAND_TOKEN }} POINTPERFECT_IP_TOKEN: ${{ secrets.POINTPERFECT_IP_TOKEN }} POINTPERFECT_LBAND_IP_TOKEN: ${{ secrets.POINTPERFECT_LBAND_IP_TOKEN }} @@ -140,6 +140,7 @@ jobs: - name: Copy custom RTKEverywhere.csv run: + # Use the 16MB partitions by default. 8MB (Postcard) partitions must be compiled separately cp Firmware/RTKEverywhere.csv /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/tools/partitions/RTKEverywhere.csv - name: Compile Sketch diff --git a/.github/workflows/non-release-build.yml b/.github/workflows/non-release-build.yml index 9e82f6fd3..5b3a39881 100644 --- a/.github/workflows/non-release-build.yml +++ b/.github/workflows/non-release-build.yml @@ -10,7 +10,7 @@ env: POINTPERFECT_LBAND_TOKEN: ${{ secrets.POINTPERFECT_LBAND_TOKEN }} POINTPERFECT_IP_TOKEN: ${{ secrets.POINTPERFECT_IP_TOKEN }} POINTPERFECT_LBAND_IP_TOKEN: ${{ secrets.POINTPERFECT_LBAND_IP_TOKEN }} - CORE_VERSION: 3.0.1 + CORE_VERSION: 3.0.7 jobs: build: @@ -78,7 +78,7 @@ jobs: run: arduino-cli lib install ArduinoJson@7.0.4 ESP32Time@2.0.0 - ESP32_BleSerial@1.0.4 + ESP32_BleSerial@2.0.1 "ESP32-OTA-Pull"@1.0.0 JC_Button@2.1.2 PubSubClient@2.8.0 @@ -88,18 +88,14 @@ jobs: "SparkFun u-blox GNSS v3"@3.1.8 "SparkFun Qwiic OLED Arduino Library"@1.0.13 SSLClientESP32@2.0.0 - "SparkFun Extensible Message Parser"@1.0.0 + "SparkFun Extensible Message Parser"@1.0.2 "SparkFun BQ40Z50 Battery Manager Arduino Library"@1.0.0 "ArduinoMqttClient"@0.1.8 "SparkFun u-blox PointPerfect Library"@1.11.4 "SparkFun IM19 IMU Arduino Library"@1.0.1 "SparkFun UM980 Triband RTK GNSS Arduino Library"@1.0.4 - - # https://github.com/avinabmalla/ESP32_BleSerial/issues/15 - - name: Patch ESP32_BleSerial BLECharacteristic - run: | - cd Firmware/RTK_Everywhere/Patch/ - cp BleSerial.cpp /home/runner/Arduino/libraries/ESP32_BleSerial/src/BleSerial.cpp + "SparkFun LG290P Quadband RTK GNSS Arduino Library"@1.0.0 + "SparkFun I2C Expander Arduino Library"@1.0.1 - name: Patch libmbedtls run: | @@ -109,6 +105,11 @@ jobs: cp libmbedcrypto.a /home/runner/.arduino15/packages/esp32/tools/esp32-arduino-libs/${{ env.ESP_IDF }}/esp32/lib/libmbedcrypto.a cp libmbedx509.a /home/runner/.arduino15/packages/esp32/tools/esp32-arduino-libs/${{ env.ESP_IDF }}/esp32/lib/libmbedx509.a + - name: Patch NetworkEvents + run: | + cd Firmware/RTK_Everywhere/Patch/ + cp NetworkEvents.* /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/libraries/Network/src/ + - name: Setup Python uses: actions/setup-python@v4 with: @@ -139,12 +140,13 @@ jobs: - name: Copy custom RTKEverywhere.csv run: + # Use the 16MB partitions by default. 8MB (Postcard) partitions must be compiled separately cp Firmware/RTKEverywhere.csv /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/tools/partitions/RTKEverywhere.csv - name: Compile Sketch run: arduino-cli compile --fqbn "esp32:esp32:esp32":DebugLevel=${{ env.DEBUG_LEVEL }},PSRAM=enabled ./Firmware/RTK_Everywhere/RTK_Everywhere.ino --build-property build.partitions=RTKEverywhere - --build-property upload.maximum_size=3145728 + --build-property upload.maximum_size=4055040 --build-property "compiler.cpp.extra_flags=-MMD -c \"-DPOINTPERFECT_LBAND_TOKEN=$POINTPERFECT_LBAND_TOKEN\" \"-DPOINTPERFECT_IP_TOKEN=$POINTPERFECT_IP_TOKEN\" \"-DPOINTPERFECT_LBAND_IP_TOKEN=$POINTPERFECT_LBAND_IP_TOKEN\" \"-DFIRMWARE_VERSION_MAJOR=$FIRMWARE_VERSION_MAJOR\" \"-DFIRMWARE_VERSION_MINOR=$FIRMWARE_VERSION_MINOR\" \"-DENABLE_DEVELOPER=${{ env.ENABLE_DEVELOPER }}\"" --export-binaries diff --git a/Firmware/RTK_Everywhere/Begin.ino b/Firmware/RTK_Everywhere/Begin.ino index 556441465..ea70c0923 100644 --- a/Firmware/RTK_Everywhere/Begin.ino +++ b/Firmware/RTK_Everywhere/Begin.ino @@ -449,7 +449,6 @@ void beginBoard() present.display_i2c0 = true; present.display_type = DISPLAY_64x48; present.i2c0BusSpeed_400 = true; - present.button_mode = true; present.peripheralPowerControl = true; present.button_powerLow = true; // Button is pressed when low present.charger_mcp73833 = true; @@ -530,7 +529,6 @@ void beginBoard() present.display_i2c0 = true; present.display_type = DISPLAY_64x48; present.i2c0BusSpeed_400 = true; - present.button_mode = true; present.peripheralPowerControl = true; present.button_powerLow = true; // Button is pressed when low present.charger_mcp73833 = true; @@ -711,14 +709,14 @@ void beginBoard() pin_GnssUart_TX = 22; pin_GNSS_Reset = 33; - pin_GNSS_TimePulse = 8; // PPS on LG290P + pin_GNSS_TimePulse = 36; // PPS on LG290P pin_SCK = 32; pin_POCI = 25; pin_PICO = 26; pin_microSD_CS = 27; - pin_gpioExpanderInterrupt = 14; // Pin 'AOI' on Portability Shield + pin_gpioExpanderInterrupt = 14; // Pin 'AOI' (Analog Output Input) on Portability Shield pin_bluetoothStatusLED = 4; // Blue LED pin_gnssStatusLED = 0; // Green LED @@ -1061,8 +1059,7 @@ void pinGnssUartTask(void *pvParameters) // Reduce threshold value above which RX FIFO full interrupt is generated // Allows more time between when the UART interrupt occurs and when the FIFO buffer overruns - // serialGNSS->setRxFIFOFull(50); //Available in >v2.0.5 - uart_set_rx_full_threshold(2, settings.serialGNSSRxFullThreshold); // uart_num, threshold + serialGNSS->setRxFIFOFull(settings.serialGNSSRxFullThreshold); // Stop notification if (settings.printTaskStartStop) diff --git a/Firmware/RTK_Everywhere/Bluetooth.ino b/Firmware/RTK_Everywhere/Bluetooth.ino index 0d196ae67..a63de0f94 100644 --- a/Firmware/RTK_Everywhere/Bluetooth.ino +++ b/Firmware/RTK_Everywhere/Bluetooth.ino @@ -42,7 +42,7 @@ BTSerialInterface *bluetoothSerialBleCommands; // Second BLE serial for CLI inte #define BLE_COMMAND_RX_UUID "7e400002-b5a3-f393-e0a9-e50e24dcca9e" #define BLE_COMMAND_TX_UUID "7e400003-b5a3-f393-e0a9-e50e24dcca9e" -TaskHandle_t bluetoothCommandTaskHandle; // Task to monitor incoming CLI from BLE +TaskHandle_t bluetoothCommandTaskHandle = nullptr; // Task to monitor incoming CLI from BLE #endif // COMPILE_BT @@ -54,24 +54,32 @@ TaskHandle_t bluetoothCommandTaskHandle; // Task to monitor incoming CLI from BL void bluetoothUpdate() { #ifdef COMPILE_BT - if (bluetoothIsConnected() == true && bluetoothState == BT_NOTCONNECTED) + static uint32_t lastCheck = millis(); // Check if connected every 100ms + if (millis() > (lastCheck + 100)) { - systemPrintln("BT client connected"); - bluetoothState = BT_CONNECTED; - // LED is controlled by tickerBluetoothLedUpdate() + lastCheck = millis(); - btPrintEchoExit = false; // Reset the exiting of config menus and/or command modes - } + // If bluetoothState == BT_OFF, don't call bluetoothIsConnected() - if (bluetoothIsConnected() == false && bluetoothState == BT_CONNECTED) - { - systemPrintln("BT client disconnected"); + if ((bluetoothState == BT_NOTCONNECTED) && (bluetoothIsConnected())) + { + systemPrintln("BT client connected"); + bluetoothState = BT_CONNECTED; + // LED is controlled by tickerBluetoothLedUpdate() - btPrintEcho = false; - btPrintEchoExit = true; // Force exit all config menus and/or command modes - printEndpoint = PRINT_ENDPOINT_SERIAL; + btPrintEchoExit = false; // Reset the exiting of config menus and/or command modes + } - bluetoothState = BT_NOTCONNECTED; + else if ((bluetoothState == BT_CONNECTED) && (!bluetoothIsConnected())) + { + systemPrintln("BT client disconnected"); + + btPrintEcho = false; + btPrintEchoExit = true; // Force exit all config menus and/or command modes + printEndpoint = PRINT_ENDPOINT_SERIAL; + + bluetoothState = BT_NOTCONNECTED; + } } #endif // COMPILE_BT } @@ -199,7 +207,7 @@ uint8_t bluetoothCommandRead() } // Determine if data is available -bool bluetoothRxDataAvailable() +int bluetoothRxDataAvailable() { #ifdef COMPILE_BT if (settings.bluetoothRadioType == BLUETOOTH_RADIO_SPP_AND_BLE) @@ -217,20 +225,20 @@ bool bluetoothRxDataAvailable() return (0); #else // COMPILE_BT - return false; + return 0; #endif // COMPILE_BT } // Determine if data is available on the BLE Command interface -bool bluetoothCommandAvailable() +int bluetoothCommandAvailable() { #ifdef COMPILE_BT if (settings.bluetoothRadioType == BLUETOOTH_RADIO_SPP_AND_BLE || settings.bluetoothRadioType == BLUETOOTH_RADIO_BLE) return bluetoothSerialBleCommands->available(); - return (false); + return (0); #else // COMPILE_BT - return false; + return 0; #endif // COMPILE_BT } diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.h b/Firmware/RTK_Everywhere/GNSS_LG290P.h index 500a5b761..9c4b96db9 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.h +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.h @@ -154,7 +154,7 @@ class GNSS_LG290P : GNSS void debuggingEnable(); - bool disableSurveyIn(); + bool disableSurveyIn(bool saveAndReset); void enableGgaForNtrip(); diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index db91ea72a..0a6f4a818 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -37,7 +37,7 @@ void GNSS_LG290P::baseRtcmLowDataRate() settings.lg290pMessageRatesRTCMBase[x] = 0; settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-1005")] = - 10; // 1005 0.1Hz - Exclude antenna height + 10; // 1005 0.1Hz - Exclude antenna height settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-107X")] = 2; // 1074 0.5Hz settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-108X")] = 2; // 1084 0.5Hz settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-109X")] = 2; // 1094 0.5Hz @@ -286,7 +286,7 @@ bool GNSS_LG290P::configureRover() } // Set the fix rate. Default on LG290P is 10Hz so set accordingly. - response &= setRate(settings.measurementRateMs / 1000.0); + response &= setRate(settings.measurementRateMs / 1000.0); // May require save/reset if (settings.debugGnss && response == false) systemPrintln("Rover: Set rate failed"); @@ -358,7 +358,7 @@ bool GNSS_LG290P::configureBase() // response &= _lg290p->setModeBase(); // Wait for save and reset // Ignore result for now. enterConfigMode disables NMEA, which causes the built-in write/save/reset methods to // fail because NMEA is not present. - _lg290p->setModeBase(); // Wait for save and reset + _lg290p->setModeBase(false); // Don't save and reset if (settings.debugGnss && response == false) systemPrintln("Base: Set mode base failed"); @@ -372,7 +372,7 @@ bool GNSS_LG290P::configureBase() // response &= disableSurveyIn(); // Wait for save and reset // Ignore result for now. enterConfigMode disables NMEA, which causes the built-in write/save/reset methods to // fail because NMEA is not present. - disableSurveyIn(); // Wait for save and reset + disableSurveyIn(false); // Don't save and reset if (settings.debugGnss && response == false) systemPrintln("Base: disable survey in failed"); } @@ -452,7 +452,7 @@ bool GNSS_LG290P::exitConfigMode() //---------------------------------------- // Disable Survey-In //---------------------------------------- -bool GNSS_LG290P::disableSurveyIn() +bool GNSS_LG290P::disableSurveyIn(bool saveAndReset) { bool response = false; if (online.gnss) @@ -460,12 +460,16 @@ bool GNSS_LG290P::disableSurveyIn() response = _lg290p->sendOkCommand("$PQTMCFGSVIN", ",W,0,0,0,0,0,0"); // Disable survey mode if (settings.debugGnss && response == false) systemPrintln("disableSurveyIn: sendOkCommand failed"); - response &= saveConfiguration(); - if (settings.debugGnss && response == false) - systemPrintln("disableSurveyIn: save failed"); - response &= softwareReset(); - if (settings.debugGnss && response == false) - systemPrintln("disableSurveyIn: reset failed"); + + if (saveAndReset) + { + response &= saveConfiguration(); + if (settings.debugGnss && response == false) + systemPrintln("disableSurveyIn: save failed"); + response &= softwareReset(); + if (settings.debugGnss && response == false) + systemPrintln("disableSurveyIn: reset failed"); + } } return (response); @@ -577,12 +581,16 @@ bool GNSS_LG290P::enableRTCMBase() } // If any message is enabled, enable MSM output - if (lgMessagesRTCM[messageNumber].msgTextName, settings.lg290pMessageRatesRTCMRover[messageNumber] == true) + if (settings.lg290pMessageRatesRTCMRover[messageNumber] == true) enableMSM = true; } if (enableMSM == true) { + if(settings.debugGnss) + + systemPrintln("Enabling RTCM MSM output"); + // PQTMCFGRTCM fails to respond with OK over UART2 of LG290P, so don't look for it _lg290p->sendOkCommand( "PQTMCFGRTCM,W,7,0,-90,07,06,2,1"); // Enable MSM7, output regular intervals, interval (seconds) @@ -738,7 +746,8 @@ bool GNSS_LG290P::fixedBaseStart() if (settings.fixedBaseCoordinateType == COORD_TYPE_ECEF) { - _lg290p->setSurveyFixedMode(settings.fixedEcefX, settings.fixedEcefY, settings.fixedEcefZ); + // Waits for save and reset + response &= _lg290p->setSurveyFixedMode(settings.fixedEcefX, settings.fixedEcefY, settings.fixedEcefZ); } else if (settings.fixedBaseCoordinateType == COORD_TYPE_GEODETIC) { @@ -755,7 +764,8 @@ bool GNSS_LG290P::fixedBaseStart() // Convert LLA to ECEF geodeticToEcef(settings.fixedLat, settings.fixedLong, totalFixedAltitude, &ecefX, &ecefY, &ecefZ); - _lg290p->setSurveyFixedMode(ecefX, ecefY, ecefZ); + // Waits for save and reset + response &= _lg290p->setSurveyFixedMode(ecefX, ecefY, ecefZ); } return (response); @@ -1099,9 +1109,7 @@ uint8_t GNSS_LG290P::getRtcmMessageNumberByName(const char *msgName) uint8_t GNSS_LG290P::getSatellitesInView() { if (online.gnss) - // return (_lg290p->getSatellitesInView()); - // Use getSatellitesUsed until SIV works correctly - return (_lg290p->getSatellitesUsedCount()); + return (_lg290p->getSatellitesInViewCount()); return 0; } diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.h b/Firmware/RTK_Everywhere/GNSS_Mosaic.h index 0c0be8097..216ae7a25 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.h +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.h @@ -617,6 +617,12 @@ class GNSS_MOSAIC : GNSS // Returns true if successfully configured and false upon failure bool configureBase(); + // Configure mosaic-X5 COM1 for Encapsulated RTCMv3 + SBF + NMEA, plus L-Band + bool configureGNSSCOM(bool enableLBand); + + // Configure mosaic-X5 L-Band + bool configureLBand(bool enableLBand, uint32_t LBandFreq = 0); + bool configureLogging(); // Configure specific aspects of the receiver for NTP mode diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 61e8251c9..862694af1 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -488,6 +488,46 @@ bool GNSS_MOSAIC::configureNtpMode() return false; } +//---------------------------------------- +// Configure mosaic-X5 COM1 for Encapsulated RTCMv3 + SBF + NMEA, plus L-Band +//---------------------------------------- +bool GNSS_MOSAIC::configureGNSSCOM(bool enableLBand) +{ + // Configure COM1. NMEA and RTCMv3 will be encapsulated in SBF format + String setting = String("sdio,COM1,auto,RTCMv3+SBF+NMEA+Encapsulate"); + if (enableLBand) + setting += String("+LBandBeam1"); + setting += String("\n\r"); + return sendWithResponse(setting, "DataInOut"); +} + +//---------------------------------------- +// Configure mosaic-X5 L-Band +//---------------------------------------- +bool GNSS_MOSAIC::configureLBand(bool enableLBand, uint32_t LBandFreq) +{ + bool result = sendWithResponse("slsm,off\n\r", "LBandSelectMode"); // Turn L-Band off + + if (!enableLBand) + return result; + + static uint32_t storedLBandFreq = 0; + if (LBandFreq > 0) + storedLBandFreq = LBandFreq; + + // US SPARTN 1.8 service is on 1556290000 Hz + // EU SPARTN 1.8 service is on 1545260000 Hz + result &= + sendWithResponse(String("slbb,User1," + String(storedLBandFreq) + ",baud2400,PPerfect,EU,Enabled\n\r"), + "LBandBeams"); // Set Freq, baud rate + result &= + sendWithResponse("slcs,5555,6959\n\r", "LBandCustomServiceID"); // 21845 = 0x5555; 26969 = 0x6959 + result &= sendWithResponse("slsm,manual,Inmarsat,User1,\n\r", + "LBandSelectMode"); // Set L-Band demodulator to manual + + return result; +} + //---------------------------------------- // Perform the GNSS configuration // Outputs: @@ -508,11 +548,7 @@ bool GNSS_MOSAIC::configureOnce() bool response = true; // Configure COM1. NMEA and RTCMv3 will be encapsulated in SBF format - String setting = String("sdio,COM1,auto,RTCMv3+SBF+NMEA+Encapsulate"); - if (settings.enablePointPerfectCorrections) - setting += String("+LBandBeam1"); - setting += String("\n\r"); - response &= sendWithResponse(setting, "DataInOut"); + response &= configureGNSSCOM(settings.enablePointPerfectCorrections); // COM2 is configured by setCorrRadioExtPort @@ -522,7 +558,7 @@ bool GNSS_MOSAIC::configureOnce() // Output SBF PVTGeodetic and ReceiverTime on their own stream - on COM1 only // TODO : make the interval adjustable // TODO : do we need to enable SBF LBandTrackerStatus so we can get CN0 ? - setting = String("sso,Stream" + String(MOSAIC_SBF_PVT_STREAM) + ",COM1,PVTGeodetic+ReceiverTime,msec500\n\r"); + String setting = String("sso,Stream" + String(MOSAIC_SBF_PVT_STREAM) + ",COM1,PVTGeodetic+ReceiverTime,msec500\n\r"); response &= sendWithResponse(setting, "SBFOutput"); // Output SBF InputLink on its own stream - at 1Hz - on COM1 only @@ -2300,6 +2336,8 @@ bool GNSS_MOSAIC::setTalkerGNGGA() //---------------------------------------- bool GNSS_MOSAIC::softwareReset() { + // We could restart L-Band here if needed, but gnss->softwareReset is never called on the X5 + // Instead, update() does it when spartnCorrectionsReceived times out return false; } @@ -2441,8 +2479,14 @@ void GNSS_MOSAIC::update() } // Update spartnCorrectionsReceived - if (millis() > (lastSpartnReception + 5000)) - spartnCorrectionsReceived = false; + if (millis() > (lastSpartnReception + (settings.correctionsSourcesLifetime_s * 1000))) // Timeout + { + if (spartnCorrectionsReceived) // If corrections were being received + { + configureLBand(settings.enablePointPerfectCorrections); // Restart L-Band using stored frequency + spartnCorrectionsReceived = false; + } + } } //---------------------------------------- @@ -2605,9 +2649,12 @@ void processUart1SBF(SEMP_PARSE_STATE *parse, uint16_t type) { GNSS_MOSAIC *mosaic = (GNSS_MOSAIC *)gnss; - // if ((settings.debugGnss == true) && !inMainMenu) - // systemPrintf("Processing SBF Block %d (%d bytes) from mosaic-X5\r\n", sempSbfGetBlockNumber(parse), - // parse->length); + if (((settings.debugGnss == true) || PERIODIC_DISPLAY(PD_GNSS_DATA_RX)) && !inMainMenu) + { + // Don't call PERIODIC_CLEAR(PD_GNSS_DATA_RX); here. Let processUart1Message do it via rtkParse + systemPrintf("Processing SBF Block %d (%d bytes) from mosaic-X5\r\n", sempSbfGetBlockNumber(parse), + parse->length); + } // If this is PVTGeodetic, extract some data if (sempSbfGetBlockNumber(parse) == 4007) @@ -2636,8 +2683,11 @@ void processUart1SBF(SEMP_PARSE_STATE *parse, uint16_t type) //---------------------------------------- void processUart1SPARTN(SEMP_PARSE_STATE *parse, uint16_t type) { - if ((settings.debugCorrections == true) && !inMainMenu) + if (((settings.debugGnss == true) || PERIODIC_DISPLAY(PD_GNSS_DATA_RX)) && !inMainMenu) + { + // Don't call PERIODIC_CLEAR(PD_GNSS_DATA_RX); here. Let processUart1Message do it via rtkParse systemPrintf("Pushing %d SPARTN (L-Band) bytes to PPL for mosaic-X5\r\n", parse->length); + } if (online.ppl == false && settings.debugCorrections == true && (!inMainMenu)) systemPrintln("Warning: PPL is offline"); diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 1fcbbff7b..7cd62257c 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1318,6 +1318,123 @@ void networkStartDelayed(NetIndex_t index, uintptr_t parameter, bool debug) } //---------------------------------------- +<<<<<<< HEAD +======= +// Maintain the network connections +//---------------------------------------- +void networkUpdate() +{ + bool displayIpAddress; + NetIndex_t index; + IPAddress ipAddress; + bool ipAddressDisplayed; + uint8_t networkType; + NETWORK_POLL_ROUTINE pollRoutine; + uint8_t priority; + NETWORK_POLL_SEQUENCE *sequence; + + // If there are no consumers, do not start the network + if (networkConsumers() == 0 && networkIsOnline() == false) + { + return; + } + + // If there are no consumers, but the network is online, shut down all networks + if (networkConsumers() == 0 && networkIsOnline() == true) + { + if (systemState == STATE_WIFI_CONFIG) + { + // The STATE_WIFI_CONFIG is in control of WiFi. Don't allow the network layer to shut it down + // As OTA exits, we need to keep AP running if we are in Web Config mode + // We don't want to make STATE_WIFI_CONFIG a consumer until startWebServer() uses the network layer + } + else + { + // Shutdown all networks + for (int index = 0; index < NETWORK_OFFLINE; index++) + networkStop(index, settings.debugNetworkLayer); + } + } + + // Allow consumers to start networks + // Each network is expected to shut itself down if it is unavailable or of a lower priority + // so that a networkStart() succeeds. + if (networkConsumers() > 0 && networkIsOnline() == false) + { + // Start network as needed + for (int index = 0; index < NETWORK_OFFLINE; index++) + networkStart(index, settings.debugNetworkLayer); + } + + // Walk the list of network priorities in descending order + for (priority = 0; priority < NETWORK_OFFLINE; priority++) + { + // Execute any active polling routine + index = networkIndexTable[priority]; + sequence = networkSequence[index]; + if (sequence) + { + pollRoutine = sequence->routine; + if (pollRoutine) + // Execute the poll routine + pollRoutine(index, sequence->parameter, settings.debugNetworkLayer); + } + } + + // Update the network services + DMW_c("mqttClientUpdate"); + mqttClientUpdate(); // Process any Point Perfect MQTT messages + DMW_c("ntpServerUpdate"); + ntpServerUpdate(); // Process any received NTP requests + DMW_c("ntripClientUpdate"); + ntripClientUpdate(); // Check the NTRIP client connection and move data NTRIP --> ZED + DMW_c("ntripServerUpdate"); + ntripServerUpdate(); // Check the NTRIP server connection and move data ZED --> NTRIP + DMW_c("tcpClientUpdate"); + tcpClientUpdate(); // Turn on the TCP client as needed + DMW_c("tcpServerUpdate"); + tcpServerUpdate(); // Turn on the TCP server as needed + DMW_c("udpServerUpdate"); + udpServerUpdate(); // Turn on the UDP server as needed + DMW_c("httpClientUpdate"); + httpClientUpdate(); // Process any Point Perfect HTTP messages + + // Periodically display the network interface state + displayIpAddress = PERIODIC_DISPLAY(PD_IP_ADDRESS); + for (int index = 0; index < NETWORK_OFFLINE; index++) + { + // Display the current state + ipAddressDisplayed = displayIpAddress && (index == networkPriority); + if (PERIODIC_DISPLAY(networkInterfaceTable[index].pdState) || PERIODIC_DISPLAY(PD_NETWORK_STATE) || + ipAddressDisplayed) + { + PERIODIC_CLEAR(networkInterfaceTable[index].pdState); + if (networkInterfaceTable[index].netif->hasIP()) + { + ipAddress = networkInterfaceTable[index].netif->localIP(); + systemPrintf("%s: %s%s\r\n", networkInterfaceTable[index].name, ipAddress.toString().c_str(), + networkInterfaceTable[index].netif->isDefault() ? " (default)" : ""); + } + else if (networkInterfaceTable[index].netif->linkUp()) + systemPrintf("%s: Link Up\r\n", networkInterfaceTable[index].name); + else if (networkInterfaceTable[index].netif->started()) + systemPrintf("%s: Started\r\n", networkInterfaceTable[index].name); + else + systemPrintf("%s: Stopped\r\n", networkInterfaceTable[index].name); + } + } + if (PERIODIC_DISPLAY(PD_NETWORK_STATE)) + PERIODIC_CLEAR(PD_NETWORK_STATE); + if (displayIpAddress) + { + if (!ipAddressDisplayed) + systemPrintln("Network: Offline"); + PERIODIC_CLEAR(PD_IP_ADDRESS); + } +} + +//---------------------------------------- +>>>>>>> release_candidate // Validate the network index //---------------------------------------- void networkValidateIndex(NetIndex_t index) @@ -1672,10 +1789,17 @@ uint8_t networkConsumers(uint16_t *consumerTypes) systemPrint("PPL Key Update Request, "); if (consumerId & (1 << 6)) systemPrint("PPL MQTT Client, "); +<<<<<<< HEAD if (consumerId & (1 << 7)) systemPrint("OTA Version Check or Update, "); if (consumerId & (1 << 8)) systemPrint("Web Config, "); +======= + if (consumerType & (1 << 7)) + systemPrint("OTA Version Check, "); + if (consumerType & (1 << 8)) + systemPrint("OTA Firmware Update, "); +>>>>>>> release_candidate } systemPrintln(); diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 7a4c5bd08..85b36a2f4 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -461,7 +461,6 @@ volatile bool forwardGnssDataToUsbSerial; #define platformPrefix platformPrefixTable[productVariant] // Sets the prefix for broadcast names -#include //Required for uart_set_rx_full_threshold() on cores 0) { +<<<<<<< HEAD if (settings.debugWebServer) systemPrintln("Webconfig: Reporting firmware version"); +======= +>>>>>>> release_candidate createFirmwareVersionString(settingsCSV); + if (settings.debugWebConfig) + systemPrintf("Webconfig: Firmware version requested. Sending: %s\r\n", settingsCSV); + sendStringToWebsocket(settingsCSV); +<<<<<<< HEAD otaReportedVersion[0] = '\0'; // Zero out the reported version to stop future reports +======= + otaReportedVersion[0] = '\0'; // Zero out the reported version +>>>>>>> release_candidate } } diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index 896d894e6..c754df710 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -159,7 +159,7 @@ void btReadTask(void *e) rxBytes = 0; if (bluetoothGetState() == BT_CONNECTED) { - while (btPrintEcho == false && bluetoothRxDataAvailable()) + while (btPrintEcho == false && (bluetoothRxDataAvailable() > 0)) { // Check stream for command characters byte incoming = bluetoothRead(); @@ -289,18 +289,18 @@ void sendGnssBuffer() { if (gnss->pushRawData(bluetoothOutgoingToGnss, bluetoothOutgoingToGnssHead)) { - if ((settings.debugCorrections || PERIODIC_DISPLAY(PD_ZED_DATA_TX)) && !inMainMenu) + if ((settings.debugCorrections || PERIODIC_DISPLAY(PD_GNSS_DATA_TX)) && !inMainMenu) { - PERIODIC_CLEAR(PD_ZED_DATA_TX); + PERIODIC_CLEAR(PD_GNSS_DATA_TX); systemPrintf("Sent %d BT bytes to GNSS\r\n", bluetoothOutgoingToGnssHead); } } } else { - if ((settings.debugCorrections || PERIODIC_DISPLAY(PD_ZED_DATA_TX)) && !inMainMenu) + if ((settings.debugCorrections || PERIODIC_DISPLAY(PD_GNSS_DATA_TX)) && !inMainMenu) { - PERIODIC_CLEAR(PD_ZED_DATA_TX); + PERIODIC_CLEAR(PD_GNSS_DATA_TX); systemPrintf("%d BT bytes NOT sent due to priority\r\n", bluetoothOutgoingToGnssHead); } } @@ -424,6 +424,14 @@ void gnssReadTask(void *e) if ((settings.enableTaskReports == true) && (!inMainMenu)) systemPrintf("SerialReadTask High watermark: %d\r\n", uxTaskGetStackHighWaterMark(nullptr)); + // Display the RX byte count + static uint32_t totalRxByteCount = 0; + if (PERIODIC_DISPLAY(PD_GNSS_DATA_RX_BYTE_COUNT)) + { + PERIODIC_CLEAR(PD_GNSS_DATA_RX_BYTE_COUNT); + systemPrintf("gnssReadTask total byte count: %d\r\n", totalRxByteCount); + } + // Two methods are accessing the hardware serial port (um980Config) at the // same time: gnssReadTask() (to harvest incoming serial data) and um980 (the unicore library to configure the // device) To allow the Unicore library to send/receive serial commands, we need to block the gnssReadTask @@ -454,6 +462,7 @@ void gnssReadTask(void *e) // Read the data from UART1 uint8_t incomingData[500]; int bytesIncoming = serialGNSS->read(incomingData, sizeof(incomingData)); + totalRxByteCount += bytesIncoming; for (int x = 0; x < bytesIncoming; x++) { @@ -573,9 +582,9 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type) int32_t use; // Display the message - if ((settings.enablePrintLogFileMessages || PERIODIC_DISPLAY(PD_ZED_DATA_RX)) && (!parse->crc) && (!inMainMenu)) + if ((settings.enablePrintLogFileMessages || PERIODIC_DISPLAY(PD_GNSS_DATA_RX)) && (!parse->crc) && (!inMainMenu)) { - PERIODIC_CLEAR(PD_ZED_DATA_RX); + PERIODIC_CLEAR(PD_GNSS_DATA_RX); if (settings.enablePrintLogFileMessages) { printTimeStamp(); @@ -2109,7 +2118,7 @@ void bluetoothCommandTask(void *pvParameters) } // Check stream for incoming characters - if (bluetoothCommandAvailable()) + if (bluetoothCommandAvailable() > 0) { byte incoming = bluetoothCommandRead(); diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index b1af8da73..63769e376 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -240,7 +240,13 @@ bool tcpServerStart() tcpServer->begin(); online.tcpServer = true; localIp = networkGetIpAddress(); - systemPrintf("TCP server online, IP address %s:%d\r\n", localIp.toString().c_str(), settings.tcpServerPort); + + if (settings.enableNtripCaster) + systemPrintf("TCP server online, IP address %s:%d, responding as NTRIP Caster\r\n", localIp.toString().c_str(), + settings.tcpServerPort); + else + systemPrintf("TCP server online, IP address %s:%d\r\n", localIp.toString().c_str(), settings.tcpServerPort); + return true; } @@ -448,27 +454,77 @@ void tcpServerUpdate() // Determine if the client data structure is in use if (!(tcpServerClientConnected & (1 << index))) { - NetworkClient client; + if(tcpServerClient[index] == nullptr) + tcpServerClient[index] = new NetworkClient; // Data structure not in use // Check for another TCP server client - client = tcpServer->accept(); + *tcpServerClient[index] = tcpServer->accept(); - // Done if no TCP server client found - if (!client) + // Exit if no TCP server client found + if (! *tcpServerClient[index]) break; // Start processing the new TCP server client connection - tcpServerClient[index] = new NetworkClient; tcpServerClientIpAddress[index] = tcpServerClient[index]->remoteIP(); - tcpServerClientConnected = tcpServerClientConnected | (1 << index); - tcpServerClientDataSent = tcpServerClientDataSent | (1 << index); + if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu)) { PERIODIC_CLEAR(PD_TCP_SERVER_DATA); systemPrintf("TCP server client %d connected to %s\r\n", index, tcpServerClientIpAddress[index].toString().c_str()); } + + // If we are acting as an NTRIP Caster, intercept the initial communication from the client + // and respond accordingly + if (settings.enableNtripCaster) + { + // Read response from client + char response[512]; + int spot = 0; + while (tcpServerClient[index]->available()) + { + response[spot++] = tcpServerClient[index]->read(); + if (spot == sizeof(response)) + spot = 0; // Wrap + } + response[spot] = '\0'; // Terminate string + + if (strnstr(response, "GET / ", sizeof(response)) != NULL) // No mount point in header + { + if (settings.debugTcpServer) + systemPrintln("Mount point table requested."); + + // Respond with a single mountpoint + const char fakeSourceTable[] = + "SOURCETABLE 200 OK\r\nServer: SparkPNT Caster/1.0\r\nContent-Type: " + "text/plain\r\nContent-Length: 96\r\n\r\nSTR;SparkBase;none;RTCM " + "3.0;none;none;none;none;none;none;none;none;none;none;none;B;N;none;none"; + + tcpServerClient[index]->write(fakeSourceTable, strlen(fakeSourceTable)); + + tcpServerStopClient(index); // Disconnect from client + } + else if (strnstr(response, "GET /", sizeof(response)) != NULL) // Mount point in header + { + // NTRIP Client is sending us their mount point. Begin sending RTCM. + if (settings.debugTcpServer) + systemPrintln("NTRIP Client connected - Sending ICY 200 OK"); + + char confirmConnection[] = "ICY 200 OK\r\n"; + tcpServerClient[index]->write(confirmConnection, strlen(confirmConnection)); + } + else + { + // Unknown response + if (settings.debugTcpServer) + systemPrintf("Unknown response: %s\r\n", response); + } + } // settings.enableNtripCaster == true + + // Make client online after any NTRIP injections so ring buffer can start outputting data to it + tcpServerClientConnected = tcpServerClientConnected | (1 << index); + tcpServerClientDataSent = tcpServerClientDataSent | (1 << index); } } diff --git a/Firmware/RTK_Everywhere/bluetoothSelect.h b/Firmware/RTK_Everywhere/bluetoothSelect.h index 9f55f190a..d3964d8a0 100644 --- a/Firmware/RTK_Everywhere/bluetoothSelect.h +++ b/Firmware/RTK_Everywhere/bluetoothSelect.h @@ -103,7 +103,7 @@ class BTLESerial : public virtual BTSerialInterface, public BleSerial bool begin(String deviceName, bool isMaster, bool disableBLE, uint16_t rxQueueSize, uint16_t txQueueSize, const char *serviceID, const char *rxID, const char *txID) { - BleSerial::begin(deviceName.c_str(), serviceID, rxID, txID); + BleSerial::begin(deviceName.c_str(), serviceID, rxID, txID, -1); // name, service_uuid, rx_uuid, tx_uuid, led_pin return true; } diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index 771d67c74..6d4924c8a 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xC8, 0x5B, 0x5B, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0xC8, 0x56, 0x63, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0x1B, 0xB9, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x1D, 0xDF, 0x73, 0xC7, 0xE6, 0x60, 0x8C, 0x6D, 0x3E, 0x12, 0x42, 0xC8, 0x5E, 0x02, 0x24, 0xE1, 0x9E, 0x40, 0xB8, 0x98, 0xCC, 0x4C, 0x26, 0x27, 0xCB, 0x36, 0x6E, 0x61, 0x7A, 0x63, @@ -1020,7 +1020,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xC8, 0x5B, 0x5B, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0xC8, 0x56, 0x63, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xE9, 0x72, 0xDB, 0x48, 0x93, 0xE0, 0xFF, 0x7E, 0x8A, 0xFA, 0x38, 0x3B, 0x63, 0x69, 0x46, 0xA4, 0x78, 0x48, 0xB2, 0xAC, 0xB6, 0x15, 0xA1, 0xCB, 0xB6, 0xF6, 0x93, 0x6C, 0x8E, 0x28, 0x7F, 0x7D, 0x6C, 0xEC, 0x76, 0x40, diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index b8514c368..43807512e 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -1313,12 +1313,9 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting sendStringToWebsocket((char *)"checkingNewFirmware,1,"); // Tell the config page we received their request - // Indicate to the network that we need access + // Indicate to the OTA state machine that we need to do a version check otaRequestFirmwareVersionCheck = true; - // Erase reported version. Once the reported version comes back, transmit to webpage - otaReportedVersion[0] = '\0'; - // Get firmware version from server // otaCheckVersion will call wifiConnect if needed // if (otaCheckVersion(reportedVersion, sizeof(reportedVersion))) diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index 05871b922..f15adc020 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -787,7 +787,11 @@ void otaUpdateStop() if (settings.debugFirmwareUpdate) systemPrintln("Firmware update releasing network request"); +<<<<<<< HEAD online.otaClient = false; +======= + online.otaFirmwareUpdate = false; +>>>>>>> release_candidate otaRequestFirmwareUpdate = false; // Let the network know we no longer need it @@ -867,8 +871,11 @@ void otaUpdate() otaReportedVersion[0] = 0; if (otaCheckVersion(otaReportedVersion, sizeof(otaReportedVersion))) { +<<<<<<< HEAD online.otaClient = true; +======= +>>>>>>> release_candidate // Create a string of the unit's current firmware version char currentVersion[21]; getFirmwareVersion(currentVersion, sizeof(currentVersion), enableRCFirmware); diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index af81423e5..a58ad7383 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -870,17 +870,10 @@ void beginLBand() // If no SPARTN data is received, the L-Band may need a 'kick'. Turn L-Band off and back on again! GNSS_MOSAIC *mosaic = (GNSS_MOSAIC *)gnss; - result &= mosaic->sendWithResponse("slsm,off\n\r", "LBandSelectMode"); // Turn L-Band off - - // US SPARTN 1.8 service is on 1556290000 Hz - // EU SPARTN 1.8 service is on 1545260000 Hz - result &= - mosaic->sendWithResponse(String("slbb,User1," + String(LBandFreq) + ",baud2400,PPerfect,EU,Enabled\n\r"), - "LBandBeams"); // Set Freq, baud rate - result &= - mosaic->sendWithResponse("slcs,5555,6959\n\r", "LBandCustomServiceID"); // 21845 = 0x5555; 26969 = 0x6959 - result &= mosaic->sendWithResponse("slsm,manual,Inmarsat,User1,\n\r", - "LBandSelectMode"); // Set L-Band demodulator to manual + + result &= mosaic->configureGNSSCOM(true); // Ensure LBandBeam1 is enabled on COM1 + + result &= mosaic->configureLBand(true, LBandFreq); // Start L-Band if (result == false) systemPrintln("mosaic-X5 L-Band failed to configure"); diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index 50b8c2411..5e15699ae 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -91,7 +91,7 @@ void menuSystem() else systemPrintln("Offline - "); - if (online.lbandCorrections == true) + if (online.ppl == true) systemPrint("Keys Good"); else systemPrint("No Keys"); @@ -1146,11 +1146,14 @@ void menuPeriodicPrint() systemPrint("7) WiFi state: "); systemPrintf("%s\r\n", PERIODIC_SETTING(PD_WIFI_STATE) ? "Enabled" : "Disabled"); - systemPrint("8) ZED RX data: "); - systemPrintf("%s\r\n", PERIODIC_SETTING(PD_ZED_DATA_RX) ? "Enabled" : "Disabled"); + systemPrint("8) GNSS RX data: "); + systemPrintf("%s\r\n", PERIODIC_SETTING(PD_GNSS_DATA_RX) ? "Enabled" : "Disabled"); + + systemPrint("9) GNSS TX data: "); + systemPrintf("%s\r\n", PERIODIC_SETTING(PD_GNSS_DATA_TX) ? "Enabled" : "Disabled"); - systemPrint("9) ZED TX data: "); - systemPrintf("%s\r\n", PERIODIC_SETTING(PD_ZED_DATA_TX) ? "Enabled" : "Disabled"); + systemPrint("10) GNSS RX byte count: "); + systemPrintf("%s\r\n", PERIODIC_SETTING(PD_GNSS_DATA_RX_BYTE_COUNT) ? "Enabled" : "Disabled"); systemPrintln("----- Software -----"); @@ -1270,9 +1273,11 @@ void menuPeriodicPrint() else if (incoming == 7) PERIODIC_TOGGLE(PD_WIFI_STATE); else if (incoming == 8) - PERIODIC_TOGGLE(PD_ZED_DATA_RX); + PERIODIC_TOGGLE(PD_GNSS_DATA_RX); else if (incoming == 9) - PERIODIC_TOGGLE(PD_ZED_DATA_TX); + PERIODIC_TOGGLE(PD_GNSS_DATA_TX); + else if (incoming == 10) + PERIODIC_TOGGLE(PD_GNSS_DATA_RX_BYTE_COUNT); else if (incoming == 20) { diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index bc6750f57..69432ff3a 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -301,8 +301,8 @@ enum PeriodDisplayValues PD_CELLULAR_STATE, // 28 PD_WIFI_STATE, // 29 - PD_ZED_DATA_RX, // 30 - PD_ZED_DATA_TX, // 31 + PD_GNSS_DATA_RX, // 30 + PD_GNSS_DATA_TX, // 31 PD_MQTT_CLIENT_DATA, // 32 PD_MQTT_CLIENT_STATE, // 33 @@ -314,6 +314,8 @@ enum PeriodDisplayValues PD_PROVISIONING_STATE, // 36 PD_CORRECTION_SOURCE, // 37 + + PD_GNSS_DATA_RX_BYTE_COUNT, // 38 // Add new values before this line }; @@ -1011,7 +1013,11 @@ struct Settings #endif // COMPILE_LG290P bool debugSettings = false; +<<<<<<< HEAD bool enableNtripCaster = false; +======= + bool enableNtripCaster = false; //When true, respond as a faux NTRIP Caster to incoming TCP connections +>>>>>>> release_candidate // Add new settings to appropriate group above or create new group // Then also add to the same group in rtkSettingsEntries below diff --git a/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp b/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp index aed24de27..e941a8ca7 100644 --- a/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp +++ b/Firmware/RTK_Everywhere/src/BluetoothSerial/BluetoothSerial.cpp @@ -789,10 +789,12 @@ static bool waitForConnect(int timeout) { if ((rc & SPP_CONNECTED) != 0) { return true; } else if ((rc & SPP_CLOSED) != 0) { - log_d("connection closed!"); + if (timeout > 0) + log_d("connection closed!"); return false; } - log_d("timeout"); + if (timeout > 0) + log_d("timeout"); return false; } @@ -881,7 +883,7 @@ size_t BluetoothSerial::write(const uint8_t *buffer, size_t size) { void BluetoothSerial::flush() { if (_spp_tx_queue != NULL) { while (uxQueueMessagesWaiting(_spp_tx_queue) > 0) { - delay(100); + delay(2); // https://github.com/espressif/arduino-esp32/pull/9905 } } } From f01062efd42e76a5c578432cf15ec8f9da158bf5 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 2 Jan 2025 13:01:15 -0700 Subject: [PATCH 060/276] Resolve conflicts --- Firmware/RTK_Everywhere/Network.ino | 124 ----------------------- Firmware/RTK_Everywhere/States.ino | 7 -- Firmware/RTK_Everywhere/menuFirmware.ino | 7 -- Firmware/RTK_Everywhere/settings.h | 4 - 4 files changed, 142 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 7cd62257c..1fcbbff7b 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1318,123 +1318,6 @@ void networkStartDelayed(NetIndex_t index, uintptr_t parameter, bool debug) } //---------------------------------------- -<<<<<<< HEAD -======= -// Maintain the network connections -//---------------------------------------- -void networkUpdate() -{ - bool displayIpAddress; - NetIndex_t index; - IPAddress ipAddress; - bool ipAddressDisplayed; - uint8_t networkType; - NETWORK_POLL_ROUTINE pollRoutine; - uint8_t priority; - NETWORK_POLL_SEQUENCE *sequence; - - // If there are no consumers, do not start the network - if (networkConsumers() == 0 && networkIsOnline() == false) - { - return; - } - - // If there are no consumers, but the network is online, shut down all networks - if (networkConsumers() == 0 && networkIsOnline() == true) - { - if (systemState == STATE_WIFI_CONFIG) - { - // The STATE_WIFI_CONFIG is in control of WiFi. Don't allow the network layer to shut it down - // As OTA exits, we need to keep AP running if we are in Web Config mode - // We don't want to make STATE_WIFI_CONFIG a consumer until startWebServer() uses the network layer - } - else - { - // Shutdown all networks - for (int index = 0; index < NETWORK_OFFLINE; index++) - networkStop(index, settings.debugNetworkLayer); - } - } - - // Allow consumers to start networks - // Each network is expected to shut itself down if it is unavailable or of a lower priority - // so that a networkStart() succeeds. - if (networkConsumers() > 0 && networkIsOnline() == false) - { - // Start network as needed - for (int index = 0; index < NETWORK_OFFLINE; index++) - networkStart(index, settings.debugNetworkLayer); - } - - // Walk the list of network priorities in descending order - for (priority = 0; priority < NETWORK_OFFLINE; priority++) - { - // Execute any active polling routine - index = networkIndexTable[priority]; - sequence = networkSequence[index]; - if (sequence) - { - pollRoutine = sequence->routine; - if (pollRoutine) - // Execute the poll routine - pollRoutine(index, sequence->parameter, settings.debugNetworkLayer); - } - } - - // Update the network services - DMW_c("mqttClientUpdate"); - mqttClientUpdate(); // Process any Point Perfect MQTT messages - DMW_c("ntpServerUpdate"); - ntpServerUpdate(); // Process any received NTP requests - DMW_c("ntripClientUpdate"); - ntripClientUpdate(); // Check the NTRIP client connection and move data NTRIP --> ZED - DMW_c("ntripServerUpdate"); - ntripServerUpdate(); // Check the NTRIP server connection and move data ZED --> NTRIP - DMW_c("tcpClientUpdate"); - tcpClientUpdate(); // Turn on the TCP client as needed - DMW_c("tcpServerUpdate"); - tcpServerUpdate(); // Turn on the TCP server as needed - DMW_c("udpServerUpdate"); - udpServerUpdate(); // Turn on the UDP server as needed - DMW_c("httpClientUpdate"); - httpClientUpdate(); // Process any Point Perfect HTTP messages - - // Periodically display the network interface state - displayIpAddress = PERIODIC_DISPLAY(PD_IP_ADDRESS); - for (int index = 0; index < NETWORK_OFFLINE; index++) - { - // Display the current state - ipAddressDisplayed = displayIpAddress && (index == networkPriority); - if (PERIODIC_DISPLAY(networkInterfaceTable[index].pdState) || PERIODIC_DISPLAY(PD_NETWORK_STATE) || - ipAddressDisplayed) - { - PERIODIC_CLEAR(networkInterfaceTable[index].pdState); - if (networkInterfaceTable[index].netif->hasIP()) - { - ipAddress = networkInterfaceTable[index].netif->localIP(); - systemPrintf("%s: %s%s\r\n", networkInterfaceTable[index].name, ipAddress.toString().c_str(), - networkInterfaceTable[index].netif->isDefault() ? " (default)" : ""); - } - else if (networkInterfaceTable[index].netif->linkUp()) - systemPrintf("%s: Link Up\r\n", networkInterfaceTable[index].name); - else if (networkInterfaceTable[index].netif->started()) - systemPrintf("%s: Started\r\n", networkInterfaceTable[index].name); - else - systemPrintf("%s: Stopped\r\n", networkInterfaceTable[index].name); - } - } - if (PERIODIC_DISPLAY(PD_NETWORK_STATE)) - PERIODIC_CLEAR(PD_NETWORK_STATE); - if (displayIpAddress) - { - if (!ipAddressDisplayed) - systemPrintln("Network: Offline"); - PERIODIC_CLEAR(PD_IP_ADDRESS); - } -} - -//---------------------------------------- ->>>>>>> release_candidate // Validate the network index //---------------------------------------- void networkValidateIndex(NetIndex_t index) @@ -1789,17 +1672,10 @@ uint8_t networkConsumers(uint16_t *consumerTypes) systemPrint("PPL Key Update Request, "); if (consumerId & (1 << 6)) systemPrint("PPL MQTT Client, "); -<<<<<<< HEAD if (consumerId & (1 << 7)) systemPrint("OTA Version Check or Update, "); if (consumerId & (1 << 8)) systemPrint("Web Config, "); -======= - if (consumerType & (1 << 7)) - systemPrint("OTA Version Check, "); - if (consumerType & (1 << 8)) - systemPrint("OTA Firmware Update, "); ->>>>>>> release_candidate } systemPrintln(); diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index f37e521ad..2fb7f3ada 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -481,12 +481,9 @@ void stateUpdate() // If a firmware version was requested, and obtained, report it back to the web page if (strlen(otaReportedVersion) > 0) { -<<<<<<< HEAD if (settings.debugWebServer) systemPrintln("Webconfig: Reporting firmware version"); -======= ->>>>>>> release_candidate createFirmwareVersionString(settingsCSV); if (settings.debugWebConfig) @@ -494,11 +491,7 @@ void stateUpdate() sendStringToWebsocket(settingsCSV); -<<<<<<< HEAD - otaReportedVersion[0] = '\0'; // Zero out the reported version to stop future reports -======= otaReportedVersion[0] = '\0'; // Zero out the reported version ->>>>>>> release_candidate } } diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index f15adc020..05871b922 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -787,11 +787,7 @@ void otaUpdateStop() if (settings.debugFirmwareUpdate) systemPrintln("Firmware update releasing network request"); -<<<<<<< HEAD online.otaClient = false; -======= - online.otaFirmwareUpdate = false; ->>>>>>> release_candidate otaRequestFirmwareUpdate = false; // Let the network know we no longer need it @@ -871,11 +867,8 @@ void otaUpdate() otaReportedVersion[0] = 0; if (otaCheckVersion(otaReportedVersion, sizeof(otaReportedVersion))) { -<<<<<<< HEAD online.otaClient = true; -======= ->>>>>>> release_candidate // Create a string of the unit's current firmware version char currentVersion[21]; getFirmwareVersion(currentVersion, sizeof(currentVersion), enableRCFirmware); diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 69432ff3a..72065fabf 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -1013,11 +1013,7 @@ struct Settings #endif // COMPILE_LG290P bool debugSettings = false; -<<<<<<< HEAD - bool enableNtripCaster = false; -======= bool enableNtripCaster = false; //When true, respond as a faux NTRIP Caster to incoming TCP connections ->>>>>>> release_candidate // Add new settings to appropriate group above or create new group // Then also add to the same group in rtkSettingsEntries below From 29cd5ed1c3956dd6135c9cbabb0b722c39a01d20 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 2 Jan 2025 13:03:01 -0700 Subject: [PATCH 061/276] Fix merge conflicts --- Firmware/RTK_Everywhere/States.ino | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 2fb7f3ada..a72258e2b 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -481,12 +481,9 @@ void stateUpdate() // If a firmware version was requested, and obtained, report it back to the web page if (strlen(otaReportedVersion) > 0) { - if (settings.debugWebServer) - systemPrintln("Webconfig: Reporting firmware version"); - createFirmwareVersionString(settingsCSV); - if (settings.debugWebConfig) + if (settings.debugWebServer) systemPrintf("Webconfig: Firmware version requested. Sending: %s\r\n", settingsCSV); sendStringToWebsocket(settingsCSV); From 3a1782a30c82c8f376a2f63231ed8984c1dd3b8f Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 2 Jan 2025 13:03:28 -0700 Subject: [PATCH 062/276] Start webconfig in AP+STA mode to allow firmware checks --- Firmware/RTK_Everywhere/Network.ino | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 1fcbbff7b..1afe472ae 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1637,12 +1637,9 @@ uint8_t networkConsumers(uint16_t *consumerTypes) consumerCount++; consumerId |= (1 << 8); - // The web server takes precedence over other network consumers so that we can start in AP mode only as needed // TODO Make web server over ethernet work here as well if (settings.wifiConfigOverAP == true) - *consumerTypes = (1 << NETCONSUMER_WIFI_AP); // Force into AP only mode - else - *consumerTypes = (1 << NETCONSUMER_WIFI_STA); // Force into STA only mode + *consumerTypes |= (1 << NETCONSUMER_WIFI_AP_STA); //WebConfig requires both AP and STA (for firmware check) } // Debug From 65ac3ec395d0e3966300e6eda6df184597151662 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 2 Jan 2025 14:38:40 -0700 Subject: [PATCH 063/276] Allow tasks to end before releasing resources --- Firmware/RTK_Everywhere/PointPerfectLibrary.ino | 14 +++++++------- Firmware/RTK_Everywhere/WebServer.ino | 9 +++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Firmware/RTK_Everywhere/PointPerfectLibrary.ino b/Firmware/RTK_Everywhere/PointPerfectLibrary.ino index d3de1410a..08aa41f4d 100644 --- a/Firmware/RTK_Everywhere/PointPerfectLibrary.ino +++ b/Firmware/RTK_Everywhere/PointPerfectLibrary.ino @@ -211,17 +211,17 @@ void stopPPL() if (task.updatePplTaskRunning) task.updatePplTaskStopRequest = true; + // Wait for task to stop running + do + delay(10); + while (task.updatePplTaskRunning); + if (pplRtcmBuffer != nullptr) { free(pplRtcmBuffer); pplRtcmBuffer = nullptr; } - // Wait for task to stop running - do - delay(10); - while (task.updatePplTaskRunning); - online.ppl = false; } @@ -417,7 +417,7 @@ bool sendGnssToPpl(uint8_t *buffer, int numDataBytes) } else { - if(settings.debugCorrections & !inMainMenu) + if (settings.debugCorrections & !inMainMenu) systemPrintln("sendGnssToPpl available"); pplGnssOutput = true; // Notify updatePPL() that GNSS is outputting NMEA/RTCM } @@ -444,7 +444,7 @@ bool sendSpartnToPpl(uint8_t *buffer, int numDataBytes) } else { - if(settings.debugCorrections & !inMainMenu) + if (settings.debugCorrections & !inMainMenu) systemPrintln("pplMqttCorrections available"); pplMqttCorrections = true; // Notify updatePPL() that MQTT is online } diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index 56aa5b766..b1ade1ffe 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -682,6 +682,11 @@ void stopWebServer() if (task.updateWebServerTaskRunning) task.updateWebServerTaskStopRequest = true; + // Wait for task to stop running + do + delay(10); + while (task.updateWebServerTaskRunning); + if (webServer != nullptr) { webServer->close(); @@ -703,10 +708,6 @@ void stopWebServer() free(incomingSettings); incomingSettings = nullptr; } - - do - delay(10); - while (task.updateWebServerTaskRunning); } void webServerReleaseResources() From 21df2f83a1b0fb8c46d22491e8533091c2be2f34 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 2 Jan 2025 14:39:05 -0700 Subject: [PATCH 064/276] Add AP_STA as a WiFi consumer type --- Firmware/RTK_Everywhere/WiFi.ino | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index cac168283..05adc9722 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -523,7 +523,14 @@ bool wifiForceStart() startWiFiStation = true; } - // The consumers need both + // The consumers need both (explicit) + else if (consumerTypes & (1 << NETCONSUMER_WIFI_AP_STA)) + { + startWiFiStation = true; + startWiFiAP = true; + } + + // The consumers need both (implicit) else if ((consumerTypes & (1 << NETCONSUMER_WIFI_AP)) && (consumerTypes & (1 << NETCONSUMER_WIFI_STA))) { startWiFiStation = true; From f246468fea6bedb7458162ffec5aecd72c7e0883 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 2 Jan 2025 15:27:03 -0700 Subject: [PATCH 065/276] Start webserver according to network mode --- Firmware/RTK_Everywhere/WebServer.ino | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index b1ade1ffe..1e2e5f644 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -6,7 +6,6 @@ Form.ino #ifdef COMPILE_AP - // State machine to allow web server access to network layer enum WebServerState { @@ -302,9 +301,29 @@ bool webServerAssignResources(int httpPort = 80) dnsserver->start(); } - webServer = new WebServer(httpPort); - // TODO: webServer = new WebServer(WiFi.localIP(), httpPort); - // TODO: webServer = new WebServer(ETH.localIP(), httpPort); + // Start the server with a given IP + if (WiFi.getMode() == WIFI_MODE_APSTA) + { + // If we are connected to a local AP, use that IP + if (settings.wifiConfigOverAP == false && wifiIsConnected()) + webServer = new WebServer(WiFi.localIP(), httpPort); + else // Use our own AP's IP + webServer = new WebServer(WiFi.softAPIP(), httpPort); + } + else if (WiFi.getMode() == WIFI_MODE_AP) + webServer = new WebServer(WiFi.softAPIP(), httpPort); + else if (WiFi.getMode() == WIFI_MODE_STA) + webServer = new WebServer(WiFi.localIP(), httpPort); + + // If WiFi is off, fall back to ethernet + else if (WiFi.getMode() == WIFI_OFF && present.ethernet_ws5500) + webServer = new WebServer(ETH.localIP(), httpPort); + + else + { + systemPrintln("Error: Unknown WebServer connection mode."); + return (false); + } if (!webServer) { From 45d89c9c761146037e762dbc02eb19e1d0bee32e Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 2 Jan 2025 15:47:56 -0700 Subject: [PATCH 066/276] Rename STATE_WEB_CONFIG --- Firmware/RTK_Everywhere/Display.ino | 226 ++++++++++----------- Firmware/RTK_Everywhere/Network.ino | 15 ++ Firmware/RTK_Everywhere/RTK_Everywhere.ino | 4 +- Firmware/RTK_Everywhere/States.ino | 30 ++- Firmware/RTK_Everywhere/Tasks.ino | 10 +- Firmware/RTK_Everywhere/WiFi.ino | 4 +- Firmware/RTK_Everywhere/menuSystem.ino | 2 +- Firmware/RTK_Everywhere/settings.h | 6 +- 8 files changed, 154 insertions(+), 143 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 9df679b35..cfa300bf2 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -407,12 +407,12 @@ void displayUpdate() case (STATE_DISPLAY_SETUP): paintDisplaySetup(); break; - case (STATE_WIFI_CONFIG_NOT_STARTED): - displayWiFiConfigNotStarted(); // Display 'WiFi Config' + case (STATE_WEB_CONFIG_NOT_STARTED): + displayWebConfigNotStarted(); // Display 'Web Config' break; - case (STATE_WIFI_CONFIG): setWiFiIcon(&iconPropertyList); // Blink WiFi in center displayWiFiConfig(); // Display SSID and IP + case (STATE_WEB_CONFIG): break; case (STATE_TEST): paintSystemTest(); @@ -2165,116 +2165,6 @@ void displayWiFiConnect() displayMessage("WiFi Connect", 0); } -// When user enters WiFi Config mode from setup, show splash while config happens -void displayWiFiConfigNotStarted() -{ - displayMessage("WiFi Config", 0); -} - -void displayWiFiConfig() -{ - int yPos = WiFi_Symbol_Height + 2; - int fontHeight = 8; - - // Characters before pixels start getting cut off. 11 characters can cut off a few pixels. - const int displayMaxCharacters = (present.display_type == DISPLAY_64x48) ? 10 : 21; - - printTextCenter("SSID:", yPos, QW_FONT_5X7, 1, false); // text, y, font type, kerning, inverted - - yPos = yPos + fontHeight + 1; - - // Toggle display back and forth for long SSIDs and IPs - // Run the timer no matter what, but load firstHalf/lastHalf with the same thing if strlen < maxWidth - if (millis() - ssidDisplayTimer > 2000) - { - ssidDisplayTimer = millis(); - ssidDisplayFirstHalf = !ssidDisplayFirstHalf; - } - - // Convert current SSID to string - char mySSID[50] = {'\0'}; - -#ifdef COMPILE_WIFI - if (settings.wifiConfigOverAP == true) - snprintf(mySSID, sizeof(mySSID), "%s", "RTK Config"); - else - { - if (WiFi.getMode() == WIFI_STA) - snprintf(mySSID, sizeof(mySSID), "%s", WiFi.SSID().c_str()); - - // If we failed to connect to a friendly WiFi, and then fell back to AP mode, still display RTK Config - else if (WiFi.getMode() == WIFI_AP) - snprintf(mySSID, sizeof(mySSID), "%s", "RTK Config"); - - // If we are in AP+STA mode, still display RTK Config - else if (WiFi.getMode() == WIFI_AP_STA) - snprintf(mySSID, sizeof(mySSID), "%s", "RTK Config"); - - else - snprintf(mySSID, sizeof(mySSID), "%s", "Error"); - } -#else // COMPILE_WIFI - snprintf(mySSID, sizeof(mySSID), "%s", "!Compiled"); -#endif // COMPILE_WIFI - - char mySSIDFront[displayMaxCharacters + 1]; // 1 for null terminator - char mySSIDBack[displayMaxCharacters + 1]; // 1 for null terminator - - // Trim SSID to a max length - strncpy(mySSIDFront, mySSID, displayMaxCharacters); - - if (strlen(mySSID) > displayMaxCharacters) - strncpy(mySSIDBack, mySSID + (strlen(mySSID) - displayMaxCharacters), displayMaxCharacters); - else - strncpy(mySSIDBack, mySSID, displayMaxCharacters); - - mySSIDFront[displayMaxCharacters] = '\0'; - mySSIDBack[displayMaxCharacters] = '\0'; - - if (ssidDisplayFirstHalf) - printTextCenter(mySSIDFront, yPos, QW_FONT_5X7, 1, false); - else - printTextCenter(mySSIDBack, yPos, QW_FONT_5X7, 1, false); - - yPos = yPos + fontHeight + 3; - printTextCenter("IP:", yPos, QW_FONT_5X7, 1, false); - - yPos = yPos + fontHeight + 1; - -#ifdef COMPILE_AP - IPAddress myIpAddress; - if ((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) - myIpAddress = WiFi.softAPIP(); - else - myIpAddress = WiFi.localIP(); - - // Convert to string - char myIP[20] = {'\0'}; - snprintf(myIP, sizeof(myIP), "%s", myIpAddress.toString()); - - char myIPFront[displayMaxCharacters + 1]; // 1 for null terminator - char myIPBack[displayMaxCharacters + 1]; // 1 for null terminator - - strncpy(myIPFront, myIP, displayMaxCharacters); - - if (strlen(myIP) > displayMaxCharacters) - strncpy(myIPBack, myIP + (strlen(myIP) - displayMaxCharacters), displayMaxCharacters); - else - strncpy(myIPBack, myIP, displayMaxCharacters); - - myIPFront[displayMaxCharacters] = '\0'; - myIPBack[displayMaxCharacters] = '\0'; - - if (ssidDisplayFirstHalf == true) - printTextCenter(myIPFront, yPos, QW_FONT_5X7, 1, false); - else - printTextCenter(myIPBack, yPos, QW_FONT_5X7, 1, false); - -#else // COMPILE_AP - printTextCenter("!Compiled", yPos, QW_FONT_5X7, 1, false); -#endif // COMPILE_AP -} - // When user does a factory reset, let us know void displaySytemReset() { @@ -3172,6 +3062,116 @@ void displayConfigViaEthStarted(uint16_t displayTime) } } +// When user enters Web Config mode, show splash while web server starts +void displayWebConfigNotStarted() +{ + displayMessage("Web Config", 0); +} + +void displayConfigViaWiFi() +{ + int yPos = WiFi_Symbol_Height + 2; + int fontHeight = 8; + + // Characters before pixels start getting cut off. 11 characters can cut off a few pixels. + const int displayMaxCharacters = (present.display_type == DISPLAY_64x48) ? 10 : 21; + + printTextCenter("SSID:", yPos, QW_FONT_5X7, 1, false); // text, y, font type, kerning, inverted + + yPos = yPos + fontHeight + 1; + + // Toggle display back and forth for long SSIDs and IPs + // Run the timer no matter what, but load firstHalf/lastHalf with the same thing if strlen < maxWidth + if (millis() - ssidDisplayTimer > 2000) + { + ssidDisplayTimer = millis(); + ssidDisplayFirstHalf = !ssidDisplayFirstHalf; + } + + // Convert current SSID to string + char mySSID[50] = {'\0'}; + +#ifdef COMPILE_WIFI + if (settings.wifiConfigOverAP == true) + snprintf(mySSID, sizeof(mySSID), "%s", "RTK Config"); + else + { + if (WiFi.getMode() == WIFI_STA) + snprintf(mySSID, sizeof(mySSID), "%s", WiFi.SSID().c_str()); + + // If we failed to connect to a friendly WiFi, and then fell back to AP mode, still display RTK Config + else if (WiFi.getMode() == WIFI_AP) + snprintf(mySSID, sizeof(mySSID), "%s", "RTK Config"); + + // If we are in AP+STA mode, still display RTK Config + else if (WiFi.getMode() == WIFI_AP_STA) + snprintf(mySSID, sizeof(mySSID), "%s", "RTK Config"); + + else + snprintf(mySSID, sizeof(mySSID), "%s", "Error"); + } +#else // COMPILE_WIFI + snprintf(mySSID, sizeof(mySSID), "%s", "!Compiled"); +#endif // COMPILE_WIFI + + char mySSIDFront[displayMaxCharacters + 1]; // 1 for null terminator + char mySSIDBack[displayMaxCharacters + 1]; // 1 for null terminator + + // Trim SSID to a max length + strncpy(mySSIDFront, mySSID, displayMaxCharacters); + + if (strlen(mySSID) > displayMaxCharacters) + strncpy(mySSIDBack, mySSID + (strlen(mySSID) - displayMaxCharacters), displayMaxCharacters); + else + strncpy(mySSIDBack, mySSID, displayMaxCharacters); + + mySSIDFront[displayMaxCharacters] = '\0'; + mySSIDBack[displayMaxCharacters] = '\0'; + + if (ssidDisplayFirstHalf) + printTextCenter(mySSIDFront, yPos, QW_FONT_5X7, 1, false); + else + printTextCenter(mySSIDBack, yPos, QW_FONT_5X7, 1, false); + + yPos = yPos + fontHeight + 3; + printTextCenter("IP:", yPos, QW_FONT_5X7, 1, false); + + yPos = yPos + fontHeight + 1; + +#ifdef COMPILE_AP + IPAddress myIpAddress; + if ((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) + myIpAddress = WiFi.softAPIP(); + else + myIpAddress = WiFi.localIP(); + + // Convert to string + char myIP[20] = {'\0'}; + snprintf(myIP, sizeof(myIP), "%s", myIpAddress.toString()); + + char myIPFront[displayMaxCharacters + 1]; // 1 for null terminator + char myIPBack[displayMaxCharacters + 1]; // 1 for null terminator + + strncpy(myIPFront, myIP, displayMaxCharacters); + + if (strlen(myIP) > displayMaxCharacters) + strncpy(myIPBack, myIP + (strlen(myIP) - displayMaxCharacters), displayMaxCharacters); + else + strncpy(myIPBack, myIP, displayMaxCharacters); + + myIPFront[displayMaxCharacters] = '\0'; + myIPBack[displayMaxCharacters] = '\0'; + + if (ssidDisplayFirstHalf == true) + printTextCenter(myIPFront, yPos, QW_FONT_5X7, 1, false); + else + printTextCenter(myIPBack, yPos, QW_FONT_5X7, 1, false); + +#else // COMPILE_AP + printTextCenter("!Compiled", yPos, QW_FONT_5X7, 1, false); +#endif // COMPILE_AP +} + void displayConfigViaEthernet() { #ifdef COMPILE_ETHERNET diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 564387e03..991e787d8 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -624,6 +624,21 @@ bool networkIsOnline() return networkOnline ? true : false; } +//---------------------------------------- +// Determine if the given network is online +//---------------------------------------- +bool networkIsOnline(NetIndex_t index) +{ + // Validate the index + networkValidateIndex(index); + + // Check for network offline + NetMask_t bitMask = 1 << index; + if (networkOnline & bitMask) + return true; + return false; +} + //---------------------------------------- // Determine if the network is present on the platform //---------------------------------------- diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 85b36a2f4..cc90c9c37 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -1286,8 +1286,8 @@ void logUpdate() // max log window. systemTime_minutes = millis() / 1000L / 60; - // If we are in AP config, don't touch the SD card - if (inWiFiConfigMode()) + // If we are in Web Config, don't touch the SD card + if (inWebConfigMode()) return; if (online.microSD == false) diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index f5a162717..4dd8f3a31 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -407,7 +407,7 @@ void stateUpdate() } break; - case (STATE_WIFI_CONFIG_NOT_STARTED): { + case (STATE_WEB_CONFIG_NOT_STARTED): { if (pin_bluetoothStatusLED != PIN_UNDEFINED) { // Start BT LED Fade to indicate the start of WiFi @@ -418,7 +418,7 @@ void stateUpdate() baseStatusLedOff(); // Turn off the status LED - displayWiFiConfigNotStarted(); // Display immediately while we wait for server to start + displayWebConfigNotStarted(); // Display immediately while we wait for server to start // TODO - Do we need to stop BT and ESP-NOW during web config or can we leave it running? //bluetoothStop(); @@ -434,11 +434,11 @@ void stateUpdate() webServerStart(); // Start the webserver state machine for web config RTK_MODE(RTK_MODE_WIFI_CONFIG); - changeState(STATE_WIFI_CONFIG); + changeState(STATE_WEB_CONFIG); } break; - case (STATE_WIFI_CONFIG): { + case (STATE_WEB_CONFIG): { if (incomingSettingsSpot > 0) { // Allow for 750ms before we parse buffer for all data to arrive @@ -785,10 +785,10 @@ const char *getState(SystemState state, char *buffer) return "STATE_BASE_FIXED_TRANSMITTING"; case (STATE_DISPLAY_SETUP): return "STATE_DISPLAY_SETUP"; - case (STATE_WIFI_CONFIG_NOT_STARTED): - return "STATE_WIFI_CONFIG_NOT_STARTED"; - case (STATE_WIFI_CONFIG): - return "STATE_WIFI_CONFIG"; + case (STATE_WEB_CONFIG_NOT_STARTED): + return "STATE_WEB_CONFIG_NOT_STARTED"; + case (STATE_WEB_CONFIG): + return "STATE_WEB_CONFIG"; case (STATE_TEST): return "STATE_TEST"; case (STATE_TESTING): @@ -932,9 +932,9 @@ bool inBaseMode() return (false); } -bool inWiFiConfigMode() +bool inWebConfigMode() { - if (systemState >= STATE_WIFI_CONFIG_NOT_STARTED && systemState <= STATE_WIFI_CONFIG) + if (systemState >= STATE_WEB_CONFIG_NOT_STARTED && systemState <= STATE_WEB_CONFIG) return (true); return (false); } @@ -959,19 +959,15 @@ void constructSetupDisplay(std::vector *buttons) { buttons->clear(); - // It looks like we don't need "Mark"? TODO: check this! addSetupButton(buttons, "Base", STATE_BASE_NOT_STARTED); addSetupButton(buttons, "Rover", STATE_ROVER_NOT_STARTED); if (present.ethernet_ws5500 == true) { addSetupButton(buttons, "NTP", STATE_NTPSERVER_NOT_STARTED); - addSetupButton(buttons, "Cfg Eth", STATE_CONFIG_VIA_ETH_NOT_STARTED); - addSetupButton(buttons, "Cfg WiFi", STATE_WIFI_CONFIG_NOT_STARTED); - } - else - { - addSetupButton(buttons, "Config", STATE_WIFI_CONFIG_NOT_STARTED); } + + addSetupButton(buttons, "Config", STATE_WEB_CONFIG_NOT_STARTED); + if (settings.enablePointPerfectCorrections) { addSetupButton(buttons, "Get Keys", STATE_KEYS_REQUESTED); diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index c754df710..2d611339b 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -1380,7 +1380,7 @@ void handleGnssDataTask(void *e) void tickerBluetoothLedUpdate() { // If we are in WiFi config mode, fade LED - if (inWiFiConfigMode() == true) + if (inWebConfigMode() == true) { // Fade in/out the BT LED during WiFi AP mode btFadeLevel += pwmFadeAmount; @@ -1660,11 +1660,11 @@ void buttonCheckTask(void *e) } forceSystemStateUpdate = true; // Immediately go to this new state - changeState(STATE_WIFI_CONFIG_NOT_STARTED); + changeState(STATE_WEB_CONFIG_NOT_STARTED); } // If we are in WiFi Config Mode, exit to Rover - else if (inWiFiConfigMode()) + else if (inWebConfigMode()) { // Beep if we are not locally compiled or a release candidate if (ENABLE_DEVELOPER == false) @@ -1754,8 +1754,8 @@ void buttonCheckTask(void *e) case STATE_BASE_TEMP_TRANSMITTING: case STATE_BASE_FIXED_NOT_STARTED: case STATE_BASE_FIXED_TRANSMITTING: - case STATE_WIFI_CONFIG_NOT_STARTED: - case STATE_WIFI_CONFIG: + case STATE_WEB_CONFIG_NOT_STARTED: + case STATE_WEB_CONFIG: case STATE_ESPNOW_PAIRING_NOT_STARTED: case STATE_ESPNOW_PAIRING: case STATE_NTPSERVER_NOT_STARTED: diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 05adc9722..4f0b46a1e 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -480,8 +480,8 @@ const char *wifiPrintState(wl_status_t wifiStatus) void wifiRestart() { // Restart the AP webServer if we are in that state - if (systemState == STATE_WIFI_CONFIG) - requestChangeState(STATE_WIFI_CONFIG_NOT_STARTED); + if (systemState == STATE_WEB_CONFIG) + requestChangeState(STATE_WEB_CONFIG_NOT_STARTED); else { // Restart WiFi if we are not in AP config mode diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index 5e15699ae..2ef203507 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -407,7 +407,7 @@ void menuSystem() else if (incoming == 'W') { forceSystemStateUpdate = true; // Immediately go to this new state - changeState(STATE_WIFI_CONFIG_NOT_STARTED); + changeState(STATE_WEB_CONFIG_NOT_STARTED); } else if (incoming == 'S' && present.fastPowerOff == true) { diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 72065fabf..906580593 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -26,9 +26,9 @@ typedef enum STATE_BASE_FIXED_NOT_STARTED, STATE_BASE_FIXED_TRANSMITTING, STATE_DISPLAY_SETUP, - STATE_WIFI_CONFIG_NOT_STARTED, - STATE_WIFI_CONFIG_WAIT_FOR_NETWORK, - STATE_WIFI_CONFIG, + STATE_WEB_CONFIG_NOT_STARTED, + STATE_WEB_CONFIG_WAIT_FOR_NETWORK, + STATE_WEB_CONFIG, STATE_TEST, STATE_TESTING, STATE_PROFILE, From 460d12fe799f31d4a717a095c2aa4b5578e192df Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 2 Jan 2025 16:20:16 -0700 Subject: [PATCH 067/276] Remove configureViaEthernet and all STATE_CONFIG_VIA_ETH states. --- Firmware/RTK_Everywhere/Begin.ino | 57 ----- Firmware/RTK_Everywhere/Buttons.ino | 5 - Firmware/RTK_Everywhere/Developer.ino | 1 + Firmware/RTK_Everywhere/Display.ino | 87 +------ Firmware/RTK_Everywhere/Ethernet.ino | 38 +-- Firmware/RTK_Everywhere/GNSS_ZED.ino | 2 - Firmware/RTK_Everywhere/NVM.ino | 16 -- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 15 +- Firmware/RTK_Everywhere/States.ino | 139 +--------- Firmware/RTK_Everywhere/Tasks.ino | 9 - Firmware/RTK_Everywhere/menuCommands.ino | 21 +- Firmware/RTK_Everywhere/menuMain.ino | 284 +++++++++------------ Firmware/RTK_Everywhere/menuPP.ino | 23 -- Firmware/RTK_Everywhere/settings.h | 13 +- 14 files changed, 161 insertions(+), 549 deletions(-) diff --git a/Firmware/RTK_Everywhere/Begin.ino b/Firmware/RTK_Everywhere/Begin.ino index ea70c0923..53ee27c46 100644 --- a/Firmware/RTK_Everywhere/Begin.ino +++ b/Firmware/RTK_Everywhere/Begin.ino @@ -973,14 +973,6 @@ void beginGnssUart() if (present.gnss_to_uart == false) return; - // Skip if going into configure-via-ethernet mode - if (configureViaEthernet) - { - if (settings.debugNetworkLayer) - systemPrintln("configureViaEthernet: skipping beginGnssUart"); - return; - } - size_t length; TaskHandle_t taskHandle; @@ -1073,14 +1065,6 @@ void beginGnssUart2() if (present.gnss_to_uart2 == false) return; - // Skip if going into configure-via-ethernet mode - if (configureViaEthernet) - { - if (settings.debugNetworkLayer) - systemPrintln("configureViaEthernet: skipping beginGnssUart2"); - return; - } - serial2GNSS = new HardwareSerial(1); // Use UART1 on the ESP32 to communicate with the mosaic serial2GNSS->setRxBufferSize(1024 * 1); @@ -1110,47 +1094,6 @@ void beginFS() } } -// Check if configureViaEthernet.txt exists -bool checkConfigureViaEthernet() -{ - if (online.fs == false) - return false; - - if (LittleFS.exists("/configureViaEthernet.txt")) - { - if (settings.debugNetworkLayer) - systemPrintln("LittleFS configureViaEthernet.txt exists"); - LittleFS.remove("/configureViaEthernet.txt"); - return true; - } - - return false; -} - -// Force configure-via-ethernet mode by creating configureViaEthernet.txt in LittleFS -bool forceConfigureViaEthernet() -{ - if (online.fs == false) - return false; - - if (LittleFS.exists("/configureViaEthernet.txt")) - { - if (settings.debugNetworkLayer) - systemPrintln("LittleFS configureViaEthernet.txt already exists"); - return true; - } - - File cveFile = LittleFS.open("/configureViaEthernet.txt", FILE_WRITE); - cveFile.close(); - - if (LittleFS.exists("/configureViaEthernet.txt")) - return true; - - if (settings.debugNetworkLayer) - systemPrintln("Unable to create configureViaEthernet.txt on LittleFS"); - return false; -} - // Begin interrupts void beginInterrupts() { diff --git a/Firmware/RTK_Everywhere/Buttons.ino b/Firmware/RTK_Everywhere/Buttons.ino index 5b2c22484..3f2b24e45 100644 --- a/Firmware/RTK_Everywhere/Buttons.ino +++ b/Firmware/RTK_Everywhere/Buttons.ino @@ -34,11 +34,6 @@ void powerDown(bool displayInfo) // Prevent other tasks from logging, even if access to the microSD card was denied online.logging = false; - // If we are in configureViaEthernet mode, we need to shut down the async web server - // otherwise it causes a core panic and badness at the restart - if (configureViaEthernet) - ethernetWebServerStopESP32W5500(); - if (displayInfo == true) { displayShutdown(); diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 519699165..3f784cd72 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -48,6 +48,7 @@ const uint8_t * networkGetMacAddress() return zero; } bool networkIsOnline() {return false;} +bool networkIsOnline(NetIndex_t index) {return false;} void networkMarkOffline(NetIndex_t index) {} void networkMarkOnline(NetIndex_t index) {} void networkUpdate() {} diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index cfa300bf2..a2ed9412b 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -391,16 +391,6 @@ void displayUpdate() } break; - case (STATE_CONFIG_VIA_ETH_NOT_STARTED): - break; - case (STATE_CONFIG_VIA_ETH_STARTED): - break; - case (STATE_CONFIG_VIA_ETH): - displayConfigViaEthernet(); - break; - case (STATE_CONFIG_VIA_ETH_RESTART_BASE): - break; - case (STATE_PROFILE): paintProfile(displayProfile); break; @@ -410,9 +400,14 @@ void displayUpdate() case (STATE_WEB_CONFIG_NOT_STARTED): displayWebConfigNotStarted(); // Display 'Web Config' break; - setWiFiIcon(&iconPropertyList); // Blink WiFi in center - displayWiFiConfig(); // Display SSID and IP case (STATE_WEB_CONFIG): + if (networkIsOnline(NETWORK_ETHERNET)) + displayConfigViaEthernet(); + else + { + setWiFiIcon(&iconPropertyList); // Blink WiFi in center + displayConfigViaWiFi(); // Display SSID and IP + } break; case (STATE_TEST): paintSystemTest(); @@ -2994,74 +2989,6 @@ void displayNTPFail(uint16_t displayTime) } } -void displayConfigViaEthStarting(uint16_t displayTime) -{ - if (online.display == true) - { - oled->erase(); - - uint8_t fontHeight = 12; - uint8_t yPos = fontHeight; - - printTextCenter("Configure", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - yPos += fontHeight; - printTextCenter("Via", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - yPos += fontHeight; - printTextCenter("Ethernet", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - yPos += fontHeight; - printTextCenter("Starting", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - - oled->display(); - - delay(displayTime); - } -} -void displayConfigViaEthExiting(uint16_t displayTime) -{ - if (online.display == true) - { - oled->erase(); - - uint8_t fontHeight = 12; - uint8_t yPos = fontHeight; - - printTextCenter("Configure", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - yPos += fontHeight; - printTextCenter("Via", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - yPos += fontHeight; - printTextCenter("Ethernet", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - yPos += fontHeight; - printTextCenter("Exiting", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - - oled->display(); - - delay(displayTime); - } -} - -void displayConfigViaEthStarted(uint16_t displayTime) -{ - if (online.display == true) - { - oled->erase(); - - uint8_t fontHeight = 12; - uint8_t yPos = fontHeight; - - printTextCenter("Configure", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - yPos += fontHeight; - printTextCenter("Via", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - yPos += fontHeight; - printTextCenter("Ethernet", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - yPos += fontHeight; - printTextCenter("Started", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - - oled->display(); - - delay(displayTime); - } -} - // When user enters Web Config mode, show splash while web server starts void displayWebConfigNotStarted() { diff --git a/Firmware/RTK_Everywhere/Ethernet.ino b/Firmware/RTK_Everywhere/Ethernet.ino index 661aa2eb7..e53bc16ff 100644 --- a/Firmware/RTK_Everywhere/Ethernet.ino +++ b/Firmware/RTK_Everywhere/Ethernet.ino @@ -268,24 +268,24 @@ void ethernetStart() //---------------------------------------- // Start Ethernet for the web server //---------------------------------------- -void ethernetWebServerStartESP32W5500() -{ - Network.onEvent(ethernetEvent); - - // begin(ETH_PHY_TYPE, ETH_PHY_ADDR, CS, IRQ, RST, SPIClass &) - ETH.begin(ETH_PHY_W5500, 0, pin_Ethernet_CS, pin_Ethernet_Interrupt, -1, SPI); - - if (!settings.ethernetDHCP) - ETH.config(settings.ethernetIP, settings.ethernetGateway, settings.ethernetSubnet, settings.ethernetDNS); -} - -//---------------------------------------- -// Stop Ethernet for the web server -//---------------------------------------- -void ethernetWebServerStopESP32W5500() -{ - ETH.end(); - Network.removeEvent(ethernetEvent); -} +// void ethernetWebServerStartESP32W5500() +// { +// Network.onEvent(ethernetEvent); + +// // begin(ETH_PHY_TYPE, ETH_PHY_ADDR, CS, IRQ, RST, SPIClass &) +// ETH.begin(ETH_PHY_W5500, 0, pin_Ethernet_CS, pin_Ethernet_Interrupt, -1, SPI); + +// if (!settings.ethernetDHCP) +// ETH.config(settings.ethernetIP, settings.ethernetGateway, settings.ethernetSubnet, settings.ethernetDNS); +// } + +// //---------------------------------------- +// // Stop Ethernet for the web server +// //---------------------------------------- +// void ethernetWebServerStopESP32W5500() +// { +// ETH.end(); +// Network.removeEvent(ethernetEvent); +// } #endif // COMPILE_ETHERNET diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.ino b/Firmware/RTK_Everywhere/GNSS_ZED.ino index 38e541a06..752adfc80 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.ino +++ b/Firmware/RTK_Everywhere/GNSS_ZED.ino @@ -142,8 +142,6 @@ void GNSS_ZED::begin() if (_zed == nullptr) _zed = new SFE_UBLOX_GNSS_SUPER(); - // Note: we don't need to skip this for configureViaEthernet because the ZED is on I2C only - not SPI - if (_zed->begin(*i2c_0) == false) { systemPrintln("GNSS Failed to begin. Trying again."); diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index 05d9db528..db807b064 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -66,22 +66,6 @@ void loadSettings() settings.resetCount = resetCount; // resetCount from LFS should override SD - // SD is not accessible during configure-via-Ethernet - // If stateFromLFS indicates that the firmware is not in configure-via-Ethernet mode - if (!((stateFromLFS >= STATE_CONFIG_VIA_ETH_NOT_STARTED) && (stateFromLFS <= STATE_CONFIG_VIA_ETH_RESTART_BASE))) - { - // and lastState from SD indicates the firmware was previously in configure-via-Ethernet mode - if ((settings.lastState >= STATE_CONFIG_VIA_ETH_NOT_STARTED) && - (settings.lastState <= STATE_CONFIG_VIA_ETH_RESTART_BASE)) - { - // then reload the settings from LFS since they will include any changes made during configure-via-Ethernet - // mode - systemPrintln("Restart after config-via-ethernet. Overwriting SD settings with those from LittleFS"); - loadSystemSettingsFromFileLFS(settingsFileName); - recordSystemSettings(); // Overwrite SD settings with those from LFS - } - } - // Change empty profile name to 'Profile1' etc if (strlen(settings.profileName) == 0) { diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index cc90c9c37..933236bac 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -443,7 +443,7 @@ float batteryChargingPercentPerHour; // serial. // // Switching from status and debug messages to GNSS output is done in two -// places, at the end of setup and at the end of maenuMain. In both of +// places, at the end of setup and at the end of menuMain. In both of // these places the new value comes from settings.enableGnssToUsbSerial. // Upon boot status and debug messages are output at least until the end // of setup. Upon entry into menuMain, this value is set false to again @@ -785,13 +785,6 @@ uint16_t failedParserMessages_NMEA; // Corrections Priorities Support CORRECTION_ID_T pplCorrectionsSource = CORR_NUM; // Record which source is feeding the PPL -// configureViaEthernet: -// Set to true if configureViaEthernet.txt exists in LittleFS. -// Previously, the SparkFun_WebServer_ESP32_W5500 needed _exclusive_ access to SPI and Interrupts. -// That's no longer true - thanks to Espressif adding full support for the W5500 within the -// arduino-esp32 core (v3.0.0+). But it's easier to leave the code as it is. -bool configureViaEthernet; - int floatLockRestarts; unsigned long rtkTimeToFixMs; @@ -821,7 +814,7 @@ unsigned long loraLastIncomingSerial; // Last time a user sent a serial command. // Display boot times //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -#define MAX_BOOT_TIME_ENTRIES 42 +#define MAX_BOOT_TIME_ENTRIES 41 uint8_t bootTimeIndex; uint32_t bootTime[MAX_BOOT_TIME_ENTRIES]; const char *bootTimeString[MAX_BOOT_TIME_ENTRIES]; @@ -1044,10 +1037,6 @@ void setup() if (um980FirmwareCheckUpdate() == true) // Check if updateUm980Firmware.txt exists um980FirmwareBeginUpdate(); - DMW_b("checkConfigureViaEthernet"); - configureViaEthernet = - checkConfigureViaEthernet(); // Check if going into dedicated configureViaEthernet (STATE_CONFIG_VIA_ETH) mode - DMW_b("beginPsram"); beginPsram(); // Inialize PSRAM (if available). Needs to occur before beginGnssUart and other malloc users. diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 4dd8f3a31..b7132d943 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -421,10 +421,10 @@ void stateUpdate() displayWebConfigNotStarted(); // Display immediately while we wait for server to start // TODO - Do we need to stop BT and ESP-NOW during web config or can we leave it running? - //bluetoothStop(); - //espnowStop(); + // bluetoothStop(); + // espnowStop(); - //tasksStopGnssUart(); // Delete serial tasks if running + // tasksStopGnssUart(); // Delete serial tasks if running // Stop any running NTRIP Client or Server ntripClientStop(true); // Do not allocate new wifiClient @@ -433,7 +433,7 @@ void stateUpdate() webServerStart(); // Start the webserver state machine for web config - RTK_MODE(RTK_MODE_WIFI_CONFIG); + RTK_MODE(RTK_MODE_WEB_CONFIG); changeState(STATE_WEB_CONFIG); } break; @@ -622,114 +622,6 @@ void stateUpdate() } break; - case (STATE_CONFIG_VIA_ETH_NOT_STARTED): { - displayConfigViaEthStarting(1500); - - settings.updateGNSSSettings = false; // On the next boot, no need to update the GNSS on this profile - settings.lastState = STATE_CONFIG_VIA_ETH_STARTED; // Record the _next_ state for POR - recordSystemSettings(); - - forceConfigureViaEthernet(); // Create a file in LittleFS to force code into configure-via-ethernet mode - - ESP.restart(); // Restart to go into the dedicated configure-via-ethernet mode - } - break; - - case (STATE_CONFIG_VIA_ETH_STARTED): { - RTK_MODE(RTK_MODE_ETHERNET_CONFIG); - // The code should only be able to enter this state if configureViaEthernet is true. - // If configureViaEthernet is not true, we need to restart again. - if (!configureViaEthernet) - { - displayConfigViaEthStarting(1500); - settings.lastState = STATE_CONFIG_VIA_ETH_STARTED; // Re-record this state for POR - recordSystemSettings(); - - forceConfigureViaEthernet(); // Create a file in LittleFS to force code into configure-via-ethernet mode - - ESP.restart(); // Restart to go into the dedicated configure-via-ethernet mode - } - - displayConfigViaEthStarted(1500); - - bluetoothStop(); // Should be redundant - but just in case - espnowStop(); // Should be redundant - but just in case - tasksStopGnssUart(); // Delete F9 serial tasks if running - - ethernetWebServerStartESP32W5500(); // Start Ethernet in dedicated configure-via-ethernet mode - - webServerStart(); // Start the webserver state machine for web config - - // TODO add a state machine step for ethernet to wait for web server to start - // See wifi web server / web config - - // if (!webServerStart(false, settings.httpPort)) // Start the web server - // changeState(STATE_ROVER_NOT_STARTED); - // else - // changeState(STATE_CONFIG_VIA_ETH); - } - break; - - case (STATE_CONFIG_VIA_ETH): { - // Display will show the IP address (displayConfigViaEthernet) - - if (incomingSettingsSpot > 0) - { - // Allow for 750ms before we parse buffer for all data to arrive - if (millis() - timeSinceLastIncomingSetting > 750) - { - currentlyParsingData = - true; // Disallow new data to flow from websocket while we are parsing the current data - - systemPrint("Parsing: "); - for (int x = 0; x < incomingSettingsSpot; x++) - systemWrite(incomingSettings[x]); - systemPrintln(); - - parseIncomingSettings(); - settings.updateGNSSSettings = - true; // When this profile is loaded next, force system to update GNSS settings. - recordSystemSettings(); // Record these settings to unit - - // Clear buffer - incomingSettingsSpot = 0; - memset(incomingSettings, 0, AP_CONFIG_SETTING_SIZE); - - currentlyParsingData = false; // Allow new data from websocket - } - } - -#ifdef COMPILE_WIFI -#ifdef COMPILE_AP - // Dynamically update the coordinates on the AP page - if (websocketConnected == true) - { - if (millis() - lastDynamicDataUpdate > 1000) - { - lastDynamicDataUpdate = millis(); - createDynamicDataString(settingsCSV); - - // log_d("Sending coordinates: %s", settingsCSV); - sendStringToWebsocket(settingsCSV); - } - } -#endif // COMPILE_AP -#endif // COMPILE_WIFI - } - break; - - case (STATE_CONFIG_VIA_ETH_RESTART_BASE): { - displayConfigViaEthExiting(1000); - - ethernetWebServerStopESP32W5500(); - - settings.updateGNSSSettings = false; // On the next boot, no need to update the GNSS on this profile - settings.lastState = STATE_BASE_NOT_STARTED; // Record the _next_ state for POR - recordSystemSettings(); - - ESP.restart(); - } - break; #endif // COMPILE_ETHERNET case (STATE_SHUTDOWN): { @@ -811,15 +703,6 @@ const char *getState(SystemState state, char *buffer) case (STATE_NTPSERVER_SYNC): return "STATE_NTPSERVER_SYNC"; - case (STATE_CONFIG_VIA_ETH_NOT_STARTED): - return "STATE_CONFIG_VIA_ETH_NOT_STARTED"; - case (STATE_CONFIG_VIA_ETH_STARTED): - return "STATE_CONFIG_VIA_ETH_STARTED"; - case (STATE_CONFIG_VIA_ETH): - return "STATE_CONFIG_VIA_ETH"; - case (STATE_CONFIG_VIA_ETH_RESTART_BASE): - return "STATE_CONFIG_VIA_ETH_RESTART_BASE"; - case (STATE_SHUTDOWN): return "STATE_SHUTDOWN"; case (STATE_NOT_SET): @@ -892,14 +775,12 @@ typedef struct _RTK_MODE_ENTRY SystemState last; } RTK_MODE_ENTRY; -const RTK_MODE_ENTRY stateModeTable[] = { - {"Rover", STATE_ROVER_NOT_STARTED, STATE_ROVER_RTK_FIX}, - {"Base", STATE_BASE_NOT_STARTED, STATE_BASE_FIXED_TRANSMITTING}, - {"Setup", STATE_DISPLAY_SETUP, STATE_PROFILE}, - {"ESPNOW Pairing", STATE_ESPNOW_PAIRING_NOT_STARTED, STATE_ESPNOW_PAIRING}, - {"NTP", STATE_NTPSERVER_NOT_STARTED, STATE_NTPSERVER_SYNC}, - {"Ethernet Config", STATE_CONFIG_VIA_ETH_NOT_STARTED, STATE_CONFIG_VIA_ETH_RESTART_BASE}, - {"Shutdown", STATE_SHUTDOWN, STATE_SHUTDOWN}}; +const RTK_MODE_ENTRY stateModeTable[] = {{"Rover", STATE_ROVER_NOT_STARTED, STATE_ROVER_RTK_FIX}, + {"Base", STATE_BASE_NOT_STARTED, STATE_BASE_FIXED_TRANSMITTING}, + {"Setup", STATE_DISPLAY_SETUP, STATE_PROFILE}, + {"ESPNOW Pairing", STATE_ESPNOW_PAIRING_NOT_STARTED, STATE_ESPNOW_PAIRING}, + {"NTP", STATE_NTPSERVER_NOT_STARTED, STATE_NTPSERVER_SYNC}, + {"Shutdown", STATE_SHUTDOWN, STATE_SHUTDOWN}}; const int stateModeTableEntries = sizeof(stateModeTable) / sizeof(stateModeTable[0]); const char *stateToRtkMode(SystemState state) diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index 2d611339b..af3d432c4 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -1761,7 +1761,6 @@ void buttonCheckTask(void *e) case STATE_NTPSERVER_NOT_STARTED: case STATE_NTPSERVER_NO_SYNC: case STATE_NTPSERVER_SYNC: - case STATE_CONFIG_VIA_ETH_NOT_STARTED: lastSystemState = systemState; // Remember this state to return if needed requestChangeState(STATE_DISPLAY_SETUP); lastSetupMenuChange = millis(); @@ -1819,14 +1818,6 @@ void buttonCheckTask(void *e) // Allow system to return to lastSystemState break; - case STATE_CONFIG_VIA_ETH_STARTED: - case STATE_CONFIG_VIA_ETH: - // If the user presses the button during configure-via-ethernet, - // do a complete restart into Base mode - lastSetupMenuChange = millis(); // Prevent a timeout during state change - requestChangeState(STATE_CONFIG_VIA_ETH_RESTART_BASE); - break; - default: systemPrintf("buttonCheckTask single tap - untrapped system state: %d\r\n", systemState); // requestChangeState(STATE_BASE_NOT_STARTED); diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index 43807512e..6a278d2f4 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -1213,26 +1213,7 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting sendStringToWebsocket((char *)"confirmReset,1,"); delay(500); // Allow for delivery - if (configureViaEthernet) - systemPrintln("Reset after Configure-Via-Ethernet"); - else - systemPrintln("Reset after AP Config"); - - if (configureViaEthernet) - { - ethernetWebServerStopESP32W5500(); - - // We need to exit configure-via-ethernet mode. - // But if the settings have not been saved then lastState will still be STATE_CONFIG_VIA_ETH_STARTED. - // If that is true, then force exit to Base mode. I think it is the best we can do. - //(If the settings have been saved, then the code will restart in NTP, Base or Rover mode as desired.) - if (settings.lastState == STATE_CONFIG_VIA_ETH_STARTED) - { - systemPrintln("Settings were not saved. Resetting into Base mode."); - settings.lastState = STATE_BASE_NOT_STARTED; - recordSystemSettings(); - } - } + systemPrintln("Reset after AP Config"); ESP.restart(); } diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 4b52b5927..a2a0f482e 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -128,220 +128,170 @@ void menuMain() return; } - if (configureViaEthernet) + while (1) { - while (1) - { - systemPrintln(); - char versionString[21]; - getFirmwareVersion(versionString, sizeof(versionString), true); - RTKBrandAttribute *brandAttributes = getBrandAttributeFromBrand(present.brand); - systemPrintf("%s RTK %s %s\r\n", brandAttributes->name, platformPrefix, versionString); - - systemPrintln("\r\n** Configure Via Ethernet Mode **\r\n"); - - systemPrintln("Menu: Main"); - - systemPrintln("r) Restart Base"); - - systemPrintln("x) Exit"); - - byte incoming = getUserInputCharacterNumber(); - - if (incoming == 'r') - { - displayConfigViaEthStarting(1000); - - ethernetWebServerStopESP32W5500(); + systemPrintln(); + char versionString[21]; + getFirmwareVersion(versionString, sizeof(versionString), true); + RTKBrandAttribute *brandAttributes = getBrandAttributeFromBrand(present.brand); + systemPrintf("%s RTK %s %s\r\n", brandAttributes->name, platformPrefix, versionString); - settings.updateGNSSSettings = false; // On the next boot, no need to update the GNSS on this profile - settings.lastState = STATE_BASE_NOT_STARTED; // Record the _next_ state for POR - recordSystemSettings(); +#ifdef COMPILE_BT - ESP.restart(); - } - else if (incoming == 'x') - break; - else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_EMPTY) - break; - else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_TIMEOUT) - break; - else - printUnknown(incoming); + if (settings.bluetoothRadioType == BLUETOOTH_RADIO_SPP_AND_BLE) + { + systemPrint("** Bluetooth SPP and BLE broadcasting as: "); + systemPrint(deviceName); } - } - - else - { - while (1) + else if (settings.bluetoothRadioType == BLUETOOTH_RADIO_SPP) { - systemPrintln(); - char versionString[21]; - getFirmwareVersion(versionString, sizeof(versionString), true); - RTKBrandAttribute *brandAttributes = getBrandAttributeFromBrand(present.brand); - systemPrintf("%s RTK %s %s\r\n", brandAttributes->name, platformPrefix, versionString); - -#ifdef COMPILE_BT - - if (settings.bluetoothRadioType == BLUETOOTH_RADIO_SPP_AND_BLE) - { - systemPrint("** Bluetooth SPP and BLE broadcasting as: "); - systemPrint(deviceName); - } - else if (settings.bluetoothRadioType == BLUETOOTH_RADIO_SPP) - { - systemPrint("** Bluetooth SPP broadcasting as: "); - systemPrint(deviceName); - } - else if (settings.bluetoothRadioType == BLUETOOTH_RADIO_BLE) - { - systemPrint("** Bluetooth Low-Energy broadcasting as: "); - systemPrint(deviceName); - } - else if (settings.bluetoothRadioType == BLUETOOTH_RADIO_OFF) - { - systemPrint("** Bluetooth Turned Off"); - } - systemPrintln(" **"); + systemPrint("** Bluetooth SPP broadcasting as: "); + systemPrint(deviceName); + } + else if (settings.bluetoothRadioType == BLUETOOTH_RADIO_BLE) + { + systemPrint("** Bluetooth Low-Energy broadcasting as: "); + systemPrint(deviceName); + } + else if (settings.bluetoothRadioType == BLUETOOTH_RADIO_OFF) + { + systemPrint("** Bluetooth Turned Off"); + } + systemPrintln(" **"); #else // COMPILE_BT - systemPrintln("** Bluetooth Not Compiled **"); + systemPrintln("** Bluetooth Not Compiled **"); #endif // COMPILE_BT - systemPrintln("Menu: Main"); + systemPrintln("Menu: Main"); - systemPrintln("1) Configure GNSS Receiver"); + systemPrintln("1) Configure GNSS Receiver"); - systemPrintln("2) Configure GNSS Messages"); + systemPrintln("2) Configure GNSS Messages"); - systemPrintln("3) Configure Base"); + systemPrintln("3) Configure Base"); - systemPrintln("4) Configure Ports"); + systemPrintln("4) Configure Ports"); - if (productVariant != RTK_TORCH) // Torch does not have logging - systemPrintln("5) Configure Logging"); + if (productVariant != RTK_TORCH) // Torch does not have logging + systemPrintln("5) Configure Logging"); #ifdef COMPILE_WIFI - systemPrintln("6) Configure WiFi"); + systemPrintln("6) Configure WiFi"); #else // COMPILE_WIFI - systemPrintln("6) **WiFi Not Compiled**"); + systemPrintln("6) **WiFi Not Compiled**"); #endif // COMPILE_WIFI #ifdef COMPILE_NETWORK - systemPrintln("7) Configure TCP/UDP"); + systemPrintln("7) Configure TCP/UDP"); #else // COMPILE_NETWORK - systemPrintln("7) **TCP/UDP Not Compiled**"); + systemPrintln("7) **TCP/UDP Not Compiled**"); #endif // COMPILE_NETWORK #ifdef COMPILE_ETHERNET - if (present.ethernet_ws5500 == true) - systemPrintln("e) Configure Ethernet"); + if (present.ethernet_ws5500 == true) + systemPrintln("e) Configure Ethernet"); #endif // COMPILE_ETHERNET - systemPrintln("f) Firmware Update"); + systemPrintln("f) Firmware Update"); - systemPrintln("i) Configure Corrections Priorities"); + systemPrintln("i) Configure Corrections Priorities"); #ifdef COMPILE_ETHERNET - if (present.ethernet_ws5500 == true) - systemPrintln("n) Configure NTP"); + if (present.ethernet_ws5500 == true) + systemPrintln("n) Configure NTP"); #endif // COMPILE_ETHERNET - systemPrintln("p) Configure PointPerfect"); + systemPrintln("p) Configure PointPerfect"); - systemPrintln("r) Configure Radios"); + systemPrintln("r) Configure Radios"); - systemPrintln("s) Configure System"); + systemPrintln("s) Configure System"); - if (present.imu_im19) - systemPrintln("t) Configure Instrument Setup"); + if (present.imu_im19) + systemPrintln("t) Configure Instrument Setup"); - systemPrintln("u) Configure User Profiles"); + systemPrintln("u) Configure User Profiles"); - if (btPrintEcho) - systemPrintln("b) Exit Bluetooth Echo mode"); + if (btPrintEcho) + systemPrintln("b) Exit Bluetooth Echo mode"); - systemPrintln("+) Enter Command line mode"); + systemPrintln("+) Enter Command line mode"); - systemPrintln("x) Exit"); + systemPrintln("x) Exit"); - byte incoming = getUserInputCharacterNumber(); + byte incoming = getUserInputCharacterNumber(); - if (incoming == 1) - menuGNSS(); - else if (incoming == 2) - gnss->menuMessages(); - else if (incoming == 3) - menuBase(); - else if (incoming == 4) - menuPorts(); + if (incoming == 1) + menuGNSS(); + else if (incoming == 2) + gnss->menuMessages(); + else if (incoming == 3) + menuBase(); + else if (incoming == 4) + menuPorts(); #ifdef COMPILE_MOSAICX5 - else if (incoming == 5 && productVariant == RTK_FACET_MOSAIC) - menuLogMosaic(); -#endif // COMPILE_MOSAICX5 - else if (incoming == 5 && productVariant != RTK_TORCH) // Torch does not have logging - menuLog(); - else if (incoming == 6) - menuWiFi(); - else if (incoming == 7) - menuTcpUdp(); - else if (incoming == 'e' && (present.ethernet_ws5500 == true)) - menuEthernet(); - else if (incoming == 'f') - menuFirmware(); - else if (incoming == 'i') - menuCorrectionsPriorities(); - else if (incoming == 'n' && (present.ethernet_ws5500 == true)) - menuNTP(); - else if (incoming == 'u') - menuUserProfiles(); - else if (incoming == 'p') - menuPointPerfect(); - else if (incoming == 'r') - menuRadio(); - else if (incoming == 's') - menuSystem(); - else if ((incoming == 't') && present.imu_im19) - menuInstrument(); - else if (incoming == 'b' && btPrintEcho == true) - { - printEndpoint = PRINT_ENDPOINT_SERIAL; - systemPrintln("BT device has exited echo mode"); - btPrintEcho = false; - break; // Exit config menu - } - else if (incoming == '+') - menuCommands(); - else if (incoming == 'x') - break; - else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_EMPTY) - break; - else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_TIMEOUT) - break; - else - printUnknown(incoming); + else if (incoming == 5 && productVariant == RTK_FACET_MOSAIC) + menuLogMosaic(); +#endif // COMPILE_MOSAICX5 + else if (incoming == 5 && productVariant != RTK_TORCH) // Torch does not have logging + menuLog(); + else if (incoming == 6) + menuWiFi(); + else if (incoming == 7) + menuTcpUdp(); + else if (incoming == 'e' && (present.ethernet_ws5500 == true)) + menuEthernet(); + else if (incoming == 'f') + menuFirmware(); + else if (incoming == 'i') + menuCorrectionsPriorities(); + else if (incoming == 'n' && (present.ethernet_ws5500 == true)) + menuNTP(); + else if (incoming == 'u') + menuUserProfiles(); + else if (incoming == 'p') + menuPointPerfect(); + else if (incoming == 'r') + menuRadio(); + else if (incoming == 's') + menuSystem(); + else if ((incoming == 't') && present.imu_im19) + menuInstrument(); + else if (incoming == 'b' && btPrintEcho == true) + { + printEndpoint = PRINT_ENDPOINT_SERIAL; + systemPrintln("BT device has exited echo mode"); + btPrintEcho = false; + break; // Exit config menu } + else if (incoming == '+') + menuCommands(); + else if (incoming == 'x') + break; + else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_EMPTY) + break; + else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_TIMEOUT) + break; + else + printUnknown(incoming); } - if (!configureViaEthernet) + // Reboot as base only if currently operating as a base station + if (restartBase == true && inBaseMode() == true) { + restartBase = false; + requestChangeState(STATE_BASE_NOT_STARTED); // Restart base upon exit for latest changes to take effect + } - // Reboot as base only if currently operating as a base station - if (restartBase == true && inBaseMode() == true) - { - restartBase = false; - requestChangeState(STATE_BASE_NOT_STARTED); // Restart base upon exit for latest changes to take effect - } - - if (restartRover == true && inRoverMode() == true) - { - restartRover = false; - requestChangeState(STATE_ROVER_NOT_STARTED); // Restart rover upon exit for latest changes to take effect - } + if (restartRover == true && inRoverMode() == true) + { + restartRover = false; + requestChangeState(STATE_ROVER_NOT_STARTED); // Restart rover upon exit for latest changes to take effect + } - gnss->saveConfiguration(); + gnss->saveConfiguration(); - recordSystemSettings(); // Once all menus have exited, record the new settings to LittleFS and config file - } + recordSystemSettings(); // Once all menus have exited, record the new settings to LittleFS and config file if (settings.debugGnss == true) { diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index a58ad7383..a491617ca 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -724,13 +724,6 @@ long gpsToMjd(long GpsCycle, long GpsWeek, long GpsSeconds) // If GNSS is mosaic-X5, configure LBandBeam1 void beginLBand() { - // Skip if going into configure-via-ethernet mode - if (configureViaEthernet) - { - if (settings.debugCorrections == true) - systemPrintln("configureViaEthernet: skipping beginLBand"); - return; - } #ifdef COMPILE_L_BAND if (present.lband_neo) @@ -1094,14 +1087,6 @@ void updateLBand() static unsigned long lbandLastReport; static unsigned long lbandTimeFloatStarted; // Monitors the ZED during L-Band reception if a fix takes too long - // Skip if in configure-via-ethernet mode - if (configureViaEthernet) - { - // if (settings.debugCorrections == true) - // systemPrintln("configureViaEthernet: skipping updateLBand"); - return; - } - #ifdef COMPILE_L_BAND if (online.lbandCorrections == true) { @@ -1235,14 +1220,6 @@ bool provisioningNeedsNetwork() void provisioningUpdate() { - // Skip if in configure-via-ethernet mode - if (configureViaEthernet) - { - // if (settings.debugCorrections == true) - // systemPrintln("configureViaEthernet: skipping updateProvisioning"); - return; - } - DMW_st(provisioningSetState, provisioningState); switch (provisioningState) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 906580593..ab91ac318 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -38,10 +38,6 @@ typedef enum STATE_NTPSERVER_NOT_STARTED, STATE_NTPSERVER_NO_SYNC, STATE_NTPSERVER_SYNC, - STATE_CONFIG_VIA_ETH_NOT_STARTED, - STATE_CONFIG_VIA_ETH_STARTED, - STATE_CONFIG_VIA_ETH, - STATE_CONFIG_VIA_ETH_RESTART_BASE, STATE_SHUTDOWN, STATE_NOT_SET, // Must be last on list } SystemState; @@ -53,11 +49,10 @@ bool newSystemStateRequested = false; // Base modes set with RTK_MODE #define RTK_MODE_BASE_FIXED 0x0001 #define RTK_MODE_BASE_SURVEY_IN 0x0002 -#define RTK_MODE_ETHERNET_CONFIG 0x0004 -#define RTK_MODE_NTP 0x0008 -#define RTK_MODE_ROVER 0x0010 -#define RTK_MODE_TESTING 0x0020 -#define RTK_MODE_WIFI_CONFIG 0x0040 +#define RTK_MODE_NTP 0x0004 +#define RTK_MODE_ROVER 0x0008 +#define RTK_MODE_TESTING 0x0010 +#define RTK_MODE_WEB_CONFIG 0x0020 typedef uint8_t RtkMode_t; From 369898b7ff25f18f60bc30eb7dde28cd8267fb00 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 2 Jan 2025 16:27:05 -0700 Subject: [PATCH 068/276] Remove all things LogTest This test was used in early days of ZED logging before the SEMP was in place. No longer relevant or needed. --- Firmware/RTK_Everywhere/NVM.ino | 10 +- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 8 +- Firmware/RTK_Everywhere/menuMessages.ino | 184 --------------------- Firmware/RTK_Everywhere/menuSystem.ino | 11 -- Firmware/RTK_Everywhere/settings.h | 25 --- 5 files changed, 6 insertions(+), 232 deletions(-) diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index db807b064..b9b39604e 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -222,10 +222,10 @@ void recordSystemSettingsToFile(File *settingsFile) if (settingAvailableOnPlatform(i) == false) continue; - // Exceptions: - // runLogTest not stored in NVM - if (strcmp(rtkSettingsEntries[i].name, "runLogTest") == 0) - continue; + // Exceptions not stored in NVM: + // none currently + // if (strcmp(rtkSettingsEntries[i].name, "example") == 0) + // continue; switch (rtkSettingsEntries[i].type) { @@ -990,7 +990,7 @@ bool parseLine(char *str) { const char *table[] = { "gnssFirmwareVersion", "gnssUniqueId", "neoFirmwareVersion", - "rtkFirmwareVersion", "rtkIdentifier", "runLogTest", + "rtkFirmwareVersion", "rtkIdentifier", }; const int tableEntries = sizeof(table) / sizeof(table[0]); diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 933236bac..adec3f3a5 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -1304,10 +1304,7 @@ void logUpdate() else if (online.logging == true && settings.enableLogging == true && (systemTime_minutes - startCurrentLogTime_minutes) >= settings.maxLogLength_minutes) { - if (settings.runLogTest == false) - endSD(false, true); // Close down file. A new one will be created at the next calling of updateLogs(). - else if (settings.runLogTest == true) - updateLogTest(); + endSD(false, true); // Close down file. A new one will be created at the next calling of updateLogs(). } if (online.logging == true) @@ -1594,9 +1591,6 @@ void getSemaphoreFunction(char *functionName) case FUNCTION_FINDLOG: strcpy(functionName, "Find Log"); break; - case FUNCTION_LOGTEST: - strcpy(functionName, "Log Test"); - break; case FUNCTION_FILELIST: strcpy(functionName, "File List"); break; diff --git a/Firmware/RTK_Everywhere/menuMessages.ino b/Firmware/RTK_Everywhere/menuMessages.ino index 30734acf3..f838fb3e7 100644 --- a/Firmware/RTK_Everywhere/menuMessages.ino +++ b/Firmware/RTK_Everywhere/menuMessages.ino @@ -744,187 +744,3 @@ void setLoggingType() { loggingType = (LoggingType)gnss->getLoggingType(); } - -// During the logging test, we have to modify the messages and rate of the device -void setLogTestFrequencyMessages(int rate, int messages) -{ -#ifdef COMPILE_ZED - // Set measurement frequency - gnss->setRate(1.0 / (double)rate); // Convert Hz to seconds. This will set settings.measurementRateMs, - // settings.navigationRate, and GSV message - - // Set messages - setGNSSMessageRates(settings.ubxMessageRates, 0); // Turn off all messages - GNSS_ZED * zed = (GNSS_ZED *)gnss; - if (messages == 5) - { - zed->setMessageRateByName("NMEA_GGA", 1); - zed->setMessageRateByName("NMEA_GSA", 1); - zed->setMessageRateByName("NMEA_GST", 1); - zed->setMessageRateByName("NMEA_GSV", rate); // One report per second - zed->setMessageRateByName("NMEA_RMC", 1); - - log_d("Messages: Surveying Defaults (NMEAx5)"); - } - else if (messages == 7) - { - zed->setMessageRateByName("NMEA_GGA", 1); - zed->setMessageRateByName("NMEA_GSA", 1); - zed->setMessageRateByName("NMEA_GST", 1); - zed->setMessageRateByName("NMEA_GSV", rate); // One report per second - zed->setMessageRateByName("NMEA_RMC", 1); - zed->setMessageRateByName("RXM_RAWX", 1); - zed->setMessageRateByName("RXM_SFRBX", 1); - - log_d("Messages: PPP NMEAx5+RXMx2"); - } - else - log_d("Unknown message amount"); - - // Apply these message rates to both UART1 / SPI and USB - gnss->setMessages(MAX_SET_MESSAGES_RETRIES); // Does a complete open/closed val set - gnss->setMessagesUsb(MAX_SET_MESSAGES_RETRIES); -#endif // COMPILE_ZED -} - -// The log test allows us to record a series of different system configurations into -// one file. At the same time, we log the output of the ZED via the USB connection. -// Once complete, the SD log is compared against the USB log to verify both are identical. -// Be sure to set maxLogLength_minutes before running test. maxLogLength_minutes will -// set the length of each test. -void updateLogTest() -{ - // Log is complete, run next text - int rate = 4; - int messages = 5; - int semaphoreWait = 10; - - // Advance to next state - // Note: logTestState is LOGTEST_END by default. - // The increment causes the default switch case to be executed, resetting logTestState to LOGTEST_END. - // The test is started via the debug menu, setting logTestState to LOGTEST_START. - logTestState++; - - switch (logTestState) - { - default: - logTestState = LOGTEST_END; - settings.runLogTest = false; - break; - - case (LOGTEST_4HZ_5MSG_10MS): - // During the first test, create the log file - reuseLastLog = false; - char fileName[100]; - snprintf(fileName, sizeof(fileName), "/%s_LogTest_%02d%02d%02d_%02d%02d%02d.ubx", // SdFat library - platformFilePrefix, rtc.getYear() - 2000, rtc.getMonth() + 1, - rtc.getDay(), // ESP32Time returns month:0-11 - rtc.getHour(true), rtc.getMinute(), rtc.getSecond() // ESP32Time getHour(true) returns hour:0-23 - ); - endSD(false, true); // End previous log - - beginLogging(fileName); - - rate = 4; - messages = 5; - semaphoreWait = 10; - break; - case (LOGTEST_4HZ_7MSG_10MS): - rate = 4; - messages = 7; - semaphoreWait = 10; - break; - case (LOGTEST_10HZ_5MSG_10MS): - rate = 10; - messages = 5; - semaphoreWait = 10; - break; - case (LOGTEST_10HZ_7MSG_10MS): - rate = 10; - messages = 7; - semaphoreWait = 10; - break; - - case (LOGTEST_4HZ_5MSG_0MS): - rate = 4; - messages = 5; - semaphoreWait = 0; - break; - case (LOGTEST_4HZ_7MSG_0MS): - rate = 4; - messages = 7; - semaphoreWait = 0; - break; - case (LOGTEST_10HZ_5MSG_0MS): - rate = 10; - messages = 5; - semaphoreWait = 0; - break; - case (LOGTEST_10HZ_7MSG_0MS): - rate = 10; - messages = 7; - semaphoreWait = 0; - break; - - case (LOGTEST_4HZ_5MSG_50MS): - rate = 4; - messages = 5; - semaphoreWait = 50; - break; - case (LOGTEST_4HZ_7MSG_50MS): - rate = 4; - messages = 7; - semaphoreWait = 50; - break; - case (LOGTEST_10HZ_5MSG_50MS): - rate = 10; - messages = 5; - semaphoreWait = 50; - break; - case (LOGTEST_10HZ_7MSG_50MS): - rate = 10; - messages = 7; - semaphoreWait = 50; - break; - - case (LOGTEST_END): - // Reduce rate - rate = 4; - messages = 5; - semaphoreWait = 10; - setLogTestFrequencyMessages(rate, messages); // Set messages and rate for both UART1 / SPI and USB ports - log_d("Log Test Complete"); - break; - } - - if (settings.runLogTest == true) - { - setLogTestFrequencyMessages(rate, messages); // Set messages and rate for both UART1 / SPI and USB ports - - loggingSemaphoreWait_ms = semaphoreWait / portTICK_PERIOD_MS; // Update variable - - startCurrentLogTime_minutes = millis() / 1000L / 60; // Mark now as start of logging - - char logMessage[100]; - snprintf(logMessage, sizeof(logMessage), "Start log test: %dHz, %dMsg, %dMS", rate, messages, semaphoreWait); - - char nmeaMessage[100]; // Max NMEA sentence length is 82 - createNMEASentence(CUSTOM_NMEA_TYPE_LOGTEST_STATUS, nmeaMessage, sizeof(nmeaMessage), - logMessage); // textID, buffer, sizeOfBuffer, text - - if (xSemaphoreTake(sdCardSemaphore, fatSemaphore_longWait_ms) == pdPASS) - { - markSemaphore(FUNCTION_LOGTEST); - - logFile->println(nmeaMessage); - - xSemaphoreGive(sdCardSemaphore); - } - else - { - log_w("sdCardSemaphore failed to yield, menuMessages.ino line %d", __LINE__); - } - - systemPrintf("%s\r\n", logMessage); - } -} diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index 2ef203507..e201bf7a0 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -464,9 +464,6 @@ void menuDebugHardware() systemPrint("5) Print log file status: "); systemPrintf("%s\r\n", settings.enablePrintLogFileStatus ? "Enabled" : "Disabled"); - systemPrint("6) Run Logging Test: "); - systemPrintf("%s\r\n", settings.runLogTest ? "Enabled" : "Disabled"); - systemPrint("7) Print SD and UART buffer sizes: "); systemPrintf("%s\r\n", settings.enablePrintSDBuffers ? "Enabled" : "Disabled"); @@ -532,15 +529,7 @@ void menuDebugHardware() settings.enablePrintLogFileMessages ^= 1; else if (incoming == 5) settings.enablePrintLogFileStatus ^= 1; - else if (incoming == 6) - { - settings.runLogTest ^= 1; - logTestState = LOGTEST_START; // Start test - - // Mark the current log file as complete to force the test start - startCurrentLogTime_minutes = systemTime_minutes - settings.maxLogLength_minutes; - } else if (incoming == 7) settings.enablePrintSDBuffers ^= 1; else if (incoming == 9) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index ab91ac318..92c5cbf34 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -233,7 +233,6 @@ typedef enum CUSTOM_NMEA_TYPE_SYSTEM_VERSION, CUSTOM_NMEA_TYPE_ZED_VERSION, CUSTOM_NMEA_TYPE_STATUS, - CUSTOM_NMEA_TYPE_LOGTEST_STATUS, CUSTOM_NMEA_TYPE_DEVICE_BT_ID, CUSTOM_NMEA_TYPE_PARSER_STATS, CUSTOM_NMEA_TYPE_CURRENT_DATE, @@ -374,27 +373,6 @@ typedef enum BLUETOOTH_RADIO_OFF, } BluetoothRadioType_e; -// Don't make this a typedef enum as logTestState -// can be incremented beyond LOGTEST_END -enum LogTestState -{ - LOGTEST_START = 0, - LOGTEST_4HZ_5MSG_10MS, - LOGTEST_4HZ_7MSG_10MS, - LOGTEST_10HZ_5MSG_10MS, - LOGTEST_10HZ_7MSG_10MS, - LOGTEST_4HZ_5MSG_0MS, - LOGTEST_4HZ_7MSG_0MS, - LOGTEST_10HZ_5MSG_0MS, - LOGTEST_10HZ_7MSG_0MS, - LOGTEST_4HZ_5MSG_50MS, - LOGTEST_4HZ_7MSG_50MS, - LOGTEST_10HZ_5MSG_50MS, - LOGTEST_10HZ_7MSG_50MS, - LOGTEST_END, -}; -uint8_t logTestState = LOGTEST_END; - typedef struct WiFiNetwork { char ssid[50]; @@ -464,7 +442,6 @@ typedef enum FUNCTION_CREATEFILE, FUNCTION_ENDLOGGING, FUNCTION_FINDLOG, - FUNCTION_LOGTEST, FUNCTION_FILELIST, FUNCTION_FILEMANAGER_OPEN1, FUNCTION_FILEMANAGER_OPEN2, @@ -681,7 +658,6 @@ struct Settings bool enablePrintLogFileStatus = true; int maxLogLength_minutes = 60 * 24; // Default to 24 hours int maxLogTime_minutes = 60 * 24; // Default to 24 hours - bool runLogTest = false; // When set to true, device will create a series of test logs // MQTT bool debugMqttClientData = false; // Debug the MQTT SPARTAN data flow @@ -1284,7 +1260,6 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 0, 0, 0, 1, 1, 1, 0, 1, 1, _bool, 0, & settings.enablePrintLogFileStatus, "enablePrintLogFileStatus", }, { 1, 1, 0, 1, 1, 1, 0, 1, 1, _int, 0, & settings.maxLogLength_minutes, "maxLogLength", }, { 1, 1, 0, 1, 1, 1, 0, 1, 1, _int, 0, & settings.maxLogTime_minutes, "maxLogTime"}, - { 0, 0, 0, 1, 1, 0, 0, 1, 1, _bool, 0, & settings.runLogTest, "runLogTest", }, // Not stored in NVM // Mosaic From 92bd6db2ba8f776ac00d362d6cf5ebb285bc5cc3 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 12:12:13 -0700 Subject: [PATCH 069/276] Update default APCs on all platforms. Averaging L1/L2 --- Firmware/RTK_Everywhere/Begin.ino | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Begin.ino b/Firmware/RTK_Everywhere/Begin.ino index 53ee27c46..743842675 100644 --- a/Firmware/RTK_Everywhere/Begin.ino +++ b/Firmware/RTK_Everywhere/Begin.ino @@ -208,6 +208,7 @@ void beginBoard() present.brand = BRAND_SPARKFUN; present.psram_2mb = true; present.gnss_um980 = true; + present.antennaPhaseCenter_mm = 116.5; // Default to Torch helical APC, average of L1/L2 present.radio_lora = true; present.fuelgauge_bq40z50 = true; present.charger_mp2762a = true; @@ -215,7 +216,6 @@ void beginBoard() present.button_powerHigh = true; // Button is pressed when high present.beeper = true; present.gnss_to_uart = true; - present.antennaPhaseCenter_mm = 115.7; // Default to Torch helical APC present.needsExternalPpl = true; // Uses the PointPerfect Library present.galileoHasCapable = true; present.multipathMitigation = true; // UM980 has MPM, other platforms do not @@ -316,6 +316,7 @@ void beginBoard() // Pin defs etc. for EVK v1.1 present.psram_4mb = true; present.gnss_zedf9p = true; + present.antennaPhaseCenter_mm = 42.0; // Default to NGS certified SPK6615H APC, average of L1/L2 present.lband_neo = true; present.cellular_lara = true; present.ethernet_ws5500 = true; @@ -443,6 +444,7 @@ void beginBoard() present.brand = BRAND_SPARKPNT; present.psram_4mb = true; present.gnss_zedf9p = true; + present.antennaPhaseCenter_mm = 68.5; // Default to L-Band element APC, average of L1/L2 present.lband_neo = true; present.microSd = true; present.microSdCardDetectLow = true; @@ -524,6 +526,7 @@ void beginBoard() present.brand = BRAND_SPARKPNT; present.psram_4mb = true; present.gnss_zedf9p = true; + present.antennaPhaseCenter_mm = 69.6; // Default to NGS certified RTK Facet element APC, average of L1/L2 present.microSd = true; present.microSdCardDetectLow = true; present.display_i2c0 = true; @@ -618,6 +621,7 @@ void beginBoard() present.brand = BRAND_SPARKPNT; present.psram_4mb = true; present.gnss_mosaicX5 = true; + present.antennaPhaseCenter_mm = 68.5; // Default to L-Band element APC, average of L1/L2 present.display_i2c0 = true; present.display_type = DISPLAY_64x48; present.i2c0BusSpeed_400 = true; @@ -688,7 +692,7 @@ void beginBoard() present.brand = BRAND_SPARKPNT; present.psram_2mb = true; present.gnss_lg290p = true; - present.antennaPhaseCenter_mm = 42.0; // Default to SPK6618H APC + present.antennaPhaseCenter_mm = 42.0; // Default to SPK6618H APC, average of L1/L2 present.needsExternalPpl = true; // Uses the PointPerfect Library present.gnss_to_uart = true; From 41954434866f81fbfa8cd0640f83d4c8a93e592c Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 12:12:44 -0700 Subject: [PATCH 070/276] Show no battery icon until data arrives --- Firmware/RTK_Everywhere/AP-Config/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/index.html b/Firmware/RTK_Everywhere/AP-Config/index.html index 5cd866cbf..999360835 100644 --- a/Firmware/RTK_Everywhere/AP-Config/index.html +++ b/Firmware/RTK_Everywhere/AP-Config/index.html @@ -84,8 +84,8 @@
- Battery level +67 + Battery level
From 0a7c2eb2f1d72800a10a2b34f991f5609d8d1b2d Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 12:13:13 -0700 Subject: [PATCH 071/276] Add LoRa settings to web config --- Firmware/RTK_Everywhere/AP-Config/index.html | 72 ++++++++++++++++---- 1 file changed, 58 insertions(+), 14 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/index.html b/Firmware/RTK_Everywhere/AP-Config/index.html index 999360835..b0aae9a18 100644 --- a/Firmware/RTK_Everywhere/AP-Config/index.html +++ b/Firmware/RTK_Everywhere/AP-Config/index.html @@ -464,7 +464,8 @@
- @@ -494,7 +495,8 @@
- @@ -524,7 +526,7 @@
- +
@@ -1259,7 +1261,8 @@
- + @@ -1269,7 +1272,8 @@
- @@ -1284,7 +1288,7 @@
- +
@@ -1437,17 +1441,19 @@
- +
- +
- @@ -1689,10 +1695,10 @@
- + + title="The internal ESP32 can be used as a point-to-point, or point-to-multipoint radio for RTCM transmission. Default: Off">
@@ -1735,8 +1741,44 @@

+
+ +
+ + + + + +
+ +
+
+ Coordination Frequency (MHz): + + + +
+
+ +

+
+ +
+ Seconds before dedicated listening mode: + + + +
+
+ +

+
+ @@ -1826,7 +1868,7 @@ @@ -2049,7 +2091,8 @@
- + From 22f0444ac5e1f876049cbe803b1686b3b78c7c2a Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 12:13:35 -0700 Subject: [PATCH 072/276] Update APCs on web config Average L1/L2. --- Firmware/RTK_Everywhere/AP-Config/src/main.js | 68 +++++++++++++++++-- 1 file changed, 61 insertions(+), 7 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/src/main.js b/Firmware/RTK_Everywhere/AP-Config/src/main.js index 314722611..f8fb370ae 100644 --- a/Firmware/RTK_Everywhere/AP-Config/src/main.js +++ b/Firmware/RTK_Everywhere/AP-Config/src/main.js @@ -178,9 +178,9 @@ function parseIncoming(msg) { newOption = new Option('Unlimited', '7'); select.add(newOption, undefined); - ge("messageRateInfoText").setAttribute('data-bs-original-title','The GNSS can output NMEA and RTCMv3 at different rates. For NMEA: select a stream for each message, and set an interval for each stream. For RTCMv3: set an interval for each message group, and enable individual messages.'); - ge("rtcmRateInfoText").setAttribute('data-bs-original-title','RTCM is transmitted by the base at a default of 1Hz for messages 1005, MSM4, and 0.1Hz for 1033. This can be lowered for radios with low bandwidth or tailored to transmit any/all RTCM messages. Limits: 0.1 to 600.'); - ge("enableExtCorrRadioInfoText").setAttribute('data-bs-original-title','Enable external radio corrections: RTCMv3 on mosaic COM2. Default: False'); + ge("messageRateInfoText").setAttribute('data-bs-original-title', 'The GNSS can output NMEA and RTCMv3 at different rates. For NMEA: select a stream for each message, and set an interval for each stream. For RTCMv3: set an interval for each message group, and enable individual messages.'); + ge("rtcmRateInfoText").setAttribute('data-bs-original-title', 'RTCM is transmitted by the base at a default of 1Hz for messages 1005, MSM4, and 0.1Hz for 1033. This can be lowered for radios with low bandwidth or tailored to transmit any/all RTCM messages. Limits: 0.1 to 600.'); + ge("enableExtCorrRadioInfoText").setAttribute('data-bs-original-title', 'Enable external radio corrections: RTCMv3 on mosaic COM2. Default: False'); } else if (platformPrefix == "Torch") { show("baseConfig"); @@ -198,6 +198,8 @@ function parseIncoming(msg) { show("useAssistNowCheckbox"); //Does the PPL use MGA? Not sure... show("measurementRateInput"); + show("loraConfig"); + select = ge("dynamicModel"); let newOption = new Option('Survey', '0'); select.add(newOption, undefined); @@ -206,7 +208,36 @@ function parseIncoming(msg) { newOption = new Option('Automotive', '2'); select.add(newOption, undefined); - ge("rtcmRateInfoText").setAttribute('data-bs-original-title','RTCM is transmitted by the base at a default of 1Hz for messages 1005, 1074, 1084, 1094, 1124, and 0.1Hz for 1033. This can be lowered for radios with low bandwidth or tailored to transmit any/all RTCM messages. Limits: 0 to 20. Note: The measurement rate is overridden to 1Hz when in Base mode.'); + ge("rtcmRateInfoText").setAttribute('data-bs-original-title', 'RTCM is transmitted by the base at a default of 1Hz for messages 1005, 1074, 1084, 1094, 1124, and 0.1Hz for 1033. This can be lowered for radios with low bandwidth or tailored to transmit any/all RTCM messages. Limits: 0 to 20. Note: The measurement rate is overridden to 1Hz when in Base mode.'); + + } + else if (platformPrefix == "Postcard") { + show("baseConfig"); + show("ppConfig"); + hide("ethernetConfig"); + hide("ntpConfig"); + show("portsConfig"); + show("externalPortOptions"); + show("logToSDCard"); + + hide("galileoHasSetting"); + hide("tiltConfig"); + hide("beeperControl"); + + show("useAssistNowCheckbox"); + show("measurementRateInput"); + hide("mosaicNMEAStreamDropdowns"); + show("surveyInSettings"); + show("useLocalizedDistributionCheckbox"); + show("useEnableExtCorrRadio"); + show("extCorrRadioSPARTNSourceDropdown"); + + hide("constellationSbas"); //Not supported on LG290P + show("constellationNavic"); + + hide("dynamicModel"); //Not supported on LG290P + + ge("rtcmRateInfoText").setAttribute('data-bs-original-title', 'RTCM is transmitted by the base at a default of 1Hz for messages 1005, 1074, 1084, 1094, 1114, 1124, 1134. This can be lowered for radios with low bandwidth or tailored to transmit any/all RTCM messages. Limits: 0 to 20. Note: The measurement rate is overridden to 1Hz when in Base mode.'); } } else if (id.includes("gnssFirmwareVersionInt")) { @@ -528,6 +559,7 @@ function parseIncoming(msg) { ge("enableExternalPulse").dispatchEvent(new CustomEvent('change')); ge("enableExternalHardwareEventLogging").dispatchEvent(new CustomEvent('change')); ge("enableEspNow").dispatchEvent(new CustomEvent('change')); + ge("enableLora").dispatchEvent(new CustomEvent('change')); ge("antennaPhaseCenter_mm").dispatchEvent(new CustomEvent('change')); ge("enableLogging").dispatchEvent(new CustomEvent('change')); ge("enableLoggingRINEX").dispatchEvent(new CustomEvent('change')); @@ -877,6 +909,13 @@ function validateFields() { //But, on WiFi, they can be... //checkCheckboxMutex("enableTcpClient", "enableTcpServer", "TCP Client and Server can not be enabled at the same time", "collapseTCPUDPConfig"); + //Radio Config + if (ge("enableLora").checked == true) { + checkElementValue("loraCoordinationFrequency", 903, 927, "Must be 903 to 927", "collapseRadioConfig"); + checkElementValue("loraSerialInteractionTimeout_s", 10, 600, "Must be 10 to 600", "collapseRadioConfig"); + } + + //System Config if (ge("enableLogging").checked == true) { checkElementValue("maxLogTime", 1, 1051200, "Must be 1 to 1,051,200", "collapseSystemConfig"); @@ -1523,11 +1562,17 @@ document.addEventListener("DOMContentLoaded", (event) => { hide("ecefConfig"); show("geodeticConfig"); - if ((platformPrefix == "Facet mosaicX5") || (platformPrefix == "Facet v2") || (platformPrefix == "Facet v2 LBand")) { - ge("antennaPhaseCenter_mm").value = 61.4; + if ((platformPrefix == "Facet mosaicX5") || (platformPrefix == "Facet v2 LBand")) { + ge("antennaPhaseCenter_mm").value = 68.5; //Average of L1/L2 + } + else if (platformPrefix == "Facet v2") { + ge("antennaPhaseCenter_mm").value = 69.6; //Average of L1/L2 } else if (platformPrefix == "Torch") { - ge("antennaPhaseCenter_mm").value = 116.2; + ge("antennaPhaseCenter_mm").value = 116.5; //Average of L1/L2 + } + else if (platformPrefix == "EVK") { + ge("antennaPhaseCenter_mm").value = 42.0; //Average of L1/L2 } else { ge("antennaPhaseCenter_mm").value = 0.0; @@ -1631,6 +1676,15 @@ document.addEventListener("DOMContentLoaded", (event) => { } }); + ge("enableLora").addEventListener("change", function () { + if (ge("enableLora").checked == true) { + show("loraDetails"); + } + else { + hide("loraDetails"); + } + }); + ge("enableLogging").addEventListener("change", function () { showHideLoggingDetails(); }); From deb204a13a931259eff4343c991b7c57f9554385 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 14:18:55 -0700 Subject: [PATCH 073/276] Turn off variables not used on web config --- Firmware/RTK_Everywhere/settings.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 92c5cbf34..4eb7c8776 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -1129,7 +1129,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 1, 1, 0, 1, 1, 1, 1, 1, 1, _double, 9, & settings.fixedLong, "fixedLong", }, { 1, 1, 0, 1, 1, 1, 1, 1, 1, _int, 0, & settings.observationSeconds, "observationSeconds", }, { 1, 1, 0, 1, 1, 1, 1, 1, 1, _float, 2, & settings.observationPositionAccuracy, "observationPositionAccuracy", }, - { 1, 1, 0, 1, 1, 0, 1, 1, 1, _float, 1, & settings.surveyInStartingAccuracy, "surveyInStartingAccuracy", }, + { 0, 1, 0, 1, 1, 0, 1, 1, 1, _float, 1, & settings.surveyInStartingAccuracy, "surveyInStartingAccuracy", }, // Battery { 0, 0, 0, 0, 1, 1, 1, 1, 1, _bool, 0, & settings.enablePrintBatteryMessages, "enablePrintBatteryMessages", }, @@ -1283,7 +1283,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = // Multicast DNS { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.mdnsEnable, "mdnsEnable", }, - { 1, 1, 0, 1, 1, 1, 1, 1, 1, tCharArry, sizeof(settings.mdnsHostName), & settings.mdnsHostName, "mdnsHostName", }, + { 0, 1, 0, 1, 1, 1, 1, 1, 1, tCharArry, sizeof(settings.mdnsHostName), & settings.mdnsHostName, "mdnsHostName", }, // Network layer { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugNetworkLayer, "debugNetworkLayer", }, @@ -1306,7 +1306,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = // NTP (Ethernet Only) { 0, 0, 0, 1, 0, 0, 0, 0, 0, _bool, 0, & settings.debugNtp, "debugNtp", }, - { 1, 1, 0, 1, 0, 0, 0, 0, 0, _bool, 0, & settings.enableNTPFile, "enableNTPFile", }, + { 0, 1, 0, 1, 0, 0, 0, 0, 0, _bool, 0, & settings.enableNTPFile, "enableNTPFile", }, { 1, 1, 0, 1, 0, 0, 0, 0, 0, _uint16_t, 0, & settings.ethernetNtpPort, "ethernetNtpPort", }, { 1, 1, 0, 1, 0, 0, 0, 0, 0, _uint8_t, 0, & settings.ntpPollExponent, "ntpPollExponent", }, { 1, 1, 0, 1, 0, 0, 0, 0, 0, _int8_t, 0, & settings.ntpPrecision, "ntpPrecision", }, @@ -1465,7 +1465,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = // g s x k 2 c h d d Type Qual Variable Name // Setup Button - { 1, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.disableSetupButton, "disableSetupButton", }, + { 0, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.disableSetupButton, "disableSetupButton", }, // State { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enablePrintDuplicateStates, "enablePrintDuplicateStates", }, @@ -1484,9 +1484,9 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 1, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.tcpServerPort, "tcpServerPort", }, // Time Zone - { 1, 1, 0, 1, 1, 1, 1, 1, 1, _int8_t, 0, & settings.timeZoneHours, "timeZoneHours", }, - { 1, 1, 0, 1, 1, 1, 1, 1, 1, _int8_t, 0, & settings.timeZoneMinutes, "timeZoneMinutes", }, - { 1, 1, 0, 1, 1, 1, 1, 1, 1, _int8_t, 0, & settings.timeZoneSeconds, "timeZoneSeconds", }, + { 0, 1, 0, 1, 1, 1, 1, 1, 1, _int8_t, 0, & settings.timeZoneHours, "timeZoneHours", }, + { 0, 1, 0, 1, 1, 1, 1, 1, 1, _int8_t, 0, & settings.timeZoneMinutes, "timeZoneMinutes", }, + { 0, 1, 0, 1, 1, 1, 1, 1, 1, _int8_t, 0, & settings.timeZoneSeconds, "timeZoneSeconds", }, // F // a From 9b5659b658a070955c63f0b4501e226cce3212a0 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 14:19:22 -0700 Subject: [PATCH 074/276] Remove unused functions --- Firmware/RTK_Everywhere/Developer.ino | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 3f784cd72..d31ee7c87 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -10,10 +10,6 @@ //---------------------------------------- void menuEthernet() {systemPrintln("**Ethernet not compiled**");} -void ethernetVerifyTables() {} - -void ethernetWebServerStartESP32W5500() {} -void ethernetWebServerStopESP32W5500() {} bool ntpLogIncreasing = false; From 3c29d0bdeabc20682b233837f082701b5dfd847b Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 14:19:41 -0700 Subject: [PATCH 075/276] Use available function (Remove old) --- Firmware/RTK_Everywhere/Display.ino | 2 +- Firmware/RTK_Everywhere/Network.ino | 17 +---------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index a2ed9412b..4c1d3d999 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -401,7 +401,7 @@ void displayUpdate() displayWebConfigNotStarted(); // Display 'Web Config' break; case (STATE_WEB_CONFIG): - if (networkIsOnline(NETWORK_ETHERNET)) + if (networkIsInterfaceOnline(NETWORK_ETHERNET)) displayConfigViaEthernet(); else { diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 991e787d8..15ed8a9ea 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -624,21 +624,6 @@ bool networkIsOnline() return networkOnline ? true : false; } -//---------------------------------------- -// Determine if the given network is online -//---------------------------------------- -bool networkIsOnline(NetIndex_t index) -{ - // Validate the index - networkValidateIndex(index); - - // Check for network offline - NetMask_t bitMask = 1 << index; - if (networkOnline & bitMask) - return true; - return false; -} - //---------------------------------------- // Determine if the network is present on the platform //---------------------------------------- @@ -1412,7 +1397,7 @@ void networkUpdate() // If there are no consumers, but the network is online, shut down all networks if (consumerCount == 0 && networkIsOnline() == true) { - if (settings.debugNetworkLayer) + if (settings.debugNetworkLayer && networkIsInterfaceOnline(NETWORK_ETHERNET) == false) //Ethernet is never stopped, so only print for other networks systemPrintln("Stopping all networks because there are no consumers"); // Shutdown all networks From 9a33f5176bf8325a8c8d6aed1a415ca65ca74ee7 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 14:20:14 -0700 Subject: [PATCH 076/276] Fix button typo --- Firmware/RTK_Everywhere/AP-Config/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/index.html b/Firmware/RTK_Everywhere/AP-Config/index.html index b0aae9a18..f5625b4ae 100644 --- a/Firmware/RTK_Everywhere/AP-Config/index.html +++ b/Firmware/RTK_Everywhere/AP-Config/index.html @@ -600,7 +600,7 @@
+ onClick="useECEFCoordinates()">Load ECEF From GNSS @@ -698,7 +698,7 @@
+ From GNSS From e1416c7c621ab9300ef37d758d850a982c720074 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 14:21:11 -0700 Subject: [PATCH 077/276] Webconfig: Add support for NTRIP Caster, LoRa --- Firmware/RTK_Everywhere/AP-Config/index.html | 70 ++++++++++++-------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/index.html b/Firmware/RTK_Everywhere/AP-Config/index.html index f5625b4ae..ccad91fcd 100644 --- a/Firmware/RTK_Everywhere/AP-Config/index.html +++ b/Firmware/RTK_Everywhere/AP-Config/index.html @@ -1651,6 +1651,16 @@

+ +
+ + + + + +

@@ -1743,40 +1753,42 @@
-
- - - - - -
- -
-
- Coordination Frequency (MHz): +
@@ -2297,7 +2309,7 @@
From 353fe1f7067fd44fe522197795eef9c426780dbd Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 14:23:57 -0700 Subject: [PATCH 078/276] Webconfig: Range check instrument. Show instrument error. --- Firmware/RTK_Everywhere/AP-Config/src/main.js | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/src/main.js b/Firmware/RTK_Everywhere/AP-Config/src/main.js index f8fb370ae..9fce92560 100644 --- a/Firmware/RTK_Everywhere/AP-Config/src/main.js +++ b/Firmware/RTK_Everywhere/AP-Config/src/main.js @@ -510,20 +510,20 @@ function parseIncoming(msg) { else if (id.includes("antennaHeight_mm")) { ge("antennaHeight_m").value = val / 1000.0; } - + //Check boxes / radio buttons else if (val == "true") { try { ge(id).checked = true; } catch (error) { - console.log("Issue with ID: " + id); + console.log("Set True issue with ID: " + id); } } else if (val == "false") { try { ge(id).checked = false; } catch (error) { - console.log("Issue with ID: " + id); + console.log("Set False issue with ID: " + id); } } @@ -884,6 +884,12 @@ function validateFields() { ge("autoKeyRenewal").checked = true; } + //Port Config + if (ge("enableExternalPulse").checked == true) { + checkElementValue("externalPulseTimeBetweenPulse", 1, 60000000, "Must be 1 to 60,000,000", "collapsePortsConfig"); + checkElementValue("externalPulseLength", 1, 60000000, "Must be 1 to 60,000,000", "collapsePortsConfig"); + } + //WiFi Config checkElementString("wifiNetwork_0SSID", 0, 49, "Must be 0 to 49 characters", "collapseWiFiConfig"); checkElementString("wifiNetwork_0Password", 0, 49, "Must be 0 to 49 characters", "collapseWiFiConfig"); @@ -915,6 +921,12 @@ function validateFields() { checkElementValue("loraSerialInteractionTimeout_s", 10, 600, "Must be 10 to 600", "collapseRadioConfig"); } + //Corrections Config + checkElementValue("correctionsSourcesLifetime", 5, 120, "Must be 5 to 120", "collapseCorrectionsPriorityConfig"); + + //Instrument Config + checkElementValue("antennaHeight_m", -15, 15, "Must be -15 to 15", "collapseBaseConfig"); + checkElementValue("antennaPhaseCenter_mm", -200.0, 200.0, "Must be -200.0 to 200.0", "collapseBaseConfig"); //System Config if (ge("enableLogging").checked == true) { @@ -965,15 +977,6 @@ function validateFields() { checkElementValue("ntpRootDispersion", 0, 10000000, "Must be 0 to 10,000,000", "collapseNTPConfig"); checkElementString("ntpReferenceId", 1, 4, "Must be 1 to 4 chars", "collapseNTPConfig"); } - - //Port Config - if (ge("enableExternalPulse").checked == true) { - checkElementValue("externalPulseTimeBetweenPulse", 1, 60000000, "Must be 1 to 60,000,000", "collapsePortsConfig"); - checkElementValue("externalPulseLength", 1, 60000000, "Must be 1 to 60,000,000", "collapsePortsConfig"); - } - - //Corrections Priorities - checkElementValue("correctionsSourcesLifetime", 5, 120, "Must be 5 to 120", "collapseCorrectionsPriorityConfig"); } var currentProfileNumber = 0; @@ -1011,12 +1014,14 @@ function changeProfile() { collapseSection("collapsePortsConfig", "portsCaret"); collapseSection("collapseWiFiConfig", "wifiCaret"); collapseSection("collapseTCPUDPConfig", "tcpUdpCaret"); + collapseSection("collapseRadioConfig", "radioCaret"); collapseSection("collapseCorrectionsPriorityConfig", "correctionsCaret"); + collapseSection("collapseInstrumentConfig", "instrumentCaret"); collapseSection("collapseSystemConfig", "systemCaret"); + collapseSection("collapseEthernetConfig", "ethernetCaret"); collapseSection("collapseNTPConfig", "ntpCaret"); collapseSection("collapseFileManager", "fileManagerCaret"); - collapseSection("collapseInstrumentConfig", "instrumentCaret"); } } @@ -2111,7 +2116,7 @@ function getMessageList() { ge(savedCheckboxNames[x]).checked = false; } else { - console.log("Issue with ID: " + savedCheckboxNames[x]); + console.log("getMessageList Issue with ID: " + savedCheckboxNames[x]); } } } @@ -2143,7 +2148,7 @@ function getMessageListBase() { ge(savedCheckboxNames[x]).checked = false; } else { - console.log("Issue with ID: " + savedCheckboxNames[x]); + console.log("getMessageListBase issue with ID: " + savedCheckboxNames[x]); } } } From 9de1fb5d58465fb0f5e2ab107e8755372b1bab7e Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 15:10:13 -0700 Subject: [PATCH 079/276] Firmware update via WebConfig works. Remove consumer AP_STA. When a consumer requests NETCONSUMER_WIFI_STA, the bit field looks different from NETCONSUMER_WIFI_AP_STA, at which point the network is shut down (bad). The solution is to remove NETCONSUMER_WIFI_AP_STA and just use a combination of bits _AP and _STA. --- Firmware/RTK_Everywhere/Network.ino | 22 +++++----------------- Firmware/RTK_Everywhere/WiFi.ino | 9 +-------- Firmware/RTK_Everywhere/menuFirmware.ino | 2 +- Firmware/RTK_Everywhere/settings.h | 2 +- 4 files changed, 8 insertions(+), 27 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 15ed8a9ea..166c59b12 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1409,25 +1409,14 @@ void networkUpdate() // then stop all networks and let the lower code restart the network accordingly if (consumerTypes != previousConsumerTypes) { - previousConsumerTypes = networkGetConsumerTypes(); // Update the previous consumer types + if (settings.debugNetworkLayer) + systemPrintf("Changing from consumer type 0x%02X to 0x%02X\r\n", previousConsumerTypes, consumerTypes); - // if (networkConsumersOnline() > 0 && networkShutdownRequest == false) - // { - // // Tell consumers to shut down - // networkShutdownRequest = true; - // if (settings.debugNetworkLayer) - // systemPrintln("Notifying consumers of impending network shutdown"); - // } - // else - // { - // // We're clear to shutdown - // if (settings.debugNetworkLayer) - // systemPrintln("Stopping all networks because of consumer type change"); + previousConsumerTypes = networkGetConsumerTypes(); // Update the previous consumer types // Shutdown all networks for (int index = 0; index < NETWORK_OFFLINE; index++) networkStop(index, settings.debugNetworkLayer); - // } } @@ -1440,8 +1429,7 @@ void networkUpdate() // If a consumer is requesting a particular type, it gets priority // Consumer is requesting WiFi specifically - if ((consumerTypes && (1 << NETCONSUMER_WIFI_STA)) || (consumerTypes && (1 << NETCONSUMER_WIFI_AP)) || - (consumerTypes && (1 << NETCONSUMER_WIFI_AP_STA))) + if ((consumerTypes && (1 << NETCONSUMER_WIFI_STA)) || (consumerTypes && (1 << NETCONSUMER_WIFI_AP))) { if (settings.debugNetworkLayer) systemPrintln("Starting WiFi Specific Network"); @@ -1640,7 +1628,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) // TODO Make web server over ethernet work here as well if (settings.wifiConfigOverAP == true) - *consumerTypes |= (1 << NETCONSUMER_WIFI_AP_STA); //WebConfig requires both AP and STA (for firmware check) + *consumerTypes |= ((1 << NETCONSUMER_WIFI_AP) | (1 << NETCONSUMER_WIFI_STA)); //WebConfig requires both AP and STA (for firmware check) } // Debug diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 4f0b46a1e..9ce1b3e0f 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -523,14 +523,7 @@ bool wifiForceStart() startWiFiStation = true; } - // The consumers need both (explicit) - else if (consumerTypes & (1 << NETCONSUMER_WIFI_AP_STA)) - { - startWiFiStation = true; - startWiFiAP = true; - } - - // The consumers need both (implicit) + // The consumers need both else if ((consumerTypes & (1 << NETCONSUMER_WIFI_AP)) && (consumerTypes & (1 << NETCONSUMER_WIFI_STA))) { startWiFiStation = true; diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index 05871b922..e9e7b3bfb 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -857,7 +857,7 @@ void otaUpdate() if (!networkIsConnected(&otaPriority)) otaUpdateStop(); if (settings.debugFirmwareUpdate) - systemPrintln("Firmware update checking SparkFun released firmware version"); + systemPrintln("Checking for latest firmware version"); // If we are using auto updates, only update to production firmware, disable release candidates if (settings.enableAutoFirmwareUpdate) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 4eb7c8776..34e9134e6 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -556,7 +556,7 @@ enum NETCONSUMER_NONE = 0, // No consumers NETCONSUMER_WIFI_STA, // The consumer needs STA NETCONSUMER_WIFI_AP, // The consumer needs AP - NETCONSUMER_WIFI_AP_STA, // The consumer needs STA and AP + //NETCONSUMER_WIFI_AP_STA, // The consumer needs STA and AP - Don't use. Use combination of STA and AP bits NETCONSUMER_CELLULAR, // The consumer needs Cellular NETCONSUMER_ETHERNET, // The consumer needs Ethernet NETCONSUMER_ANY, // The consumer doesn't care what type of network access is granted From 909a4050fe35d8007d4fc6a5f269dab612663ee8 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 15:21:34 -0700 Subject: [PATCH 080/276] Webconfig: Turn off Postcard settings. Fix NavIC spelling. --- Firmware/RTK_Everywhere/AP-Config/index.html | 51 ++++++++++--------- Firmware/RTK_Everywhere/AP-Config/src/main.js | 4 +- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/index.html b/Firmware/RTK_Everywhere/AP-Config/index.html index ccad91fcd..d2c62fb32 100644 --- a/Firmware/RTK_Everywhere/AP-Config/index.html +++ b/Firmware/RTK_Everywhere/AP-Config/index.html @@ -282,29 +282,33 @@
-
- -
- -

+
+
+ +
+ +

+
-
- -
- -

+
+
+ +
+ +

+
@@ -331,8 +335,8 @@
- - + +
@@ -1653,8 +1657,7 @@
- + diff --git a/Firmware/RTK_Everywhere/AP-Config/src/main.js b/Firmware/RTK_Everywhere/AP-Config/src/main.js index 9fce92560..d22d2c14c 100644 --- a/Firmware/RTK_Everywhere/AP-Config/src/main.js +++ b/Firmware/RTK_Everywhere/AP-Config/src/main.js @@ -235,7 +235,9 @@ function parseIncoming(msg) { hide("constellationSbas"); //Not supported on LG290P show("constellationNavic"); - hide("dynamicModel"); //Not supported on LG290P + hide("dynamicModelDropdown"); //Not supported on LG290P + hide("minElevConfig"); //Not supported on LG290P + hide("minCNOConfig"); //Not supported on LG290P ge("rtcmRateInfoText").setAttribute('data-bs-original-title', 'RTCM is transmitted by the base at a default of 1Hz for messages 1005, 1074, 1084, 1094, 1114, 1124, 1134. This can be lowered for radios with low bandwidth or tailored to transmit any/all RTCM messages. Limits: 0 to 20. Note: The measurement rate is overridden to 1Hz when in Base mode.'); } From 89928d2887035e67f287346ecaee5cd8e5334fa4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Jan 2025 22:43:35 +0000 Subject: [PATCH 081/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4102 ++++++++++++++++---------------- 1 file changed, 2074 insertions(+), 2028 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index 6d4924c8a..b86752087 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,993 +26,1010 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xC8, 0x56, 0x63, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, - 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0x1B, 0xB9, 0x92, 0xE8, 0xFF, - 0x79, 0x0A, 0x1D, 0xDF, 0x73, 0xC7, 0xE6, 0x60, 0x8C, 0x6D, 0x3E, 0x12, 0x42, 0xC8, 0x5E, 0x02, - 0x24, 0xE1, 0x9E, 0x40, 0xB8, 0x98, 0xCC, 0x4C, 0x26, 0x27, 0xCB, 0x36, 0x6E, 0x61, 0x7A, 0x63, - 0x77, 0x7B, 0xBB, 0xDB, 0x10, 0xE6, 0x2C, 0xEF, 0xB4, 0xCF, 0xB0, 0x4F, 0x76, 0xAB, 0x24, 0x75, - 0xB7, 0xA4, 0x56, 0x7F, 0xDA, 0x26, 0x9C, 0xB3, 0xC3, 0xEF, 0x37, 0x19, 0x68, 0xA9, 0x3E, 0x54, - 0x2A, 0x95, 0x4A, 0x52, 0xA9, 0x74, 0x6B, 0xF9, 0x64, 0x64, 0x85, 0xF4, 0xCE, 0xBA, 0x27, 0x7B, - 0xE4, 0xDF, 0xEE, 0x82, 0x97, 0xEB, 0xEB, 0x7F, 0xFE, 0xFB, 0x9D, 0xE3, 0xDA, 0xDE, 0x5D, 0x67, - 0xEC, 0x0D, 0xAD, 0xD0, 0xF1, 0xDC, 0xCE, 0x8D, 0x17, 0x84, 0xAE, 0x35, 0xA1, 0x0F, 0x2F, 0x5F, - 0xF4, 0xD6, 0xEF, 0x82, 0x7F, 0xDB, 0x7D, 0x76, 0x0B, 0x70, 0x77, 0xF4, 0x2A, 0xF0, 0x86, 0xDF, - 0x68, 0xB8, 0xFB, 0xEC, 0x99, 0x80, 0xB0, 0x6C, 0xFB, 0xE8, 0x96, 0xBA, 0xE1, 0x07, 0x27, 0x08, - 0xA9, 0x4B, 0xFD, 0x56, 0x73, 0xEC, 0x59, 0x76, 0xB3, 0x4D, 0x3C, 0xF7, 0x03, 0xFC, 0xB2, 0x02, - 0x35, 0xAF, 0x67, 0xEE, 0x10, 0x91, 0x8A, 0x4F, 0x2D, 0x8A, 0xF5, 0x57, 0xC8, 0xDF, 0x9F, 0x11, - 0xF8, 0x71, 0x5C, 0x27, 0xFC, 0x85, 0x5E, 0x0D, 0x18, 0xDA, 0x16, 0x54, 0x7F, 0x90, 0x00, 0xB4, - 0x42, 0x01, 0x12, 0x73, 0x01, 0xFC, 0xBB, 0xF4, 0x8E, 0x24, 0x35, 0x44, 0xBB, 0x00, 0x8B, 0x52, - 0xAF, 0xE3, 0xB9, 0x13, 0x1A, 0x04, 0xD6, 0x88, 0x02, 0x44, 0x8C, 0xBC, 0x35, 0x09, 0x46, 0x11, - 0x4A, 0xFC, 0x99, 0x5A, 0x7E, 0x40, 0x8F, 0xDD, 0xA1, 0x37, 0x71, 0xDC, 0x11, 0x16, 0x76, 0x6C, - 0x2B, 0xB4, 0x04, 0xAE, 0x07, 0x95, 0xB1, 0x11, 0x6D, 0xD1, 0x08, 0xD6, 0xA7, 0xE1, 0xCC, 0x77, - 0x89, 0xED, 0x0D, 0x67, 0x13, 0x68, 0x58, 0x67, 0x44, 0xC3, 0xA3, 0x31, 0xC5, 0x5F, 0xDF, 0xDC, - 0x1F, 0x43, 0x6B, 0x79, 0x9B, 0x50, 0x7C, 0xD7, 0xCE, 0x77, 0x6A, 0x7F, 0xB0, 0x90, 0xEF, 0xEE, - 0xAE, 0xF4, 0xC5, 0x73, 0x47, 0xC9, 0xA7, 0xE9, 0xD8, 0x0A, 0xAF, 0x3D, 0x7F, 0x72, 0xE6, 0x53, - 0x28, 0x85, 0xEF, 0x8D, 0x06, 0x2F, 0x18, 0x51, 0xCF, 0xA6, 0xA1, 0x33, 0xE4, 0x08, 0x36, 0xBB, - 0x9D, 0x6E, 0x4F, 0x2B, 0x00, 0xC6, 0xF6, 0xC8, 0x5A, 0xAF, 0xBB, 0xD5, 0xE9, 0xED, 0xA8, 0x45, - 0xFB, 0x63, 0x84, 0xE9, 0x6D, 0x75, 0xBB, 0x1D, 0x01, 0x44, 0x87, 0xF4, 0xFA, 0x57, 0x56, 0xBD, - 0xFF, 0xA2, 0xDB, 0xEF, 0x6E, 0x77, 0xB6, 0xB6, 0x5F, 0x24, 0x25, 0x9F, 0xB1, 0x64, 0xF3, 0x79, - 0x6F, 0xFB, 0x45, 0x77, 0xB3, 0xB3, 0xD9, 0xDD, 0x48, 0x4A, 0x7E, 0x63, 0xB4, 0x5F, 0x6C, 0x6F, - 0x6F, 0x6F, 0x75, 0x36, 0x5F, 0x6C, 0xF2, 0x82, 0xB1, 0x15, 0x84, 0x6F, 0x9D, 0x31, 0x3D, 0x05, - 0x8D, 0x91, 0x38, 0xBE, 0xC6, 0x4F, 0xB3, 0xC9, 0x15, 0xF5, 0x93, 0xE6, 0xB9, 0xEC, 0xEF, 0x8F, - 0xD7, 0x58, 0x3D, 0x18, 0xD0, 0x31, 0x1D, 0x86, 0xD4, 0x4E, 0x8A, 0x03, 0xF1, 0x85, 0x15, 0x4B, - 0xA8, 0x82, 0x1B, 0x0F, 0x14, 0x6E, 0x84, 0x9F, 0x51, 0xD3, 0xB0, 0x1F, 0xAD, 0x71, 0x40, 0x79, + 0x1F, 0x8B, 0x08, 0x08, 0x17, 0x68, 0x78, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0x1B, 0x39, 0xB2, 0xE8, 0xFF, + 0x79, 0x0A, 0xAD, 0xEF, 0xDE, 0x31, 0x2C, 0xC6, 0xD8, 0xE6, 0x23, 0x21, 0x84, 0xEC, 0x25, 0x40, + 0x12, 0xEE, 0x02, 0xE1, 0x62, 0x32, 0x33, 0x99, 0x6C, 0x0E, 0xA7, 0x71, 0x0B, 0xD3, 0x27, 0x76, + 0xB7, 0xB7, 0xBB, 0x0D, 0x61, 0xF6, 0xF0, 0x4E, 0xE7, 0x19, 0xCE, 0x93, 0xDD, 0x2A, 0x49, 0xDD, + 0x2D, 0xA9, 0xD5, 0x9F, 0xB6, 0x09, 0xB3, 0x27, 0xF9, 0xFD, 0x86, 0x81, 0x96, 0xEA, 0x43, 0xA5, + 0x52, 0xA9, 0x24, 0x95, 0x4A, 0xB7, 0x96, 0x4F, 0x86, 0x56, 0x48, 0xEF, 0xAC, 0x7B, 0xB2, 0x4B, + 0xFE, 0xFD, 0x2E, 0x78, 0xB9, 0xB6, 0xF6, 0xE7, 0x7F, 0xDE, 0x39, 0xAE, 0xED, 0xDD, 0xB5, 0x47, + 0xDE, 0xC0, 0x0A, 0x1D, 0xCF, 0x6D, 0xDF, 0x78, 0x41, 0xE8, 0x5A, 0x63, 0xFA, 0xF0, 0xF2, 0x45, + 0x77, 0xED, 0x2E, 0xF8, 0xF7, 0x9D, 0x67, 0xB7, 0x00, 0x77, 0x47, 0xAF, 0x02, 0x6F, 0xF0, 0x95, + 0x86, 0x3B, 0xCF, 0x9E, 0x09, 0x08, 0xCB, 0xB6, 0x0F, 0x6F, 0xA9, 0x1B, 0x1E, 0x3B, 0x41, 0x48, + 0x5D, 0xEA, 0x2F, 0x35, 0x47, 0x9E, 0x65, 0x37, 0x5B, 0xC4, 0x73, 0x8F, 0xE1, 0x97, 0x65, 0xA8, + 0x79, 0x3D, 0x75, 0x07, 0x88, 0x54, 0x7C, 0x5A, 0xA2, 0x58, 0x7F, 0x99, 0xFC, 0xF3, 0x19, 0x81, + 0x7F, 0x8E, 0xEB, 0x84, 0xBF, 0xD0, 0xAB, 0x3E, 0x43, 0xBB, 0x04, 0xD5, 0x1F, 0x24, 0x00, 0xAD, + 0x50, 0x80, 0xC4, 0x5C, 0x00, 0xFF, 0x2E, 0xBD, 0x23, 0x49, 0x0D, 0xD1, 0x2E, 0xC0, 0xA2, 0xD4, + 0x6B, 0x7B, 0xEE, 0x98, 0x06, 0x81, 0x35, 0xA4, 0x00, 0x11, 0x23, 0x5F, 0x1A, 0x07, 0xC3, 0x08, + 0x25, 0xFE, 0x9B, 0x58, 0x7E, 0x40, 0x8F, 0xDC, 0x81, 0x37, 0x76, 0xDC, 0x21, 0x16, 0xB6, 0x6D, + 0x2B, 0xB4, 0x04, 0xAE, 0x07, 0x95, 0xB1, 0x21, 0x5D, 0xA2, 0x11, 0xAC, 0x4F, 0xC3, 0xA9, 0xEF, + 0x12, 0xDB, 0x1B, 0x4C, 0xC7, 0xD0, 0xB0, 0xF6, 0x90, 0x86, 0x87, 0x23, 0x8A, 0xBF, 0xBE, 0xB9, + 0x3F, 0x82, 0xD6, 0xF2, 0x36, 0xA1, 0xF8, 0xAE, 0x9D, 0x6F, 0xD4, 0x3E, 0xB6, 0x90, 0xEF, 0xCE, + 0x8E, 0xF4, 0xC5, 0x73, 0x87, 0xC9, 0xA7, 0xC9, 0xC8, 0x0A, 0xAF, 0x3D, 0x7F, 0x7C, 0xE6, 0x53, + 0x28, 0x85, 0xEF, 0x8D, 0x06, 0x2F, 0x18, 0x52, 0xCF, 0xA6, 0xA1, 0x33, 0xE0, 0x08, 0x36, 0x3A, + 0xED, 0x4E, 0x57, 0x2B, 0x00, 0xC6, 0x76, 0xC9, 0x6A, 0xB7, 0xB3, 0xD9, 0xEE, 0x6E, 0xAB, 0x45, + 0x7B, 0x23, 0x84, 0xE9, 0x6E, 0x76, 0x3A, 0x6D, 0x01, 0x44, 0x07, 0xF4, 0xFA, 0x57, 0x56, 0xBD, + 0xF7, 0xA2, 0xD3, 0xEB, 0x6C, 0xB5, 0x37, 0xB7, 0x5E, 0x24, 0x25, 0x9F, 0xB0, 0x64, 0xE3, 0x79, + 0x77, 0xEB, 0x45, 0x67, 0xA3, 0xBD, 0xD1, 0x59, 0x4F, 0x4A, 0x7E, 0x63, 0xB4, 0x5F, 0x6C, 0x6D, + 0x6D, 0x6D, 0xB6, 0x37, 0x5E, 0x6C, 0xF0, 0x82, 0x91, 0x15, 0x84, 0x6F, 0x9D, 0x11, 0x3D, 0x05, + 0x8D, 0x91, 0x38, 0xBE, 0xC6, 0x4F, 0xD3, 0xF1, 0x15, 0xF5, 0x93, 0xE6, 0xB9, 0xEC, 0xEF, 0x0F, + 0xD7, 0x58, 0x3D, 0xE8, 0xD3, 0x11, 0x1D, 0x84, 0xD4, 0x4E, 0x8A, 0x03, 0xF1, 0x85, 0x15, 0x4B, + 0xA8, 0x82, 0x1B, 0x0F, 0x14, 0x6E, 0x88, 0x9F, 0x51, 0xD3, 0xB0, 0x1F, 0xAD, 0x51, 0x40, 0x79, 0xA1, 0x77, 0x15, 0x5A, 0x8E, 0x4B, 0xED, 0x13, 0xDE, 0xC9, 0xA5, 0x2A, 0xBC, 0xB1, 0x02, 0xAA, - 0x56, 0x12, 0x24, 0x44, 0x9D, 0xF3, 0x8B, 0x83, 0x93, 0x34, 0x22, 0x6C, 0xD1, 0x85, 0x75, 0x05, - 0xFF, 0xD0, 0xEF, 0xA1, 0xC4, 0xDE, 0xD0, 0xF3, 0x7D, 0xCA, 0x54, 0x43, 0x2B, 0x10, 0x7A, 0xA7, - 0x7D, 0x45, 0x79, 0x09, 0x3A, 0x17, 0xF7, 0x53, 0x9A, 0x5D, 0x22, 0xB8, 0xC4, 0x52, 0xCE, 0xA3, - 0x75, 0x1B, 0xB7, 0x02, 0x85, 0x8D, 0x22, 0xFA, 0xF2, 0x75, 0x37, 0x55, 0xF6, 0xB3, 0x35, 0x9E, - 0xA5, 0x0B, 0x0F, 0x6E, 0xE8, 0xF0, 0xDB, 0x95, 0xF7, 0xDD, 0x08, 0x19, 0x15, 0x2A, 0xA0, 0xAC, - 0x18, 0x5A, 0xE6, 0xF9, 0x76, 0x70, 0x74, 0x70, 0xF4, 0x56, 0x02, 0x12, 0x5F, 0xDF, 0x09, 0x0D, - 0x93, 0x4A, 0xAE, 0x67, 0xE3, 0xF1, 0x19, 0x30, 0xF1, 0x69, 0x0A, 0x03, 0x48, 0x12, 0xB2, 0x00, - 0x0B, 0x68, 0x78, 0xE1, 0x4C, 0xA8, 0x37, 0x0B, 0xA3, 0x2E, 0x77, 0xED, 0x43, 0x18, 0x69, 0xCA, - 0xC7, 0x21, 0x72, 0x73, 0x4A, 0xEF, 0xDE, 0x3A, 0xFE, 0xE4, 0xCE, 0xF2, 0xA9, 0x52, 0x08, 0x23, - 0xCC, 0x54, 0xF4, 0x6C, 0xE8, 0xB9, 0xD0, 0x61, 0xA0, 0x61, 0x07, 0x71, 0x77, 0x04, 0x03, 0x6F, - 0xE6, 0x0F, 0x59, 0x7B, 0x5E, 0xE8, 0x5D, 0x25, 0xCA, 0x74, 0x69, 0xA4, 0x2A, 0x9C, 0xF9, 0x8E, - 0xE7, 0x3B, 0xA1, 0x93, 0x48, 0x85, 0x13, 0x3A, 0xF0, 0x40, 0x00, 0x8E, 0x0B, 0x6D, 0xC4, 0xAE, - 0xC2, 0x42, 0x6E, 0x10, 0x0E, 0x3E, 0x7E, 0x3C, 0x3F, 0x3C, 0x3E, 0xDD, 0xBF, 0x38, 0xBA, 0x3C, - 0x3E, 0x3D, 0xFB, 0x74, 0x71, 0x79, 0xF1, 0xF9, 0xEC, 0xE8, 0xF2, 0xF0, 0xF0, 0x25, 0xE9, 0xB6, - 0xC9, 0xFA, 0xFA, 0x21, 0xBD, 0xB6, 0x66, 0x30, 0x1E, 0x0F, 0x0F, 0x3B, 0x76, 0xF4, 0x93, 0x0B, - 0x77, 0x72, 0xF2, 0x92, 0xF4, 0x18, 0x24, 0xFC, 0xDA, 0x99, 0xE0, 0x4F, 0x6E, 0xFD, 0x4B, 0x04, - 0xE8, 0x73, 0x00, 0x52, 0x16, 0xE2, 0xF2, 0x70, 0x7F, 0xF0, 0xFE, 0x25, 0xD9, 0xE0, 0x60, 0x6B, - 0xA5, 0xC1, 0x06, 0x9F, 0x4F, 0xDE, 0x7C, 0xFC, 0xF0, 0x92, 0x6C, 0x72, 0xC0, 0xFF, 0xFE, 0xAF, - 0x08, 0x72, 0x32, 0x69, 0x16, 0xB4, 0x6A, 0x30, 0x78, 0x49, 0xB6, 0x62, 0x36, 0xC9, 0x60, 0xD0, - 0x09, 0xD8, 0x4F, 0x31, 0x4D, 0x00, 0xDC, 0xAE, 0x07, 0x28, 0x9A, 0xF9, 0x3C, 0x6E, 0xE6, 0x5A, - 0x25, 0xE8, 0xA8, 0xB5, 0x2F, 0x92, 0xD6, 0x36, 0x63, 0x04, 0x8D, 0xC2, 0xF6, 0x5E, 0x9E, 0x7E, - 0xBC, 0x3C, 0x3C, 0x3A, 0x38, 0x3E, 0xD9, 0x07, 0x1C, 0x3B, 0x51, 0x97, 0x0E, 0x06, 0x64, 0x8D, - 0x9C, 0x7A, 0xC4, 0xA6, 0x43, 0x67, 0x62, 0x8D, 0xCB, 0xF0, 0x21, 0xE3, 0xE9, 0x75, 0x65, 0x51, - 0x54, 0x46, 0x85, 0x02, 0x51, 0xF1, 0xF5, 0x64, 0xE1, 0x94, 0xC5, 0x77, 0x7C, 0xFA, 0xF3, 0xFE, - 0x87, 0xE3, 0xC3, 0xCB, 0x4F, 0xA7, 0x7F, 0x3D, 0xFD, 0xF8, 0xCB, 0x29, 0xA0, 0xE9, 0xB7, 0xA3, - 0x79, 0x0F, 0x86, 0xCB, 0x2D, 0xF5, 0xC1, 0xAA, 0x27, 0x23, 0x06, 0x2D, 0x7E, 0xA7, 0x1B, 0x0D, - 0xB8, 0xE8, 0xEB, 0xB1, 0x3B, 0x9D, 0x85, 0xC2, 0x22, 0x6A, 0xA3, 0xAB, 0x93, 0xD5, 0x0C, 0xD9, - 0xC1, 0x48, 0x4D, 0xE1, 0xD1, 0x1C, 0xBD, 0xBE, 0x8E, 0x43, 0xD6, 0x1B, 0x53, 0xF0, 0x70, 0x46, - 0xAD, 0x46, 0x54, 0x25, 0x32, 0xCF, 0x2F, 0x49, 0x83, 0xAC, 0x12, 0xAC, 0x0F, 0xD8, 0xB0, 0x3E, - 0xB2, 0x85, 0xB3, 0x3F, 0xF0, 0x81, 0x8E, 0x40, 0x30, 0x1D, 0x3B, 0x61, 0xAB, 0xD9, 0x6E, 0x0A, - 0x6F, 0x00, 0xE6, 0x67, 0xD2, 0x1A, 0x83, 0x03, 0xF2, 0x9D, 0xCD, 0x5C, 0xF0, 0xBF, 0x57, 0xAC, - 0x7A, 0x67, 0x4C, 0xDD, 0x51, 0x78, 0x03, 0x32, 0xEB, 0xE1, 0xC7, 0xD5, 0x3D, 0xD2, 0x97, 0x3D, - 0x0C, 0xC4, 0xEA, 0xE0, 0x64, 0x87, 0x75, 0xBF, 0x7C, 0xFF, 0xBA, 0xAB, 0x94, 0xDC, 0x5A, 0xE3, - 0xB8, 0x08, 0xB8, 0xE9, 0x49, 0xC5, 0x1A, 0xFB, 0x8E, 0xCD, 0x19, 0x06, 0x5C, 0xAB, 0xA4, 0xD1, - 0x46, 0x48, 0xFE, 0x01, 0x7E, 0x89, 0x5A, 0xC0, 0xC1, 0x06, 0x53, 0xE8, 0x38, 0xC0, 0x0B, 0xCD, - 0x9D, 0x58, 0xAE, 0x1D, 0xC4, 0x45, 0xCE, 0x35, 0x69, 0x39, 0x76, 0xC7, 0x71, 0x87, 0xE3, 0x99, - 0x4D, 0x83, 0x56, 0x23, 0xB0, 0x4F, 0xBC, 0x99, 0x0B, 0x7D, 0xD4, 0x58, 0x91, 0x59, 0xE6, 0x68, - 0x2E, 0xD0, 0xC1, 0xF1, 0xDC, 0x75, 0xEF, 0xFA, 0x9A, 0x0C, 0x0E, 0x09, 0x18, 0x5D, 0x4B, 0xA9, - 0x81, 0xD8, 0x18, 0xFB, 0x30, 0x55, 0x31, 0x63, 0xDF, 0xD0, 0x71, 0xE0, 0xCF, 0x8D, 0x63, 0xD3, - 0x56, 0x03, 0xA7, 0xD0, 0x13, 0xCB, 0x05, 0xA9, 0xFB, 0x8D, 0x95, 0x5D, 0xA5, 0xD2, 0x83, 0xF2, - 0x17, 0x05, 0x3C, 0x0A, 0xE6, 0xD0, 0x9F, 0x99, 0x11, 0xE3, 0xCC, 0x5D, 0x12, 0x71, 0xF2, 0x5B, - 0x8C, 0x1E, 0x7B, 0x04, 0xB0, 0xAB, 0x7E, 0x57, 0x8A, 0x4E, 0xCA, 0x2D, 0x03, 0xAE, 0x54, 0x22, - 0xB1, 0x03, 0x18, 0x3A, 0xE1, 0x98, 0xCD, 0xDA, 0xE7, 0x17, 0x7F, 0x65, 0xDD, 0xA2, 0xC1, 0x42, - 0x9F, 0x91, 0x01, 0x38, 0x8D, 0xD3, 0x86, 0x8A, 0x20, 0x35, 0x6F, 0x62, 0x83, 0xD5, 0x2A, 0x46, - 0x3F, 0x23, 0xD5, 0x15, 0x3A, 0xAF, 0x50, 0xED, 0xE8, 0xE7, 0xBF, 0xE6, 0x88, 0xEE, 0x0A, 0xDC, - 0x8C, 0x03, 0xCF, 0xBD, 0x76, 0x46, 0xBA, 0xE4, 0x92, 0x3A, 0xD3, 0x69, 0x51, 0x0D, 0x1A, 0xDE, - 0x50, 0xDF, 0xA5, 0x61, 0x51, 0x3D, 0x37, 0x2C, 0x44, 0x35, 0xF5, 0xFC, 0x30, 0xC8, 0xAE, 0xC4, - 0x35, 0x09, 0x24, 0x00, 0xF4, 0xAC, 0xF1, 0x19, 0x54, 0xFE, 0x38, 0x65, 0x13, 0x76, 0x36, 0x46, - 0x18, 0x38, 0x17, 0xDE, 0xE0, 0xF0, 0xC0, 0xF2, 0xED, 0x6C, 0x8C, 0x23, 0x6B, 0x0C, 0x4A, 0xE4, - 0xBD, 0xB7, 0xC0, 0x33, 0x0D, 0x43, 0x30, 0x10, 0xD9, 0x55, 0x43, 0x67, 0x1C, 0x16, 0x31, 0x78, - 0x45, 0xE9, 0x94, 0xFA, 0x50, 0x2B, 0xF4, 0xBD, 0x71, 0x36, 0x6B, 0xB3, 0x80, 0xEE, 0x07, 0x01, - 0xF8, 0x9A, 0xA7, 0xDE, 0x5D, 0xE4, 0x85, 0x65, 0xD7, 0x9E, 0x50, 0x2B, 0x98, 0xF9, 0x6C, 0x7D, - 0x71, 0x1E, 0x99, 0xCC, 0x6C, 0x16, 0x26, 0x5E, 0x60, 0x39, 0xC3, 0xD3, 0x93, 0xA3, 0xFD, 0x41, - 0x08, 0xA3, 0x76, 0x72, 0xE8, 0x7B, 0x53, 0x58, 0xB6, 0xE5, 0x49, 0x0A, 0xB0, 0xDF, 0xD2, 0xFB, - 0x63, 0x57, 0x88, 0x20, 0xC8, 0x65, 0xFC, 0x03, 0x2C, 0x18, 0xC7, 0xCE, 0xEF, 0xD4, 0x3E, 0x04, - 0xFE, 0x7D, 0xE7, 0x6A, 0x86, 0xDD, 0x50, 0xDC, 0x08, 0x80, 0x3C, 0x72, 0xD1, 0x8F, 0x3E, 0xFA, - 0x1E, 0xA2, 0xB3, 0x76, 0x6E, 0xD9, 0x8E, 0x97, 0xA3, 0x59, 0x52, 0xAD, 0xC1, 0xD9, 0xFE, 0xF9, - 0xC5, 0x29, 0xF7, 0xCC, 0xA2, 0xD6, 0x94, 0x34, 0x24, 0xA6, 0x81, 0xF1, 0xD6, 0x1A, 0x82, 0x1D, - 0xBF, 0xED, 0xC3, 0xE8, 0xF8, 0xCF, 0xFF, 0x24, 0x79, 0x35, 0xC8, 0x87, 0x37, 0x60, 0x42, 0xD3, - 0xE6, 0x71, 0x71, 0xC3, 0x48, 0xA8, 0x75, 0xE1, 0x30, 0xE2, 0xF5, 0xE6, 0x1F, 0x46, 0xB1, 0x70, - 0xFF, 0x18, 0x46, 0x7F, 0x0C, 0xA3, 0xF2, 0xC3, 0x28, 0x73, 0x8C, 0x70, 0x29, 0xFD, 0xBA, 0xD5, - 0xF8, 0x63, 0x88, 0x3C, 0xB5, 0x21, 0xC2, 0xAB, 0x95, 0x1D, 0x22, 0x42, 0xE9, 0x4B, 0x0E, 0x11, - 0x31, 0xA0, 0xAA, 0x0C, 0x11, 0x4E, 0xA0, 0xCC, 0x10, 0x89, 0x19, 0x5F, 0xF6, 0x10, 0x89, 0x7D, - 0x8A, 0xC2, 0x21, 0x92, 0xA6, 0xC4, 0x36, 0xAD, 0xC0, 0x1B, 0x1B, 0x01, 0x06, 0xFB, 0xDE, 0xB5, - 0x26, 0xCE, 0xF0, 0xC4, 0xB3, 0xA9, 0xB1, 0x27, 0x70, 0xD9, 0xE0, 0xD2, 0x3B, 0xAE, 0x46, 0x62, - 0x07, 0x93, 0xFF, 0xD1, 0x6A, 0x0E, 0x42, 0x2B, 0x74, 0x86, 0xCD, 0x36, 0x69, 0x76, 0x9B, 0xA6, - 0x16, 0x31, 0x3A, 0xB8, 0xE5, 0xDA, 0x8A, 0x31, 0xB4, 0xC9, 0xCC, 0xB5, 0x61, 0x1C, 0xBA, 0xD4, - 0x36, 0x40, 0x64, 0x11, 0xFA, 0x7F, 0x33, 0x0B, 0xD5, 0x20, 0xA2, 0xD6, 0x5B, 0x2E, 0xB5, 0x33, - 0x0A, 0x4B, 0x0C, 0xE8, 0x33, 0xCB, 0x45, 0x62, 0xFD, 0xE5, 0x12, 0xDB, 0x9F, 0x85, 0xDE, 0xC4, - 0x0B, 0x9D, 0x5B, 0x8A, 0xC4, 0x36, 0x96, 0x4B, 0xEC, 0x1C, 0xEC, 0x1E, 0x81, 0x91, 0x8E, 0xA4, - 0x36, 0x97, 0x4B, 0xEA, 0x3D, 0xB5, 0x6E, 0xEF, 0xC9, 0x89, 0x35, 0xBC, 0x01, 0x40, 0xFF, 0x1E, - 0x29, 0x6E, 0x2D, 0x97, 0xE2, 0xA7, 0xFD, 0x9F, 0x91, 0xCA, 0xF6, 0x92, 0xA9, 0xB8, 0x63, 0x67, - 0xE2, 0xC0, 0xC2, 0x13, 0x69, 0x3D, 0xAF, 0x47, 0x2B, 0x05, 0x32, 0x62, 0xE6, 0x8B, 0x6F, 0xE4, - 0x32, 0xD3, 0x75, 0xED, 0xE1, 0x82, 0xA9, 0xB1, 0xD2, 0x09, 0x68, 0xB8, 0x1F, 0x72, 0xFB, 0x41, - 0x5B, 0x4D, 0x5C, 0x6D, 0xAF, 0x5D, 0x05, 0x6B, 0x9E, 0xEF, 0x8C, 0x1C, 0x30, 0xF0, 0x6B, 0x6C, - 0xED, 0x06, 0x0B, 0xFD, 0x8B, 0x1B, 0x4A, 0xDE, 0x9D, 0x0E, 0x06, 0x64, 0x68, 0xC1, 0xCA, 0x77, - 0x16, 0x82, 0xE9, 0x23, 0x68, 0xDB, 0x08, 0xB8, 0x80, 0x04, 0xF7, 0x86, 0x6F, 0x37, 0x88, 0x15, - 0x12, 0xDB, 0xB9, 0xBE, 0xA6, 0x3E, 0x18, 0x48, 0xE2, 0x03, 0x99, 0xA0, 0x43, 0xDE, 0x7A, 0x3E, - 0xAB, 0xF7, 0x32, 0x32, 0x0A, 0x16, 0x09, 0x98, 0x39, 0x64, 0x7B, 0x06, 0x14, 0x7A, 0x2F, 0xDA, - 0x73, 0x68, 0x33, 0x54, 0xC0, 0x0E, 0xFC, 0x9F, 0x38, 0xB0, 0xF2, 0xF6, 0x71, 0x9D, 0x1B, 0xD7, - 0xE2, 0x50, 0x1C, 0x21, 0xA7, 0xF7, 0x32, 0xBB, 0x72, 0x74, 0xBA, 0x31, 0xF2, 0xBD, 0xD9, 0x94, - 0x23, 0xA6, 0xCC, 0xE8, 0x41, 0x5D, 0xDB, 0xB9, 0x75, 0xEC, 0x19, 0xD4, 0x16, 0x95, 0x82, 0x8E, - 0x49, 0xC6, 0x28, 0x30, 0x3F, 0x1C, 0x4E, 0xEA, 0x49, 0x0B, 0x19, 0x24, 0x4E, 0x00, 0x0B, 0x56, - 0xCB, 0x0D, 0xA0, 0x33, 0x71, 0x4B, 0xFF, 0xEA, 0x9E, 0xC0, 0x2C, 0x4D, 0x70, 0xC2, 0x47, 0x49, - 0x59, 0xC4, 0x16, 0xFB, 0x9E, 0xDE, 0x35, 0xE9, 0xBD, 0xFF, 0x9D, 0x31, 0x1F, 0xB1, 0x44, 0x7A, - 0xDD, 0xEE, 0x56, 0x9B, 0x9C, 0x0C, 0x4E, 0x36, 0x39, 0xF7, 0xDD, 0x4E, 0x54, 0xA5, 0xD7, 0xDD, - 0xD8, 0xE8, 0x90, 0x8B, 0x1B, 0xC0, 0x8E, 0x5D, 0x71, 0x45, 0xC9, 0xD8, 0xBB, 0x03, 0x91, 0xDB, - 0xAC, 0xD4, 0x47, 0x3B, 0x1D, 0x90, 0x3B, 0x27, 0xBC, 0xC1, 0xEF, 0x40, 0xCD, 0xB5, 0xEF, 0x1C, - 0x1B, 0xFE, 0x82, 0xC2, 0xD0, 0x72, 0xC6, 0x1E, 0xD6, 0x0C, 0xBD, 0x98, 0x33, 0xC0, 0x7E, 0xBF, - 0x6E, 0x8D, 0xC7, 0x4C, 0xA6, 0x89, 0x48, 0xC8, 0x07, 0xD4, 0xC1, 0xE0, 0x25, 0x12, 0xC6, 0xEA, - 0xDB, 0xDD, 0x6E, 0xA6, 0x98, 0x68, 0x6A, 0x3A, 0xA9, 0x2E, 0x30, 0x3E, 0x25, 0x91, 0xC8, 0xAF, - 0xE0, 0xED, 0x90, 0x77, 0x9E, 0x5F, 0x46, 0x4A, 0x06, 0xE3, 0x85, 0xCF, 0xAC, 0xE4, 0xE0, 0xE3, - 0x49, 0xBF, 0x43, 0xC4, 0xEE, 0xF1, 0x4B, 0xF2, 0x16, 0xF7, 0x59, 0x9A, 0xB5, 0x3D, 0xB6, 0x0B, - 0xCF, 0x1F, 0xDE, 0xFC, 0x13, 0x39, 0x6A, 0xB9, 0x5B, 0x02, 0x19, 0xB5, 0x35, 0x4F, 0x2D, 0xA3, - 0x16, 0xDB, 0xEC, 0xA7, 0xE3, 0x31, 0x3B, 0x18, 0x1D, 0x80, 0x5C, 0xA0, 0x2E, 0x59, 0x5F, 0x3F, - 0xF5, 0x42, 0x12, 0xCC, 0xA6, 0xC8, 0x16, 0xA8, 0x18, 0x74, 0xD3, 0xA7, 0x93, 0x9D, 0x17, 0xDD, - 0x32, 0x38, 0x4E, 0xAD, 0x5B, 0x67, 0x98, 0x8B, 0xA4, 0xDA, 0x0A, 0x07, 0x77, 0x6B, 0x3D, 0x18, - 0x44, 0x38, 0xDC, 0xCE, 0xCE, 0x3E, 0x10, 0xA8, 0x46, 0x4E, 0xDE, 0xED, 0xFF, 0x0B, 0xE1, 0xD8, - 0x7D, 0xDA, 0xE9, 0x74, 0x2A, 0xAE, 0x82, 0x96, 0xE8, 0xE2, 0x30, 0x9F, 0xEF, 0x11, 0x5C, 0x1C, - 0x31, 0x7B, 0xF5, 0x1E, 0xD3, 0xDB, 0xE8, 0x2F, 0x70, 0xFA, 0xFA, 0xE1, 0xD6, 0xB8, 0xD7, 0x7D, - 0xBE, 0x89, 0xFF, 0xBE, 0x60, 0xFF, 0xEE, 0xE0, 0xBF, 0xBD, 0xFE, 0x0F, 0xB7, 0xCF, 0x58, 0xB9, - 0xDF, 0xED, 0xA0, 0x6E, 0xD3, 0x97, 0x04, 0xA7, 0x69, 0x49, 0x87, 0xD9, 0x2C, 0x8C, 0x4D, 0xF7, - 0x6E, 0xA9, 0xEF, 0x3B, 0xB6, 0x4D, 0x5D, 0xAC, 0x8F, 0xBC, 0xDE, 0xDD, 0x50, 0x9C, 0x39, 0x09, - 0x3B, 0x51, 0x9D, 0x80, 0xE6, 0x76, 0x9A, 0xD5, 0x36, 0x89, 0xA5, 0xBD, 0xF2, 0x91, 0x1B, 0x04, - 0xD1, 0xE9, 0xE3, 0xCF, 0xD4, 0x0F, 0xA0, 0x43, 0x8F, 0xDD, 0xD0, 0xB4, 0x71, 0x0E, 0x43, 0xC4, - 0xB9, 0xBE, 0xC7, 0x89, 0x9B, 0x2D, 0x70, 0x88, 0x3D, 0xA3, 0xC8, 0xD0, 0xB5, 0x00, 0x26, 0xCC, - 0xF5, 0x61, 0x46, 0x21, 0x48, 0xED, 0xE2, 0x66, 0x6F, 0xE3, 0x16, 0x6C, 0x54, 0xCD, 0xB9, 0x95, - 0xB5, 0xA8, 0x91, 0x8E, 0x36, 0x18, 0x67, 0xB9, 0x47, 0x18, 0xEB, 0x03, 0x2E, 0x43, 0x8B, 0xBB, - 0xC5, 0xFD, 0xC7, 0x5C, 0xCD, 0x6C, 0x3C, 0xA6, 0x7D, 0x59, 0xF2, 0x12, 0x63, 0x40, 0xAD, 0x47, - 0x58, 0x56, 0xEC, 0x3B, 0xFE, 0x95, 0x07, 0x4E, 0x01, 0xE9, 0x8D, 0x1E, 0x61, 0x79, 0x11, 0x53, - 0xEB, 0x8F, 0xE6, 0x58, 0x60, 0x54, 0xA6, 0xB6, 0xC9, 0xA8, 0xBD, 0x58, 0x2E, 0xB5, 0x5F, 0x7C, - 0xF0, 0x05, 0x90, 0xCE, 0xCE, 0x72, 0xE9, 0xBC, 0x71, 0xBE, 0x31, 0xF5, 0xEB, 0x2D, 0x68, 0x18, - 0x47, 0x87, 0x7A, 0xAF, 0xF7, 0x48, 0xAF, 0xDF, 0x33, 0x19, 0xA1, 0xCA, 0x86, 0xA8, 0xC8, 0x18, - 0x9D, 0xE0, 0xA4, 0xC4, 0xDA, 0x60, 0x74, 0x08, 0xEA, 0xB5, 0x23, 0x4F, 0x66, 0x47, 0x6B, 0x83, - 0xA1, 0x07, 0x73, 0x14, 0x27, 0xDA, 0x5F, 0x1C, 0xD1, 0x87, 0xC2, 0x49, 0x6B, 0x7D, 0x7D, 0x00, - 0xE6, 0x09, 0xA7, 0x9B, 0x11, 0x46, 0xE4, 0x59, 0x62, 0xFE, 0xC7, 0xD3, 0xC8, 0x99, 0xEB, 0x84, - 0x05, 0x93, 0x5B, 0x60, 0xBF, 0xF5, 0x29, 0x1D, 0x4C, 0x61, 0xAA, 0x68, 0xAC, 0x28, 0xB4, 0x60, - 0x52, 0xD1, 0x6A, 0x0E, 0x9C, 0xDF, 0x8B, 0x2A, 0xDD, 0x80, 0x73, 0x8D, 0x53, 0xDD, 0xF1, 0x61, - 0x41, 0x45, 0xC3, 0xA4, 0x5A, 0x00, 0x61, 0x5B, 0xF7, 0xC1, 0x39, 0x9D, 0x58, 0x8E, 0xCB, 0xF6, - 0x4F, 0x73, 0xEB, 0x4E, 0x7D, 0x0F, 0xCF, 0x87, 0xBB, 0x18, 0xEC, 0x53, 0xAE, 0x6A, 0xAF, 0x7C, - 0xD5, 0x7E, 0xF9, 0xAA, 0x1B, 0xE5, 0xAB, 0x6E, 0x96, 0xAF, 0xBA, 0x55, 0xBE, 0xEA, 0x76, 0xF9, - 0xAA, 0xCF, 0x4B, 0x54, 0x65, 0x0E, 0xDE, 0xC9, 0xFE, 0x41, 0x51, 0x57, 0x51, 0x58, 0xF2, 0xD0, - 0x37, 0x17, 0x85, 0x5A, 0x00, 0x4B, 0xB2, 0x28, 0x90, 0xB0, 0xA0, 0xE6, 0x95, 0x05, 0x8E, 0xAD, - 0x7F, 0x7F, 0x46, 0xFD, 0x21, 0x45, 0xE7, 0x2B, 0xAE, 0xAC, 0xDB, 0x13, 0x30, 0x1F, 0x8E, 0xBD, - 0x02, 0x90, 0x30, 0x16, 0xDE, 0x5F, 0x9C, 0x7C, 0xD0, 0xCF, 0xEE, 0x8B, 0xBC, 0x3D, 0x3F, 0xFC, - 0x96, 0xD2, 0x4B, 0x03, 0x0D, 0x63, 0xBD, 0x6C, 0xAA, 0xD9, 0x50, 0x9F, 0xA6, 0x23, 0x90, 0x2A, - 0x6D, 0xCC, 0xC1, 0xF2, 0x10, 0x97, 0xC9, 0xFE, 0xE4, 0x1C, 0x63, 0xED, 0xD2, 0xCC, 0xB2, 0x10, - 0xBC, 0x03, 0x6F, 0x32, 0x05, 0x83, 0x49, 0x5B, 0x2B, 0x95, 0xD1, 0x62, 0xB0, 0xDE, 0x39, 0x1D, - 0x52, 0x67, 0x6A, 0x40, 0x9E, 0xAE, 0xA3, 0x52, 0x28, 0x20, 0x21, 0x54, 0x8F, 0x47, 0x8D, 0x1A, - 0xB0, 0xCF, 0x7C, 0xDC, 0x6D, 0x3B, 0x93, 0x6B, 0x99, 0x24, 0xFB, 0xE7, 0x56, 0xC3, 0xC1, 0xB5, - 0xEC, 0x17, 0x8C, 0x61, 0xDE, 0x13, 0x48, 0xD9, 0x5E, 0xCD, 0xD7, 0x2F, 0xB7, 0x18, 0xE0, 0xB8, - 0x87, 0x71, 0x19, 0x46, 0x6C, 0xAB, 0xA4, 0xF1, 0x15, 0x64, 0x0F, 0x30, 0xD3, 0x56, 0x93, 0x85, - 0x21, 0xB2, 0xAD, 0x49, 0x8C, 0xC5, 0xA8, 0x20, 0xAA, 0xC8, 0xC3, 0xFF, 0x34, 0xC5, 0x70, 0xE8, - 0x48, 0xD8, 0xE9, 0x06, 0x99, 0xEB, 0xB5, 0x6A, 0x53, 0x42, 0x4F, 0x78, 0x16, 0x14, 0xD1, 0xE1, - 0xB5, 0x5A, 0x3C, 0x5C, 0xA8, 0xF4, 0xAA, 0x27, 0x89, 0x3F, 0x36, 0x0D, 0x00, 0x39, 0x38, 0xD9, - 0xA4, 0xE9, 0x73, 0x8D, 0x41, 0x29, 0xC4, 0x39, 0x87, 0x36, 0x9B, 0x84, 0x97, 0x46, 0x7B, 0x7F, - 0x9C, 0xD3, 0x6E, 0x1E, 0x60, 0xBD, 0x70, 0xDA, 0x2C, 0x4A, 0x3B, 0x4D, 0x35, 0x0A, 0xDE, 0x5E, - 0x0A, 0xBD, 0xCF, 0x66, 0x7A, 0x9F, 0x97, 0x45, 0xEF, 0x37, 0x33, 0xBD, 0xDF, 0x96, 0x42, 0x2F, - 0x98, 0xBA, 0xDE, 0xDD, 0x19, 0xC5, 0xB3, 0xD2, 0x99, 0x69, 0xC9, 0x1E, 0xBB, 0xA6, 0xA4, 0xBB, - 0x62, 0xDC, 0x96, 0x99, 0x02, 0x2C, 0xCC, 0x77, 0x81, 0x66, 0x9E, 0x1B, 0x8D, 0x3A, 0x4C, 0x5C, - 0x66, 0x32, 0xF0, 0xA5, 0xFB, 0x95, 0xFC, 0x09, 0xD0, 0x76, 0x1B, 0xE4, 0xA7, 0x9F, 0xB0, 0x8D, - 0x5F, 0x7A, 0xD1, 0x07, 0x93, 0xBF, 0x9C, 0xC9, 0xD9, 0x2A, 0x13, 0x10, 0x1A, 0xB5, 0x57, 0x57, - 0xFE, 0xEB, 0x46, 0xDD, 0x1D, 0x8F, 0x80, 0x2F, 0xB0, 0x31, 0x04, 0xDC, 0x34, 0x9F, 0xC4, 0xF1, - 0xE1, 0x9D, 0xE9, 0x2C, 0xB8, 0xA9, 0x68, 0x57, 0x04, 0xEE, 0x28, 0x90, 0x3C, 0x13, 0x7F, 0x54, - 0xA1, 0x0E, 0x8D, 0xEB, 0x09, 0xF7, 0x28, 0x74, 0xD4, 0xDA, 0xC5, 0x85, 0x4A, 0xBA, 0x74, 0x3D, - 0xE1, 0xEE, 0x6F, 0xDA, 0xD4, 0xCA, 0x77, 0x04, 0xA0, 0x03, 0x1A, 0xAF, 0x42, 0x9F, 0x58, 0x63, - 0x67, 0xE4, 0xEE, 0x35, 0xC7, 0xF4, 0x3A, 0x6C, 0xEA, 0xFD, 0x60, 0x82, 0xB0, 0x5F, 0xE3, 0x0C, - 0xA5, 0xF0, 0x87, 0x9D, 0xB8, 0x8E, 0x05, 0x65, 0xA1, 0xA3, 0x9E, 0x2F, 0x0D, 0xF4, 0x8A, 0x4D, - 0x9A, 0x24, 0xBC, 0x9F, 0xD2, 0x3D, 0x3E, 0xF7, 0x5D, 0x79, 0xDF, 0x9B, 0xE0, 0x77, 0xED, 0x35, - 0x4D, 0xDC, 0x34, 0x09, 0x9B, 0x5E, 0x9B, 0x88, 0xEC, 0xF8, 0xB0, 0x49, 0x86, 0x50, 0x21, 0x80, - 0x3F, 0x3D, 0x7F, 0xB2, 0xC6, 0xA0, 0xD7, 0x38, 0x3E, 0x29, 0x32, 0x93, 0x6D, 0x5B, 0x37, 0x5F, - 0x97, 0x64, 0x69, 0x3D, 0x54, 0x74, 0xB6, 0x44, 0x2F, 0xB3, 0x8D, 0x52, 0xBD, 0x47, 0xF0, 0x86, - 0x01, 0xF2, 0x5D, 0x65, 0x5A, 0x9D, 0x5D, 0x7D, 0x3F, 0x49, 0x0E, 0x10, 0x19, 0x4E, 0x58, 0x58, - 0x11, 0xF5, 0xF3, 0x25, 0x1E, 0xF5, 0x5D, 0x1E, 0x5E, 0x9C, 0x68, 0xDF, 0x71, 0x93, 0xF1, 0x12, - 0x77, 0x30, 0x2F, 0x71, 0x2B, 0x55, 0xE1, 0x45, 0xBA, 0x14, 0x22, 0x94, 0xCE, 0xB1, 0x77, 0xB3, - 0x6A, 0x9C, 0xF3, 0x38, 0xD0, 0x94, 0x19, 0xD4, 0x90, 0x7C, 0xB0, 0xAE, 0xE8, 0xD8, 0x14, 0x0C, - 0x2A, 0xD5, 0x3B, 0x14, 0xD1, 0xCC, 0x09, 0x54, 0x14, 0xD5, 0x7C, 0xA9, 0xAF, 0x4D, 0x51, 0x16, - 0x12, 0x54, 0x14, 0xD4, 0x0C, 0xAB, 0xF5, 0x0D, 0x93, 0xED, 0x91, 0xAF, 0xB9, 0xF0, 0xD0, 0x6D, - 0x09, 0x18, 0xCC, 0xD6, 0x6E, 0x9E, 0xDC, 0xF6, 0xD8, 0x69, 0xA9, 0x71, 0x87, 0x40, 0xBF, 0x24, - 0xF3, 0xA7, 0x3D, 0x99, 0x4C, 0xD6, 0xAE, 0x41, 0xFA, 0x6A, 0x8D, 0x04, 0x64, 0x5E, 0x83, 0xCB, - 0x77, 0x74, 0x98, 0xDA, 0xDD, 0xA4, 0x2C, 0xA5, 0xE6, 0xBB, 0x6A, 0x90, 0x72, 0x1F, 0xA8, 0x6D, - 0xC7, 0x51, 0x72, 0xC9, 0x62, 0xCB, 0xA5, 0xCF, 0x7D, 0x93, 0x48, 0x54, 0x95, 0x01, 0x44, 0x66, - 0xF5, 0xC9, 0xE9, 0x9F, 0xBD, 0x3D, 0xB2, 0x99, 0x25, 0x95, 0xBA, 0x8C, 0x1A, 0x3F, 0x6F, 0x18, - 0xBB, 0x94, 0xF1, 0xBB, 0xD9, 0x7D, 0xDE, 0xBF, 0xEC, 0x46, 0xDC, 0xF3, 0xBF, 0x0A, 0x77, 0x30, - 0x9E, 0xE5, 0x76, 0x86, 0xED, 0xDC, 0x2A, 0x86, 0x85, 0x9D, 0x71, 0x13, 0xDF, 0xBB, 0xE3, 0x76, - 0x69, 0x12, 0x8C, 0x24, 0xFE, 0x62, 0xCB, 0xA4, 0x77, 0x60, 0x0A, 0xED, 0x98, 0x89, 0x01, 0x30, - 0x72, 0xD3, 0xA6, 0xC3, 0x47, 0x24, 0x87, 0xDE, 0x78, 0x2D, 0x98, 0xAC, 0x6D, 0x12, 0xFC, 0x65, - 0x9B, 0xFD, 0xCB, 0xB8, 0x60, 0xE0, 0xCD, 0xD7, 0x1A, 0x28, 0x97, 0x2D, 0xC0, 0xBF, 0x7C, 0xB5, - 0xCE, 0x6A, 0x14, 0xB2, 0x21, 0xB5, 0x4E, 0x21, 0xB5, 0xD9, 0x54, 0x8D, 0x31, 0xBF, 0x36, 0xA7, - 0x99, 0x58, 0x1E, 0xEE, 0xD5, 0x2C, 0xA0, 0x11, 0x9B, 0xEF, 0x54, 0x1B, 0xF9, 0x4A, 0x48, 0x2E, - 0x63, 0x06, 0xA7, 0x94, 0xFC, 0xA6, 0x59, 0x68, 0x8F, 0x7C, 0xDF, 0x4B, 0x18, 0x75, 0xDC, 0xB1, - 0xE3, 0x52, 0xFE, 0x0D, 0xAC, 0xFE, 0xB4, 0x10, 0xEF, 0x3A, 0x48, 0xE4, 0x35, 0xFF, 0xB7, 0x82, - 0xE5, 0x9F, 0xC8, 0xA6, 0x3A, 0xB5, 0x55, 0x20, 0x4A, 0x8F, 0x45, 0xDC, 0x04, 0xEA, 0xA6, 0xE9, - 0xB0, 0x46, 0x16, 0x02, 0x33, 0x50, 0xEF, 0xCE, 0xC0, 0x44, 0xE5, 0x54, 0x42, 0x44, 0xE7, 0x78, - 0xD4, 0xC4, 0x94, 0x1F, 0xC6, 0x6A, 0xCF, 0x5C, 0x19, 0xEB, 0x06, 0x58, 0x25, 0x1E, 0xE4, 0xD9, - 0x75, 0x15, 0x2E, 0x25, 0xE4, 0xFD, 0x8D, 0x6E, 0x09, 0x80, 0x84, 0x80, 0x5E, 0xBF, 0xCE, 0xBC, - 0xC3, 0xAE, 0xD3, 0xBC, 0x85, 0x05, 0x63, 0xA8, 0xB9, 0x5B, 0x05, 0x73, 0x90, 0x5E, 0xED, 0x3F, - 0x66, 0xE0, 0xFD, 0x5C, 0x3B, 0x6C, 0xA9, 0xAE, 0x97, 0x67, 0x75, 0x65, 0x7E, 0x67, 0xE1, 0x8F, - 0x82, 0x35, 0x0E, 0x8A, 0x69, 0xE4, 0x19, 0x97, 0x7A, 0xF3, 0x61, 0xA1, 0xF1, 0xDC, 0xFD, 0x27, - 0x34, 0x61, 0x89, 0x74, 0xFF, 0x30, 0x67, 0x3F, 0xCA, 0x9C, 0xF1, 0x40, 0x5A, 0x34, 0x45, 0x79, - 0xE6, 0x2A, 0xA9, 0x75, 0xF9, 0xEE, 0xDD, 0x7E, 0xFD, 0x41, 0xBF, 0x04, 0x4F, 0x72, 0x21, 0x23, - 0xE7, 0x9F, 0x60, 0x96, 0x17, 0x47, 0x59, 0x7C, 0xB5, 0x64, 0x64, 0x24, 0x53, 0xA9, 0xE5, 0x11, - 0x62, 0x8B, 0x20, 0x64, 0x32, 0xB9, 0x5A, 0xEB, 0x17, 0x37, 0xDE, 0xE3, 0xE7, 0x52, 0x62, 0x58, - 0x74, 0x9B, 0xAF, 0x3F, 0x5E, 0x5F, 0xBF, 0x5A, 0xE7, 0x5F, 0x2B, 0x02, 0xF7, 0x9A, 0xAF, 0xB9, - 0x9A, 0xF5, 0x6A, 0x22, 0xE8, 0x47, 0x08, 0xFA, 0xA5, 0x11, 0xAC, 0x73, 0xA9, 0x95, 0x1B, 0x62, - 0xBA, 0xBE, 0xC2, 0xF0, 0x18, 0x58, 0xB7, 0x94, 0x05, 0xBD, 0xA0, 0xD8, 0x59, 0xD4, 0x0A, 0xE3, - 0x85, 0x58, 0x01, 0xB9, 0xA3, 0x18, 0xAC, 0xD2, 0x0C, 0x59, 0x44, 0x25, 0x56, 0xE1, 0x25, 0xF7, - 0x34, 0xEC, 0x28, 0xF8, 0x6F, 0xA0, 0xAE, 0xEB, 0x85, 0x58, 0x40, 0xAE, 0x28, 0x75, 0x89, 0x65, - 0xDB, 0x3C, 0x5E, 0x25, 0xDE, 0x61, 0x51, 0x17, 0x9A, 0xFA, 0xF5, 0x7C, 0xBE, 0x57, 0x21, 0x75, - 0xAA, 0x36, 0x40, 0xD2, 0x77, 0xF6, 0xEB, 0xEC, 0x6E, 0x08, 0xFC, 0x3C, 0xA8, 0xD0, 0x2E, 0x72, - 0x6F, 0xA4, 0x6A, 0xA5, 0xFC, 0x0B, 0xA9, 0xFE, 0x82, 0xDC, 0x8B, 0xA7, 0x6A, 0x69, 0x52, 0xFB, - 0x17, 0x64, 0x12, 0xAE, 0x6D, 0x94, 0xB5, 0x32, 0xE9, 0xDD, 0x0F, 0x6E, 0x3E, 0xB2, 0xCD, 0xCF, - 0x6B, 0x11, 0x06, 0x9A, 0x65, 0x5F, 0xCA, 0x9A, 0x17, 0x3E, 0xB3, 0x66, 0xEC, 0xBE, 0x34, 0x33, - 0xB7, 0x73, 0x2A, 0x5B, 0xD3, 0x79, 0x47, 0x5A, 0x7C, 0x9C, 0xB2, 0xA0, 0x91, 0xA6, 0xE4, 0xB3, - 0x28, 0x35, 0xD4, 0xD4, 0x24, 0x17, 0x75, 0xC6, 0x9A, 0x14, 0xA3, 0x2B, 0xF2, 0x42, 0xDC, 0xA7, - 0x07, 0x9B, 0x9A, 0x46, 0x22, 0x67, 0x40, 0x24, 0x95, 0x22, 0x64, 0x91, 0xDB, 0x0D, 0xFE, 0x6F, - 0x86, 0xD3, 0x9D, 0xC0, 0x88, 0xF1, 0xA1, 0x52, 0xCA, 0x1C, 0x22, 0x69, 0xA6, 0xA2, 0x91, 0xA2, - 0x62, 0x4C, 0x0F, 0x16, 0x14, 0x82, 0x39, 0x6D, 0x46, 0xB4, 0xF7, 0xF0, 0xCA, 0x9C, 0x75, 0xC3, - 0xE4, 0xB6, 0x67, 0x20, 0x62, 0x5D, 0x61, 0x60, 0xCF, 0x10, 0x01, 0x91, 0x93, 0xA0, 0x43, 0x47, - 0x13, 0x49, 0xB5, 0x30, 0x4C, 0xDA, 0x40, 0x44, 0xBA, 0x70, 0x7F, 0xE1, 0x79, 0x64, 0x62, 0xB9, - 0xF7, 0x32, 0x69, 0x12, 0xF0, 0x36, 0x36, 0xAA, 0x28, 0x0F, 0xAA, 0x9F, 0xE3, 0x8E, 0xA4, 0xEC, - 0x25, 0x86, 0x33, 0xCE, 0x74, 0xA5, 0x2A, 0x1B, 0x97, 0x6E, 0x02, 0x96, 0x79, 0x5C, 0x9D, 0xAE, - 0x53, 0xF9, 0x2C, 0x90, 0x05, 0x34, 0xE6, 0xB6, 0x23, 0x5D, 0xA7, 0x4A, 0x33, 0xBC, 0xD0, 0x8A, - 0xC0, 0xB2, 0xCE, 0x34, 0x53, 0x55, 0x2A, 0x36, 0x42, 0x44, 0x10, 0x1C, 0x43, 0x57, 0x27, 0x31, - 0x07, 0xA6, 0x93, 0x7D, 0x63, 0xC5, 0x4E, 0xE0, 0x0F, 0xAB, 0x9F, 0xCB, 0xA7, 0x32, 0x5D, 0x98, - 0x4E, 0xD0, 0x4D, 0xE9, 0x30, 0xAA, 0x1D, 0x4D, 0x88, 0x44, 0x53, 0xA6, 0xC3, 0x89, 0x38, 0x05, - 0x55, 0x0D, 0x8C, 0x1E, 0xC6, 0xD9, 0x98, 0x51, 0xF2, 0x1C, 0x56, 0xD5, 0x02, 0x2B, 0xE8, 0x95, - 0xE7, 0x85, 0x27, 0x8E, 0x3B, 0x0B, 0x69, 0x90, 0x7F, 0x14, 0x97, 0x71, 0xE4, 0xA5, 0x61, 0xE8, - 0xF0, 0x69, 0xC7, 0xB0, 0x61, 0xAE, 0xDE, 0xDD, 0xC0, 0xA0, 0x4A, 0x11, 0x1B, 0xD1, 0x11, 0x53, - 0x92, 0x31, 0xDB, 0x82, 0x74, 0x01, 0x34, 0x86, 0x9B, 0xE0, 0x9D, 0x39, 0x06, 0x7C, 0x48, 0x31, - 0x80, 0x39, 0x28, 0x71, 0x69, 0xB6, 0x1A, 0xF3, 0xDD, 0xEA, 0xAC, 0x8B, 0x04, 0x4B, 0x19, 0x77, - 0x22, 0xEA, 0xF0, 0xFE, 0x20, 0x67, 0x11, 0x39, 0xE0, 0xF9, 0x5B, 0x60, 0x2A, 0x8E, 0xD2, 0xA6, - 0x4C, 0x70, 0x66, 0xC6, 0x64, 0x71, 0x78, 0xAD, 0x08, 0xC6, 0x46, 0x50, 0xD0, 0xD5, 0x96, 0x1B, - 0x52, 0xD7, 0xB5, 0xDE, 0x53, 0x67, 0x74, 0x13, 0x5E, 0x4E, 0x26, 0xE6, 0x71, 0xA6, 0xD5, 0x52, - 0x3B, 0x94, 0xAC, 0x63, 0x5C, 0x3A, 0x4B, 0x1A, 0x63, 0x66, 0x92, 0x39, 0x6C, 0x30, 0xB7, 0xD3, - 0x00, 0xAA, 0xF2, 0x0B, 0x35, 0x57, 0xB3, 0x30, 0x94, 0x43, 0xAB, 0xCB, 0xA5, 0x14, 0x09, 0xFD, - 0x7B, 0x73, 0x97, 0xE1, 0xD1, 0x73, 0x9E, 0xBE, 0x3C, 0x80, 0xAF, 0x13, 0x0E, 0x6F, 0x48, 0x8B, - 0xE2, 0x06, 0x81, 0x79, 0xF2, 0x93, 0xB3, 0xD0, 0x04, 0x01, 0x34, 0x8E, 0xC5, 0xC6, 0x1F, 0x1F, - 0x46, 0x19, 0x5D, 0xAA, 0x04, 0xA5, 0xE7, 0xA7, 0x5C, 0x29, 0xD9, 0x0C, 0x83, 0xEE, 0x2C, 0xB9, - 0x1D, 0x52, 0xA7, 0xED, 0x8F, 0xC7, 0xC4, 0xA7, 0xA3, 0xD9, 0x18, 0x33, 0xE3, 0x30, 0x2F, 0x96, - 0x77, 0x60, 0xEC, 0x43, 0x6A, 0x7D, 0x57, 0xA1, 0x85, 0x99, 0xB6, 0xE0, 0x11, 0x7A, 0xE9, 0xC1, - 0x94, 0x74, 0x28, 0xBA, 0xE5, 0x4C, 0x30, 0x02, 0x87, 0x26, 0x37, 0x8E, 0xD8, 0xD9, 0x3D, 0x0F, - 0x41, 0x3A, 0xB8, 0xB1, 0xDC, 0x11, 0x15, 0xEB, 0x41, 0x2D, 0xC2, 0xA0, 0xD9, 0xDC, 0x7D, 0x96, - 0x98, 0x0E, 0x18, 0xC3, 0x22, 0x6C, 0xE9, 0x24, 0x18, 0x19, 0x6A, 0x0A, 0x06, 0x0E, 0x3D, 0xF4, - 0xBD, 0x67, 0x3C, 0xA1, 0x0C, 0xA8, 0x0C, 0xDE, 0xAC, 0x00, 0x97, 0xDC, 0xC7, 0xC8, 0x2C, 0x70, - 0x87, 0xC9, 0x1D, 0xB8, 0xDD, 0xC9, 0x7C, 0x03, 0x5D, 0x70, 0xED, 0x3D, 0x8B, 0x6C, 0xAF, 0x9E, - 0x8E, 0x86, 0x6B, 0xBC, 0x2C, 0xAF, 0xCC, 0x44, 0x6F, 0x49, 0x07, 0xBF, 0xF5, 0xC0, 0x47, 0x82, - 0xBE, 0xE3, 0xD7, 0x33, 0x38, 0x23, 0x49, 0x9F, 0x8E, 0xD2, 0xB7, 0xCC, 0xDF, 0xFF, 0x0E, 0xAD, - 0xB1, 0x9D, 0x60, 0x8A, 0x7D, 0xC4, 0x32, 0x4B, 0x62, 0x60, 0x2C, 0x39, 0x98, 0x05, 0x60, 0xBF, - 0xF8, 0xDF, 0xB0, 0x8C, 0x40, 0x31, 0x35, 0x57, 0xA4, 0x5E, 0x30, 0x60, 0x1A, 0xD0, 0x61, 0x6D, - 0x54, 0x78, 0x4F, 0x06, 0x27, 0xDE, 0x81, 0xB8, 0xA1, 0x3E, 0x37, 0xA2, 0xB7, 0x38, 0x49, 0xD6, - 0xC6, 0xC2, 0xA6, 0xD8, 0x37, 0xEC, 0x46, 0x9E, 0x9C, 0x14, 0x8B, 0x87, 0x63, 0x2C, 0x16, 0xE7, - 0x3B, 0xEA, 0xD5, 0x46, 0xC9, 0x67, 0x9A, 0xD3, 0xD0, 0x77, 0xA6, 0x03, 0x0A, 0x82, 0xF3, 0x17, - 0x81, 0xE9, 0x60, 0xEC, 0xB0, 0xF8, 0xCE, 0x9A, 0x98, 0xF0, 0x96, 0x14, 0xDE, 0x44, 0xC1, 0xA1, - 0xE5, 0x62, 0xEC, 0xF8, 0x5C, 0x1C, 0x9D, 0x79, 0x8E, 0x1B, 0x9E, 0x51, 0xFF, 0x1A, 0x16, 0x01, - 0xD2, 0x72, 0x67, 0x4E, 0xAC, 0x47, 0xD1, 0xAD, 0xC5, 0x19, 0xB3, 0xE3, 0x0B, 0xC1, 0xF5, 0x5E, - 0xC4, 0x5D, 0xF3, 0xE4, 0xAC, 0xDE, 0x68, 0xC4, 0x62, 0xA4, 0xE7, 0x43, 0x1D, 0x4C, 0x4F, 0xBD, - 0xBB, 0xDA, 0x48, 0xC4, 0xEC, 0x7E, 0x76, 0x83, 0x3A, 0x47, 0xF1, 0xB8, 0x86, 0x39, 0x02, 0x73, - 0xB1, 0xB4, 0x98, 0x86, 0x09, 0x2C, 0xE7, 0xC7, 0xA7, 0x47, 0xBF, 0xCE, 0x89, 0x6A, 0xFF, 0xFC, - 0x6C, 0x31, 0x3C, 0xA1, 0xBF, 0xF6, 0x36, 0x0E, 0xDA, 0xB4, 0xD9, 0xC1, 0xE6, 0xDC, 0x08, 0x23, - 0xCF, 0xB1, 0x1E, 0x9E, 0xAC, 0x24, 0x1C, 0x95, 0x10, 0xC6, 0x18, 0xF9, 0x5C, 0x80, 0x26, 0x0C, - 0xD3, 0xAC, 0xCA, 0x4B, 0x43, 0x5E, 0x12, 0x85, 0x7B, 0xE9, 0xA5, 0xE1, 0x50, 0x98, 0x84, 0x37, - 0xE8, 0x29, 0x68, 0x25, 0xDC, 0xEC, 0xA4, 0x4A, 0x66, 0xF6, 0x34, 0xF5, 0xCD, 0xBE, 0x19, 0x4E, - 0x8F, 0xC4, 0xF5, 0xE4, 0x34, 0x75, 0x58, 0x22, 0xE1, 0x92, 0x26, 0x5D, 0x70, 0x90, 0xDA, 0xFF, - 0x71, 0x12, 0xBC, 0x0F, 0x4A, 0x92, 0x60, 0xE6, 0x7E, 0x83, 0xAF, 0x20, 0x66, 0x4C, 0xE1, 0x97, - 0x04, 0xE1, 0x3D, 0x78, 0x04, 0x28, 0xB0, 0x31, 0xCB, 0xC0, 0xDC, 0x70, 0x3D, 0x97, 0x36, 0xD4, - 0xF4, 0xC2, 0x6C, 0xD1, 0x51, 0x0C, 0x79, 0x05, 0x1E, 0xF8, 0x37, 0x0E, 0x0A, 0xFE, 0xAF, 0x4F, - 0x71, 0x12, 0x3E, 0x18, 0xFC, 0x8C, 0x77, 0x3A, 0x71, 0xA2, 0x17, 0xB7, 0x0E, 0x59, 0x4A, 0x41, - 0x09, 0xB7, 0x48, 0xB7, 0x1A, 0xA7, 0x53, 0xE6, 0x39, 0x58, 0x59, 0x55, 0x04, 0x96, 0xB6, 0x64, - 0xD7, 0xD7, 0x8F, 0x13, 0x9F, 0x2C, 0xAE, 0x3B, 0x1C, 0x07, 0x22, 0xBF, 0x31, 0xA6, 0x3C, 0x8D, - 0xB3, 0xDE, 0xFD, 0xC7, 0x0C, 0x96, 0xC8, 0x3C, 0xA1, 0xAF, 0xE7, 0x83, 0x5F, 0xD7, 0x6A, 0x74, - 0xE4, 0x63, 0xBD, 0x36, 0xE9, 0x28, 0x67, 0x18, 0x8D, 0x9C, 0x54, 0x8A, 0x12, 0x05, 0xB1, 0xC1, - 0x04, 0xDF, 0x57, 0x57, 0x65, 0xD7, 0x43, 0x62, 0x78, 0x75, 0x4F, 0x06, 0xF8, 0xF2, 0xFD, 0x6B, - 0x47, 0xE4, 0x45, 0x64, 0x21, 0xDE, 0x6A, 0x09, 0x77, 0x0A, 0x59, 0x61, 0xD4, 0x63, 0xCF, 0x52, - 0xCB, 0x87, 0xB6, 0x61, 0xF5, 0xB0, 0xBE, 0x7E, 0x4E, 0x27, 0xDE, 0x2D, 0x65, 0x51, 0x6A, 0xB8, - 0x17, 0x84, 0xC1, 0x6C, 0xEC, 0x0F, 0x5E, 0x5E, 0x55, 0x28, 0xC9, 0xFE, 0xEC, 0x4B, 0xD7, 0x0B, - 0x5B, 0x1D, 0x3D, 0x44, 0x6E, 0x25, 0x92, 0x97, 0x2F, 0xE7, 0xAB, 0x79, 0x5C, 0x61, 0x45, 0x6B, - 0x84, 0xB4, 0xB8, 0x4C, 0x7C, 0xC8, 0x51, 0xA0, 0xA5, 0xF8, 0x50, 0x82, 0x4A, 0x81, 0x08, 0x26, - 0x46, 0x6C, 0xB6, 0x9B, 0xF0, 0xAF, 0x84, 0x0A, 0xF8, 0xA8, 0x46, 0x3F, 0x8E, 0x12, 0xAD, 0xC4, - 0x43, 0x1C, 0x7C, 0x6A, 0xE2, 0x23, 0x2A, 0x2C, 0xCF, 0x4B, 0xEE, 0x66, 0x69, 0x11, 0x4B, 0x86, - 0x1D, 0x66, 0x16, 0x82, 0x65, 0x46, 0xCA, 0x99, 0xE2, 0xFC, 0xE6, 0x6C, 0x8C, 0x9A, 0x79, 0xD7, - 0xD6, 0x27, 0x2E, 0xB8, 0x81, 0x23, 0xBE, 0xC4, 0x49, 0x78, 0x4A, 0x25, 0x53, 0x47, 0x03, 0xD2, - 0x52, 0xCA, 0x9F, 0x45, 0x41, 0x96, 0x52, 0x1A, 0x67, 0x10, 0x46, 0x92, 0xE8, 0xB9, 0x15, 0x15, - 0xB6, 0x49, 0x1F, 0xD6, 0xF0, 0x2B, 0x69, 0x6B, 0xC7, 0x8E, 0xD4, 0xC1, 0xCA, 0xB5, 0x09, 0x5B, - 0x95, 0xE1, 0x99, 0x80, 0x62, 0xFD, 0xB0, 0x8D, 0xFC, 0xD8, 0x5D, 0x5B, 0xEB, 0x60, 0x58, 0x33, - 0x2B, 0x78, 0x49, 0x50, 0x04, 0x31, 0x34, 0x92, 0x88, 0x29, 0x0C, 0xC7, 0xD4, 0xF2, 0x23, 0x12, - 0xE5, 0xF0, 0x36, 0xD3, 0x3C, 0x0E, 0x66, 0xC3, 0x21, 0x2C, 0xCD, 0x18, 0x97, 0x52, 0x6E, 0xD9, - 0x18, 0x8F, 0x28, 0x37, 0x71, 0xD8, 0xE4, 0xE9, 0x65, 0xD3, 0x4C, 0x25, 0x38, 0xCB, 0xA2, 0x33, - 0x30, 0x06, 0x4B, 0xC0, 0x88, 0x29, 0x21, 0xBF, 0x68, 0x2D, 0x16, 0x67, 0xD9, 0xBF, 0x16, 0xCB, - 0x5D, 0xD3, 0x32, 0x2E, 0xBD, 0x8C, 0x8E, 0x36, 0x09, 0xF0, 0x44, 0x09, 0xE7, 0xDF, 0x8E, 0xCF, - 0x8C, 0x5F, 0x4B, 0xC4, 0x3F, 0xC4, 0x9C, 0xED, 0xE6, 0x43, 0xE1, 0xAD, 0x46, 0x25, 0x64, 0xC2, - 0xB8, 0x39, 0xCB, 0x57, 0xE3, 0x7F, 0x57, 0x96, 0xCE, 0xDA, 0x62, 0xBF, 0x32, 0x87, 0x29, 0x72, - 0x45, 0xFC, 0x19, 0x9A, 0x94, 0xCF, 0xA1, 0xE1, 0x26, 0x42, 0x66, 0x4F, 0x8B, 0x3E, 0x4A, 0x74, - 0x5C, 0xD2, 0x1E, 0xB9, 0xFF, 0x1A, 0x42, 0x91, 0x45, 0x32, 0xE2, 0xF8, 0xD2, 0x91, 0xAE, 0x34, - 0x52, 0x7F, 0x6B, 0x2E, 0x82, 0x41, 0x53, 0x58, 0xE2, 0x7E, 0xC4, 0xCB, 0x6E, 0x3C, 0xF0, 0xFD, - 0x45, 0x09, 0x1F, 0xDA, 0x78, 0xF9, 0x00, 0xFA, 0xD3, 0x9B, 0x5F, 0x25, 0x65, 0x64, 0xC5, 0x62, - 0x4E, 0x60, 0xC5, 0x8C, 0x6E, 0x17, 0x86, 0xF1, 0xD6, 0x16, 0xF0, 0x7B, 0x02, 0x4E, 0x1E, 0xA6, - 0x7C, 0xB8, 0xA2, 0xE1, 0x1D, 0x1E, 0xDA, 0x75, 0xD9, 0xC6, 0x0D, 0x94, 0x35, 0xDA, 0x68, 0xC7, - 0xC6, 0x63, 0x6B, 0x1A, 0x50, 0x4C, 0xA3, 0xC4, 0xF3, 0xB6, 0xB0, 0xAD, 0x0A, 0x55, 0x7D, 0x4D, - 0xF4, 0x71, 0x51, 0xBA, 0x4C, 0x1E, 0x10, 0x7F, 0x31, 0x1F, 0x98, 0x88, 0xA5, 0x0C, 0x17, 0xDB, - 0xD9, 0x4C, 0x6C, 0xCF, 0x23, 0x07, 0xA4, 0x5F, 0x56, 0x12, 0xF5, 0x78, 0x30, 0xCA, 0x41, 0x54, - 0x1C, 0xF0, 0x79, 0x04, 0x0C, 0xF7, 0x90, 0x5F, 0x49, 0x1E, 0xC2, 0x3A, 0x44, 0x36, 0xC9, 0xA2, - 0xC0, 0x34, 0x04, 0x51, 0xA5, 0xA3, 0x81, 0x04, 0x35, 0x39, 0xA4, 0x69, 0xA8, 0xC2, 0xF4, 0xB3, - 0xC6, 0x4A, 0xD7, 0xD0, 0x23, 0xAC, 0x08, 0x32, 0x9B, 0xE6, 0x01, 0xF0, 0xA1, 0x9D, 0x26, 0x20, - 0xB7, 0x15, 0x9C, 0x41, 0x07, 0x5D, 0xFA, 0xB7, 0x0E, 0x1D, 0xDB, 0x41, 0x2B, 0xC9, 0x15, 0x7E, - 0x20, 0x84, 0x20, 0xBC, 0xE8, 0x61, 0x92, 0x9F, 0x43, 0x17, 0x4F, 0x2C, 0x58, 0xB1, 0x19, 0x27, - 0xF2, 0x13, 0x81, 0xC4, 0xA3, 0x1D, 0x3D, 0xA4, 0x1E, 0xB9, 0x6F, 0x99, 0xD0, 0x49, 0xB7, 0x20, - 0x28, 0xDE, 0x84, 0xAE, 0x0A, 0x87, 0x2A, 0x25, 0x40, 0xE1, 0xD7, 0x72, 0xD0, 0x6F, 0x92, 0x14, - 0x4F, 0x00, 0xCA, 0x12, 0x3E, 0x55, 0xA7, 0xCA, 0x94, 0x48, 0x80, 0x97, 0xA6, 0x7C, 0x76, 0x26, - 0x09, 0x4A, 0xDE, 0x52, 0x29, 0x07, 0x2D, 0x65, 0x82, 0x62, 0x08, 0xF0, 0xCF, 0x52, 0x90, 0xBF, - 0x38, 0x6F, 0x9D, 0x04, 0xF0, 0xCE, 0xB9, 0x76, 0xCA, 0xC1, 0x5D, 0x1C, 0x9C, 0x7D, 0x3A, 0x94, - 0x78, 0x86, 0x95, 0xE6, 0x27, 0x7B, 0x5A, 0x0E, 0x96, 0xDD, 0x3A, 0x4D, 0x40, 0x99, 0x3F, 0x5F, - 0x0E, 0x32, 0xBD, 0xD4, 0xBC, 0x4F, 0xF0, 0x48, 0xBE, 0x5E, 0x39, 0x6C, 0x83, 0xFB, 0x20, 0xA4, - 0x93, 0x04, 0x41, 0xC0, 0xFF, 0x2E, 0x05, 0x7B, 0xA4, 0xA6, 0xF1, 0x02, 0xE8, 0x38, 0xB1, 0x57, - 0x29, 0xF8, 0xD3, 0x0B, 0x49, 0x78, 0x98, 0xEB, 0xAB, 0x14, 0xD4, 0x5B, 0x29, 0xA1, 0x3B, 0xC0, - 0xC9, 0x4B, 0xA4, 0x08, 0x9E, 0x3B, 0x0B, 0xFA, 0xEC, 0xC6, 0x47, 0xB1, 0x18, 0x92, 0x84, 0x53, - 0x4E, 0x19, 0x50, 0x9E, 0x23, 0x21, 0xB9, 0x71, 0x8C, 0x87, 0xBA, 0x6D, 0x7C, 0x67, 0x63, 0x73, - 0x47, 0x32, 0xA6, 0x2C, 0x1B, 0xDC, 0xE6, 0x0E, 0x40, 0x5A, 0xBE, 0x35, 0xC4, 0x93, 0x2E, 0xD9, - 0x9C, 0xAA, 0xA3, 0x7E, 0x25, 0x26, 0xCD, 0x32, 0x07, 0x66, 0xD0, 0xE5, 0x86, 0xDB, 0xB0, 0xED, - 0xDD, 0xC6, 0x17, 0x11, 0xBA, 0xDD, 0x5E, 0xBF, 0xCD, 0x9E, 0x74, 0x48, 0xDB, 0x73, 0x5E, 0xCA, - 0xAC, 0x7A, 0xAF, 0xCB, 0x00, 0x4C, 0x06, 0x24, 0x92, 0x2A, 0x92, 0x3C, 0x90, 0xD3, 0x8E, 0xB1, - 0x5D, 0x8A, 0x4C, 0x76, 0x1C, 0x17, 0x3E, 0xDC, 0x36, 0xD8, 0x74, 0xB2, 0xD3, 0xCD, 0x9C, 0x4E, - 0x76, 0xBA, 0x25, 0xC8, 0xA6, 0x50, 0x1F, 0x9C, 0x7E, 0x9C, 0x0B, 0x73, 0xEC, 0xC3, 0x66, 0xED, - 0x0D, 0xC7, 0xC7, 0x59, 0x69, 0xEF, 0xD6, 0xD4, 0xE7, 0x6E, 0x02, 0x7C, 0x60, 0x81, 0x84, 0xFC, - 0xF7, 0x5E, 0x10, 0x8A, 0xDE, 0xDF, 0x4A, 0xF5, 0xFE, 0x56, 0x46, 0xEF, 0xA7, 0x5B, 0x9F, 0x21, - 0x81, 0x14, 0x39, 0xB4, 0x60, 0x9C, 0xDC, 0x0E, 0xFE, 0xE8, 0x14, 0xD9, 0xC7, 0x6A, 0x94, 0x0C, - 0x2D, 0x63, 0xEF, 0x39, 0xB0, 0x0D, 0x6B, 0x4E, 0x6A, 0xA3, 0xAB, 0xD3, 0xD9, 0xE8, 0xD6, 0x6E, - 0x19, 0x6F, 0xC7, 0xA7, 0x80, 0xFA, 0xD9, 0xD2, 0x4C, 0x17, 0x60, 0x7D, 0x66, 0x04, 0xC3, 0x6F, - 0xFD, 0x91, 0xD7, 0x19, 0x7A, 0x13, 0xFC, 0x0B, 0xBF, 0x92, 0x09, 0x32, 0x86, 0x99, 0xEB, 0xC0, - 0xB0, 0x38, 0xE0, 0xB1, 0x4E, 0x2C, 0x67, 0x8C, 0x41, 0x60, 0x3E, 0xF8, 0x44, 0xF9, 0xAC, 0x45, - 0x87, 0x6D, 0x84, 0x1F, 0x76, 0x61, 0x48, 0xE3, 0x1D, 0xD8, 0x4A, 0x71, 0x66, 0x87, 0x61, 0x69, - 0x22, 0xD7, 0x59, 0x40, 0xC0, 0x66, 0xD1, 0x0E, 0xE1, 0xF4, 0xAC, 0x7B, 0x72, 0x67, 0x81, 0xC9, - 0x00, 0x39, 0xD8, 0x4E, 0xC0, 0xE2, 0xF0, 0x4E, 0x2F, 0xCE, 0x8F, 0xCF, 0x70, 0xDB, 0x87, 0x85, - 0xA2, 0x8D, 0x3D, 0xCE, 0x0D, 0xA1, 0xDF, 0xC1, 0xA3, 0xC0, 0x8D, 0xB4, 0x28, 0x8D, 0x57, 0x27, - 0xA2, 0x28, 0x2D, 0x53, 0xE0, 0x2F, 0xBE, 0x0F, 0x84, 0x2B, 0x4D, 0x2E, 0xA3, 0x1C, 0xC9, 0x48, - 0x02, 0x10, 0xAD, 0x28, 0x07, 0x2F, 0x14, 0xA7, 0xDF, 0xEB, 0xF6, 0x4A, 0xC2, 0x29, 0x5A, 0xD0, - 0xB8, 0x1A, 0xDB, 0xFE, 0xE5, 0x60, 0x6A, 0xF9, 0xDF, 0xDE, 0xCE, 0xDC, 0x5E, 0xA3, 0x32, 0x8E, - 0xB3, 0x5F, 0xAA, 0xF1, 0x1B, 0x75, 0x78, 0x48, 0x83, 0xF0, 0xFF, 0xE0, 0x3F, 0xD5, 0x9B, 0x8C, - 0x28, 0x80, 0x2C, 0x20, 0xD1, 0xE0, 0x46, 0xEA, 0xC8, 0xBA, 0x10, 0x19, 0xE4, 0xDE, 0xBD, 0xDB, - 0xCF, 0x08, 0xEB, 0x00, 0x38, 0x6D, 0xBB, 0x0F, 0xFD, 0x3B, 0x58, 0x70, 0xC4, 0xF9, 0x53, 0x93, - 0x8D, 0xCE, 0xF5, 0xF5, 0x09, 0x5B, 0xF4, 0x61, 0x0D, 0xC7, 0x0E, 0x48, 0x10, 0x5A, 0x3E, 0xD3, - 0x01, 0xA6, 0x54, 0xDA, 0xD5, 0xB7, 0x67, 0x3F, 0x28, 0x65, 0x1B, 0x2E, 0xED, 0x12, 0x56, 0xF2, - 0x37, 0x1E, 0x9B, 0x3C, 0x1F, 0x86, 0x63, 0xFF, 0xEB, 0x9E, 0xC6, 0xFD, 0x57, 0x79, 0xD1, 0x6B, - 0xDA, 0xCD, 0x92, 0x48, 0x64, 0x6D, 0x61, 0x99, 0x43, 0x80, 0x25, 0x40, 0xBE, 0xD3, 0xB8, 0x9B, - 0x0E, 0x74, 0xD3, 0xD7, 0x9E, 0xE6, 0x00, 0x4E, 0x39, 0xB9, 0x51, 0xF9, 0x8E, 0x61, 0xE1, 0xCA, - 0x8B, 0x95, 0x16, 0x43, 0xF9, 0xA4, 0x24, 0xC6, 0xD6, 0x88, 0x79, 0x52, 0x33, 0xE9, 0x3C, 0x2E, - 0x2E, 0x0D, 0x5A, 0x5F, 0x2D, 0x61, 0xAC, 0xC4, 0x7E, 0x69, 0x69, 0xEA, 0x57, 0xEC, 0x0A, 0x45, - 0x39, 0xA9, 0x25, 0xC7, 0x49, 0x25, 0x21, 0xB2, 0xA5, 0x7E, 0x91, 0xE2, 0xCD, 0xD9, 0xDA, 0x24, - 0xDC, 0xFE, 0x7F, 0x54, 0x93, 0xCB, 0x8D, 0x97, 0xC7, 0x6A, 0x71, 0xD5, 0xB1, 0xA2, 0x3E, 0x6B, - 0xC1, 0x73, 0x92, 0x46, 0x17, 0x0D, 0x8B, 0x47, 0x4C, 0xCE, 0xA3, 0x18, 0x73, 0x48, 0x36, 0x75, - 0x3F, 0xF4, 0x47, 0x49, 0x57, 0xF1, 0x71, 0x25, 0x58, 0x5C, 0xC7, 0x80, 0xBB, 0x89, 0x29, 0xB4, - 0xCD, 0xCB, 0x98, 0x1E, 0xDF, 0x98, 0xC2, 0xF2, 0xDC, 0xFD, 0xB1, 0x85, 0x2A, 0xA4, 0x7E, 0x4B, - 0xF6, 0x9F, 0x52, 0x6A, 0xD1, 0x8E, 0x5E, 0x86, 0x52, 0xB3, 0xDC, 0xB7, 0xD2, 0xB2, 0x34, 0x5A, - 0x51, 0x19, 0xA2, 0x9D, 0x4A, 0x2E, 0xA8, 0xC4, 0x02, 0xC7, 0xBB, 0x0A, 0x50, 0xB8, 0x2C, 0x41, - 0x36, 0x1D, 0x7A, 0xAE, 0x8D, 0x2E, 0xFB, 0x76, 0x97, 0x35, 0xC7, 0xD0, 0x98, 0xED, 0xAE, 0xC8, - 0xB1, 0x2E, 0x37, 0xE4, 0x8D, 0x31, 0xE1, 0x78, 0x3E, 0xB1, 0x33, 0x2F, 0x70, 0xF0, 0xFF, 0xFB, - 0xC3, 0xE1, 0x0C, 0x96, 0x31, 0xF7, 0x7C, 0xA1, 0xB3, 0x85, 0x82, 0x4C, 0x11, 0xED, 0x75, 0x18, - 0xD5, 0xAD, 0x4E, 0x0E, 0xD5, 0x84, 0xAC, 0xE2, 0x93, 0xB2, 0x50, 0xA9, 0x23, 0x96, 0x8A, 0xA9, - 0xAD, 0x3C, 0x98, 0x2B, 0x33, 0x6A, 0x86, 0xF8, 0x8C, 0x10, 0xD2, 0x43, 0xBA, 0xC5, 0x10, 0xBF, - 0x01, 0x84, 0xF4, 0xC0, 0x6E, 0x3E, 0xC0, 0x07, 0x2B, 0x64, 0xB9, 0xA1, 0xDB, 0xEC, 0x3D, 0xE0, - 0x9D, 0x6E, 0x7F, 0x67, 0xF3, 0xF9, 0x4E, 0x01, 0x88, 0xE7, 0x8E, 0x04, 0x0C, 0x7F, 0x2A, 0xF8, - 0xC5, 0x56, 0x77, 0xEB, 0xF9, 0x76, 0x2F, 0x1F, 0x6A, 0x7F, 0x1C, 0x3A, 0xE1, 0xCC, 0x66, 0x5B, - 0x24, 0x5B, 0xDB, 0x40, 0xEB, 0xC5, 0x8E, 0xB2, 0xFC, 0xD2, 0x0E, 0x6C, 0x54, 0x0C, 0x19, 0xEA, - 0x91, 0x49, 0x31, 0xBF, 0x87, 0xA1, 0x07, 0xE5, 0xAE, 0x8A, 0x94, 0x38, 0x3F, 0x46, 0x2E, 0x47, - 0x9F, 0x6B, 0x8A, 0xB6, 0xBE, 0x78, 0x2B, 0x89, 0xB8, 0xC0, 0x82, 0x68, 0xBA, 0xF9, 0xBC, 0xCB, - 0x7E, 0xDA, 0x24, 0xFE, 0x25, 0x1E, 0x07, 0x51, 0x19, 0x0E, 0x02, 0xF1, 0x6B, 0xF1, 0xF0, 0x2B, - 0x22, 0xFA, 0xF9, 0x47, 0x10, 0xFD, 0x6D, 0x19, 0x44, 0x1F, 0xF2, 0x02, 0x8D, 0xAB, 0x9B, 0x83, - 0x7A, 0x26, 0xA1, 0x92, 0x59, 0x48, 0xCB, 0x2B, 0x09, 0x5A, 0x02, 0x63, 0xFF, 0x33, 0xF5, 0x31, - 0xF5, 0x38, 0x7C, 0x5B, 0x67, 0x97, 0x33, 0x92, 0xEB, 0xF7, 0xA5, 0x04, 0x2D, 0x69, 0xE3, 0x5A, - 0xAF, 0xD7, 0xDD, 0xD8, 0x6C, 0x93, 0x17, 0x2F, 0x94, 0xAD, 0x51, 0xFE, 0x19, 0x85, 0x8C, 0x05, - 0x25, 0x8C, 0x6A, 0x06, 0x39, 0x3D, 0xEA, 0x1F, 0x09, 0x62, 0xFA, 0xF9, 0x2D, 0x85, 0xD6, 0x16, - 0x4B, 0xE4, 0xBE, 0x55, 0x5B, 0x7B, 0xCC, 0xD1, 0x87, 0x40, 0xAB, 0xCF, 0x67, 0xDC, 0xBE, 0x36, - 0xF1, 0xF2, 0xEF, 0x3C, 0xDB, 0x7C, 0xB7, 0x53, 0x5A, 0x81, 0x1E, 0x32, 0xF7, 0x2A, 0xE3, 0x88, - 0xD8, 0x3A, 0x7B, 0x95, 0x1C, 0x38, 0xD9, 0x43, 0xBA, 0xEC, 0x96, 0xDE, 0xAB, 0x96, 0xE1, 0x19, - 0xD3, 0xDD, 0x32, 0xBB, 0x95, 0x32, 0x41, 0xDC, 0x74, 0x8A, 0x08, 0xE6, 0xEF, 0x57, 0x96, 0xA7, - 0x95, 0xD9, 0x3A, 0xDC, 0xEE, 0x61, 0xC4, 0xBA, 0x5A, 0xEB, 0xBA, 0x73, 0xB6, 0x2E, 0x97, 0xE2, - 0xD9, 0x2F, 0x8F, 0x45, 0x33, 0xD9, 0x4B, 0x5B, 0x4A, 0x1F, 0xE6, 0x52, 0x7C, 0xBC, 0x56, 0x4A, - 0x9A, 0xDA, 0xAB, 0x4F, 0xB1, 0x57, 0x4B, 0x53, 0x05, 0x41, 0x5D, 0x53, 0xBB, 0xF9, 0x9A, 0xDA, - 0xAB, 0xA7, 0xA9, 0xCB, 0x68, 0x5D, 0x91, 0xA6, 0x3E, 0x12, 0x4D, 0x49, 0x53, 0x1F, 0x9D, 0xE2, - 0xE3, 0xB5, 0x52, 0xD2, 0xD4, 0x7E, 0x7D, 0x8A, 0xFD, 0x5A, 0x9A, 0xDA, 0xAF, 0xA5, 0xA9, 0xFD, - 0x7A, 0x9A, 0xBA, 0x8C, 0xD6, 0x15, 0x69, 0xEA, 0x23, 0xD1, 0x94, 0x34, 0xF5, 0xD1, 0x29, 0x3E, - 0x5E, 0x2B, 0x25, 0x4D, 0xDD, 0xA8, 0x4F, 0x71, 0xA3, 0x96, 0xA6, 0x6E, 0xD4, 0xD2, 0xD4, 0x8D, - 0x7A, 0x9A, 0xBA, 0x8C, 0xD6, 0x15, 0x69, 0xEA, 0x23, 0xD1, 0x94, 0x34, 0xF5, 0xD1, 0x29, 0x2E, - 0xA8, 0x95, 0x4F, 0xFD, 0xB8, 0xD5, 0xE8, 0x2A, 0x57, 0x3A, 0x70, 0x35, 0xFA, 0xBE, 0xA5, 0x8E, - 0x5C, 0x8D, 0x8E, 0x6C, 0xD5, 0xC3, 0xCF, 0x0C, 0xDF, 0xB4, 0x51, 0x16, 0x52, 0xF3, 0x30, 0xF9, - 0x99, 0xAF, 0x7D, 0xE7, 0x86, 0x77, 0x6E, 0xBF, 0x3A, 0x8E, 0x88, 0xFA, 0x2F, 0xE7, 0x5B, 0x77, - 0xE7, 0xDE, 0xE6, 0xFB, 0x6A, 0xFC, 0xC7, 0x1E, 0x60, 0xA3, 0x86, 0xD8, 0x99, 0x07, 0x50, 0x5D, - 0xE6, 0x35, 0xC8, 0x49, 0x8E, 0x55, 0x1D, 0x31, 0xD7, 0x84, 0xAB, 0x4A, 0x51, 0x73, 0x55, 0xEA, - 0x88, 0xB4, 0x5F, 0x4F, 0xA4, 0xFD, 0xDA, 0x22, 0xED, 0xD7, 0x14, 0x69, 0xBF, 0xB6, 0x48, 0xFB, - 0x35, 0x45, 0xBA, 0x51, 0x53, 0xA4, 0x1B, 0xF5, 0x44, 0xBA, 0x51, 0x5B, 0xA4, 0x1B, 0x35, 0x45, - 0xBA, 0x51, 0x5B, 0xA4, 0x3A, 0x64, 0x7C, 0xA0, 0x20, 0x5F, 0x87, 0x35, 0x1D, 0x2C, 0x14, 0x5D, - 0x9A, 0xCD, 0xD9, 0x0A, 0x89, 0xAE, 0xEF, 0xB3, 0xDB, 0xF1, 0x12, 0x82, 0x43, 0xF6, 0x92, 0x8C, - 0x08, 0xBC, 0xBB, 0xF0, 0xBE, 0x51, 0x37, 0x4A, 0x13, 0xB1, 0xFB, 0x4C, 0xCB, 0x1C, 0x32, 0xA3, - 0x71, 0xEA, 0x6A, 0x3D, 0x9B, 0xBF, 0x31, 0x10, 0x30, 0x9F, 0x4A, 0x9B, 0x6C, 0x6C, 0xF3, 0xFF, - 0xE2, 0xA9, 0x73, 0x63, 0x3B, 0x2B, 0x2E, 0xF0, 0xCC, 0x14, 0xA2, 0x94, 0xBB, 0x47, 0x5E, 0x48, - 0xBD, 0xD1, 0xD0, 0xEF, 0xD3, 0xCE, 0x42, 0xEF, 0xAF, 0xF4, 0xFE, 0x9C, 0xBA, 0xF4, 0xCE, 0x1A, - 0x67, 0xC4, 0xBC, 0xC4, 0x5D, 0x85, 0xA1, 0xAF, 0x45, 0xA1, 0x90, 0x18, 0x10, 0x7B, 0x4A, 0xC3, - 0x3B, 0xCF, 0xFF, 0x76, 0xD9, 0x1D, 0x0C, 0x8E, 0x0F, 0x4B, 0xBB, 0x0B, 0x86, 0x00, 0x5B, 0x43, - 0x40, 0xA0, 0x91, 0xCE, 0x99, 0x15, 0x04, 0xF0, 0x9B, 0xFD, 0x08, 0xB4, 0x7A, 0x8F, 0xD4, 0xA6, - 0xDE, 0x23, 0xB6, 0xA9, 0xFF, 0x48, 0x6D, 0xEA, 0x3F, 0x62, 0x9B, 0x36, 0x1E, 0xA9, 0x4D, 0x1B, - 0x0B, 0x6A, 0x93, 0x18, 0x62, 0x17, 0x07, 0x67, 0xEB, 0x9F, 0x0E, 0xCF, 0xB2, 0x0D, 0xE1, 0xC5, - 0xB0, 0x72, 0xC4, 0xAA, 0x58, 0x95, 0xC5, 0x97, 0x9E, 0x93, 0xC8, 0xD1, 0xED, 0xAD, 0xAD, 0x8D, - 0x54, 0xAC, 0x2A, 0xFB, 0x28, 0x33, 0xAA, 0x44, 0xAE, 0x17, 0xAC, 0x1A, 0x62, 0x22, 0x52, 0x34, - 0x6C, 0xF9, 0x58, 0x68, 0x13, 0xA5, 0x07, 0xB3, 0x10, 0xAA, 0x6E, 0x85, 0x27, 0x42, 0xE0, 0x90, - 0x8B, 0x10, 0x82, 0x89, 0xB5, 0x4F, 0x76, 0x5D, 0xD6, 0x66, 0xF6, 0xC2, 0x59, 0x5B, 0x5F, 0xFF, - 0xE8, 0x92, 0x28, 0xF0, 0xBE, 0x4D, 0xA0, 0x22, 0xE1, 0xBD, 0xC3, 0xE2, 0x00, 0x38, 0x35, 0xF6, - 0xE4, 0x2E, 0x2E, 0x9E, 0x00, 0x3F, 0x6F, 0x82, 0x8D, 0xAF, 0xFB, 0xE2, 0x2A, 0x2A, 0xC0, 0x78, - 0x84, 0xD0, 0x99, 0xD0, 0xE8, 0xEC, 0x7F, 0x06, 0x48, 0x3C, 0x97, 0xA0, 0xE6, 0xB6, 0xB1, 0xC6, - 0xBD, 0x78, 0xAF, 0x37, 0x7A, 0x1C, 0x7A, 0x7D, 0x9D, 0x87, 0x8C, 0x8B, 0x0C, 0x89, 0x27, 0xB3, - 0x90, 0x7E, 0x4F, 0x2B, 0x2E, 0x86, 0xFE, 0x6B, 0xDD, 0x08, 0x9F, 0x6A, 0x33, 0x97, 0x27, 0x0A, - 0xC1, 0x15, 0xBF, 0xB7, 0x90, 0x3D, 0xA8, 0x92, 0x74, 0x0B, 0xD5, 0xBA, 0x6C, 0x62, 0x7D, 0x07, - 0xD0, 0x0B, 0x27, 0x0A, 0xFB, 0xEF, 0x75, 0xB7, 0x7A, 0xFD, 0x6E, 0x2A, 0x46, 0xBA, 0xD7, 0x86, - 0xEF, 0xED, 0xBE, 0x7A, 0x84, 0xA8, 0xDC, 0xA5, 0xC8, 0xDF, 0x4F, 0xE1, 0x64, 0x3E, 0x30, 0x3F, - 0x64, 0x31, 0x84, 0x4A, 0x38, 0x13, 0x4A, 0xDB, 0xB6, 0xBB, 0xE4, 0x2F, 0xA4, 0x9F, 0x1D, 0x48, - 0xA0, 0x71, 0xA8, 0x56, 0x37, 0x9E, 0x67, 0x29, 0x49, 0x2E, 0xAA, 0x49, 0x3D, 0x01, 0x8D, 0x02, - 0x72, 0xC4, 0x68, 0x49, 0x0B, 0x64, 0x7B, 0x21, 0xA2, 0x30, 0x13, 0xEC, 0xE6, 0x36, 0xCF, 0x94, - 0x7A, 0xA3, 0x5A, 0x33, 0x2D, 0x09, 0x05, 0x1B, 0x51, 0x51, 0x9A, 0xB7, 0xE4, 0x10, 0xCD, 0x7C, - 0x8A, 0xB6, 0xB3, 0x80, 0x26, 0xE7, 0x10, 0x2F, 0x6C, 0x77, 0x2A, 0xB7, 0x5C, 0xA9, 0xE6, 0xAA, - 0xA9, 0xEC, 0xF8, 0xCC, 0xD1, 0xDF, 0xD9, 0xDC, 0xD9, 0x7E, 0x9E, 0x9A, 0x3E, 0xF8, 0xE7, 0x05, - 0xB4, 0x52, 0xA7, 0xD9, 0x65, 0xA7, 0xDE, 0xF8, 0xF6, 0x88, 0xD8, 0x5F, 0x8A, 0x1A, 0x2A, 0xEC, - 0x48, 0x64, 0x4A, 0xE3, 0x86, 0x67, 0xC6, 0x6A, 0x9B, 0x9B, 0x7A, 0x7C, 0xB6, 0xCF, 0x6F, 0x23, - 0xB4, 0xE2, 0xCB, 0x4F, 0xC7, 0x67, 0x0D, 0xA9, 0x7D, 0xAE, 0xEB, 0x76, 0xA4, 0xFF, 0xE4, 0x26, - 0x6A, 0xF7, 0xA7, 0x32, 0x2C, 0x86, 0x81, 0xC2, 0xE1, 0xE9, 0x60, 0xD9, 0x24, 0xDE, 0x81, 0x7E, - 0xDF, 0x59, 0xF7, 0xCB, 0x26, 0x33, 0x98, 0x5D, 0xC1, 0xBF, 0x0B, 0xA5, 0x22, 0x94, 0x2F, 0xA2, - 0x70, 0x1A, 0x4E, 0xC5, 0xEC, 0xDB, 0x4D, 0xCF, 0xBE, 0x5D, 0xE3, 0xEC, 0x6B, 0xA6, 0x13, 0xAF, - 0x99, 0x4E, 0x2F, 0xCE, 0xEA, 0x6A, 0x4B, 0xBC, 0x9B, 0x0E, 0x3C, 0x8D, 0xC7, 0x47, 0xDF, 0xA7, - 0x9E, 0xCB, 0xA7, 0xCF, 0x0D, 0x18, 0x1D, 0xF2, 0xA8, 0xD8, 0x60, 0xB6, 0x5F, 0x19, 0x10, 0xC9, - 0x6D, 0xB9, 0xA2, 0xAD, 0xFA, 0x29, 0x70, 0x33, 0x74, 0x58, 0x8E, 0xD7, 0x36, 0x59, 0xC3, 0x0B, - 0x3E, 0x4A, 0x08, 0xC3, 0x06, 0x6B, 0x75, 0xB7, 0x26, 0xEE, 0x73, 0x18, 0x5E, 0x87, 0x74, 0xCC, - 0x54, 0xA3, 0xDB, 0x66, 0xC9, 0x17, 0xB5, 0x40, 0x1B, 0x86, 0xBE, 0xD7, 0x6D, 0xE3, 0x57, 0x2D, - 0xC8, 0xA6, 0x2A, 0x1D, 0x27, 0x98, 0x8A, 0x64, 0xB5, 0xCB, 0x20, 0x96, 0xEC, 0x8B, 0x4F, 0xCF, - 0xE9, 0x35, 0xF5, 0xA9, 0x3B, 0xA4, 0xC7, 0xB6, 0x30, 0x54, 0x29, 0x13, 0xC5, 0x1C, 0xDC, 0x20, - 0x97, 0x80, 0xB4, 0x03, 0xE2, 0xE7, 0xEC, 0x7C, 0xE8, 0x89, 0xBD, 0xAA, 0x59, 0x55, 0x2A, 0x43, - 0xE3, 0x64, 0xFE, 0x86, 0x87, 0x32, 0x72, 0x6C, 0xD1, 0xB4, 0xA9, 0xCB, 0x49, 0xCC, 0x9D, 0x26, - 0x39, 0xC9, 0x17, 0x67, 0x0B, 0xC6, 0x94, 0x4C, 0x5A, 0x76, 0x5E, 0xE6, 0x26, 0x98, 0x44, 0x58, - 0x4B, 0xA9, 0x94, 0x93, 0x3C, 0x25, 0x59, 0x97, 0x08, 0x53, 0xA9, 0x4D, 0x82, 0x0F, 0xCE, 0x35, - 0x15, 0x2E, 0x24, 0x46, 0x0B, 0xF5, 0x65, 0x96, 0x78, 0xB0, 0x50, 0x5F, 0xE1, 0x25, 0xFB, 0x36, - 0xED, 0x4A, 0x9C, 0x27, 0x21, 0xE3, 0x79, 0x59, 0x2D, 0x63, 0x02, 0xE6, 0xB2, 0x12, 0x55, 0xA4, - 0x24, 0x4A, 0xEA, 0x5D, 0x72, 0xE9, 0xCE, 0xA2, 0x7C, 0x3D, 0x75, 0x8F, 0x28, 0xCF, 0x9D, 0x27, - 0x99, 0x4F, 0x9A, 0x98, 0x9E, 0xFC, 0x4D, 0xE8, 0x36, 0x81, 0xE3, 0x33, 0x98, 0xE7, 0x60, 0xE2, - 0x63, 0xD3, 0x1D, 0xCB, 0x05, 0x21, 0x61, 0x58, 0x85, 0x0F, 0xEC, 0xCF, 0x86, 0xEE, 0xCF, 0x45, - 0x99, 0x44, 0x62, 0x4C, 0x52, 0x85, 0xA5, 0x3E, 0x87, 0xFB, 0xA0, 0x06, 0xC2, 0x4B, 0xCC, 0xBE, - 0x5E, 0x58, 0x6B, 0x83, 0x27, 0xD9, 0xDC, 0xBF, 0x2B, 0xFB, 0x71, 0x65, 0x72, 0x78, 0x7E, 0xF0, - 0x2C, 0xCC, 0xB1, 0xD3, 0x21, 0xA2, 0xD5, 0x77, 0x96, 0x13, 0xC2, 0x02, 0xAC, 0x29, 0x87, 0x1E, - 0x9B, 0x75, 0xD0, 0x1C, 0xEB, 0x1E, 0x05, 0xBA, 0xA7, 0x1B, 0xFA, 0x32, 0x62, 0x3E, 0xDE, 0x1D, - 0x7D, 0x26, 0x3F, 0x87, 0xC8, 0x33, 0x80, 0xE9, 0x4B, 0x02, 0xB5, 0x73, 0xA4, 0x62, 0x39, 0xFD, - 0x8D, 0xDC, 0x79, 0x03, 0xEB, 0x16, 0x9B, 0xD3, 0xE9, 0x28, 0x81, 0x7E, 0x5A, 0xAE, 0xA0, 0x46, - 0x92, 0xAC, 0xB4, 0x9D, 0x27, 0xF8, 0xB6, 0x82, 0x64, 0x44, 0xB3, 0xB2, 0x2B, 0xA4, 0xF2, 0x3C, - 0xC8, 0x09, 0x27, 0xE6, 0xC9, 0xB3, 0x30, 0x7F, 0xAE, 0x85, 0x79, 0xF2, 0x2D, 0x2C, 0x26, 0xE7, - 0xC2, 0xFC, 0x79, 0x17, 0xE6, 0xCB, 0xBD, 0x30, 0x4F, 0xFE, 0x85, 0x79, 0x73, 0x30, 0x2C, 0x3E, - 0x9B, 0xC2, 0xBC, 0x19, 0x15, 0x16, 0x91, 0x55, 0xA1, 0x7E, 0x66, 0x85, 0x79, 0xB3, 0x2B, 0x14, - 0xE2, 0x38, 0x76, 0x03, 0xB0, 0x8C, 0xEC, 0x3E, 0x78, 0xCC, 0x84, 0x93, 0x7C, 0x93, 0xF1, 0xA8, - 0xA9, 0x11, 0xD1, 0x84, 0x70, 0x90, 0x7F, 0x80, 0x19, 0xF4, 0x69, 0x4D, 0x70, 0xC6, 0xF9, 0x67, - 0x59, 0x26, 0x5D, 0x78, 0x6C, 0xA9, 0x4C, 0x45, 0x7A, 0x62, 0x09, 0x29, 0xCD, 0x58, 0x8B, 0x1B, - 0x6E, 0xA9, 0xFC, 0xF2, 0xDD, 0xD9, 0x40, 0x75, 0x7E, 0x79, 0x6E, 0xB2, 0x98, 0x95, 0x9F, 0x7E, - 0x22, 0x26, 0x28, 0x50, 0x88, 0x31, 0xCB, 0x46, 0x5C, 0x15, 0xF2, 0x0D, 0x75, 0x0E, 0xBD, 0x59, - 0x1D, 0x92, 0x1F, 0x3E, 0x9E, 0xEE, 0x0F, 0x8C, 0xCC, 0xAE, 0x68, 0xB3, 0xBD, 0x29, 0x1F, 0x41, - 0xD1, 0xBC, 0x24, 0xE9, 0x07, 0x9B, 0x7B, 0x14, 0x21, 0xCA, 0xAA, 0x72, 0xE3, 0x61, 0x30, 0x0C, - 0x2C, 0x19, 0x89, 0xC2, 0x9F, 0xAC, 0x23, 0x89, 0x12, 0xAD, 0xAE, 0xEA, 0x8A, 0x61, 0x52, 0x81, - 0x46, 0x9A, 0xA2, 0x31, 0x07, 0xD5, 0x1B, 0x27, 0x3C, 0xB1, 0xA6, 0x49, 0x76, 0xA9, 0x89, 0xE3, - 0xC2, 0x3F, 0xD6, 0xF7, 0x36, 0xB9, 0x62, 0x25, 0x52, 0x82, 0xBE, 0x76, 0x6C, 0x18, 0x8E, 0x0F, - 0xA5, 0x51, 0x1C, 0x1D, 0xDB, 0xC6, 0x49, 0xD8, 0x39, 0x7B, 0x13, 0x2B, 0xF8, 0xC6, 0x0B, 0x38, - 0x22, 0xA5, 0x90, 0x29, 0x0E, 0x87, 0x7D, 0x85, 0x24, 0xF9, 0x75, 0x78, 0xFE, 0xE1, 0x35, 0x92, - 0xE7, 0x1F, 0x5A, 0x0C, 0x09, 0x74, 0x5D, 0x8F, 0xBC, 0x7A, 0xC5, 0x69, 0x41, 0xC7, 0x40, 0x1F, - 0x75, 0xF5, 0xFE, 0xC9, 0xC9, 0xEC, 0x67, 0xCE, 0x16, 0x28, 0xC1, 0x4A, 0xAD, 0x2A, 0xEA, 0xD1, - 0xBC, 0x5E, 0x48, 0xED, 0x5C, 0x45, 0xF9, 0x07, 0x25, 0x83, 0x18, 0x5D, 0x34, 0x85, 0xF6, 0x1B, - 0x2E, 0x6A, 0x04, 0x04, 0x2C, 0x28, 0xB1, 0x61, 0x89, 0x3F, 0x85, 0x79, 0x81, 0xED, 0x69, 0xA9, - 0x9D, 0x15, 0x5F, 0xF8, 0x90, 0x52, 0xB9, 0x3A, 0x78, 0x00, 0xAC, 0x5E, 0x61, 0xDA, 0x4D, 0x72, - 0xB7, 0xC6, 0x4D, 0x23, 0x7B, 0xC6, 0x0B, 0x0D, 0x49, 0x8E, 0x79, 0x9B, 0x86, 0x60, 0xEE, 0xA9, - 0xFD, 0xD6, 0xF3, 0x27, 0x02, 0x4F, 0x92, 0x54, 0x3F, 0x4E, 0x11, 0x7B, 0x1B, 0x25, 0xEE, 0xC7, - 0xBB, 0x56, 0xFC, 0x5D, 0x11, 0xC7, 0x06, 0xDB, 0xEF, 0x5C, 0xDF, 0xC7, 0xAF, 0x97, 0xB4, 0x64, - 0x65, 0x58, 0x89, 0xFB, 0x5B, 0x05, 0xDB, 0x23, 0xEA, 0xBD, 0xAD, 0xA0, 0x73, 0xF0, 0xF1, 0xE3, - 0xF9, 0xE1, 0xF1, 0xE9, 0xFE, 0xC5, 0xD1, 0xE5, 0xF1, 0xE9, 0xD9, 0xA7, 0x8B, 0xCB, 0x8B, 0xCF, - 0x67, 0xF8, 0xEB, 0xCF, 0xFB, 0x1F, 0x8E, 0x0F, 0x2F, 0x3F, 0x9D, 0xFE, 0xF5, 0xF4, 0xE3, 0x2F, - 0xA7, 0xFA, 0xA5, 0xDA, 0xB8, 0x47, 0x91, 0xC9, 0x04, 0x23, 0xDE, 0xF0, 0x84, 0x56, 0x90, 0x99, - 0xFB, 0xCD, 0xC5, 0xE4, 0xB3, 0xBB, 0x4F, 0x4D, 0x57, 0xD8, 0x00, 0x18, 0xF2, 0x77, 0x36, 0xA8, - 0x2D, 0x31, 0xFE, 0x8A, 0xAC, 0xF5, 0x5E, 0x74, 0xB9, 0xFA, 0x9B, 0xCA, 0x61, 0x0A, 0x7A, 0xD1, - 0x5D, 0xC9, 0x15, 0x43, 0x72, 0x89, 0xE6, 0x05, 0xDF, 0x44, 0x79, 0xD1, 0x7D, 0x72, 0x02, 0xC8, - 0x1C, 0x2A, 0x5C, 0x5D, 0x24, 0x9D, 0x8E, 0xEE, 0xD7, 0xED, 0x1A, 0xF4, 0x8F, 0x3F, 0x42, 0x53, - 0x5D, 0x01, 0x19, 0xDC, 0x1F, 0x1A, 0xF8, 0x87, 0x06, 0x66, 0x6B, 0x60, 0x4A, 0x5F, 0xFE, 0xB4, - 0xA7, 0x18, 0xBE, 0xDC, 0xF6, 0x73, 0x1B, 0x1A, 0xF0, 0x24, 0x47, 0x2C, 0x7F, 0xC9, 0x13, 0x69, - 0x7E, 0xAE, 0xB1, 0x97, 0xF9, 0x98, 0xFA, 0xB0, 0x5A, 0xC4, 0x19, 0x28, 0x19, 0x54, 0xF5, 0x46, - 0x4B, 0xA6, 0xD8, 0xEB, 0xB2, 0xA1, 0x74, 0x82, 0xC8, 0x85, 0x8E, 0x13, 0x9A, 0x8D, 0xA7, 0xDD, - 0x78, 0xD8, 0x6C, 0x78, 0x4F, 0xAB, 0x1D, 0x8D, 0x46, 0x2C, 0x07, 0x6F, 0x68, 0x7D, 0x8C, 0x3D, - 0x1A, 0x62, 0x6F, 0xF1, 0x64, 0x28, 0xF1, 0x34, 0xAB, 0x65, 0x83, 0x4F, 0xF2, 0x5F, 0xAA, 0x33, - 0x6C, 0x32, 0x33, 0x8A, 0x11, 0xC2, 0x48, 0xB5, 0xA2, 0x3A, 0x6D, 0x13, 0x13, 0x49, 0xF6, 0x4A, - 0xCD, 0xB2, 0xE5, 0x22, 0x83, 0x4A, 0x79, 0xD8, 0xD2, 0xF7, 0x40, 0xF9, 0x09, 0x66, 0x20, 0x22, - 0xB3, 0xB9, 0x7C, 0x45, 0xF3, 0xD3, 0xDE, 0x5F, 0x2A, 0xB9, 0x68, 0xE2, 0xFE, 0xD5, 0x74, 0xFB, - 0x4A, 0x7A, 0x76, 0x02, 0x01, 0x7A, 0x16, 0x3F, 0xC8, 0x95, 0xE3, 0x8F, 0x1C, 0x26, 0xEE, 0xD1, - 0x5E, 0x66, 0x66, 0x0A, 0xC3, 0xCB, 0x55, 0x75, 0x56, 0x03, 0x0F, 0x95, 0x49, 0xF3, 0xF4, 0x0E, - 0x39, 0xE4, 0xE5, 0x9B, 0xA9, 0xE5, 0xC9, 0xD7, 0xB2, 0x8A, 0x59, 0xAA, 0x23, 0x8E, 0x5A, 0x16, - 0xAC, 0x3B, 0xC9, 0x3B, 0x93, 0xAA, 0x0A, 0x25, 0x01, 0x9E, 0xA8, 0x49, 0x8B, 0x52, 0x1C, 0x43, - 0x7F, 0x98, 0x6E, 0x43, 0x2E, 0xA8, 0x23, 0x94, 0x5C, 0x66, 0x32, 0x89, 0x39, 0x40, 0xBB, 0x95, - 0xFA, 0x3F, 0x9A, 0xFE, 0x8B, 0xDA, 0xDC, 0x7B, 0xD2, 0x6D, 0xEE, 0x2D, 0xA5, 0xCD, 0xFD, 0x27, - 0xDD, 0xE6, 0xFE, 0x52, 0xDA, 0xBC, 0xF1, 0xA4, 0xDB, 0xBC, 0x51, 0xB5, 0xCD, 0x3A, 0xCA, 0x65, - 0x3B, 0x8C, 0x59, 0xA6, 0x31, 0x89, 0x8A, 0x50, 0xDE, 0x39, 0xA8, 0x66, 0x13, 0xD1, 0xB7, 0xB4, - 0xF9, 0xBB, 0xBF, 0xDC, 0x02, 0x8A, 0xE7, 0x7E, 0x3B, 0x11, 0xDB, 0xCC, 0x68, 0x62, 0x8D, 0xC8, - 0x36, 0x82, 0xA3, 0xBA, 0x99, 0x6C, 0x7C, 0xB1, 0x6D, 0x14, 0x2C, 0xFE, 0xD2, 0xFD, 0x2A, 0xE6, - 0x5B, 0xF6, 0xCD, 0x09, 0x4E, 0xAD, 0xD3, 0x16, 0x3F, 0x8C, 0x89, 0xCA, 0x57, 0x56, 0x78, 0x59, - 0x54, 0xFD, 0x15, 0xE9, 0xAA, 0x1F, 0x5E, 0x63, 0x9E, 0xF5, 0x15, 0x13, 0xF2, 0x5E, 0x01, 0xF2, - 0x9E, 0x8A, 0xBC, 0xA7, 0x23, 0xEF, 0xE5, 0x21, 0xEF, 0x17, 0x20, 0xEF, 0xAB, 0xC8, 0xFB, 0x3A, - 0xF2, 0x7E, 0x1E, 0xF2, 0x8D, 0x02, 0xE4, 0x1B, 0x2A, 0xF2, 0x0D, 0x1D, 0xF9, 0x46, 0x8C, 0xFC, - 0xE9, 0x6D, 0x49, 0x55, 0x56, 0x59, 0x29, 0xCD, 0xEB, 0x8D, 0x17, 0x80, 0xAA, 0xCE, 0xE0, 0x57, - 0xF8, 0xD7, 0x1F, 0x17, 0x28, 0xB0, 0x88, 0x83, 0x40, 0x20, 0xA1, 0xBE, 0x9D, 0xD0, 0xFB, 0xE0, - 0xDD, 0xB1, 0xBB, 0x2C, 0xB4, 0xB5, 0x92, 0xBC, 0x0D, 0x0A, 0xB8, 0x56, 0x32, 0x2E, 0x7E, 0x20, - 0x31, 0xE3, 0xE5, 0x0E, 0xDD, 0x29, 0xE8, 0x19, 0x5D, 0x82, 0xCD, 0x1D, 0xD3, 0x2B, 0xA3, 0x88, - 0xB4, 0x66, 0x47, 0x54, 0xEF, 0x8C, 0xEC, 0x55, 0x57, 0x8E, 0x89, 0x92, 0x3A, 0x87, 0x49, 0xA0, - 0x4C, 0x2F, 0x8A, 0x8A, 0xE9, 0x8D, 0x7A, 0x25, 0x9C, 0xD7, 0xB1, 0x7B, 0x6D, 0xE2, 0xD8, 0xFD, - 0x12, 0x9D, 0xC7, 0xF7, 0x4C, 0x7A, 0x86, 0x98, 0x15, 0xB1, 0x75, 0x0E, 0x68, 0xD2, 0x85, 0x29, - 0x95, 0xEF, 0xD5, 0xD7, 0x79, 0x20, 0xF0, 0x64, 0xF7, 0x70, 0x7B, 0xE6, 0x73, 0x16, 0x94, 0x89, - 0xE9, 0xB8, 0x4B, 0x89, 0x5C, 0x44, 0xE3, 0xCF, 0x77, 0xA2, 0xD4, 0xB7, 0x3B, 0xA4, 0x07, 0x4B, - 0x23, 0x7D, 0xCF, 0x1B, 0xA6, 0xEC, 0x0D, 0xD0, 0x0B, 0xEF, 0xAD, 0x85, 0x71, 0x00, 0xF7, 0x87, - 0xE2, 0xCE, 0xAD, 0xBA, 0x44, 0x55, 0xCB, 0xD2, 0x2F, 0x85, 0x36, 0xA2, 0x22, 0xB2, 0x3F, 0x85, - 0x69, 0x84, 0xDA, 0x4A, 0x60, 0x02, 0x4B, 0x8B, 0x67, 0xB3, 0xBB, 0x48, 0x9C, 0x1A, 0x1E, 0x0A, - 0x19, 0x5F, 0x03, 0xD2, 0x28, 0xB1, 0x20, 0xD2, 0x76, 0xAF, 0xDD, 0x30, 0xB3, 0x6C, 0x38, 0x89, - 0x4D, 0xB1, 0x5F, 0xEA, 0x55, 0x25, 0xE9, 0xDD, 0xF7, 0x8C, 0x24, 0x7D, 0x05, 0x2F, 0x22, 0xED, - 0x91, 0xEF, 0x4A, 0x54, 0x52, 0xC1, 0x13, 0x6F, 0x72, 0x5B, 0x7E, 0xA7, 0xBE, 0x17, 0xA5, 0x6A, - 0x95, 0x9E, 0x8E, 0x90, 0x92, 0xD3, 0xB2, 0x6D, 0xFC, 0xC2, 0xDC, 0xC1, 0xA4, 0x85, 0x21, 0xF2, - 0x86, 0x24, 0xB3, 0x2B, 0xCF, 0x96, 0x90, 0xE2, 0xB7, 0x66, 0xB2, 0xDA, 0x4A, 0x89, 0x6A, 0x47, - 0x6A, 0x8A, 0x4D, 0xFD, 0x5D, 0xEB, 0x07, 0x45, 0x52, 0x7A, 0x3E, 0xD8, 0x67, 0x0B, 0x4F, 0x2C, - 0x5B, 0x27, 0xB7, 0x63, 0xF9, 0xBC, 0x8E, 0x99, 0x8D, 0xED, 0x74, 0x8B, 0xDA, 0x9B, 0x64, 0x84, - 0xE5, 0xE7, 0x63, 0x0B, 0xCD, 0x2D, 0xFB, 0xB4, 0x5A, 0xCD, 0xDF, 0x51, 0xC1, 0x66, 0x18, 0x06, - 0x84, 0xC0, 0x34, 0x08, 0x7D, 0x6A, 0x4D, 0x12, 0x25, 0x28, 0x27, 0x0F, 0x8E, 0x55, 0x16, 0x88, - 0x84, 0xE7, 0x47, 0x4B, 0x23, 0x47, 0x01, 0x52, 0x59, 0x5C, 0xE7, 0x52, 0x82, 0x34, 0xB6, 0x1F, - 0xDC, 0xF4, 0x5E, 0x27, 0xAF, 0xF1, 0x47, 0xFC, 0x36, 0xD0, 0x62, 0xDA, 0x9E, 0x42, 0xF6, 0x83, - 0x9A, 0x6E, 0x7C, 0x51, 0xFD, 0x21, 0x35, 0x67, 0xA0, 0x6D, 0xCF, 0x9F, 0x37, 0xCA, 0x24, 0x35, - 0x37, 0xCD, 0x1A, 0x8B, 0x9C, 0x31, 0xD4, 0xB4, 0xCD, 0x4F, 0x79, 0xD6, 0x88, 0x93, 0x4C, 0x2F, - 0x62, 0xE6, 0x48, 0x67, 0xAC, 0x7E, 0x92, 0xB3, 0x87, 0x9E, 0xCB, 0x78, 0x61, 0xB6, 0xE3, 0x29, - 0xB4, 0xBD, 0xB4, 0xE9, 0x98, 0xBB, 0xE5, 0x3A, 0xAE, 0xA7, 0x6B, 0x38, 0x84, 0xE3, 0xCC, 0xF3, - 0x33, 0x83, 0x5D, 0x48, 0xB9, 0xCB, 0xAA, 0x37, 0xBA, 0xFB, 0xA3, 0x1E, 0xA4, 0x60, 0xAF, 0x44, - 0xAB, 0x46, 0x89, 0x4D, 0xC4, 0xFC, 0x4D, 0x8E, 0xB8, 0x87, 0x77, 0x8B, 0x01, 0x06, 0x95, 0x01, - 0x2E, 0xAA, 0x02, 0xFC, 0x2C, 0x01, 0x6C, 0x16, 0x03, 0x9C, 0x9F, 0x1C, 0xA4, 0x29, 0x3C, 0xD4, - 0x78, 0x36, 0x61, 0xC4, 0x5E, 0x7F, 0x52, 0xBD, 0xD5, 0x77, 0x67, 0xAA, 0x88, 0xBA, 0x9D, 0xAD, - 0xDD, 0x22, 0x80, 0x41, 0x65, 0x80, 0x8B, 0xAA, 0x00, 0xB2, 0x88, 0xE2, 0x71, 0x99, 0x0D, 0xA0, - 0x8A, 0x28, 0xA6, 0xF0, 0x30, 0x4F, 0xA6, 0x7C, 0xA4, 0x14, 0x30, 0x97, 0x2E, 0x32, 0x54, 0x8C, - 0x58, 0x57, 0x22, 0xB4, 0x8D, 0xC7, 0x9C, 0x93, 0x80, 0x0E, 0xB7, 0xBA, 0xDD, 0x22, 0xB8, 0x9E, - 0x04, 0xF7, 0x1C, 0xE1, 0x00, 0xAC, 0x67, 0x6A, 0x96, 0xE4, 0x46, 0xE6, 0x6A, 0xAF, 0xA1, 0xFA, - 0xA0, 0x62, 0xF5, 0x8B, 0x6A, 0xD5, 0xE5, 0x4E, 0xE9, 0x17, 0x55, 0x4F, 0x69, 0xAD, 0xA9, 0x7E, - 0xDA, 0x7D, 0xC4, 0xDF, 0x7A, 0xDD, 0x8D, 0x0D, 0x19, 0xB6, 0x9B, 0x18, 0xE6, 0x87, 0x94, 0x69, - 0x12, 0x77, 0x6C, 0xFF, 0x30, 0x4C, 0x4F, 0xC0, 0x30, 0xE5, 0x41, 0x9C, 0xFF, 0x7A, 0x72, 0x79, - 0xBE, 0xFF, 0xCB, 0xAF, 0xA5, 0x79, 0x42, 0x80, 0xC1, 0xDB, 0xF3, 0x37, 0xBF, 0xFE, 0x61, 0xFC, - 0x2A, 0x1B, 0xBF, 0x2C, 0x08, 0x7D, 0x9C, 0xF5, 0x76, 0x4A, 0x92, 0xD2, 0x01, 0xFB, 0xDD, 0x9A, - 0x80, 0x9B, 0xFD, 0xBA, 0x80, 0xDB, 0x8D, 0x4C, 0x57, 0xED, 0x0F, 0x0B, 0xFF, 0xCF, 0x60, 0xE1, - 0x4D, 0xE0, 0xA9, 0x35, 0xB6, 0xA4, 0xB7, 0xA6, 0xAC, 0x53, 0xE5, 0xC0, 0x99, 0xF6, 0xD6, 0x07, - 0x67, 0x3A, 0x3C, 0x07, 0xF8, 0x76, 0x66, 0xCA, 0x2C, 0x83, 0xEB, 0x8D, 0x30, 0xC6, 0xC9, 0x4D, - 0x5D, 0xCF, 0x3F, 0xA1, 0x09, 0x8E, 0x2D, 0x69, 0x90, 0xED, 0xCB, 0x5E, 0xB7, 0xBB, 0x55, 0xD6, - 0xDE, 0xCB, 0x50, 0xCF, 0x37, 0x6B, 0x41, 0x3D, 0x6F, 0xA4, 0x56, 0xEF, 0xC5, 0x50, 0x2F, 0x6A, - 0xD1, 0x7A, 0xA1, 0xD1, 0x2A, 0x09, 0xB6, 0x53, 0x8B, 0xD8, 0x4E, 0x9D, 0x86, 0xF5, 0xFA, 0x75, - 0x68, 0xF5, 0xFA, 0x75, 0x68, 0xF5, 0x37, 0x94, 0xE9, 0xA0, 0xAC, 0x3C, 0x36, 0xBB, 0xCF, 0xFB, - 0x8A, 0xB5, 0x2D, 0x49, 0x8F, 0xC1, 0xF5, 0x1A, 0x19, 0x5B, 0x35, 0x73, 0xB9, 0x05, 0xF1, 0x92, - 0x9C, 0x0F, 0x55, 0x55, 0x7D, 0x0B, 0x66, 0x2B, 0x09, 0x2E, 0xC3, 0x7F, 0x2D, 0x06, 0x54, 0x35, - 0xBF, 0x3C, 0xDC, 0x8B, 0x9A, 0x70, 0x3B, 0xF5, 0xE0, 0x34, 0xE5, 0x5A, 0xD8, 0x6C, 0x9C, 0xB5, - 0x33, 0x54, 0x77, 0xCE, 0xD0, 0xBB, 0xB2, 0x9A, 0xD1, 0xD6, 0x49, 0xD7, 0x80, 0x3E, 0x19, 0x9C, - 0x6C, 0x56, 0xB5, 0xF6, 0x1F, 0xBC, 0x3B, 0x34, 0xB3, 0x77, 0x8E, 0x1D, 0xDE, 0xFC, 0xA3, 0x5B, - 0xFC, 0x6E, 0x2D, 0x93, 0xDF, 0x7F, 0x44, 0x93, 0xDF, 0x7F, 0x4C, 0x93, 0xDF, 0x7F, 0x44, 0x93, - 0xDF, 0xFF, 0xC3, 0xE4, 0xCF, 0x6D, 0xF2, 0xFB, 0x8F, 0x6D, 0xF2, 0xFB, 0x35, 0x4D, 0x7E, 0xBF, - 0xA6, 0xC9, 0xEF, 0xD7, 0x34, 0xF9, 0xFD, 0x47, 0x32, 0xF9, 0xDD, 0xAD, 0xFF, 0xDC, 0x2E, 0x23, - 0xD7, 0xF2, 0x33, 0x46, 0x19, 0x60, 0x61, 0xB5, 0x95, 0xC6, 0xFE, 0xD3, 0xCC, 0x34, 0xB3, 0x80, - 0x3D, 0x4D, 0x97, 0x5C, 0xA2, 0x09, 0xD2, 0xB7, 0x4B, 0xF8, 0x1B, 0x63, 0x89, 0x04, 0x28, 0xFE, - 0xBD, 0x9B, 0xAE, 0xF3, 0x59, 0xAB, 0xF3, 0xD9, 0x50, 0xE7, 0x37, 0xAD, 0xCE, 0x6F, 0xBB, 0xF2, - 0x2E, 0x1E, 0x70, 0xF3, 0x8E, 0x7A, 0x36, 0x0D, 0x9D, 0x61, 0x2E, 0x47, 0xE9, 0xFB, 0x2E, 0x23, - 0x01, 0x06, 0x25, 0xC5, 0xF7, 0x59, 0xE2, 0xCA, 0x9E, 0xAB, 0x55, 0x7E, 0xBF, 0x7F, 0xB4, 0x7F, - 0x76, 0x60, 0xA8, 0xBA, 0x3F, 0x0E, 0x45, 0xAF, 0xAB, 0x59, 0x5D, 0x26, 0x96, 0xFF, 0x4D, 0x49, - 0xE9, 0xD2, 0x2B, 0xC8, 0xDB, 0x52, 0x00, 0xDE, 0x37, 0x81, 0xF3, 0xAB, 0xDF, 0x82, 0xBE, 0x65, - 0xFF, 0xFB, 0x2C, 0x08, 0x81, 0x51, 0x3D, 0x14, 0x88, 0x9D, 0xD6, 0x9E, 0xD2, 0xBB, 0x0F, 0x5E, - 0x72, 0x43, 0x28, 0x95, 0x02, 0x25, 0xA9, 0x63, 0x08, 0x8C, 0xA2, 0xDF, 0x9D, 0x50, 0x4B, 0x87, - 0x70, 0xE3, 0xD8, 0x2C, 0x7B, 0xA4, 0xE3, 0x9E, 0xB1, 0x3C, 0x32, 0xBC, 0x11, 0x18, 0xBB, 0x86, - 0xA9, 0xEF, 0xC0, 0x4B, 0x39, 0x76, 0xCF, 0x7C, 0x0F, 0x6F, 0xEF, 0xC7, 0x59, 0x53, 0x74, 0x9A, - 0x88, 0x75, 0xDF, 0xB5, 0xE5, 0x68, 0x2C, 0xAC, 0xC6, 0x7D, 0x1C, 0x67, 0x42, 0xBD, 0x19, 0x5E, - 0x4E, 0x4B, 0xFE, 0x68, 0x25, 0x6C, 0xB0, 0xF7, 0xD0, 0xBA, 0xA6, 0xF0, 0xAD, 0x03, 0x6F, 0x32, - 0x1D, 0xD3, 0x30, 0xC9, 0x7C, 0xC4, 0x62, 0xD4, 0x22, 0x0C, 0x32, 0x6E, 0x41, 0xCE, 0xDC, 0x10, - 0xFE, 0x35, 0xDD, 0x10, 0xAD, 0x91, 0x11, 0xB5, 0x46, 0x74, 0xB3, 0xEB, 0xC0, 0x1A, 0x63, 0x1E, - 0xD1, 0xBB, 0x1B, 0xCA, 0x2F, 0x77, 0x1D, 0x0D, 0xCE, 0x36, 0xFA, 0xE4, 0xC6, 0x0A, 0xF0, 0xAE, - 0xD4, 0xB5, 0xE3, 0x4F, 0xA0, 0xD0, 0x07, 0xFD, 0x76, 0xA6, 0x21, 0xF1, 0xAE, 0x79, 0xA4, 0x34, - 0x2E, 0xFA, 0x13, 0xE1, 0x90, 0x6B, 0xDF, 0x9B, 0x90, 0xFD, 0x33, 0x0E, 0x30, 0x22, 0x53, 0xE0, - 0x4A, 0x8A, 0xD4, 0xE3, 0x58, 0x30, 0x97, 0xC2, 0x39, 0x47, 0x23, 0x1D, 0xD2, 0x1F, 0x02, 0x27, - 0xFE, 0xC4, 0x71, 0x29, 0xD0, 0x77, 0x86, 0x37, 0x24, 0xD1, 0x00, 0xCC, 0x7C, 0x8A, 0xEC, 0x78, - 0xBE, 0x33, 0x82, 0xB1, 0x33, 0x66, 0x84, 0x63, 0xCF, 0x30, 0xCA, 0xCE, 0x10, 0x09, 0xFD, 0x4F, - 0x7B, 0xC4, 0x9D, 0x8D, 0xC7, 0x2B, 0x7A, 0x74, 0x61, 0x24, 0x45, 0xAD, 0x7E, 0x99, 0xA4, 0x0D, - 0xFC, 0xDB, 0x4B, 0xB2, 0x3F, 0x1E, 0x93, 0x01, 0x7C, 0xB7, 0xF3, 0x33, 0x29, 0x7A, 0x6E, 0xE0, - 0x8D, 0x69, 0x67, 0x0C, 0x1A, 0xDB, 0xF8, 0xC4, 0x6F, 0xA4, 0x12, 0xF8, 0x0F, 0xE4, 0x04, 0x42, - 0x4B, 0xCB, 0xC0, 0x9C, 0xC4, 0xE3, 0x3A, 0xCE, 0x91, 0x39, 0xF6, 0x2C, 0xFB, 0x17, 0xCB, 0x09, - 0x95, 0x8B, 0xE8, 0x98, 0x51, 0x44, 0x24, 0x70, 0x0F, 0x66, 0x57, 0x13, 0x27, 0x8C, 0x72, 0x52, - 0x62, 0xE6, 0x11, 0x18, 0x6C, 0x58, 0x1E, 0x7C, 0xE9, 0x7E, 0x4D, 0xE2, 0xDA, 0x71, 0xCA, 0x12, - 0xB1, 0xED, 0x2E, 0xBD, 0x23, 0x78, 0x0B, 0x50, 0x4E, 0x6A, 0x11, 0x15, 0x77, 0xAC, 0xE9, 0x94, - 0x0F, 0xAA, 0x34, 0xDA, 0x36, 0x23, 0xBB, 0x92, 0xE0, 0xB4, 0xFE, 0xDD, 0xFA, 0x2E, 0xF0, 0xFD, - 0x7A, 0xF2, 0xE1, 0x7D, 0x88, 0x19, 0xE0, 0xFE, 0x63, 0x46, 0x83, 0x30, 0xC2, 0x8A, 0x15, 0x3A, - 0x1E, 0x20, 0x6C, 0x35, 0xCE, 0x3E, 0x0E, 0x2E, 0x30, 0x85, 0xC9, 0xFA, 0x8C, 0xB5, 0x28, 0x42, - 0xDC, 0x90, 0x6B, 0xB2, 0xA1, 0x15, 0x71, 0x12, 0x8D, 0x3C, 0x6E, 0xC6, 0x64, 0x69, 0x18, 0x62, - 0x2D, 0x5F, 0x5D, 0xF9, 0xAF, 0x79, 0xA1, 0x83, 0x77, 0xF8, 0xA6, 0x4A, 0x06, 0xA8, 0xC6, 0x6E, - 0x8E, 0x68, 0x07, 0xA1, 0x15, 0xCE, 0x02, 0x0C, 0x6F, 0x56, 0x0D, 0x72, 0x3E, 0x41, 0xA8, 0x9E, - 0x87, 0x34, 0x35, 0x90, 0xF9, 0xB0, 0x33, 0x57, 0x6A, 0x64, 0x0E, 0x66, 0x85, 0x80, 0xE7, 0x8F, - 0x68, 0x78, 0x66, 0x39, 0x3E, 0xCC, 0x88, 0x68, 0x5C, 0xD5, 0x19, 0xE4, 0x2A, 0x74, 0xDF, 0xB2, - 0x1A, 0xBC, 0xCC, 0x20, 0x22, 0xD4, 0x5E, 0x9F, 0x15, 0x32, 0x5C, 0x5E, 0x18, 0x52, 0xB7, 0x23, - 0xE5, 0x24, 0x98, 0x52, 0xEA, 0x9F, 0xEC, 0x1F, 0x04, 0x3A, 0xDC, 0xA9, 0xE7, 0xD2, 0xAC, 0xC8, - 0x54, 0x46, 0xF1, 0x28, 0x98, 0x9E, 0x7A, 0x77, 0x67, 0x00, 0x1E, 0x18, 0xCC, 0x2F, 0x30, 0xC6, - 0x8C, 0xA4, 0x9E, 0xD4, 0x6D, 0x14, 0x99, 0x28, 0x51, 0x60, 0xE0, 0x98, 0xC1, 0xB1, 0x50, 0x1D, - 0x91, 0x7D, 0x2B, 0x2B, 0x42, 0x56, 0xC6, 0x93, 0xB0, 0x10, 0x87, 0x2B, 0x58, 0xB6, 0x7D, 0x74, - 0x0B, 0xBF, 0x60, 0x98, 0x32, 0x05, 0xFC, 0xAD, 0xC6, 0xE1, 0xC7, 0x13, 0xB0, 0xC5, 0x21, 0x7E, - 0x83, 0x8E, 0xA0, 0x98, 0xAD, 0xB0, 0x45, 0xB1, 0xCA, 0x0A, 0xD9, 0x7B, 0x0D, 0x0C, 0xC6, 0x1A, - 0x2E, 0x04, 0x56, 0x22, 0xF6, 0x21, 0x9D, 0x25, 0x4C, 0x89, 0x78, 0x60, 0x77, 0xE9, 0xD1, 0xA9, - 0x67, 0xB7, 0xF6, 0xE0, 0x17, 0x8E, 0x39, 0x8E, 0x78, 0x70, 0x30, 0x0C, 0xC2, 0xFA, 0x0E, 0xBF, - 0xA8, 0xA1, 0x0F, 0xBC, 0xDA, 0x17, 0xE7, 0x6B, 0xC7, 0x73, 0x87, 0x63, 0x67, 0x88, 0x69, 0x3E, - 0x62, 0xD9, 0xB6, 0x52, 0x4F, 0xED, 0xAA, 0xF9, 0xF3, 0x32, 0x1E, 0xD0, 0xE4, 0x2E, 0x96, 0x15, - 0xCC, 0x7C, 0x16, 0x34, 0x8D, 0x8E, 0xF0, 0xFB, 0xDF, 0x41, 0xF8, 0x69, 0x39, 0x71, 0x7C, 0x38, - 0xF0, 0x8D, 0x24, 0x0D, 0x88, 0x06, 0x74, 0xA8, 0x6E, 0x9B, 0x90, 0xF5, 0x4C, 0x7A, 0x52, 0x30, - 0xF6, 0x83, 0x3C, 0xDA, 0x8D, 0x28, 0x17, 0xC1, 0x5C, 0x42, 0x35, 0x8F, 0x37, 0xA9, 0x09, 0x06, - 0xE6, 0x0C, 0xEF, 0x79, 0x57, 0x66, 0xAD, 0xDE, 0xDB, 0xE0, 0x89, 0x1D, 0x09, 0x44, 0x7D, 0xF3, - 0x03, 0xAD, 0xDC, 0x8E, 0x30, 0xCF, 0x2F, 0xF3, 0x25, 0x55, 0x53, 0x8B, 0xDE, 0x22, 0xC4, 0x22, - 0x9A, 0x13, 0x21, 0x2A, 0xD5, 0x96, 0x0C, 0x3E, 0x93, 0x86, 0x64, 0x37, 0xD6, 0xD0, 0x96, 0xFC, - 0x87, 0xAA, 0x6B, 0xB7, 0x6C, 0xAE, 0xF7, 0xAF, 0x79, 0x3B, 0x71, 0x5D, 0x90, 0xD7, 0xCC, 0x51, - 0xBC, 0x44, 0xA8, 0xDF, 0xCC, 0x77, 0x2C, 0xA3, 0xD3, 0xA2, 0x5B, 0xF9, 0x4E, 0xCF, 0x13, 0x65, - 0x6A, 0x24, 0x6F, 0x44, 0x76, 0x23, 0xB9, 0x10, 0xD2, 0x8D, 0x54, 0x2A, 0x65, 0xED, 0xF4, 0xA5, - 0xD6, 0xD7, 0x4B, 0xD9, 0xF4, 0x53, 0xDE, 0x7F, 0x31, 0xBE, 0x68, 0x2C, 0x1D, 0x9A, 0xF6, 0x3A, - 0x9B, 0x6A, 0x03, 0x1F, 0xD4, 0x7B, 0x49, 0x95, 0xB6, 0x6B, 0xAA, 0x50, 0xEE, 0xF5, 0xB6, 0x3B, - 0xFD, 0x42, 0xD2, 0xF5, 0x70, 0x2B, 0xBB, 0x07, 0x2A, 0x66, 0x83, 0x12, 0x9A, 0xDE, 0x5F, 0xAE, - 0xAD, 0x7B, 0x15, 0x1F, 0x73, 0x4E, 0x54, 0xCA, 0x70, 0xFB, 0xB5, 0xE4, 0xC3, 0xE3, 0x5C, 0x65, - 0x4B, 0xC0, 0x67, 0xB5, 0x3A, 0x7E, 0x6F, 0x64, 0x11, 0xAD, 0x2E, 0xF3, 0x78, 0x89, 0xD6, 0x6A, - 0x0E, 0x52, 0xBF, 0xD5, 0xF9, 0xF0, 0x86, 0x56, 0x6B, 0xF7, 0xA1, 0xE6, 0x6F, 0x79, 0x1A, 0x61, - 0x41, 0xEB, 0x0D, 0x37, 0xAF, 0x00, 0x48, 0x24, 0xA5, 0xD7, 0xC2, 0x3C, 0x0B, 0x45, 0x51, 0x88, - 0x4C, 0xDD, 0x99, 0x32, 0x88, 0x05, 0xD7, 0x29, 0x98, 0xB5, 0x13, 0xF3, 0xD2, 0xBA, 0x74, 0x3C, - 0x8F, 0x40, 0xD2, 0xA8, 0xE2, 0xB4, 0x1D, 0x5D, 0xB3, 0x0E, 0x44, 0x10, 0x6F, 0xAC, 0x99, 0x7D, - 0xE8, 0x7B, 0x53, 0x1B, 0x53, 0x1F, 0x19, 0xE7, 0x16, 0x25, 0xE3, 0x74, 0xA1, 0xBE, 0x94, 0xE0, - 0xA8, 0x67, 0x36, 0xFF, 0x65, 0x38, 0x12, 0xB3, 0x61, 0x25, 0x8E, 0xEA, 0xD2, 0xAA, 0xD0, 0x7A, - 0x83, 0xB6, 0x67, 0x3F, 0xAD, 0x36, 0xA7, 0xD6, 0x17, 0xBE, 0xD9, 0x66, 0xEE, 0xEF, 0x29, 0x98, - 0x29, 0xFE, 0x68, 0x67, 0x2D, 0x81, 0x15, 0x83, 0x2B, 0x32, 0x98, 0x05, 0xF4, 0x83, 0x37, 0xB4, - 0xC6, 0xCE, 0xEF, 0xD4, 0x3E, 0x84, 0x76, 0xFA, 0xCE, 0xD5, 0x8C, 0xE7, 0x49, 0xAC, 0xDF, 0xFC, - 0x1C, 0x9C, 0xB9, 0x2D, 0x1F, 0x9B, 0x80, 0x2E, 0x60, 0x89, 0xF3, 0x01, 0x16, 0x6D, 0x63, 0x53, - 0xEF, 0x97, 0x90, 0x47, 0x5D, 0xA4, 0x06, 0x4D, 0xD1, 0x53, 0xD1, 0xCF, 0xA9, 0x1F, 0x15, 0x32, - 0xDB, 0xE7, 0x8E, 0xA8, 0x43, 0x1A, 0x5A, 0xCE, 0x38, 0xA8, 0x28, 0x97, 0x2A, 0x88, 0x72, 0x64, - 0xF1, 0xDE, 0xF2, 0x6D, 0xDC, 0xEB, 0xE0, 0x82, 0x88, 0x5F, 0xB4, 0x59, 0x90, 0x68, 0x32, 0xB0, - 0x57, 0x92, 0x94, 0x0C, 0x3B, 0x9F, 0xA8, 0x4A, 0x61, 0x32, 0xC9, 0x8A, 0xED, 0x9C, 0x2C, 0x40, - 0x2A, 0x11, 0x9E, 0x52, 0xED, 0x67, 0x5B, 0x0A, 0xF5, 0x1A, 0x9C, 0x0F, 0x6A, 0xF2, 0x18, 0xA4, - 0x3D, 0xA9, 0x05, 0xB8, 0x0B, 0x2A, 0xB6, 0x0C, 0x9B, 0x61, 0xD8, 0x0E, 0x9B, 0xCF, 0x47, 0xC8, - 0x45, 0x56, 0xE8, 0x23, 0xE8, 0x2F, 0x69, 0x55, 0x96, 0x01, 0xF6, 0xDA, 0x7B, 0x10, 0xBF, 0xAA, - 0x60, 0xD1, 0xEE, 0x4E, 0x36, 0xAD, 0xF3, 0xE3, 0xD3, 0xA3, 0x5F, 0xE7, 0x17, 0xBA, 0x86, 0xAD, - 0xDC, 0x10, 0x4B, 0x41, 0xD6, 0x1C, 0x60, 0xE5, 0xF1, 0x18, 0xE4, 0xA0, 0x3C, 0xA5, 0x35, 0xA7, - 0x14, 0xCA, 0x3E, 0xCB, 0xA5, 0xCB, 0x20, 0x81, 0x9B, 0x47, 0x02, 0x25, 0xB0, 0x98, 0xDA, 0x6F, - 0x7A, 0x6B, 0x6B, 0x5E, 0x39, 0x54, 0x7C, 0xBF, 0x2B, 0x25, 0x0F, 0x80, 0x9F, 0x58, 0xA1, 0x33, - 0x54, 0x91, 0xCC, 0x25, 0x9C, 0x8A, 0x28, 0x33, 0x24, 0x15, 0xBD, 0xCE, 0xB5, 0x00, 0x01, 0x95, - 0x78, 0xE8, 0x2B, 0x53, 0x2E, 0x0C, 0x76, 0x21, 0xE2, 0xC8, 0xC7, 0x94, 0xDE, 0x4F, 0xDA, 0x1F, - 0x87, 0x4E, 0x38, 0xB3, 0x6B, 0x29, 0x89, 0x72, 0x7E, 0x9B, 0x42, 0x2F, 0xF6, 0x1D, 0xDE, 0x53, - 0x67, 0x74, 0x13, 0x5E, 0x4E, 0x96, 0x46, 0x20, 0xB5, 0xB1, 0xB1, 0x60, 0x32, 0xEA, 0x69, 0xFA, - 0x02, 0x91, 0xC7, 0x97, 0x22, 0xEF, 0xF9, 0xA5, 0xC8, 0x7B, 0xF2, 0x8A, 0xB8, 0xB3, 0xC9, 0x41, - 0xEA, 0x61, 0x1E, 0x28, 0x4A, 0x5F, 0x8D, 0x04, 0xD7, 0x35, 0xF4, 0x5C, 0x71, 0x33, 0x92, 0x3D, - 0xB7, 0x80, 0xA9, 0x35, 0xDE, 0xB0, 0xAF, 0x98, 0x13, 0xFF, 0x5E, 0x89, 0xAE, 0x48, 0x6A, 0x1B, - 0x9B, 0x80, 0x67, 0x0C, 0x99, 0x2D, 0x88, 0xD2, 0x7E, 0x24, 0xF8, 0x0F, 0xB0, 0x7E, 0xEB, 0x5E, - 0x56, 0x2F, 0x29, 0xB5, 0xFD, 0x8A, 0x7C, 0x92, 0x9F, 0x31, 0x8D, 0x49, 0x79, 0x71, 0xAA, 0x85, - 0xD6, 0x14, 0x3C, 0x55, 0x59, 0x62, 0x66, 0x12, 0x3C, 0x9C, 0x30, 0xEC, 0xF3, 0x4C, 0x4D, 0x05, - 0x88, 0x8C, 0xE7, 0xC4, 0x0B, 0x63, 0x7F, 0x01, 0x8C, 0x9B, 0x58, 0x56, 0x02, 0x6A, 0xF2, 0x72, - 0xB7, 0xE4, 0x64, 0x95, 0xC9, 0xD0, 0x61, 0xED, 0x7A, 0x6F, 0x7D, 0xED, 0x4F, 0x12, 0x4A, 0x66, - 0xA7, 0xA2, 0xB9, 0x67, 0x39, 0xC7, 0xBE, 0x9B, 0xF6, 0x5B, 0xCB, 0x0C, 0x9E, 0xEF, 0xBB, 0xA6, - 0xAD, 0x54, 0x79, 0x10, 0x61, 0x6A, 0x5B, 0x71, 0x9A, 0xC8, 0xD2, 0xCA, 0x6A, 0xAC, 0x60, 0x25, - 0xE4, 0xA2, 0x60, 0x67, 0x55, 0xCD, 0x69, 0x64, 0x18, 0x63, 0xF8, 0x8D, 0xFF, 0x9D, 0x04, 0x4D, - 0x90, 0x63, 0x77, 0xE8, 0xB3, 0xA3, 0xEE, 0xA9, 0x48, 0xF6, 0x43, 0xD6, 0x48, 0x70, 0x67, 0x4D, - 0xF9, 0x4B, 0xB0, 0xEC, 0x94, 0x12, 0xE6, 0x9F, 0x84, 0x27, 0x12, 0x30, 0x9E, 0x78, 0xEE, 0x03, - 0xAC, 0xE3, 0x62, 0x5E, 0xDE, 0x1B, 0xB0, 0xCB, 0x34, 0x48, 0x5E, 0x6F, 0x4C, 0x48, 0xB1, 0xD7, - 0xDD, 0xF5, 0x9B, 0xD8, 0xD6, 0x37, 0x7A, 0x42, 0xDF, 0x23, 0x8C, 0xBF, 0x6B, 0x28, 0x61, 0x99, - 0xC8, 0x76, 0xD3, 0xBD, 0x5B, 0x59, 0x2F, 0xCA, 0xF4, 0xEE, 0x77, 0xD6, 0xBB, 0x69, 0xD9, 0xC8, - 0x3F, 0x32, 0xC3, 0x49, 0x5A, 0x22, 0xF3, 0xEE, 0x79, 0x39, 0x7A, 0xB2, 0x84, 0xD6, 0x48, 0x6F, - 0x25, 0x9B, 0x2A, 0x13, 0x46, 0x1E, 0xD1, 0x87, 0x05, 0x0A, 0x8A, 0x99, 0x4C, 0xB9, 0xB5, 0x26, - 0xBE, 0x0A, 0x5A, 0xB7, 0x86, 0x37, 0x29, 0x64, 0xD5, 0x2A, 0x10, 0x96, 0x44, 0x93, 0xB5, 0xD5, - 0x44, 0x12, 0xB0, 0x9D, 0x7A, 0x21, 0x7D, 0x49, 0x1A, 0x05, 0xC4, 0x57, 0x81, 0x78, 0x83, 0x78, - 0xEE, 0xF8, 0x9E, 0xE0, 0x23, 0xE2, 0x41, 0xC4, 0x2C, 0xFC, 0xED, 0x5C, 0x9B, 0xD0, 0xE6, 0xE0, - 0x63, 0xEF, 0x3B, 0x38, 0x6E, 0xD8, 0x66, 0xEF, 0x24, 0x07, 0x2C, 0x75, 0x6E, 0x87, 0x7C, 0xC2, - 0xB1, 0x62, 0xF9, 0xF8, 0xBC, 0x4E, 0x88, 0x63, 0x85, 0x52, 0x62, 0x5D, 0x79, 0xB7, 0xB4, 0xAA, - 0x98, 0x56, 0x23, 0x31, 0x1D, 0xD2, 0x5C, 0x31, 0x3D, 0x28, 0xE9, 0x16, 0xC8, 0xF1, 0x35, 0xB1, - 0xC6, 0x50, 0xDF, 0xBE, 0x67, 0xA3, 0x4F, 0x0C, 0xBC, 0x78, 0xF4, 0xB6, 0x99, 0x24, 0x89, 0x13, - 0x92, 0x31, 0xC8, 0x52, 0x8C, 0x48, 0xCD, 0x92, 0xB3, 0x48, 0x82, 0xFD, 0xC9, 0x7B, 0x0E, 0xFA, - 0xB8, 0xE3, 0x0C, 0x6D, 0x01, 0x36, 0xA3, 0x4B, 0x9C, 0x80, 0xBC, 0x97, 0xAC, 0x86, 0x82, 0x2A, - 0x66, 0x2E, 0xAD, 0xF7, 0xF8, 0x73, 0x05, 0xED, 0xFF, 0xF6, 0x38, 0xC3, 0x01, 0xF3, 0xC8, 0xC7, - 0xDC, 0x2C, 0x79, 0x30, 0x64, 0x9C, 0xBB, 0x15, 0x66, 0x49, 0x33, 0xB6, 0x09, 0xAD, 0x0A, 0x23, - 0xFC, 0x21, 0xD1, 0x83, 0x6C, 0xE5, 0xAA, 0x9A, 0x5F, 0x0D, 0xDD, 0xBE, 0x83, 0xA3, 0xB7, 0xF1, - 0xD4, 0x2D, 0xBF, 0x01, 0x15, 0xC7, 0xFD, 0xBB, 0x30, 0xE9, 0x60, 0x50, 0x0B, 0xD6, 0x8C, 0x4F, - 0x08, 0x7D, 0x3A, 0x81, 0xC1, 0xF2, 0xC6, 0xB2, 0x0F, 0xF0, 0x19, 0xCF, 0x56, 0xBA, 0x4E, 0xE4, - 0xD1, 0x1A, 0x5F, 0x08, 0x95, 0x6A, 0x8B, 0xF7, 0x41, 0x53, 0x0F, 0x35, 0x6F, 0xEE, 0xB0, 0x17, - 0x42, 0x2D, 0x98, 0xB7, 0xD4, 0x67, 0x42, 0xE5, 0xCC, 0xB8, 0xBB, 0x59, 0x2F, 0x59, 0x4A, 0x91, - 0xBD, 0x6D, 0xB2, 0xF6, 0x3C, 0x7A, 0x4E, 0xF3, 0x79, 0xEA, 0x5D, 0xCD, 0xA8, 0x0C, 0x49, 0x8A, - 0x5F, 0xEB, 0x13, 0xFB, 0xFC, 0x98, 0xC4, 0x7E, 0x5B, 0x24, 0xB1, 0x8C, 0x57, 0xC0, 0x94, 0x29, - 0x3F, 0x7A, 0x46, 0x07, 0x7B, 0x8E, 0x58, 0x23, 0x0B, 0xDF, 0x20, 0xE3, 0xB9, 0xFD, 0x1D, 0x49, - 0x31, 0xF9, 0x5B, 0x21, 0x36, 0xFD, 0xAE, 0x5E, 0x78, 0x60, 0x83, 0x78, 0x57, 0x94, 0xBC, 0xC2, - 0xE8, 0x51, 0xCF, 0xB7, 0x03, 0xA6, 0x2E, 0x51, 0xE4, 0xD3, 0xEA, 0x2A, 0x2B, 0xD5, 0x47, 0x27, - 0x22, 0x04, 0x43, 0x1D, 0x06, 0x4C, 0xEB, 0x62, 0xB0, 0x2F, 0xAC, 0xF2, 0xD7, 0x28, 0x33, 0x2F, - 0xD1, 0x13, 0x82, 0x46, 0x5E, 0xB5, 0xA2, 0x6B, 0xD2, 0xC9, 0x15, 0x43, 0x89, 0xE9, 0x77, 0x0D, - 0x43, 0x35, 0x4D, 0x06, 0x87, 0x67, 0x7A, 0x18, 0xAC, 0x92, 0x26, 0xCB, 0x8E, 0x99, 0x68, 0x5B, - 0x56, 0xC1, 0xE7, 0xAC, 0x82, 0xDF, 0xF4, 0xCC, 0xAB, 0x15, 0x8D, 0x23, 0x7F, 0x32, 0x83, 0x89, - 0x7B, 0xCF, 0x20, 0xD5, 0x95, 0x67, 0x19, 0xED, 0xEA, 0x4C, 0x67, 0xC1, 0x4D, 0x6B, 0xA9, 0x6D, - 0x5A, 0x31, 0x64, 0x7D, 0x44, 0x42, 0xB8, 0xC6, 0xD4, 0x0D, 0x91, 0x4D, 0x31, 0x00, 0x32, 0xB6, - 0x45, 0x71, 0xD8, 0x1D, 0x20, 0x12, 0xD1, 0xAD, 0x18, 0x9E, 0x09, 0x35, 0xA5, 0xC0, 0x79, 0xB9, - 0x47, 0x93, 0x0B, 0x62, 0x08, 0xF1, 0x9A, 0x65, 0x16, 0x56, 0x67, 0x4A, 0x93, 0x0A, 0x41, 0x5D, - 0xB3, 0x02, 0x21, 0x00, 0xCA, 0x46, 0xAC, 0x06, 0x22, 0x5D, 0x91, 0xA2, 0x54, 0xF8, 0x34, 0xC9, - 0x42, 0x78, 0x5B, 0x8D, 0x43, 0xC6, 0x3D, 0xC1, 0x83, 0x24, 0xD6, 0x1A, 0x5C, 0x2E, 0xC4, 0xE0, - 0xAB, 0xA4, 0xF1, 0x2F, 0x8D, 0x95, 0xAC, 0xAD, 0x1F, 0xB9, 0x4B, 0x90, 0x93, 0x21, 0xC5, 0x16, - 0x80, 0x4D, 0xCC, 0x58, 0x3B, 0xE6, 0x8B, 0x11, 0xA3, 0x49, 0x15, 0x83, 0xFE, 0x03, 0x65, 0x98, - 0x79, 0xC1, 0x82, 0x4B, 0xB3, 0xF7, 0x35, 0xA3, 0xEA, 0xE7, 0x54, 0xD5, 0x7E, 0x56, 0xD5, 0xDF, - 0x52, 0x55, 0x37, 0xB4, 0xAA, 0xE6, 0xD1, 0x2F, 0x75, 0xA8, 0xE9, 0x11, 0x37, 0x99, 0xEB, 0x82, - 0x1A, 0x9F, 0x0B, 0x6B, 0xFC, 0x96, 0x55, 0x43, 0x65, 0x4D, 0x79, 0xAE, 0x2C, 0x7E, 0x59, 0x45, - 0x12, 0x34, 0x78, 0xB1, 0xBE, 0x05, 0x7E, 0x21, 0x57, 0x00, 0x62, 0xB9, 0x36, 0x99, 0x78, 0xAE, - 0x17, 0x4C, 0x2D, 0x58, 0xC5, 0xB1, 0x40, 0x59, 0x66, 0x86, 0xB5, 0x95, 0x7A, 0xA2, 0x28, 0x52, - 0xB4, 0x6D, 0xA6, 0x1A, 0x88, 0xA4, 0xCE, 0xC9, 0xD4, 0x8F, 0xCA, 0x90, 0x36, 0x2A, 0xA9, 0x99, - 0x81, 0xEF, 0x27, 0x64, 0xA1, 0x4D, 0x9A, 0x2F, 0x37, 0x19, 0x2F, 0xAD, 0xE8, 0xF1, 0xC5, 0xD2, - 0x93, 0x2B, 0x98, 0x9E, 0xCF, 0xF3, 0xA9, 0xDD, 0xC8, 0x7B, 0x8F, 0x91, 0xED, 0x84, 0xCC, 0x4D, - 0x56, 0x94, 0xBE, 0x24, 0xBF, 0xAE, 0x7F, 0x5E, 0xFF, 0xAD, 0xA1, 0x26, 0xC1, 0x36, 0xB4, 0xFE, - 0x15, 0xD9, 0x5A, 0x49, 0x1D, 0x0D, 0x65, 0xCA, 0x34, 0x70, 0x7E, 0xA7, 0xC4, 0x64, 0x9A, 0x15, - 0xEB, 0x18, 0xFB, 0xB8, 0xC9, 0xD4, 0x59, 0x75, 0xAE, 0xC4, 0x01, 0xEA, 0x4D, 0x59, 0xDF, 0x4B, - 0x51, 0xCA, 0xE8, 0xAD, 0x82, 0x1A, 0x88, 0xAC, 0xC8, 0x4D, 0x5E, 0x41, 0x1E, 0xA6, 0xFC, 0x0B, - 0xDB, 0xBB, 0x30, 0x4E, 0xB0, 0xA9, 0x9A, 0xD1, 0x18, 0x62, 0xC5, 0xEA, 0x68, 0xCB, 0x14, 0x02, - 0xA6, 0x84, 0xE6, 0xE0, 0xEA, 0xA4, 0xF0, 0xE7, 0x56, 0xE3, 0x7F, 0x99, 0x81, 0x04, 0x35, 0x80, - 0xA5, 0xD6, 0xF0, 0xA6, 0x65, 0xDE, 0x85, 0x94, 0x6D, 0xD2, 0x9F, 0x5B, 0xE1, 0x8D, 0x13, 0xF0, - 0x4D, 0x98, 0xD6, 0x4A, 0xAE, 0x55, 0x77, 0x55, 0xAB, 0xDE, 0x09, 0x66, 0x57, 0x7C, 0x55, 0xD8, - 0x02, 0xFF, 0xA9, 0xB7, 0xA5, 0xBC, 0x71, 0x2D, 0x21, 0x8D, 0x41, 0x61, 0xC2, 0xE3, 0x59, 0xB1, - 0x23, 0x4B, 0x16, 0x4F, 0x81, 0x91, 0xBD, 0xD2, 0x3E, 0x6C, 0x7C, 0xE5, 0x28, 0x92, 0xCD, 0x5E, - 0xCD, 0x09, 0x8F, 0xAE, 0x85, 0x95, 0x73, 0xC4, 0xA3, 0xDA, 0x45, 0xCE, 0xB8, 0x5A, 0xAF, 0x8C, - 0x43, 0x1E, 0x41, 0x2C, 0xCA, 0x29, 0x4F, 0xDE, 0x48, 0xCA, 0x75, 0x67, 0xE3, 0x03, 0x07, 0xF0, - 0x68, 0x7B, 0xBD, 0xEE, 0xC6, 0x66, 0x9B, 0xBC, 0x78, 0xA1, 0x50, 0xE7, 0x9F, 0x91, 0x05, 0x2C, - 0xA8, 0xEC, 0x34, 0xEB, 0xE7, 0x0E, 0x48, 0x07, 0xDF, 0xB3, 0xDF, 0x52, 0x48, 0xF0, 0x07, 0xED, - 0xB7, 0xEA, 0x62, 0xD7, 0x0E, 0x1D, 0x80, 0x46, 0xBF, 0xDB, 0xED, 0x74, 0xD9, 0x2D, 0xAF, 0x8E, - 0xE2, 0x99, 0xB3, 0x0F, 0x48, 0x8C, 0xFD, 0xF2, 0xE4, 0xBC, 0xF2, 0x58, 0x6F, 0xAA, 0x7B, 0xE6, - 0x11, 0x68, 0x55, 0xEF, 0x3C, 0x56, 0xBC, 0x6A, 0x1E, 0xBA, 0x46, 0x4E, 0xF2, 0xD2, 0xB5, 0x31, - 0xA2, 0xF8, 0xA8, 0xE2, 0x7E, 0xA5, 0xB1, 0x48, 0x5C, 0xA7, 0x34, 0x95, 0x45, 0x5A, 0xAA, 0x95, - 0x69, 0xBA, 0x65, 0x2E, 0x55, 0x75, 0x63, 0x09, 0x3E, 0xBF, 0xD6, 0x67, 0x46, 0xBF, 0x3F, 0xAE, - 0xA3, 0xF8, 0xFE, 0xFF, 0x00, 0x92, 0x32, 0xAD, 0x24, 0x22, 0xB6, 0xB3, 0x57, 0x13, 0x29, 0xA3, - 0x5A, 0xE4, 0x0C, 0xEB, 0x4A, 0x58, 0xD9, 0x21, 0x8E, 0xD5, 0xF1, 0xE9, 0x2C, 0x2C, 0xE2, 0xDE, - 0x2D, 0xBF, 0xB8, 0xC8, 0x93, 0xAC, 0x74, 0x72, 0x29, 0x2F, 0xD3, 0x6E, 0x2C, 0x7A, 0x42, 0xC3, - 0x1B, 0xCF, 0xCE, 0xBC, 0x20, 0xA5, 0xDC, 0x8E, 0x4A, 0xEE, 0x05, 0xBF, 0x8C, 0xAE, 0x01, 0xA7, - 0x9E, 0xDF, 0x01, 0x94, 0x89, 0xFC, 0x25, 0xFC, 0x5A, 0xCC, 0x69, 0xFA, 0x34, 0x36, 0x3B, 0xBE, - 0xC7, 0x74, 0xC0, 0x9D, 0x19, 0xC0, 0x03, 0x24, 0xE1, 0x9B, 0x78, 0x93, 0x26, 0xE3, 0x06, 0xF5, - 0x0A, 0x59, 0x23, 0x2D, 0xA9, 0x4A, 0xFA, 0x78, 0x5B, 0x54, 0x5B, 0x25, 0xE9, 0x5A, 0xE6, 0xE0, - 0xFB, 0x15, 0xB2, 0x4E, 0x7A, 0xFC, 0x56, 0x70, 0x1E, 0xDB, 0xD1, 0xCC, 0x0F, 0x5C, 0x76, 0x30, - 0x0E, 0x03, 0x4A, 0x5B, 0x1B, 0x79, 0x97, 0x51, 0x73, 0xE5, 0x94, 0xBE, 0x78, 0x9F, 0x23, 0x26, - 0x4D, 0xA8, 0x66, 0x39, 0xE9, 0xAC, 0xA2, 0x08, 0x1E, 0x51, 0x52, 0xA9, 0x8B, 0xEE, 0x66, 0x39, - 0xE9, 0x4B, 0xE7, 0x27, 0x6B, 0x31, 0x66, 0x93, 0x33, 0x01, 0xC7, 0xE0, 0x95, 0x15, 0x44, 0x44, - 0x31, 0xAE, 0xF4, 0x7A, 0x8F, 0x6C, 0x9B, 0xA6, 0xEA, 0xB1, 0x15, 0x46, 0x58, 0x92, 0xCA, 0x6B, - 0x64, 0x13, 0x05, 0xD9, 0x37, 0x3C, 0x09, 0x96, 0x39, 0x35, 0x1B, 0x96, 0xCF, 0x05, 0xF9, 0x0B, - 0xD2, 0x4B, 0xFE, 0x88, 0xEB, 0x98, 0xA9, 0xD7, 0xE9, 0x58, 0x72, 0x65, 0x61, 0x34, 0x81, 0xD5, - 0x60, 0xC4, 0x7E, 0x6F, 0x57, 0xFA, 0xF3, 0x55, 0xDC, 0x30, 0xE9, 0x6B, 0xFA, 0x1C, 0xA0, 0x90, - 0xCB, 0xD5, 0x3D, 0xC5, 0x67, 0x4F, 0x08, 0xAC, 0x12, 0x9D, 0xF1, 0xF4, 0x9E, 0xFF, 0x43, 0x86, - 0x24, 0xD2, 0xD9, 0x19, 0x84, 0x28, 0x00, 0x6B, 0xC4, 0xF6, 0xD3, 0x92, 0x8A, 0xCE, 0x71, 0x9E, - 0x58, 0xB2, 0x1B, 0x51, 0x5A, 0x42, 0x06, 0x9B, 0xC6, 0x09, 0x49, 0x1A, 0xBA, 0x61, 0x50, 0xB4, - 0x0C, 0x03, 0x62, 0x02, 0xEF, 0x67, 0x83, 0x67, 0x5E, 0x80, 0x4A, 0x21, 0xE9, 0x7D, 0xD5, 0xAE, - 0xA8, 0xD5, 0x49, 0x94, 0x11, 0x65, 0xBA, 0xA8, 0x80, 0xA7, 0x9F, 0x93, 0x70, 0x43, 0xC1, 0xA3, - 0xC4, 0x14, 0x65, 0xBD, 0x74, 0x65, 0x18, 0xD4, 0xBB, 0x99, 0x75, 0xD5, 0x51, 0x52, 0x54, 0x2F, - 0xD6, 0x9B, 0x82, 0x8A, 0x49, 0x87, 0x67, 0x57, 0x4C, 0x75, 0x6E, 0x61, 0x55, 0xBD, 0x23, 0x4B, - 0x06, 0xC2, 0x28, 0x29, 0x1A, 0x02, 0x6E, 0xDE, 0x23, 0xD1, 0x10, 0x66, 0x8D, 0xF9, 0x4A, 0x3C, - 0x23, 0x2C, 0x26, 0xBD, 0x53, 0x17, 0x03, 0xD7, 0xDA, 0xAD, 0x53, 0x3D, 0xAF, 0xDC, 0x1D, 0x3B, - 0xC9, 0x2A, 0xE7, 0xED, 0xDA, 0x69, 0xCB, 0x82, 0xD2, 0x3B, 0x77, 0x26, 0xFD, 0xD0, 0x75, 0x67, - 0x89, 0x3B, 0x78, 0x35, 0xC9, 0xC7, 0x3B, 0x79, 0xA0, 0xB5, 0xEB, 0xA8, 0x91, 0xEB, 0xA0, 0x6D, - 0xE6, 0x0D, 0x3D, 0x5D, 0x30, 0x25, 0x37, 0xF5, 0x24, 0xB1, 0xAB, 0x1B, 0x7B, 0xFA, 0x9A, 0xB9, - 0xE2, 0xE6, 0x5E, 0x99, 0x25, 0xF7, 0x22, 0x37, 0xF8, 0xB4, 0x85, 0xF3, 0x7C, 0x9B, 0x7C, 0x92, - 0x50, 0xAA, 0x6D, 0xF4, 0xC5, 0xA3, 0xE5, 0x87, 0x6E, 0xF6, 0x29, 0xEA, 0x21, 0xFB, 0x57, 0xE8, - 0x49, 0x3D, 0xD7, 0x67, 0xCC, 0x85, 0x6D, 0x09, 0xA6, 0xE6, 0x4B, 0xB5, 0xC2, 0xA6, 0x0E, 0xB1, - 0xA5, 0x7F, 0xD8, 0x2E, 0x42, 0xF1, 0x5C, 0xD9, 0x76, 0x2C, 0x34, 0x86, 0x4B, 0xD9, 0xEC, 0x94, - 0x74, 0xE0, 0x21, 0x95, 0xE9, 0x48, 0xD9, 0xB5, 0x94, 0x12, 0xAF, 0x70, 0x97, 0x1B, 0xFE, 0x95, - 0x7A, 0xB6, 0xF3, 0xEF, 0x9E, 0xE3, 0xB6, 0x9A, 0xCD, 0x38, 0xEB, 0x8C, 0x56, 0xA5, 0x5D, 0x5C, - 0xE5, 0x6F, 0x7F, 0x4B, 0xD5, 0xF1, 0x69, 0x38, 0xF3, 0x5D, 0xE6, 0xAE, 0x6B, 0xDC, 0x8D, 0x68, - 0x88, 0xB9, 0x6E, 0x14, 0x53, 0xCC, 0xD2, 0x0C, 0x81, 0xC9, 0x02, 0xED, 0x89, 0xCA, 0xD0, 0xA2, - 0xF2, 0x69, 0x5D, 0x33, 0x6B, 0x4A, 0x1D, 0xB1, 0xC2, 0x92, 0x36, 0xED, 0x8E, 0xAF, 0xD9, 0x26, - 0x5D, 0x68, 0x5D, 0x91, 0x3B, 0x2B, 0x20, 0x38, 0x77, 0x13, 0xCC, 0x8F, 0x43, 0xED, 0x36, 0xE1, - 0x43, 0x1A, 0xCB, 0xC6, 0x94, 0x27, 0x52, 0x0A, 0x86, 0x3E, 0xBE, 0xCF, 0xA2, 0x2D, 0x74, 0xC6, - 0xF4, 0xC4, 0x72, 0xAD, 0x11, 0xF5, 0x2F, 0xB0, 0x66, 0x2A, 0x13, 0x0E, 0x83, 0x7F, 0xFD, 0x2A, - 0xF4, 0x89, 0x35, 0x76, 0x46, 0xEE, 0x5E, 0x73, 0x4C, 0xAF, 0xC3, 0x26, 0x7C, 0xB8, 0x79, 0x8D, - 0xFB, 0x07, 0xAF, 0xD6, 0xE1, 0x17, 0xFC, 0x63, 0x00, 0x86, 0x4C, 0xFC, 0x61, 0xBF, 0x7E, 0xC5, - 0x5F, 0xD4, 0x0B, 0xEF, 0xA7, 0x74, 0x8F, 0x7B, 0x1C, 0x57, 0xDE, 0xF7, 0x26, 0x71, 0xEC, 0xBD, - 0x26, 0x12, 0xE4, 0xCB, 0xF9, 0xFD, 0xF1, 0xB8, 0x49, 0xD8, 0x83, 0x8F, 0xF0, 0xD5, 0xF3, 0x27, - 0x6B, 0xAC, 0xE2, 0x1A, 0x07, 0x95, 0xF8, 0x62, 0x3B, 0x93, 0x4D, 0x22, 0x02, 0x17, 0x39, 0x86, - 0x88, 0x65, 0x6F, 0x34, 0xC2, 0xCC, 0x24, 0xC0, 0xCF, 0x3A, 0x92, 0x5D, 0x0F, 0xFD, 0xF8, 0x1F, - 0xC6, 0xB7, 0x64, 0xB6, 0x11, 0x8C, 0x35, 0xF1, 0x82, 0xDB, 0xB0, 0x46, 0x43, 0x12, 0xE5, 0xF7, - 0xC9, 0xF8, 0x26, 0x0C, 0xA7, 0xB9, 0xD9, 0x87, 0xA4, 0x7A, 0x22, 0x09, 0xD1, 0xBB, 0x23, 0x9E, - 0x83, 0x08, 0x67, 0x61, 0x96, 0x22, 0xA9, 0x91, 0xF6, 0xCE, 0x22, 0x08, 0x96, 0x5A, 0x46, 0xB6, - 0x13, 0x22, 0x6C, 0x6C, 0xE8, 0x4D, 0xD0, 0x8C, 0x44, 0xD5, 0x7C, 0x1A, 0x4C, 0xC1, 0x9D, 0x60, - 0x4C, 0xAE, 0x60, 0xC8, 0x8E, 0x48, 0xB8, 0x45, 0x0E, 0x06, 0x3F, 0xF3, 0x14, 0x59, 0x8E, 0x1B, - 0x7A, 0x6C, 0xF2, 0x7F, 0x56, 0xBE, 0x23, 0xC1, 0xFD, 0x56, 0x9A, 0x5F, 0x30, 0x99, 0xAA, 0x5A, - 0x97, 0xF9, 0xD4, 0x0D, 0x28, 0xB7, 0x48, 0x3D, 0x99, 0xD2, 0x6F, 0xEF, 0x2A, 0xB4, 0x1C, 0x50, - 0x43, 0xA9, 0xDC, 0xA8, 0xE3, 0xC6, 0x7A, 0xBA, 0x9E, 0x4B, 0x39, 0xFC, 0xB0, 0x82, 0xAE, 0xA2, - 0x52, 0x1F, 0x8B, 0x5A, 0x52, 0x0F, 0xC7, 0xCD, 0xC2, 0x44, 0x5B, 0x27, 0xC9, 0x5B, 0x3E, 0x68, - 0xFF, 0xBF, 0x7C, 0x35, 0x97, 0xB3, 0x0D, 0x79, 0x63, 0x85, 0xE8, 0x89, 0xD6, 0x4C, 0x0C, 0x51, - 0x05, 0x05, 0xC5, 0x02, 0xB5, 0x2C, 0x4A, 0x66, 0xFB, 0x03, 0x15, 0x2D, 0xAB, 0x27, 0x56, 0xF7, - 0x64, 0xF1, 0x2B, 0x66, 0x8A, 0x9C, 0xD3, 0xA9, 0xC0, 0x6E, 0xB9, 0xF7, 0x5C, 0x52, 0x51, 0x65, - 0x76, 0xE4, 0x10, 0x30, 0xDF, 0xF6, 0x96, 0x0B, 0x6D, 0x8D, 0x38, 0x1D, 0xDA, 0x61, 0x86, 0x4D, - 0x7C, 0x41, 0xD7, 0x07, 0xFF, 0xC4, 0x24, 0xFA, 0x84, 0xBF, 0x23, 0x40, 0x6C, 0x71, 0xA3, 0x36, - 0xC8, 0x8D, 0xF0, 0x4B, 0x75, 0x7B, 0xD6, 0x9B, 0x50, 0xA2, 0x75, 0xA9, 0xFA, 0x5F, 0xBE, 0x7F, - 0x4D, 0xD6, 0x73, 0x69, 0x25, 0xF9, 0x22, 0x7B, 0x3D, 0x0F, 0x85, 0x6D, 0x8E, 0x4C, 0x61, 0x95, - 0x46, 0x63, 0xBE, 0x4A, 0xC2, 0xA3, 0xEC, 0x13, 0x04, 0xB4, 0x44, 0xB3, 0x15, 0x65, 0xCD, 0x6B, - 0x37, 0x9B, 0x90, 0xD2, 0xDA, 0x2B, 0x82, 0x34, 0x1B, 0x38, 0x1A, 0xB3, 0xF2, 0x8B, 0xA4, 0x09, - 0x31, 0x81, 0x65, 0x65, 0xE3, 0xCC, 0xC9, 0x6C, 0x92, 0xC3, 0x00, 0xD3, 0xF4, 0xDA, 0x1C, 0x68, - 0x3B, 0x8D, 0x15, 0x22, 0x2D, 0xA5, 0x55, 0xDD, 0x71, 0x10, 0xCC, 0x44, 0x98, 0xFB, 0xF1, 0xE1, - 0x4B, 0xB6, 0x83, 0x6E, 0x26, 0x5C, 0x25, 0x2C, 0x5F, 0xB5, 0x9F, 0x6F, 0xD8, 0x63, 0xDB, 0xF9, - 0x36, 0x14, 0xEB, 0x94, 0xB5, 0xA3, 0xBC, 0x6E, 0x81, 0x2D, 0xC5, 0x4A, 0xF5, 0xED, 0xE9, 0x93, - 0x31, 0x87, 0xAC, 0x19, 0x4F, 0xC2, 0x24, 0xA6, 0x04, 0x5A, 0xD5, 0x2C, 0xFE, 0x61, 0x22, 0xFE, - 0x30, 0x11, 0x72, 0x1E, 0xC8, 0xD8, 0xAB, 0x3B, 0x84, 0xC9, 0x0E, 0x8F, 0x17, 0x92, 0x24, 0x90, - 0xE2, 0x3E, 0x0E, 0xBA, 0x6A, 0xE5, 0x73, 0x0A, 0x22, 0xC6, 0xE3, 0x43, 0xE9, 0xC8, 0x8C, 0xB3, - 0xE3, 0xB2, 0xF3, 0x92, 0x8F, 0xD7, 0x0C, 0xD9, 0x20, 0xBA, 0xE9, 0x53, 0x1B, 0xA9, 0xB2, 0x81, - 0x81, 0xA5, 0xFC, 0x3C, 0x26, 0x89, 0x1B, 0xC0, 0x21, 0xF9, 0x96, 0x67, 0x15, 0x84, 0x91, 0x30, - 0xC0, 0x94, 0xBB, 0x98, 0xF4, 0x12, 0xDC, 0x3F, 0x2C, 0x51, 0x73, 0xF6, 0xC6, 0x55, 0x25, 0xE3, - 0x28, 0xE3, 0xDC, 0x33, 0x73, 0xBF, 0x22, 0xD6, 0x65, 0xC9, 0x69, 0xE0, 0xCC, 0x1F, 0x87, 0x98, - 0xA6, 0x03, 0x57, 0x74, 0x8D, 0x75, 0x44, 0xF1, 0x2F, 0x8C, 0x7D, 0xD6, 0x57, 0xB2, 0x34, 0xBF, - 0x24, 0xE8, 0xF1, 0x41, 0x48, 0x3C, 0x24, 0xFD, 0xC9, 0x62, 0xDC, 0xEC, 0xD9, 0xA2, 0x1B, 0x84, - 0x2D, 0x94, 0x55, 0x20, 0x46, 0x2F, 0x64, 0x0A, 0x7E, 0x34, 0xD4, 0xEE, 0x44, 0xE7, 0xAE, 0x9D, - 0x1B, 0x9F, 0x5E, 0xE3, 0xCB, 0xAA, 0x51, 0xB5, 0xE8, 0xB6, 0x66, 0x4C, 0x0B, 0x1F, 0xB5, 0xCF, - 0xE8, 0xFD, 0x68, 0xA5, 0x23, 0x1D, 0x29, 0x25, 0x03, 0xBD, 0x6A, 0x3F, 0x65, 0xA5, 0x92, 0xC4, - 0x2D, 0xA1, 0x04, 0xAB, 0x92, 0x4C, 0xD2, 0x4D, 0xA5, 0x92, 0x4C, 0x2A, 0x62, 0x3A, 0xC9, 0x64, - 0x30, 0x45, 0x8B, 0x91, 0x78, 0x91, 0x97, 0x5C, 0x42, 0xDC, 0x2D, 0xD0, 0x70, 0xAA, 0x26, 0x39, - 0x5D, 0x94, 0x7E, 0x3F, 0xCB, 0x3A, 0x11, 0x4F, 0xF5, 0x7B, 0xB4, 0x65, 0x03, 0xFD, 0xCD, 0x18, - 0x0B, 0xC4, 0xD1, 0x78, 0x6A, 0xBE, 0x95, 0x35, 0x4B, 0xDF, 0x9F, 0x93, 0x8D, 0xAC, 0x01, 0xB9, - 0xF1, 0x39, 0xD2, 0xF2, 0x9A, 0xF9, 0x3D, 0xA5, 0x90, 0xAC, 0x2D, 0x8D, 0xDD, 0xD2, 0xD3, 0x6A, - 0xEE, 0xBC, 0x1A, 0x33, 0x52, 0x3C, 0x9B, 0x4A, 0x6D, 0x5F, 0x5F, 0x3F, 0xA7, 0xD7, 0x30, 0x7D, - 0xDE, 0xF0, 0x4C, 0xC2, 0x71, 0xD0, 0x50, 0xEE, 0x62, 0x52, 0xD9, 0x1B, 0xD9, 0xD5, 0x2E, 0x88, - 0xF2, 0xA4, 0xBE, 0x9A, 0xC6, 0x4B, 0x69, 0x8A, 0xF1, 0xD7, 0xDE, 0x42, 0x32, 0x13, 0x73, 0x4C, - 0x35, 0x93, 0x11, 0x73, 0x46, 0x0D, 0x17, 0x9F, 0x61, 0x62, 0x1F, 0xF9, 0x98, 0x28, 0xBB, 0x4D, - 0xA2, 0x5F, 0xDF, 0xC3, 0x5C, 0x3E, 0xA6, 0xBE, 0x2A, 0x58, 0x86, 0x25, 0x0D, 0xCE, 0x2C, 0x4C, - 0x1B, 0xAC, 0x0B, 0xCF, 0xE9, 0x5B, 0x05, 0x94, 0x1F, 0x35, 0xB4, 0xF9, 0x91, 0x43, 0x15, 0x40, - 0xEB, 0xCA, 0xF3, 0x43, 0x00, 0x64, 0xFF, 0xCF, 0x06, 0xCC, 0xC8, 0xBF, 0x3C, 0xCE, 0xCF, 0xBD, - 0x2C, 0x25, 0xB0, 0xD7, 0xE4, 0x11, 0x65, 0xCA, 0x4D, 0xBA, 0x79, 0x4A, 0xFD, 0x21, 0xBF, 0xFD, - 0xCA, 0xCB, 0x3A, 0x63, 0x96, 0x55, 0x97, 0xAC, 0x13, 0xFE, 0x67, 0xE8, 0x85, 0xB8, 0xCB, 0xF7, - 0x17, 0x3C, 0xB8, 0x97, 0x12, 0x0E, 0x0B, 0xB4, 0x6F, 0x2C, 0x5F, 0x3A, 0x82, 0x3B, 0xB1, 0xC2, - 0x9B, 0x8E, 0xEF, 0xCD, 0x80, 0x1B, 0x81, 0x76, 0x25, 0x01, 0x99, 0x49, 0x29, 0x9B, 0x35, 0x2F, - 0xD8, 0x00, 0x87, 0x83, 0xEE, 0x7F, 0x0B, 0xD5, 0xA4, 0x36, 0x4F, 0x04, 0x1D, 0x6F, 0xF8, 0x0A, - 0x96, 0x5F, 0xE3, 0xA3, 0x09, 0xDD, 0xD4, 0xDB, 0x2F, 0xD9, 0x74, 0x1A, 0x67, 0x49, 0x6E, 0xE9, - 0x36, 0xB9, 0xC3, 0x0B, 0x56, 0xEE, 0x88, 0x2B, 0x3A, 0xB8, 0x9A, 0x4C, 0xBB, 0xEF, 0xA1, 0x83, - 0x26, 0x0D, 0xC3, 0x7B, 0x9E, 0x9A, 0x76, 0xA8, 0x82, 0x2C, 0xA2, 0xCB, 0x93, 0x46, 0x93, 0x38, - 0x6B, 0x74, 0x91, 0x20, 0xA3, 0x63, 0xA1, 0x45, 0x0C, 0x75, 0xF6, 0x2D, 0x36, 0xE7, 0x98, 0xF3, - 0x99, 0x1F, 0x3C, 0xBC, 0xB9, 0x3F, 0xB6, 0xAB, 0x72, 0x2D, 0xC9, 0x43, 0xD6, 0xF8, 0x5A, 0xC2, - 0x78, 0x6B, 0x01, 0x93, 0xB6, 0x8A, 0x54, 0x1E, 0x0D, 0xB5, 0x90, 0xEE, 0x23, 0x02, 0x81, 0x35, - 0x41, 0x1B, 0x0E, 0x45, 0xBE, 0xC4, 0x37, 0x38, 0x83, 0x2A, 0xAE, 0x4D, 0x72, 0x8B, 0xFF, 0x62, - 0x58, 0x2A, 0x8F, 0x23, 0x3F, 0xFF, 0x8A, 0x31, 0xAA, 0x91, 0xA6, 0xC6, 0x4D, 0x3E, 0x7E, 0x60, - 0x97, 0x01, 0x11, 0xB5, 0x2D, 0x2E, 0xC6, 0xBC, 0x78, 0xF2, 0xE3, 0x1E, 0x3B, 0x9B, 0x2F, 0x4C, - 0x33, 0x39, 0xD4, 0xE7, 0x89, 0x2F, 0x0B, 0x9A, 0x54, 0x26, 0x21, 0x67, 0xDC, 0x24, 0x53, 0x2A, - 0xCD, 0xFC, 0x26, 0x65, 0x25, 0xDF, 0x1C, 0xC9, 0xC5, 0x25, 0x9B, 0x34, 0xB3, 0xA7, 0x79, 0x8D, - 0xF9, 0x64, 0x57, 0x68, 0xCC, 0xCC, 0xCE, 0xC8, 0x98, 0x97, 0xD3, 0x9C, 0x4C, 0x98, 0x58, 0xFF, - 0x6C, 0x73, 0x83, 0x7A, 0xDD, 0x5E, 0xAF, 0x6B, 0x6A, 0x91, 0x7D, 0x33, 0x9C, 0x1E, 0xC1, 0x9A, - 0xD1, 0x77, 0x69, 0x98, 0x6E, 0x95, 0x28, 0x38, 0x7C, 0x7F, 0x70, 0x96, 0xDF, 0x24, 0x29, 0x29, - 0xF4, 0xF1, 0x99, 0xCA, 0x62, 0x84, 0x3D, 0xB7, 0x79, 0x52, 0xB2, 0xE6, 0x62, 0x78, 0x99, 0x7F, - 0x28, 0xC0, 0xAB, 0xDC, 0x2C, 0x8A, 0x59, 0xF5, 0x86, 0xB5, 0x30, 0x77, 0xFC, 0x76, 0xE7, 0x5C, - 0x3B, 0xA7, 0x1C, 0xA0, 0xF4, 0x83, 0xF3, 0x12, 0xCC, 0xD7, 0x26, 0xF9, 0xE9, 0x27, 0x12, 0x97, - 0xFD, 0x79, 0x6F, 0x30, 0xD0, 0x9D, 0x67, 0xCD, 0xDF, 0x93, 0x09, 0x66, 0xB9, 0x7B, 0x28, 0x6C, - 0xB9, 0x1E, 0x7A, 0x74, 0xAC, 0xDB, 0xE2, 0xF3, 0x42, 0xD2, 0x5D, 0xD1, 0xE2, 0x0B, 0xA0, 0x69, - 0xB8, 0x36, 0x90, 0x3C, 0xAE, 0xE8, 0xC8, 0x89, 0x95, 0x69, 0xDE, 0x13, 0xEB, 0xB7, 0x53, 0x7A, - 0x17, 0x25, 0x30, 0x52, 0xFA, 0x59, 0xCF, 0x8A, 0xF2, 0xA7, 0xF8, 0xE9, 0x33, 0x68, 0x6B, 0x4B, - 0x13, 0x2F, 0x3B, 0xE8, 0xD7, 0x55, 0xF9, 0x24, 0x18, 0xF1, 0xB0, 0x89, 0x66, 0xF4, 0x00, 0xC1, - 0x81, 0x20, 0x08, 0x25, 0xF8, 0xC2, 0xC5, 0x2F, 0xCE, 0x5B, 0x87, 0x4D, 0x0C, 0x78, 0xAD, 0x9B, - 0x4E, 0xA6, 0xE1, 0xBD, 0xAC, 0xB6, 0x06, 0xD7, 0x59, 0x64, 0x45, 0x3B, 0xD0, 0xF8, 0xCE, 0x0A, - 0x2F, 0x14, 0x4C, 0x64, 0xD2, 0x07, 0x3D, 0x72, 0xF1, 0xD2, 0x32, 0x4C, 0xA4, 0x30, 0x87, 0x8A, - 0x26, 0x35, 0xB4, 0x27, 0x62, 0x50, 0x3F, 0xC4, 0x7B, 0x00, 0xB8, 0xBD, 0x23, 0x9D, 0x07, 0xC1, - 0x72, 0x14, 0x9C, 0x17, 0x32, 0x9C, 0xF9, 0x3E, 0x4E, 0xE9, 0xAC, 0x35, 0xD8, 0xF3, 0x6C, 0x2F, - 0xE6, 0xEC, 0x97, 0x20, 0x51, 0xB9, 0x71, 0x20, 0x26, 0xAE, 0x7A, 0xDA, 0x95, 0xA3, 0x48, 0x12, - 0xEA, 0x2C, 0x3D, 0x92, 0x98, 0x5F, 0xDD, 0x93, 0x01, 0x92, 0x25, 0x42, 0x1B, 0x97, 0x0F, 0x5A, - 0x49, 0x14, 0x2E, 0x0D, 0x85, 0x4A, 0x1F, 0xA8, 0x96, 0xED, 0xFC, 0x40, 0xEA, 0x04, 0xDD, 0x0E, - 0x64, 0xB0, 0x90, 0x02, 0x6D, 0x63, 0xED, 0x88, 0x0C, 0x1A, 0x80, 0xD2, 0x80, 0xAC, 0xA7, 0xDA, - 0x51, 0x87, 0x68, 0xB5, 0x75, 0xF5, 0xC6, 0x27, 0x1A, 0xA2, 0x5B, 0x29, 0xF2, 0x86, 0x4C, 0x54, - 0xCE, 0x36, 0x10, 0x00, 0x5E, 0xEC, 0xC9, 0xC4, 0xC8, 0x56, 0x8C, 0xAF, 0x3F, 0x28, 0xE5, 0xC9, - 0x5D, 0x0D, 0x89, 0x9E, 0xF1, 0x3D, 0x9E, 0x14, 0x53, 0xA6, 0x57, 0x79, 0x58, 0x25, 0x40, 0x6E, - 0x1A, 0x9B, 0xCA, 0xAB, 0x32, 0x19, 0x24, 0x57, 0xD2, 0x7B, 0x0E, 0x8D, 0x03, 0x84, 0x63, 0xAA, - 0x2E, 0xD8, 0x42, 0x75, 0xCA, 0x80, 0x8F, 0x6F, 0x83, 0x14, 0x8E, 0x20, 0xC1, 0x68, 0xFC, 0x0E, - 0x09, 0x81, 0x29, 0x26, 0x60, 0xC1, 0x15, 0xBB, 0x9A, 0x39, 0x8E, 0x69, 0xFC, 0xCC, 0x6B, 0xB4, - 0xAE, 0xD5, 0xBF, 0x95, 0xF6, 0x65, 0xD2, 0x94, 0xDE, 0x66, 0xD4, 0xE0, 0xF9, 0xDB, 0x8C, 0xE7, - 0xE7, 0x1F, 0xCF, 0x1B, 0x95, 0x0D, 0x91, 0x18, 0x69, 0x04, 0x24, 0xC2, 0x67, 0x49, 0x96, 0xBB, - 0xC3, 0xBA, 0x05, 0x37, 0x8F, 0x1F, 0x91, 0xEE, 0x6A, 0x13, 0x9A, 0xED, 0xDC, 0xBE, 0xA3, 0xA1, - 0x62, 0x82, 0xD4, 0xF9, 0xB6, 0xD0, 0x4A, 0x69, 0x5B, 0x89, 0xAA, 0xB1, 0x53, 0x76, 0x33, 0x4D, - 0xED, 0x3C, 0xF8, 0x74, 0x7E, 0x7E, 0x74, 0x7A, 0x61, 0x6A, 0x69, 0x66, 0x23, 0x63, 0x35, 0x07, - 0x63, 0x3B, 0x9B, 0xA2, 0xC5, 0xE3, 0x69, 0xF4, 0x1E, 0xB9, 0x6D, 0xB2, 0x21, 0xD7, 0xE9, 0xE8, - 0x7E, 0x31, 0x8B, 0x66, 0x03, 0x46, 0x6F, 0x1B, 0xEC, 0xAE, 0x87, 0x22, 0x87, 0xDD, 0x5C, 0x44, - 0x66, 0x6E, 0xD4, 0x27, 0x76, 0x10, 0xFB, 0x59, 0xD6, 0x1A, 0xC6, 0xAC, 0x8A, 0x2A, 0x90, 0xA4, - 0x90, 0x22, 0x35, 0xB6, 0x49, 0x74, 0xDA, 0x49, 0x8E, 0x3E, 0xA6, 0x9F, 0xCE, 0x84, 0xFB, 0xE3, - 0xBB, 0xDF, 0x38, 0x8B, 0x97, 0x32, 0x08, 0x29, 0xE5, 0x4F, 0xF7, 0x14, 0xB4, 0xFF, 0x9D, 0x78, - 0xD7, 0x07, 0x37, 0x6B, 0xAE, 0xA5, 0xE6, 0xFD, 0x31, 0xD1, 0xAB, 0x13, 0xBD, 0x61, 0x32, 0x55, - 0x35, 0x77, 0xD9, 0x53, 0xA9, 0x4A, 0xCD, 0x38, 0x91, 0x6A, 0x0C, 0x99, 0xA6, 0xD1, 0x11, 0xC7, - 0x2B, 0x8F, 0x38, 0x29, 0xEC, 0x2B, 0xBA, 0x37, 0x81, 0xF6, 0xB4, 0xD7, 0xC8, 0x7C, 0xB8, 0xCD, - 0xC8, 0xCA, 0x8A, 0xD1, 0x52, 0x47, 0xD8, 0xD2, 0xB3, 0xD0, 0x92, 0x86, 0x56, 0x91, 0xC9, 0x67, - 0xD6, 0x20, 0x12, 0x83, 0xAA, 0xF5, 0xCA, 0x3B, 0x8A, 0xEA, 0xD2, 0xC9, 0x0B, 0xAD, 0x88, 0xBA, - 0x78, 0xA5, 0x4C, 0xEC, 0x5A, 0x45, 0xBB, 0x29, 0x46, 0x57, 0x24, 0x4B, 0x4E, 0xE5, 0x87, 0xA7, - 0x46, 0x85, 0x6F, 0xA3, 0xE9, 0xAF, 0x95, 0x95, 0x35, 0xE1, 0x1A, 0x32, 0x69, 0x73, 0x5F, 0x27, - 0xB3, 0x97, 0xDA, 0x8A, 0xD3, 0x1E, 0x45, 0x54, 0x92, 0x25, 0xBC, 0x73, 0x6E, 0xA9, 0x4B, 0x2C, - 0x7C, 0x5D, 0xD3, 0x6F, 0x06, 0x22, 0xBF, 0x17, 0x0A, 0xF3, 0x1E, 0x27, 0x2A, 0xE8, 0x66, 0x37, - 0x74, 0xAE, 0x79, 0x96, 0x2D, 0x8C, 0x6A, 0x63, 0x26, 0x42, 0xAC, 0xC1, 0xF0, 0x5B, 0x12, 0xB0, - 0x4C, 0x1C, 0x97, 0x1C, 0x1E, 0x76, 0xEC, 0xE8, 0x87, 0x6D, 0x38, 0x5B, 0x52, 0x90, 0x76, 0x84, - 0xEB, 0x18, 0x6D, 0x05, 0x3E, 0x88, 0xD3, 0x42, 0x9A, 0x47, 0x2E, 0x90, 0x52, 0xD7, 0xB3, 0x11, - 0xC6, 0xB8, 0x22, 0x34, 0x5F, 0x7D, 0x4A, 0x27, 0xE8, 0x1C, 0x7C, 0xFC, 0x78, 0x7E, 0x78, 0x7C, - 0xBA, 0x7F, 0x71, 0x74, 0x79, 0x7C, 0x7A, 0xF6, 0xE9, 0xE2, 0xF2, 0xE2, 0xF3, 0x19, 0xFE, 0xFA, - 0xF3, 0xFE, 0x87, 0xE3, 0xC3, 0xCB, 0x4F, 0xA7, 0x7F, 0x3D, 0xFD, 0xF8, 0xCB, 0x69, 0xB2, 0xA9, - 0x6D, 0x5B, 0xC1, 0x8D, 0x74, 0x1F, 0x3C, 0x36, 0x8F, 0x18, 0x50, 0x6E, 0xF8, 0x6E, 0xD3, 0xA1, - 0x33, 0xB1, 0xC6, 0x86, 0x12, 0x6E, 0xAA, 0x3E, 0x5E, 0x7F, 0xA0, 0xEC, 0x89, 0x3C, 0xFD, 0x74, - 0x0F, 0x8C, 0x07, 0x78, 0x5B, 0x21, 0xBE, 0xC4, 0x14, 0xCB, 0x85, 0xBF, 0x07, 0x83, 0x37, 0x8D, - 0x51, 0xBD, 0xC8, 0xDD, 0x8D, 0xC5, 0xA6, 0xAB, 0x11, 0x13, 0x3C, 0xC8, 0x78, 0x16, 0xC4, 0x56, - 0x79, 0x68, 0xB9, 0x84, 0xA2, 0x40, 0x98, 0xC9, 0x74, 0x5C, 0xE8, 0x7C, 0xC7, 0x66, 0x77, 0xC6, - 0x03, 0x51, 0x65, 0x9F, 0xF0, 0x6F, 0xBC, 0x16, 0xBE, 0x29, 0xC9, 0xB2, 0xBC, 0xF1, 0x73, 0xC0, - 0xA0, 0x4D, 0xD6, 0xDA, 0x18, 0x4D, 0xDA, 0x66, 0xDD, 0xD4, 0x51, 0xCF, 0xBA, 0x24, 0xE3, 0x1B, - 0x0B, 0x5E, 0x37, 0xBD, 0xEA, 0x25, 0xD9, 0xC0, 0x76, 0x46, 0x4E, 0x98, 0x74, 0x13, 0x1E, 0xE2, - 0x66, 0x5D, 0x98, 0x44, 0x00, 0x55, 0x6C, 0x2C, 0x56, 0xDE, 0x28, 0xAF, 0xD5, 0xD5, 0xBC, 0x37, - 0x33, 0x64, 0x72, 0x88, 0xA5, 0xB9, 0xD6, 0x5C, 0x49, 0x3A, 0x70, 0x75, 0x15, 0x45, 0x89, 0x8F, - 0xF0, 0x8D, 0x3C, 0xCF, 0x2E, 0x01, 0x4D, 0x00, 0x3A, 0xE9, 0xE7, 0xCA, 0xE0, 0x1D, 0x24, 0x2E, - 0xB5, 0x2B, 0x0F, 0x41, 0xB4, 0x37, 0x51, 0x4B, 0x59, 0xC5, 0x79, 0x30, 0x5B, 0xD2, 0x80, 0x1A, - 0x61, 0x58, 0x4B, 0xA0, 0xA8, 0x00, 0x4B, 0x1B, 0xA0, 0x1E, 0x3E, 0x81, 0x77, 0x8F, 0x4A, 0x34, - 0xF5, 0x82, 0xC0, 0xC1, 0x68, 0x57, 0xAE, 0x15, 0x38, 0x4E, 0x23, 0x7D, 0x49, 0x86, 0x64, 0xF2, - 0xE1, 0xE4, 0xA4, 0x33, 0xE1, 0x3F, 0xC9, 0x37, 0x62, 0xFA, 0xB8, 0x66, 0xFA, 0x78, 0x72, 0x32, - 0x18, 0x74, 0x02, 0xF6, 0xA3, 0x80, 0x13, 0xC3, 0x67, 0x40, 0xB0, 0x96, 0x7C, 0x7E, 0x66, 0xD4, - 0x13, 0x76, 0x47, 0x6B, 0x7E, 0xC9, 0xFD, 0x5F, 0x0C, 0x01, 0x76, 0xBD, 0x0E, 0xD9, 0x84, 0xD1, - 0xB6, 0xD3, 0xDD, 0xD8, 0xD8, 0x7C, 0xCE, 0xB2, 0xEB, 0x31, 0xF9, 0x75, 0x92, 0xF8, 0xE3, 0x64, - 0xC4, 0xBF, 0x26, 0xFD, 0x45, 0x10, 0xFE, 0x88, 0xE3, 0xAF, 0xCB, 0x32, 0x3E, 0xC0, 0x48, 0xEB, - 0x13, 0x6B, 0x8C, 0x39, 0x07, 0x6D, 0x64, 0x84, 0x74, 0xB7, 0x48, 0x7F, 0xAB, 0xD3, 0xEF, 0x6E, - 0xEE, 0x18, 0x58, 0x49, 0x6C, 0xD2, 0x6B, 0xB2, 0xB1, 0x60, 0x4E, 0xFA, 0x8C, 0x99, 0x8D, 0x84, - 0x99, 0xB5, 0x5E, 0x77, 0x6B, 0xAD, 0xD7, 0x5B, 0xEB, 0x6E, 0x75, 0x7A, 0xDB, 0x7D, 0x13, 0x3B, - 0x66, 0xCB, 0xF6, 0x1A, 0x43, 0xF8, 0x17, 0xC4, 0xDA, 0x73, 0xE4, 0xE9, 0x9A, 0xDE, 0x51, 0x9F, - 0xF3, 0xD3, 0xEB, 0x21, 0x37, 0x2F, 0x5E, 0xEC, 0xEC, 0xF4, 0x49, 0xEB, 0x90, 0x6B, 0x16, 0x56, - 0xE1, 0xBF, 0xAD, 0xC4, 0x3C, 0x26, 0xEE, 0xAC, 0x4B, 0x47, 0x56, 0x08, 0x76, 0x73, 0xE0, 0x8C, - 0x5C, 0xD5, 0x7B, 0x50, 0xC7, 0x6E, 0x37, 0x31, 0x1C, 0x89, 0x95, 0x8A, 0x8B, 0xB9, 0xDF, 0x85, - 0x61, 0xF3, 0xFB, 0x92, 0x71, 0x6B, 0xA3, 0xE8, 0x30, 0xB2, 0x9D, 0x9D, 0xF4, 0x60, 0x6C, 0x3D, - 0x18, 0x2F, 0x26, 0x0A, 0x6E, 0x3E, 0x92, 0x9B, 0x34, 0x2A, 0x13, 0x6A, 0x14, 0x4F, 0xDC, 0xA9, - 0x6B, 0x6B, 0x88, 0x08, 0xD3, 0x64, 0x26, 0xFD, 0x0C, 0xD6, 0x1A, 0xE7, 0x4C, 0xC7, 0xE5, 0xCF, - 0x5D, 0xB0, 0x12, 0xCA, 0x2D, 0x38, 0xCF, 0xAE, 0xC9, 0x12, 0x4F, 0x08, 0xA2, 0x11, 0x19, 0x12, - 0x00, 0x1D, 0x7D, 0xC3, 0x4A, 0xD6, 0x63, 0x6E, 0x68, 0x71, 0x4D, 0x25, 0xCD, 0x72, 0xF1, 0xB7, - 0x8C, 0x7E, 0xDD, 0x63, 0x77, 0x33, 0xF0, 0x75, 0xB7, 0xCC, 0xF2, 0xED, 0x15, 0x58, 0x90, 0xAD, - 0xAF, 0xA7, 0x47, 0xBC, 0xFC, 0x46, 0x6F, 0xFD, 0xB9, 0x9A, 0xE3, 0x95, 0x4E, 0xE5, 0x79, 0x92, - 0x0D, 0x76, 0xE8, 0xC2, 0x2F, 0xE9, 0xB0, 0xA3, 0x48, 0x10, 0xAF, 0x3B, 0x8C, 0xEE, 0x3E, 0x27, - 0x0E, 0x03, 0xEB, 0x26, 0x70, 0x3E, 0x89, 0xD0, 0x1B, 0x05, 0x8B, 0xB0, 0x2F, 0x2A, 0x0A, 0x09, - 0x35, 0xBF, 0xF9, 0xDC, 0x95, 0x71, 0x24, 0x13, 0x5F, 0x52, 0x6D, 0x6D, 0x2F, 0x36, 0x55, 0xFC, - 0xCC, 0x55, 0xB9, 0x2D, 0xCD, 0x12, 0xF5, 0x3A, 0xEE, 0x2C, 0x64, 0x31, 0x1A, 0x39, 0x84, 0x62, - 0x32, 0x27, 0x27, 0x72, 0x10, 0xDC, 0x5B, 0x07, 0xA6, 0x68, 0x98, 0x5E, 0x94, 0x29, 0x37, 0x99, - 0x98, 0xD9, 0xD5, 0xA1, 0x8F, 0xD7, 0x2D, 0x36, 0x01, 0x41, 0x6F, 0xAC, 0xF5, 0xF4, 0xBD, 0xF1, - 0x79, 0x45, 0x7F, 0x79, 0xFA, 0xF1, 0xF2, 0xF0, 0xE8, 0xE0, 0xF8, 0x64, 0xFF, 0x83, 0xD6, 0x0B, - 0x01, 0x85, 0x09, 0xC8, 0xC6, 0x66, 0xC5, 0xFC, 0x68, 0xE2, 0x96, 0xD5, 0x81, 0x2F, 0xAE, 0x38, - 0x84, 0x51, 0x64, 0xC9, 0x80, 0x92, 0x05, 0x2D, 0x83, 0x44, 0x72, 0xFC, 0x4B, 0x2C, 0x2F, 0x01, - 0x00, 0x22, 0x93, 0x62, 0xCE, 0x0C, 0xAE, 0x55, 0x44, 0x6C, 0x35, 0x41, 0xB2, 0x4E, 0xB6, 0x61, - 0x0A, 0x60, 0x57, 0xE6, 0x23, 0x1A, 0xEB, 0x64, 0x63, 0x1B, 0x73, 0xC5, 0xAC, 0x68, 0x77, 0xBE, - 0x95, 0x91, 0x6C, 0xF6, 0x6B, 0x4C, 0x64, 0xFF, 0x82, 0xDD, 0x21, 0xBF, 0xF1, 0xF7, 0x60, 0x5A, - 0x3D, 0x69, 0x43, 0x14, 0x47, 0xA3, 0x3A, 0x40, 0xD9, 0xF8, 0xCC, 0x1C, 0x7E, 0x5B, 0x38, 0x3A, - 0x33, 0x4B, 0x37, 0xE3, 0xB1, 0xA9, 0xCC, 0xD0, 0x8B, 0x1B, 0x9A, 0x25, 0x07, 0x66, 0x32, 0x22, - 0x15, 0x0D, 0xC9, 0x18, 0x8E, 0xFA, 0xD0, 0xA8, 0x3A, 0x00, 0x33, 0x87, 0x9F, 0x59, 0x4F, 0x15, - 0xD1, 0xB0, 0xB0, 0x5E, 0x01, 0x60, 0x40, 0x6C, 0x56, 0xD2, 0xAA, 0x4A, 0xB7, 0x64, 0xFD, 0x52, - 0x15, 0x4C, 0xD1, 0xA6, 0x1E, 0xD7, 0x87, 0xB5, 0x25, 0x29, 0xC4, 0xE5, 0xC9, 0xC9, 0xE5, 0xE1, - 0xFE, 0xE0, 0xBD, 0xA6, 0x16, 0x22, 0xDE, 0x28, 0x31, 0x5B, 0xE2, 0xAE, 0xD8, 0x9A, 0x7E, 0x97, - 0x30, 0xD1, 0x01, 0x61, 0xCA, 0x11, 0x12, 0xB3, 0x13, 0x25, 0x1D, 0x96, 0xD1, 0xB5, 0x72, 0xFD, - 0xDE, 0x57, 0xC9, 0x98, 0xA6, 0x7A, 0xF7, 0x89, 0x75, 0x56, 0x76, 0x5F, 0xF5, 0xE3, 0xBE, 0x8A, - 0xBC, 0xE3, 0x85, 0xF7, 0x15, 0x98, 0xF7, 0x27, 0xD6, 0x5D, 0x4F, 0x66, 0xEE, 0x93, 0xC4, 0x53, - 0x66, 0x0A, 0x94, 0x1B, 0xD4, 0x4F, 0x1A, 0x94, 0x9E, 0x03, 0xFF, 0xD1, 0x27, 0x28, 0xAE, 0x94, - 0xC9, 0x06, 0xCE, 0x42, 0x75, 0x72, 0xB7, 0x40, 0x4C, 0x89, 0x01, 0xFF, 0x61, 0x02, 0x10, 0x16, - 0x94, 0x2C, 0xCF, 0x82, 0x96, 0x1C, 0x8D, 0xE4, 0x0F, 0xE3, 0x99, 0xD7, 0x4F, 0xFD, 0xB8, 0x9F, - 0xC8, 0x72, 0xD6, 0x25, 0xDC, 0x40, 0x3C, 0xA1, 0xCE, 0x7A, 0x6A, 0xA6, 0xF3, 0x7F, 0x9A, 0xD5, - 0x14, 0x1B, 0x5A, 0xCA, 0xC9, 0x90, 0x01, 0x01, 0x3F, 0x1C, 0x32, 0x14, 0xC4, 0xB9, 0xB3, 0x76, - 0x56, 0xB4, 0x8B, 0xF3, 0x86, 0xEE, 0xE0, 0x67, 0x3E, 0xC9, 0xC6, 0xBC, 0xB4, 0xC3, 0x8E, 0x9B, - 0xBA, 0xC9, 0x05, 0xF3, 0x36, 0xF1, 0x66, 0x21, 0xFE, 0x61, 0x89, 0x5D, 0x7B, 0x00, 0x1A, 0x78, - 0xEA, 0x1E, 0x3C, 0x6E, 0x28, 0x5F, 0x81, 0xB4, 0x26, 0x94, 0x34, 0xB5, 0x21, 0xD3, 0x6C, 0x13, - 0x1A, 0x0E, 0xE5, 0xA0, 0x5A, 0xC6, 0x37, 0xE3, 0x43, 0xE2, 0xAB, 0x6D, 0x52, 0x19, 0xF3, 0x7E, - 0xBD, 0xD8, 0xBC, 0x94, 0x0E, 0x1A, 0xF9, 0xDD, 0x03, 0x83, 0xC6, 0x95, 0x57, 0xB9, 0x15, 0xE3, - 0xB0, 0x4E, 0x34, 0x2C, 0xF9, 0xB6, 0x22, 0x89, 0x59, 0x3F, 0xAD, 0x95, 0xD9, 0x30, 0x9F, 0x75, - 0xCD, 0xC9, 0xE6, 0xA5, 0xB4, 0xE6, 0x81, 0x75, 0xDB, 0x9C, 0xD8, 0x16, 0x8A, 0x2C, 0x72, 0xDD, - 0x17, 0x8C, 0x72, 0xF0, 0xF9, 0xE4, 0xCD, 0xC7, 0x0F, 0x0C, 0xA9, 0x7E, 0xA9, 0x63, 0xEC, 0xB9, - 0x23, 0x96, 0xA5, 0xE8, 0x90, 0x8E, 0x7C, 0xAA, 0xEF, 0x8F, 0xA4, 0x7A, 0x42, 0xEB, 0x5A, 0x58, - 0x9C, 0xE9, 0x08, 0x8C, 0xF5, 0x60, 0xB8, 0x6E, 0x77, 0x77, 0xB5, 0xCC, 0x8F, 0x71, 0xE9, 0x2B, - 0x92, 0x69, 0xF9, 0xF8, 0x40, 0x97, 0x4C, 0x97, 0xA2, 0x57, 0xC3, 0xF4, 0xB0, 0x7D, 0xBE, 0x92, - 0xCA, 0x30, 0x39, 0x67, 0xF7, 0x66, 0xB1, 0x16, 0x0F, 0xA1, 0x94, 0x08, 0x57, 0x61, 0x54, 0x31, - 0xEB, 0x12, 0x55, 0xDD, 0x4D, 0x1F, 0x5E, 0x2C, 0x48, 0x51, 0x6A, 0x31, 0xB7, 0xF6, 0x18, 0xDC, - 0x71, 0x9D, 0xAB, 0xC5, 0xDF, 0x7F, 0xFF, 0x97, 0xCA, 0x20, 0x7E, 0x6B, 0x36, 0x54, 0x36, 0xEB, - 0xE0, 0x25, 0xA6, 0x76, 0x6B, 0xB6, 0x65, 0x21, 0x4D, 0x1F, 0xAC, 0xC8, 0x03, 0x78, 0x7E, 0x15, - 0x5C, 0x30, 0x42, 0x69, 0x55, 0xB5, 0x0C, 0xBC, 0x7A, 0xCF, 0x2F, 0x48, 0x04, 0x92, 0x2B, 0xB3, - 0x0C, 0xAE, 0x97, 0x8B, 0x5D, 0x5B, 0xC1, 0xAE, 0xFC, 0xA3, 0x9B, 0x61, 0x85, 0xE7, 0x13, 0xD3, - 0xD6, 0x7A, 0x15, 0x9E, 0x05, 0x82, 0x3C, 0x9E, 0x4B, 0x4F, 0x00, 0xDB, 0x0B, 0x9F, 0x00, 0xE4, - 0xD1, 0x57, 0x71, 0x0A, 0x48, 0x89, 0xE8, 0x91, 0xA6, 0x86, 0xD4, 0xE8, 0xAE, 0x3A, 0x3B, 0x98, - 0x18, 0x5F, 0x7B, 0x24, 0xCE, 0xE7, 0x9E, 0x39, 0x4C, 0xCC, 0x37, 0xD3, 0x53, 0xCA, 0xDF, 0x1A, - 0x8D, 0x65, 0xB5, 0x61, 0xA5, 0xF6, 0xF4, 0x64, 0xE2, 0x9D, 0x2C, 0x5B, 0xF0, 0x99, 0xE6, 0x75, - 0x41, 0xEA, 0x2E, 0x5D, 0x54, 0x34, 0x9A, 0x85, 0x05, 0x2B, 0xD0, 0x9C, 0x2D, 0xC9, 0xEF, 0x87, - 0x47, 0x6E, 0x8B, 0x3E, 0x71, 0x2C, 0x7E, 0x44, 0xE7, 0x35, 0x28, 0x75, 0x91, 0x47, 0xA5, 0xA7, - 0xC5, 0x3C, 0x46, 0x41, 0x48, 0x43, 0x7C, 0x32, 0x51, 0xC0, 0xAC, 0xFF, 0xCD, 0x5E, 0xEF, 0x84, - 0x78, 0x25, 0x79, 0xB8, 0xB2, 0x4B, 0xD4, 0x94, 0x09, 0xD1, 0xB9, 0x3E, 0x2C, 0x89, 0xDB, 0x3C, - 0xFF, 0x22, 0xAC, 0x60, 0x6F, 0x7C, 0x39, 0x48, 0x92, 0x27, 0x8F, 0x7C, 0x8D, 0xAB, 0xE6, 0xE8, - 0xEA, 0xD1, 0x9A, 0x14, 0x84, 0x02, 0x9F, 0x95, 0x45, 0x3A, 0x56, 0x53, 0xD2, 0x1E, 0x8A, 0xD4, - 0x92, 0xAB, 0x88, 0x17, 0xA3, 0x41, 0x95, 0x72, 0x8E, 0x7C, 0x95, 0x25, 0x89, 0x97, 0xD7, 0xF1, - 0xAE, 0xB2, 0x72, 0x17, 0xA8, 0x2D, 0x7C, 0xB1, 0xD2, 0xE5, 0x99, 0xEA, 0xC4, 0x1A, 0x5E, 0xBA, - 0x2D, 0x2C, 0x4A, 0x92, 0x78, 0xB9, 0x9C, 0x95, 0x78, 0x70, 0xE7, 0x84, 0xC3, 0x1B, 0x92, 0x57, - 0x85, 0x85, 0x27, 0xD0, 0x6B, 0x6B, 0x36, 0x0E, 0x5F, 0x6A, 0xB9, 0xEE, 0x79, 0x4F, 0x34, 0x3E, - 0xB9, 0xDF, 0x5C, 0xEF, 0xCE, 0xD5, 0x13, 0xC6, 0x6A, 0xEF, 0x2A, 0x0C, 0xF1, 0xDA, 0x6E, 0xAB, - 0xF4, 0xFA, 0x3D, 0x83, 0x96, 0xBC, 0x4D, 0xB1, 0x50, 0x82, 0xB0, 0xB8, 0xCA, 0x24, 0x99, 0xEC, - 0x7B, 0x2E, 0x94, 0xE4, 0x65, 0x1E, 0x4D, 0xB2, 0x3C, 0xA2, 0x7C, 0x3E, 0xCE, 0xA4, 0xBC, 0xB6, - 0x24, 0xCA, 0xCC, 0x7B, 0xC9, 0x91, 0x71, 0xBC, 0xC5, 0xB4, 0xF0, 0xF6, 0xE6, 0xD1, 0x55, 0x36, - 0xB7, 0x96, 0x40, 0xB9, 0x58, 0xD8, 0x6B, 0xCB, 0x21, 0xAF, 0x4F, 0xA4, 0xB9, 0x92, 0x5F, 0x46, - 0xC3, 0xCB, 0xD0, 0xE6, 0xD2, 0x5F, 0x96, 0xD8, 0x4B, 0xB1, 0xC0, 0x7B, 0x20, 0x87, 0x85, 0x87, - 0x67, 0x59, 0xD6, 0xEE, 0xE1, 0xFF, 0x03, 0x56, 0x33, 0x60, 0xED, 0x71, 0x8A, 0x00 + 0x56, 0x12, 0x24, 0x44, 0x9D, 0xF3, 0x8B, 0xFD, 0x93, 0x34, 0x22, 0x6C, 0xD1, 0x85, 0x75, 0x05, + 0x3F, 0xE8, 0xB7, 0x50, 0x62, 0x6F, 0xE0, 0xF9, 0x3E, 0x65, 0xAA, 0xA1, 0x15, 0x08, 0xBD, 0xD3, + 0xBE, 0xA2, 0xBC, 0x04, 0x9D, 0x8B, 0xFB, 0x09, 0xCD, 0x2E, 0x11, 0x5C, 0x62, 0x29, 0xE7, 0xD1, + 0xBA, 0x8D, 0x5B, 0x81, 0xC2, 0x46, 0x11, 0x7D, 0xFE, 0xB2, 0x93, 0x2A, 0xFB, 0xD9, 0x1A, 0x4D, + 0xD3, 0x85, 0xFB, 0x37, 0x74, 0xF0, 0xF5, 0xCA, 0xFB, 0x66, 0x84, 0x8C, 0x0A, 0x15, 0x50, 0x56, + 0x0C, 0x2D, 0xF3, 0x7C, 0x3B, 0x38, 0xDC, 0x3F, 0x7C, 0x2B, 0x01, 0x89, 0xAF, 0xEF, 0x84, 0x86, + 0x49, 0x25, 0xD7, 0xD3, 0xD1, 0xE8, 0x0C, 0x98, 0xF8, 0x38, 0x81, 0x01, 0x24, 0x09, 0x59, 0x80, + 0x05, 0x34, 0xBC, 0x70, 0xC6, 0xD4, 0x9B, 0x86, 0x51, 0x97, 0xBB, 0xF6, 0x01, 0x8C, 0x34, 0xE5, + 0xE3, 0x00, 0xB9, 0x39, 0xA5, 0x77, 0x6F, 0x1D, 0x7F, 0x7C, 0x67, 0xF9, 0x54, 0x29, 0x84, 0x11, + 0x66, 0x2A, 0x7A, 0x36, 0xF0, 0x5C, 0xE8, 0x30, 0xD0, 0xB0, 0xFD, 0xB8, 0x3B, 0x82, 0xBE, 0x37, + 0xF5, 0x07, 0xAC, 0x3D, 0x2F, 0xF4, 0xAE, 0x12, 0x65, 0xBA, 0x34, 0x52, 0x15, 0xCE, 0x7C, 0xC7, + 0xF3, 0x9D, 0xD0, 0x49, 0xA4, 0xC2, 0x09, 0xED, 0x7B, 0x20, 0x00, 0xC7, 0x85, 0x36, 0x62, 0x57, + 0x61, 0x21, 0x37, 0x08, 0xFB, 0x1F, 0x3E, 0x9C, 0x1F, 0x1C, 0x9D, 0xEE, 0x5D, 0x1C, 0x5E, 0x1E, + 0x9D, 0x9E, 0x7D, 0xBC, 0xB8, 0xBC, 0xF8, 0x74, 0x76, 0x78, 0x79, 0x70, 0xF0, 0x92, 0x74, 0x5A, + 0x64, 0x6D, 0xED, 0x80, 0x5E, 0x5B, 0x53, 0x18, 0x8F, 0x07, 0x07, 0x6D, 0x3B, 0xFA, 0x97, 0x0B, + 0x77, 0x72, 0xF2, 0x92, 0x74, 0x19, 0x24, 0xFC, 0xDA, 0x1E, 0xE3, 0xBF, 0xDC, 0xFA, 0x97, 0x08, + 0xD0, 0xE3, 0x00, 0xA4, 0x2C, 0xC4, 0xE5, 0xC1, 0x5E, 0xFF, 0xFD, 0x4B, 0xB2, 0xCE, 0xC1, 0x56, + 0x4B, 0x83, 0xF5, 0x3F, 0x9D, 0xBC, 0xF9, 0x70, 0xFC, 0x92, 0x6C, 0x70, 0xC0, 0xFF, 0xFE, 0xAF, + 0x08, 0x72, 0x3C, 0x6E, 0x16, 0xB4, 0xAA, 0xDF, 0x7F, 0x49, 0x36, 0x63, 0x36, 0x49, 0xBF, 0xDF, + 0x0E, 0xD8, 0xBF, 0x62, 0x9A, 0x00, 0xB8, 0x55, 0x0F, 0x50, 0x34, 0xF3, 0x79, 0xDC, 0xCC, 0xD5, + 0x4A, 0xD0, 0x51, 0x6B, 0x5F, 0x24, 0xAD, 0x6D, 0xC6, 0x08, 0x1A, 0x85, 0xED, 0xBD, 0x3C, 0xFD, + 0x70, 0x79, 0x70, 0xB8, 0x7F, 0x74, 0xB2, 0x07, 0x38, 0xB6, 0xA3, 0x2E, 0xED, 0xF7, 0xC9, 0x2A, + 0x39, 0xF5, 0x88, 0x4D, 0x07, 0xCE, 0xD8, 0x1A, 0x95, 0xE1, 0x43, 0xC6, 0xD3, 0xED, 0xC8, 0xA2, + 0xA8, 0x8C, 0x0A, 0x05, 0xA2, 0xE2, 0xEB, 0xCA, 0xC2, 0x29, 0x8B, 0xEF, 0xE8, 0xF4, 0xE7, 0xBD, + 0xE3, 0xA3, 0x83, 0xCB, 0x8F, 0xA7, 0x7F, 0x3B, 0xFD, 0xF0, 0xCB, 0x29, 0xA0, 0xE9, 0xB5, 0xA2, + 0x79, 0x0F, 0x86, 0xCB, 0x2D, 0xF5, 0xC1, 0xAA, 0x27, 0x23, 0x06, 0x2D, 0x7E, 0xBB, 0x13, 0x0D, + 0xB8, 0xE8, 0xEB, 0x91, 0x3B, 0x99, 0x86, 0xC2, 0x22, 0x6A, 0xA3, 0xAB, 0x9D, 0xD5, 0x0C, 0xD9, + 0xC1, 0x48, 0x4D, 0xE1, 0xD1, 0x1C, 0xBD, 0xB6, 0x86, 0x43, 0xD6, 0x1B, 0x51, 0xF0, 0x70, 0x86, + 0x4B, 0x8D, 0xA8, 0x4A, 0x64, 0x9E, 0x5F, 0x92, 0x06, 0x59, 0x21, 0x58, 0x1F, 0xB0, 0x61, 0x7D, + 0x64, 0x0B, 0x67, 0x7F, 0xE0, 0x03, 0x1D, 0x81, 0x60, 0x32, 0x72, 0xC2, 0xA5, 0x66, 0xAB, 0x29, + 0xBC, 0x01, 0x98, 0x9F, 0xC9, 0xD2, 0x08, 0x1C, 0x90, 0x6F, 0x6C, 0xE6, 0x82, 0xFF, 0xBD, 0x62, + 0xD5, 0xDB, 0x23, 0xEA, 0x0E, 0xC3, 0x1B, 0x90, 0x59, 0x17, 0x3F, 0xAE, 0xEC, 0x92, 0x9E, 0xEC, + 0x61, 0x20, 0x56, 0x07, 0x27, 0x3B, 0xAC, 0xFB, 0xF9, 0xDB, 0x97, 0x1D, 0xA5, 0xE4, 0xD6, 0x1A, + 0xC5, 0x45, 0xC0, 0x4D, 0x57, 0x2A, 0xD6, 0xD8, 0x77, 0x6C, 0xCE, 0x30, 0xE0, 0x5A, 0x21, 0x8D, + 0x16, 0x42, 0xF2, 0x0F, 0xF0, 0x4B, 0xD4, 0x02, 0x0E, 0xD6, 0x9F, 0x40, 0xC7, 0x01, 0x5E, 0x68, + 0xEE, 0xD8, 0x72, 0xED, 0x20, 0x2E, 0x72, 0xAE, 0xC9, 0x92, 0x63, 0xB7, 0x1D, 0x77, 0x30, 0x9A, + 0xDA, 0x34, 0x58, 0x6A, 0x04, 0xF6, 0x89, 0x37, 0x75, 0xA1, 0x8F, 0x1A, 0xCB, 0x32, 0xCB, 0x1C, + 0xCD, 0x05, 0x3A, 0x38, 0x9E, 0xBB, 0xE6, 0x5D, 0x5F, 0x93, 0xFE, 0x01, 0x01, 0xA3, 0x6B, 0x29, + 0x35, 0x10, 0x1B, 0x63, 0x1F, 0xA6, 0x2A, 0x66, 0xEC, 0x1B, 0x3A, 0x0E, 0xFC, 0x77, 0xE3, 0xD8, + 0x74, 0xA9, 0x81, 0x53, 0xE8, 0x89, 0xE5, 0x82, 0xD4, 0xFD, 0xC6, 0xF2, 0x8E, 0x52, 0xE9, 0x41, + 0xF9, 0x8B, 0x02, 0x1E, 0x05, 0x73, 0xE8, 0x4F, 0xCD, 0x88, 0x71, 0xE6, 0x2E, 0x89, 0x38, 0xF9, + 0x2D, 0x46, 0x8F, 0x3D, 0x02, 0xD8, 0x55, 0xBF, 0x2B, 0x45, 0x27, 0xE5, 0x96, 0x01, 0x57, 0x2A, + 0x91, 0xD8, 0x01, 0x0C, 0x9D, 0x70, 0xC4, 0x66, 0xED, 0xF3, 0x8B, 0xBF, 0xB1, 0x6E, 0xD1, 0x60, + 0xA1, 0xCF, 0x48, 0x1F, 0x9C, 0xC6, 0x49, 0x43, 0x45, 0x90, 0x9A, 0x37, 0xB1, 0xC1, 0x6A, 0x15, + 0xA3, 0x9F, 0x91, 0xEA, 0x0A, 0x9D, 0x57, 0xA8, 0x76, 0xF8, 0xF3, 0xDF, 0x72, 0x44, 0x77, 0x05, + 0x6E, 0xC6, 0xBE, 0xE7, 0x5E, 0x3B, 0x43, 0x5D, 0x72, 0x49, 0x9D, 0xC9, 0xA4, 0xA8, 0x06, 0x0D, + 0x6F, 0xA8, 0xEF, 0xD2, 0xB0, 0xA8, 0x9E, 0x1B, 0x16, 0xA2, 0x9A, 0x78, 0x7E, 0x18, 0x64, 0x57, + 0xE2, 0x9A, 0x04, 0x12, 0x00, 0x7A, 0xD6, 0xE8, 0x0C, 0x2A, 0x7F, 0x98, 0xB0, 0x09, 0x3B, 0x1B, + 0x23, 0x0C, 0x9C, 0x0B, 0xAF, 0x7F, 0xB0, 0x6F, 0xF9, 0x76, 0x36, 0xC6, 0xA1, 0x35, 0x02, 0x25, + 0xF2, 0xDE, 0x5B, 0xE0, 0x99, 0x86, 0x21, 0x18, 0x88, 0xEC, 0xAA, 0xA1, 0x33, 0x0A, 0x8B, 0x18, + 0xBC, 0xA2, 0x74, 0x42, 0x7D, 0xA8, 0x15, 0xFA, 0xDE, 0x28, 0x9B, 0xB5, 0x69, 0x40, 0xF7, 0x82, + 0x00, 0x7C, 0xCD, 0x53, 0xEF, 0x2E, 0xF2, 0xC2, 0xB2, 0x6B, 0x8F, 0xA9, 0x15, 0x4C, 0x7D, 0xB6, + 0xBE, 0x38, 0x8F, 0x4C, 0x66, 0x36, 0x0B, 0x63, 0x2F, 0xB0, 0x9C, 0xC1, 0xE9, 0xC9, 0xE1, 0x5E, + 0x3F, 0x84, 0x51, 0x3B, 0x3E, 0xF0, 0xBD, 0x09, 0x2C, 0xDB, 0xF2, 0x24, 0x05, 0xD8, 0x6F, 0xE9, + 0xFD, 0x91, 0x2B, 0x44, 0x10, 0xE4, 0x32, 0x7E, 0x0C, 0x0B, 0xC6, 0x91, 0xF3, 0x3B, 0xB5, 0x0F, + 0x80, 0x7F, 0xDF, 0xB9, 0x9A, 0x62, 0x37, 0x14, 0x37, 0x02, 0x20, 0x0F, 0x5D, 0xF4, 0xA3, 0x0F, + 0xBF, 0x85, 0xE8, 0xAC, 0x9D, 0x5B, 0xB6, 0xE3, 0xE5, 0x68, 0x96, 0x54, 0xAB, 0x7F, 0xB6, 0x77, + 0x7E, 0x71, 0xCA, 0x3D, 0xB3, 0xA8, 0x35, 0x25, 0x0D, 0x89, 0x69, 0x60, 0xBC, 0xB5, 0x06, 0x60, + 0xC7, 0x6F, 0x7B, 0x30, 0x3A, 0xFE, 0xF3, 0x3F, 0x49, 0x5E, 0x0D, 0x72, 0xFC, 0x06, 0x4C, 0x68, + 0xDA, 0x3C, 0xCE, 0x6F, 0x18, 0x09, 0xB5, 0x2E, 0x1C, 0x46, 0xBC, 0xDE, 0xEC, 0xC3, 0x28, 0x16, + 0xEE, 0x8F, 0x61, 0xF4, 0x63, 0x18, 0x95, 0x1F, 0x46, 0x99, 0x63, 0x84, 0x4B, 0xE9, 0xD7, 0xCD, + 0xC6, 0x8F, 0x21, 0xF2, 0xD4, 0x86, 0x08, 0xAF, 0x56, 0x76, 0x88, 0x08, 0xA5, 0x2F, 0x39, 0x44, + 0xC4, 0x80, 0xAA, 0x32, 0x44, 0x38, 0x81, 0x32, 0x43, 0x24, 0x66, 0x7C, 0xD1, 0x43, 0x24, 0xF6, + 0x29, 0x0A, 0x87, 0x48, 0x9A, 0x12, 0xDB, 0xB4, 0x02, 0x6F, 0x6C, 0x08, 0x18, 0xEC, 0x7B, 0xD7, + 0x1A, 0x3B, 0x83, 0x13, 0xCF, 0xA6, 0xC6, 0x9E, 0xC0, 0x65, 0x83, 0x4B, 0xEF, 0xB8, 0x1A, 0x89, + 0x1D, 0x4C, 0xFE, 0xC7, 0x52, 0xB3, 0x1F, 0x5A, 0xA1, 0x33, 0x68, 0xB6, 0x48, 0xB3, 0xD3, 0x34, + 0xB5, 0x88, 0xD1, 0xC1, 0x2D, 0xD7, 0xA5, 0x18, 0x43, 0x8B, 0x4C, 0x5D, 0x1B, 0xC6, 0xA1, 0x4B, + 0x6D, 0x03, 0x44, 0x16, 0xA1, 0xFF, 0x37, 0xB5, 0x50, 0x0D, 0x22, 0x6A, 0xDD, 0xC5, 0x52, 0x3B, + 0xA3, 0xB0, 0xC4, 0x80, 0x3E, 0xB3, 0x5C, 0x24, 0xD6, 0x5B, 0x2C, 0xB1, 0xBD, 0x69, 0xE8, 0x8D, + 0xBD, 0xD0, 0xB9, 0xA5, 0x48, 0x6C, 0x7D, 0xB1, 0xC4, 0xCE, 0xC1, 0xEE, 0x11, 0x18, 0xE9, 0x48, + 0x6A, 0x63, 0xB1, 0xA4, 0xDE, 0x53, 0xEB, 0xF6, 0x9E, 0x9C, 0x58, 0x83, 0x1B, 0x00, 0xF4, 0xEF, + 0x91, 0xE2, 0xE6, 0x62, 0x29, 0x7E, 0xDC, 0xFB, 0x19, 0xA9, 0x6C, 0x2D, 0x98, 0x8A, 0x3B, 0x72, + 0xC6, 0x0E, 0x2C, 0x3C, 0x91, 0xD6, 0xF3, 0x7A, 0xB4, 0x52, 0x20, 0x43, 0x66, 0xBE, 0xF8, 0x46, + 0x2E, 0x33, 0x5D, 0xD7, 0x1E, 0x2E, 0x98, 0x1A, 0xCB, 0xED, 0x80, 0x86, 0x7B, 0x21, 0xB7, 0x1F, + 0x74, 0xA9, 0x89, 0xAB, 0xED, 0xD5, 0xAB, 0x60, 0xD5, 0xF3, 0x9D, 0xA1, 0x03, 0x06, 0x7E, 0x95, + 0xAD, 0xDD, 0x90, 0x93, 0x8B, 0x1B, 0x4A, 0xDE, 0x9D, 0xF6, 0xFB, 0x64, 0x60, 0xC1, 0xD2, 0x77, + 0x1A, 0x82, 0xED, 0x23, 0x68, 0xDC, 0x08, 0xF8, 0x80, 0x04, 0x37, 0x87, 0x6F, 0xD7, 0x89, 0x15, + 0x12, 0xDB, 0xB9, 0xBE, 0xA6, 0x3E, 0x58, 0x48, 0xE2, 0x03, 0x9D, 0xA0, 0x4D, 0xDE, 0x7A, 0x3E, + 0xAB, 0xF7, 0x32, 0xB2, 0x0A, 0x16, 0x09, 0x98, 0x3D, 0x64, 0x9B, 0x06, 0x14, 0xBA, 0x2F, 0xDA, + 0x74, 0x68, 0x31, 0x54, 0xC0, 0x0F, 0xFC, 0x9F, 0x38, 0xB0, 0xF4, 0xF6, 0x71, 0xA1, 0x1B, 0xD7, + 0xE2, 0x50, 0x1C, 0x21, 0xA7, 0xF7, 0x32, 0xBB, 0x72, 0x74, 0xBC, 0x31, 0xF4, 0xBD, 0xE9, 0x84, + 0x23, 0xA6, 0xCC, 0xEA, 0x41, 0x5D, 0xDB, 0xB9, 0x75, 0xEC, 0x29, 0xD4, 0x16, 0x95, 0x82, 0xB6, + 0x49, 0xC8, 0x28, 0x31, 0x3F, 0x1C, 0x8C, 0x6B, 0x8A, 0x0B, 0x39, 0x24, 0x4E, 0x00, 0x4B, 0x56, + 0xCB, 0x0D, 0xA0, 0x3B, 0x71, 0x53, 0xFF, 0xEA, 0x9E, 0xC0, 0x3C, 0x4D, 0x70, 0xCA, 0x47, 0x51, + 0x59, 0xC4, 0x16, 0x3B, 0x9F, 0xDE, 0x35, 0xE9, 0xBE, 0xFF, 0x9D, 0x71, 0x1F, 0xF1, 0x44, 0xBA, + 0x9D, 0xCE, 0x66, 0x8B, 0x9C, 0xF4, 0x4F, 0x36, 0x38, 0xFB, 0x9D, 0x76, 0x54, 0xA5, 0xDB, 0x59, + 0x5F, 0x6F, 0x93, 0x8B, 0x1B, 0xC0, 0x8E, 0x7D, 0x71, 0x45, 0xC9, 0xC8, 0xBB, 0x03, 0x99, 0xDB, + 0xAC, 0xD4, 0x47, 0x4B, 0x1D, 0x90, 0x3B, 0x27, 0xBC, 0xC1, 0xEF, 0x40, 0xCD, 0xB5, 0xEF, 0x1C, + 0x1B, 0xFE, 0x82, 0xC2, 0xD0, 0x72, 0x46, 0x1E, 0xD6, 0x0C, 0xBD, 0x98, 0x33, 0xC0, 0x7E, 0xBF, + 0x66, 0x8D, 0x46, 0x4C, 0xA8, 0x89, 0x4C, 0xC8, 0x31, 0x6A, 0x61, 0xF0, 0x12, 0x09, 0x63, 0xF5, + 0xAD, 0x4E, 0x27, 0x53, 0x4E, 0x34, 0x35, 0xA1, 0xD4, 0x90, 0x18, 0x9F, 0x95, 0x48, 0xE4, 0x5A, + 0xF0, 0x86, 0xC8, 0x9B, 0xCF, 0x2F, 0x23, 0x35, 0x83, 0x21, 0xC3, 0x27, 0x57, 0xB2, 0xFF, 0xE1, + 0xA4, 0xD7, 0x26, 0x62, 0x03, 0xF9, 0x25, 0x79, 0x8B, 0x5B, 0x2D, 0xCD, 0xDA, 0x4E, 0xDB, 0x85, + 0xE7, 0x0F, 0x6E, 0xFE, 0x85, 0x7C, 0xB5, 0xDC, 0x5D, 0x81, 0x8C, 0xDA, 0x9A, 0xB3, 0x96, 0x51, + 0x8B, 0xED, 0xF7, 0xD3, 0xD1, 0x88, 0x9D, 0x8D, 0xF6, 0x41, 0x2E, 0x50, 0x97, 0xAC, 0xAD, 0x9D, + 0x7A, 0x21, 0x09, 0xA6, 0x13, 0x64, 0x0B, 0x74, 0x0C, 0xBA, 0xE9, 0xE3, 0xC9, 0xF6, 0x8B, 0x4E, + 0x19, 0x1C, 0xA7, 0xD6, 0xAD, 0x33, 0xC8, 0x45, 0x52, 0x6D, 0x91, 0x83, 0x1B, 0xB6, 0x1E, 0x8C, + 0x22, 0x1C, 0x6F, 0x67, 0x67, 0xC7, 0x04, 0xAA, 0x91, 0x93, 0x77, 0x7B, 0x7F, 0x25, 0x1C, 0xBB, + 0x4F, 0xDB, 0xED, 0x76, 0xC5, 0x85, 0x50, 0xA6, 0x77, 0xEB, 0x5B, 0x49, 0x17, 0x2C, 0xD0, 0x15, + 0x62, 0xBE, 0xE1, 0x23, 0xB8, 0x42, 0x62, 0x96, 0xEB, 0x3E, 0xA6, 0x57, 0xD2, 0x9B, 0xE3, 0x34, + 0xF7, 0xFD, 0x8D, 0x76, 0xB7, 0xF3, 0x7C, 0x03, 0x7F, 0xBE, 0x60, 0x3F, 0xB7, 0xF1, 0x67, 0xB7, + 0xF7, 0xDD, 0xCD, 0x38, 0x56, 0xEE, 0x75, 0xDA, 0x38, 0x02, 0xE8, 0x4B, 0x82, 0xD3, 0xB9, 0xA4, + 0xE9, 0x6C, 0xB6, 0xC6, 0xA6, 0x7B, 0xB7, 0xD4, 0xF7, 0x1D, 0xDB, 0xA6, 0x2E, 0xD6, 0x47, 0x5E, + 0xEF, 0x6E, 0x28, 0xCE, 0xB0, 0x84, 0x1D, 0xBD, 0x8E, 0x41, 0x75, 0xD9, 0x34, 0x50, 0xD3, 0xC4, + 0x9E, 0x79, 0x41, 0x38, 0x60, 0xB6, 0xE5, 0xC7, 0x8A, 0xB8, 0xC8, 0xC8, 0x2E, 0x7A, 0x49, 0xFC, + 0x63, 0xDB, 0x68, 0x81, 0xDB, 0x46, 0x33, 0x4E, 0x9C, 0xC7, 0xEF, 0x7A, 0xDB, 0x9D, 0xB3, 0x0C, + 0xFA, 0xC6, 0x99, 0x33, 0x8B, 0xA2, 0x3C, 0xE7, 0x48, 0x0C, 0x56, 0x20, 0x2A, 0xBA, 0xCE, 0x71, + 0x0F, 0x47, 0xF4, 0x36, 0xD6, 0xB2, 0x3A, 0x08, 0xF6, 0x4F, 0x3F, 0x94, 0x81, 0xFF, 0x03, 0x99, + 0xF5, 0x6E, 0x6C, 0xDC, 0xBB, 0xDD, 0xF5, 0x8D, 0x3F, 0xAE, 0x39, 0xAF, 0x70, 0x38, 0x28, 0x9D, + 0x91, 0x0E, 0xDD, 0x20, 0x88, 0xA2, 0x4E, 0x7E, 0xA6, 0x7E, 0x00, 0xEA, 0x78, 0xE4, 0x86, 0xA6, + 0x03, 0x53, 0x50, 0x3F, 0xE7, 0xFA, 0x1E, 0xD7, 0x6B, 0x6C, 0x10, 0x13, 0x7B, 0x4A, 0x91, 0xA1, + 0x6B, 0x01, 0x4C, 0xD8, 0x92, 0x97, 0xE9, 0x73, 0x90, 0x3A, 0xBD, 0xCB, 0x3E, 0xBE, 0x2B, 0x38, + 0xA0, 0x98, 0xF1, 0x08, 0x63, 0x5E, 0x9E, 0x1B, 0x4E, 0x09, 0x68, 0x5C, 0x1E, 0xC1, 0x77, 0xEB, + 0x73, 0x19, 0x5A, 0x7C, 0x3B, 0xA4, 0xF7, 0x98, 0xBB, 0x58, 0xEB, 0x8F, 0xE9, 0x2F, 0x2E, 0x78, + 0x6B, 0xA9, 0x4F, 0xAD, 0x47, 0xD8, 0x4E, 0xDA, 0x73, 0xFC, 0x2B, 0x0F, 0x7C, 0x14, 0xD2, 0x1D, + 0x3E, 0xC2, 0xB6, 0x52, 0x4C, 0xAD, 0x37, 0x9C, 0x61, 0x63, 0xA9, 0x32, 0xB5, 0x0D, 0x46, 0xED, + 0xC5, 0x62, 0xA9, 0xFD, 0xE2, 0xC3, 0x74, 0x8F, 0x74, 0xB6, 0x17, 0x4B, 0xE7, 0x8D, 0xF3, 0x95, + 0xA9, 0x5F, 0x77, 0x4E, 0xC3, 0x38, 0x0A, 0xE6, 0x78, 0xBD, 0x4B, 0xBA, 0xBD, 0xAE, 0xC9, 0x08, + 0x55, 0x36, 0x44, 0x45, 0xC6, 0xE8, 0x04, 0x27, 0x25, 0xD6, 0x06, 0xE3, 0x02, 0xAF, 0x5E, 0x3B, + 0xF2, 0x64, 0x76, 0xB8, 0xDA, 0x1F, 0x78, 0x30, 0x47, 0x71, 0xA2, 0xBD, 0xF9, 0x11, 0x7D, 0x28, + 0x9C, 0xB4, 0xD6, 0xD6, 0xC0, 0xCB, 0x64, 0xD3, 0xCD, 0x10, 0x23, 0xB1, 0x2D, 0x31, 0xEF, 0x63, + 0x14, 0xCA, 0xD4, 0x75, 0xC2, 0x82, 0xC9, 0x2D, 0xB0, 0xDF, 0xFA, 0x94, 0xF6, 0x27, 0x30, 0x55, + 0x34, 0x96, 0x15, 0x5A, 0x30, 0xA9, 0x68, 0x35, 0xFB, 0xE0, 0x73, 0x16, 0x54, 0xBA, 0x01, 0x67, + 0x1F, 0xA7, 0xBA, 0xA3, 0x83, 0x82, 0x8A, 0x86, 0x49, 0xB5, 0x00, 0xC2, 0xB6, 0xEE, 0x83, 0x73, + 0x3A, 0xB6, 0x1C, 0x97, 0x2D, 0x12, 0x72, 0xEB, 0x4E, 0x7C, 0x0F, 0xE3, 0x82, 0x3A, 0x18, 0xE4, + 0x59, 0xAE, 0x6A, 0xB7, 0x7C, 0xD5, 0x5E, 0xF9, 0xAA, 0xEB, 0xE5, 0xAB, 0x6E, 0x94, 0xAF, 0xBA, + 0x59, 0xBE, 0xEA, 0x56, 0xF9, 0xAA, 0xCF, 0x4B, 0x54, 0x65, 0x0E, 0xDE, 0xC9, 0xDE, 0x7E, 0x51, + 0x57, 0x51, 0xF0, 0xD6, 0xE9, 0x9B, 0x8B, 0x42, 0x2D, 0x80, 0x25, 0x62, 0x14, 0x40, 0x5E, 0x50, + 0xF3, 0xCA, 0x02, 0x87, 0xD6, 0xBF, 0x3F, 0xA3, 0xB0, 0x02, 0x41, 0xE7, 0x2B, 0xAE, 0xAC, 0xDB, + 0x13, 0x30, 0x1F, 0x8E, 0xBD, 0x0C, 0x90, 0x30, 0x16, 0xDE, 0x5F, 0x9C, 0x1C, 0xEB, 0x31, 0x5B, + 0x45, 0xDE, 0x9E, 0x1F, 0x7E, 0x4D, 0xE9, 0xA5, 0x81, 0x86, 0xB1, 0x5E, 0x36, 0xD5, 0x6C, 0xA8, + 0x8F, 0x93, 0x21, 0x48, 0x95, 0x36, 0x66, 0x60, 0x79, 0x80, 0xAB, 0x0D, 0x7F, 0x7C, 0x8E, 0x31, + 0xD6, 0x69, 0x66, 0x59, 0xE8, 0xF5, 0xBE, 0x37, 0x9E, 0x80, 0xC1, 0xA4, 0x4B, 0xCB, 0x95, 0xD1, + 0x62, 0x90, 0xF6, 0x39, 0x1D, 0x50, 0x67, 0x62, 0x40, 0x9E, 0xAE, 0xA3, 0x52, 0x28, 0x20, 0x21, + 0x54, 0x8F, 0xDF, 0x16, 0x30, 0x60, 0x9F, 0xFA, 0x78, 0xC8, 0x72, 0x26, 0xD7, 0x32, 0x49, 0xF6, + 0xCF, 0x4B, 0x0D, 0x07, 0x97, 0xE4, 0x9F, 0xF1, 0xEE, 0xCA, 0xAE, 0x40, 0xCA, 0x16, 0xAE, 0x5F, + 0x3E, 0xDF, 0x62, 0x60, 0xFB, 0x2E, 0xC6, 0xE3, 0x19, 0xB1, 0xAD, 0x90, 0xC6, 0x17, 0x90, 0x3D, + 0xC0, 0x4C, 0x96, 0x9A, 0x2C, 0xFC, 0x9C, 0x1D, 0x49, 0x61, 0x0C, 0x5E, 0x05, 0x51, 0x45, 0x1E, + 0xFE, 0xC7, 0x09, 0x5E, 0x83, 0x89, 0x84, 0x9D, 0x6E, 0x90, 0xB9, 0xDE, 0x52, 0x6D, 0x4A, 0xE8, + 0x09, 0x4F, 0x83, 0x22, 0x3A, 0xBC, 0xD6, 0x12, 0x0F, 0x13, 0x2D, 0xBD, 0xEA, 0x49, 0xEE, 0x9D, + 0x98, 0x06, 0x80, 0x7C, 0x29, 0xC5, 0xA4, 0xE9, 0x33, 0x8D, 0x41, 0xE9, 0x6A, 0x4B, 0x0E, 0x6D, + 0x36, 0x09, 0x2F, 0x8C, 0xF6, 0xDE, 0x28, 0xA7, 0xDD, 0xFC, 0x62, 0xCD, 0xDC, 0x69, 0xB3, 0xDB, + 0x39, 0x69, 0xAA, 0xD1, 0xA5, 0x9D, 0x85, 0xD0, 0xFB, 0x64, 0xA6, 0xF7, 0x69, 0x51, 0xF4, 0x7E, + 0x33, 0xD3, 0xFB, 0x6D, 0x21, 0xF4, 0x82, 0x89, 0xEB, 0xDD, 0x9D, 0x51, 0xDC, 0x10, 0x9C, 0x9A, + 0x96, 0xEC, 0xB1, 0x6B, 0x4A, 0x3A, 0xCB, 0xC6, 0xFD, 0x98, 0x09, 0xC0, 0xC2, 0x7C, 0x17, 0x68, + 0xE6, 0xB9, 0xD1, 0xA8, 0xC3, 0xC4, 0x65, 0x26, 0x03, 0x9F, 0x3B, 0x5F, 0xC8, 0x9F, 0x00, 0x6D, + 0xA7, 0x41, 0x7E, 0xFA, 0x09, 0xDB, 0xF8, 0xB9, 0x1B, 0x7D, 0x30, 0xF9, 0xCB, 0x99, 0x9C, 0xAD, + 0x30, 0x01, 0xA1, 0x51, 0x7B, 0x75, 0xE5, 0xBF, 0x6E, 0xD4, 0xDD, 0xF1, 0x08, 0xF8, 0x02, 0x1B, + 0xAF, 0xFE, 0x98, 0xE6, 0x93, 0xF8, 0x5E, 0x50, 0x7B, 0x32, 0x0D, 0x6E, 0x2A, 0xDA, 0x15, 0x81, + 0x3B, 0xBA, 0x40, 0x94, 0x89, 0x3F, 0xAA, 0x50, 0x87, 0xC6, 0xF5, 0x98, 0x7B, 0x14, 0x3A, 0x6A, + 0xED, 0xC2, 0x5A, 0x25, 0x5D, 0xBA, 0x1E, 0x73, 0xF7, 0x37, 0x6D, 0x6A, 0xE5, 0xBB, 0x61, 0xD0, + 0x01, 0x8D, 0x57, 0xA1, 0x4F, 0xAC, 0x91, 0x33, 0x74, 0x77, 0x9B, 0x23, 0x7A, 0x1D, 0x36, 0xF5, + 0x7E, 0x30, 0x41, 0xD8, 0xAF, 0x71, 0x86, 0x52, 0xF8, 0xC3, 0x4E, 0x5C, 0xC3, 0x82, 0xB2, 0xD0, + 0x51, 0xCF, 0x97, 0x06, 0x7A, 0xC5, 0x26, 0x4D, 0x12, 0xDE, 0x4F, 0xE8, 0x2E, 0x9F, 0xFB, 0xAE, + 0xBC, 0x6F, 0x4D, 0xF0, 0xBB, 0x76, 0x9B, 0x26, 0x6E, 0x9A, 0x84, 0x4D, 0xAF, 0x4D, 0x44, 0x76, + 0x74, 0xD0, 0x24, 0x03, 0xA8, 0x10, 0xC0, 0x9F, 0x9E, 0x3F, 0x5E, 0x65, 0xD0, 0xAB, 0x1C, 0x9F, + 0x14, 0x91, 0xCF, 0x36, 0xA5, 0x9B, 0xAF, 0x4B, 0xB2, 0xB4, 0x16, 0x2A, 0x3A, 0x5B, 0xA2, 0x97, + 0xD9, 0x0E, 0xA9, 0xDE, 0x23, 0x78, 0xB3, 0x0C, 0xF9, 0xAE, 0x32, 0xAD, 0x4E, 0xAF, 0xBE, 0x9D, + 0x24, 0x81, 0x23, 0x0C, 0x27, 0x2C, 0xAC, 0x88, 0xFA, 0xF9, 0x12, 0xB7, 0xF4, 0x2F, 0x0F, 0x2E, + 0x4E, 0xB4, 0xEF, 0xB8, 0xC9, 0x78, 0x89, 0x3B, 0x98, 0x97, 0xB8, 0x85, 0xAA, 0xF0, 0x22, 0x5D, + 0x06, 0x14, 0x4A, 0xE7, 0xD8, 0x3B, 0x59, 0x35, 0xCE, 0x79, 0xFC, 0x7F, 0xCA, 0x0C, 0x6A, 0x48, + 0x8E, 0xAD, 0x2B, 0x3A, 0x32, 0x5D, 0x02, 0x90, 0xEA, 0x1D, 0x88, 0x5B, 0x2C, 0x09, 0x54, 0x74, + 0x9B, 0xE5, 0x52, 0x5F, 0x9B, 0xA2, 0x2C, 0x24, 0xA8, 0xE8, 0x32, 0x0B, 0xAC, 0xD6, 0xD7, 0x4D, + 0xB6, 0x47, 0xBE, 0xDE, 0xC8, 0xAF, 0xEC, 0x48, 0xC0, 0x60, 0xB6, 0x76, 0xF2, 0xE4, 0xB6, 0xCB, + 0x82, 0x64, 0x8C, 0x3B, 0x04, 0xFA, 0xE5, 0xC8, 0x3F, 0xED, 0xCA, 0x64, 0xB2, 0x76, 0x0D, 0xD2, + 0x57, 0x2A, 0x25, 0x20, 0xF3, 0x1A, 0x5C, 0xBE, 0x9B, 0xC9, 0xD4, 0xEE, 0x26, 0x65, 0x29, 0x35, + 0xDF, 0x55, 0x83, 0x94, 0xFB, 0x40, 0x6D, 0x3B, 0x8E, 0x92, 0x4B, 0x76, 0xA7, 0x48, 0xFA, 0xDC, + 0x33, 0x89, 0x44, 0x55, 0x19, 0x40, 0x64, 0x56, 0x9F, 0x9C, 0xFE, 0xD9, 0xDD, 0x25, 0x1B, 0x59, + 0x52, 0xA9, 0xCB, 0xA8, 0xF1, 0xF3, 0xBA, 0xB1, 0x4B, 0x19, 0xBF, 0x1B, 0x9D, 0xE7, 0xBD, 0xCB, + 0x4E, 0xC4, 0x3D, 0xFF, 0xAB, 0x70, 0x07, 0xE3, 0x59, 0x6E, 0x67, 0xD8, 0xCE, 0xAD, 0x62, 0x58, + 0x58, 0x68, 0x13, 0xF1, 0xBD, 0x3B, 0x6E, 0x97, 0xC6, 0xC1, 0x50, 0xE2, 0x2F, 0xB6, 0x4C, 0x7A, + 0x07, 0xA6, 0xD0, 0x8E, 0x98, 0x18, 0x00, 0x23, 0x37, 0x6D, 0x3A, 0x7C, 0x44, 0x72, 0xE0, 0x8D, + 0x56, 0x83, 0xF1, 0xEA, 0x06, 0xC1, 0x5F, 0xB6, 0xD8, 0x4F, 0xC6, 0x05, 0x03, 0x6F, 0xBE, 0xD6, + 0x40, 0xB9, 0x6C, 0x01, 0xFE, 0xE5, 0xAB, 0x35, 0x56, 0xA3, 0x90, 0x0D, 0xA9, 0x75, 0x0A, 0xA9, + 0x8D, 0xA6, 0x6A, 0x8C, 0xF9, 0x75, 0x69, 0xCD, 0xC4, 0xF2, 0x33, 0xCD, 0x66, 0x01, 0x8D, 0xD8, + 0x7C, 0xA7, 0xDA, 0xC8, 0x57, 0x42, 0x72, 0x19, 0x33, 0x38, 0xA5, 0xE4, 0x37, 0xC9, 0x42, 0x7B, + 0xE8, 0xFB, 0x5E, 0xC2, 0xA8, 0xE3, 0x8E, 0x1C, 0x97, 0xF2, 0x6F, 0x60, 0xF5, 0x27, 0x85, 0x78, + 0xD7, 0x40, 0x22, 0xAF, 0xF9, 0xCF, 0x0A, 0x96, 0x7F, 0x2C, 0x9B, 0xEA, 0xD4, 0x56, 0x81, 0x28, + 0x3D, 0x12, 0xE1, 0x72, 0xA8, 0x9B, 0xA6, 0xC3, 0x1A, 0x59, 0x08, 0xCC, 0x40, 0xBD, 0x3B, 0x03, + 0x13, 0x95, 0x53, 0x09, 0x11, 0x9D, 0xE3, 0x51, 0x13, 0x53, 0x7E, 0x18, 0xAB, 0x5D, 0x73, 0x65, + 0xAC, 0x1B, 0x60, 0x95, 0x78, 0x90, 0x67, 0xD7, 0x55, 0xB8, 0x94, 0x90, 0xF7, 0xD6, 0x3B, 0x25, + 0x00, 0x12, 0x02, 0x7A, 0xFD, 0x3A, 0xF3, 0x0E, 0xBB, 0x46, 0xF9, 0x16, 0x16, 0x8C, 0xA1, 0xE6, + 0x6E, 0x15, 0xCC, 0x41, 0x7A, 0xB5, 0x7F, 0x4C, 0xC1, 0xFB, 0xB9, 0x76, 0xD8, 0x52, 0x5D, 0x2F, + 0xCF, 0xEA, 0xCA, 0xFC, 0xCE, 0xC2, 0x7F, 0x0A, 0xD6, 0x38, 0x16, 0xB2, 0x91, 0x67, 0x5C, 0xEA, + 0xCD, 0x87, 0x85, 0xC6, 0x73, 0xE7, 0x5F, 0xD0, 0x84, 0x25, 0xD2, 0xFD, 0x61, 0xCE, 0xBE, 0x97, + 0x39, 0xE3, 0xC1, 0x22, 0x68, 0x8A, 0xF2, 0xCC, 0x55, 0x52, 0xEB, 0xF2, 0xDD, 0xBB, 0xBD, 0xFA, + 0x83, 0x7E, 0x01, 0x9E, 0xE4, 0x5C, 0x46, 0xCE, 0xBF, 0xC0, 0x2C, 0x2F, 0x8E, 0xB2, 0xF8, 0x6A, + 0xC9, 0xC8, 0x48, 0xA6, 0x52, 0xCB, 0x23, 0xC4, 0x16, 0x71, 0x2C, 0x64, 0x7C, 0xB5, 0xDA, 0x2B, + 0x6E, 0xBC, 0xC7, 0xCF, 0xA5, 0xC4, 0xB0, 0xE8, 0x34, 0x5F, 0x7F, 0xB8, 0xBE, 0x7E, 0xB5, 0xC6, + 0xBF, 0x56, 0x04, 0xEE, 0x36, 0x5F, 0x73, 0x35, 0xEB, 0xD6, 0x44, 0xD0, 0x8B, 0x10, 0xF4, 0x4A, + 0x23, 0x58, 0xE3, 0x52, 0x2B, 0x37, 0xC4, 0x74, 0x7D, 0x85, 0xE1, 0xD1, 0xB7, 0x6E, 0x29, 0x0B, + 0x76, 0x41, 0xB1, 0xB3, 0x20, 0x44, 0xC6, 0x0B, 0xB1, 0x02, 0x72, 0x47, 0x31, 0x58, 0xA5, 0x19, + 0xB2, 0x40, 0x7A, 0xAC, 0xC2, 0x4B, 0xEE, 0x69, 0xD8, 0x56, 0xF0, 0xDF, 0x40, 0x5D, 0xD7, 0x0B, + 0xB1, 0x80, 0x5C, 0x51, 0xEA, 0x12, 0xCB, 0xB6, 0x79, 0xBC, 0x4A, 0xBC, 0xC3, 0xA2, 0x2E, 0x34, + 0xF5, 0xB4, 0x2C, 0x7C, 0xAF, 0x42, 0xEA, 0x54, 0x6D, 0x80, 0xA4, 0x73, 0xB5, 0xD4, 0xD9, 0xDD, + 0x10, 0xF8, 0x79, 0x2C, 0x97, 0x5D, 0xE4, 0xDE, 0x48, 0xD5, 0x4A, 0xF9, 0x17, 0x52, 0xFD, 0x39, + 0xB9, 0x17, 0x4F, 0xD5, 0xD2, 0xA4, 0xF6, 0x2F, 0xC8, 0x38, 0x5C, 0x5D, 0x2F, 0x6B, 0x65, 0xD2, + 0xBB, 0x1F, 0xDC, 0x7C, 0x64, 0x9B, 0x9F, 0xD7, 0x22, 0xF6, 0x3F, 0xCB, 0xBE, 0x94, 0x35, 0x2F, + 0x7C, 0x66, 0xCD, 0xD8, 0x7D, 0x69, 0x66, 0x6E, 0xE7, 0x54, 0xB6, 0xA6, 0xB3, 0x8E, 0xB4, 0xF8, + 0x38, 0x65, 0x4E, 0x23, 0x4D, 0xC9, 0x63, 0x54, 0x6A, 0xA8, 0xA9, 0xC9, 0x8D, 0xEA, 0x8C, 0x35, + 0xE9, 0x62, 0x86, 0xC8, 0x07, 0x74, 0x9F, 0x1E, 0x6C, 0x6A, 0xFA, 0xA0, 0x9C, 0x01, 0x91, 0x54, + 0x8A, 0x90, 0x45, 0x6E, 0x37, 0xF8, 0xBF, 0x19, 0x4E, 0x77, 0x02, 0x23, 0xC6, 0x87, 0x4A, 0x29, + 0x73, 0x88, 0xA4, 0x99, 0x8A, 0x46, 0x8A, 0x8A, 0x31, 0x3D, 0x58, 0x50, 0x08, 0xE6, 0x74, 0x49, + 0xD1, 0xDE, 0xC3, 0x2B, 0x73, 0xB6, 0x25, 0x93, 0xDB, 0x9E, 0x81, 0x88, 0x75, 0x85, 0x81, 0x3D, + 0x43, 0x04, 0x44, 0x4E, 0x62, 0x26, 0x1D, 0x4D, 0x24, 0xD5, 0xC2, 0xBB, 0x31, 0x06, 0x22, 0x52, + 0xA2, 0x95, 0x0B, 0xCF, 0x23, 0x63, 0xCB, 0xBD, 0x97, 0x49, 0x93, 0x80, 0xB7, 0xB1, 0x51, 0x45, + 0x79, 0x50, 0xFD, 0x1C, 0x77, 0x28, 0x65, 0xAD, 0x32, 0x9C, 0x71, 0xA6, 0x2B, 0x55, 0xD9, 0xB8, + 0x74, 0x13, 0xB0, 0xCC, 0xE3, 0xEA, 0x74, 0x9D, 0xCA, 0x67, 0x81, 0x2C, 0xA0, 0x31, 0xB7, 0x1D, + 0xE9, 0x3A, 0x55, 0x9A, 0xE1, 0x85, 0x56, 0x04, 0x96, 0x75, 0xA6, 0x99, 0xAA, 0x52, 0xB1, 0x11, + 0x22, 0x82, 0xE0, 0x08, 0xBA, 0x3A, 0x89, 0x39, 0x30, 0x9D, 0xEC, 0x1B, 0x2B, 0xB6, 0x03, 0x7F, + 0x50, 0xFD, 0x5C, 0x3E, 0x95, 0xE1, 0xC8, 0x74, 0x82, 0x6E, 0x4A, 0x83, 0x54, 0xED, 0x68, 0x42, + 0x24, 0x18, 0x34, 0x1D, 0x4E, 0xC4, 0xA9, 0x07, 0x6B, 0x60, 0xF4, 0x30, 0xCE, 0xC6, 0x8C, 0x92, + 0xE7, 0x2E, 0xAC, 0x16, 0x58, 0x41, 0xAF, 0x3C, 0x2F, 0x3C, 0x71, 0xDC, 0x69, 0x48, 0x83, 0xFC, + 0xA3, 0xB8, 0x8C, 0x23, 0x2F, 0x0D, 0x43, 0x9B, 0x4F, 0x3B, 0x86, 0x0D, 0x73, 0xF5, 0xC6, 0x1E, + 0x06, 0x55, 0x8A, 0xD8, 0x88, 0xB6, 0x98, 0x92, 0x8C, 0x59, 0x76, 0xA4, 0xD0, 0xF7, 0x18, 0x6E, + 0x8C, 0x77, 0xA5, 0x19, 0xF0, 0x01, 0xC5, 0x00, 0xE6, 0xA0, 0x44, 0xB2, 0x84, 0x6A, 0xCC, 0x77, + 0xAA, 0xB3, 0x2E, 0x12, 0xEB, 0x65, 0x5C, 0x09, 0xA9, 0xC3, 0xFB, 0x83, 0x9C, 0x3D, 0x6A, 0x9F, + 0xE7, 0xED, 0x82, 0xA9, 0x38, 0x4A, 0x97, 0x35, 0xC6, 0x99, 0x19, 0x93, 0x84, 0xE2, 0x6D, 0x52, + 0x18, 0x1B, 0x41, 0x41, 0x57, 0x5B, 0x6E, 0x48, 0x5D, 0xD7, 0x7A, 0x4F, 0x9D, 0xE1, 0x4D, 0x78, + 0x39, 0x1E, 0x9B, 0xC7, 0x99, 0x56, 0x4B, 0xED, 0x50, 0xB2, 0x86, 0xF1, 0xE8, 0x2C, 0x59, 0x98, + 0x59, 0xD4, 0x32, 0xC3, 0xCC, 0x79, 0x83, 0x79, 0x9E, 0x06, 0x00, 0xC6, 0x6F, 0x54, 0x5E, 0x4D, + 0xC3, 0x50, 0x0E, 0xB3, 0x2E, 0x97, 0x56, 0x2A, 0xF4, 0xEF, 0xCD, 0xDD, 0x87, 0xC7, 0xD0, 0x79, + 0xBA, 0xF3, 0x00, 0x7E, 0x4F, 0x38, 0xB8, 0x21, 0x4B, 0x14, 0x37, 0x0B, 0xCC, 0x13, 0xA1, 0x34, + 0xC3, 0xF4, 0xC1, 0xEF, 0xB9, 0x00, 0x24, 0xC4, 0x09, 0x02, 0xF8, 0xC9, 0x02, 0xE6, 0x8F, 0x0E, + 0xA2, 0xF4, 0x5E, 0x55, 0x22, 0xD5, 0xF3, 0xF3, 0x6F, 0x95, 0x6C, 0x8F, 0x41, 0xA1, 0x6A, 0x34, + 0x88, 0xDD, 0x4B, 0xAD, 0xDC, 0x22, 0xA9, 0x1F, 0xF7, 0x46, 0x23, 0xE2, 0xD3, 0xE1, 0x74, 0x84, + 0x09, 0xD3, 0x98, 0x93, 0xCB, 0xFB, 0x34, 0x76, 0x31, 0xB5, 0xEE, 0xAC, 0xD0, 0xD6, 0x4C, 0x53, + 0x51, 0xB1, 0x9D, 0x47, 0x35, 0xFA, 0xEB, 0xC1, 0x94, 0x8B, 0x2E, 0xBA, 0xE8, 0x43, 0x30, 0x40, + 0x87, 0x26, 0x17, 0xA4, 0xD8, 0xD1, 0x3E, 0x8F, 0x50, 0xDA, 0xBF, 0xB1, 0xDC, 0x21, 0x15, 0xCB, + 0x45, 0x2D, 0x00, 0xA1, 0xD9, 0xDC, 0x79, 0x96, 0x58, 0x16, 0x18, 0xE2, 0x22, 0xAA, 0xE9, 0x24, + 0x18, 0x1A, 0x6A, 0x0A, 0x06, 0x0E, 0x3C, 0x74, 0xCD, 0xA7, 0x3C, 0xCF, 0x18, 0x28, 0x0F, 0x5E, + 0xBC, 0x00, 0x8F, 0xDD, 0xC7, 0xC0, 0x2D, 0xF0, 0x96, 0xC9, 0x1D, 0x78, 0xE5, 0xC9, 0x74, 0x04, + 0x5D, 0x70, 0xED, 0x3D, 0x8B, 0x4C, 0xB3, 0x9E, 0xA5, 0x8C, 0x0F, 0x02, 0x59, 0x5E, 0x99, 0xF9, + 0x3F, 0x93, 0x0E, 0x7E, 0xEB, 0x81, 0x0B, 0x05, 0x7D, 0xC7, 0x6F, 0x6F, 0x70, 0x46, 0x92, 0x3E, + 0x1D, 0xA6, 0x93, 0x8F, 0xBC, 0xFF, 0x1D, 0x5A, 0x63, 0x3B, 0xC1, 0x04, 0xFB, 0x88, 0x25, 0x1C, + 0xC6, 0xB8, 0x59, 0xB2, 0x3F, 0x0D, 0xC0, 0xBC, 0xF1, 0xBF, 0x61, 0x95, 0x81, 0x62, 0x6A, 0x2E, + 0x4B, 0xBD, 0x60, 0xC0, 0xD4, 0xA7, 0x83, 0xDA, 0xA8, 0xF0, 0xFA, 0x0C, 0xCE, 0xCB, 0x7D, 0x71, + 0x49, 0x6B, 0x66, 0x44, 0x6F, 0x71, 0x0E, 0xAD, 0x8D, 0x85, 0xCD, 0xC0, 0x6F, 0xD8, 0xFD, 0x41, + 0x39, 0x57, 0x22, 0x8F, 0xD6, 0x98, 0x2F, 0xCE, 0x77, 0xD4, 0xAB, 0x8D, 0x92, 0x4F, 0x44, 0xA7, + 0xA1, 0xEF, 0x4C, 0xFA, 0x14, 0x04, 0xE7, 0xCF, 0x03, 0xD3, 0xFE, 0xC8, 0x61, 0xE1, 0x9F, 0x35, + 0x31, 0xE1, 0xED, 0x29, 0xBC, 0xA8, 0x82, 0x43, 0xCB, 0xC5, 0xD0, 0xF2, 0x99, 0x38, 0x3A, 0xF3, + 0x1C, 0x37, 0x3C, 0xA3, 0xFE, 0x35, 0xAC, 0x11, 0xA4, 0xD5, 0xD0, 0x8C, 0x58, 0x0F, 0xA3, 0x3B, + 0x96, 0x53, 0x66, 0xD1, 0xE7, 0x82, 0xEB, 0xBD, 0x08, 0xCB, 0xE6, 0x39, 0xBB, 0xBD, 0xE1, 0x90, + 0x85, 0x50, 0xCF, 0x86, 0x3A, 0x98, 0x9C, 0x7A, 0x77, 0x33, 0x22, 0x39, 0xF6, 0x7C, 0xAB, 0x36, + 0x0A, 0xE1, 0x3F, 0x9C, 0xDD, 0xA0, 0xDA, 0x52, 0x3C, 0x10, 0x62, 0xAE, 0xC6, 0x8C, 0x0C, 0xCD, + 0x43, 0x36, 0x02, 0xCB, 0xF9, 0xD1, 0xE9, 0xE1, 0xAF, 0x33, 0xA2, 0xDA, 0x3B, 0x3F, 0x9B, 0x0F, + 0x4F, 0xE8, 0x11, 0xBE, 0x8D, 0xC3, 0x42, 0x6D, 0x76, 0x74, 0x3A, 0x33, 0xC2, 0xC8, 0x37, 0xAD, + 0x87, 0x27, 0xEB, 0x2A, 0x6B, 0x25, 0x84, 0x31, 0x46, 0x3E, 0x9D, 0xA0, 0x15, 0xC4, 0x04, 0xDE, + 0xF2, 0xE2, 0x93, 0x97, 0x44, 0x01, 0x65, 0x7A, 0x69, 0x38, 0x10, 0x56, 0xE5, 0x0D, 0x3A, 0x1B, + 0x5A, 0x09, 0xB7, 0x5C, 0xA9, 0x92, 0xA9, 0x3D, 0x49, 0x7D, 0xB3, 0x6F, 0x06, 0x93, 0x43, 0x71, + 0x1F, 0x3B, 0x4D, 0x1D, 0x16, 0x61, 0xB8, 0x68, 0x4A, 0x17, 0xEC, 0xA7, 0x76, 0x98, 0x9C, 0x04, + 0xEF, 0x83, 0x92, 0x7E, 0x9E, 0x39, 0xF8, 0xE0, 0x6E, 0x88, 0x49, 0x57, 0xB8, 0x36, 0x41, 0x78, + 0x0F, 0x4E, 0x05, 0x0A, 0x6C, 0xC4, 0x72, 0xFB, 0x37, 0x5C, 0xCF, 0xA5, 0x0D, 0x35, 0x71, 0x3D, + 0x5B, 0xD6, 0x14, 0x43, 0x5E, 0x81, 0x8F, 0xFF, 0x95, 0x83, 0x82, 0x57, 0xED, 0x53, 0x9C, 0xC7, + 0xF7, 0xFB, 0x3F, 0xE3, 0x6D, 0x51, 0xF4, 0x15, 0xC4, 0xBD, 0x46, 0x96, 0xAC, 0x56, 0xC2, 0x2D, + 0x12, 0x79, 0xC7, 0x89, 0xFA, 0x79, 0x76, 0x6F, 0x56, 0x15, 0x81, 0xA5, 0x4D, 0xDF, 0xB5, 0xB5, + 0xA3, 0xC4, 0xAD, 0x8B, 0xEB, 0x0E, 0x46, 0x81, 0xC8, 0x9C, 0x8F, 0xC9, 0xB4, 0xE3, 0x7C, 0xAA, + 0xFF, 0x98, 0xC2, 0x22, 0x9C, 0xA7, 0x8A, 0xF7, 0x7C, 0x70, 0x0D, 0x97, 0x1A, 0x6D, 0xF9, 0xE0, + 0xB0, 0x45, 0xDA, 0xCA, 0x29, 0x49, 0x23, 0x27, 0x49, 0xAF, 0x44, 0x41, 0x6C, 0x61, 0xC1, 0xF7, + 0x95, 0x15, 0xD9, 0x7B, 0x91, 0x18, 0x5E, 0xD9, 0x95, 0x01, 0x3E, 0x7F, 0xFB, 0xD2, 0x16, 0x19, + 0x77, 0x59, 0x10, 0xB9, 0x5A, 0xC2, 0xFD, 0x4A, 0x56, 0x18, 0xF5, 0xD8, 0xB3, 0xD4, 0xA2, 0xA4, + 0x65, 0x58, 0x93, 0xAC, 0xAD, 0x9D, 0xD3, 0xB1, 0x77, 0x4B, 0x59, 0x1C, 0x1C, 0xEE, 0x36, 0x61, + 0xB8, 0x1C, 0xFB, 0x83, 0x97, 0x57, 0x15, 0x4A, 0xB2, 0x03, 0xFC, 0xD2, 0xF5, 0xC2, 0xA5, 0xB6, + 0x1E, 0x84, 0xB7, 0x1C, 0xC9, 0xCB, 0x97, 0x6F, 0x7D, 0x3F, 0xAE, 0xB0, 0xA2, 0x05, 0x47, 0x5A, + 0x5C, 0x26, 0x3E, 0xE4, 0x38, 0xD3, 0x52, 0x7C, 0x28, 0x61, 0xAB, 0x40, 0x04, 0x53, 0xEE, 0x36, + 0x5B, 0x4D, 0xF8, 0x29, 0xA1, 0x02, 0x3E, 0xAA, 0xD1, 0x8F, 0xE3, 0x50, 0x2B, 0xF1, 0x10, 0x87, + 0xB7, 0x9A, 0xF8, 0x88, 0x0A, 0xCB, 0xF3, 0x92, 0xBB, 0x1D, 0x5B, 0xC4, 0x92, 0x61, 0x0F, 0x9B, + 0x05, 0x79, 0x99, 0x91, 0x72, 0xA6, 0x38, 0xBF, 0x39, 0x5B, 0xAF, 0x66, 0xDE, 0xB5, 0x25, 0x8E, + 0x0B, 0x9E, 0xE4, 0x90, 0xAF, 0x92, 0x12, 0x9E, 0x52, 0xCF, 0x74, 0xA0, 0x01, 0x59, 0x52, 0xCA, + 0x9F, 0x45, 0x61, 0x9C, 0xD2, 0x03, 0x01, 0x20, 0x8C, 0xE4, 0x09, 0x81, 0xA5, 0xA8, 0xB0, 0x45, + 0x7A, 0x9D, 0x4E, 0x67, 0x39, 0x6D, 0xED, 0xD8, 0xA1, 0x3D, 0x58, 0xB9, 0x16, 0x61, 0x0B, 0x3B, + 0x3C, 0x75, 0x50, 0xAC, 0x1F, 0xB6, 0x91, 0x1F, 0xEC, 0x6B, 0xCB, 0x25, 0x0C, 0x9C, 0x66, 0x05, + 0x2F, 0x09, 0x8A, 0x20, 0x86, 0x46, 0x12, 0x31, 0x85, 0xC1, 0x88, 0x5A, 0x7E, 0x44, 0xA2, 0x1C, + 0xDE, 0x66, 0x9A, 0xC7, 0xFE, 0x74, 0x30, 0x80, 0xD5, 0x1D, 0xE3, 0x52, 0xCA, 0x5A, 0x1E, 0xE3, + 0x11, 0xE5, 0x26, 0x0E, 0x9B, 0x3C, 0x71, 0x79, 0x9A, 0xA9, 0x04, 0x67, 0x59, 0x74, 0x06, 0xC6, + 0x60, 0x15, 0x19, 0x31, 0x25, 0xE4, 0x17, 0x2D, 0xE7, 0xE2, 0xF7, 0x5B, 0xAE, 0xC5, 0x8A, 0xD9, + 0xB4, 0x12, 0x4C, 0xAF, 0xC4, 0xA3, 0x1D, 0x07, 0x3C, 0xB3, 0xC2, 0xF9, 0xB7, 0xED, 0x33, 0xE3, + 0xB7, 0x24, 0x22, 0x2C, 0x62, 0xCE, 0x76, 0xF2, 0xA1, 0xF0, 0xDE, 0xA4, 0x12, 0x94, 0x61, 0xDC, + 0xFE, 0xE5, 0x0B, 0xFA, 0x7F, 0x2A, 0xAB, 0x6F, 0x6D, 0xBF, 0xA0, 0x32, 0x87, 0x29, 0x72, 0x45, + 0xFC, 0x19, 0x9A, 0x94, 0xCF, 0xA1, 0xE1, 0xAE, 0x43, 0x66, 0x4F, 0x8B, 0x3E, 0x4A, 0x74, 0x5C, + 0xD2, 0x1E, 0xB9, 0xFF, 0x1A, 0x42, 0x91, 0x45, 0x9A, 0xFB, 0xF8, 0x5A, 0x93, 0xAE, 0x34, 0x52, + 0x7F, 0x6B, 0x2E, 0x82, 0x41, 0x53, 0xD8, 0x93, 0x30, 0x88, 0x97, 0xDD, 0xA9, 0xE0, 0x3B, 0x98, + 0x12, 0x3E, 0xB4, 0xF1, 0xF2, 0x11, 0xF7, 0xC7, 0x37, 0xBF, 0x4A, 0xCA, 0xC8, 0x8A, 0xC5, 0x9C, + 0xC0, 0x8A, 0x19, 0xDD, 0x0E, 0x0C, 0xE3, 0xCD, 0x4D, 0xE0, 0xF7, 0x04, 0x9C, 0x3C, 0x4C, 0x2A, + 0x71, 0x45, 0xC3, 0x3B, 0x3C, 0x16, 0xEC, 0xB0, 0xBD, 0x1F, 0x28, 0x6B, 0xB4, 0xD0, 0x8E, 0x8D, + 0x46, 0xD6, 0x24, 0xA0, 0x98, 0x9F, 0x8F, 0x27, 0xD8, 0x60, 0xBB, 0x1D, 0xAA, 0xFA, 0x9A, 0xE8, + 0xE3, 0xBA, 0x76, 0x91, 0x3C, 0x20, 0xFE, 0x62, 0x3E, 0x30, 0xBF, 0x57, 0x19, 0x2E, 0xB6, 0xB2, + 0x99, 0xD8, 0x9A, 0x45, 0x0E, 0x48, 0xBF, 0xAC, 0x24, 0xEA, 0xF1, 0x60, 0x94, 0x83, 0xA8, 0xD8, + 0xE7, 0xF3, 0x08, 0x18, 0xEE, 0x01, 0xBF, 0xF4, 0x3C, 0x80, 0x75, 0x88, 0x6C, 0x92, 0x45, 0x81, + 0x69, 0x08, 0xA2, 0x4A, 0x47, 0x03, 0x09, 0x6A, 0x72, 0x48, 0xD3, 0x50, 0x85, 0xE9, 0x67, 0x95, + 0x95, 0xAE, 0xA2, 0x47, 0x58, 0x11, 0x64, 0x3A, 0xC9, 0x03, 0xE0, 0x43, 0x3B, 0x4D, 0x40, 0x6E, + 0x2B, 0x38, 0x83, 0x0E, 0xBA, 0xF4, 0x6F, 0x1D, 0x3A, 0xB2, 0x83, 0xA5, 0xE4, 0x15, 0x8A, 0x7D, + 0x21, 0x04, 0xE1, 0x45, 0x0F, 0x92, 0x0C, 0x20, 0xBA, 0x78, 0x62, 0xC1, 0x8A, 0xFD, 0x3C, 0x91, + 0x48, 0x06, 0x24, 0x1E, 0x6D, 0x0A, 0x22, 0xF5, 0xC8, 0x7D, 0xCB, 0x84, 0x4E, 0xBA, 0x05, 0x41, + 0xF1, 0xAE, 0x75, 0x55, 0x38, 0x54, 0x29, 0x01, 0x0A, 0xBF, 0x96, 0x83, 0x7E, 0x93, 0xE4, 0xB4, + 0x02, 0x50, 0x96, 0xE1, 0xAA, 0x3A, 0x55, 0xA6, 0x44, 0x02, 0xBC, 0x34, 0xE5, 0xB3, 0x33, 0x49, + 0x50, 0xF2, 0xAE, 0x4C, 0x39, 0x68, 0x29, 0xF5, 0x15, 0x43, 0x80, 0x7F, 0x96, 0x82, 0xFC, 0xC5, + 0x79, 0xEB, 0x24, 0x80, 0x77, 0xCE, 0xB5, 0x53, 0x0E, 0xEE, 0x62, 0xFF, 0xEC, 0xE3, 0x81, 0xC4, + 0x33, 0xAC, 0x34, 0x3F, 0xDA, 0x93, 0x72, 0xB0, 0xEC, 0x5E, 0x6B, 0x02, 0xCA, 0xFC, 0xF9, 0x72, + 0x90, 0xE9, 0xA5, 0xE6, 0x7D, 0x82, 0x47, 0xF2, 0xF5, 0xCA, 0x61, 0xEB, 0xDF, 0x07, 0x21, 0x1D, + 0x27, 0x08, 0x02, 0xFE, 0x77, 0x29, 0xD8, 0x43, 0x35, 0x6F, 0x19, 0x40, 0xC7, 0x99, 0xCC, 0x4A, + 0xC1, 0x9F, 0x5E, 0x48, 0xC2, 0xC3, 0xE4, 0x66, 0xA5, 0xA0, 0xDE, 0x4A, 0x4F, 0x85, 0x00, 0x9C, + 0xBC, 0x44, 0x8A, 0xE0, 0xB9, 0xB3, 0xA0, 0xCF, 0x6E, 0x7C, 0x14, 0x8B, 0x21, 0x49, 0x38, 0xE5, + 0x94, 0x01, 0xE5, 0x59, 0x18, 0x92, 0x3B, 0xCD, 0x78, 0x6C, 0xDC, 0xC2, 0x17, 0x9C, 0x36, 0xB6, + 0x25, 0x63, 0xCA, 0xB2, 0x8C, 0x6E, 0x6C, 0x03, 0xA4, 0xE5, 0x5B, 0x03, 0x3C, 0x4B, 0x93, 0xCD, + 0xA9, 0x3A, 0xEA, 0x97, 0x63, 0xD2, 0x2C, 0x25, 0x6D, 0x06, 0x5D, 0x6E, 0xB8, 0x0D, 0x3B, 0xE7, + 0x2D, 0x7C, 0x6B, 0xA7, 0xD3, 0xE9, 0xF6, 0x5A, 0xEC, 0xB1, 0xA0, 0xB4, 0x3D, 0xE7, 0xA5, 0xCC, + 0xAA, 0x77, 0x3B, 0x0C, 0xC0, 0x64, 0x40, 0x22, 0xA9, 0x22, 0xC9, 0x7D, 0x39, 0x27, 0x17, 0xDB, + 0xA5, 0xC8, 0x64, 0x87, 0x27, 0xD2, 0x6A, 0xB0, 0xE9, 0x64, 0xBB, 0x93, 0x39, 0x9D, 0x6C, 0x77, + 0x4A, 0x90, 0x4D, 0xA1, 0xDE, 0x3F, 0xFD, 0x30, 0x13, 0xE6, 0xD8, 0x87, 0xCD, 0xDA, 0x5E, 0x8E, + 0xCF, 0xC6, 0xD2, 0xDE, 0xAD, 0xA9, 0xCF, 0xDD, 0x04, 0x78, 0xDF, 0x02, 0x09, 0xF9, 0xEF, 0xBD, + 0x20, 0x14, 0xBD, 0xBF, 0x99, 0xEA, 0xFD, 0xCD, 0x8C, 0xDE, 0x4F, 0xB7, 0x3E, 0x43, 0x02, 0x29, + 0x72, 0x68, 0xC1, 0x38, 0xB9, 0x6D, 0xFC, 0xA7, 0x53, 0x64, 0x1F, 0xAB, 0x51, 0x32, 0xB4, 0x8C, + 0xBD, 0x14, 0xC4, 0xF6, 0xBC, 0x39, 0xA9, 0xF5, 0x8E, 0x4E, 0x67, 0xBD, 0x53, 0xBB, 0x65, 0xBC, + 0x1D, 0x1F, 0x03, 0xEA, 0x67, 0x4B, 0x33, 0x5D, 0x80, 0xF5, 0x99, 0x11, 0x0C, 0xBF, 0xF6, 0x86, + 0x5E, 0x7B, 0xE0, 0x8D, 0xF1, 0x2F, 0xFC, 0x4A, 0xC6, 0xC8, 0x18, 0x26, 0x44, 0x05, 0xC3, 0xE2, + 0x80, 0xC7, 0x3A, 0xB6, 0x9C, 0x11, 0x86, 0x99, 0xF9, 0xE0, 0x13, 0xE5, 0xB3, 0x16, 0x9D, 0xD7, + 0x11, 0x7E, 0x5E, 0x86, 0x41, 0x93, 0x77, 0x60, 0x2B, 0xC5, 0xB1, 0x1F, 0x06, 0xBE, 0x89, 0x2C, + 0x6A, 0x01, 0x01, 0x9B, 0x45, 0xDB, 0x84, 0xD3, 0xB3, 0xEE, 0xC9, 0x9D, 0x05, 0x26, 0x03, 0xE4, + 0x60, 0x3B, 0x01, 0x8B, 0xF4, 0x3B, 0xBD, 0x38, 0x3F, 0x3A, 0xC3, 0x6D, 0x1F, 0x16, 0xEC, 0x36, + 0xF2, 0x38, 0x37, 0x84, 0x7E, 0x03, 0x8F, 0x02, 0x37, 0xD2, 0xA2, 0x44, 0x61, 0xED, 0x88, 0xA2, + 0xB4, 0x4C, 0x81, 0xBF, 0xF8, 0x3E, 0x10, 0xAE, 0x34, 0xB9, 0x8C, 0x72, 0x24, 0x23, 0x09, 0x40, + 0xB4, 0xA2, 0x1C, 0xBC, 0x50, 0x9C, 0x5E, 0xB7, 0xD3, 0x2D, 0x09, 0xA7, 0x68, 0x41, 0xE3, 0x6A, + 0x64, 0xFB, 0x97, 0xFD, 0x89, 0xE5, 0x7F, 0x7D, 0x3B, 0x75, 0xBB, 0x8D, 0xCA, 0x38, 0xCE, 0x7E, + 0xA9, 0xC6, 0x6F, 0xD4, 0xE1, 0x21, 0x0D, 0xC2, 0xFF, 0x83, 0x3F, 0xAA, 0x37, 0x19, 0x51, 0x00, + 0x59, 0x40, 0xA2, 0xC1, 0x0D, 0xD5, 0x91, 0x75, 0x21, 0x72, 0xD4, 0xBD, 0x7B, 0xB7, 0x97, 0x11, + 0x38, 0x02, 0x70, 0xDA, 0x76, 0x1F, 0xFA, 0x77, 0xB0, 0xE0, 0x88, 0x13, 0x73, 0x27, 0x1B, 0x9D, + 0x6B, 0x6B, 0x63, 0xB6, 0xE8, 0xC3, 0x1A, 0x8E, 0x1D, 0x90, 0x20, 0xB4, 0x7C, 0xA6, 0x03, 0x4C, + 0xA9, 0xB4, 0xCB, 0x75, 0xCF, 0xBE, 0x53, 0x52, 0x38, 0x5C, 0xDA, 0x25, 0xAC, 0xE4, 0x6F, 0x3C, + 0x36, 0x79, 0xC6, 0x0D, 0xC7, 0xFE, 0xB7, 0x5D, 0x8D, 0xFB, 0x2F, 0xF2, 0xA2, 0xD7, 0xB4, 0x9B, + 0x25, 0x91, 0xC8, 0xDA, 0xC2, 0x32, 0x07, 0x19, 0x4B, 0x80, 0x7C, 0xA7, 0x71, 0x27, 0x1D, 0x4A, + 0xA7, 0xAF, 0x3D, 0xCD, 0x21, 0xA2, 0x72, 0xFA, 0xA4, 0xF2, 0x1D, 0xC3, 0x02, 0xA2, 0xE7, 0x2B, + 0x2D, 0x86, 0xF2, 0x49, 0x49, 0x8C, 0xAD, 0x11, 0xF3, 0xA4, 0x66, 0xD2, 0x79, 0x5C, 0x5C, 0x1A, + 0xB4, 0xBE, 0x5A, 0x1E, 0x72, 0x89, 0xFD, 0xD2, 0xD2, 0xD4, 0x2F, 0xF1, 0x15, 0x8A, 0x72, 0x5C, + 0x4B, 0x8E, 0xE3, 0x4A, 0x42, 0x64, 0x4B, 0xFD, 0x22, 0xC5, 0x9B, 0xB1, 0xB5, 0x49, 0x40, 0xFF, + 0xFF, 0xA8, 0x26, 0x97, 0x1B, 0x2F, 0x8F, 0xD5, 0xE2, 0xAA, 0x63, 0x45, 0x7D, 0x30, 0x89, 0x67, + 0x3D, 0x8D, 0xAE, 0x32, 0x16, 0x8F, 0x98, 0x9C, 0xE7, 0x96, 0x66, 0x90, 0x6C, 0xEA, 0x06, 0xEA, + 0xF7, 0x92, 0xAE, 0xE2, 0xE3, 0x4A, 0xB0, 0xB8, 0x8E, 0x01, 0x77, 0x13, 0x9F, 0x66, 0x30, 0x2F, + 0x63, 0xBA, 0x7C, 0x63, 0x0A, 0xCB, 0x73, 0xF7, 0xC7, 0xE6, 0xAA, 0x90, 0xFA, 0x3D, 0xDC, 0x7F, + 0x49, 0xA9, 0x45, 0x3B, 0x7A, 0x19, 0x4A, 0xCD, 0xB2, 0xEB, 0x4A, 0xCB, 0xD2, 0x68, 0x45, 0x65, + 0x08, 0x98, 0x2A, 0xB9, 0xA0, 0x12, 0x0B, 0x1C, 0xEF, 0x2A, 0x40, 0xE1, 0xB2, 0xF4, 0xD1, 0x74, + 0xE0, 0xB9, 0x36, 0xBA, 0xEC, 0x5B, 0x1D, 0xD6, 0x1C, 0x43, 0x63, 0xB6, 0x3A, 0xE2, 0xED, 0x0E, + 0xB9, 0x21, 0x6F, 0x8C, 0x19, 0xD6, 0xF3, 0x89, 0x9D, 0x79, 0x81, 0x83, 0xFF, 0xDF, 0x1B, 0x0C, + 0xA6, 0xB0, 0x8C, 0xB9, 0xE7, 0x0B, 0x9D, 0x4D, 0x14, 0x64, 0x8A, 0x68, 0xB7, 0xCD, 0xA8, 0x6E, + 0xB6, 0x73, 0xA8, 0x26, 0x64, 0x15, 0x9F, 0x94, 0x45, 0x5B, 0x1D, 0xB2, 0x64, 0x4F, 0x2D, 0xE5, + 0x29, 0x76, 0x99, 0x51, 0x33, 0xC4, 0x27, 0x84, 0x90, 0x9E, 0x68, 0x2F, 0x86, 0xF8, 0x0D, 0x20, + 0xA4, 0xA7, 0xDB, 0xF3, 0x01, 0x8E, 0xAD, 0x90, 0xA5, 0x9D, 0x6E, 0xB1, 0x97, 0xE6, 0xB7, 0x3B, + 0xBD, 0xED, 0x8D, 0xE7, 0xDB, 0x05, 0x20, 0x9E, 0x3B, 0x14, 0x30, 0xFC, 0x11, 0xFA, 0x17, 0x9B, + 0x9D, 0xCD, 0xE7, 0x5B, 0xDD, 0x7C, 0xA8, 0xBD, 0x51, 0xE8, 0x84, 0x53, 0x9B, 0x6D, 0x91, 0x6C, + 0x6E, 0x01, 0xAD, 0x17, 0xDB, 0xCA, 0xF2, 0x4B, 0x3B, 0xB0, 0x51, 0x31, 0x64, 0xA8, 0x47, 0x26, + 0xC5, 0xFC, 0x1E, 0x86, 0x1E, 0x94, 0xBB, 0x2A, 0x52, 0xE2, 0xFC, 0x30, 0xBB, 0x1C, 0x7D, 0xAE, + 0x29, 0xDA, 0xFA, 0xE2, 0xAD, 0x24, 0xE2, 0x02, 0x0B, 0xA2, 0xE9, 0xE6, 0xF3, 0x0E, 0xFB, 0xD7, + 0x22, 0xF1, 0x2F, 0xF1, 0x38, 0x88, 0xCA, 0x70, 0x10, 0x88, 0x5F, 0x8B, 0x87, 0x5F, 0x11, 0xD1, + 0x4F, 0xDF, 0x83, 0xE8, 0x6F, 0x8B, 0x20, 0xFA, 0x90, 0x17, 0xAB, 0x5C, 0xDD, 0x1C, 0xD4, 0x33, + 0x09, 0x95, 0xCC, 0x42, 0x5A, 0x5E, 0x49, 0xD0, 0x12, 0x18, 0xFB, 0x9F, 0xA9, 0x8F, 0xC9, 0xCD, + 0xE1, 0xDB, 0x1A, 0xBB, 0xFE, 0x91, 0x5C, 0xF0, 0x2F, 0x25, 0x68, 0x49, 0x1B, 0x57, 0xBB, 0xDD, + 0xCE, 0xFA, 0x46, 0x8B, 0xBC, 0x78, 0xA1, 0x6C, 0x8D, 0xF2, 0xCF, 0x28, 0x64, 0x2C, 0x28, 0x61, + 0x54, 0x33, 0xC8, 0xE9, 0xF7, 0x0A, 0x90, 0x20, 0x26, 0xB6, 0xDF, 0x54, 0x68, 0x6D, 0xB2, 0x54, + 0xF1, 0x9B, 0xB5, 0xB5, 0xC7, 0x1C, 0x7D, 0x08, 0xB4, 0x7A, 0x7C, 0xC6, 0xED, 0x69, 0x13, 0x2F, + 0xFF, 0xCE, 0xF3, 0xD9, 0x77, 0xDA, 0xA5, 0x15, 0xE8, 0x21, 0x73, 0xAF, 0x32, 0x0E, 0xAA, 0xAD, + 0xB3, 0x57, 0xC9, 0x81, 0x93, 0x3D, 0xA4, 0xCB, 0x4E, 0xE9, 0xBD, 0x6A, 0x19, 0x9E, 0x31, 0xDD, + 0x29, 0xB3, 0x5B, 0x29, 0x13, 0xC4, 0x4D, 0xA7, 0x88, 0x60, 0xFE, 0x7E, 0x65, 0x79, 0x5A, 0x99, + 0xAD, 0xC3, 0xED, 0x1E, 0x46, 0xAC, 0xA3, 0xB5, 0xAE, 0x33, 0x63, 0xEB, 0x72, 0x29, 0x9E, 0xFD, + 0xF2, 0x58, 0x34, 0x93, 0xBD, 0xB4, 0x85, 0xF4, 0x61, 0x2E, 0xC5, 0xC7, 0x6B, 0xA5, 0xA4, 0xA9, + 0xDD, 0xFA, 0x14, 0xBB, 0xB5, 0x34, 0x55, 0x10, 0xD4, 0x35, 0xB5, 0x93, 0xAF, 0xA9, 0xDD, 0x7A, + 0x9A, 0xBA, 0x88, 0xD6, 0x15, 0x69, 0xEA, 0x23, 0xD1, 0x94, 0x34, 0xF5, 0xD1, 0x29, 0x3E, 0x5E, + 0x2B, 0x25, 0x4D, 0xED, 0xD5, 0xA7, 0xD8, 0xAB, 0xA5, 0xA9, 0xBD, 0x5A, 0x9A, 0xDA, 0xAB, 0xA7, + 0xA9, 0x8B, 0x68, 0x5D, 0x91, 0xA6, 0x3E, 0x12, 0x4D, 0x49, 0x53, 0x1F, 0x9D, 0xE2, 0xE3, 0xB5, + 0x52, 0xD2, 0xD4, 0xF5, 0xFA, 0x14, 0xD7, 0x6B, 0x69, 0xEA, 0x7A, 0x2D, 0x4D, 0x5D, 0xAF, 0xA7, + 0xA9, 0x8B, 0x68, 0x5D, 0x91, 0xA6, 0x3E, 0x12, 0x4D, 0x49, 0x53, 0x1F, 0x9D, 0xE2, 0x9C, 0x5A, + 0xF9, 0xD4, 0x8F, 0x5B, 0x8D, 0xAE, 0x72, 0xA5, 0x03, 0x57, 0xA3, 0xEF, 0x5B, 0xEA, 0xC8, 0xD5, + 0xE8, 0xC8, 0x56, 0x3D, 0xFC, 0xCC, 0xF0, 0x4D, 0x1B, 0x65, 0x21, 0x35, 0x0F, 0x93, 0x9F, 0xF9, + 0xDA, 0x77, 0x6E, 0x78, 0xE7, 0xF6, 0xAA, 0xE3, 0x88, 0xA8, 0xFF, 0x72, 0xBE, 0x79, 0x77, 0xEE, + 0x6D, 0xBC, 0xAF, 0xC6, 0x7F, 0xEC, 0x01, 0x36, 0x6A, 0x88, 0x9D, 0x79, 0x00, 0xD5, 0x65, 0x5E, + 0x83, 0x9C, 0xE4, 0x58, 0xD5, 0x11, 0x73, 0x4D, 0xB8, 0xAA, 0x14, 0x35, 0x57, 0xA5, 0x8E, 0x48, + 0x7B, 0xF5, 0x44, 0xDA, 0xAB, 0x2D, 0xD2, 0x5E, 0x4D, 0x91, 0xF6, 0x6A, 0x8B, 0xB4, 0x57, 0x53, + 0xA4, 0xEB, 0x35, 0x45, 0xBA, 0x5E, 0x4F, 0xA4, 0xEB, 0xB5, 0x45, 0xBA, 0x5E, 0x53, 0xA4, 0xEB, + 0xB5, 0x45, 0xAA, 0x43, 0xC6, 0x07, 0x0A, 0xF2, 0x8D, 0x5A, 0xD3, 0xC1, 0x42, 0xD1, 0xBD, 0xDB, + 0x9C, 0xAD, 0x90, 0x28, 0x03, 0x00, 0xBB, 0x60, 0x2F, 0x21, 0x38, 0x60, 0x6F, 0xD5, 0x88, 0xC0, + 0xBB, 0x0B, 0xEF, 0x2B, 0x75, 0xA3, 0x44, 0x14, 0x3B, 0xCF, 0xB4, 0xDC, 0x24, 0x53, 0x1A, 0x27, + 0xC7, 0xD6, 0xDF, 0x0B, 0x30, 0x06, 0x02, 0xE6, 0x53, 0x69, 0x91, 0xF5, 0x2D, 0xFE, 0x5F, 0x3C, + 0x75, 0xAE, 0x6F, 0x65, 0xC5, 0x05, 0x9E, 0x99, 0x42, 0x94, 0x72, 0xF7, 0xC8, 0x0B, 0xA9, 0x37, + 0x1A, 0xFA, 0x7D, 0xDA, 0x69, 0xE8, 0xFD, 0x8D, 0xDE, 0x9F, 0x53, 0x97, 0xDE, 0x59, 0xA3, 0x8C, + 0x98, 0x17, 0xA9, 0xAB, 0xFC, 0x9C, 0x2E, 0xD2, 0x2F, 0x31, 0x57, 0x3B, 0xFE, 0xA1, 0x32, 0x34, + 0x5E, 0xF9, 0x79, 0xC3, 0xCF, 0x5C, 0x38, 0x36, 0xB6, 0xC9, 0xB1, 0xD5, 0x49, 0x6D, 0xD3, 0x8A, + 0x07, 0xDC, 0x5B, 0xF8, 0x55, 0xDB, 0xA2, 0x3D, 0x33, 0x3F, 0x6E, 0x5B, 0x44, 0xFA, 0x98, 0xF5, + 0xF6, 0x9C, 0x08, 0xC6, 0x92, 0xC3, 0xA0, 0xE1, 0xA2, 0x20, 0x52, 0x0C, 0x25, 0x3E, 0x85, 0x46, + 0x7B, 0xFE, 0xD7, 0xCB, 0x4E, 0xBF, 0x7F, 0x74, 0x50, 0xDA, 0xD1, 0x32, 0x84, 0x26, 0x1B, 0x42, + 0x29, 0x8D, 0x74, 0xCE, 0xAC, 0x20, 0x80, 0xDF, 0xEC, 0x47, 0xA0, 0xD5, 0x7D, 0xA4, 0x36, 0x75, + 0x1F, 0xB1, 0x4D, 0xBD, 0x47, 0x6A, 0x53, 0xEF, 0x11, 0xDB, 0xB4, 0xFE, 0x48, 0x6D, 0x5A, 0x9F, + 0x53, 0x9B, 0xC4, 0x10, 0xBB, 0xD8, 0x3F, 0x5B, 0xFB, 0x78, 0x70, 0x96, 0x6D, 0x9F, 0x2E, 0x06, + 0x95, 0x63, 0x7D, 0x85, 0x81, 0x88, 0xAF, 0x8B, 0x27, 0x31, 0xB7, 0x5B, 0x9B, 0x9B, 0xEB, 0xA9, + 0x28, 0x5F, 0xF6, 0x51, 0x66, 0x54, 0x89, 0xF9, 0x2F, 0x58, 0x6F, 0xC5, 0x44, 0xA4, 0x38, 0xE2, + 0xF2, 0x51, 0xE4, 0x26, 0x4A, 0x0F, 0x66, 0x21, 0x54, 0x3D, 0x44, 0x48, 0x84, 0xC0, 0x21, 0xE7, + 0x21, 0x04, 0x13, 0x6B, 0x1F, 0xED, 0xBA, 0xAC, 0x4D, 0xED, 0xB9, 0xB3, 0xB6, 0xB6, 0xF6, 0xC1, + 0x25, 0xD1, 0x95, 0x85, 0x16, 0x81, 0x8A, 0x84, 0xF7, 0x0E, 0x8B, 0xA0, 0xE0, 0xD4, 0xD8, 0x73, + 0xC8, 0xB8, 0xEC, 0x04, 0xFC, 0xBC, 0x09, 0x36, 0xBE, 0xB8, 0x8C, 0xEB, 0xCF, 0x00, 0x23, 0x39, + 0x42, 0x98, 0xC5, 0xA2, 0xA8, 0x89, 0x29, 0x20, 0xF1, 0x5C, 0x82, 0x9A, 0xDB, 0xC2, 0x1A, 0xF7, + 0xE2, 0x2D, 0xE5, 0x76, 0x3B, 0x5A, 0x99, 0xF2, 0x60, 0x7B, 0x91, 0xBD, 0xF2, 0x64, 0x1A, 0xD2, + 0x6F, 0x69, 0xC5, 0xC5, 0x4B, 0x13, 0x5A, 0x37, 0xC2, 0xA7, 0xDA, 0xCC, 0xE5, 0x89, 0x22, 0xBA, + 0xB1, 0xCE, 0x6E, 0xB1, 0x67, 0x8E, 0x29, 0x91, 0xCC, 0xA3, 0x5A, 0x77, 0x8D, 0x00, 0x28, 0x3E, + 0x60, 0x07, 0x2F, 0xEE, 0xAD, 0x4F, 0xFF, 0x31, 0xA5, 0x2E, 0x3B, 0x98, 0xDF, 0xEE, 0xAC, 0xC3, + 0x8F, 0xDE, 0x73, 0xA9, 0xEB, 0xE0, 0x13, 0xDB, 0x22, 0xEA, 0x3D, 0x97, 0xF9, 0x95, 0xAF, 0xC4, + 0xE4, 0x4F, 0xEF, 0x48, 0x0E, 0x64, 0xE2, 0x58, 0x23, 0x16, 0xBF, 0x63, 0x31, 0xCF, 0x51, 0x5C, + 0x2A, 0xBE, 0xC4, 0x41, 0xD4, 0x4D, 0x05, 0x99, 0x74, 0x4D, 0xC1, 0x25, 0x06, 0x8A, 0x49, 0xA8, + 0x97, 0x94, 0x35, 0x32, 0xFF, 0xCE, 0x46, 0xEA, 0x7E, 0x75, 0x70, 0xEC, 0x5C, 0x53, 0xD1, 0x1B, + 0x78, 0x64, 0xD9, 0x93, 0x19, 0xE1, 0x27, 0x96, 0x3D, 0x85, 0x8F, 0xEC, 0x2B, 0x3D, 0xCB, 0x52, + 0xCE, 0x85, 0x00, 0x3A, 0x82, 0xA5, 0x5C, 0xCA, 0x67, 0x67, 0x8E, 0x07, 0xA7, 0x8F, 0x79, 0x60, + 0x2A, 0x9A, 0xC9, 0xEF, 0x23, 0xE5, 0xA9, 0x67, 0x94, 0x46, 0xA5, 0x9A, 0x86, 0x8E, 0xAD, 0x6F, + 0x00, 0x7A, 0xE1, 0x44, 0xD7, 0x79, 0xBA, 0x9D, 0x4D, 0xE8, 0x84, 0x94, 0x1F, 0xD8, 0x6D, 0xC1, + 0xF7, 0x56, 0x4F, 0x55, 0x13, 0xE5, 0x8E, 0x54, 0xBE, 0x66, 0x72, 0x32, 0xB2, 0xC7, 0x39, 0x2B, + 0xA1, 0x12, 0x8B, 0x04, 0xA5, 0x6D, 0x5B, 0x1D, 0xF2, 0x17, 0xD2, 0xCB, 0x0E, 0x10, 0xD2, 0x38, + 0x54, 0xAB, 0x1B, 0xCF, 0xA9, 0x95, 0xE4, 0x35, 0xD5, 0xA4, 0x9E, 0x80, 0x46, 0x81, 0x76, 0xB1, + 0x1B, 0x9E, 0xF6, 0xC0, 0xE7, 0x21, 0x0A, 0x33, 0xC1, 0x4E, 0x6E, 0xF3, 0x4C, 0x29, 0x75, 0xAA, + 0x35, 0xD3, 0x92, 0x50, 0x30, 0x7B, 0x1F, 0x25, 0x88, 0x4C, 0x0E, 0xC7, 0xCD, 0xA7, 0xE3, 0xDB, + 0x73, 0x68, 0x72, 0x0E, 0xF1, 0xC2, 0x76, 0xA7, 0xB2, 0x52, 0x96, 0x6A, 0xAE, 0x9A, 0x04, 0x93, + 0xFB, 0x35, 0xBD, 0xED, 0x8D, 0xED, 0xAD, 0xE7, 0x29, 0xE7, 0x86, 0x7F, 0x9E, 0x43, 0x2B, 0x75, + 0x9A, 0x1D, 0x16, 0xCD, 0x82, 0xAF, 0x16, 0x89, 0x7D, 0xE3, 0xA8, 0xA1, 0xC2, 0x8E, 0x44, 0x13, + 0x7D, 0xDC, 0xF0, 0xCC, 0x3B, 0x18, 0xE6, 0xA6, 0x1E, 0x9D, 0xED, 0xF1, 0x5B, 0x46, 0x4B, 0xF1, + 0xA5, 0xC6, 0xA3, 0xB3, 0x86, 0xD4, 0x3E, 0xD7, 0x75, 0xDB, 0xD2, 0x7F, 0x72, 0x13, 0xB5, 0x7B, + 0x91, 0x19, 0x16, 0xC3, 0x40, 0xE1, 0xE0, 0xB4, 0xBF, 0x68, 0x12, 0xEF, 0x40, 0xBF, 0xEF, 0xAC, + 0xFB, 0x45, 0x93, 0xE9, 0x4F, 0xAF, 0xE0, 0xE7, 0x5C, 0xA9, 0x44, 0x4B, 0x7B, 0x51, 0xF9, 0x34, + 0x9C, 0x08, 0xDF, 0xB0, 0x93, 0xF6, 0x0D, 0x3B, 0x46, 0xDF, 0xD0, 0x4C, 0x27, 0x9E, 0xF1, 0x4F, + 0x2F, 0xCE, 0xEA, 0x6A, 0x4B, 0x7C, 0x4A, 0x06, 0x3C, 0x8D, 0x46, 0x87, 0xDF, 0x26, 0x9E, 0xCB, + 0x9D, 0x3B, 0x70, 0x7D, 0xBA, 0xF2, 0xA8, 0x60, 0x7E, 0x4F, 0x57, 0x19, 0x10, 0xC9, 0x2D, 0xD8, + 0xA2, 0x23, 0xB8, 0x09, 0x70, 0x33, 0x70, 0x58, 0x76, 0x68, 0x98, 0x70, 0xF1, 0xE2, 0x9E, 0x32, + 0xD3, 0xAE, 0xB3, 0x56, 0x77, 0x6A, 0xE2, 0x3E, 0x87, 0xE1, 0x75, 0x40, 0x47, 0x4C, 0x35, 0x3A, + 0x2D, 0x96, 0xB6, 0x55, 0xDB, 0x28, 0x61, 0xE8, 0xBB, 0xC6, 0x8D, 0x92, 0xAA, 0x74, 0x9C, 0x60, + 0x22, 0xD2, 0x5C, 0x2F, 0x82, 0x58, 0x72, 0xDE, 0x35, 0x39, 0xA7, 0xD7, 0xD4, 0x07, 0x47, 0x94, + 0x1E, 0xD9, 0xC2, 0x50, 0xA5, 0x4C, 0x14, 0x5B, 0x7E, 0x05, 0xB9, 0x04, 0x1E, 0xA2, 0x8C, 0x19, + 0x19, 0x4F, 0x19, 0x6B, 0xB9, 0x33, 0x30, 0xAB, 0x99, 0xA8, 0x22, 0xA5, 0xD3, 0x52, 0xB3, 0x0A, + 0x48, 0xB7, 0x57, 0xE5, 0x8B, 0xCA, 0xBB, 0xA4, 0xAB, 0xE4, 0x00, 0x8A, 0x73, 0xE0, 0x34, 0x31, + 0x15, 0xFE, 0x9B, 0xD0, 0x6D, 0x02, 0x9F, 0x67, 0x60, 0x19, 0xC1, 0x54, 0x32, 0x03, 0xC9, 0xB2, + 0x82, 0x48, 0x18, 0x56, 0xE0, 0x03, 0xFB, 0xB3, 0xA1, 0x7B, 0x00, 0x51, 0x4E, 0x99, 0x18, 0x93, + 0x54, 0x61, 0xA1, 0x4F, 0x2F, 0x3F, 0xA8, 0x57, 0x22, 0x24, 0x66, 0x5F, 0xCF, 0xAD, 0xB5, 0xC1, + 0x93, 0x6C, 0xEE, 0x3F, 0x95, 0x9D, 0xD9, 0x32, 0x09, 0x61, 0x8F, 0x3D, 0x0B, 0xB3, 0x2D, 0xB5, + 0x89, 0x68, 0xF5, 0x9D, 0xE5, 0x84, 0xB0, 0xA0, 0x6C, 0xCA, 0x41, 0xE8, 0x66, 0x1D, 0x34, 0xDF, + 0x7A, 0x88, 0xAE, 0x3C, 0xA4, 0x1B, 0xFA, 0x32, 0x62, 0x3E, 0xDE, 0x27, 0x7F, 0x26, 0x3F, 0xBD, + 0xC9, 0x73, 0xC1, 0xE9, 0x4E, 0xA4, 0xDA, 0x39, 0x52, 0xB1, 0x9C, 0x08, 0x49, 0xEE, 0xBC, 0xBE, + 0x75, 0x8B, 0xCD, 0x69, 0xB7, 0x95, 0x90, 0x4F, 0x2D, 0x6B, 0x54, 0x23, 0xC9, 0x7C, 0xDB, 0xCA, + 0x13, 0x7C, 0x4B, 0x41, 0x32, 0xA4, 0x59, 0x79, 0x36, 0x52, 0x19, 0x3F, 0xE4, 0xD4, 0x23, 0xB3, + 0x64, 0xDC, 0x98, 0x3D, 0xEB, 0xC6, 0x2C, 0x99, 0x37, 0xE6, 0x93, 0x7D, 0x63, 0xF6, 0x0C, 0x1C, + 0xB3, 0x65, 0xE1, 0x98, 0x25, 0x13, 0xC7, 0xAC, 0xD9, 0x38, 0x66, 0xCB, 0xC8, 0x31, 0xFF, 0xAC, + 0x1C, 0xB9, 0x18, 0x93, 0x05, 0x7F, 0x82, 0xC8, 0x49, 0xBE, 0x95, 0xC6, 0x53, 0x90, 0xE1, 0xA3, + 0x18, 0x41, 0xC9, 0x34, 0x1F, 0xF5, 0x53, 0x7D, 0xCC, 0x9A, 0xEE, 0x23, 0x9D, 0x63, 0x13, 0x2D, + 0x10, 0xA7, 0xF7, 0x07, 0x98, 0x80, 0x9F, 0xD6, 0xFC, 0x68, 0x9C, 0xBE, 0x16, 0x35, 0x23, 0x08, + 0xFF, 0x3B, 0x95, 0xF2, 0x4A, 0xCF, 0x50, 0x22, 0xE5, 0xAB, 0x5B, 0xE2, 0x76, 0x5F, 0x2A, 0xBF, + 0x7C, 0x77, 0xD6, 0x57, 0xD7, 0xB0, 0x3C, 0xC9, 0x5D, 0xCC, 0xCA, 0x4F, 0x3F, 0x11, 0x13, 0x14, + 0x28, 0xC4, 0x88, 0x65, 0xC6, 0xAE, 0x0A, 0xF9, 0x86, 0x3A, 0x07, 0xDE, 0xB4, 0x0E, 0xC9, 0xE3, + 0x0F, 0xA7, 0x7B, 0x7D, 0x23, 0xB3, 0xCB, 0x9A, 0xB3, 0x60, 0x4A, 0x6C, 0x51, 0x34, 0xAD, 0x49, + 0xFA, 0xC1, 0xA6, 0x2E, 0x45, 0x88, 0xB2, 0xAA, 0xDC, 0x78, 0x18, 0x55, 0x05, 0x6B, 0x14, 0xA2, + 0xF0, 0x27, 0xEB, 0x48, 0xA2, 0x44, 0x2B, 0x2B, 0xBA, 0x62, 0x98, 0x54, 0xA0, 0x91, 0xA6, 0x68, + 0x4C, 0x66, 0xF6, 0xC6, 0x09, 0x4F, 0xAC, 0x49, 0x92, 0xA6, 0x6C, 0xEC, 0xB8, 0xF0, 0xC3, 0xFA, + 0xD6, 0x22, 0x57, 0xAC, 0x44, 0xCA, 0xF4, 0xD8, 0x8A, 0x8D, 0xC2, 0xD1, 0x81, 0x34, 0x8A, 0xA3, + 0xF3, 0xFF, 0xF8, 0x41, 0x00, 0xCE, 0xDE, 0xD8, 0x0A, 0xBE, 0xF2, 0x02, 0x8E, 0x48, 0x29, 0x64, + 0x8A, 0xC3, 0x61, 0x5F, 0x21, 0x49, 0x9E, 0x57, 0x81, 0x7F, 0x78, 0x8D, 0xE4, 0xF9, 0x87, 0x25, + 0x86, 0x04, 0xBA, 0xAE, 0x4B, 0x5E, 0xBD, 0xE2, 0xB4, 0xA0, 0x63, 0xA0, 0x8F, 0x3A, 0x7A, 0xFF, + 0xE4, 0xA4, 0x88, 0x34, 0xA7, 0x9D, 0x94, 0x60, 0xA5, 0x56, 0x15, 0xF5, 0x68, 0x5E, 0x2F, 0xA4, + 0xB6, 0x4A, 0xA2, 0x44, 0x96, 0x92, 0x41, 0x8C, 0x6E, 0x2C, 0x43, 0xFB, 0x0D, 0x37, 0x7E, 0x02, + 0x02, 0x16, 0x94, 0xD8, 0xB0, 0xA6, 0x9C, 0x80, 0x3D, 0x67, 0x9B, 0x28, 0x6A, 0x67, 0xC5, 0x37, + 0x87, 0xA4, 0x9C, 0xC0, 0x0E, 0x46, 0x12, 0xA8, 0x77, 0xE1, 0x76, 0x92, 0x24, 0xC0, 0x71, 0xD3, + 0xC8, 0xAE, 0x71, 0xA3, 0x37, 0x79, 0xEF, 0xC0, 0xA6, 0x21, 0x98, 0x7A, 0x6A, 0xBF, 0x85, 0x55, + 0xB6, 0xC0, 0x93, 0x3C, 0xF0, 0x10, 0xE7, 0x1A, 0xBE, 0x8D, 0x1E, 0x91, 0xC0, 0x4B, 0x7B, 0xFC, + 0x09, 0x1C, 0xC7, 0x86, 0xE9, 0xCF, 0xB9, 0xBE, 0x8F, 0x1F, 0xDA, 0x59, 0x92, 0x95, 0x61, 0x39, + 0xEE, 0x6F, 0x15, 0x6C, 0x97, 0xA8, 0x17, 0x00, 0x83, 0xF6, 0xFE, 0x87, 0x0F, 0xE7, 0x07, 0x47, + 0xA7, 0x7B, 0x17, 0x87, 0x97, 0x47, 0xA7, 0x67, 0x1F, 0x2F, 0x2E, 0x2F, 0x3E, 0x9D, 0xE1, 0xAF, + 0x3F, 0xEF, 0x1D, 0x1F, 0x1D, 0x5C, 0x7E, 0x3C, 0xFD, 0xDB, 0xE9, 0x87, 0x5F, 0x4E, 0xF5, 0xDB, + 0xD9, 0x71, 0x8F, 0x22, 0x93, 0x09, 0x46, 0xBC, 0x2A, 0x0C, 0xAD, 0x20, 0x53, 0xF7, 0xAB, 0x8B, + 0x59, 0x8C, 0x77, 0x9E, 0x9A, 0xAE, 0xB0, 0x01, 0x30, 0xE0, 0x4F, 0xC2, 0x50, 0x5B, 0x62, 0xFC, + 0x15, 0x59, 0xED, 0xBE, 0xE8, 0x70, 0xF5, 0x37, 0x95, 0xC3, 0x14, 0xF4, 0xA2, 0xB3, 0x9C, 0x2B, + 0x86, 0xE4, 0x50, 0xE1, 0x05, 0x5F, 0xB5, 0xBF, 0xE8, 0x3C, 0x39, 0x01, 0x64, 0x0E, 0x15, 0xAE, + 0x2E, 0x92, 0x4E, 0x47, 0x17, 0x35, 0x77, 0x0C, 0xFA, 0xC7, 0xDF, 0x4B, 0xAA, 0xAE, 0x80, 0x0C, + 0xEE, 0x87, 0x06, 0xFE, 0xD0, 0xC0, 0x6C, 0x0D, 0x4C, 0xE9, 0xCB, 0x9F, 0x76, 0x15, 0xC3, 0x97, + 0xDB, 0x7E, 0x6E, 0x43, 0x03, 0x9E, 0x2D, 0x8B, 0x25, 0xC2, 0x79, 0x22, 0xCD, 0xCF, 0x35, 0xF6, + 0x32, 0x1F, 0x13, 0x1F, 0x16, 0x9B, 0x38, 0x03, 0x25, 0x83, 0xAA, 0xDE, 0x68, 0xC9, 0x14, 0x7B, + 0x5D, 0x36, 0x94, 0x4E, 0x10, 0x49, 0xF5, 0x71, 0x42, 0xB3, 0xF1, 0xF0, 0x1F, 0xCF, 0xDE, 0x0D, + 0x4F, 0xBF, 0xB5, 0xA2, 0xD1, 0x88, 0xE5, 0xE0, 0x0D, 0xAD, 0x8D, 0xB0, 0x47, 0x43, 0xEC, 0x2D, + 0x9E, 0x55, 0x27, 0x9E, 0x66, 0xB5, 0x67, 0x05, 0x92, 0x44, 0xAA, 0xEA, 0x0C, 0x9B, 0xCC, 0x8C, + 0x62, 0x84, 0x30, 0x52, 0x4B, 0x51, 0x9D, 0x96, 0x89, 0x89, 0x24, 0x0D, 0xAA, 0x66, 0xD9, 0x72, + 0x91, 0x41, 0xA5, 0x3C, 0x6C, 0xE9, 0x0B, 0xC5, 0xFC, 0xC8, 0x2C, 0x10, 0x21, 0xFE, 0x5C, 0xBE, + 0xA2, 0xF9, 0x69, 0xEF, 0x2F, 0x95, 0xA5, 0x36, 0x71, 0xFF, 0x6A, 0xBA, 0x7D, 0x25, 0x3D, 0x3B, + 0x81, 0x00, 0x3D, 0x8B, 0xEF, 0xE4, 0xCA, 0xF1, 0xF7, 0x38, 0x13, 0xF7, 0x68, 0x37, 0x33, 0xC5, + 0x89, 0xE1, 0x91, 0xB5, 0x3A, 0xAB, 0x81, 0x87, 0xCA, 0xA4, 0x79, 0x9E, 0x90, 0x1C, 0xF2, 0xF2, + 0x89, 0x7D, 0x79, 0xF2, 0xB5, 0xAC, 0x62, 0x96, 0xEA, 0x88, 0xBD, 0xFD, 0x39, 0xEB, 0x4E, 0xF2, + 0x24, 0xAA, 0xAA, 0x42, 0x49, 0xA4, 0x30, 0x6A, 0xD2, 0xBC, 0x14, 0xC7, 0xD0, 0x1F, 0xA6, 0x6B, + 0xB5, 0x73, 0xEA, 0x08, 0x25, 0x29, 0x9E, 0x4C, 0x62, 0x06, 0xD0, 0x4E, 0xA5, 0xFE, 0x8F, 0xA6, + 0xFF, 0xA2, 0x36, 0x77, 0x9F, 0x74, 0x9B, 0xBB, 0x0B, 0x69, 0x73, 0xEF, 0x49, 0xB7, 0xB9, 0xB7, + 0x90, 0x36, 0xAF, 0x3F, 0xE9, 0x36, 0xAF, 0x57, 0x6D, 0xB3, 0x8E, 0x72, 0xD1, 0x0E, 0x63, 0x96, + 0x69, 0x4C, 0x8E, 0xE1, 0x95, 0x07, 0x33, 0xAA, 0xD9, 0x44, 0xF4, 0x2D, 0x6D, 0xFE, 0x44, 0x35, + 0xB7, 0x80, 0xE2, 0x65, 0xEA, 0x76, 0xC4, 0x36, 0x33, 0x9A, 0x58, 0x23, 0xB2, 0x8D, 0xE0, 0xA8, + 0x6E, 0x24, 0x1B, 0x5F, 0x6C, 0x1B, 0x05, 0x8B, 0x3F, 0x77, 0xBE, 0x88, 0xF9, 0x96, 0x7D, 0x73, + 0x82, 0x53, 0xEB, 0x74, 0x89, 0x9F, 0xE5, 0x44, 0xE5, 0xCB, 0xCB, 0xBC, 0x2C, 0xAA, 0xFE, 0x8A, + 0x74, 0xD4, 0x0F, 0xAF, 0x31, 0x61, 0xFF, 0xB2, 0x09, 0x79, 0xB7, 0x00, 0x79, 0x57, 0x45, 0xDE, + 0xD5, 0x91, 0x77, 0xF3, 0x90, 0xF7, 0x0A, 0x90, 0xF7, 0x54, 0xE4, 0x3D, 0x1D, 0x79, 0x2F, 0x0F, + 0xF9, 0x7A, 0x01, 0xF2, 0x75, 0x15, 0xF9, 0xBA, 0x8E, 0x7C, 0x3D, 0x46, 0xFE, 0xF4, 0xB6, 0xA4, + 0x2A, 0xAB, 0xAC, 0x94, 0x2F, 0xF8, 0xC6, 0x0B, 0x40, 0x55, 0xA7, 0xF0, 0x2B, 0xFC, 0xF4, 0x47, + 0x05, 0x0A, 0x2C, 0x42, 0x99, 0x10, 0x48, 0xA8, 0x6F, 0x3B, 0xF4, 0x8E, 0xBD, 0x3B, 0x76, 0x29, + 0x8A, 0x2E, 0x2D, 0x27, 0xCF, 0xD8, 0x02, 0xAE, 0xE5, 0x8C, 0x1B, 0x44, 0x48, 0xCC, 0x78, 0x4B, + 0x48, 0x77, 0x0A, 0xBA, 0x46, 0x97, 0x60, 0x63, 0xDB, 0xF4, 0x20, 0x2E, 0x22, 0xAD, 0xD9, 0x11, + 0xD5, 0x3B, 0x23, 0x7B, 0xD5, 0x95, 0x63, 0xA2, 0xA4, 0xCE, 0x61, 0x12, 0x28, 0xD3, 0x8B, 0xA2, + 0x62, 0x7A, 0xA3, 0x5E, 0x89, 0x6E, 0x76, 0xEC, 0x6E, 0x8B, 0x38, 0x76, 0xAF, 0x44, 0xE7, 0xF1, + 0x3D, 0x93, 0xAE, 0x21, 0xF4, 0x4C, 0x6C, 0x9D, 0x03, 0x9A, 0x74, 0x61, 0x4A, 0xE5, 0xBB, 0xF5, + 0x75, 0x1E, 0x08, 0x3C, 0xD9, 0x3D, 0xDC, 0xAE, 0xF9, 0x9C, 0x05, 0x65, 0x62, 0x3A, 0xEE, 0x52, + 0x42, 0xE5, 0xD0, 0xF8, 0xF3, 0x9D, 0x28, 0xF5, 0x11, 0x18, 0xE9, 0xF1, 0xDC, 0x48, 0xDF, 0xF3, + 0x86, 0x29, 0x7B, 0x8F, 0xF6, 0xC2, 0x7B, 0x6B, 0x61, 0x18, 0xC1, 0xFD, 0x81, 0xB8, 0xBC, 0xAD, + 0x2E, 0x51, 0xD5, 0xB2, 0xF4, 0xAB, 0xB5, 0x8D, 0xA8, 0x88, 0xEC, 0x4D, 0x60, 0x1A, 0xA1, 0xB6, + 0x12, 0xD7, 0xC0, 0xF2, 0x2B, 0xDA, 0xEC, 0x52, 0x1B, 0xA7, 0x86, 0x87, 0x42, 0xC6, 0x67, 0xA5, + 0x34, 0x4A, 0x2C, 0x6A, 0xB1, 0xD5, 0x6D, 0x35, 0xCC, 0x2C, 0x1B, 0x8E, 0x62, 0x53, 0xEC, 0x97, + 0x7A, 0x9E, 0x2B, 0x79, 0x27, 0x2B, 0x2B, 0xDB, 0x63, 0xC1, 0xD3, 0x5A, 0xBB, 0xE4, 0x9B, 0x12, + 0x63, 0x56, 0xF0, 0x56, 0xA0, 0xDC, 0x96, 0xDF, 0xA9, 0xEF, 0x45, 0x39, 0x7F, 0xA5, 0x37, 0x48, + 0xA4, 0x2C, 0xC7, 0x6C, 0x1B, 0xBF, 0x30, 0x09, 0x35, 0x59, 0xC2, 0x1B, 0x03, 0x86, 0x6C, 0xC5, + 0xCB, 0xCF, 0x16, 0x90, 0x2B, 0xBA, 0x66, 0xD6, 0xE3, 0x4A, 0x19, 0x8F, 0x87, 0x6A, 0xAE, 0x56, + 0xFD, 0x09, 0xF6, 0x07, 0x45, 0x52, 0x7A, 0x62, 0xE1, 0x67, 0x73, 0xCF, 0x50, 0x5C, 0x27, 0x49, + 0x68, 0xF9, 0x04, 0xA1, 0x99, 0x8D, 0x6D, 0x77, 0x8A, 0xDA, 0x9B, 0xA4, 0x16, 0xE6, 0xE7, 0x63, + 0x73, 0x4D, 0x52, 0xFC, 0xB4, 0x5A, 0xCD, 0x1F, 0xE4, 0xC1, 0x66, 0x18, 0x06, 0x84, 0xC0, 0xD4, + 0x0F, 0x7D, 0x6A, 0x8D, 0x13, 0x25, 0x28, 0x27, 0x0F, 0x8E, 0x55, 0x16, 0x88, 0x84, 0xE7, 0x7B, + 0x4B, 0x23, 0x47, 0x01, 0x52, 0xE9, 0x80, 0x67, 0x52, 0x82, 0x34, 0xB6, 0xEF, 0xDC, 0xF4, 0x6E, + 0x3B, 0xAF, 0xF1, 0x87, 0xFC, 0x72, 0xD4, 0x7C, 0xDA, 0x9E, 0x42, 0xF6, 0x9D, 0x9A, 0x9E, 0x5C, + 0xE3, 0x16, 0x2F, 0xB2, 0xA7, 0xDD, 0x00, 0x9C, 0x33, 0xD0, 0xB6, 0xE7, 0xCF, 0x1B, 0x65, 0xB2, + 0xE3, 0x9B, 0x66, 0x8D, 0x79, 0xCE, 0x18, 0x6A, 0xFE, 0xEF, 0xA7, 0x3C, 0x6B, 0xC4, 0xD9, 0xCA, + 0xE7, 0x31, 0x73, 0xA4, 0x53, 0x9F, 0x3F, 0xC9, 0xD9, 0x43, 0x4F, 0x8A, 0x3D, 0x37, 0xDB, 0xF1, + 0x14, 0xDA, 0x5E, 0xDA, 0x74, 0xCC, 0xDC, 0x72, 0x1D, 0xD7, 0xD3, 0x35, 0x1C, 0xC2, 0x71, 0xE6, + 0x89, 0xBE, 0xC1, 0x2E, 0xA4, 0xDC, 0x65, 0xD5, 0x1B, 0xDD, 0xF9, 0x5E, 0x2F, 0x9B, 0xB0, 0xE7, + 0xC6, 0x55, 0xA3, 0xC4, 0x26, 0x62, 0xFE, 0xB8, 0x4B, 0xDC, 0xC3, 0x3B, 0xC5, 0x00, 0xFD, 0xCA, + 0x00, 0x17, 0x55, 0x01, 0x7E, 0x96, 0x00, 0x36, 0x8A, 0x01, 0xCE, 0x4F, 0xF6, 0xD3, 0x14, 0x1E, + 0x6A, 0xBC, 0xBF, 0x31, 0x64, 0xCF, 0x88, 0xA9, 0xDE, 0xEA, 0xBB, 0x33, 0x55, 0x44, 0x9D, 0xF6, + 0xE6, 0x4E, 0x11, 0x40, 0xBF, 0x32, 0xC0, 0x45, 0x55, 0x00, 0x59, 0x44, 0xF1, 0xB8, 0xCC, 0x06, + 0x50, 0x45, 0x14, 0x53, 0x78, 0x98, 0xE5, 0xC9, 0x05, 0xA4, 0x14, 0x30, 0x97, 0x2E, 0x32, 0x54, + 0x8C, 0x58, 0x47, 0x22, 0xB4, 0x85, 0xC7, 0x9C, 0xE3, 0x80, 0x0E, 0x36, 0x3B, 0x9D, 0x22, 0xB8, + 0xAE, 0x04, 0xF7, 0x1C, 0xE1, 0x00, 0xAC, 0x6B, 0x6A, 0x96, 0xE4, 0x46, 0xE6, 0x6A, 0xAF, 0xA1, + 0x7A, 0xBF, 0x62, 0xF5, 0x8B, 0x6A, 0xD5, 0xE5, 0x4E, 0xE9, 0x15, 0x55, 0x4F, 0x69, 0xAD, 0xA9, + 0x7E, 0xDA, 0x7D, 0xC4, 0xDF, 0xBA, 0x9D, 0xF5, 0x75, 0x19, 0xB6, 0x93, 0x18, 0xE6, 0x87, 0x94, + 0x69, 0x12, 0x97, 0x3A, 0x7F, 0x18, 0xA6, 0x27, 0x60, 0x98, 0xF2, 0x20, 0xCE, 0x7F, 0x3D, 0xB9, + 0x3C, 0xDF, 0xFB, 0xE5, 0xD7, 0xD2, 0x3C, 0x21, 0x40, 0xFF, 0xED, 0xF9, 0x9B, 0x5F, 0x7F, 0x18, + 0xBF, 0xCA, 0xC6, 0x2F, 0x0B, 0x42, 0x1F, 0x67, 0xDD, 0xED, 0x92, 0xA4, 0x74, 0xC0, 0x5E, 0xA7, + 0x26, 0xE0, 0x46, 0xAF, 0x2E, 0xE0, 0x56, 0x23, 0xD3, 0x55, 0xFB, 0x61, 0xE1, 0xFF, 0x15, 0x2C, + 0xBC, 0x09, 0x3C, 0xB5, 0xC6, 0x96, 0xF4, 0xD6, 0x94, 0xBE, 0xAC, 0x1C, 0x38, 0xD3, 0xDE, 0xFA, + 0xE0, 0x4C, 0x87, 0x67, 0x00, 0xDF, 0xCA, 0xCC, 0xBD, 0x66, 0x70, 0xBD, 0x11, 0xC6, 0x38, 0xB9, + 0xA9, 0xEB, 0xF9, 0x27, 0x34, 0xC1, 0xB1, 0x25, 0x0D, 0xB2, 0x7D, 0xD9, 0xED, 0x74, 0x36, 0xCB, + 0xDA, 0x7B, 0x19, 0xEA, 0xF9, 0x46, 0x2D, 0xA8, 0xE7, 0x8D, 0xD4, 0xEA, 0xBD, 0x18, 0xEA, 0x45, + 0x2D, 0x5A, 0x2F, 0x34, 0x5A, 0x25, 0xC1, 0xB6, 0x6B, 0x11, 0xDB, 0xAE, 0xD3, 0xB0, 0x6E, 0xAF, + 0x0E, 0xAD, 0x6E, 0xAF, 0x0E, 0xAD, 0xDE, 0xBA, 0x32, 0x1D, 0x94, 0x95, 0xC7, 0x46, 0xE7, 0x79, + 0x4F, 0xB1, 0xB6, 0x25, 0xE9, 0x31, 0xB8, 0x6E, 0x23, 0x63, 0xAB, 0x66, 0x26, 0xB7, 0x20, 0x5E, + 0x92, 0xF3, 0xA1, 0xAA, 0xAA, 0x6F, 0xC1, 0x6C, 0x25, 0xC1, 0x65, 0xF8, 0xAF, 0xC5, 0x80, 0xAA, + 0xE6, 0x97, 0x87, 0x7B, 0x51, 0x13, 0x6E, 0xBB, 0x1E, 0x9C, 0xA6, 0x5C, 0x73, 0x9B, 0x8D, 0xB3, + 0x76, 0x86, 0xEA, 0xCE, 0x19, 0x7A, 0x57, 0x56, 0x33, 0xDA, 0x3A, 0xE9, 0x1A, 0xD0, 0x27, 0xFD, + 0x93, 0x8D, 0xAA, 0xD6, 0xFE, 0xD8, 0xBB, 0x43, 0x33, 0x7B, 0xE7, 0xD8, 0xE1, 0xCD, 0x1F, 0xDD, + 0xE2, 0x77, 0x6A, 0x99, 0xFC, 0xDE, 0x23, 0x9A, 0xFC, 0xDE, 0x63, 0x9A, 0xFC, 0xDE, 0x23, 0x9A, + 0xFC, 0xDE, 0x0F, 0x93, 0x3F, 0xB3, 0xC9, 0xEF, 0x3D, 0xB6, 0xC9, 0xEF, 0xD5, 0x34, 0xF9, 0xBD, + 0x9A, 0x26, 0xBF, 0x57, 0xD3, 0xE4, 0xF7, 0x1E, 0xC9, 0xE4, 0x77, 0x36, 0xFF, 0x73, 0xAB, 0x8C, + 0x5C, 0xCB, 0xCF, 0x18, 0x65, 0x80, 0x85, 0xD5, 0x56, 0x1A, 0xFB, 0x2F, 0x33, 0xD3, 0x4C, 0x03, + 0xF6, 0xC6, 0x61, 0x72, 0x89, 0x26, 0x48, 0xDF, 0x2E, 0xE1, 0x8F, 0xD5, 0x25, 0x12, 0xA0, 0xF8, + 0xF7, 0x4E, 0xBA, 0xCE, 0x27, 0xAD, 0xCE, 0x27, 0x43, 0x9D, 0xDF, 0xB4, 0x3A, 0xBF, 0xED, 0xC8, + 0xBB, 0x78, 0xC0, 0xCD, 0x3B, 0xEA, 0xD9, 0x34, 0x74, 0x06, 0xB9, 0x1C, 0xA5, 0xEF, 0xBB, 0x0C, + 0x05, 0x18, 0x94, 0x14, 0xDF, 0x67, 0x89, 0x2B, 0x7B, 0xAE, 0x56, 0xF9, 0xFD, 0xDE, 0xE1, 0xDE, + 0xD9, 0xBE, 0xA1, 0xEA, 0xDE, 0x28, 0x14, 0xBD, 0xAE, 0x26, 0x85, 0x19, 0x5B, 0xFE, 0x57, 0x25, + 0x23, 0x4C, 0xB7, 0x20, 0xED, 0x4B, 0x01, 0x78, 0xCF, 0x04, 0xCE, 0xAF, 0x7E, 0x0B, 0xFA, 0x96, + 0xFD, 0x1F, 0xD3, 0x20, 0x04, 0x46, 0xF5, 0x50, 0x20, 0x76, 0x5A, 0x7B, 0x4A, 0xEF, 0x8E, 0xBD, + 0xE4, 0x86, 0x50, 0x2A, 0x83, 0x4A, 0x52, 0xC7, 0x10, 0x18, 0x45, 0xBF, 0x39, 0xA1, 0x96, 0x0E, + 0xE1, 0xC6, 0xB1, 0x59, 0xBA, 0x42, 0xC7, 0x3D, 0x63, 0x69, 0x68, 0x78, 0x23, 0x30, 0x76, 0x0D, + 0x73, 0xAD, 0x81, 0x97, 0x72, 0xE4, 0x9E, 0xF9, 0x1E, 0xDE, 0xDE, 0x8F, 0x93, 0x44, 0xE8, 0x34, + 0x11, 0xEB, 0x9E, 0x6B, 0xCB, 0xD1, 0x58, 0x58, 0x8D, 0xFB, 0x38, 0x3C, 0x19, 0x27, 0x08, 0x3A, + 0xF9, 0x63, 0x29, 0x61, 0x83, 0xE5, 0x89, 0xEC, 0x98, 0xC2, 0xB7, 0xF6, 0xBD, 0xF1, 0x64, 0x44, + 0xC3, 0x24, 0x71, 0x12, 0x8B, 0x51, 0x8B, 0x30, 0xC8, 0xB8, 0x05, 0x39, 0x73, 0x43, 0xF8, 0xD7, + 0x74, 0x43, 0xB4, 0x46, 0x46, 0xD4, 0x1A, 0xD1, 0xCD, 0xAE, 0x7D, 0x6B, 0x84, 0x69, 0x55, 0xEF, + 0x6E, 0x28, 0xBF, 0xDC, 0x75, 0xD8, 0x3F, 0x5B, 0xEF, 0x91, 0x1B, 0x2B, 0xC0, 0xBB, 0x52, 0xD7, + 0x8E, 0x3F, 0x86, 0x42, 0x1F, 0xF4, 0xDB, 0x99, 0x84, 0xC4, 0xBB, 0xE6, 0x91, 0xD2, 0xB8, 0xE8, + 0x4F, 0x84, 0x43, 0xAE, 0x7D, 0x6F, 0x4C, 0xF6, 0xCE, 0x38, 0xC0, 0x90, 0x4C, 0x80, 0x2B, 0x29, + 0x52, 0x8F, 0x63, 0xC1, 0x5C, 0x0A, 0xE7, 0x1C, 0x8D, 0x74, 0x48, 0x7F, 0x00, 0x9C, 0xF8, 0x63, + 0xC7, 0xA5, 0x40, 0xDF, 0x19, 0xDC, 0x90, 0x44, 0x03, 0x30, 0xEB, 0x27, 0xB2, 0xE3, 0xF9, 0xCE, + 0x10, 0xC6, 0xCE, 0x88, 0x11, 0x8E, 0x3D, 0xC3, 0x28, 0x3B, 0x43, 0x24, 0xF4, 0x3F, 0xED, 0x12, + 0x77, 0x3A, 0x1A, 0x2D, 0xEB, 0xD1, 0x85, 0x91, 0x14, 0xB5, 0xFA, 0x65, 0x92, 0x36, 0xF0, 0x6F, + 0x2F, 0xC9, 0xDE, 0x68, 0x44, 0xFA, 0xF0, 0xDD, 0xCE, 0x4F, 0xDD, 0xE7, 0xB9, 0x81, 0x37, 0xA2, + 0xED, 0x11, 0x68, 0x6C, 0xE3, 0x23, 0xBF, 0x91, 0x4A, 0xE0, 0x3F, 0x90, 0x13, 0x08, 0x2D, 0x2D, + 0x03, 0x73, 0x12, 0x8F, 0xEB, 0x38, 0x29, 0xE3, 0xC8, 0xB3, 0xEC, 0x5F, 0x2C, 0x27, 0x54, 0x2E, + 0xA2, 0x63, 0x26, 0x10, 0xF1, 0x12, 0x40, 0x30, 0xBD, 0x1A, 0x3B, 0x61, 0x94, 0x04, 0x11, 0x33, + 0x86, 0xC0, 0x60, 0xC3, 0xF2, 0xE0, 0x73, 0xE7, 0x4B, 0x12, 0xD7, 0x8E, 0x53, 0x96, 0x88, 0x6D, + 0x77, 0xE9, 0x1D, 0xC1, 0x5B, 0x80, 0x72, 0x52, 0x8B, 0xA8, 0xB8, 0x6D, 0x4D, 0x26, 0x7C, 0x50, + 0xA5, 0xD1, 0xB6, 0x18, 0xD9, 0xE5, 0x04, 0xA7, 0xF5, 0x1F, 0xD6, 0x37, 0x81, 0xEF, 0xD7, 0x93, + 0xE3, 0xF7, 0x21, 0xA6, 0x1C, 0xFB, 0xC7, 0x94, 0x06, 0x61, 0x84, 0x15, 0x2B, 0xB4, 0x3D, 0x40, + 0xB8, 0xD4, 0x38, 0xFB, 0xD0, 0xBF, 0xC0, 0x1C, 0x26, 0x6B, 0x53, 0xD6, 0xA2, 0x08, 0x71, 0x43, + 0xAE, 0xC9, 0x86, 0x56, 0xC4, 0x49, 0x34, 0xF2, 0xB8, 0x19, 0x93, 0xA5, 0x61, 0x88, 0xB5, 0x7C, + 0x75, 0xE5, 0xBF, 0xE6, 0x85, 0x0E, 0xDE, 0xE1, 0x9B, 0x28, 0x09, 0xA4, 0x1A, 0x3B, 0x39, 0xA2, + 0xED, 0x87, 0x56, 0x38, 0x0D, 0x30, 0xBC, 0x59, 0x35, 0xC8, 0xF9, 0x04, 0xA1, 0x7A, 0x1E, 0xD2, + 0xD4, 0x40, 0xE6, 0xC3, 0xCE, 0x5C, 0xA9, 0x91, 0x39, 0x98, 0x15, 0x02, 0x9E, 0x3F, 0xA4, 0xE1, + 0x99, 0xE5, 0xF8, 0x30, 0x23, 0xA2, 0x71, 0x55, 0x67, 0x90, 0xAB, 0xD0, 0x7D, 0xCB, 0x6A, 0xF0, + 0x32, 0x83, 0x88, 0x50, 0x7B, 0x59, 0x5E, 0x9F, 0x80, 0xE1, 0xF2, 0xC2, 0x90, 0xBA, 0x6D, 0x29, + 0x27, 0xC1, 0x84, 0x52, 0xFF, 0x64, 0x6F, 0x3F, 0xD0, 0xE1, 0x4E, 0x3D, 0x97, 0x66, 0x45, 0xA6, + 0x32, 0x8A, 0x87, 0xC1, 0xE4, 0xD4, 0xBB, 0x3B, 0x03, 0xF0, 0xC0, 0x60, 0x7E, 0x81, 0x31, 0x66, + 0x24, 0xF5, 0x9C, 0x70, 0xC3, 0xC8, 0x44, 0x89, 0x02, 0x03, 0xC7, 0x0C, 0x8E, 0x85, 0xEA, 0x88, + 0xE4, 0x5D, 0x59, 0x11, 0xB2, 0x32, 0x9E, 0x84, 0x85, 0x38, 0x5C, 0xC1, 0xB2, 0xED, 0xC3, 0x5B, + 0xF8, 0x05, 0xC3, 0x94, 0x29, 0xE0, 0x5F, 0x6A, 0x1C, 0x7C, 0x38, 0x01, 0x5B, 0x1C, 0xE2, 0x37, + 0xE8, 0x08, 0x8A, 0xE9, 0xF1, 0x96, 0x28, 0x56, 0x59, 0x26, 0xBB, 0xAF, 0x81, 0xC1, 0x58, 0xC3, + 0x85, 0xC0, 0x4A, 0xC4, 0x3E, 0xA4, 0x93, 0x8C, 0x29, 0x11, 0x0F, 0xEC, 0x2E, 0x3D, 0x3A, 0xF5, + 0xEC, 0xD6, 0x1E, 0xFC, 0xC2, 0x31, 0xC7, 0x11, 0x0F, 0x0E, 0x86, 0x41, 0x58, 0xDF, 0xE0, 0x17, + 0x35, 0xF4, 0x81, 0x57, 0xFB, 0xEC, 0x7C, 0x69, 0x7B, 0xEE, 0x60, 0xE4, 0x0C, 0x30, 0xCD, 0x47, + 0x2C, 0xDB, 0xA5, 0xD4, 0x9B, 0xCD, 0x6A, 0xFA, 0xBD, 0x8C, 0x97, 0x58, 0xB9, 0x8B, 0x65, 0x05, + 0x53, 0x9F, 0x05, 0x4D, 0xA3, 0x23, 0xFC, 0xFE, 0x77, 0x10, 0x7E, 0x5A, 0x4E, 0x1C, 0x1F, 0x0E, + 0x7C, 0x23, 0x49, 0x03, 0xA2, 0x3E, 0x1D, 0xA8, 0xDB, 0x26, 0x64, 0x2D, 0x93, 0x9E, 0x14, 0x8C, + 0xFD, 0x20, 0x8F, 0x76, 0x23, 0xCA, 0x79, 0x30, 0x97, 0x50, 0xCD, 0xE3, 0x4D, 0x6A, 0x82, 0x81, + 0x39, 0xC3, 0xC3, 0xF0, 0x95, 0x59, 0xAB, 0xF7, 0xC8, 0x7C, 0x62, 0x47, 0x02, 0x51, 0xDF, 0xFC, + 0xD2, 0x2F, 0xB7, 0x23, 0xCC, 0xF3, 0xCB, 0x7C, 0x92, 0xD7, 0xD4, 0xA2, 0xB7, 0x08, 0x31, 0x8F, + 0xE6, 0x44, 0x88, 0x4A, 0xB5, 0x25, 0x83, 0xCF, 0xA4, 0x21, 0xD9, 0x8D, 0x35, 0xB4, 0x25, 0xFF, + 0xC5, 0xF3, 0xDA, 0x2D, 0x9B, 0xE9, 0x21, 0x75, 0xDE, 0x4E, 0x5C, 0x17, 0xE4, 0x35, 0x73, 0x18, + 0x2F, 0x11, 0xEA, 0x37, 0xF3, 0x1D, 0xCB, 0xE8, 0x34, 0xEF, 0x56, 0xBE, 0xD3, 0xF3, 0x44, 0x99, + 0x1A, 0xC9, 0x1B, 0x91, 0xDD, 0x48, 0x2E, 0x84, 0x74, 0x23, 0x95, 0x4A, 0x59, 0x3B, 0x7D, 0xA9, + 0xF5, 0x75, 0x8D, 0x2D, 0x3D, 0xE5, 0x99, 0x20, 0x63, 0x1E, 0x77, 0xE9, 0x48, 0xF4, 0x45, 0x7B, + 0x13, 0x4F, 0x37, 0xF7, 0xC0, 0xB9, 0x85, 0xA9, 0x18, 0xFD, 0xB6, 0xE3, 0xEE, 0xDA, 0x71, 0x4F, + 0x41, 0xF6, 0xA0, 0x5E, 0x44, 0x2A, 0xDC, 0x1E, 0xB8, 0x4D, 0xDF, 0x76, 0x2D, 0xCD, 0xCF, 0x76, + 0x7B, 0x6B, 0x8E, 0xFC, 0xA4, 0xF7, 0x8B, 0xAA, 0x30, 0xD3, 0xED, 0x6E, 0xCD, 0x55, 0x3A, 0x7A, + 0x6A, 0xE1, 0x2A, 0xBC, 0x6C, 0xE0, 0xBE, 0x45, 0x0D, 0x56, 0xEA, 0x51, 0x53, 0x36, 0x57, 0x54, + 0xCC, 0x86, 0x31, 0x6A, 0x7A, 0xE7, 0xBC, 0xF6, 0xD0, 0xAC, 0xF8, 0x68, 0x7A, 0x32, 0xE2, 0x0C, + 0x97, 0x83, 0x33, 0xAF, 0x2F, 0x9B, 0x46, 0x74, 0x09, 0xF8, 0xAC, 0x56, 0xC7, 0xAF, 0xD3, 0xCC, + 0xA3, 0xD5, 0x65, 0x9E, 0xBA, 0xD1, 0x5A, 0xCD, 0x41, 0xEA, 0xB7, 0x3A, 0x1F, 0xDE, 0xD0, 0x6A, + 0xED, 0xBA, 0xD8, 0xEC, 0x2D, 0x4F, 0x23, 0x2C, 0x68, 0xBD, 0xE1, 0x62, 0x1A, 0x00, 0x89, 0x24, + 0xF1, 0x5A, 0x14, 0x6C, 0xA1, 0x28, 0x0A, 0x91, 0xA9, 0x1B, 0x77, 0x06, 0xB1, 0xE0, 0x32, 0x0E, + 0x73, 0xA2, 0x62, 0xD6, 0x5F, 0x97, 0x8E, 0x66, 0x11, 0x48, 0x1A, 0x55, 0x9C, 0xD5, 0xA4, 0x63, + 0xD6, 0x81, 0x08, 0xE2, 0x8D, 0x35, 0xB5, 0x0F, 0x7C, 0x6F, 0x62, 0x63, 0x66, 0x28, 0xE3, 0xD4, + 0xAB, 0x3C, 0x98, 0x56, 0xA8, 0x2F, 0x25, 0x38, 0xEA, 0x9A, 0x67, 0xC7, 0x32, 0x1C, 0x09, 0x67, + 0xA1, 0x12, 0x47, 0x75, 0x69, 0x55, 0x68, 0xBD, 0x41, 0xDB, 0xB3, 0x9F, 0x30, 0x9C, 0x51, 0xEB, + 0x0B, 0xDF, 0x46, 0x34, 0xF7, 0xF7, 0x04, 0xCC, 0x14, 0x7F, 0x1C, 0xB7, 0x96, 0xC0, 0x8A, 0xC1, + 0x15, 0x19, 0x4C, 0x03, 0x7A, 0xEC, 0x0D, 0xAC, 0x91, 0xF3, 0x3B, 0xB5, 0x0F, 0xA0, 0x9D, 0xBE, + 0x73, 0x35, 0xE5, 0x69, 0x24, 0xEB, 0x37, 0x3F, 0x07, 0x67, 0x6E, 0xCB, 0x47, 0x26, 0xA0, 0x0B, + 0x58, 0x01, 0x1E, 0xC3, 0x9A, 0x76, 0x64, 0xEA, 0xFD, 0x12, 0xF2, 0xA8, 0x8B, 0xD4, 0xA0, 0x29, + 0xFA, 0x4B, 0x8A, 0x33, 0xEA, 0x47, 0x85, 0x87, 0x19, 0x73, 0x47, 0xD4, 0x01, 0x0D, 0x2D, 0x67, + 0x14, 0x54, 0x94, 0x4B, 0x15, 0x44, 0x39, 0xB2, 0x78, 0x6F, 0xF9, 0x36, 0x6E, 0x05, 0x71, 0x41, + 0xC4, 0x2F, 0xCC, 0xCC, 0x49, 0x34, 0x19, 0xD8, 0x2B, 0x49, 0x4A, 0x86, 0x9D, 0x4D, 0x54, 0xA5, + 0x30, 0x99, 0x64, 0xC5, 0x36, 0x96, 0xE6, 0x20, 0x95, 0x08, 0x4F, 0xA9, 0xF6, 0xB3, 0x1D, 0x97, + 0x7A, 0x0D, 0xCE, 0x07, 0x35, 0x79, 0x0C, 0xD2, 0x96, 0xDD, 0x1C, 0xDC, 0x05, 0x15, 0x5B, 0x86, + 0xCD, 0x30, 0xEC, 0x16, 0xCE, 0xE6, 0x23, 0xE4, 0x22, 0x2B, 0xF4, 0x11, 0x94, 0x87, 0xD7, 0x66, + 0x14, 0x40, 0xF1, 0xF3, 0x6D, 0xB2, 0xD1, 0xF4, 0xAD, 0x7A, 0xBD, 0x9C, 0x0B, 0x69, 0x6C, 0x5B, + 0xED, 0xD1, 0x8D, 0xAC, 0xBE, 0x07, 0xA2, 0xEA, 0xE0, 0x89, 0x36, 0xF6, 0xB2, 0x69, 0x9D, 0x1F, + 0x9D, 0x1E, 0xFE, 0x3A, 0x0F, 0x79, 0x2A, 0xD8, 0xCA, 0x99, 0x8F, 0x14, 0x64, 0x4D, 0xE3, 0x51, + 0x1E, 0x8F, 0x41, 0x0E, 0xCA, 0xB3, 0x5D, 0x33, 0x4A, 0xA1, 0xEC, 0x13, 0x60, 0xBA, 0x0C, 0x12, + 0xB8, 0x59, 0x24, 0x50, 0x02, 0x8B, 0xA9, 0xFD, 0xA6, 0x77, 0xBD, 0x66, 0x95, 0x43, 0xC5, 0xB7, + 0xC2, 0x52, 0xF2, 0x00, 0xF8, 0xB1, 0x15, 0x3A, 0x03, 0x15, 0xC9, 0x4C, 0xC2, 0xA9, 0x88, 0x32, + 0x43, 0x52, 0xD1, 0x4B, 0x60, 0x73, 0x10, 0x50, 0x89, 0x47, 0xC5, 0x32, 0xE5, 0xC2, 0x60, 0xE7, + 0x22, 0x8E, 0x7C, 0x4C, 0xE9, 0xAD, 0xC4, 0xBD, 0x51, 0xE8, 0x84, 0x53, 0xBB, 0x96, 0x92, 0x28, + 0x47, 0xF7, 0x29, 0xF4, 0xFA, 0x83, 0x8C, 0x8B, 0x22, 0x90, 0xDA, 0xB4, 0x99, 0x33, 0x19, 0x35, + 0x90, 0x62, 0x8E, 0xC8, 0xE3, 0xFB, 0xB0, 0xF7, 0xFC, 0x3E, 0xEC, 0x3D, 0x79, 0x45, 0xDC, 0xE9, + 0x78, 0x3F, 0xF5, 0xAE, 0x26, 0x14, 0xA5, 0x6F, 0xC5, 0x82, 0x5B, 0x1E, 0x7A, 0xAE, 0xB8, 0x14, + 0xCB, 0x9E, 0xDA, 0xC0, 0xAC, 0x2A, 0x6F, 0xD8, 0x57, 0x7C, 0x0E, 0xE1, 0x5E, 0x09, 0xAC, 0x49, + 0x6A, 0x1B, 0x9B, 0x80, 0xC7, 0x4B, 0x99, 0x2D, 0x88, 0x32, 0xBE, 0x24, 0xF8, 0xF7, 0xB1, 0xFE, + 0xD2, 0xBD, 0xAC, 0x5E, 0xD2, 0xAB, 0x06, 0xCB, 0x72, 0x10, 0x47, 0xC6, 0x34, 0x26, 0xA5, 0x44, + 0xAA, 0x16, 0x55, 0x55, 0xF0, 0x2C, 0x66, 0x89, 0x99, 0x49, 0xF0, 0x70, 0xC2, 0xB0, 0xCF, 0x32, + 0x35, 0x15, 0x20, 0x32, 0x86, 0x08, 0xCC, 0x8D, 0xFD, 0x39, 0x30, 0x6E, 0x62, 0x59, 0x89, 0xA5, + 0xCA, 0x4B, 0xDB, 0x93, 0x93, 0x50, 0x28, 0x43, 0x87, 0xB5, 0x9B, 0xDD, 0xF5, 0xB5, 0x3F, 0xC9, + 0x25, 0x9A, 0x9D, 0x85, 0xE8, 0x9E, 0xA5, 0x9B, 0xFB, 0x66, 0xDA, 0x5D, 0x2E, 0x33, 0x78, 0xBE, + 0xED, 0x98, 0xB6, 0x89, 0xE5, 0x41, 0x84, 0x59, 0x8D, 0xC5, 0x41, 0x32, 0xCB, 0x28, 0xAC, 0xB1, + 0x82, 0x95, 0x90, 0x8B, 0x82, 0x5D, 0x63, 0x35, 0x9D, 0x95, 0x61, 0x8C, 0xE1, 0x37, 0xFE, 0x77, + 0x12, 0x2F, 0x43, 0x8E, 0xDC, 0x81, 0xCF, 0xA2, 0x1C, 0x26, 0x22, 0xCF, 0x13, 0x59, 0x25, 0xC1, + 0x9D, 0x35, 0xE1, 0x6F, 0x22, 0xB3, 0x03, 0x6A, 0x98, 0x7F, 0x12, 0x9E, 0x48, 0xC0, 0x78, 0xE2, + 0x69, 0x2F, 0xB0, 0x8E, 0x8B, 0x29, 0x99, 0x6F, 0xC0, 0x2E, 0xD3, 0x20, 0x79, 0x29, 0x32, 0x21, + 0x45, 0x5E, 0xAB, 0x3B, 0x6B, 0xEC, 0x12, 0xBE, 0xF5, 0x95, 0x9E, 0xD0, 0xF7, 0x08, 0xE3, 0xEF, + 0x18, 0x4A, 0x58, 0x12, 0xBA, 0x9D, 0x74, 0xEF, 0x56, 0xD6, 0x8B, 0x32, 0xBD, 0xFB, 0x8D, 0xF5, + 0x6E, 0x5A, 0x36, 0xF2, 0x3F, 0x99, 0xE1, 0x24, 0x23, 0x95, 0xF9, 0x64, 0xA0, 0x1C, 0x3D, 0x59, + 0x42, 0xAB, 0xA4, 0xBB, 0x9C, 0x4D, 0x95, 0x09, 0x23, 0x8F, 0xE8, 0xC3, 0x1C, 0x05, 0xC5, 0x4C, + 0xA6, 0xDC, 0x5A, 0x13, 0x5F, 0x05, 0xAD, 0x5B, 0xC5, 0x4B, 0x34, 0xB2, 0x6A, 0x15, 0x08, 0x4B, + 0xA2, 0xC9, 0xDA, 0x6A, 0x22, 0x09, 0xD8, 0x4E, 0xBD, 0x90, 0xBE, 0x24, 0x8D, 0x02, 0xE2, 0x2B, + 0x40, 0xBC, 0x41, 0x3C, 0x77, 0x74, 0x4F, 0xEE, 0x3C, 0xFF, 0x6B, 0x10, 0x31, 0x0B, 0x7F, 0x3B, + 0xD7, 0x26, 0xB4, 0x39, 0xF8, 0xD8, 0xD3, 0x1E, 0x8E, 0x1B, 0xB6, 0xD8, 0x8B, 0xE1, 0x01, 0xCB, + 0x9A, 0xDC, 0x26, 0x1F, 0x71, 0xAC, 0x58, 0x3E, 0x3E, 0x2E, 0x15, 0xE2, 0x58, 0xA1, 0x94, 0x58, + 0x57, 0xDE, 0x2D, 0xAD, 0x2A, 0xA6, 0x95, 0x48, 0x4C, 0x07, 0x34, 0x57, 0x4C, 0x0F, 0x4A, 0xA6, + 0x0D, 0x72, 0x74, 0x4D, 0xAC, 0x11, 0xD4, 0xB7, 0xEF, 0xD9, 0xE8, 0x13, 0x03, 0x2F, 0x1E, 0xBD, + 0x2D, 0x26, 0x49, 0xE2, 0x84, 0x64, 0x04, 0xB2, 0x14, 0x23, 0x52, 0xB3, 0xE4, 0x2C, 0x88, 0x64, + 0x6F, 0xFC, 0x9E, 0x83, 0x3E, 0xEE, 0x38, 0x43, 0x5B, 0x80, 0xCD, 0xE8, 0x10, 0x27, 0x20, 0xEF, + 0x25, 0xAB, 0xA1, 0xA0, 0x8A, 0x99, 0x4B, 0xEB, 0x3D, 0xFE, 0xBB, 0x82, 0xF6, 0x7F, 0x7D, 0x9C, + 0xE1, 0x80, 0x4F, 0x08, 0xC4, 0xDC, 0x2C, 0x78, 0x30, 0x64, 0x9C, 0x29, 0x16, 0x26, 0xC8, 0x33, + 0xB6, 0x09, 0xAD, 0x0A, 0x23, 0x7C, 0x9C, 0xE8, 0x41, 0xB6, 0x72, 0x55, 0x4D, 0xAD, 0x87, 0x6E, + 0xDF, 0xFE, 0xE1, 0xDB, 0x78, 0xEA, 0x96, 0x9F, 0xFF, 0x8A, 0xAF, 0x7C, 0xB8, 0x30, 0xE9, 0x60, + 0x3C, 0x13, 0xD6, 0x8C, 0x4F, 0x3F, 0x7D, 0x3A, 0x86, 0xC1, 0xF2, 0xC6, 0xB2, 0xF7, 0xF1, 0xC9, + 0xD0, 0xA5, 0x74, 0x9D, 0xC8, 0xA3, 0x35, 0xBE, 0x46, 0x2A, 0xD5, 0x16, 0x6F, 0x91, 0xA6, 0x1E, + 0x85, 0xDE, 0xD8, 0x66, 0xAF, 0x91, 0x5A, 0x30, 0x6F, 0xA9, 0x4F, 0x92, 0x96, 0x7A, 0x9B, 0x5D, + 0x0A, 0xEA, 0x6E, 0x91, 0xD5, 0xE7, 0xD1, 0x9B, 0xAA, 0xCF, 0x53, 0x8F, 0xAB, 0x46, 0x65, 0x48, + 0x52, 0xFC, 0x5A, 0x9F, 0xD8, 0xA7, 0xC7, 0x24, 0xF6, 0xDB, 0x3C, 0x89, 0x65, 0x3C, 0x00, 0xA7, + 0x4C, 0xF9, 0xD1, 0x0B, 0x4A, 0xD8, 0x73, 0xC4, 0x1A, 0x5A, 0xF8, 0x02, 0x1F, 0x7F, 0xD6, 0xC1, + 0x91, 0x14, 0x93, 0x3F, 0x13, 0x63, 0xD3, 0x6F, 0xEA, 0x5D, 0x17, 0x36, 0x88, 0x77, 0x44, 0xC9, + 0x2B, 0x0C, 0x1C, 0xF6, 0x7C, 0x3B, 0x60, 0xEA, 0x12, 0x05, 0xBD, 0xAD, 0xAC, 0xB0, 0x52, 0x7D, + 0x74, 0x22, 0x42, 0x30, 0xD4, 0x61, 0xC0, 0xB4, 0x2E, 0x06, 0xFB, 0xCC, 0x2A, 0x7F, 0x89, 0x92, + 0x32, 0x13, 0x3D, 0x17, 0x6C, 0xE4, 0x55, 0x2B, 0xBA, 0x26, 0x9D, 0xCA, 0x31, 0x94, 0x98, 0x79, + 0xD9, 0x30, 0x54, 0xD3, 0x64, 0x70, 0x78, 0xA6, 0x87, 0xC1, 0x0A, 0x69, 0xB2, 0xC4, 0xA8, 0x89, + 0xB6, 0x65, 0x15, 0x7C, 0xCA, 0x2A, 0xF8, 0x4D, 0x4F, 0xBA, 0x5B, 0xD1, 0x38, 0xF2, 0xD7, 0x52, + 0x98, 0xB8, 0x77, 0x0D, 0x52, 0x5D, 0x7E, 0x96, 0xD1, 0xAE, 0xF6, 0x64, 0x1A, 0xDC, 0x2C, 0x2D, + 0xB4, 0x4D, 0xCB, 0x86, 0x84, 0x9F, 0x48, 0x08, 0xD7, 0x98, 0xBA, 0x21, 0xB2, 0x29, 0xC6, 0xBE, + 0xC6, 0xB6, 0x28, 0x8E, 0xB8, 0x04, 0x44, 0x22, 0xB0, 0x19, 0x23, 0x73, 0xA1, 0xA6, 0x74, 0x67, + 0x42, 0xEE, 0xD1, 0xE4, 0x6E, 0x20, 0x42, 0xBC, 0x66, 0x49, 0xA5, 0xD5, 0x99, 0xD2, 0xA4, 0x42, + 0x50, 0xD7, 0xAC, 0x40, 0x08, 0x80, 0xB2, 0x11, 0xAB, 0x81, 0x48, 0x57, 0xA4, 0x00, 0x25, 0x3E, + 0x4D, 0xB2, 0xE8, 0xED, 0xA5, 0xC6, 0x01, 0xE3, 0x9E, 0xE0, 0x21, 0x19, 0x6B, 0x0D, 0x2E, 0x17, + 0x62, 0xF0, 0x15, 0xD2, 0xF8, 0x6B, 0x63, 0x39, 0x6B, 0xEB, 0x47, 0xEE, 0x12, 0xE4, 0x64, 0x40, + 0xB1, 0x05, 0x60, 0x13, 0x33, 0xD6, 0x8E, 0xF9, 0x62, 0xC4, 0x40, 0x62, 0xC5, 0xA0, 0x7F, 0x47, + 0x19, 0x66, 0xDE, 0xAD, 0xE1, 0xD2, 0xEC, 0x7E, 0xC9, 0xA8, 0xFA, 0x29, 0x55, 0xB5, 0x97, 0x55, + 0xF5, 0xB7, 0x54, 0xD5, 0x75, 0xAD, 0xAA, 0x79, 0xF4, 0x4B, 0x1D, 0x6A, 0x7A, 0xBF, 0x4F, 0xE6, + 0xBA, 0xA0, 0xC6, 0xA7, 0xC2, 0x1A, 0xBF, 0x65, 0xD5, 0x50, 0x59, 0x53, 0x5E, 0xAA, 0x8B, 0x1F, + 0xD5, 0x91, 0x04, 0x0D, 0x5E, 0xAC, 0x6F, 0x81, 0x5F, 0xC8, 0x15, 0x80, 0x58, 0xAE, 0x4D, 0xC6, + 0x9E, 0xEB, 0x05, 0x13, 0x0B, 0x56, 0x71, 0x2C, 0x46, 0x9A, 0x99, 0x61, 0x6D, 0xA5, 0x9E, 0x28, + 0x8A, 0x14, 0x68, 0x9D, 0xA9, 0x06, 0x22, 0x9F, 0x77, 0x32, 0xF5, 0xA3, 0x32, 0xA4, 0x8D, 0x4A, + 0x6A, 0x66, 0xE0, 0xFB, 0x09, 0x59, 0x68, 0x93, 0xE6, 0xCB, 0x4D, 0xC6, 0xFB, 0x4A, 0x7A, 0x68, + 0xB9, 0xF4, 0xDA, 0x0E, 0x66, 0x66, 0xF4, 0x7C, 0x6A, 0x37, 0xF2, 0x9E, 0xE2, 0x64, 0x3B, 0x21, + 0x33, 0x93, 0x15, 0xA5, 0x2F, 0xC9, 0xAF, 0x6B, 0x9F, 0xD6, 0x7E, 0x6B, 0xA8, 0xF9, 0xCF, 0x0D, + 0xAD, 0x7F, 0x45, 0x36, 0x97, 0x53, 0xC7, 0x5E, 0x99, 0x32, 0x0D, 0x9C, 0xDF, 0x29, 0x31, 0x99, + 0x66, 0xC5, 0x3A, 0xC6, 0x3E, 0x6E, 0x32, 0x75, 0x56, 0x9D, 0x2B, 0x71, 0x80, 0x7A, 0x13, 0xD6, + 0xF7, 0x52, 0x80, 0x3A, 0x7A, 0xAB, 0xA0, 0x06, 0x22, 0x21, 0x76, 0x93, 0x57, 0x90, 0x87, 0x29, + 0xFF, 0xC2, 0xF6, 0x2E, 0x8C, 0x13, 0x6C, 0xAA, 0x66, 0x34, 0x86, 0x58, 0xB1, 0x3A, 0xDA, 0x32, + 0x85, 0x80, 0xD9, 0xC0, 0x39, 0xB8, 0x3A, 0x29, 0xFC, 0x79, 0xA9, 0xF1, 0xBF, 0xCC, 0x40, 0x82, + 0x1A, 0xC0, 0x52, 0x6B, 0x70, 0xB3, 0x64, 0xDE, 0x85, 0x94, 0x6D, 0xD2, 0x9F, 0x97, 0xC2, 0x1B, + 0x27, 0xE0, 0x9B, 0x30, 0x4B, 0xCB, 0xB9, 0x56, 0xDD, 0x55, 0xAD, 0x7A, 0x3B, 0x98, 0x5E, 0xF1, + 0x55, 0xE1, 0x12, 0xF8, 0x4F, 0xDD, 0x4D, 0xE5, 0x75, 0x74, 0x09, 0x69, 0x0C, 0x0A, 0x13, 0x1E, + 0x4F, 0x88, 0x1E, 0x59, 0xB2, 0x78, 0x0A, 0x8C, 0xEC, 0x95, 0xF6, 0x61, 0xFD, 0x0B, 0x47, 0x91, + 0x6C, 0xF6, 0x6A, 0x4E, 0x78, 0x74, 0x23, 0xB0, 0x9C, 0x23, 0x1E, 0xD5, 0x2E, 0x72, 0xC6, 0xD5, + 0x7A, 0x65, 0x1C, 0xF2, 0x08, 0x62, 0x5E, 0x4E, 0x79, 0xF2, 0x3C, 0x56, 0xAE, 0x3B, 0x1B, 0x1F, + 0x38, 0x80, 0x47, 0xDB, 0xED, 0x76, 0xD6, 0x37, 0x5A, 0xE4, 0xC5, 0x0B, 0x85, 0x3A, 0xFF, 0x8C, + 0x2C, 0x60, 0x41, 0x65, 0xA7, 0x59, 0x3F, 0x77, 0x40, 0x3A, 0x9B, 0xD8, 0xD7, 0x0A, 0x89, 0x4D, + 0xF6, 0x60, 0xDE, 0x66, 0x5D, 0xEC, 0xDA, 0xA1, 0x03, 0xD0, 0xE8, 0x75, 0x3A, 0xED, 0x0E, 0xBB, + 0xE0, 0xD7, 0x56, 0x3C, 0x73, 0xF6, 0x01, 0x89, 0xB1, 0x5F, 0x9E, 0x9C, 0x57, 0x1E, 0xEB, 0x4D, + 0x75, 0xCF, 0x3C, 0x02, 0xAD, 0xEA, 0x9D, 0xC7, 0x8A, 0x57, 0xCD, 0x43, 0xD7, 0xC8, 0x49, 0x5E, + 0xBA, 0x36, 0x46, 0x14, 0x1F, 0x55, 0x5C, 0xAD, 0x35, 0x16, 0x89, 0x9B, 0xB4, 0xA6, 0xB2, 0x48, + 0x4B, 0xB5, 0x32, 0x4D, 0xB7, 0xCC, 0xA5, 0xAA, 0x6E, 0x2C, 0xC0, 0xE7, 0xD7, 0xFA, 0xCC, 0xE8, + 0xF7, 0xC7, 0x75, 0x14, 0xDF, 0xFF, 0x0F, 0x20, 0x29, 0xD3, 0x4A, 0x22, 0x62, 0x3B, 0x7B, 0x35, + 0x91, 0x32, 0xAA, 0x45, 0xCE, 0xB0, 0xAE, 0x84, 0x95, 0x1D, 0xE2, 0x58, 0x1D, 0x9F, 0xCE, 0xC2, + 0x22, 0xEE, 0xDD, 0xF2, 0x8B, 0x8B, 0x3C, 0xC9, 0x4A, 0x27, 0x97, 0xF2, 0x32, 0xED, 0xC6, 0xA2, + 0x27, 0x34, 0xBC, 0xF1, 0xEC, 0xCC, 0xBB, 0x71, 0xCA, 0xC5, 0xB8, 0xE4, 0x4A, 0xF8, 0xCB, 0xE8, + 0x06, 0x78, 0xEA, 0xE5, 0x25, 0x40, 0x99, 0xC8, 0x5F, 0xC2, 0xAF, 0xC5, 0xD3, 0xA6, 0x4F, 0x63, + 0xB3, 0x63, 0x97, 0x4C, 0x07, 0xDC, 0x99, 0xC1, 0x49, 0x40, 0x12, 0xBE, 0x89, 0xE7, 0x88, 0x32, + 0x2E, 0xCF, 0x2F, 0x93, 0x55, 0xB2, 0x24, 0x55, 0x49, 0x1F, 0x6F, 0x8B, 0x6A, 0x2B, 0x24, 0x5D, + 0xCB, 0x7C, 0xB1, 0x60, 0x99, 0xAC, 0x91, 0x2E, 0xBF, 0x10, 0x9E, 0xC7, 0x76, 0x34, 0xF3, 0x03, + 0x97, 0x6D, 0x8C, 0xC3, 0x80, 0xD2, 0xA5, 0xF5, 0xBC, 0x7B, 0xC8, 0xB9, 0x72, 0x4A, 0xE7, 0x5C, + 0xC8, 0x11, 0x93, 0x26, 0x54, 0xB3, 0x9C, 0x74, 0x56, 0x51, 0x04, 0x8F, 0x28, 0xA9, 0x54, 0x8E, + 0x03, 0xB3, 0x9C, 0xF4, 0xA5, 0xF3, 0x93, 0xB5, 0x18, 0xD3, 0xF1, 0x99, 0x80, 0x63, 0xF0, 0xCA, + 0x0A, 0x22, 0xA2, 0x18, 0x57, 0x7A, 0xBD, 0x4B, 0xB6, 0x4C, 0x53, 0xF5, 0xC8, 0x0A, 0x23, 0x2C, + 0x49, 0xE5, 0x55, 0xB2, 0x81, 0x82, 0xEC, 0x19, 0x5E, 0x83, 0xCB, 0x9C, 0x9A, 0x0D, 0xCB, 0xE7, + 0x82, 0xD4, 0x15, 0xE9, 0x25, 0x7F, 0xC4, 0x75, 0xCC, 0xD4, 0xEB, 0x74, 0x9C, 0xBC, 0xB2, 0x30, + 0x1A, 0xC3, 0x6A, 0x30, 0x62, 0xBF, 0xBB, 0x23, 0xFD, 0xF9, 0x2A, 0x6E, 0x98, 0xF4, 0x35, 0x7D, + 0x0E, 0x50, 0xC8, 0xE5, 0xCA, 0xAE, 0xE2, 0xB3, 0x27, 0x04, 0x56, 0x88, 0xCE, 0x78, 0x7A, 0xCF, + 0xFF, 0x21, 0x43, 0x12, 0xE9, 0xC4, 0x1C, 0x42, 0x14, 0x80, 0x35, 0x62, 0xFB, 0x69, 0x49, 0x45, + 0xE7, 0x38, 0x4F, 0x2C, 0xD9, 0x8D, 0x28, 0x2D, 0x21, 0x83, 0x4D, 0xE3, 0x84, 0x24, 0x0D, 0x5D, + 0x37, 0x28, 0x5A, 0x86, 0x01, 0x31, 0x81, 0xF7, 0xB2, 0xC1, 0x33, 0x2F, 0x77, 0xA5, 0x90, 0x74, + 0xBF, 0x68, 0xB7, 0x13, 0xEB, 0xE4, 0x48, 0x89, 0x92, 0x9C, 0x54, 0xC0, 0xD3, 0xCB, 0xC9, 0xB5, + 0xA2, 0xE0, 0x51, 0x62, 0x8A, 0xB2, 0x1E, 0x39, 0x33, 0x0C, 0xEA, 0x9D, 0xCC, 0xBA, 0xEA, 0x28, + 0x29, 0xAA, 0x17, 0xEB, 0x4D, 0x41, 0xC5, 0xA4, 0xC3, 0xB3, 0x2B, 0xA6, 0x3A, 0xB7, 0xB0, 0xAA, + 0xDE, 0x91, 0x25, 0x03, 0x61, 0x94, 0xEC, 0x1C, 0x01, 0x37, 0xEF, 0x91, 0x68, 0x08, 0xB3, 0xC6, + 0x7C, 0x25, 0x9E, 0x11, 0x16, 0x93, 0xDE, 0xA9, 0x8B, 0x81, 0x6B, 0xED, 0xD6, 0xA9, 0x9E, 0x57, + 0xEE, 0x8E, 0x9D, 0x64, 0x95, 0xF3, 0x76, 0xED, 0xB4, 0x65, 0x41, 0xE9, 0x9D, 0x3B, 0x93, 0x7E, + 0xE8, 0xBA, 0xB3, 0xC0, 0x1D, 0xBC, 0x9A, 0xE4, 0xE3, 0x9D, 0x3C, 0xD0, 0xDA, 0x35, 0xD4, 0xC8, + 0x35, 0xD0, 0x36, 0xF3, 0x86, 0x9E, 0x2E, 0x98, 0x92, 0x9B, 0x7A, 0x92, 0xD8, 0xD5, 0x8D, 0x3D, + 0x7D, 0xCD, 0x5C, 0x71, 0x73, 0xAF, 0xCC, 0x92, 0x7B, 0x9E, 0x1B, 0x7C, 0xDA, 0xC2, 0x79, 0xB6, + 0x4D, 0x3E, 0x49, 0x28, 0xD5, 0x36, 0xFA, 0xE2, 0xD1, 0xF2, 0x5D, 0x37, 0xFB, 0x14, 0xF5, 0x90, + 0xFD, 0x2B, 0xF4, 0xA4, 0x9E, 0xEB, 0x33, 0xE6, 0xDC, 0xB6, 0x04, 0x53, 0xF3, 0xA5, 0x5A, 0x61, + 0x43, 0x87, 0xD8, 0xD4, 0x3F, 0x6C, 0x15, 0xA1, 0x78, 0xAE, 0x6C, 0x3B, 0x16, 0x1A, 0xC3, 0x85, + 0x6C, 0x76, 0x4A, 0x3A, 0xF0, 0x90, 0x4A, 0x72, 0xA5, 0xEC, 0x5A, 0x4A, 0x39, 0x77, 0xB8, 0xCB, + 0x0D, 0x3F, 0xA5, 0x9E, 0x6D, 0xFF, 0x87, 0xE7, 0xB8, 0x4B, 0xCD, 0x66, 0x9C, 0x70, 0x48, 0xAB, + 0xD2, 0x2A, 0xAE, 0xF2, 0xF7, 0xBF, 0xA7, 0xEA, 0xF8, 0x34, 0x9C, 0xFA, 0x2E, 0x73, 0xD7, 0x35, + 0xEE, 0x86, 0x34, 0xC4, 0x34, 0x47, 0x8A, 0x29, 0x66, 0x19, 0xA6, 0xC0, 0x64, 0x81, 0xF6, 0x44, + 0x65, 0x68, 0x51, 0xF9, 0xB4, 0xAE, 0x99, 0x35, 0xA5, 0x8E, 0x58, 0x61, 0x49, 0x9B, 0x76, 0x47, + 0xD7, 0x6C, 0x93, 0x2E, 0xB4, 0xAE, 0xC8, 0x9D, 0x15, 0x10, 0x9C, 0xBB, 0x09, 0xA6, 0x46, 0xA2, + 0x76, 0x8B, 0xF0, 0x21, 0x8D, 0x65, 0x23, 0xCA, 0x73, 0x68, 0x05, 0x03, 0x1F, 0x9F, 0xE6, 0xD1, + 0x16, 0x3A, 0x23, 0x7A, 0x62, 0xB9, 0xD6, 0x90, 0xFA, 0x17, 0x58, 0x33, 0x95, 0x04, 0x89, 0xC1, + 0xBF, 0x7E, 0x15, 0xFA, 0xC4, 0x1A, 0x39, 0x43, 0x77, 0xB7, 0x39, 0xA2, 0xD7, 0x61, 0x13, 0x3E, + 0xDC, 0xBC, 0xC6, 0xFD, 0x83, 0x57, 0x6B, 0xF0, 0x0B, 0xFE, 0xD1, 0x07, 0x43, 0x26, 0xFE, 0xB0, + 0x5F, 0xBF, 0xE2, 0x8F, 0x29, 0x86, 0xF7, 0x13, 0xBA, 0xCB, 0x3D, 0x8E, 0x2B, 0xEF, 0x5B, 0x93, + 0x38, 0xF6, 0x6E, 0x13, 0x09, 0xF2, 0xE5, 0xFC, 0xDE, 0x68, 0xD4, 0x24, 0xEC, 0xAD, 0x4F, 0xF8, + 0xEA, 0xF9, 0xE3, 0x55, 0x56, 0x71, 0x95, 0x83, 0x4A, 0x7C, 0xB1, 0x9D, 0xC9, 0x26, 0x11, 0x81, + 0x8B, 0x1C, 0x43, 0xC4, 0xB2, 0x37, 0x1C, 0x62, 0x52, 0x1A, 0xE0, 0x67, 0x0D, 0xC9, 0xAE, 0x85, + 0x7E, 0xFC, 0x83, 0xF1, 0x2D, 0x99, 0x6D, 0x04, 0x63, 0x4D, 0xBC, 0xE0, 0x36, 0xAC, 0xD1, 0x90, + 0x44, 0xF9, 0x6D, 0x3C, 0xBA, 0x09, 0xC3, 0x49, 0x6E, 0xE2, 0x29, 0xA9, 0x9E, 0xC8, 0x3F, 0xF5, + 0xEE, 0x90, 0xA7, 0x9F, 0xC2, 0x59, 0x98, 0x65, 0xC7, 0x6A, 0xA4, 0xBD, 0xB3, 0x08, 0x82, 0x65, + 0x15, 0x92, 0xED, 0x84, 0x08, 0x1B, 0x1B, 0x78, 0x63, 0x34, 0x23, 0x51, 0x35, 0x9F, 0x06, 0x13, + 0x70, 0x27, 0x18, 0x93, 0xCB, 0x18, 0xB2, 0x23, 0x72, 0xAD, 0x91, 0xFD, 0xFE, 0xCF, 0x3C, 0x3B, + 0x9A, 0xE3, 0x86, 0x1E, 0x9B, 0xFC, 0x9F, 0x95, 0xEF, 0x48, 0x70, 0xBF, 0x95, 0xE6, 0x17, 0x4C, + 0xA6, 0xAA, 0xD6, 0x65, 0xBE, 0x72, 0x04, 0xCA, 0x2D, 0xB2, 0x8E, 0xA6, 0xF4, 0xDB, 0xBB, 0x0A, + 0x2D, 0x07, 0xD4, 0x50, 0x2A, 0x37, 0xEA, 0xB8, 0xB1, 0x9E, 0xAE, 0xE7, 0x52, 0xFA, 0x46, 0xAC, + 0xA0, 0xAB, 0xA8, 0xD4, 0xC7, 0xA2, 0x96, 0xD4, 0xC3, 0x71, 0xB3, 0x30, 0xC7, 0xDA, 0x49, 0xF2, + 0x8C, 0x13, 0xDA, 0xFF, 0xCF, 0x5F, 0xCC, 0xE5, 0x6C, 0x43, 0xDE, 0x58, 0x21, 0x7A, 0x9D, 0x37, + 0x13, 0x43, 0x54, 0x41, 0x41, 0x31, 0x47, 0x2D, 0x8B, 0xF2, 0x18, 0x7F, 0x47, 0x45, 0xCB, 0xEA, + 0x89, 0x95, 0x5D, 0x59, 0xFC, 0x8A, 0x99, 0x22, 0xE7, 0x74, 0x22, 0xB0, 0x5B, 0xEE, 0x3D, 0x97, + 0x54, 0x54, 0x99, 0x1D, 0x39, 0x04, 0xCC, 0xB7, 0xBD, 0xE5, 0x42, 0x5B, 0x25, 0x4E, 0x9B, 0xB6, + 0x99, 0x61, 0x13, 0x5F, 0xD0, 0xF5, 0xC1, 0x3F, 0xF1, 0xFD, 0x04, 0xC2, 0x9F, 0x90, 0x20, 0xB6, + 0xB8, 0x2D, 0x1C, 0xE4, 0x46, 0xF8, 0xA5, 0xBA, 0x3D, 0xEB, 0x39, 0x30, 0xD1, 0xBA, 0x54, 0xFD, + 0xCF, 0xDF, 0xBE, 0x24, 0xEB, 0xB9, 0xB4, 0x92, 0x7C, 0x96, 0xBD, 0x9E, 0x87, 0xC2, 0x36, 0x47, + 0xA6, 0xB0, 0x4A, 0xA3, 0x31, 0x55, 0x29, 0xE1, 0x51, 0xF6, 0x09, 0x02, 0x5A, 0xA2, 0xD9, 0x8A, + 0xB2, 0xE6, 0xB5, 0x9B, 0x4D, 0x48, 0x69, 0xED, 0x15, 0x41, 0x9A, 0x0D, 0x1C, 0x8D, 0x59, 0xD9, + 0x54, 0xD2, 0x84, 0x98, 0xC0, 0xB2, 0x12, 0xB1, 0xE6, 0x64, 0x71, 0xC9, 0x61, 0x80, 0x69, 0x7A, + 0x6D, 0x0E, 0xB4, 0x9D, 0xC6, 0x0A, 0x91, 0x96, 0xD2, 0xAA, 0x4E, 0x35, 0x75, 0xE4, 0x28, 0x08, + 0xA6, 0x22, 0xEA, 0xFD, 0xE8, 0xE0, 0x25, 0xDB, 0x50, 0x37, 0xF3, 0x51, 0x25, 0x4A, 0x5F, 0xA5, + 0xF1, 0x86, 0x3D, 0xBB, 0x9E, 0x6F, 0x52, 0xB1, 0x4E, 0x59, 0xB3, 0xCA, 0xEB, 0x16, 0x98, 0x56, + 0xAC, 0x54, 0xDF, 0xBC, 0x3E, 0x19, 0xEB, 0xC8, 0x9A, 0xF1, 0x24, 0x2C, 0x64, 0x4A, 0xA0, 0x55, + 0xAD, 0xE4, 0x0F, 0x8B, 0xF1, 0x2F, 0x61, 0x31, 0xD8, 0xE8, 0x73, 0x16, 0x61, 0x35, 0x24, 0xBF, + 0xEF, 0x00, 0xA6, 0x43, 0x3C, 0x80, 0x48, 0x32, 0x84, 0x8A, 0x1B, 0x3B, 0xE8, 0xCC, 0x95, 0x4F, + 0x38, 0x89, 0x18, 0x8F, 0x0E, 0xA4, 0x43, 0x35, 0xCE, 0x8E, 0xCB, 0x4E, 0x54, 0x3E, 0x5C, 0x33, + 0x64, 0xFD, 0xE8, 0x2E, 0x50, 0x6D, 0xA4, 0xCA, 0x16, 0x07, 0x96, 0xF2, 0x13, 0x9B, 0x24, 0xB2, + 0x00, 0x47, 0xE9, 0x5B, 0x9E, 0x72, 0x12, 0x06, 0x47, 0x1F, 0xF3, 0x31, 0x63, 0x46, 0x54, 0xB0, + 0xBE, 0x58, 0xA2, 0x26, 0x74, 0x8E, 0xAB, 0x4A, 0xF6, 0x52, 0xC6, 0xB9, 0x6B, 0xE6, 0x7E, 0x59, + 0xAC, 0xDC, 0x92, 0xF3, 0xC2, 0xA9, 0x3F, 0x0A, 0x31, 0x49, 0x09, 0xAE, 0xF9, 0x1A, 0x6B, 0x88, + 0xE2, 0xAF, 0x8C, 0x7D, 0xD6, 0x57, 0xB2, 0x34, 0x3F, 0x27, 0xE8, 0xF1, 0xB5, 0x50, 0x3C, 0x46, + 0xFD, 0xC9, 0x62, 0xDC, 0xEC, 0xDA, 0xA2, 0x1B, 0x84, 0x79, 0x94, 0xB5, 0x22, 0x46, 0x2F, 0x64, + 0x0A, 0x9E, 0x36, 0xD4, 0x6E, 0x47, 0x27, 0xB3, 0xED, 0x1B, 0x9F, 0x5E, 0xE3, 0xB3, 0xBB, 0x51, + 0xB5, 0xE8, 0x3E, 0x67, 0x4C, 0x6B, 0x65, 0x65, 0x27, 0xAB, 0xF7, 0xA3, 0xB5, 0x90, 0x74, 0xE8, + 0x94, 0x8C, 0xFD, 0xAA, 0xFD, 0x94, 0x95, 0x67, 0x14, 0x37, 0x8D, 0x12, 0xAC, 0x4A, 0xA6, 0x51, + 0x37, 0x95, 0x67, 0x34, 0xA9, 0x88, 0xB9, 0x46, 0x93, 0xF1, 0x15, 0x2D, 0x57, 0xE2, 0x65, 0x60, + 0x72, 0x4D, 0x71, 0xA7, 0x40, 0xC3, 0xA9, 0x9A, 0x01, 0x77, 0x5E, 0xFA, 0xFD, 0x2C, 0xEB, 0xCC, + 0x3C, 0xD5, 0xEF, 0xD1, 0xA6, 0x0E, 0xF4, 0x37, 0x63, 0x2C, 0x10, 0x87, 0xE7, 0xA9, 0x29, 0x58, + 0xD6, 0x2C, 0x7D, 0x07, 0x4F, 0xB6, 0xBB, 0x06, 0xE4, 0xC6, 0xB7, 0x6A, 0xCB, 0x6B, 0xE6, 0xB7, + 0x94, 0x42, 0xB2, 0xB6, 0x34, 0x76, 0x4A, 0xCF, 0xB4, 0xB9, 0x53, 0x6D, 0xCC, 0x48, 0xF1, 0x04, + 0x2B, 0xB5, 0x7D, 0x6D, 0xED, 0x9C, 0x5E, 0xC3, 0x8C, 0x7A, 0xC3, 0xD3, 0x4C, 0xC7, 0x61, 0x45, + 0xB9, 0xCB, 0x4D, 0x65, 0xF7, 0x64, 0x47, 0xBB, 0x42, 0xCA, 0x33, 0x3E, 0x6B, 0x1A, 0x2F, 0xE5, + 0xB0, 0xC6, 0x5F, 0xBB, 0x73, 0x49, 0x5B, 0xCD, 0x31, 0xD5, 0xCC, 0x54, 0xCD, 0x19, 0x35, 0x5C, + 0x8D, 0x86, 0xB9, 0x7E, 0xE8, 0x63, 0x16, 0xF5, 0x16, 0x89, 0x7E, 0x7D, 0x0F, 0xD3, 0xFB, 0x88, + 0xFA, 0xAA, 0x60, 0x19, 0x96, 0x34, 0x38, 0xB3, 0x30, 0x2D, 0xB0, 0x2E, 0x3C, 0xE1, 0x73, 0x15, + 0x50, 0x7E, 0x18, 0xD1, 0xE2, 0x87, 0x12, 0x55, 0x00, 0xAD, 0x2B, 0xCF, 0x0F, 0x01, 0x90, 0xFD, + 0x3F, 0x1B, 0x30, 0x23, 0x39, 0xF7, 0x28, 0x3F, 0x31, 0xB7, 0xF4, 0xBA, 0x81, 0x26, 0x8F, 0x28, + 0x8D, 0x72, 0xD2, 0xCD, 0x13, 0xEA, 0x0F, 0xF8, 0xFD, 0x58, 0x5E, 0xD6, 0x1E, 0xB1, 0x94, 0xCB, + 0x64, 0x8D, 0xF0, 0x3F, 0x43, 0x2F, 0xC4, 0x7D, 0xC0, 0xBF, 0xE0, 0xD1, 0xBE, 0x94, 0x8D, 0x5A, + 0xA0, 0x7D, 0x63, 0xF9, 0xD2, 0x21, 0xDD, 0x89, 0x15, 0xDE, 0xB4, 0x7D, 0x6F, 0x0A, 0xDC, 0x08, + 0xB4, 0xCB, 0x09, 0xC8, 0x54, 0xCA, 0xE7, 0xAD, 0x39, 0xC6, 0x06, 0x38, 0x1C, 0x74, 0xFF, 0x5B, + 0xA8, 0x26, 0xB5, 0x79, 0x96, 0xF0, 0x78, 0x4B, 0x58, 0xB0, 0xFC, 0x1A, 0x5F, 0xD4, 0xE8, 0xA4, + 0x1E, 0x06, 0xCA, 0xA6, 0xD3, 0x38, 0x4B, 0x12, 0x8F, 0xB7, 0xC8, 0x1D, 0x5E, 0xC1, 0x72, 0x87, + 0x5C, 0xD1, 0xC1, 0xFB, 0x64, 0xDA, 0x7D, 0x0F, 0x1D, 0x34, 0x6E, 0x18, 0x1E, 0x7B, 0xD5, 0xB4, + 0x43, 0x15, 0x64, 0x11, 0x5D, 0x9E, 0x51, 0x9C, 0xC4, 0x29, 0xC5, 0x8B, 0x04, 0x19, 0x1D, 0x1C, + 0xCD, 0x63, 0xA8, 0xB3, 0x6F, 0xB1, 0x39, 0xC7, 0x84, 0xE0, 0xFC, 0x68, 0xE2, 0xCD, 0xFD, 0x91, + 0x5D, 0x95, 0x6B, 0x49, 0x1E, 0xB2, 0xC6, 0xD7, 0x12, 0xC6, 0x5B, 0x0B, 0x98, 0xB4, 0x55, 0xA4, + 0xF2, 0x68, 0xA8, 0x85, 0x74, 0x0F, 0x11, 0x08, 0xAC, 0x09, 0xDA, 0x70, 0x20, 0xB2, 0x45, 0xBE, + 0xC1, 0x19, 0x54, 0x71, 0x6D, 0x92, 0x7B, 0xFE, 0x17, 0x83, 0x52, 0x59, 0x2C, 0xF9, 0x09, 0x59, + 0x8C, 0x51, 0x8D, 0x45, 0x35, 0x6E, 0x03, 0xF2, 0x23, 0xBD, 0x0C, 0x88, 0xA8, 0x6D, 0x71, 0x31, + 0x66, 0x05, 0x94, 0x5F, 0x7E, 0xD9, 0xDE, 0x78, 0x61, 0x9A, 0xC9, 0xA1, 0x3E, 0x4F, 0xFB, 0x59, + 0xD0, 0xA4, 0x32, 0xE9, 0x48, 0xE3, 0x26, 0x99, 0x12, 0x89, 0xE6, 0x37, 0x29, 0x2B, 0xF5, 0xE8, + 0x50, 0x2E, 0x2E, 0xD9, 0xA4, 0xA9, 0x3D, 0xC9, 0x6B, 0xCC, 0x47, 0xBB, 0x42, 0x63, 0xA6, 0x76, + 0x46, 0xBE, 0xC0, 0x9C, 0xE6, 0x64, 0xC2, 0xC4, 0xFA, 0x67, 0x9B, 0x1B, 0xD4, 0xED, 0x74, 0xBB, + 0x1D, 0x53, 0x8B, 0xEC, 0x9B, 0xC1, 0xE4, 0x10, 0x96, 0x91, 0xBE, 0x4B, 0xC3, 0x74, 0xAB, 0x44, + 0xC1, 0xC1, 0xFB, 0xFD, 0xB3, 0xFC, 0x26, 0x49, 0x19, 0xC3, 0x8F, 0xCE, 0x54, 0x16, 0x23, 0xEC, + 0xB9, 0xCD, 0x93, 0x32, 0x79, 0x17, 0xC3, 0xCB, 0xFC, 0x43, 0x01, 0x5E, 0xF6, 0x66, 0x71, 0xCE, + 0xAA, 0x37, 0xAC, 0x05, 0xC2, 0xE3, 0xB7, 0x3B, 0xE7, 0xDA, 0x39, 0xE5, 0x00, 0xA5, 0x1C, 0x48, + 0xC7, 0xFE, 0xB7, 0x5D, 0x09, 0xE6, 0x4B, 0x93, 0xFC, 0xF4, 0x13, 0x89, 0xCB, 0xFE, 0xBC, 0xDB, + 0xEF, 0xEB, 0xCE, 0xB3, 0xE6, 0xEF, 0xC9, 0x04, 0xB3, 0xDC, 0x3D, 0x14, 0xB6, 0x5C, 0x0F, 0x3D, + 0x3A, 0xD6, 0x6D, 0xF1, 0x89, 0x22, 0xE9, 0x2C, 0x6B, 0x11, 0x08, 0xD0, 0x34, 0x5C, 0x1B, 0x48, + 0x1E, 0x57, 0x74, 0x28, 0xC5, 0xCA, 0x34, 0xEF, 0x89, 0xF5, 0xDB, 0x29, 0xBD, 0x8B, 0x52, 0x1C, + 0x29, 0xFD, 0xAC, 0xE7, 0x4D, 0xF9, 0x53, 0x9C, 0x50, 0x19, 0xDA, 0xBA, 0xA4, 0x89, 0x97, 0x85, + 0x02, 0xE8, 0xAA, 0x7C, 0x12, 0x0C, 0x79, 0x60, 0x45, 0x33, 0x7A, 0x9D, 0x62, 0x5F, 0x10, 0x84, + 0x12, 0x7C, 0xFE, 0xE4, 0x17, 0xE7, 0xAD, 0xC3, 0x26, 0x06, 0xBC, 0xF8, 0x4D, 0xC7, 0x93, 0xF0, + 0x5E, 0x56, 0x5B, 0x83, 0xEB, 0x2C, 0x72, 0xC2, 0xED, 0x6B, 0x7C, 0x67, 0x05, 0x20, 0x0A, 0x26, + 0x32, 0xE9, 0x83, 0x1E, 0xB9, 0x78, 0xAD, 0x19, 0x26, 0x52, 0x98, 0x43, 0x45, 0x93, 0x1A, 0xDA, + 0xFB, 0x41, 0xA8, 0x1F, 0xE2, 0xB1, 0x08, 0xDC, 0xF1, 0x91, 0x4E, 0x8C, 0x60, 0x39, 0x0A, 0xCE, + 0x0B, 0x19, 0x4C, 0x7D, 0x1F, 0xA7, 0x74, 0xD6, 0x1A, 0xEC, 0x79, 0xB6, 0x3D, 0x73, 0xF6, 0x4B, + 0x90, 0xA8, 0xDC, 0x28, 0x10, 0x13, 0x57, 0x3D, 0xED, 0xCA, 0x51, 0x24, 0x09, 0x75, 0x96, 0x1E, + 0x49, 0xCC, 0xAF, 0xEC, 0xCA, 0x00, 0xC9, 0x12, 0xA1, 0x85, 0xCB, 0x07, 0xAD, 0x24, 0x0A, 0xA8, + 0x86, 0x42, 0xA5, 0x0F, 0x54, 0xCB, 0x76, 0xBE, 0x2F, 0x75, 0x82, 0x6E, 0x07, 0x32, 0x58, 0x48, + 0x81, 0xB6, 0xB0, 0x76, 0x44, 0x06, 0x0D, 0x40, 0x69, 0x40, 0xD6, 0x53, 0xAD, 0xA8, 0x43, 0xB4, + 0xDA, 0xBA, 0x7A, 0xE3, 0xFB, 0x1D, 0xD1, 0xBD, 0x15, 0x79, 0x8F, 0x26, 0x2A, 0x67, 0x1B, 0x08, + 0x00, 0x2F, 0xF6, 0x64, 0x62, 0x64, 0xCB, 0xC6, 0xA7, 0x41, 0x94, 0xF2, 0xE4, 0x36, 0x87, 0x44, + 0xCF, 0xF8, 0x58, 0x53, 0x8A, 0x29, 0xD3, 0x93, 0x4D, 0xAC, 0x12, 0x20, 0x37, 0x8D, 0x4D, 0xE5, + 0xC9, 0xA1, 0x0C, 0x92, 0xCB, 0xE9, 0x3D, 0x87, 0xC6, 0x3E, 0xC2, 0x31, 0x55, 0x17, 0x6C, 0xA1, + 0x3A, 0x65, 0xC0, 0xC7, 0xF7, 0x45, 0x0A, 0x47, 0x90, 0x60, 0x34, 0x7E, 0xA4, 0x86, 0xC0, 0x14, + 0x13, 0xB0, 0xF0, 0x8B, 0x1D, 0xCD, 0x1C, 0xC7, 0x34, 0x7E, 0xE6, 0x35, 0x96, 0xAE, 0xD5, 0xBF, + 0x95, 0xF6, 0x65, 0xD2, 0x94, 0x1E, 0xEE, 0xD4, 0xE0, 0x79, 0xC6, 0xF7, 0xF3, 0xF3, 0x0F, 0xE7, + 0x8D, 0xCA, 0x86, 0x48, 0x8C, 0x34, 0x02, 0x12, 0xE1, 0xB3, 0x24, 0xCB, 0xEE, 0x61, 0xDD, 0x82, + 0x9B, 0xC7, 0x0F, 0x51, 0x77, 0xB4, 0x09, 0xCD, 0x76, 0x6E, 0xDF, 0xD1, 0x50, 0x31, 0x41, 0xEA, + 0x7C, 0x5B, 0x68, 0xA5, 0xB4, 0xDD, 0x45, 0xD5, 0xD8, 0x29, 0x1B, 0x9C, 0xA6, 0x76, 0xEE, 0x7F, + 0x3C, 0x3F, 0x3F, 0x3C, 0xBD, 0x30, 0xB5, 0x34, 0xB3, 0x91, 0xB1, 0x9A, 0x83, 0xB1, 0x9D, 0x4E, + 0xD0, 0xE2, 0xF1, 0x44, 0x7B, 0x8F, 0xDC, 0x36, 0xD9, 0x90, 0xEB, 0x74, 0x74, 0xBF, 0x98, 0xC5, + 0xBB, 0x01, 0xA3, 0xB7, 0x0D, 0x76, 0x1B, 0x44, 0x91, 0xC3, 0x4E, 0x2E, 0x22, 0x33, 0x37, 0xEA, + 0xFB, 0x4B, 0x88, 0xFD, 0x2C, 0x6B, 0x0D, 0x63, 0x56, 0x45, 0x15, 0x48, 0x52, 0x48, 0x91, 0x18, + 0xDC, 0x24, 0x3A, 0xED, 0x70, 0x47, 0x1F, 0xD3, 0x4F, 0x67, 0xC2, 0xFD, 0xFE, 0xDD, 0x6F, 0x9C, + 0xC5, 0x4B, 0x19, 0x84, 0x94, 0xF2, 0xA7, 0x7B, 0x0A, 0xDA, 0xFF, 0x4E, 0x3C, 0xFA, 0x84, 0x9B, + 0x35, 0xD7, 0x52, 0xF3, 0x7E, 0x4C, 0xF4, 0xEA, 0x44, 0x6F, 0x98, 0x4C, 0x55, 0xCD, 0x5D, 0xF4, + 0x54, 0xAA, 0x52, 0x33, 0x4E, 0xA4, 0x1A, 0x43, 0xA6, 0x69, 0x74, 0xC8, 0xF1, 0xCA, 0x23, 0x4E, + 0x0A, 0x0C, 0x8B, 0x6E, 0x56, 0xA0, 0x3D, 0xED, 0x36, 0x32, 0x5F, 0xF5, 0x33, 0xB2, 0xB2, 0x6C, + 0xB4, 0xD4, 0x11, 0xB6, 0xF4, 0x2C, 0xB4, 0xA0, 0xA1, 0x55, 0x64, 0xF2, 0x99, 0x35, 0x88, 0xC4, + 0xA0, 0x6A, 0xBD, 0xF2, 0xC8, 0xA6, 0xBA, 0x74, 0xF2, 0x42, 0x2B, 0xA2, 0x2E, 0x9E, 0xB0, 0x13, + 0xBB, 0x56, 0xD1, 0x6E, 0x8A, 0xD1, 0x15, 0xC9, 0x92, 0x53, 0xF9, 0xE1, 0xA9, 0x51, 0xE1, 0xDB, + 0x68, 0xFA, 0x53, 0x76, 0x65, 0x4D, 0xB8, 0x86, 0x4C, 0xDA, 0xDC, 0xD7, 0xC9, 0xEC, 0xA6, 0xB6, + 0xE2, 0xB4, 0x17, 0x33, 0x95, 0x74, 0x0A, 0xEF, 0x9C, 0x5B, 0xEA, 0x12, 0x0B, 0x9F, 0x5E, 0xF5, + 0x9B, 0x81, 0xC8, 0x00, 0x86, 0xC2, 0xBC, 0xC7, 0x89, 0x0A, 0xBA, 0xD9, 0x0D, 0x9D, 0x6B, 0x9E, + 0x87, 0x0B, 0xE3, 0xDE, 0x98, 0x89, 0x10, 0x6B, 0x30, 0xFC, 0x96, 0x84, 0x34, 0x13, 0xC7, 0x25, + 0x07, 0x07, 0x6D, 0x3B, 0xFA, 0xC7, 0x36, 0x9C, 0x2D, 0x29, 0x8C, 0x3B, 0xC2, 0x75, 0x84, 0xB6, + 0x02, 0x5F, 0x4B, 0x5A, 0x42, 0x9A, 0x87, 0x2E, 0x90, 0x52, 0xD7, 0xB3, 0x11, 0xC6, 0xB8, 0x22, + 0x34, 0x5F, 0x7D, 0x67, 0x29, 0x68, 0xEF, 0x7F, 0xF8, 0x70, 0x7E, 0x70, 0x74, 0xBA, 0x77, 0x71, + 0x78, 0x79, 0x74, 0x7A, 0xF6, 0xF1, 0xE2, 0xF2, 0xE2, 0xD3, 0x19, 0xFE, 0xFA, 0xF3, 0xDE, 0xF1, + 0xD1, 0xC1, 0xE5, 0xC7, 0xD3, 0xBF, 0x9D, 0x7E, 0xF8, 0xE5, 0x34, 0xD9, 0xD4, 0xB6, 0xAD, 0xE0, + 0x46, 0xBA, 0x31, 0x1E, 0x9B, 0x47, 0x0C, 0x39, 0x37, 0x7C, 0xB7, 0xE9, 0xC0, 0x19, 0x5B, 0x23, + 0x43, 0x09, 0x37, 0x55, 0x1F, 0xAE, 0x8F, 0x29, 0x7B, 0x3F, 0x51, 0x3F, 0xDD, 0x03, 0xE3, 0x01, + 0xDE, 0x56, 0x88, 0xCF, 0x74, 0xC5, 0x72, 0xE1, 0xAF, 0xE1, 0xE0, 0x5D, 0x64, 0x54, 0x2F, 0x72, + 0x77, 0x63, 0xB1, 0xE9, 0x6A, 0xC8, 0x04, 0x0F, 0x32, 0x9E, 0x06, 0xB1, 0x55, 0x1E, 0x58, 0x2E, + 0xA1, 0x28, 0x10, 0x66, 0x32, 0x1D, 0x17, 0x3A, 0xDF, 0xB1, 0xD9, 0xAD, 0xF2, 0x40, 0x54, 0xD9, + 0x23, 0xFC, 0x1B, 0xAF, 0x85, 0x0F, 0x8E, 0xB2, 0x3C, 0x70, 0xFC, 0x1C, 0x30, 0x68, 0x91, 0xD5, + 0x16, 0xC6, 0x9B, 0xB6, 0x58, 0x37, 0xB5, 0xD5, 0xB3, 0x2E, 0xC9, 0xF8, 0xC6, 0x82, 0xD7, 0x4D, + 0xAF, 0x7A, 0x8D, 0x36, 0xB0, 0x9D, 0xA1, 0x13, 0x26, 0xDD, 0x84, 0x87, 0xB8, 0x59, 0x57, 0x2A, + 0x11, 0x40, 0x15, 0x1B, 0x8B, 0xA6, 0x37, 0xCA, 0x6B, 0x65, 0x25, 0xEF, 0xC5, 0x10, 0x99, 0x1C, + 0x62, 0x69, 0xAE, 0x36, 0x97, 0x93, 0x0E, 0x5C, 0x59, 0x61, 0xAF, 0x18, 0x8D, 0x46, 0x64, 0xE8, + 0x79, 0x76, 0x09, 0x68, 0x02, 0xD0, 0x49, 0x3F, 0x57, 0x06, 0x6F, 0x23, 0x71, 0xA9, 0x5D, 0x79, + 0x08, 0xA2, 0xBD, 0x89, 0x5A, 0xCA, 0x2A, 0xCE, 0x83, 0xD9, 0x92, 0x06, 0xD4, 0x08, 0x23, 0x5D, + 0x02, 0x45, 0x05, 0x58, 0x62, 0x01, 0xF5, 0xF0, 0x09, 0xBC, 0x7B, 0x54, 0xA2, 0x89, 0x17, 0x04, + 0x0E, 0xC6, 0xC3, 0x72, 0xAD, 0xC0, 0x71, 0x1A, 0xE9, 0x4B, 0x32, 0x24, 0x93, 0x0F, 0x27, 0x27, + 0xED, 0x31, 0xFF, 0x97, 0x7C, 0x23, 0xA6, 0x8F, 0xAB, 0xA6, 0x8F, 0x27, 0x27, 0xFD, 0x7E, 0x3B, + 0x60, 0xFF, 0x14, 0x70, 0x62, 0xF8, 0x0C, 0x08, 0x56, 0x93, 0xCF, 0xCF, 0x8C, 0x7A, 0xC2, 0x6E, + 0x71, 0xCD, 0x2E, 0xB9, 0xFF, 0x8B, 0x41, 0xC2, 0xAE, 0xD7, 0x26, 0x1B, 0x30, 0xDA, 0xB6, 0x3B, + 0xEB, 0xEB, 0x1B, 0xCF, 0x59, 0xFE, 0x3D, 0x26, 0xBF, 0x76, 0x12, 0xA1, 0x9C, 0x8C, 0xF8, 0xD7, + 0xA4, 0x37, 0x0F, 0xC2, 0x1F, 0x70, 0xFC, 0x75, 0x58, 0x4E, 0x08, 0x18, 0x69, 0x3D, 0x62, 0x8D, + 0x30, 0x2B, 0xA1, 0x8D, 0x8C, 0x90, 0xCE, 0x26, 0xE9, 0x6D, 0xB6, 0x7B, 0x9D, 0x8D, 0x6D, 0x03, + 0x2B, 0x89, 0x4D, 0x7A, 0x4D, 0xD6, 0xE7, 0xCC, 0x49, 0x8F, 0x31, 0xB3, 0x9E, 0x30, 0xB3, 0xDA, + 0xED, 0x6C, 0xAE, 0x76, 0xBB, 0xAB, 0x9D, 0xCD, 0x76, 0x77, 0xAB, 0x67, 0x62, 0xC7, 0x6C, 0xD9, + 0x5E, 0x63, 0x90, 0xFF, 0x9C, 0x58, 0x7B, 0x8E, 0x3C, 0x5D, 0xD3, 0x3B, 0xEA, 0x73, 0x7E, 0xBA, + 0x5D, 0xE4, 0xE6, 0xC5, 0x8B, 0xED, 0xED, 0x1E, 0x59, 0x3A, 0xE0, 0x9A, 0x85, 0x55, 0xF8, 0x6F, + 0xCB, 0x31, 0x8F, 0x89, 0x3B, 0xEB, 0xD2, 0xA1, 0x15, 0x82, 0xDD, 0xEC, 0x3B, 0x43, 0x57, 0xF5, + 0x1E, 0xD4, 0xB1, 0xDB, 0x49, 0x0C, 0x47, 0x62, 0xA5, 0xE2, 0x62, 0xEE, 0x77, 0x61, 0x60, 0xFD, + 0x9E, 0x64, 0xDC, 0x5A, 0x28, 0x3A, 0x8C, 0x7D, 0x67, 0x27, 0x3D, 0x18, 0x7D, 0x0F, 0xC6, 0x8B, + 0x89, 0x82, 0x9B, 0x8F, 0xE4, 0xAE, 0x8D, 0xCA, 0x84, 0x1A, 0xD8, 0x13, 0x77, 0xEA, 0xEA, 0x2A, + 0x22, 0xC2, 0x44, 0x9A, 0x49, 0x3F, 0x83, 0xB5, 0xC6, 0x39, 0xD3, 0x71, 0xF9, 0x63, 0x1F, 0xAC, + 0x84, 0x72, 0x0B, 0xCE, 0xF3, 0x6F, 0xB2, 0xD4, 0x14, 0x82, 0x68, 0x44, 0x86, 0x04, 0x40, 0x47, + 0xDF, 0xB0, 0x92, 0xF5, 0x98, 0x1B, 0x5A, 0x5C, 0x53, 0x49, 0xB3, 0x5C, 0xFC, 0x2D, 0xA3, 0x5F, + 0x77, 0xD9, 0xED, 0x0D, 0x7C, 0x1C, 0x30, 0xB3, 0x7C, 0x6B, 0x19, 0x16, 0x64, 0x6B, 0x6B, 0xE9, + 0x11, 0x2F, 0x3F, 0xE0, 0x5C, 0x7F, 0xAE, 0xE6, 0x78, 0xA5, 0x53, 0x79, 0x9E, 0x86, 0x83, 0x1D, + 0xBA, 0xF0, 0x6B, 0x3C, 0xEC, 0x28, 0x12, 0xC4, 0xEB, 0x0E, 0xA2, 0xDB, 0xD1, 0x89, 0xC3, 0xC0, + 0xBA, 0x09, 0x9C, 0x4F, 0x22, 0xF4, 0x46, 0xC1, 0x22, 0xEC, 0x8B, 0x8A, 0x42, 0x42, 0xCD, 0xEF, + 0x46, 0x77, 0x64, 0x1C, 0xC9, 0xC4, 0x97, 0x54, 0x5B, 0xDD, 0x8D, 0x4D, 0x15, 0x3F, 0x73, 0x55, + 0xEE, 0x53, 0xB3, 0x54, 0xBE, 0x8E, 0x3B, 0x0D, 0x59, 0x8C, 0x46, 0x0E, 0xA1, 0x98, 0xCC, 0xC9, + 0x89, 0x1C, 0x17, 0xF7, 0xD6, 0x81, 0x29, 0x1A, 0xA6, 0x17, 0x65, 0xCA, 0x4D, 0x26, 0x66, 0x76, + 0xB9, 0xE8, 0xC3, 0xF5, 0x12, 0x9B, 0x80, 0xA0, 0x37, 0x56, 0xBB, 0xFA, 0xDE, 0xF8, 0xAC, 0xA2, + 0xBF, 0x3C, 0xFD, 0x70, 0x79, 0x70, 0xB8, 0x7F, 0x74, 0xB2, 0x77, 0xAC, 0xF5, 0x42, 0x40, 0x61, + 0x02, 0xB2, 0xB1, 0x59, 0x31, 0x3F, 0x9A, 0xB8, 0x65, 0x75, 0xE0, 0x8B, 0x2B, 0x0E, 0x61, 0x14, + 0x59, 0x32, 0xA0, 0x64, 0x41, 0xCB, 0x20, 0x91, 0x1C, 0xFF, 0x12, 0xCB, 0x4B, 0x00, 0x80, 0xC8, + 0xA4, 0x30, 0x34, 0x83, 0x6B, 0x15, 0x11, 0x5B, 0x49, 0x90, 0xAC, 0x91, 0x2D, 0x98, 0x02, 0xD8, + 0xA5, 0xFA, 0x88, 0xC6, 0x1A, 0x59, 0xDF, 0xC2, 0x6C, 0x32, 0xCB, 0xDA, 0xAD, 0x70, 0x65, 0x24, + 0x9B, 0xFD, 0x1A, 0x13, 0xD9, 0xBF, 0x60, 0x77, 0xC8, 0x2F, 0x1C, 0x3E, 0x98, 0x56, 0x4F, 0xDA, + 0x10, 0xC5, 0xD1, 0xA8, 0x0E, 0x50, 0x36, 0x3E, 0x33, 0x87, 0xDF, 0x26, 0x8E, 0xCE, 0xCC, 0xD2, + 0x8D, 0x78, 0x6C, 0x2A, 0x33, 0xF4, 0xFC, 0x86, 0x66, 0xC9, 0x81, 0x99, 0x8C, 0x48, 0x45, 0x43, + 0x32, 0x86, 0xA3, 0x3E, 0x34, 0xAA, 0x0E, 0xC0, 0xCC, 0xE1, 0x67, 0xD6, 0x53, 0x45, 0x34, 0x2C, + 0xD2, 0x57, 0x00, 0x18, 0x10, 0x9B, 0x95, 0xB4, 0xAA, 0xD2, 0x2D, 0x58, 0xBF, 0x54, 0x05, 0x53, + 0xB4, 0xA9, 0xCB, 0xF5, 0x61, 0x75, 0x41, 0x0A, 0x71, 0x79, 0x72, 0x72, 0x79, 0xB0, 0xD7, 0x7F, + 0xAF, 0xA9, 0x85, 0x88, 0x37, 0x4A, 0xCC, 0x96, 0xB8, 0x4D, 0xB6, 0xAA, 0xDF, 0x36, 0x4C, 0x74, + 0x40, 0x98, 0x72, 0x84, 0xC4, 0xFC, 0x45, 0x49, 0x87, 0x65, 0x74, 0xAD, 0x5C, 0xBF, 0xFB, 0x45, + 0x32, 0xA6, 0xA9, 0xDE, 0x7D, 0x62, 0x9D, 0x95, 0xDD, 0x57, 0xBD, 0xB8, 0xAF, 0x22, 0xEF, 0x78, + 0xEE, 0x7D, 0x05, 0xE6, 0xFD, 0x89, 0x75, 0xD7, 0x93, 0x99, 0xFB, 0x24, 0xF1, 0x94, 0x99, 0x02, + 0xE5, 0x06, 0xF5, 0x92, 0x06, 0xA5, 0xE7, 0xC0, 0x3F, 0xFA, 0x04, 0xC5, 0x95, 0x32, 0xD9, 0xC0, + 0x99, 0xAB, 0x4E, 0xEE, 0x14, 0x88, 0x29, 0x31, 0xE0, 0xDF, 0x4D, 0x00, 0xC2, 0x82, 0x92, 0xC5, + 0x59, 0xD0, 0x92, 0xA3, 0x91, 0xFC, 0x30, 0x9E, 0x79, 0xFD, 0xD4, 0x8B, 0xFB, 0x89, 0x2C, 0x66, + 0x5D, 0xC2, 0x0D, 0xC4, 0x13, 0xEA, 0xAC, 0xA7, 0x66, 0x3A, 0xFF, 0xA7, 0x59, 0x4D, 0xB1, 0xA1, + 0xA5, 0x9C, 0x0C, 0x19, 0x10, 0xF0, 0xC3, 0x21, 0x43, 0x41, 0x9C, 0x5D, 0x6B, 0x7B, 0x59, 0xBB, + 0x5A, 0x6F, 0xE8, 0x0E, 0x7E, 0xE6, 0x93, 0x6C, 0xCC, 0x4B, 0x3B, 0xEC, 0xB8, 0xA9, 0x9B, 0x5C, + 0x41, 0x6F, 0x11, 0x6F, 0x1A, 0xE2, 0x1F, 0x96, 0xD8, 0xB5, 0x07, 0xA0, 0xBE, 0xA7, 0xEE, 0xC1, + 0xE3, 0x86, 0xF2, 0x15, 0x48, 0x6B, 0x4C, 0x49, 0x53, 0x1B, 0x32, 0xCD, 0x16, 0xA1, 0xE1, 0x40, + 0x0E, 0xAA, 0x65, 0x7C, 0x33, 0x3E, 0x24, 0xBE, 0x5A, 0x26, 0x95, 0x31, 0xEF, 0xD7, 0x8B, 0xCD, + 0x4B, 0xE9, 0xA0, 0x91, 0xDF, 0x3D, 0x30, 0x68, 0x5C, 0x79, 0x95, 0x5B, 0x36, 0x0E, 0xEB, 0x44, + 0xC3, 0x92, 0x6F, 0xCB, 0x92, 0x98, 0xF5, 0xD3, 0x5A, 0x99, 0x0D, 0xF3, 0x59, 0xD7, 0x8C, 0x6C, + 0x5E, 0x4A, 0x6B, 0x1E, 0x58, 0xB7, 0xCD, 0x88, 0x6D, 0xAE, 0xC8, 0x22, 0xD7, 0x7D, 0xCE, 0x28, + 0xFB, 0x9F, 0x4E, 0xDE, 0x7C, 0x38, 0x66, 0x48, 0xF5, 0x4B, 0x1D, 0x23, 0xCF, 0x1D, 0xB2, 0x3C, + 0x46, 0x07, 0x74, 0xE8, 0x53, 0x7D, 0x7F, 0x24, 0xD5, 0x13, 0x5A, 0xD7, 0xC2, 0xE2, 0x4C, 0x47, + 0x60, 0xAC, 0x07, 0xC3, 0x75, 0xAB, 0xB3, 0xA3, 0xE5, 0x86, 0x8C, 0x4B, 0x5F, 0x91, 0x4C, 0xCB, + 0xC7, 0x07, 0xBA, 0x64, 0xBA, 0x14, 0xBD, 0x1A, 0xA4, 0x87, 0xED, 0xF3, 0xE5, 0x54, 0x0E, 0xCA, + 0x19, 0xBB, 0x37, 0x8B, 0xB5, 0x78, 0x08, 0xA5, 0x44, 0xB8, 0x02, 0xA3, 0x8A, 0x59, 0x97, 0xA8, + 0xEA, 0x4E, 0xFA, 0xF0, 0x62, 0x4E, 0x8A, 0x52, 0x8B, 0xB9, 0xD5, 0xC7, 0xE0, 0x8E, 0xEB, 0x5C, + 0x2D, 0xFE, 0xFE, 0xFB, 0xBF, 0x54, 0x06, 0xF1, 0x5B, 0xB3, 0xA1, 0xB2, 0x59, 0x07, 0x2F, 0x31, + 0xB5, 0x5B, 0xB3, 0x2D, 0x73, 0x69, 0x7A, 0x7F, 0x59, 0x1E, 0xC0, 0xB3, 0xAB, 0xE0, 0x9C, 0x11, + 0x4A, 0xAB, 0xAA, 0x45, 0xE0, 0xD5, 0x7B, 0x7E, 0x4E, 0x22, 0x90, 0x5C, 0x99, 0x45, 0x70, 0xBD, + 0x58, 0xEC, 0xDA, 0x0A, 0x76, 0xF9, 0x8F, 0x6E, 0x86, 0x15, 0x9E, 0x4F, 0x4C, 0x5B, 0xEB, 0x55, + 0x78, 0x16, 0x08, 0xF2, 0x78, 0x2E, 0x3D, 0x01, 0x6C, 0xCD, 0x7D, 0x02, 0x90, 0x47, 0x5F, 0xC5, + 0x29, 0x20, 0x25, 0xA2, 0x47, 0x9A, 0x1A, 0x52, 0xA3, 0xBB, 0xEA, 0xEC, 0x60, 0x62, 0x7C, 0xF5, + 0x91, 0x38, 0x9F, 0x79, 0xE6, 0x30, 0x31, 0xDF, 0x4C, 0x4F, 0x29, 0x7F, 0x6F, 0x34, 0x16, 0xD5, + 0x86, 0xE5, 0xDA, 0xD3, 0x93, 0x89, 0x77, 0xB2, 0x68, 0xC1, 0x67, 0x9A, 0xD7, 0x39, 0xA9, 0xBB, + 0x74, 0x51, 0xD1, 0x68, 0x16, 0xE6, 0xAC, 0x40, 0x33, 0xB6, 0x24, 0xBF, 0x1F, 0x1E, 0xB9, 0x2D, + 0xFA, 0xC4, 0x31, 0xFF, 0x11, 0x9D, 0xD7, 0xA0, 0xD4, 0x45, 0x1E, 0x95, 0x9E, 0x16, 0xF3, 0x18, + 0x05, 0x21, 0x0D, 0xF0, 0x51, 0x45, 0x01, 0xB3, 0xF6, 0x77, 0x7B, 0xAD, 0x1D, 0xE2, 0x95, 0xE4, + 0xC1, 0xF2, 0x0E, 0x51, 0x53, 0x26, 0x44, 0xE7, 0xFA, 0xB0, 0x24, 0x6E, 0xF1, 0x0C, 0x8D, 0xB0, + 0x82, 0xBD, 0xF1, 0xE5, 0x20, 0x49, 0x9E, 0x5E, 0xF2, 0x35, 0xAE, 0x9A, 0xA3, 0xAB, 0x47, 0xAB, + 0x52, 0x10, 0x0A, 0x7C, 0x56, 0x16, 0xE9, 0x58, 0x4D, 0x49, 0x8C, 0x28, 0x92, 0x4F, 0xAE, 0x20, + 0x5E, 0x8C, 0x06, 0x55, 0xCA, 0x39, 0xF2, 0x15, 0x96, 0x46, 0x5E, 0x5E, 0xC7, 0xBB, 0xCA, 0xCA, + 0x5D, 0xA0, 0xB6, 0xF0, 0x4D, 0x4B, 0x97, 0xE7, 0xB2, 0x13, 0x6B, 0x78, 0xE9, 0xB6, 0xB0, 0x28, + 0x49, 0xE2, 0xE5, 0x72, 0x56, 0xE2, 0xC1, 0x9D, 0x13, 0x0E, 0x6E, 0x48, 0x5E, 0x15, 0x16, 0x9E, + 0x40, 0xAF, 0xAD, 0xE9, 0x28, 0x7C, 0xA9, 0x65, 0xC3, 0xE7, 0x3D, 0xD1, 0xF8, 0xE8, 0x7E, 0x75, + 0xBD, 0x3B, 0x57, 0x4F, 0x29, 0xAB, 0xBD, 0xBC, 0x30, 0xC0, 0x6B, 0xBB, 0x4B, 0xA5, 0xD7, 0xEF, + 0x19, 0xB4, 0xE4, 0x6D, 0x8A, 0xB9, 0x12, 0x84, 0xC5, 0x55, 0x26, 0xC9, 0x64, 0xDF, 0x73, 0xAE, + 0x24, 0x2F, 0xF3, 0x68, 0x92, 0xC5, 0x11, 0xE5, 0xF3, 0x71, 0x26, 0xE5, 0xD5, 0x05, 0x51, 0x66, + 0xDE, 0x4B, 0x8E, 0x8C, 0xE3, 0x2D, 0xA6, 0xB9, 0xB7, 0x37, 0x8F, 0xAE, 0xB2, 0xB9, 0xB5, 0x00, + 0xCA, 0xC5, 0xC2, 0x5E, 0x5D, 0x0C, 0x79, 0x7D, 0x22, 0xCD, 0x95, 0xFC, 0x22, 0x1A, 0x5E, 0x86, + 0x36, 0x97, 0xFE, 0xA2, 0xC4, 0x5E, 0x8A, 0x05, 0xDE, 0x03, 0x39, 0x2C, 0x3C, 0x3C, 0xCB, 0xB2, + 0x76, 0x0F, 0xFF, 0x1F, 0xFC, 0x51, 0x1D, 0xD3, 0x31, 0x95, 0x00 }; ///main_js //To convert AP-Config\index.html to index_html[], run the Python index_html_zipper.py script in the Tools folder: @@ -1020,1049 +1037,1078 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xC8, 0x56, 0x63, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, - 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xE9, 0x72, 0xDB, 0x48, - 0x93, 0xE0, 0xFF, 0x7E, 0x8A, 0xFA, 0x38, 0x3B, 0x63, 0x69, 0x46, 0xA4, 0x78, 0x48, 0xB2, 0xAC, - 0xB6, 0x15, 0xA1, 0xCB, 0xB6, 0xF6, 0x93, 0x6C, 0x8E, 0x28, 0x7F, 0x7D, 0x6C, 0xEC, 0x76, 0x40, - 0x40, 0x91, 0xC4, 0x67, 0x10, 0x40, 0xE3, 0x90, 0x2C, 0x4F, 0xCC, 0xC4, 0x3C, 0xC6, 0xEE, 0x83, - 0xEC, 0x0B, 0xEC, 0xA3, 0xCC, 0x93, 0x6C, 0x66, 0x56, 0x01, 0x04, 0x40, 0x9C, 0x24, 0x48, 0x51, - 0x32, 0xDD, 0xD1, 0x12, 0x05, 0xA2, 0xAE, 0xAC, 0xCC, 0xAC, 0xCC, 0xAC, 0x3C, 0xDE, 0xFE, 0xE5, - 0xFC, 0xF3, 0xD9, 0xED, 0x6F, 0xFD, 0x0B, 0x36, 0xF6, 0x26, 0xC6, 0xF1, 0x4F, 0x6F, 0xF1, 0x17, - 0x33, 0x14, 0x73, 0xF4, 0xAE, 0xC1, 0xCD, 0xC6, 0xF1, 0x4F, 0xF0, 0x84, 0x2B, 0xDA, 0xF1, 0x4F, - 0x0C, 0xFE, 0xBD, 0x9D, 0x70, 0x4F, 0x61, 0xEA, 0x58, 0x71, 0x5C, 0xEE, 0xBD, 0x6B, 0xF8, 0xDE, - 0xB0, 0x79, 0xD8, 0x60, 0xBB, 0xD1, 0x2F, 0xC7, 0x9E, 0x67, 0x37, 0xF9, 0x9F, 0xBE, 0x7E, 0xFF, - 0xAE, 0xF1, 0x6B, 0xF3, 0xCB, 0x49, 0xF3, 0xCC, 0x9A, 0xD8, 0x8A, 0xA7, 0xDF, 0x19, 0xBC, 0xC1, - 0x54, 0xCB, 0xF4, 0xB8, 0x09, 0x2D, 0x2F, 0x2F, 0xDE, 0x71, 0x6D, 0xC4, 0x77, 0xD4, 0xB1, 0x63, - 0x4D, 0xF8, 0xBB, 0xCE, 0xB4, 0x13, 0x4F, 0xF7, 0x0C, 0x7E, 0x3C, 0xB0, 0x15, 0xE7, 0xEB, 0x7B, - 0xDF, 0x64, 0x37, 0xB7, 0x7F, 0x65, 0x03, 0xEE, 0xF9, 0xF6, 0xDB, 0x5D, 0xF1, 0x4D, 0x64, 0x28, - 0x53, 0x81, 0xA6, 0x8D, 0x7B, 0x9D, 0x3F, 0xD8, 0x96, 0xE3, 0x35, 0xE8, 0x1B, 0xFC, 0x17, 0x8E, - 0xF2, 0xA0, 0x6B, 0xDE, 0xF8, 0x9D, 0xC6, 0xEF, 0x75, 0x95, 0x37, 0xE9, 0x8F, 0x1D, 0xA6, 0x9B, - 0xBA, 0xA7, 0x2B, 0x46, 0xD3, 0x55, 0x15, 0x03, 0x06, 0xDE, 0x61, 0x13, 0xE5, 0x9B, 0x3E, 0xF1, - 0x27, 0xD3, 0x07, 0xBE, 0xCB, 0x1D, 0xFA, 0x4B, 0x81, 0x39, 0xBF, 0x6B, 0xEF, 0x30, 0x77, 0xEC, - 0xE8, 0xE6, 0xD7, 0xA6, 0x67, 0x35, 0x87, 0xBA, 0xF7, 0xEE, 0x91, 0xBB, 0xD3, 0xD9, 0x1A, 0xF0, - 0x05, 0x73, 0xB8, 0xF1, 0xAE, 0xE1, 0x7A, 0x8F, 0x06, 0x77, 0xC7, 0x9C, 0x7B, 0x0D, 0x36, 0x76, - 0xF8, 0x10, 0x9E, 0x38, 0xEA, 0xEE, 0x9D, 0x65, 0x79, 0xAE, 0xE7, 0x28, 0x76, 0x6B, 0xA2, 0x9B, - 0x2D, 0xD5, 0x75, 0x1B, 0x25, 0x1B, 0xD2, 0xD3, 0x68, 0x03, 0x57, 0x75, 0x74, 0xDB, 0x63, 0xF0, - 0x9D, 0x78, 0xE1, 0xEF, 0x7F, 0xFA, 0xDC, 0x79, 0x6C, 0xF6, 0x5A, 0x07, 0xAD, 0x36, 0x75, 0xFE, - 0x77, 0x78, 0xF5, 0xED, 0xAE, 0x78, 0x2D, 0xA3, 0x4D, 0x7C, 0x36, 0x95, 0x1A, 0xDC, 0xF9, 0xA6, - 0x06, 0x13, 0x9A, 0x6D, 0x17, 0x6D, 0x78, 0x1C, 0x6E, 0xC1, 0x7F, 0xDB, 0xD2, 0x2C, 0xD5, 0x9F, - 0xC0, 0x2E, 0x6C, 0xB7, 0x2C, 0x73, 0xEB, 0x95, 0x6A, 0xE8, 0xEA, 0xD7, 0x57, 0x3B, 0xEC, 0x55, - 0xCB, 0xB3, 0x46, 0x23, 0x83, 0x37, 0xEF, 0x3C, 0x13, 0xFE, 0x1C, 0xFA, 0xA6, 0xEA, 0xE9, 0x96, - 0xC9, 0xB6, 0xF8, 0x36, 0xFB, 0xB7, 0xB0, 0xB5, 0xE8, 0x01, 0x96, 0xEF, 0x3B, 0x0E, 0x74, 0x71, - 0xAB, 0x38, 0x23, 0xEE, 0xB5, 0xD4, 0xB1, 0x6E, 0x68, 0xF0, 0xF7, 0xFF, 0x68, 0xFF, 0xCF, 0x6D, - 0xD9, 0xCD, 0x99, 0xA1, 0xB8, 0xEE, 0xD6, 0x2B, 0x1D, 0x76, 0xBC, 0xA9, 0x2A, 0x0E, 0xF7, 0x9A, - 0x9A, 0xF5, 0x60, 0xB2, 0xC8, 0xDF, 0xBE, 0xFD, 0x6A, 0xFB, 0xE7, 0xB0, 0xE3, 0x7F, 0xDF, 0x16, - 0xD3, 0x4D, 0xCE, 0x1E, 0x81, 0x3D, 0x9D, 0x7C, 0xCB, 0xF5, 0x00, 0x61, 0xD5, 0xE6, 0xC8, 0xB1, - 0x7C, 0x3B, 0x31, 0xAD, 0x31, 0xD7, 0x47, 0x63, 0xEF, 0x88, 0xB5, 0x7F, 0x8E, 0x3D, 0xB6, 0xEE, - 0xB9, 0x33, 0x34, 0xAC, 0x87, 0x23, 0x36, 0xD6, 0x35, 0x8D, 0x9B, 0xF1, 0x6F, 0x01, 0x82, 0xA6, - 0xAB, 0xE3, 0x42, 0x8F, 0x64, 0x07, 0xAC, 0xDD, 0xDA, 0x73, 0x19, 0x57, 0x5C, 0x1E, 0x7F, 0xF3, - 0xCE, 0x72, 0x34, 0xC0, 0xBE, 0x3B, 0xCB, 0xF3, 0xAC, 0xC9, 0x11, 0x73, 0x2D, 0x43, 0xD7, 0x58, - 0xC7, 0xFE, 0xC6, 0xFE, 0x41, 0x6D, 0xE3, 0x7F, 0x91, 0xA5, 0xFC, 0x34, 0x9D, 0xAF, 0xA1, 0xBB, - 0xDE, 0x7A, 0xCF, 0x16, 0xFF, 0xD9, 0x8A, 0xA6, 0xE9, 0xE6, 0xA8, 0xE9, 0x88, 0x39, 0xED, 0xB7, - 0xED, 0x6F, 0xE9, 0xCB, 0x11, 0xDD, 0x02, 0x51, 0xB8, 0xCC, 0xD3, 0x76, 0xD2, 0x9F, 0x8F, 0x13, - 0x2B, 0x15, 0xDF, 0x1D, 0x31, 0xD3, 0x32, 0x13, 0x93, 0x9C, 0x00, 0xF6, 0xE8, 0x66, 0xD3, 0xE0, - 0x43, 0x04, 0x44, 0xC6, 0x98, 0x77, 0x3E, 0x2C, 0xC1, 0x3C, 0x1A, 0x02, 0xD2, 0xBA, 0x89, 0x9E, - 0x2D, 0xDF, 0x03, 0x62, 0xE5, 0x31, 0x20, 0x46, 0x67, 0xAB, 0x9B, 0xF8, 0xF5, 0x85, 0xE3, 0x58, - 0x4E, 0xA2, 0xA5, 0xA6, 0xBB, 0xB6, 0xA1, 0x3C, 0x1E, 0x31, 0xF1, 0x4A, 0x7C, 0x5A, 0xAA, 0x65, - 0x58, 0x30, 0x5F, 0x87, 0x6B, 0xF1, 0xE7, 0x43, 0x60, 0x5E, 0x4D, 0x57, 0xFF, 0x0E, 0x03, 0xBA, - 0x13, 0xC5, 0x30, 0xB8, 0x93, 0x37, 0xEC, 0xC0, 0x57, 0x55, 0x84, 0x47, 0xF5, 0x81, 0x47, 0x0E, - 0x4F, 0x6E, 0x7C, 0xDE, 0xD0, 0xE1, 0xF7, 0x0F, 0x12, 0xA5, 0xEE, 0x2C, 0x43, 0xCB, 0xDA, 0xBE, - 0x6F, 0x4D, 0x6A, 0x9F, 0x98, 0x55, 0xF6, 0x46, 0xE0, 0x3F, 0x62, 0xCF, 0x47, 0xAC, 0xD7, 0xFE, - 0xC7, 0xEC, 0x5E, 0x45, 0x0F, 0xDD, 0x76, 0x5E, 0xC7, 0xDD, 0x1C, 0xB4, 0x0A, 0x7A, 0xD8, 0xCB, - 0xED, 0x61, 0x2F, 0xBB, 0x07, 0xC5, 0xF3, 0x80, 0xE9, 0x26, 0x1A, 0xDB, 0x56, 0x40, 0x2D, 0xCA, - 0x1D, 0x90, 0x80, 0xEF, 0x25, 0x00, 0xFE, 0xBD, 0xA9, 0x9B, 0x1A, 0xFF, 0x76, 0xC4, 0x3A, 0xED, - 0x76, 0x82, 0x24, 0x24, 0x29, 0x74, 0x66, 0xA0, 0x01, 0x87, 0x52, 0x53, 0x42, 0xE4, 0xA0, 0x9D, - 0xF2, 0x2D, 0x4D, 0xD7, 0xB3, 0x6C, 0x20, 0xA3, 0xF8, 0x64, 0x25, 0x7B, 0x13, 0x0C, 0xED, 0xED, - 0xAE, 0x38, 0xBA, 0x7F, 0x7A, 0x7B, 0x67, 0x69, 0x8F, 0x92, 0xC7, 0x6B, 0xFA, 0x3D, 0x53, 0x91, - 0x6F, 0xBE, 0x6B, 0xE0, 0x41, 0xA9, 0x00, 0x82, 0x38, 0x0D, 0xA6, 0x6B, 0xEF, 0x1A, 0x72, 0x79, - 0x97, 0xF0, 0xB8, 0x31, 0xE5, 0x86, 0xD4, 0x40, 0x31, 0xF4, 0x91, 0xF9, 0xAE, 0x41, 0xF3, 0x6D, - 0x04, 0xCD, 0xE5, 0xFB, 0x91, 0x77, 0xE9, 0x7D, 0x7D, 0x32, 0x4A, 0x76, 0xF7, 0x5E, 0x37, 0xF8, - 0x27, 0x38, 0xAD, 0x1B, 0xD3, 0xA3, 0xE5, 0x54, 0x7C, 0xDB, 0xFD, 0xE3, 0x6C, 0x4C, 0xAB, 0x19, - 0xB5, 0x6C, 0x73, 0xD4, 0x80, 0x81, 0xE0, 0xDC, 0x96, 0xDF, 0x31, 0x83, 0xDF, 0x73, 0xA3, 0x71, - 0x0C, 0x0C, 0xDA, 0x56, 0xCC, 0x68, 0x9F, 0x7D, 0xEE, 0xA8, 0x70, 0x30, 0x34, 0x62, 0x03, 0x13, - 0x72, 0x8B, 0x99, 0x11, 0xFA, 0xC1, 0x60, 0x08, 0x86, 0x77, 0x8D, 0x80, 0x1C, 0x24, 0x35, 0x34, - 0x8E, 0xFF, 0xE5, 0xE0, 0x35, 0xC0, 0x08, 0xFA, 0x8C, 0xAC, 0x72, 0x17, 0x96, 0x29, 0x21, 0x24, - 0x3E, 0xE6, 0x41, 0x2B, 0xD1, 0x31, 0x31, 0x9D, 0xE8, 0xAE, 0x10, 0x12, 0x4E, 0xF7, 0x50, 0x6C, - 0xA1, 0x00, 0xB2, 0xC3, 0x41, 0x74, 0xBA, 0x34, 0xFB, 0x8E, 0x85, 0x84, 0x1B, 0x85, 0xF3, 0xDD, - 0xF1, 0x0D, 0x7E, 0xE7, 0x01, 0x2C, 0xDE, 0xEE, 0xDE, 0x1D, 0xBF, 0xBD, 0x73, 0xE8, 0x7F, 0x94, - 0x80, 0x84, 0x08, 0xC3, 0x74, 0x17, 0xF8, 0x05, 0x9E, 0xC9, 0x08, 0x2E, 0xD6, 0x37, 0x90, 0x23, - 0xB3, 0x07, 0x45, 0xF7, 0x5A, 0xAD, 0xD6, 0xAA, 0xA6, 0x8E, 0xE2, 0x9C, 0xC1, 0x3D, 0x9E, 0x32, - 0x73, 0x76, 0x0E, 0x9D, 0x65, 0x4C, 0x7D, 0xAC, 0xB8, 0xC0, 0x9B, 0x1F, 0x18, 0xF5, 0xB1, 0x8A, - 0xC9, 0x0E, 0x75, 0x67, 0xF2, 0x00, 0x22, 0xC0, 0x17, 0xDB, 0xB0, 0x14, 0x2D, 0x7D, 0xD6, 0xC9, - 0xF9, 0xBE, 0x97, 0x6D, 0x98, 0x6F, 0x6B, 0x8A, 0xC7, 0x81, 0x55, 0x8A, 0x56, 0x2D, 0x16, 0xDF, - 0x04, 0xB1, 0x90, 0x60, 0x23, 0x4A, 0x2E, 0xE6, 0xF8, 0xA7, 0x54, 0x92, 0x42, 0x3C, 0xC6, 0xA5, - 0x86, 0xEF, 0x83, 0x68, 0x3A, 0x69, 0x76, 0xBA, 0x20, 0x63, 0x21, 0x21, 0x85, 0xF4, 0xE2, 0x78, - 0x5F, 0x9B, 0x2E, 0x0A, 0xC2, 0x11, 0x3A, 0x89, 0x49, 0xC9, 0xBF, 0xE8, 0xEF, 0x75, 0x21, 0x2A, - 0xA3, 0x78, 0x16, 0x99, 0x4D, 0x69, 0x30, 0x47, 0x00, 0xDB, 0xC9, 0x06, 0xEC, 0x04, 0x1A, 0xF5, - 0x95, 0x11, 0x2F, 0xB9, 0x20, 0xC7, 0x7A, 0x98, 0xD9, 0xC7, 0x3B, 0xC3, 0x52, 0xBF, 0xFE, 0x1C, - 0xED, 0xA0, 0xA0, 0x13, 0x71, 0x9C, 0x20, 0x7B, 0x4E, 0x30, 0x1B, 0xFC, 0x87, 0x8B, 0xBF, 0x00, - 0x89, 0xE6, 0xF1, 0x61, 0xCC, 0x61, 0xEF, 0x82, 0x4D, 0x3C, 0x8A, 0xB0, 0x0D, 0x00, 0x5E, 0xF0, - 0xF8, 0x6F, 0xDC, 0x71, 0x81, 0x59, 0x67, 0x33, 0x87, 0xFB, 0x76, 0xAB, 0x2D, 0xB9, 0x03, 0xE2, - 0xC4, 0xCC, 0x70, 0xD3, 0x5E, 0x47, 0xA6, 0xEB, 0x96, 0xEE, 0xF6, 0xC3, 0xA7, 0xC1, 0x20, 0x32, - 0xB7, 0xC8, 0x28, 0xAC, 0x60, 0x18, 0x81, 0x77, 0xA7, 0xB7, 0x97, 0xE7, 0xD9, 0xBD, 0x9F, 0x0B, - 0xDC, 0x3C, 0x35, 0x7C, 0xEE, 0x01, 0x5A, 0x8E, 0xD9, 0xE5, 0x39, 0x9C, 0xB1, 0xF0, 0xAF, 0xE4, - 0x18, 0xAA, 0x05, 0xF2, 0x93, 0x6E, 0x02, 0xD2, 0xBB, 0x57, 0x57, 0x1F, 0xB3, 0xC7, 0xB9, 0xBA, - 0x1A, 0x1F, 0xCD, 0x74, 0x93, 0x80, 0x0A, 0xB7, 0x34, 0x0E, 0xE2, 0xF3, 0x95, 0xE2, 0x65, 0xF7, - 0xB3, 0x07, 0xCB, 0x7F, 0xD3, 0xEE, 0xBE, 0xD9, 0x7B, 0xFD, 0x46, 0xCE, 0x70, 0xA7, 0x6C, 0xB7, - 0x79, 0x40, 0x6E, 0x76, 0xDA, 0xFB, 0xAD, 0xCE, 0xE1, 0x7E, 0x7B, 0xFF, 0xF5, 0x41, 0xA7, 0x62, - 0xC7, 0x27, 0x46, 0xCE, 0x7C, 0x3B, 0xFB, 0x07, 0x30, 0xE3, 0xC3, 0x60, 0xB2, 0x6C, 0xEB, 0xA4, - 0x7F, 0xB6, 0x3D, 0x0B, 0xCF, 0x52, 0x68, 0x13, 0x81, 0xF5, 0xC5, 0xD9, 0xC5, 0xFB, 0xEC, 0x41, - 0xF1, 0xDB, 0x22, 0x68, 0x73, 0x95, 0x0F, 0x7F, 0xCD, 0x03, 0x48, 0xF7, 0xB0, 0xDD, 0x6D, 0x1F, - 0xB4, 0xF6, 0x0F, 0x0E, 0x4B, 0xC2, 0x03, 0x7B, 0xFC, 0x2D, 0xA7, 0xC7, 0xBD, 0xD7, 0x9D, 0x83, - 0xC3, 0xF6, 0x5E, 0x6B, 0xAF, 0xDD, 0xAB, 0xD0, 0xE3, 0xEF, 0x79, 0xB8, 0x70, 0x78, 0x70, 0x70, - 0xB0, 0xDF, 0xDA, 0x3B, 0xDC, 0x4B, 0x9E, 0xCA, 0x45, 0x80, 0x8D, 0xF2, 0xB6, 0xD4, 0xBF, 0xC7, - 0x4E, 0xC0, 0x42, 0x26, 0x5E, 0xB3, 0x9D, 0x94, 0x6A, 0x66, 0xF9, 0x1E, 0x1D, 0x28, 0x33, 0x8C, - 0xE9, 0x2F, 0xCD, 0x26, 0x6B, 0x06, 0xFF, 0x18, 0x1C, 0xDD, 0x43, 0x90, 0x67, 0xD8, 0x99, 0x65, - 0x0E, 0xF5, 0x51, 0xE4, 0x8B, 0x66, 0xF3, 0x78, 0x96, 0xA1, 0xC9, 0xE1, 0x35, 0xD0, 0xCF, 0x40, - 0x39, 0x1A, 0x29, 0x76, 0xB3, 0x9B, 0xC2, 0xC3, 0xDE, 0x0A, 0x05, 0x24, 0x94, 0xAC, 0x3C, 0x93, - 0xC1, 0xFF, 0x4D, 0xDB, 0xD1, 0x61, 0x72, 0x8F, 0x6C, 0xAA, 0x34, 0x0B, 0x1E, 0x6C, 0x8B, 0x29, - 0x88, 0x19, 0x34, 0x98, 0xF7, 0x68, 0xC3, 0x32, 0x44, 0x17, 0x0D, 0x06, 0x47, 0x97, 0xD2, 0x14, - 0x2D, 0xE8, 0x3C, 0x31, 0x14, 0xDB, 0xE5, 0x8D, 0xD4, 0x3D, 0x12, 0xAF, 0x92, 0x7A, 0xFD, 0xAE, - 0xF1, 0x0F, 0xC1, 0xBB, 0xFD, 0x78, 0xEF, 0x8A, 0xA3, 0x2B, 0x4D, 0xFE, 0x0D, 0x36, 0x40, 0xE3, - 0x78, 0xB0, 0x2A, 0x06, 0x74, 0x27, 0x9E, 0xE2, 0x19, 0xE2, 0x58, 0x86, 0x3B, 0x1D, 0x27, 0xDE, - 0xF6, 0x38, 0x75, 0xD4, 0x38, 0x00, 0x7D, 0x47, 0x21, 0x13, 0xC0, 0x5B, 0x3D, 0xB6, 0x34, 0xD4, - 0xDE, 0xA7, 0xA7, 0x22, 0xE9, 0xF2, 0xA8, 0xD6, 0xB3, 0x3B, 0x9D, 0x25, 0xD4, 0x7D, 0x3C, 0xEE, - 0xF4, 0x34, 0x9C, 0x11, 0x00, 0x49, 0xC5, 0x98, 0xAC, 0x6D, 0x0A, 0x96, 0xC1, 0x26, 0x77, 0xB0, - 0x4F, 0x92, 0x5C, 0xCB, 0xAD, 0x8C, 0xB0, 0x24, 0xB5, 0x2F, 0x77, 0x0C, 0xF2, 0x42, 0x61, 0x87, - 0x33, 0xE8, 0x33, 0x33, 0x37, 0xC5, 0xD1, 0x18, 0xFE, 0x68, 0xA2, 0x34, 0x9F, 0x44, 0xD2, 0xB4, - 0x16, 0x43, 0xCB, 0x99, 0x48, 0xBB, 0x00, 0xA0, 0x7F, 0x37, 0x63, 0x3B, 0x22, 0x5B, 0x72, 0x94, - 0xF9, 0x82, 0xA0, 0x66, 0xD9, 0xAF, 0xE7, 0x49, 0x2C, 0xBB, 0x73, 0x9B, 0x40, 0xCB, 0x2A, 0x9F, - 0x90, 0xB9, 0x4D, 0x68, 0x07, 0x99, 0x5D, 0x90, 0x6D, 0x01, 0x6D, 0x78, 0x20, 0xB8, 0x70, 0x83, - 0xAB, 0x1E, 0x53, 0x98, 0xDC, 0x6D, 0x06, 0xB8, 0x05, 0x3A, 0x3D, 0x37, 0x19, 0xF4, 0x0F, 0x02, - 0x00, 0x93, 0x72, 0x30, 0x28, 0xFA, 0x16, 0x3C, 0x57, 0xBC, 0xE0, 0xC5, 0x16, 0x3B, 0xF1, 0x84, - 0x0C, 0xB9, 0x13, 0x95, 0xC9, 0x1E, 0x74, 0x10, 0x0F, 0x7C, 0x04, 0x35, 0x75, 0xCC, 0xB5, 0xE9, - 0xFB, 0x01, 0xB2, 0xA9, 0x63, 0xC5, 0x1C, 0x71, 0x97, 0xA1, 0x78, 0xE7, 0x2A, 0xF7, 0xF0, 0xCA, - 0x03, 0x8D, 0x07, 0xCA, 0xF2, 0x70, 0xC8, 0xD1, 0xCC, 0x14, 0x4E, 0x06, 0x24, 0xBC, 0xB0, 0x1F, - 0x50, 0xEA, 0xE9, 0xBD, 0x57, 0x03, 0x68, 0x13, 0xC7, 0xD8, 0x57, 0xF8, 0xA2, 0x0D, 0x93, 0x71, - 0xB9, 0xD6, 0xCA, 0x81, 0xED, 0x0C, 0xF8, 0x08, 0x7F, 0x75, 0x73, 0x68, 0x35, 0x55, 0xDD, 0x51, - 0x61, 0x40, 0x8F, 0x7F, 0xF3, 0x42, 0x5A, 0x9F, 0xB8, 0xB8, 0x53, 0x59, 0x9C, 0x30, 0xC1, 0x11, - 0xD3, 0x51, 0x20, 0xC1, 0x05, 0x4B, 0xA0, 0x07, 0x4A, 0x69, 0xC7, 0x05, 0x9B, 0x9F, 0xCE, 0xBF, - 0x63, 0xBA, 0x73, 0xC0, 0x3E, 0x73, 0x41, 0xA1, 0x9B, 0xB6, 0xEF, 0x49, 0x9E, 0xE5, 0x28, 0x9A, - 0x6E, 0x35, 0xA4, 0x25, 0x57, 0xC2, 0xFF, 0x46, 0x3C, 0xBB, 0x57, 0x40, 0x98, 0x79, 0xD7, 0x68, - 0x17, 0x75, 0x67, 0x28, 0x77, 0xDC, 0x88, 0xB2, 0x8E, 0x36, 0x69, 0x9A, 0xC7, 0x72, 0xE3, 0x41, - 0x0C, 0xA0, 0x37, 0x16, 0x02, 0xE5, 0x8B, 0x80, 0x64, 0xA7, 0x32, 0x24, 0x3B, 0x02, 0x92, 0x9D, - 0x6E, 0x6F, 0x6F, 0xFF, 0xE0, 0xF5, 0xE1, 0x9B, 0xF6, 0xF4, 0xD3, 0x06, 0xAA, 0x12, 0xAA, 0xDD, - 0xCA, 0x50, 0xED, 0x0A, 0xA8, 0x6E, 0x20, 0x28, 0x21, 0xD8, 0xAB, 0x0C, 0xC1, 0xDE, 0x06, 0x82, - 0x31, 0x08, 0xEE, 0x55, 0x86, 0xE0, 0xDE, 0x06, 0x82, 0x31, 0x08, 0xEE, 0x57, 0x86, 0xE0, 0xFE, - 0x06, 0x82, 0x31, 0x08, 0x1E, 0x54, 0x86, 0xE0, 0xC1, 0x06, 0x82, 0x31, 0x08, 0xBE, 0xAE, 0x0C, - 0xC1, 0xD7, 0xF5, 0x41, 0xB0, 0x46, 0x10, 0x8A, 0x69, 0xC2, 0xFB, 0xE1, 0x3C, 0x85, 0xE9, 0x3F, - 0xD0, 0x6D, 0xA3, 0x17, 0x39, 0xD2, 0xDC, 0xD9, 0xA3, 0x0F, 0x7B, 0xF4, 0x93, 0x06, 0xA2, 0x3E, - 0x42, 0x19, 0x2E, 0x17, 0x2C, 0xD8, 0xF9, 0x51, 0x31, 0x08, 0xE2, 0x8A, 0x19, 0x0E, 0x7A, 0x48, - 0xC3, 0xBD, 0xAE, 0xB2, 0x89, 0x28, 0xA8, 0x37, 0x62, 0x10, 0x91, 0x1A, 0x70, 0x4C, 0x2D, 0x17, - 0xBB, 0x92, 0xDF, 0xAB, 0x9D, 0x6C, 0x40, 0x17, 0x88, 0x61, 0xDF, 0x91, 0x4B, 0x45, 0xDC, 0x5F, - 0x3B, 0x6F, 0x6F, 0x33, 0x29, 0x60, 0x76, 0xA0, 0x33, 0x52, 0x82, 0xAE, 0x41, 0x65, 0x41, 0x03, - 0x6E, 0x7C, 0x30, 0x79, 0x95, 0x98, 0x33, 0x5C, 0xFD, 0xA8, 0x32, 0x6B, 0x84, 0x91, 0x77, 0xC9, - 0xFB, 0x25, 0xA8, 0x4B, 0x9A, 0x4C, 0xE2, 0xC6, 0x0F, 0xBA, 0x24, 0xF2, 0x4C, 0xBA, 0x8F, 0x90, - 0xD8, 0xD3, 0xC8, 0xB2, 0xAA, 0xA4, 0x62, 0x62, 0xBE, 0xFE, 0x4A, 0x17, 0xC2, 0xE6, 0x19, 0x7A, - 0x33, 0xCC, 0x8C, 0xB3, 0xB5, 0xDD, 0x90, 0xF7, 0x20, 0xF2, 0x41, 0xBA, 0x05, 0x62, 0x49, 0x9A, - 0x75, 0x44, 0xBB, 0x16, 0x93, 0x48, 0xAA, 0xC2, 0xA8, 0x4A, 0x0F, 0x15, 0xD5, 0xB3, 0x60, 0xE5, - 0x1A, 0x1F, 0x2A, 0xBE, 0xE1, 0xB9, 0x45, 0x6A, 0xEB, 0x52, 0x54, 0xD7, 0x22, 0x8E, 0x54, 0x1E, - 0xAB, 0x9D, 0x08, 0xF4, 0xAF, 0xDD, 0x51, 0x6D, 0x08, 0x9D, 0x66, 0x24, 0x4A, 0x79, 0x35, 0x61, - 0x17, 0x24, 0x0B, 0xFF, 0x0A, 0x8D, 0x82, 0x13, 0x0F, 0xF8, 0x66, 0xD4, 0x32, 0x58, 0xB3, 0x19, - 0x10, 0xD7, 0x33, 0x97, 0x0D, 0x30, 0xD2, 0x30, 0x1D, 0xEE, 0x11, 0x48, 0x25, 0xAC, 0x7F, 0x78, - 0xA5, 0xF2, 0xC4, 0xA6, 0xBF, 0xB8, 0x91, 0x2E, 0x77, 0x2D, 0xD9, 0xD6, 0x39, 0x66, 0x7B, 0xCD, - 0x4E, 0xAE, 0x89, 0x8E, 0xAE, 0xD2, 0xB8, 0xE2, 0xFA, 0x0E, 0xD1, 0xF8, 0x8D, 0xE2, 0xF1, 0x4B, - 0x3C, 0x69, 0x72, 0x28, 0xF2, 0x7A, 0xFA, 0x3A, 0xC3, 0xF7, 0x8F, 0x4A, 0x9D, 0x76, 0xF9, 0x2C, - 0x38, 0xE3, 0x6C, 0xEC, 0x12, 0x3F, 0xEC, 0x74, 0x91, 0xA4, 0x7B, 0x6C, 0xCA, 0xD0, 0xCB, 0xF0, - 0x8B, 0xC8, 0xF9, 0x9F, 0x58, 0xE0, 0xC7, 0xEF, 0xB1, 0x7B, 0xCE, 0xE8, 0x49, 0x7F, 0x69, 0x16, - 0x76, 0x8C, 0xFF, 0x3E, 0x7E, 0x3F, 0x2A, 0xF5, 0x5E, 0x8D, 0x4C, 0x35, 0xC1, 0x5C, 0x6F, 0xC7, - 0x9C, 0x99, 0xFE, 0xE4, 0x8E, 0x3B, 0xCC, 0x1A, 0x32, 0xF2, 0xF7, 0x00, 0xFC, 0x75, 0xD1, 0x50, - 0x68, 0x58, 0xAA, 0x40, 0xE6, 0xFF, 0xFA, 0xCF, 0xFF, 0x3D, 0xD4, 0xBF, 0x71, 0xF7, 0xBF, 0xFE, - 0xF3, 0xFF, 0x30, 0x1B, 0x5E, 0x74, 0x39, 0xA0, 0xAD, 0xD6, 0x62, 0x27, 0xE6, 0xA3, 0x37, 0xD6, - 0xCD, 0x11, 0x53, 0xEE, 0xAC, 0x7B, 0xCE, 0xF6, 0x3E, 0x7E, 0x07, 0x99, 0xF2, 0x11, 0xB0, 0x06, - 0x4D, 0x97, 0xD3, 0xBB, 0x3B, 0x78, 0x79, 0xC4, 0x5D, 0xEA, 0x09, 0xE8, 0x6D, 0x97, 0x7A, 0x1E, - 0xA1, 0x8B, 0x04, 0x3A, 0xF6, 0xA8, 0x0E, 0x87, 0xA5, 0xA9, 0x3A, 0x77, 0x5B, 0xEC, 0x93, 0x05, - 0x48, 0xC0, 0x70, 0x46, 0x11, 0x40, 0x33, 0x07, 0xAF, 0xAE, 0x75, 0x97, 0xBC, 0xBC, 0x1C, 0xF2, - 0xEF, 0x42, 0xD6, 0xDF, 0x81, 0xC1, 0xC8, 0x92, 0xA9, 0x9B, 0xEC, 0x14, 0xFD, 0x06, 0x26, 0x96, - 0xC6, 0x5B, 0xEC, 0x5C, 0x9C, 0x04, 0x47, 0x38, 0x99, 0x16, 0xBB, 0xD2, 0x27, 0x3A, 0x3A, 0xE7, - 0xB4, 0xDA, 0xED, 0x76, 0xA7, 0xDB, 0xA5, 0x76, 0x6D, 0xF8, 0xA2, 0xC4, 0xB6, 0x2F, 0xF5, 0xB8, - 0x28, 0x7B, 0x6C, 0x4C, 0xDF, 0x2B, 0x10, 0x07, 0x4B, 0x9C, 0x31, 0x19, 0x94, 0x21, 0x84, 0xD4, - 0xFD, 0x79, 0x08, 0x23, 0x2A, 0x49, 0x0A, 0x14, 0x4A, 0x95, 0x25, 0x23, 0x57, 0x05, 0xB3, 0xF4, - 0x53, 0x62, 0x18, 0x3B, 0xBD, 0xE9, 0xBC, 0x02, 0x66, 0x91, 0xE4, 0x17, 0x19, 0x37, 0x76, 0x5B, - 0x4F, 0x00, 0xC2, 0x5B, 0x37, 0x5C, 0x4F, 0x1B, 0x06, 0xE1, 0x93, 0x63, 0xCB, 0x79, 0xBB, 0x0B, - 0xBF, 0x68, 0xBC, 0xF5, 0x60, 0x49, 0x03, 0xAE, 0x36, 0x8E, 0x07, 0x44, 0x9F, 0x2E, 0xBB, 0xE3, - 0xDE, 0x03, 0x07, 0x12, 0x89, 0xBC, 0xE3, 0xAE, 0x19, 0xBF, 0xC9, 0x99, 0x69, 0x0B, 0x38, 0x01, - 0x90, 0xBD, 0xC0, 0x32, 0x1D, 0x7D, 0x24, 0x81, 0x0D, 0x98, 0xC0, 0x04, 0x80, 0xD8, 0xA1, 0xA9, - 0x97, 0xC6, 0x26, 0xF0, 0xDE, 0x05, 0x5E, 0x05, 0xFE, 0x33, 0xF4, 0x0D, 0xC1, 0x1F, 0x3C, 0xE5, - 0x2B, 0xB1, 0xA8, 0xD8, 0xCB, 0x1C, 0xFD, 0x2B, 0xD8, 0x90, 0x3F, 0x84, 0x33, 0x50, 0x54, 0xC7, - 0x72, 0xE1, 0x17, 0xF0, 0x26, 0x78, 0x1B, 0x5E, 0xBC, 0xE7, 0x8F, 0x6C, 0xAB, 0xBB, 0xF7, 0x2F, - 0x6C, 0x6C, 0xF9, 0x8E, 0xBB, 0x5D, 0x07, 0x77, 0x0A, 0xD9, 0x51, 0x07, 0xDF, 0x39, 0xEC, 0xBC, - 0x39, 0x08, 0x86, 0x07, 0x8E, 0x44, 0x20, 0x2F, 0x0D, 0xCD, 0x88, 0x73, 0xD8, 0x86, 0x29, 0xD5, - 0xCA, 0x94, 0x88, 0x82, 0xE6, 0xE4, 0x4A, 0xD0, 0xB6, 0x06, 0xB6, 0x34, 0xC7, 0xD7, 0x73, 0xAA, - 0xB2, 0xC2, 0x1F, 0xE7, 0xD1, 0x54, 0x26, 0xBA, 0x7A, 0x0D, 0x18, 0x6A, 0x9C, 0x3B, 0x96, 0x2D, - 0x04, 0xD1, 0x52, 0xF6, 0x90, 0x68, 0xD3, 0x46, 0xEA, 0x1E, 0x1E, 0xCC, 0xD8, 0x40, 0xCE, 0x45, - 0x1B, 0x46, 0x8D, 0x8E, 0x56, 0xAC, 0x4A, 0x9E, 0x68, 0x7F, 0xF7, 0x5D, 0x2F, 0xE0, 0x25, 0x1E, - 0x77, 0x4C, 0xC5, 0x60, 0x8A, 0x31, 0xB2, 0x1C, 0xDD, 0x1B, 0x4F, 0x90, 0x2A, 0x27, 0x8A, 0xA7, - 0x8E, 0xE9, 0x7B, 0x50, 0x0F, 0x84, 0xC2, 0xA9, 0xD8, 0x36, 0x28, 0xC8, 0x42, 0x14, 0xE2, 0xE6, - 0xBD, 0xEE, 0x58, 0x26, 0x8E, 0x2D, 0xF9, 0x93, 0xBC, 0xDA, 0x65, 0xFA, 0x04, 0x14, 0xD3, 0x7B, - 0x2E, 0xFA, 0x76, 0xB8, 0xCA, 0x75, 0xE0, 0x08, 0xAF, 0x5C, 0x31, 0x8C, 0x0D, 0x12, 0xBE, 0xE8, - 0x00, 0x38, 0x57, 0x94, 0xC9, 0xC9, 0x9B, 0x62, 0x1F, 0x6F, 0x5E, 0xAD, 0x7B, 0x5D, 0xC3, 0x1B, - 0x5D, 0x60, 0x16, 0x0E, 0xB0, 0x32, 0x55, 0xF5, 0x89, 0xB9, 0x04, 0xFE, 0xB8, 0xE8, 0xB9, 0x0D, - 0xB8, 0xDD, 0x42, 0xA7, 0x38, 0x1A, 0x31, 0x3A, 0x10, 0x4E, 0x1D, 0x60, 0xE5, 0x9B, 0xAE, 0xAF, - 0x7B, 0x18, 0xE8, 0xC1, 0x00, 0x46, 0x1E, 0xC2, 0x9D, 0x58, 0x0F, 0xED, 0x17, 0x35, 0x18, 0xC1, - 0xDB, 0x66, 0xD6, 0x92, 0x90, 0x91, 0x19, 0xFA, 0x57, 0x6E, 0xA0, 0x8B, 0x06, 0xDE, 0x4B, 0x83, - 0x28, 0x85, 0x2C, 0x0C, 0xB9, 0x22, 0x30, 0x47, 0x98, 0x7B, 0x38, 0x1E, 0xC8, 0x81, 0xD8, 0x3B, - 0x88, 0x6E, 0x82, 0xEB, 0x86, 0xB3, 0x14, 0xF3, 0x56, 0x1F, 0xD7, 0x57, 0x15, 0xAF, 0x6E, 0x5A, - 0x93, 0xB8, 0x5C, 0x78, 0x29, 0x2E, 0xDC, 0x00, 0x84, 0x4D, 0x34, 0x4E, 0x1B, 0x49, 0x42, 0x8B, - 0x33, 0x25, 0x4D, 0x92, 0x9D, 0xE0, 0x4A, 0x85, 0xEB, 0xA3, 0x61, 0x56, 0xC9, 0x27, 0xCA, 0x71, - 0x83, 0x89, 0x6E, 0x5E, 0x18, 0xFC, 0xBE, 0x2C, 0x23, 0xB8, 0x06, 0xC4, 0x1A, 0xFC, 0x8D, 0x61, - 0x13, 0x42, 0xC4, 0x55, 0xF3, 0x02, 0x18, 0x1F, 0x03, 0xA5, 0x18, 0x0F, 0x26, 0x80, 0x98, 0xAE, - 0x71, 0x0C, 0x24, 0x70, 0x89, 0x5C, 0x14, 0xA1, 0xD8, 0xBB, 0x40, 0x84, 0x86, 0xA1, 0x7B, 0x64, - 0x71, 0xBA, 0xE3, 0x28, 0x5C, 0x68, 0x82, 0x28, 0x40, 0x29, 0x6A, 0xFD, 0x80, 0x68, 0x5E, 0xF2, - 0x88, 0x95, 0xA7, 0xAB, 0x44, 0x8A, 0x52, 0xF6, 0x63, 0xF9, 0xF2, 0x12, 0x6C, 0xC7, 0xCB, 0x46, - 0xFC, 0xB3, 0x4F, 0x9F, 0xAB, 0xE0, 0xFD, 0xD9, 0xEE, 0xA7, 0xF6, 0x53, 0xE1, 0xFB, 0x14, 0x9F, - 0xD1, 0x35, 0x49, 0x31, 0x44, 0x58, 0x42, 0x2A, 0x72, 0x4F, 0xD5, 0xE9, 0x03, 0xED, 0x14, 0x44, - 0x5A, 0xA4, 0x8A, 0xDF, 0x2F, 0xCE, 0x9B, 0xEF, 0xDF, 0xF4, 0x89, 0xE9, 0x77, 0xDA, 0xE1, 0xE3, - 0x2F, 0xD7, 0x6F, 0x0E, 0xDB, 0x1B, 0x6A, 0x28, 0xA6, 0x06, 0xC4, 0x94, 0xB2, 0xC4, 0x00, 0xEF, - 0xAE, 0x07, 0x2D, 0xA0, 0x6D, 0x36, 0x30, 0x24, 0x9A, 0x2E, 0xE2, 0x0F, 0x71, 0xCC, 0xB3, 0x31, - 0x57, 0xBF, 0x9E, 0x5A, 0xDF, 0xB8, 0x5B, 0x92, 0x52, 0xC8, 0x1E, 0x1A, 0xED, 0x01, 0x1A, 0xC6, - 0xFF, 0x2E, 0x71, 0xF5, 0x55, 0xAB, 0xEB, 0xDE, 0x6D, 0x54, 0x88, 0x02, 0xF1, 0x47, 0x55, 0x6C, - 0x12, 0x9F, 0x40, 0xD6, 0x81, 0xA5, 0xCA, 0x88, 0x4D, 0x90, 0x87, 0xC4, 0x3B, 0x28, 0x76, 0x09, - 0xAA, 0x81, 0x23, 0xC2, 0xB1, 0x40, 0xB8, 0x02, 0xEA, 0xD0, 0x6D, 0x83, 0x4F, 0xA9, 0x2A, 0x54, - 0x25, 0xC3, 0xAF, 0x62, 0x20, 0x03, 0xB5, 0x76, 0x60, 0x4D, 0x78, 0x54, 0x02, 0x73, 0x99, 0xA6, - 0xAB, 0x1E, 0x8A, 0x7A, 0x28, 0xA0, 0x99, 0x1C, 0x28, 0x10, 0xDD, 0x04, 0x7D, 0x07, 0xA5, 0x45, - 0x98, 0x06, 0x77, 0x30, 0xB0, 0x21, 0xDE, 0x0D, 0xCD, 0xC7, 0xC6, 0x4F, 0x48, 0xA4, 0x42, 0x22, - 0x10, 0x6A, 0xAE, 0x10, 0xF0, 0xE2, 0x2F, 0x93, 0x3F, 0xA1, 0x30, 0xCB, 0x25, 0x85, 0x46, 0x58, - 0x0C, 0x4A, 0x9B, 0xDE, 0xD8, 0x72, 0x79, 0xB8, 0x34, 0x10, 0x57, 0xA1, 0x93, 0x40, 0xC8, 0x9C, - 0x88, 0xA5, 0xDE, 0x71, 0xFC, 0x9B, 0x18, 0x84, 0xE6, 0x3B, 0xF8, 0x39, 0x94, 0xF9, 0x54, 0xC5, - 0x50, 0xFD, 0x70, 0x7D, 0x21, 0xD3, 0x38, 0x81, 0x51, 0xB9, 0x89, 0xE0, 0x5C, 0x2F, 0x87, 0xC2, - 0x98, 0xD1, 0x3A, 0x06, 0xA9, 0x53, 0xAE, 0x9F, 0x5B, 0x7E, 0x82, 0x80, 0x11, 0xC9, 0xC5, 0xED, - 0x44, 0xF4, 0x86, 0xAD, 0xDC, 0xED, 0xF6, 0x4C, 0x47, 0xF2, 0x14, 0x10, 0xE4, 0x10, 0x1B, 0xFB, - 0x0F, 0x39, 0xF8, 0xB1, 0xF8, 0x5D, 0x4E, 0xBD, 0x16, 0xDC, 0x67, 0x76, 0x14, 0x7A, 0x1E, 0x5C, - 0xA1, 0xD0, 0x23, 0x98, 0x7B, 0x78, 0x35, 0x9F, 0x42, 0xCA, 0xE1, 0xE8, 0x73, 0xDF, 0x61, 0xA5, - 0x02, 0xF4, 0x83, 0x62, 0xE8, 0x06, 0xB7, 0x9E, 0x08, 0xA2, 0xC1, 0xE8, 0xC7, 0xF2, 0xC3, 0xAA, - 0x61, 0x1A, 0x8E, 0x5F, 0x33, 0x50, 0x0D, 0xCB, 0x84, 0xC9, 0x3D, 0x15, 0x50, 0xAF, 0x3E, 0x7F, - 0x3A, 0x19, 0x0C, 0x00, 0xA8, 0xE2, 0xC3, 0xCA, 0x81, 0x1A, 0x8C, 0x5F, 0x33, 0x50, 0xED, 0x27, - 0x03, 0x68, 0x1F, 0x81, 0xD9, 0x5F, 0x3D, 0x20, 0xFB, 0xB5, 0x03, 0xF1, 0x93, 0x72, 0xAF, 0xAB, - 0x4F, 0x04, 0xC6, 0xEB, 0x93, 0xBF, 0x5D, 0x9E, 0x35, 0x8E, 0x3F, 0xE1, 0xAF, 0x55, 0x83, 0xF2, - 0x93, 0x18, 0xBB, 0x5E, 0x60, 0xFE, 0xEB, 0xF7, 0x27, 0xA3, 0xF1, 0x7F, 0xFD, 0x1D, 0x09, 0x0C, - 0x7F, 0xAE, 0x1A, 0x92, 0x62, 0xE4, 0x7A, 0x01, 0x39, 0xB8, 0x53, 0x9E, 0x0A, 0x90, 0x83, 0xD3, - 0x13, 0x58, 0x0E, 0xFE, 0x5C, 0x35, 0x20, 0xC5, 0xC8, 0x0B, 0x01, 0xB2, 0xAA, 0x4E, 0x1C, 0x51, - 0x5E, 0x66, 0x05, 0xFD, 0xA7, 0x50, 0x64, 0x68, 0x26, 0xE2, 0x0C, 0xFE, 0xA8, 0xB8, 0xD2, 0x6E, - 0xDA, 0xA8, 0xB0, 0xEA, 0x29, 0x9E, 0xD4, 0x81, 0x1A, 0x42, 0x16, 0xFE, 0x10, 0x4E, 0xA8, 0x71, - 0x7C, 0x41, 0x4F, 0x98, 0x7C, 0xC4, 0x3E, 0x9E, 0x0C, 0x76, 0x2F, 0x0E, 0x0A, 0x55, 0xE8, 0x33, - 0x0B, 0xB4, 0x12, 0x4A, 0x34, 0xE3, 0x2E, 0x1F, 0xAB, 0x66, 0x27, 0xBD, 0x62, 0xBB, 0xC5, 0x17, - 0x50, 0x4C, 0x3E, 0x42, 0x0B, 0x76, 0x22, 0x2D, 0xCB, 0x6C, 0xC0, 0x1D, 0x0A, 0x93, 0x52, 0xA7, - 0x70, 0x08, 0xCC, 0xE7, 0x1A, 0x5D, 0xC4, 0x91, 0x96, 0x13, 0x00, 0x35, 0x46, 0x16, 0x11, 0xED, - 0xE4, 0xA2, 0x9C, 0x66, 0xB2, 0x8E, 0x3E, 0x63, 0x95, 0x34, 0xF8, 0x52, 0x38, 0x5C, 0x01, 0x7F, - 0x3F, 0x79, 0x8E, 0x6E, 0x9F, 0x19, 0x3A, 0x26, 0xAC, 0x08, 0x10, 0xF8, 0xD3, 0xED, 0xCD, 0x65, - 0x9F, 0x89, 0x87, 0xC5, 0x0A, 0xFC, 0xE2, 0xE8, 0x18, 0x9B, 0xC3, 0x8A, 0x2C, 0x05, 0x5F, 0x48, - 0x7B, 0xD6, 0x5D, 0xB9, 0x58, 0x95, 0x46, 0x47, 0x15, 0x1A, 0x2D, 0xF7, 0x98, 0x94, 0x21, 0x82, - 0x8F, 0x34, 0x92, 0x50, 0x9B, 0x15, 0xD0, 0x8E, 0x5D, 0x52, 0xA5, 0x5D, 0x81, 0xB6, 0x2D, 0xF6, - 0x9B, 0xE5, 0x3B, 0x41, 0xA8, 0xDF, 0xC4, 0x77, 0x3D, 0x34, 0xBC, 0x3D, 0xE8, 0xE8, 0x4A, 0x23, - 0xB2, 0x1E, 0x38, 0xE8, 0xD5, 0xCA, 0x14, 0x8F, 0xA1, 0xDF, 0x81, 0xA7, 0x4F, 0x78, 0x54, 0xA9, - 0x3E, 0xD7, 0xDD, 0xF5, 0xD3, 0xA8, 0x4B, 0x71, 0x62, 0x73, 0xBA, 0x69, 0x81, 0x1F, 0x5E, 0x6A, - 0x98, 0xEA, 0x32, 0x4E, 0xA5, 0x88, 0x0D, 0x2A, 0x3A, 0x0D, 0xD8, 0x19, 0xEE, 0x7C, 0xB4, 0x5C, - 0xAF, 0x84, 0x3B, 0xF7, 0xFE, 0x8C, 0x25, 0x57, 0x34, 0x2F, 0xE4, 0x1E, 0xD8, 0xFF, 0x51, 0x39, - 0x46, 0x9D, 0xE5, 0xD5, 0x7D, 0x50, 0xF5, 0xEA, 0xBB, 0xC0, 0xB3, 0x3B, 0x1D, 0x06, 0xA5, 0xAF, - 0xBD, 0x53, 0x9B, 0x2F, 0xFF, 0xE6, 0x7B, 0xC5, 0x78, 0xD1, 0xC7, 0x2C, 0x7C, 0x4B, 0xC4, 0x0B, - 0xEC, 0x7F, 0xD5, 0x78, 0x51, 0x68, 0xA1, 0x4E, 0x87, 0xC2, 0xFC, 0x98, 0x81, 0xCD, 0x5F, 0x1C, - 0x66, 0xC0, 0x51, 0xE0, 0x2C, 0x13, 0x33, 0xB0, 0xFF, 0x75, 0xE7, 0x18, 0x04, 0x83, 0xF9, 0xF1, - 0x02, 0x9B, 0xBF, 0x48, 0xBC, 0xE8, 0xFF, 0x52, 0x2C, 0xD9, 0xE6, 0x60, 0x4E, 0xD6, 0xAD, 0x61, - 0x05, 0xCC, 0x61, 0xFD, 0x5F, 0xE6, 0x46, 0x9E, 0xD7, 0x02, 0x71, 0x57, 0x81, 0x3C, 0x00, 0xA8, - 0xC5, 0xD0, 0xA7, 0xFF, 0xCB, 0x0B, 0x42, 0xA0, 0x6B, 0xCB, 0x37, 0xBD, 0xBE, 0xA5, 0x9B, 0xF3, - 0x1D, 0x39, 0xD4, 0xBC, 0xC4, 0x89, 0x03, 0xFD, 0xAF, 0x2F, 0x63, 0x89, 0xC0, 0x60, 0x1E, 0xCC, - 0x98, 0x36, 0x7F, 0x91, 0x78, 0xB1, 0x24, 0xC6, 0x52, 0x01, 0x73, 0x8A, 0xDF, 0x5A, 0x63, 0xC6, - 0x13, 0x03, 0xE4, 0x62, 0xE8, 0xB5, 0x5E, 0x8C, 0x27, 0xD4, 0xEF, 0x3B, 0xB5, 0xDB, 0x32, 0x23, - 0xAB, 0xBF, 0xC5, 0x2C, 0xBA, 0x13, 0xDD, 0xFB, 0xF0, 0xE1, 0xA4, 0x71, 0x1C, 0xFC, 0xC1, 0xE0, - 0x2F, 0xD4, 0x80, 0x05, 0x4F, 0x5E, 0xBE, 0x2D, 0x2A, 0x63, 0x3E, 0x85, 0x9B, 0xE9, 0x9B, 0xD4, - 0x21, 0xD7, 0x56, 0x6D, 0xBB, 0xA2, 0xAB, 0x7E, 0x95, 0xA0, 0x83, 0xB9, 0x2E, 0xFF, 0xF4, 0x75, - 0xF4, 0xEC, 0x84, 0x4F, 0x23, 0xDF, 0x50, 0x9C, 0xE9, 0x05, 0xBA, 0x4C, 0xD0, 0x48, 0x06, 0x03, - 0xBA, 0xA1, 0x27, 0x2B, 0xD6, 0x16, 0x82, 0x77, 0x22, 0xA2, 0x5B, 0xB7, 0x99, 0x2B, 0x53, 0x07, - 0xE1, 0xF7, 0xA2, 0x4B, 0xF8, 0x65, 0x32, 0xC5, 0xF7, 0xAC, 0x09, 0xE6, 0x77, 0x56, 0x0C, 0xE3, - 0x51, 0x46, 0x49, 0x4A, 0x47, 0x02, 0xC5, 0xE1, 0xAE, 0xC7, 0x94, 0x7B, 0x45, 0xA7, 0xDC, 0xDF, - 0x49, 0xFB, 0x44, 0x8A, 0x51, 0xE1, 0x25, 0xDA, 0xC2, 0x84, 0x9F, 0x36, 0x01, 0x11, 0x7D, 0xB4, - 0x4F, 0x45, 0x3C, 0x61, 0xCE, 0x58, 0x32, 0x4C, 0x31, 0x8C, 0x8B, 0x1D, 0x71, 0x4F, 0x86, 0x18, - 0x5F, 0xE9, 0xAE, 0xB7, 0xB5, 0x3D, 0x13, 0x80, 0x3B, 0xD1, 0xE8, 0x97, 0xCC, 0xAC, 0x9C, 0x19, - 0xD0, 0x98, 0x6F, 0x64, 0x2A, 0x11, 0xEC, 0x58, 0x18, 0xD8, 0x88, 0x41, 0xA3, 0xB9, 0xA3, 0xCC, - 0x19, 0xF7, 0x88, 0xFD, 0xE6, 0x6F, 0xA0, 0x04, 0x10, 0xC5, 0xF1, 0xB9, 0xD1, 0xE8, 0x47, 0x68, - 0xBA, 0x78, 0x00, 0xE4, 0x74, 0xAF, 0x8B, 0x22, 0x90, 0xCB, 0x93, 0x70, 0x12, 0x2F, 0x2E, 0x01, - 0x8B, 0x6F, 0xF1, 0x34, 0x29, 0x63, 0x0B, 0xFC, 0x74, 0x7D, 0x71, 0x42, 0x1E, 0x70, 0x37, 0x27, - 0xBF, 0xFC, 0x4A, 0x39, 0xB8, 0x90, 0xE2, 0xBC, 0x07, 0x8B, 0x4D, 0x2C, 0x20, 0x39, 0xD5, 0x9A, - 0x4C, 0x2C, 0x93, 0xBC, 0x86, 0x30, 0x95, 0x3F, 0x3A, 0xF4, 0xC0, 0xF6, 0xBA, 0xC2, 0xF9, 0x5B, - 0x00, 0xEA, 0xCE, 0xF7, 0xE2, 0xBE, 0x38, 0xAE, 0x6F, 0xE3, 0xBB, 0xAE, 0xF0, 0xFE, 0x06, 0x4A, - 0x37, 0xD9, 0xEB, 0x76, 0x24, 0x9B, 0x97, 0x6C, 0xE8, 0xB6, 0xD8, 0x85, 0xA2, 0x8E, 0xC3, 0x7E, - 0x44, 0xFC, 0x89, 0xE0, 0xA9, 0x72, 0x07, 0xD9, 0xC3, 0x58, 0x9F, 0xBE, 0x21, 0x52, 0x84, 0x69, - 0x92, 0xC0, 0xD9, 0x56, 0x7B, 0x9B, 0x26, 0x8E, 0x39, 0xDC, 0xAC, 0xA1, 0x87, 0xE1, 0x2A, 0x14, - 0xD1, 0x22, 0x7A, 0xA3, 0x8C, 0xBC, 0x72, 0xCA, 0x5B, 0x1D, 0xF6, 0x0E, 0x88, 0x60, 0xFA, 0x65, - 0xF8, 0x0D, 0xC6, 0x00, 0x76, 0xD0, 0x41, 0x70, 0x87, 0xED, 0xCB, 0x77, 0xC4, 0x77, 0x32, 0xAE, - 0x66, 0x9F, 0x51, 0xB8, 0xE0, 0x76, 0x84, 0xC1, 0x10, 0xC0, 0x80, 0x9D, 0xED, 0xB0, 0x0F, 0x03, - 0xFA, 0x71, 0x8B, 0x3F, 0xFE, 0xB6, 0x23, 0x80, 0x78, 0x7D, 0x26, 0x63, 0xF5, 0xDC, 0x23, 0xD6, - 0xC6, 0x03, 0xA5, 0xDB, 0x7E, 0x96, 0x19, 0xC8, 0x8A, 0x62, 0x6E, 0xF3, 0xE9, 0x28, 0x27, 0x39, - 0x5E, 0x4A, 0x6A, 0xC7, 0xFD, 0x94, 0xCC, 0x8E, 0xA9, 0x3D, 0xCE, 0x9B, 0x90, 0x20, 0xCA, 0x0B, - 0x67, 0x93, 0x12, 0x98, 0x13, 0xAE, 0xC8, 0xDD, 0x75, 0xB3, 0x32, 0x12, 0x94, 0x0B, 0x0E, 0x0B, - 0xF9, 0x2C, 0x85, 0xBF, 0xDF, 0x5A, 0x03, 0x8A, 0xBD, 0xD2, 0xCD, 0x51, 0xD0, 0xFD, 0x34, 0x11, - 0x01, 0x60, 0x46, 0xF8, 0x6D, 0x80, 0x5B, 0x6E, 0xC9, 0xB4, 0x04, 0x25, 0x03, 0x91, 0x96, 0x03, - 0x2D, 0x19, 0xF0, 0xBA, 0x1C, 0x80, 0x5D, 0xC5, 0x3B, 0x8F, 0x81, 0x4B, 0x7E, 0xB7, 0x04, 0x60, - 0xA5, 0x25, 0x85, 0x4D, 0x3F, 0x7B, 0x2D, 0x57, 0xD1, 0x55, 0x64, 0x00, 0x03, 0xCF, 0xE1, 0xCA, - 0x24, 0x88, 0x31, 0x72, 0xCB, 0x40, 0x34, 0xAB, 0x93, 0x4E, 0x89, 0x48, 0xA5, 0x2C, 0xED, 0xCA, - 0xA5, 0x1E, 0x2E, 0x31, 0x2E, 0x07, 0xA4, 0x4B, 0xEC, 0xF3, 0x0F, 0x90, 0x96, 0x89, 0x43, 0xC9, - 0xCE, 0x45, 0xD0, 0x0E, 0x7C, 0x79, 0x54, 0x2E, 0xCA, 0x6D, 0xCA, 0x94, 0xA2, 0x11, 0x20, 0xA9, - 0xE3, 0xD0, 0x6A, 0xD2, 0xBF, 0x99, 0x37, 0x22, 0x24, 0x36, 0x03, 0x8B, 0x9C, 0x42, 0x23, 0xD9, - 0x06, 0x3B, 0xED, 0x09, 0xEC, 0xBA, 0x78, 0x3C, 0x77, 0x3F, 0x9D, 0xC6, 0x71, 0xB7, 0x8E, 0x7E, - 0xBA, 0x98, 0x1E, 0xB7, 0x86, 0x7E, 0x7A, 0x8D, 0xE3, 0xFD, 0x3A, 0xFA, 0xD9, 0x43, 0xF8, 0xD4, - 0xD1, 0xD1, 0x3E, 0x02, 0xA8, 0x8E, 0x8E, 0x0E, 0x70, 0x65, 0x75, 0x74, 0xF4, 0x1A, 0x96, 0xB6, - 0x78, 0x2F, 0x87, 0xB0, 0xAE, 0xC5, 0x7B, 0x79, 0x03, 0x8B, 0xAA, 0x01, 0x09, 0x09, 0x9B, 0x6B, - 0xE8, 0xA7, 0x83, 0x09, 0xB0, 0x6B, 0xE8, 0x07, 0xB0, 0xB9, 0x57, 0xC7, 0x7C, 0x00, 0x9B, 0x0F, - 0xEA, 0xE8, 0x07, 0xB0, 0xB9, 0x3B, 0xD1, 0xCD, 0xC5, 0x3B, 0x02, 0x6C, 0xDE, 0xAF, 0xA5, 0xA3, - 0x03, 0xE2, 0x3F, 0x75, 0xF4, 0x84, 0xE8, 0x5C, 0xCF, 0x9C, 0x0E, 0x71, 0xD7, 0x6A, 0xE9, 0xE9, - 0x0D, 0xEE, 0x5B, 0xE5, 0x9E, 0x8A, 0x03, 0xF8, 0x96, 0x64, 0x93, 0x48, 0xDA, 0x26, 0xA6, 0xA6, - 0x82, 0xE0, 0xB8, 0xA3, 0x48, 0x9E, 0xE8, 0x41, 0xF8, 0xDC, 0x12, 0x65, 0x94, 0x92, 0x4C, 0x4A, - 0x4A, 0x38, 0xB9, 0xF2, 0x47, 0xB7, 0x5E, 0xF9, 0xA3, 0x13, 0x93, 0x3F, 0xBA, 0x4B, 0x93, 0x3F, - 0x3A, 0x99, 0xF2, 0x47, 0x67, 0x23, 0x7F, 0x6C, 0xE4, 0x8F, 0x8D, 0xFC, 0xB1, 0x91, 0x3F, 0x36, - 0xF2, 0xC7, 0x46, 0xFE, 0x58, 0x17, 0xF9, 0xA3, 0xFB, 0xFC, 0x12, 0x75, 0x15, 0x1B, 0x4E, 0x4A, - 0x1A, 0xA2, 0x22, 0xE6, 0x69, 0xBC, 0x76, 0x28, 0x32, 0xF5, 0xE1, 0xBF, 0xE5, 0x26, 0x97, 0x29, - 0xF1, 0x38, 0xB0, 0x93, 0xE6, 0xA5, 0x95, 0xA4, 0x74, 0x48, 0x4F, 0x99, 0x56, 0x52, 0xD4, 0xDD, - 0x73, 0x97, 0x55, 0x6D, 0xE6, 0x34, 0xD2, 0x75, 0xA5, 0xEB, 0x96, 0x48, 0xC3, 0x8C, 0x7D, 0x40, - 0x40, 0xA6, 0x94, 0x90, 0xCB, 0xA8, 0xB5, 0x82, 0xFF, 0x22, 0xC0, 0x4E, 0x64, 0xA6, 0x24, 0x08, - 0xAC, 0x53, 0x66, 0xCA, 0xDC, 0xE5, 0xCF, 0x59, 0x37, 0x86, 0x64, 0x5D, 0x32, 0x18, 0x5F, 0x9A, - 0x22, 0x39, 0x75, 0xA1, 0x57, 0x7A, 0x2C, 0xBB, 0x75, 0x00, 0xA8, 0x5B, 0x78, 0x38, 0x90, 0xFD, - 0x04, 0x39, 0xAF, 0x83, 0xE7, 0x71, 0xB9, 0x59, 0x36, 0x2C, 0xBC, 0x6E, 0x8E, 0xEA, 0x03, 0x33, - 0x23, 0x1C, 0x8B, 0x4F, 0xCD, 0x4B, 0x73, 0xC5, 0xC1, 0xF0, 0x97, 0x22, 0xAD, 0x9A, 0xED, 0x70, - 0x55, 0x07, 0xC4, 0x09, 0x13, 0x40, 0x5A, 0x43, 0xA6, 0x30, 0x9C, 0x26, 0x73, 0x65, 0x1A, 0x23, - 0xAA, 0x1A, 0xE8, 0xB1, 0xAF, 0x26, 0xD5, 0x27, 0xF6, 0x28, 0xEF, 0xE3, 0x1D, 0x67, 0xD6, 0x1D, - 0xD5, 0xE0, 0xD3, 0xD8, 0xDD, 0x23, 0x66, 0x8D, 0x74, 0x03, 0x63, 0x3D, 0x66, 0x8E, 0xC4, 0x9E, - 0x83, 0x1E, 0x5B, 0x94, 0x47, 0x8D, 0x7A, 0x84, 0x9E, 0xF0, 0xB6, 0x88, 0xB2, 0x4E, 0xE0, 0x4D, - 0x12, 0x4D, 0x5C, 0xA4, 0x45, 0x52, 0xBE, 0xE2, 0xED, 0x95, 0x6D, 0x3B, 0xD6, 0x37, 0xA0, 0x65, - 0x0F, 0xD3, 0x12, 0x1D, 0xB4, 0xC3, 0x8C, 0x6D, 0x0F, 0x96, 0xE3, 0x8D, 0x45, 0x4E, 0x22, 0x45, - 0x0B, 0x8A, 0xEB, 0x88, 0x09, 0xE0, 0x6C, 0xF1, 0xEA, 0x7B, 0x08, 0x33, 0x0B, 0x17, 0x81, 0xA3, - 0x69, 0xCC, 0x32, 0x93, 0x99, 0xE3, 0x82, 0x44, 0x73, 0x13, 0xEE, 0x8D, 0x2D, 0x8D, 0x29, 0xEA, - 0x58, 0xE7, 0x98, 0xC7, 0xE9, 0x3F, 0x7A, 0x6D, 0x75, 0x92, 0x92, 0x86, 0x09, 0x6F, 0xEE, 0xF0, - 0xE2, 0xFD, 0x1E, 0xB8, 0x4B, 0x8B, 0x5D, 0x9A, 0x2A, 0x8C, 0xEF, 0x06, 0xF9, 0x98, 0x82, 0x24, - 0x1B, 0x9F, 0xEF, 0xD0, 0xDB, 0x5F, 0x0C, 0x7C, 0xAB, 0x4F, 0x78, 0x90, 0xF9, 0xF2, 0x46, 0xF8, - 0x00, 0x68, 0x98, 0xFC, 0xD4, 0x64, 0x58, 0xE6, 0x2E, 0x12, 0xA1, 0xAF, 0x8B, 0xBE, 0x78, 0x98, - 0x43, 0x89, 0xC6, 0xA2, 0x8B, 0x44, 0x4C, 0xEF, 0x04, 0x53, 0xD0, 0x31, 0xED, 0xD4, 0x29, 0xC7, - 0xA2, 0xA1, 0xD3, 0x97, 0x74, 0x37, 0x98, 0xB4, 0x46, 0x61, 0x04, 0x94, 0xC2, 0xAE, 0x09, 0xAF, - 0x4C, 0xC2, 0x44, 0x9B, 0x32, 0x43, 0x13, 0xD5, 0x04, 0xC2, 0x24, 0xC2, 0x54, 0x70, 0x73, 0x9A, - 0xDC, 0xA3, 0x2D, 0xF2, 0x50, 0xED, 0xB7, 0xDA, 0x93, 0xE9, 0x45, 0xDC, 0x01, 0xDD, 0xC4, 0xBD, - 0x69, 0xB7, 0xDD, 0x1D, 0xD6, 0x69, 0xD1, 0x1F, 0xF4, 0xC2, 0xB3, 0x8B, 0x3B, 0x08, 0x38, 0x80, - 0x8C, 0xFF, 0x72, 0x1B, 0x25, 0xE2, 0x07, 0x83, 0x36, 0x73, 0x06, 0x2A, 0x2C, 0xE4, 0x09, 0x96, - 0xE4, 0x0F, 0xD6, 0x14, 0x97, 0x64, 0x66, 0xC7, 0x5C, 0x17, 0xC1, 0x4E, 0x37, 0x2D, 0xE5, 0x0C, - 0x62, 0x65, 0xB9, 0xDB, 0xA5, 0x08, 0xE6, 0x62, 0xEC, 0x09, 0xDB, 0x72, 0xB7, 0x8F, 0x4A, 0x5B, - 0x21, 0x8A, 0x92, 0xF9, 0x55, 0x30, 0x27, 0x54, 0xF3, 0x5B, 0x4F, 0x01, 0x52, 0xC9, 0x61, 0xEC, - 0x8C, 0xF6, 0x8B, 0xF8, 0x78, 0x55, 0x93, 0x05, 0x57, 0x8E, 0x46, 0x7D, 0xC9, 0xCB, 0x82, 0x88, - 0xBA, 0x72, 0xB2, 0x7B, 0x35, 0x9C, 0x0B, 0x38, 0x5D, 0xA9, 0xAE, 0x89, 0x1B, 0xF6, 0xCE, 0x41, - 0xEC, 0x07, 0x3E, 0x84, 0xE7, 0x7B, 0xC8, 0x19, 0x4B, 0x35, 0xDF, 0x9A, 0x2C, 0x8A, 0xA2, 0x84, - 0x9C, 0x12, 0x4F, 0xEF, 0x0A, 0xA3, 0x3D, 0x17, 0x46, 0xD1, 0x99, 0x0D, 0x98, 0x17, 0x57, 0x93, - 0x1D, 0xAD, 0x0E, 0x69, 0x97, 0xE5, 0xAA, 0x45, 0xC2, 0xC0, 0xA2, 0xC2, 0xDA, 0x7B, 0xEC, 0x64, - 0x56, 0x52, 0x0B, 0xAD, 0x89, 0x29, 0x32, 0x5B, 0x35, 0x59, 0x4D, 0x0C, 0x70, 0x4C, 0xBF, 0x62, - 0x27, 0x9E, 0x28, 0xD5, 0x7D, 0xCC, 0xB6, 0xCE, 0xC6, 0x16, 0xA6, 0xD4, 0xC1, 0xA2, 0xA7, 0xCC, - 0x2A, 0x76, 0xDC, 0xFF, 0x20, 0xCB, 0xB6, 0x6E, 0x07, 0xB5, 0x41, 0x9F, 0x44, 0xF2, 0x8B, 0x4A, - 0x7C, 0x5E, 0x44, 0x42, 0x0B, 0xE5, 0x3C, 0x14, 0x7C, 0x40, 0xCE, 0xA3, 0x72, 0xC6, 0x42, 0x66, - 0xE3, 0x20, 0x71, 0x80, 0x34, 0x22, 0xD7, 0x19, 0xAE, 0x83, 0x45, 0xCA, 0xC2, 0xA2, 0x94, 0x24, - 0x42, 0x27, 0x31, 0x17, 0x65, 0xDC, 0xED, 0x49, 0x08, 0x3E, 0x93, 0x09, 0xD7, 0x74, 0x21, 0xE1, - 0xDD, 0xF1, 0x91, 0x1E, 0xE4, 0xBA, 0xA4, 0xB0, 0xC9, 0x9B, 0xDB, 0xB3, 0xEB, 0x59, 0xD7, 0xC5, - 0x13, 0x29, 0x35, 0x86, 0x62, 0x99, 0xEE, 0x0A, 0x99, 0x2F, 0x14, 0x41, 0x49, 0x14, 0xEA, 0xF7, - 0xFB, 0x6C, 0xCB, 0x16, 0x95, 0xC5, 0x5D, 0x0E, 0x02, 0xAA, 0xEF, 0x30, 0xCF, 0xF7, 0x2C, 0x50, - 0xC1, 0x8C, 0x6D, 0xAA, 0x86, 0x88, 0x6F, 0x25, 0x44, 0x23, 0xA6, 0x8C, 0xA0, 0x0B, 0x74, 0x9D, - 0x84, 0x79, 0x92, 0xFB, 0x95, 0x1A, 0x4A, 0xBE, 0x11, 0xB1, 0x29, 0x28, 0x57, 0xFD, 0xCA, 0x9D, - 0xC2, 0x0D, 0xF3, 0xFD, 0x5A, 0xBE, 0xA1, 0x71, 0x67, 0x07, 0xF4, 0x2E, 0xC3, 0x02, 0xDC, 0xB2, - 0x9E, 0x9F, 0xC4, 0x44, 0xA0, 0xAD, 0x21, 0x46, 0xB3, 0x4C, 0xE0, 0x7C, 0x06, 0x25, 0xD3, 0x14, - 0x84, 0x4E, 0x18, 0xE0, 0x11, 0xD2, 0x9D, 0xA8, 0x30, 0x2C, 0xAB, 0x0E, 0xC9, 0xAD, 0x8F, 0xD1, - 0x76, 0xBB, 0xB4, 0x93, 0xFC, 0x94, 0xF6, 0xE7, 0xF0, 0x9B, 0x26, 0x66, 0x90, 0x37, 0x47, 0xAA, - 0x76, 0xCC, 0xA6, 0x5F, 0x84, 0x91, 0xFA, 0xB9, 0xD7, 0x53, 0xA5, 0x9C, 0xBF, 0x83, 0x1A, 0xC4, - 0x05, 0x1B, 0xB4, 0x44, 0xA9, 0x22, 0xD2, 0x78, 0x0A, 0xBA, 0xBD, 0x50, 0x1A, 0x10, 0x81, 0x22, - 0x87, 0x33, 0x22, 0x41, 0xC9, 0xEB, 0xBB, 0x2C, 0x27, 0x2A, 0xDF, 0x25, 0xD0, 0x46, 0x60, 0x5A, - 0xAA, 0x14, 0x4E, 0x79, 0xC3, 0x64, 0xE8, 0x58, 0x35, 0x3B, 0x12, 0x3A, 0x55, 0x5D, 0x61, 0x8C, - 0x37, 0x6D, 0xEB, 0x7B, 0xF4, 0xD3, 0xFE, 0xFD, 0xE2, 0xBC, 0x9C, 0x37, 0xD5, 0xF2, 0x4D, 0xA9, - 0x7D, 0x5F, 0xE6, 0x34, 0x96, 0xF9, 0xEA, 0xC4, 0x2C, 0x23, 0x1C, 0x18, 0x2D, 0xAC, 0x16, 0xBD, - 0x21, 0xB8, 0xE6, 0xAF, 0xBB, 0xBF, 0xED, 0xFE, 0x8E, 0x50, 0xE2, 0x6E, 0xEB, 0xE5, 0xDA, 0x58, - 0x57, 0x43, 0x01, 0xB1, 0x7C, 0xFE, 0xBD, 0x39, 0xEE, 0x83, 0x69, 0x4B, 0x2E, 0x44, 0xE1, 0xF3, - 0x2C, 0xAA, 0x8A, 0x92, 0xD1, 0xAF, 0x15, 0x64, 0xDD, 0x0A, 0xD7, 0xDC, 0x69, 0x5A, 0xDB, 0xE1, - 0x52, 0x04, 0xE1, 0xC8, 0x82, 0x2B, 0xC9, 0xBD, 0xD3, 0x76, 0x2F, 0x42, 0x37, 0x5B, 0x0A, 0x0E, - 0xFD, 0x56, 0x0E, 0x87, 0x7E, 0x7B, 0x31, 0x38, 0xF4, 0xDB, 0x9C, 0x38, 0xF4, 0xDB, 0x06, 0x87, - 0xB2, 0x70, 0xE8, 0xF7, 0x72, 0x38, 0xF4, 0xFB, 0x8B, 0xC1, 0xA1, 0xDF, 0xE7, 0xC4, 0xA1, 0xDF, - 0x37, 0x38, 0x94, 0xC0, 0x21, 0x13, 0xE4, 0x27, 0x94, 0xCE, 0x85, 0x9C, 0x5E, 0x06, 0x8B, 0xCA, - 0xD5, 0xBB, 0x7C, 0x52, 0x44, 0x2A, 0x0A, 0x32, 0x8D, 0xAE, 0xB9, 0x12, 0x22, 0x45, 0x5B, 0xBE, - 0x1C, 0x73, 0xE3, 0xF1, 0x59, 0x10, 0xFE, 0xF4, 0x05, 0x6F, 0x5C, 0x22, 0x52, 0xF4, 0x93, 0xD7, - 0x1E, 0xA2, 0xFA, 0x16, 0x68, 0x24, 0x18, 0xC6, 0xA4, 0x63, 0x69, 0xD5, 0xA0, 0xDC, 0xC6, 0x20, - 0x27, 0xFF, 0xE9, 0xC3, 0xBE, 0xC0, 0xF4, 0x55, 0xCB, 0x7E, 0xDC, 0xB5, 0x31, 0xD4, 0x52, 0x1A, - 0x40, 0x66, 0x24, 0xEA, 0xE7, 0x2D, 0x47, 0x97, 0xAF, 0xDF, 0xB3, 0x5C, 0xEE, 0x53, 0x45, 0x7D, - 0x4A, 0x92, 0x0D, 0x85, 0xEC, 0x65, 0x54, 0x38, 0x06, 0xE6, 0x22, 0xDF, 0x3C, 0x12, 0x3B, 0x25, - 0x41, 0x53, 0xCE, 0x45, 0x54, 0x8C, 0x19, 0x75, 0xA8, 0x1C, 0x08, 0x13, 0x50, 0x04, 0xA1, 0x05, - 0x9B, 0xC3, 0x39, 0x65, 0x7D, 0xE7, 0xEA, 0xDF, 0xC9, 0x3D, 0xAF, 0x34, 0x6E, 0x84, 0x01, 0x48, - 0xDF, 0x9A, 0x0F, 0xBA, 0xE6, 0x8D, 0x8F, 0x7A, 0xFB, 0xED, 0x72, 0xE1, 0x47, 0x59, 0x6E, 0x42, - 0xA8, 0xB9, 0x0A, 0xF3, 0xD4, 0x09, 0x6B, 0x76, 0xBA, 0x87, 0xED, 0x6E, 0xFB, 0xA0, 0xB5, 0x7F, - 0x70, 0xC8, 0x9A, 0x7B, 0xAF, 0x3B, 0x07, 0x87, 0xED, 0xBD, 0xD6, 0x5E, 0xBB, 0xC7, 0xF6, 0xDA, - 0x87, 0x07, 0x07, 0x07, 0xFB, 0xAD, 0xBD, 0xC3, 0xBD, 0x3A, 0xDC, 0x2C, 0x83, 0x21, 0x4F, 0x57, - 0x34, 0x64, 0x8F, 0x86, 0x3C, 0x5B, 0xD1, 0x68, 0x7B, 0x8D, 0xE3, 0x13, 0x3C, 0xB8, 0x6E, 0xC7, - 0x8A, 0x77, 0xE9, 0xDE, 0x5A, 0xD6, 0x95, 0x65, 0x8E, 0x6E, 0xAD, 0x53, 0x7E, 0x2E, 0x30, 0x10, - 0xF8, 0x48, 0xE6, 0x44, 0x2A, 0xD5, 0xF8, 0x9A, 0x7B, 0xD2, 0xE5, 0xBD, 0xBC, 0xD6, 0x4D, 0x06, - 0x99, 0xB9, 0x5F, 0xAA, 0xD1, 0x84, 0xA4, 0x68, 0x5A, 0x5C, 0x32, 0xA9, 0xD7, 0x6E, 0x24, 0xBB, - 0x47, 0x63, 0xD1, 0x89, 0xA6, 0x55, 0xB4, 0x0E, 0xE5, 0x04, 0x0F, 0x2A, 0x4B, 0x9D, 0x75, 0xD0, - 0x7F, 0x60, 0xE3, 0xAA, 0x6B, 0xDE, 0x1A, 0x20, 0xA0, 0xC7, 0x97, 0x39, 0xF3, 0xE9, 0x08, 0x38, - 0xF7, 0x73, 0xFA, 0x6B, 0x5D, 0x6C, 0x72, 0x80, 0x00, 0x20, 0x4B, 0xEC, 0x88, 0x42, 0xAA, 0x8A, - 0x46, 0xB9, 0x1D, 0x76, 0xC8, 0x04, 0x17, 0x56, 0xB2, 0x76, 0xB8, 0x0A, 0xA7, 0x45, 0x44, 0x92, - 0xA0, 0xB7, 0xC5, 0xA2, 0x98, 0xEE, 0xB5, 0x7E, 0x3C, 0xEF, 0xC7, 0x2A, 0xC9, 0x4F, 0xEA, 0xBF, - 0x5C, 0xF8, 0x80, 0x85, 0x0A, 0x72, 0xEE, 0x16, 0x3A, 0x4F, 0x7F, 0xB7, 0xF0, 0x81, 0xAA, 0x19, - 0xC8, 0x3B, 0xB6, 0x7A, 0xAF, 0x14, 0x46, 0xB2, 0xD7, 0x27, 0x73, 0x79, 0x79, 0xB2, 0x5B, 0x85, - 0x0F, 0xE1, 0xCA, 0xA7, 0x37, 0x0B, 0xA5, 0x29, 0xAF, 0x0C, 0x67, 0x8B, 0xDD, 0x2C, 0xA4, 0x8C, - 0x16, 0xDE, 0x2E, 0x5C, 0x5D, 0x8D, 0x4B, 0x0F, 0xBC, 0xF6, 0x97, 0x10, 0xB0, 0x98, 0xE4, 0xBD, - 0x03, 0x3E, 0xDA, 0xDC, 0x3A, 0xD4, 0xE1, 0xCD, 0x43, 0xF0, 0xBC, 0x52, 0xBC, 0xE2, 0x94, 0x25, - 0x99, 0xEE, 0x3B, 0x7B, 0x89, 0xAC, 0x72, 0x7B, 0x33, 0xA4, 0x05, 0xFD, 0xEB, 0x9E, 0xAF, 0xF1, - 0x1A, 0xFC, 0xBF, 0x0E, 0x96, 0x60, 0x78, 0x89, 0xC1, 0xA0, 0xBA, 0x05, 0x4F, 0xB6, 0x7C, 0x69, - 0x7E, 0x5E, 0x62, 0x6D, 0xA8, 0x8F, 0x2C, 0x15, 0x35, 0x60, 0x80, 0xF5, 0xC7, 0x8D, 0x00, 0x0A, - 0x73, 0x20, 0x87, 0x6C, 0xFA, 0x62, 0x2C, 0xBC, 0x42, 0x22, 0xF7, 0x48, 0xF2, 0x7C, 0x8F, 0x95, - 0x5B, 0xBD, 0x54, 0xFB, 0x6C, 0x35, 0x9B, 0x6F, 0x56, 0xFA, 0x38, 0x90, 0xC5, 0xC5, 0x48, 0x4C, - 0x0C, 0x75, 0x54, 0x31, 0x8C, 0x35, 0xB0, 0xF4, 0xC4, 0x27, 0x9C, 0x6F, 0xEB, 0x79, 0xAE, 0xF7, - 0xC7, 0x95, 0x1B, 0xA7, 0x12, 0xFC, 0x89, 0x21, 0x58, 0x75, 0xA3, 0x98, 0x98, 0x67, 0x73, 0x40, - 0x7E, 0x3C, 0xB9, 0x28, 0x7D, 0x1A, 0x5F, 0x2B, 0xCE, 0xD7, 0x5D, 0x18, 0x0D, 0x7D, 0x2E, 0xE7, - 0x3B, 0xC2, 0xEB, 0x91, 0x3A, 0x22, 0x92, 0xC7, 0x47, 0x8E, 0x4D, 0xD9, 0xC9, 0x9D, 0x75, 0xCF, - 0xD9, 0x85, 0x61, 0xE8, 0xB6, 0x6B, 0xE9, 0x5A, 0x58, 0x24, 0x1E, 0x26, 0x1C, 0xD4, 0x92, 0x97, - 0x02, 0x4A, 0x28, 0x79, 0xA1, 0xBE, 0xA5, 0x48, 0xC8, 0x45, 0xDF, 0xC7, 0xE7, 0x13, 0xCB, 0xF4, - 0xA9, 0x28, 0xB2, 0x0C, 0x19, 0xC0, 0x2D, 0x32, 0xB5, 0x2A, 0x82, 0xCB, 0xD2, 0x85, 0x97, 0x2A, - 0x02, 0x4C, 0x69, 0x93, 0x6F, 0x21, 0xBB, 0xDE, 0xAB, 0x22, 0xBB, 0x55, 0xBF, 0x90, 0x0B, 0x31, - 0xB9, 0xEC, 0x9A, 0xCA, 0xDD, 0x08, 0x95, 0x7C, 0xCD, 0x9E, 0x9D, 0x48, 0x0D, 0xC9, 0x3E, 0x97, - 0xC8, 0x49, 0x08, 0xBF, 0xD2, 0x79, 0x22, 0x93, 0x59, 0xAC, 0x0C, 0x3E, 0xF4, 0x8E, 0xF6, 0x2A, - 0x58, 0x91, 0xD3, 0xF4, 0x66, 0xA1, 0x17, 0x23, 0x71, 0x08, 0xE7, 0xDC, 0x88, 0x33, 0x6D, 0xC4, - 0xFE, 0x85, 0xE5, 0xD5, 0x81, 0x9B, 0xA0, 0x42, 0x53, 0x85, 0x8F, 0x51, 0x20, 0x98, 0x62, 0xA8, - 0xD0, 0x14, 0xF9, 0x0B, 0xA6, 0xBB, 0x16, 0x15, 0x25, 0x39, 0x83, 0x47, 0xC4, 0x73, 0xE6, 0x38, - 0x41, 0x96, 0xA1, 0xE5, 0x5C, 0x0E, 0x83, 0x92, 0x96, 0x3B, 0xE1, 0xD4, 0x44, 0xDD, 0x50, 0x39, - 0x61, 0x8A, 0x7D, 0xFA, 0x67, 0xD7, 0xBF, 0xF3, 0x1C, 0x85, 0x6A, 0x72, 0xFE, 0xB3, 0xA8, 0x26, - 0x2F, 0x3D, 0x66, 0x4F, 0xE0, 0xB7, 0x69, 0x2A, 0x4C, 0xF2, 0x2C, 0x0C, 0xBB, 0x39, 0xB9, 0xE9, - 0x4F, 0x33, 0x7F, 0x86, 0xDC, 0x28, 0xCC, 0xB6, 0x07, 0xDD, 0x51, 0x39, 0x1B, 0xAC, 0x45, 0x1D, - 0xB8, 0xCD, 0x4E, 0xF9, 0xD9, 0x18, 0x7A, 0x78, 0x64, 0x0F, 0x63, 0x6E, 0xCA, 0x98, 0x26, 0x51, - 0x05, 0x94, 0x98, 0x18, 0xF9, 0xB6, 0x2A, 0xF2, 0xEE, 0xCA, 0xB6, 0x80, 0xDF, 0x8C, 0x63, 0xA3, - 0xEE, 0x50, 0x7C, 0x91, 0x6F, 0x8A, 0x17, 0xA8, 0x49, 0x58, 0x0C, 0xBB, 0xC5, 0x3E, 0x59, 0x1E, - 0x3F, 0xA2, 0x38, 0xAD, 0x70, 0x9D, 0xB4, 0xE5, 0x14, 0x6F, 0x64, 0x3C, 0x28, 0x8F, 0xAE, 0x34, - 0x60, 0xC9, 0x7A, 0xA5, 0x63, 0x8C, 0x34, 0xCC, 0xB8, 0xF8, 0x63, 0x54, 0x93, 0xFE, 0x19, 0x2A, - 0x7D, 0x65, 0x52, 0x97, 0x96, 0x8B, 0xE7, 0x7D, 0xB6, 0x04, 0xDE, 0xCD, 0x20, 0x70, 0x56, 0x2A, - 0xA7, 0x6E, 0x3A, 0xA1, 0x1B, 0xD0, 0xC5, 0x49, 0xFF, 0x2C, 0x49, 0xE7, 0xF0, 0x68, 0x4D, 0xC9, - 0x1C, 0x66, 0x96, 0x42, 0xE5, 0x8A, 0xA6, 0x95, 0x25, 0x70, 0x49, 0x21, 0x65, 0xC9, 0x7B, 0x43, - 0x7C, 0x55, 0x88, 0x6F, 0x85, 0x8A, 0xB5, 0x44, 0xDC, 0x62, 0x29, 0x7B, 0x3F, 0x4D, 0xCA, 0x46, - 0x3C, 0x2A, 0x2D, 0x38, 0x2F, 0x0F, 0xBB, 0xF3, 0x05, 0xE6, 0x00, 0x83, 0xFB, 0x63, 0x8A, 0x1E, - 0x27, 0xC4, 0x8E, 0x0B, 0xD0, 0xAE, 0x3F, 0x09, 0x5E, 0x56, 0xE4, 0xCB, 0xE2, 0x64, 0xD9, 0x61, - 0x36, 0x35, 0x52, 0xA9, 0x91, 0xC8, 0xEE, 0x4A, 0xE7, 0x8A, 0xF8, 0x9A, 0xF0, 0x1A, 0xDD, 0x2C, - 0x1C, 0xC6, 0x35, 0x9D, 0xD0, 0x72, 0x87, 0xB9, 0x63, 0x3C, 0x7D, 0x30, 0xF3, 0x03, 0x22, 0x19, - 0xEA, 0x79, 0x14, 0x80, 0x02, 0x98, 0xFC, 0x32, 0x5D, 0x2A, 0x72, 0x65, 0xEB, 0xFD, 0xE5, 0x39, - 0xBA, 0x05, 0x98, 0x1B, 0xA4, 0x02, 0xAE, 0x6E, 0x13, 0x11, 0x3D, 0xAC, 0xCC, 0x22, 0x42, 0xD7, - 0x1A, 0xAB, 0x21, 0xED, 0xC0, 0xA3, 0x24, 0xB0, 0xCD, 0x37, 0xE6, 0x31, 0x89, 0x91, 0x27, 0xDB, - 0x13, 0x53, 0xF6, 0x07, 0x38, 0x3E, 0x44, 0xA8, 0x15, 0x05, 0x8B, 0x83, 0xF4, 0x17, 0x2C, 0x8D, - 0xDD, 0xF1, 0x21, 0x66, 0x96, 0x16, 0x67, 0x16, 0xC6, 0x72, 0xC9, 0x73, 0x23, 0x4C, 0x56, 0x4D, - 0xEE, 0x4F, 0x51, 0x17, 0x27, 0x74, 0x95, 0xFA, 0x01, 0x69, 0xF0, 0x60, 0x89, 0x3E, 0x82, 0x21, - 0x82, 0xCD, 0xE5, 0x27, 0x18, 0xB4, 0xDE, 0xF8, 0x0A, 0x2E, 0x9D, 0x90, 0xEA, 0xF7, 0x15, 0xBC, - 0x52, 0xBC, 0x5D, 0xB4, 0x2A, 0xA3, 0xF1, 0x6C, 0xE3, 0x32, 0xF8, 0x44, 0x2E, 0x83, 0x01, 0x05, - 0x95, 0x74, 0x1B, 0x2C, 0xBD, 0x3D, 0xD1, 0xCD, 0xAD, 0xDD, 0xCB, 0x70, 0x7A, 0x2A, 0xA5, 0x7B, - 0x1A, 0x4E, 0xBF, 0x5F, 0x33, 0x6F, 0xC3, 0xBD, 0x76, 0xAB, 0xFD, 0xA6, 0xDD, 0x7D, 0xB3, 0xF7, - 0xFA, 0x0D, 0x6B, 0x76, 0xDA, 0xFB, 0xAD, 0xCE, 0xE1, 0x7E, 0x7B, 0xFF, 0xF5, 0x41, 0x87, 0x75, - 0xF6, 0x0F, 0xE0, 0xBB, 0xC3, 0x37, 0xF5, 0xBA, 0x1A, 0xAE, 0x60, 0xBC, 0xC0, 0xCF, 0x70, 0x05, - 0x43, 0x95, 0x70, 0x32, 0xCC, 0x9C, 0x45, 0x25, 0x1B, 0xF5, 0x7C, 0x33, 0xDE, 0x78, 0x18, 0x66, - 0x78, 0x18, 0xCE, 0x0A, 0x91, 0xB5, 0x7B, 0x19, 0x06, 0x43, 0x2C, 0xC1, 0xD3, 0x70, 0xD9, 0xB3, - 0x8F, 0x8E, 0xB1, 0x1C, 0x8F, 0xC3, 0x65, 0xAF, 0x20, 0x3E, 0xCA, 0xB3, 0xF7, 0x3C, 0x8C, 0x1E, - 0x5D, 0x3F, 0x8C, 0x03, 0xE2, 0xF3, 0xAC, 0xBA, 0x8E, 0x85, 0xEF, 0xB1, 0xEA, 0x6A, 0xAC, 0xEA, - 0xBA, 0x78, 0xB8, 0xB2, 0xAA, 0xEB, 0xC1, 0x1C, 0x9E, 0xA6, 0xEA, 0xBA, 0x4B, 0xA3, 0xA3, 0xE0, - 0xED, 0xDB, 0x84, 0xDC, 0x41, 0x96, 0x92, 0x57, 0xEE, 0x4C, 0xF9, 0x75, 0xCA, 0x99, 0x36, 0x53, - 0x7C, 0xFD, 0x33, 0xA5, 0x2B, 0x11, 0xD5, 0xD7, 0x85, 0x34, 0xEF, 0xE1, 0xE5, 0x89, 0xA2, 0x62, - 0xF2, 0x0F, 0xA9, 0x10, 0xC7, 0xFB, 0xF1, 0x45, 0x4E, 0x10, 0x33, 0x56, 0xF8, 0xFD, 0xE5, 0x54, - 0x64, 0x17, 0x1B, 0x3A, 0x6F, 0x32, 0x89, 0xB7, 0x25, 0x2A, 0xC5, 0xA4, 0xE6, 0xE7, 0x2C, 0x59, - 0x34, 0x2D, 0xCE, 0xE5, 0x0B, 0x39, 0x40, 0xA9, 0xC2, 0x69, 0x33, 0xCB, 0x6E, 0x67, 0xA4, 0xEA, - 0x2C, 0x1C, 0x2E, 0x91, 0xCA, 0x33, 0xA5, 0xE3, 0x62, 0xA6, 0x15, 0xA5, 0x62, 0xD6, 0xC1, 0xFC, - 0x9C, 0x35, 0x54, 0x4A, 0x13, 0x28, 0x50, 0x58, 0x2D, 0xAD, 0x82, 0xBB, 0x75, 0x3C, 0x6B, 0x67, - 0xE5, 0x95, 0xD6, 0x5F, 0xDC, 0xAA, 0x76, 0x3F, 0x9A, 0xE8, 0x9A, 0xC2, 0xAA, 0xF6, 0x7F, 0xB4, - 0xAB, 0xBB, 0x02, 0xD7, 0x5F, 0x10, 0x3C, 0xF8, 0x87, 0x33, 0x3A, 0x5A, 0xD4, 0x8B, 0xE3, 0xB0, - 0x92, 0x95, 0xAB, 0xB2, 0xA5, 0x2B, 0x03, 0x8A, 0x15, 0x46, 0xB3, 0xF3, 0x3A, 0x5A, 0xD4, 0xF6, - 0x55, 0xDD, 0x67, 0xE4, 0x89, 0xB1, 0xB0, 0x6F, 0x39, 0x6B, 0x86, 0x85, 0x38, 0xA3, 0xA7, 0xC6, - 0xC2, 0xC2, 0x3B, 0x8F, 0x2C, 0x38, 0x2E, 0x8E, 0x87, 0xA2, 0xA3, 0x1F, 0x0E, 0x0F, 0xB1, 0xE4, - 0xFA, 0x7A, 0xE1, 0x21, 0xCE, 0xE8, 0xB9, 0x71, 0x43, 0x09, 0xC5, 0xC5, 0xB1, 0x50, 0x74, 0xF4, - 0x43, 0x62, 0x61, 0xFF, 0x97, 0x9A, 0xF0, 0x30, 0xAB, 0x26, 0xFA, 0x1C, 0x78, 0x58, 0xBA, 0xF6, - 0x79, 0x0E, 0x2A, 0xBE, 0xAE, 0x74, 0x05, 0x5C, 0x0B, 0x2A, 0x12, 0x28, 0xEB, 0x41, 0x46, 0xEC, - 0xEA, 0x07, 0x42, 0xC7, 0x69, 0x39, 0xF8, 0x25, 0x33, 0x45, 0x1A, 0xA8, 0xC2, 0xD9, 0x0C, 0x33, - 0x7A, 0x3E, 0x4C, 0x31, 0x06, 0xC5, 0x45, 0xF0, 0x30, 0xDA, 0xD1, 0x0F, 0x89, 0x85, 0x4B, 0x67, - 0x8A, 0x73, 0xE0, 0xE1, 0xB3, 0x62, 0x8A, 0x09, 0x50, 0xD6, 0x83, 0x8C, 0x4F, 0xC3, 0x14, 0x17, - 0x78, 0xA5, 0x8C, 0x49, 0xE0, 0xD9, 0xDB, 0x7B, 0x3A, 0xCB, 0xB2, 0xF7, 0x74, 0xAA, 0xDA, 0x7B, - 0xBA, 0xCF, 0xD5, 0xDE, 0xD3, 0x79, 0xA9, 0xF6, 0x9E, 0xCE, 0xC6, 0xDE, 0x53, 0x83, 0xBD, 0xA7, - 0x53, 0x97, 0xBD, 0xA7, 0xF3, 0x63, 0xDA, 0x7B, 0x3A, 0x1B, 0x7B, 0x4F, 0x2D, 0xF6, 0x9E, 0x4E, - 0x5D, 0xF6, 0x9E, 0xCE, 0x8F, 0x69, 0xEF, 0xE9, 0x6C, 0xEC, 0x3D, 0x35, 0xD8, 0x7B, 0x3A, 0x75, - 0xD9, 0x7B, 0x3A, 0x3F, 0xAA, 0xBD, 0xA7, 0xB3, 0xB1, 0xF7, 0xD4, 0x65, 0xEF, 0xE9, 0xD4, 0x67, - 0xEF, 0xE9, 0xFC, 0x98, 0xF6, 0x9E, 0xCE, 0xC6, 0xDE, 0x53, 0x83, 0xBD, 0xA7, 0x53, 0x97, 0xBD, - 0xA7, 0xF3, 0xA3, 0xDA, 0x7B, 0x3A, 0x1B, 0x7B, 0x4F, 0x5D, 0xF6, 0x9E, 0x4E, 0x7D, 0xF6, 0x9E, - 0xCE, 0xC6, 0xDE, 0xB3, 0x6E, 0xF6, 0x9E, 0xEE, 0xB2, 0xEC, 0x3D, 0xDD, 0xAA, 0xF6, 0x9E, 0xDE, - 0x73, 0xB5, 0xF7, 0x74, 0x5F, 0xAA, 0xBD, 0xA7, 0xBB, 0xB1, 0xF7, 0xD4, 0x60, 0xEF, 0xE9, 0xD6, - 0x65, 0xEF, 0xE9, 0xFE, 0x98, 0xF6, 0x9E, 0xEE, 0xC6, 0xDE, 0x53, 0x8B, 0xBD, 0xA7, 0x5B, 0x97, - 0xBD, 0xA7, 0xFB, 0x63, 0xDA, 0x7B, 0xBA, 0x1B, 0x7B, 0x4F, 0x0D, 0xF6, 0x9E, 0x6E, 0x5D, 0xF6, - 0x9E, 0xEE, 0x8F, 0x6A, 0xEF, 0xE9, 0x6E, 0xEC, 0x3D, 0x75, 0xD9, 0x7B, 0xBA, 0xF5, 0xD9, 0x7B, - 0xBA, 0x3F, 0xA6, 0xBD, 0xA7, 0xBB, 0xB1, 0xF7, 0xD4, 0x60, 0xEF, 0xE9, 0xD6, 0x65, 0xEF, 0xE9, - 0xFE, 0xA8, 0xF6, 0x9E, 0xEE, 0xC6, 0xDE, 0x53, 0x97, 0xBD, 0xA7, 0x5B, 0x9F, 0xBD, 0xA7, 0xBB, - 0xB1, 0xF7, 0xAC, 0x9B, 0xBD, 0xA7, 0xB7, 0x2C, 0x7B, 0x4F, 0xAF, 0xAA, 0xBD, 0x67, 0xEF, 0xB9, - 0xDA, 0x7B, 0x7A, 0x2F, 0xD5, 0xDE, 0xD3, 0xDB, 0xD8, 0x7B, 0x6A, 0xB0, 0xF7, 0xF4, 0xEA, 0xB2, - 0xF7, 0xF4, 0x7E, 0x4C, 0x7B, 0x4F, 0x6F, 0x63, 0xEF, 0xA9, 0xC5, 0xDE, 0xD3, 0xAB, 0xCB, 0xDE, - 0xD3, 0xFB, 0x31, 0xED, 0x3D, 0xBD, 0x8D, 0xBD, 0xA7, 0x06, 0x7B, 0x4F, 0xAF, 0x2E, 0x7B, 0x4F, - 0xEF, 0x47, 0xB5, 0xF7, 0xF4, 0x36, 0xF6, 0x9E, 0xBA, 0xEC, 0x3D, 0xBD, 0xFA, 0xEC, 0x3D, 0xBD, - 0x1F, 0xD3, 0xDE, 0xD3, 0xDB, 0xD8, 0x7B, 0x6A, 0xB0, 0xF7, 0xF4, 0xEA, 0xB2, 0xF7, 0xF4, 0x7E, - 0x54, 0x7B, 0x4F, 0x6F, 0x63, 0xEF, 0xA9, 0xCB, 0xDE, 0xD3, 0xAB, 0xCF, 0xDE, 0xD3, 0x7B, 0x31, - 0xF6, 0x9E, 0xA2, 0x1C, 0x41, 0x39, 0xBD, 0x4A, 0x1B, 0x50, 0x98, 0x13, 0x6D, 0xC4, 0xBD, 0x6B, - 0xEE, 0xBA, 0xCA, 0x88, 0x5F, 0xE9, 0xAE, 0x87, 0x75, 0x2B, 0xA9, 0x42, 0xC0, 0x5C, 0x26, 0xA2, - 0xFC, 0xB4, 0x50, 0xB1, 0xA4, 0x6F, 0xA5, 0xCC, 0x43, 0xC1, 0x73, 0x4C, 0xB1, 0x2F, 0x8C, 0x1B, - 0xD7, 0xEE, 0x08, 0xA7, 0x98, 0x3F, 0x52, 0xAA, 0x05, 0x29, 0x69, 0x21, 0xCA, 0xEE, 0x3B, 0x7F, - 0xD7, 0x6E, 0x6E, 0xCF, 0xAE, 0xD9, 0x0D, 0x25, 0x87, 0x7D, 0xAB, 0x13, 0xBA, 0x61, 0x12, 0x2B, - 0x68, 0x7B, 0x86, 0x16, 0xA1, 0x46, 0x1D, 0x26, 0xA3, 0x12, 0xE6, 0xA2, 0xD2, 0x99, 0xBA, 0x68, - 0x86, 0x8E, 0xA7, 0x4E, 0x70, 0xCA, 0x97, 0xE6, 0xD0, 0x2A, 0xAE, 0x2D, 0x27, 0xF3, 0x77, 0xD1, - 0x42, 0x31, 0x6D, 0xBC, 0xA3, 0x98, 0xEE, 0x44, 0xF7, 0x22, 0x25, 0x0F, 0x70, 0xC5, 0x4C, 0xC1, - 0x1C, 0xD5, 0x9A, 0x48, 0xA5, 0x85, 0xA9, 0x76, 0x3B, 0x1F, 0xBF, 0x53, 0x2E, 0xF8, 0x89, 0xC0, - 0x26, 0x97, 0x75, 0xDA, 0xED, 0xFD, 0x1D, 0xF8, 0xF9, 0x7A, 0x0F, 0x7F, 0x1E, 0xD2, 0xCF, 0x37, - 0xF8, 0xB3, 0xD3, 0xDD, 0x13, 0x09, 0xE6, 0xDB, 0xAD, 0xA0, 0x51, 0xA7, 0xDB, 0x6B, 0xCB, 0x4C, - 0xF5, 0x32, 0x4D, 0xAF, 0x61, 0x3D, 0x50, 0x55, 0x06, 0xFC, 0x96, 0xEA, 0x5C, 0xB8, 0xA2, 0x2A, - 0x0A, 0x3C, 0x87, 0xF1, 0x4D, 0x8D, 0x92, 0x9E, 0x62, 0xD2, 0x3B, 0x4F, 0xD1, 0x0D, 0xCB, 0x91, - 0xD5, 0x14, 0xE4, 0x5C, 0xA1, 0xF7, 0xC7, 0x5D, 0xC5, 0x30, 0xC4, 0x6E, 0x05, 0x33, 0x6A, 0xB1, - 0x2B, 0x1D, 0xBE, 0x74, 0x8F, 0x58, 0x1B, 0x5F, 0xEE, 0xB6, 0xA3, 0xD5, 0x1A, 0x44, 0x0D, 0x16, - 0x82, 0x1D, 0x8C, 0xE7, 0x51, 0xBD, 0x06, 0x0B, 0x38, 0x88, 0xA3, 0x6B, 0x1A, 0x37, 0xF1, 0x7D, - 0x9C, 0x2B, 0x95, 0x6B, 0xD1, 0x4D, 0x86, 0x88, 0xC2, 0x26, 0x96, 0xC6, 0x9F, 0x57, 0xEA, 0xB0, - 0x54, 0x0B, 0xE2, 0x3C, 0x94, 0x50, 0xBF, 0x11, 0x91, 0x7A, 0x8C, 0x37, 0xBD, 0xB3, 0x80, 0x0A, - 0x26, 0x41, 0xEB, 0x42, 0x8E, 0x9B, 0x9A, 0x5C, 0x32, 0x3D, 0x91, 0x64, 0xA4, 0x30, 0x8A, 0xC3, - 0x5D, 0xEE, 0xDD, 0x5A, 0x88, 0x28, 0x32, 0x2F, 0x1C, 0x15, 0x75, 0xBD, 0xC1, 0xC7, 0xB0, 0xEB, - 0xA5, 0xCE, 0x84, 0xA0, 0x61, 0xB9, 0x3C, 0x92, 0x65, 0xEB, 0xCE, 0x3C, 0x2D, 0x30, 0xAE, 0xAC, - 0x87, 0xD3, 0x80, 0xCC, 0x42, 0x80, 0x94, 0x82, 0x06, 0x66, 0xA6, 0x04, 0x22, 0x0D, 0x5B, 0x03, - 0xD5, 0x99, 0x5F, 0x2B, 0x81, 0xA6, 0x18, 0x36, 0x88, 0xB7, 0x93, 0xF8, 0xB1, 0xD5, 0x58, 0x76, - 0xFA, 0xC8, 0x12, 0x8F, 0xD3, 0x06, 0x79, 0xFB, 0x97, 0x66, 0x93, 0x35, 0x83, 0x7F, 0x81, 0x38, - 0xC6, 0x9D, 0x21, 0x26, 0x8E, 0x16, 0xF4, 0x16, 0xF9, 0xBA, 0xD9, 0x4C, 0xF4, 0x18, 0x21, 0x34, - 0x0D, 0x64, 0x55, 0x5D, 0x63, 0x23, 0xC5, 0x4E, 0xAD, 0xE7, 0x9C, 0x71, 0xBD, 0x93, 0x79, 0x9F, - 0x83, 0x30, 0xB4, 0xED, 0x20, 0x7D, 0x60, 0x99, 0xE3, 0xF9, 0xA7, 0xEC, 0x8B, 0x9E, 0xE4, 0x91, - 0xDD, 0xEF, 0x07, 0x1D, 0x57, 0x3A, 0x8D, 0xC3, 0x66, 0xA9, 0x43, 0xC5, 0xB3, 0x7E, 0x67, 0x6C, - 0xB8, 0x90, 0xF6, 0x62, 0xF0, 0xF5, 0x1D, 0x51, 0x9A, 0x44, 0x1E, 0xD8, 0x76, 0xE4, 0x8D, 0xC5, - 0x4F, 0xED, 0x74, 0xCC, 0x4E, 0x43, 0x8E, 0x42, 0x0E, 0x1C, 0xAE, 0x3E, 0x65, 0x94, 0x6C, 0x86, - 0x3B, 0x97, 0x1C, 0x78, 0x4E, 0x69, 0x34, 0xD9, 0xE5, 0xF9, 0x51, 0x20, 0x35, 0x8F, 0xA1, 0xC3, - 0x07, 0x58, 0xEC, 0xE5, 0x79, 0x4E, 0x7A, 0xF5, 0xDD, 0x13, 0x14, 0x94, 0x73, 0xF3, 0xA3, 0x9F, - 0x63, 0x89, 0x23, 0x90, 0xBA, 0x75, 0x83, 0x7D, 0xE5, 0xF0, 0x11, 0xB6, 0x5E, 0x77, 0x78, 0x38, - 0x8C, 0x06, 0x5F, 0xDF, 0xF0, 0x89, 0xA2, 0x9B, 0xBA, 0x39, 0xCA, 0x19, 0xC9, 0x62, 0x7F, 0x85, - 0xD6, 0x99, 0x62, 0xF9, 0x93, 0xA6, 0x74, 0x8D, 0xA2, 0xD8, 0x59, 0x98, 0x73, 0xD4, 0x0D, 0xD3, - 0xBB, 0x46, 0xBF, 0xCF, 0x65, 0x4A, 0x91, 0xC6, 0x6C, 0x15, 0x79, 0x60, 0x33, 0x27, 0xBE, 0xC2, - 0x9C, 0xB0, 0x57, 0x4D, 0x3C, 0x19, 0xD8, 0x2E, 0xBB, 0xEC, 0xC7, 0x69, 0x55, 0x8D, 0x00, 0x83, - 0xE4, 0x2C, 0xE5, 0x1E, 0x44, 0x3B, 0xAA, 0x80, 0x35, 0x9B, 0xB2, 0xF5, 0xD9, 0x65, 0x6C, 0x1D, - 0x71, 0x6B, 0xE4, 0x28, 0xF6, 0x58, 0x57, 0x6F, 0xF8, 0x08, 0xD6, 0x78, 0xEE, 0x58, 0xB6, 0xE0, - 0x2A, 0x45, 0x18, 0x49, 0x88, 0x97, 0x6C, 0xDE, 0x38, 0xFE, 0x10, 0x3E, 0x61, 0xE2, 0x51, 0xB1, - 0x82, 0x1F, 0x2F, 0x57, 0x30, 0xD3, 0x65, 0xEA, 0x3C, 0xE3, 0x2A, 0xBB, 0x26, 0x67, 0x1D, 0x64, - 0x97, 0xCD, 0xDD, 0x83, 0x78, 0x52, 0xFC, 0x76, 0xE3, 0xF8, 0xCB, 0xA0, 0x5C, 0xA2, 0xFA, 0xD9, - 0xCA, 0x04, 0x17, 0x5F, 0xE6, 0x6A, 0x09, 0x53, 0x3C, 0x99, 0xAF, 0x25, 0x70, 0x8A, 0xBF, 0xDE, - 0xCC, 0xD5, 0x72, 0xAF, 0x71, 0xFC, 0xDF, 0x15, 0xC0, 0x95, 0xE2, 0xC6, 0xC5, 0x79, 0xF8, 0xEB, - 0xA5, 0xBE, 0x81, 0xD8, 0xFD, 0x47, 0xCB, 0x77, 0xD8, 0x74, 0x9B, 0x99, 0x43, 0xFB, 0x2C, 0xB5, - 0x2F, 0x50, 0xE8, 0x80, 0x01, 0x8B, 0x74, 0xCA, 0x92, 0x52, 0x87, 0x0E, 0xFF, 0xD3, 0xE7, 0xA6, - 0xFA, 0x48, 0x3A, 0x9B, 0xC0, 0x0A, 0xC5, 0x88, 0xF0, 0x2E, 0x90, 0x2A, 0x6C, 0x5D, 0x8D, 0x10, - 0xE9, 0x97, 0xC1, 0x3A, 0x91, 0xA7, 0x90, 0x8D, 0x9C, 0x05, 0x68, 0xD7, 0xB6, 0x07, 0xDC, 0xC3, - 0x64, 0xD4, 0x6E, 0xE6, 0xF9, 0xBC, 0xD8, 0xD9, 0x53, 0xFA, 0xFC, 0x51, 0x7C, 0xCF, 0x82, 0x73, - 0xF1, 0x86, 0x9B, 0xFC, 0x41, 0x31, 0x00, 0xBB, 0xE1, 0x6F, 0x3C, 0x28, 0x99, 0x7C, 0x52, 0xB2, - 0xD0, 0xCB, 0x22, 0x27, 0x49, 0x72, 0x0A, 0xE5, 0x37, 0x7A, 0xB1, 0x5C, 0xF9, 0x12, 0x89, 0x7F, - 0xC1, 0x93, 0x81, 0x04, 0x0B, 0xE4, 0x45, 0x0C, 0xD6, 0x0A, 0xBA, 0x46, 0xF7, 0x90, 0xA1, 0x5C, - 0x81, 0xAA, 0x07, 0x89, 0x1B, 0x8F, 0x3B, 0x0C, 0xA7, 0x89, 0x15, 0xE9, 0xB0, 0x66, 0x25, 0x60, - 0xAE, 0xE7, 0xF1, 0x89, 0x4D, 0x95, 0xB3, 0x00, 0xDB, 0x4C, 0x24, 0x03, 0xF8, 0xF8, 0xEA, 0xA3, - 0x35, 0xE1, 0xAF, 0x98, 0xC9, 0xBD, 0x07, 0xCB, 0xF9, 0xBA, 0x03, 0x7A, 0x10, 0x88, 0x44, 0x0A, - 0x76, 0xB5, 0x83, 0x5F, 0x3B, 0xB8, 0x44, 0x1A, 0x2B, 0x82, 0xDB, 0xE2, 0x88, 0xD7, 0x4A, 0xD7, - 0xFF, 0xAC, 0x39, 0xB1, 0x7E, 0x31, 0x21, 0x94, 0x77, 0x24, 0xAA, 0x64, 0xFE, 0x8E, 0x1E, 0x46, - 0x51, 0x01, 0x5A, 0x08, 0x92, 0x7D, 0xC7, 0x1A, 0xEA, 0x06, 0xBF, 0xB5, 0xBE, 0xF2, 0x12, 0xBE, - 0x61, 0x85, 0x77, 0x2F, 0xB3, 0x25, 0xDA, 0xA4, 0xBC, 0x2A, 0xC7, 0x61, 0x34, 0xD0, 0x51, 0xB5, - 0x2D, 0x58, 0xBC, 0x54, 0xC3, 0xB4, 0xC4, 0x28, 0xF1, 0x50, 0xCB, 0x19, 0x29, 0xA6, 0xFE, 0x5D, - 0xE8, 0x16, 0x63, 0xC5, 0xC5, 0xA4, 0xF5, 0x96, 0x63, 0x5B, 0x64, 0x3E, 0x02, 0x6E, 0x6A, 0x8E, - 0x06, 0x9E, 0xC3, 0x95, 0x09, 0xF1, 0xCD, 0x98, 0xA8, 0xA3, 0xA8, 0x2A, 0x1A, 0xA6, 0x77, 0x44, - 0x82, 0x7C, 0x9D, 0xE4, 0x1D, 0x87, 0x63, 0xAF, 0x0C, 0x09, 0x93, 0x7A, 0x57, 0x7D, 0x17, 0x30, - 0x58, 0xE6, 0xBB, 0x67, 0xB6, 0x5C, 0xB8, 0x87, 0x0B, 0x8F, 0xA2, 0x23, 0x60, 0xF5, 0x23, 0x6B, - 0x32, 0x91, 0x6D, 0x9F, 0xB3, 0x81, 0xAD, 0x38, 0x5F, 0xDF, 0xFB, 0xA6, 0x80, 0x50, 0x63, 0x8E, - 0x8A, 0x16, 0x75, 0x96, 0x80, 0x28, 0x87, 0xD1, 0x65, 0x38, 0x56, 0xD6, 0xCD, 0xD8, 0xEB, 0x32, - 0x84, 0x58, 0xE1, 0x1A, 0xA2, 0x00, 0xB5, 0x4B, 0xD7, 0x21, 0xCF, 0xEF, 0xA7, 0x86, 0xC2, 0xE4, - 0xB5, 0x31, 0x80, 0x7A, 0x0F, 0x28, 0x92, 0x15, 0x5C, 0x0F, 0x0E, 0x88, 0x2F, 0x36, 0x10, 0x1B, - 0x47, 0xC3, 0x11, 0x3D, 0xA1, 0x53, 0x4A, 0x3C, 0x5B, 0xC1, 0x21, 0x35, 0x3B, 0x8D, 0xA7, 0x38, - 0xA6, 0x64, 0x9D, 0x65, 0x51, 0xC2, 0x25, 0xC6, 0x00, 0xE8, 0x00, 0x7B, 0xD0, 0x0D, 0x03, 0x4D, - 0xDD, 0x72, 0xB2, 0x5C, 0x23, 0x46, 0xE1, 0xD3, 0x84, 0x35, 0xB4, 0xAF, 0x63, 0x33, 0x13, 0xF0, - 0x95, 0x59, 0x36, 0xD6, 0x1C, 0xF6, 0x4D, 0xDD, 0x7B, 0xAC, 0xAE, 0x0B, 0xAD, 0xF7, 0x59, 0x84, - 0xBB, 0xE5, 0xBB, 0xFC, 0xC4, 0x75, 0x75, 0xD7, 0xFB, 0x64, 0x3D, 0x9C, 0x05, 0x1B, 0x5A, 0xB1, - 0x32, 0x77, 0x69, 0x34, 0x2E, 0x8D, 0xCA, 0xD1, 0x59, 0x81, 0xA4, 0x15, 0x7C, 0xAC, 0x50, 0xA7, - 0x72, 0x11, 0x0C, 0x8E, 0x8F, 0xFE, 0x44, 0x27, 0x1D, 0x61, 0x71, 0x58, 0x4E, 0x7B, 0x0A, 0x82, - 0xEB, 0x0F, 0x27, 0xA2, 0xC2, 0xCA, 0x2C, 0x0A, 0x83, 0xDC, 0xA4, 0x4F, 0xE0, 0xB4, 0xBA, 0x97, - 0x95, 0xB1, 0x15, 0xF5, 0x4F, 0x5F, 0x77, 0x75, 0x3A, 0x23, 0x6D, 0xC0, 0x7E, 0xAC, 0x13, 0x6C, - 0xAA, 0x7C, 0x3E, 0x34, 0x5E, 0x83, 0xC3, 0x6A, 0x71, 0xE6, 0x2B, 0x77, 0x17, 0x8B, 0xDF, 0x19, - 0xFA, 0x77, 0xAE, 0xC1, 0xFA, 0x3D, 0x47, 0xBF, 0xF3, 0xA9, 0x36, 0xE0, 0x3A, 0x61, 0x7F, 0xEA, - 0x0C, 0x45, 0xD5, 0x3E, 0x7A, 0xCC, 0xA2, 0xCF, 0x57, 0x47, 0x16, 0x19, 0xD3, 0x5A, 0x0B, 0x12, - 0x31, 0x42, 0xD8, 0x44, 0xAD, 0x59, 0x78, 0x87, 0x49, 0x32, 0x9D, 0x21, 0x0B, 0x1E, 0x86, 0x74, - 0x43, 0xC5, 0x48, 0x75, 0x13, 0x28, 0x47, 0x09, 0xAB, 0x78, 0xA3, 0x3C, 0x02, 0xF2, 0x80, 0xE9, - 0x81, 0x3A, 0x17, 0xE9, 0xE5, 0x79, 0x53, 0x4C, 0xB9, 0x2B, 0x1D, 0x23, 0x6D, 0x6B, 0x6F, 0x41, - 0x6A, 0xBA, 0xE2, 0xF7, 0xDC, 0x28, 0x61, 0x32, 0x4B, 0xD3, 0x56, 0xF2, 0x3B, 0xCD, 0xC4, 0x67, - 0x7C, 0x83, 0xD1, 0x2B, 0xE5, 0x3D, 0x67, 0xE2, 0x06, 0xB6, 0x82, 0x81, 0x4B, 0xAC, 0x78, 0x7E, - 0xE3, 0x5B, 0xB6, 0x11, 0xAE, 0xD3, 0x6E, 0xB7, 0xD9, 0x37, 0xBC, 0x9D, 0x6F, 0x7F, 0x9D, 0x90, - 0xBE, 0xE0, 0xF2, 0x8A, 0xF5, 0x23, 0x67, 0xCC, 0x73, 0xFB, 0xD4, 0xE5, 0x7E, 0x5D, 0x3D, 0xC2, - 0xE2, 0xBA, 0xFB, 0xD8, 0x23, 0xFC, 0xAC, 0xA7, 0xC7, 0x5E, 0x72, 0xDD, 0x1F, 0x81, 0xD0, 0x81, - 0xA0, 0x4C, 0x38, 0x99, 0x1E, 0x17, 0xEA, 0x79, 0x2F, 0xBE, 0xFA, 0xDA, 0xFA, 0xDD, 0x8F, 0xC3, - 0x60, 0xBE, 0x7E, 0x2B, 0x54, 0xFA, 0x5C, 0x0A, 0x73, 0x94, 0x16, 0x47, 0xE4, 0x6A, 0x53, 0xCE, - 0xA8, 0x45, 0xA9, 0xCC, 0x43, 0x2A, 0x33, 0x10, 0xD7, 0x5B, 0xB1, 0x35, 0xA2, 0x52, 0x8C, 0xB5, - 0x0E, 0x27, 0x30, 0xB4, 0xC6, 0xB5, 0x96, 0x44, 0x02, 0x36, 0x51, 0x1E, 0x91, 0x6F, 0x6A, 0xDC, - 0x86, 0x6F, 0x51, 0x4E, 0x8E, 0xB0, 0xC5, 0x2C, 0x78, 0x3D, 0x07, 0x36, 0x99, 0x6B, 0xA4, 0xAC, - 0x26, 0x7D, 0xE0, 0xC7, 0x9F, 0x56, 0x71, 0x91, 0xED, 0x78, 0xEE, 0xD3, 0x5F, 0x60, 0xE3, 0x2C, - 0x96, 0x75, 0x87, 0x1D, 0xED, 0xBB, 0xDA, 0x35, 0x76, 0xA4, 0x65, 0xD6, 0x2D, 0xF5, 0x14, 0x7A, - 0x33, 0xD7, 0xD3, 0xD8, 0x78, 0xAD, 0xEE, 0xA5, 0x73, 0x97, 0x33, 0xDF, 0xD5, 0x74, 0x8A, 0x11, - 0x12, 0x36, 0x38, 0xBF, 0x62, 0x21, 0x22, 0xE0, 0x7B, 0x2B, 0xA8, 0x01, 0x29, 0xFC, 0xC1, 0x80, - 0x64, 0x81, 0x32, 0xB9, 0x83, 0x57, 0x12, 0xE7, 0x27, 0xB7, 0x27, 0x0C, 0xC1, 0xB7, 0xC3, 0xDC, - 0x31, 0xA8, 0x29, 0x43, 0x1F, 0xA4, 0x2C, 0xC9, 0x56, 0xD1, 0x9D, 0x27, 0x89, 0x9B, 0xA9, 0x32, - 0x48, 0xD0, 0x1B, 0x2E, 0xFA, 0xB3, 0x5D, 0x74, 0x3F, 0x1A, 0x6B, 0x4A, 0x7E, 0x6A, 0xD8, 0xEE, - 0x6C, 0xAC, 0x98, 0x66, 0x44, 0x60, 0x09, 0x16, 0x5B, 0xF2, 0xE0, 0x8E, 0x4A, 0x2F, 0x61, 0x9F, - 0xA7, 0x8A, 0x0F, 0x02, 0xDF, 0x0D, 0xFE, 0x49, 0xD8, 0xC3, 0xF0, 0x01, 0x79, 0x22, 0x1E, 0xB1, - 0x39, 0x05, 0x94, 0x78, 0xDF, 0xF1, 0x25, 0x88, 0x47, 0x69, 0xE2, 0xC7, 0x7C, 0x92, 0xC7, 0xDE, - 0x61, 0x1B, 0x84, 0x0F, 0xFC, 0xB9, 0xD0, 0xB1, 0xF8, 0xE6, 0x00, 0xBB, 0xC1, 0x9F, 0x8B, 0xC9, - 0x2C, 0x6F, 0xBA, 0xD8, 0x0F, 0xFD, 0x5A, 0x4C, 0xB0, 0x38, 0xDC, 0xC3, 0x8E, 0xE8, 0xD7, 0x62, - 0xE7, 0xFD, 0x6B, 0x5A, 0x19, 0xFD, 0x5A, 0x6C, 0x69, 0x9D, 0x7D, 0xB1, 0x36, 0xFA, 0xBD, 0x98, - 0x1C, 0xD6, 0x6B, 0xD3, 0xEA, 0xC4, 0xEF, 0xC5, 0xC4, 0xA4, 0x83, 0xB6, 0x40, 0x00, 0xFA, 0xBD, - 0x18, 0x0A, 0x74, 0x3B, 0x02, 0x09, 0xE8, 0xF7, 0xF3, 0x11, 0x86, 0x6E, 0xC9, 0x73, 0x16, 0x68, - 0x96, 0xEE, 0x07, 0x50, 0x27, 0x44, 0xB9, 0xE8, 0xE6, 0xE4, 0xFC, 0xF2, 0x33, 0x31, 0xAD, 0xC0, - 0xF3, 0x55, 0x05, 0xE6, 0x31, 0x12, 0x96, 0x94, 0x89, 0xE2, 0xA9, 0xC0, 0xE2, 0x50, 0x4D, 0x74, - 0xB0, 0x4E, 0xEE, 0xD8, 0x42, 0xBE, 0x07, 0x7A, 0x22, 0x91, 0x69, 0x44, 0xF4, 0x21, 0xB4, 0xB9, - 0xB3, 0xDD, 0x97, 0x26, 0xEA, 0x94, 0xE3, 0xBB, 0xB8, 0x3D, 0x35, 0xB3, 0xDD, 0x44, 0x97, 0x8D, - 0xE3, 0x6B, 0xFF, 0x1B, 0x93, 0x7F, 0xCC, 0xCD, 0x6F, 0x93, 0x9D, 0xA6, 0x4D, 0xBE, 0x4E, 0x9E, - 0x0B, 0x44, 0xF2, 0xE9, 0xFA, 0xE2, 0x64, 0x51, 0xED, 0xAE, 0xDF, 0x1F, 0xEC, 0x5E, 0xDC, 0xA3, - 0x63, 0xF4, 0x2D, 0x60, 0xFD, 0x08, 0x4B, 0x56, 0x2F, 0xA4, 0xDC, 0x09, 0xEF, 0x4D, 0xFF, 0x9B, - 0x5C, 0x31, 0x6C, 0xCD, 0x65, 0xF7, 0x6C, 0x51, 0xF5, 0xEE, 0xE4, 0xFC, 0x6C, 0xF7, 0xFC, 0xE4, - 0xEC, 0x79, 0xB1, 0x83, 0x50, 0x60, 0x09, 0x69, 0x5F, 0x0A, 0x84, 0xD2, 0xF1, 0x5D, 0xD3, 0x87, - 0x43, 0xEE, 0x20, 0xE4, 0x15, 0xDB, 0x36, 0x74, 0x61, 0x3C, 0x72, 0x5B, 0x0C, 0x77, 0x15, 0x35, - 0x24, 0x32, 0x1F, 0xE1, 0x8B, 0xC0, 0x1F, 0x74, 0x10, 0x80, 0x6E, 0x7F, 0xDD, 0xBD, 0xF9, 0x15, - 0xF9, 0x43, 0x68, 0x68, 0x42, 0xBA, 0x76, 0x26, 0xF4, 0xB9, 0xC5, 0x70, 0x23, 0xE5, 0x16, 0xC6, - 0x5A, 0xDB, 0x3E, 0x08, 0xB3, 0x68, 0x9D, 0x85, 0x7E, 0x60, 0x06, 0x1A, 0xB3, 0x7C, 0x0F, 0x4D, - 0x74, 0x78, 0x1D, 0xB1, 0x6F, 0xBA, 0x78, 0x5D, 0xE9, 0x13, 0xD3, 0xF2, 0x82, 0xC6, 0x68, 0xA9, - 0x83, 0x79, 0xC0, 0xBE, 0x85, 0x1D, 0xE1, 0xFD, 0xA7, 0xC9, 0x14, 0x4D, 0x23, 0x5B, 0x2F, 0x4C, - 0x66, 0x70, 0x7E, 0xB2, 0x3B, 0x38, 0xBB, 0x12, 0x86, 0x62, 0x55, 0xEC, 0x75, 0x8B, 0xFD, 0x32, - 0xE6, 0xDC, 0xD8, 0x3D, 0xD7, 0x1D, 0x76, 0xAB, 0xAB, 0x5F, 0x63, 0xD3, 0xA0, 0x2B, 0x7B, 0xCB, - 0xD3, 0xEF, 0x39, 0xD6, 0xB7, 0xE7, 0xCE, 0x50, 0x51, 0x75, 0x73, 0xD4, 0x62, 0x72, 0x6B, 0x63, - 0xEF, 0xCA, 0xDB, 0xD1, 0xA1, 0xEE, 0x4C, 0xD0, 0x69, 0x31, 0x01, 0x9F, 0x90, 0x2F, 0x22, 0xA0, - 0x5E, 0x9C, 0x95, 0x2C, 0xE0, 0x18, 0x28, 0xA2, 0xD5, 0xC9, 0xEB, 0x84, 0x84, 0x79, 0x8E, 0xDB, - 0x55, 0x93, 0x80, 0x19, 0xEB, 0x79, 0x66, 0xEE, 0x1B, 0xF1, 0x72, 0x23, 0x5E, 0x6E, 0xC4, 0xCB, - 0xDA, 0xBC, 0x52, 0x4C, 0x71, 0x2C, 0x60, 0x54, 0xD2, 0x8E, 0x0C, 0xD3, 0x4A, 0x0A, 0x9B, 0xB3, - 0xE7, 0x4D, 0xA6, 0xAC, 0x19, 0x61, 0xA8, 0x11, 0x7E, 0x2A, 0xE0, 0xFB, 0x4C, 0x04, 0xCD, 0x4A, - 0x4C, 0x35, 0x54, 0xFB, 0xF1, 0x2C, 0x0C, 0x8C, 0x3E, 0x09, 0xAB, 0x48, 0x59, 0xC3, 0xFB, 0x62, - 0xD7, 0x73, 0xA5, 0xAF, 0xE8, 0xC4, 0xAD, 0xD3, 0x45, 0x74, 0xE2, 0xA1, 0x0B, 0x7A, 0xF0, 0xB4, - 0x7C, 0x98, 0x30, 0x36, 0xAF, 0x16, 0x22, 0xBC, 0xB8, 0x3F, 0x7A, 0x62, 0xEE, 0xD5, 0x51, 0x6A, - 0x71, 0xEA, 0x89, 0x50, 0xD0, 0x07, 0x6E, 0x72, 0x22, 0x17, 0x45, 0x40, 0x03, 0xA3, 0x74, 0xD8, - 0x40, 0x4A, 0x44, 0x20, 0x9E, 0xC0, 0x7B, 0x13, 0x19, 0xFC, 0x38, 0xF1, 0x81, 0x56, 0x86, 0x94, - 0x71, 0x61, 0x47, 0xD8, 0xA1, 0x00, 0x7F, 0x30, 0x7A, 0x50, 0xCA, 0x4A, 0xEA, 0x63, 0x8B, 0xA1, - 0xE3, 0x8B, 0xEE, 0x70, 0x57, 0xDC, 0x83, 0x3B, 0x5C, 0xE5, 0x76, 0x82, 0x9A, 0xA4, 0x2F, 0xA1, - 0xE8, 0xA0, 0xD3, 0x6E, 0xEF, 0xB4, 0xDB, 0x6D, 0xDF, 0x95, 0xE2, 0x98, 0xC1, 0xCD, 0x11, 0xD9, - 0xB7, 0x34, 0xF6, 0x26, 0xFC, 0x4A, 0xCC, 0x80, 0x7B, 0x0F, 0x9C, 0x9B, 0xE2, 0x3D, 0xB7, 0x55, - 0x25, 0x40, 0x7A, 0x59, 0xE4, 0x58, 0x49, 0xF7, 0xAB, 0x12, 0xA9, 0x9F, 0x41, 0x9A, 0xE7, 0x1C, - 0xC3, 0x3E, 0xDD, 0xB9, 0x29, 0x74, 0x21, 0x57, 0xC8, 0x2C, 0x39, 0x2A, 0x36, 0xCF, 0x5B, 0xD8, - 0xA9, 0x53, 0xB1, 0x51, 0x02, 0xBB, 0x4B, 0x77, 0x39, 0xA7, 0x87, 0xE4, 0xED, 0x2C, 0x6A, 0xB0, - 0xAD, 0xFF, 0xF7, 0x7F, 0xDD, 0xED, 0xA3, 0xF2, 0x8B, 0xA9, 0x42, 0xFE, 0x0B, 0xBB, 0xE5, 0x65, - 0xBA, 0xE8, 0xE5, 0x65, 0x94, 0xAA, 0xD4, 0x2B, 0xFE, 0x9B, 0x41, 0xA0, 0x99, 0x8D, 0xA9, 0x38, - 0x53, 0xBB, 0xB8, 0xCB, 0x3A, 0xF2, 0x0C, 0x94, 0xB8, 0xEF, 0x99, 0x87, 0xA8, 0x96, 0x8F, 0xF8, - 0x57, 0xC4, 0xB7, 0x96, 0x8E, 0xEE, 0xFD, 0x08, 0x93, 0xAC, 0x34, 0x96, 0xA0, 0x89, 0x67, 0x80, - 0xEA, 0xB3, 0x78, 0x26, 0x41, 0xBB, 0x38, 0xC2, 0x8A, 0x8E, 0x9E, 0x03, 0x9A, 0xD2, 0x85, 0x18, - 0xD1, 0x94, 0x36, 0xE2, 0xF3, 0x2A, 0xBB, 0x85, 0x38, 0xDB, 0xB7, 0x0C, 0xC5, 0xC1, 0x9B, 0xE2, - 0xD5, 0x60, 0x6D, 0x30, 0xDC, 0xD1, 0x1C, 0x1C, 0x37, 0xA6, 0x5F, 0xA7, 0x2F, 0x62, 0x76, 0xBF, - 0x17, 0x5A, 0xDF, 0x3C, 0xDA, 0x79, 0xB6, 0x41, 0xF2, 0x46, 0x77, 0x75, 0x73, 0xC4, 0x70, 0x3B, - 0xAB, 0xA9, 0x69, 0xD9, 0xF6, 0xC9, 0xF7, 0x8A, 0x61, 0xCC, 0xDF, 0x67, 0x79, 0xBD, 0x6D, 0x89, - 0x12, 0x68, 0xC2, 0x2E, 0x28, 0x24, 0x40, 0x57, 0x1F, 0xA1, 0x1D, 0x2D, 0xF0, 0x15, 0x1B, 0xA3, - 0x4B, 0x83, 0x08, 0x8C, 0x54, 0xC9, 0x48, 0xB6, 0xE5, 0x08, 0x58, 0x72, 0x58, 0xF7, 0x36, 0x4A, - 0xA8, 0x18, 0x0A, 0x13, 0x7B, 0x61, 0x28, 0x21, 0x43, 0x6F, 0x44, 0x04, 0xCF, 0xC8, 0x26, 0x54, - 0xDD, 0xD0, 0x65, 0x4A, 0x90, 0x55, 0xA4, 0xC8, 0x0A, 0x8C, 0x67, 0xEE, 0xD4, 0x50, 0xAB, 0x50, - 0xDB, 0x3E, 0xCA, 0xB0, 0x6B, 0x32, 0xB0, 0x5F, 0x59, 0xA3, 0x11, 0x86, 0x45, 0x4B, 0x2D, 0xAE, - 0x34, 0xD0, 0x2A, 0x6B, 0x7B, 0xC2, 0x9C, 0x2F, 0x87, 0x5B, 0x89, 0xD6, 0x57, 0x7A, 0x6A, 0xB3, - 0xDA, 0x61, 0x3A, 0x88, 0x9E, 0x58, 0x59, 0x84, 0x79, 0x4C, 0x1D, 0x0F, 0x02, 0x71, 0x9B, 0xE3, - 0x0C, 0xDD, 0x6D, 0xA1, 0xD0, 0xF5, 0xDA, 0xA1, 0xE9, 0x5C, 0x7D, 0x64, 0x37, 0xD7, 0x83, 0x16, - 0x46, 0xE9, 0x0C, 0x7D, 0x43, 0x9A, 0x63, 0x30, 0x9E, 0x90, 0x19, 0xFA, 0x57, 0xD0, 0x19, 0x7D, - 0xBC, 0xD4, 0xF7, 0x1C, 0x5D, 0x31, 0x47, 0xBE, 0x21, 0x6D, 0x2E, 0x03, 0x2E, 0x22, 0x7A, 0x50, - 0xB8, 0x04, 0x7A, 0xFA, 0x8A, 0xB6, 0x79, 0x62, 0x7C, 0xD2, 0x4D, 0xF4, 0xF7, 0x8B, 0xF3, 0xE6, - 0xFB, 0x37, 0x7D, 0x76, 0x69, 0x7A, 0x7C, 0x24, 0x3D, 0x48, 0xAE, 0x15, 0xD3, 0x57, 0x44, 0xFF, - 0x13, 0xCB, 0xE1, 0x71, 0xEB, 0x7F, 0xB1, 0x3E, 0x5A, 0xD1, 0xAF, 0xF4, 0xF9, 0x6B, 0x94, 0x51, - 0x8C, 0xAA, 0x4D, 0xA5, 0xA4, 0x01, 0xB0, 0xE3, 0x65, 0x89, 0x2C, 0x34, 0xEB, 0x95, 0x89, 0x2C, - 0x82, 0x55, 0xD4, 0x2E, 0xB2, 0xC4, 0x17, 0x31, 0xBB, 0x2B, 0x6B, 0x24, 0xB2, 0x60, 0x36, 0x1B, - 0xCF, 0x22, 0x97, 0xC2, 0xBA, 0x44, 0x16, 0x72, 0x4F, 0x14, 0x89, 0x72, 0x5E, 0x86, 0xC4, 0x12, - 0xB2, 0x42, 0xC2, 0xFC, 0x50, 0x66, 0x31, 0x80, 0xB6, 0xB8, 0xC6, 0xD0, 0xD1, 0x73, 0x1C, 0xE4, - 0x12, 0xD3, 0x13, 0x5C, 0x27, 0x02, 0xDE, 0x8D, 0x30, 0x52, 0xDD, 0x70, 0xED, 0x83, 0x6E, 0x14, - 0x1C, 0x97, 0x18, 0x93, 0x4F, 0x1E, 0x62, 0x6B, 0x68, 0xA4, 0x8E, 0xCC, 0x2D, 0x61, 0xA3, 0x66, - 0xC2, 0xA9, 0x2D, 0x92, 0x90, 0xE4, 0x09, 0xEC, 0xD0, 0x55, 0x40, 0x57, 0x8D, 0xA4, 0x32, 0xC6, - 0x29, 0x97, 0x8C, 0x2F, 0x85, 0xDC, 0x24, 0xF4, 0x42, 0x8A, 0x23, 0x5F, 0xA0, 0x68, 0xA4, 0xC8, - 0x11, 0xA5, 0xBD, 0xDB, 0xFD, 0x72, 0xFA, 0xEB, 0xEE, 0xA0, 0x7F, 0x72, 0x73, 0xFB, 0x09, 0xE9, - 0x2F, 0x10, 0x17, 0xBE, 0xC0, 0x83, 0x6E, 0x84, 0xFA, 0xDE, 0x2B, 0xD5, 0x6C, 0x60, 0xEB, 0x74, - 0xE0, 0x17, 0xBD, 0x56, 0x49, 0x20, 0x08, 0x37, 0x46, 0xC0, 0x6C, 0x60, 0xF9, 0x8E, 0x9A, 0x72, - 0x7C, 0x57, 0x26, 0x8F, 0xE0, 0xE8, 0x4E, 0xED, 0x1F, 0x68, 0x21, 0xD8, 0x46, 0xB9, 0x55, 0xE2, - 0x79, 0xC5, 0x63, 0x76, 0xE6, 0x88, 0x4D, 0x1D, 0xEC, 0x16, 0x08, 0xA1, 0x91, 0xBB, 0xDC, 0xC6, - 0xA2, 0x07, 0xE8, 0xEC, 0x49, 0x27, 0x92, 0x88, 0xCC, 0x71, 0xC8, 0xCD, 0x1C, 0xC3, 0x97, 0xFD, - 0x8A, 0xF7, 0xBA, 0x95, 0x8E, 0xC9, 0xE5, 0x69, 0x0A, 0x14, 0x21, 0x26, 0x77, 0x37, 0x1A, 0x15, - 0x86, 0x6E, 0x2B, 0x18, 0x28, 0xA9, 0x6B, 0xE2, 0x84, 0x24, 0xCA, 0x94, 0x29, 0x01, 0xA2, 0x69, - 0x58, 0x5C, 0xDA, 0x9A, 0x16, 0x79, 0x3E, 0x7F, 0xBA, 0xF8, 0xDC, 0x3C, 0x7F, 0x73, 0x76, 0xC4, - 0xE4, 0x86, 0x0B, 0xE8, 0x46, 0xC8, 0xF9, 0xB2, 0xDF, 0x7A, 0x81, 0xC4, 0xBC, 0x68, 0xD8, 0x25, - 0x3A, 0x8E, 0x9F, 0x18, 0x0F, 0x98, 0x22, 0x84, 0x1C, 0xC3, 0x25, 0x0B, 0x25, 0x45, 0x48, 0xFA, - 0x3A, 0x61, 0xAE, 0x4F, 0xF6, 0x65, 0x70, 0x5A, 0xEC, 0x24, 0xBE, 0xBC, 0xE0, 0x79, 0x71, 0x48, - 0x7C, 0x30, 0x5D, 0xF7, 0xD6, 0xFA, 0xE2, 0xDE, 0x0D, 0xC8, 0xA9, 0x2B, 0x3C, 0x2E, 0x93, 0xB3, - 0x2D, 0x04, 0x2C, 0xAC, 0x66, 0xF9, 0x91, 0xF6, 0x19, 0x73, 0x5E, 0x71, 0xB8, 0xFD, 0x67, 0x01, - 0x16, 0x02, 0x91, 0xF4, 0x85, 0x23, 0xB7, 0xB3, 0x2D, 0x9D, 0xEF, 0x08, 0xB7, 0x08, 0xCA, 0x5D, - 0x04, 0xC7, 0xE2, 0xB6, 0xD8, 0x69, 0x24, 0x2C, 0xDC, 0x6D, 0x72, 0x86, 0x88, 0x04, 0x60, 0xBA, - 0x9E, 0xE2, 0xF9, 0x6E, 0x24, 0x65, 0x6C, 0xE5, 0x83, 0xF2, 0x29, 0x43, 0xED, 0x2B, 0x7C, 0x95, - 0x1D, 0xF4, 0x93, 0x45, 0x55, 0x89, 0xF8, 0x9F, 0x5F, 0xF4, 0xF7, 0x7A, 0x7E, 0xF8, 0x4F, 0xC9, - 0xD0, 0x9F, 0xAA, 0x61, 0x3F, 0x73, 0x45, 0xF9, 0xA4, 0x47, 0xF8, 0xE0, 0x1A, 0xE6, 0x0A, 0xF0, - 0x89, 0x34, 0x9C, 0x05, 0x6D, 0x04, 0x32, 0x89, 0xD0, 0x9E, 0x07, 0x7D, 0xA8, 0x2F, 0x16, 0xD9, - 0x33, 0x1B, 0xD5, 0x93, 0xDC, 0xB5, 0xC2, 0x68, 0x9E, 0xCC, 0xB9, 0x57, 0x0B, 0xE4, 0xC9, 0x0F, - 0xE2, 0x49, 0xC3, 0xC4, 0x4F, 0x22, 0xCF, 0x92, 0x9B, 0x7E, 0x21, 0x5D, 0x03, 0x53, 0x08, 0x05, - 0x64, 0x10, 0xA9, 0x98, 0xEA, 0x70, 0x0D, 0x1A, 0x01, 0x2B, 0x10, 0x01, 0xD8, 0x30, 0x37, 0xD0, - 0x32, 0xF7, 0xC4, 0xEE, 0xC8, 0x94, 0x4F, 0x40, 0xDF, 0x27, 0xA0, 0xA8, 0x06, 0x7F, 0x85, 0x6A, - 0xAB, 0xE7, 0xE8, 0x32, 0x1B, 0x07, 0xF9, 0x51, 0x61, 0xFA, 0x12, 0xF9, 0xCE, 0x34, 0x29, 0x61, - 0x2C, 0x86, 0xBB, 0x55, 0x36, 0x85, 0xE2, 0xA2, 0x0C, 0x21, 0xEB, 0xBB, 0xAC, 0x23, 0xB0, 0xF2, - 0x5D, 0x6F, 0x54, 0x6A, 0x45, 0x74, 0x95, 0x9B, 0xF6, 0x47, 0x7B, 0x30, 0xC0, 0xCC, 0xA0, 0x91, - 0x1B, 0xD0, 0xDE, 0x8C, 0xA9, 0x08, 0x5F, 0x61, 0x9D, 0xFC, 0xBB, 0xD5, 0xB9, 0xEE, 0x51, 0xAB, - 0x64, 0xF0, 0x49, 0x99, 0xB4, 0x3C, 0xB0, 0x3C, 0xD8, 0xC7, 0xBC, 0x41, 0xEC, 0xF4, 0xF6, 0xF3, - 0x5C, 0x93, 0xE6, 0x33, 0xDD, 0x25, 0xEE, 0x52, 0x1F, 0xFA, 0x80, 0x4F, 0x5A, 0xC1, 0x4E, 0xF5, - 0x7F, 0xC9, 0x04, 0xC3, 0x5A, 0xED, 0x5F, 0xB8, 0x9C, 0x6A, 0xDB, 0x16, 0x34, 0x7B, 0x4E, 0x5B, - 0xD7, 0x29, 0x4B, 0x60, 0xDD, 0x35, 0xDA, 0x20, 0x31, 0xE9, 0x4A, 0x9B, 0xD3, 0x79, 0x6E, 0x34, - 0xD5, 0x59, 0x9C, 0xA6, 0xD6, 0x6A, 0xCB, 0xE6, 0xA3, 0xA9, 0xCE, 0x73, 0xA4, 0xA9, 0x6E, 0x59, - 0x9A, 0xEA, 0xAD, 0xD1, 0x06, 0x75, 0xAB, 0xD3, 0x54, 0xF7, 0xB9, 0xD1, 0x54, 0x77, 0x71, 0x9A, - 0x5A, 0xAB, 0x2D, 0x9B, 0x8F, 0xA6, 0xBA, 0xCF, 0x91, 0xA6, 0x7A, 0x65, 0x69, 0x6A, 0x6F, 0x8D, - 0x36, 0xA8, 0x57, 0x9D, 0xA6, 0x7A, 0xCF, 0x8D, 0xA6, 0x7A, 0x8B, 0xD3, 0xD4, 0x5A, 0x6D, 0xD9, - 0x7C, 0x34, 0xD5, 0x5B, 0x35, 0x4D, 0x85, 0x7A, 0x3D, 0xA9, 0xD4, 0x68, 0x63, 0xAF, 0x72, 0x69, - 0x90, 0xDC, 0x4C, 0xD1, 0xCB, 0xE7, 0x7B, 0xEE, 0x9C, 0xF4, 0x1B, 0xC7, 0x81, 0x11, 0x81, 0xB3, - 0x6B, 0x4B, 0x2B, 0xBA, 0x14, 0x88, 0x5F, 0x02, 0xC4, 0xA7, 0xD4, 0x48, 0x4C, 0x53, 0x0E, 0x50, - 0xD5, 0xDC, 0x3F, 0x6B, 0xDE, 0x3F, 0x29, 0x61, 0x94, 0x9F, 0x35, 0xE5, 0xA3, 0x0E, 0x9E, 0xDF, - 0x2E, 0xDF, 0x78, 0x5F, 0x9F, 0xAD, 0xE0, 0xD2, 0x64, 0x27, 0xFD, 0x48, 0xCC, 0x54, 0x98, 0x5A, - 0x04, 0x75, 0x7B, 0xC7, 0x52, 0x34, 0x55, 0x01, 0xE5, 0x5F, 0xC6, 0xB6, 0xAA, 0x2A, 0x77, 0x5D, - 0x46, 0xA9, 0x5D, 0x19, 0xE6, 0x95, 0xE6, 0x68, 0x52, 0xFC, 0x6B, 0x53, 0x80, 0xB4, 0xC5, 0xA0, - 0x2F, 0x32, 0x2E, 0xA4, 0xF7, 0x16, 0xC9, 0x3B, 0x4D, 0xB9, 0x90, 0xC4, 0xBB, 0x68, 0x63, 0x88, - 0xC4, 0xFD, 0x92, 0x61, 0x81, 0x6E, 0xCB, 0x39, 0x93, 0x35, 0x31, 0x60, 0x90, 0xCB, 0x3E, 0xC6, - 0xD5, 0x3A, 0x30, 0xF8, 0x5A, 0xDA, 0x19, 0xAA, 0xD9, 0x0D, 0x6F, 0xCF, 0xFA, 0x6C, 0x97, 0x7D, - 0x39, 0xEF, 0x3F, 0x77, 0xE3, 0x21, 0x2C, 0x04, 0x56, 0x31, 0x97, 0xF9, 0x30, 0xD6, 0x74, 0x16, - 0xC8, 0x49, 0x10, 0x25, 0xAC, 0x88, 0x9E, 0x6A, 0x7F, 0xD1, 0xEC, 0x27, 0xB7, 0x23, 0xE6, 0x2C, - 0x62, 0x41, 0x4B, 0x62, 0xE1, 0xAD, 0x4A, 0x85, 0xDB, 0x94, 0x5B, 0xD5, 0x3E, 0x33, 0x74, 0xE0, - 0x08, 0x8D, 0x63, 0x04, 0xAB, 0xF8, 0x9C, 0xCF, 0x47, 0x17, 0xBF, 0x0E, 0x99, 0x0E, 0x9A, 0x49, - 0xAD, 0x61, 0xCD, 0x2D, 0x2F, 0x78, 0xF7, 0xD4, 0xFA, 0xC6, 0xA9, 0xF6, 0xD8, 0xB2, 0x59, 0xDE, - 0x70, 0x9A, 0xAF, 0x32, 0x83, 0x41, 0x85, 0xAC, 0xC9, 0xF6, 0xDD, 0xB1, 0xB8, 0x3F, 0xC1, 0xEA, - 0x7A, 0xC0, 0x94, 0x46, 0xFA, 0x3D, 0x37, 0x09, 0x41, 0x5D, 0x2A, 0xB0, 0x39, 0xBD, 0x4D, 0x11, - 0xDF, 0xE0, 0x7D, 0xCA, 0xBA, 0x30, 0xA9, 0xCC, 0xE3, 0x3A, 0x04, 0x79, 0x6E, 0x8A, 0xAE, 0xB9, - 0xC2, 0x64, 0xA2, 0xE7, 0x79, 0x38, 0x0C, 0x06, 0xBC, 0x37, 0xE6, 0x0A, 0x17, 0x80, 0x86, 0x47, - 0x35, 0x5D, 0xA5, 0x85, 0xDE, 0x5A, 0xB0, 0x77, 0x74, 0xEB, 0x05, 0x3B, 0xEA, 0xBB, 0xD1, 0x44, - 0xBC, 0xDD, 0x37, 0x7B, 0x87, 0xEB, 0x7B, 0xC1, 0x55, 0x54, 0xDB, 0x66, 0xDE, 0xF8, 0x9C, 0x2A, - 0xF2, 0x69, 0x7C, 0x47, 0x0B, 0xFA, 0xB5, 0x67, 0x9B, 0xCC, 0x1B, 0x71, 0x53, 0xFD, 0x7A, 0xAF, - 0x5E, 0x04, 0xFE, 0x68, 0xB9, 0xF3, 0x21, 0x30, 0x36, 0xC4, 0xBE, 0x72, 0x21, 0x35, 0xE5, 0xCB, - 0x47, 0x2B, 0xBE, 0x36, 0x46, 0xCF, 0x45, 0x14, 0x97, 0x29, 0xBC, 0x57, 0x48, 0x58, 0x81, 0x7B, - 0xF5, 0x18, 0x67, 0xFE, 0x30, 0xD6, 0xD5, 0xB1, 0xF0, 0xC2, 0x86, 0x39, 0xAA, 0x34, 0xC7, 0x78, - 0xE2, 0x6B, 0x64, 0x90, 0x14, 0x3F, 0xDF, 0xDA, 0x50, 0x4E, 0x29, 0xCA, 0x11, 0xA8, 0x54, 0xEE, - 0x46, 0x26, 0x8D, 0x8C, 0xB0, 0xFD, 0xEA, 0xC8, 0x28, 0xEF, 0x24, 0xA9, 0xA4, 0xB3, 0xDB, 0x69, - 0xD2, 0x41, 0xD5, 0x75, 0x94, 0x36, 0x21, 0xD4, 0x2C, 0x40, 0x89, 0x5A, 0xDA, 0x42, 0x80, 0x12, - 0x9F, 0x57, 0x20, 0x40, 0xC9, 0x41, 0x4B, 0x09, 0x50, 0xE2, 0xDD, 0xA7, 0x16, 0xA0, 0x40, 0x23, - 0xB4, 0x1E, 0x98, 0x6E, 0xDE, 0x59, 0x3E, 0x88, 0x4E, 0xC4, 0x31, 0x84, 0x48, 0x25, 0xDC, 0xBD, - 0x62, 0xE2, 0x54, 0x8A, 0xD8, 0x24, 0x43, 0xB7, 0x02, 0x36, 0x83, 0xA5, 0x90, 0x45, 0xF3, 0xF5, - 0xB9, 0x5E, 0xCE, 0x93, 0xA8, 0xC4, 0x1E, 0x2C, 0x5D, 0xA2, 0x12, 0xC3, 0x6C, 0x24, 0xAA, 0x97, - 0x73, 0x2E, 0x44, 0x76, 0xB4, 0xEC, 0x51, 0x30, 0x6D, 0xF2, 0xFC, 0x8F, 0x02, 0xB1, 0x96, 0x67, - 0x71, 0x14, 0x7C, 0xD1, 0xC2, 0xA3, 0x00, 0x8D, 0x13, 0xAB, 0x39, 0x0A, 0xA6, 0x83, 0x4E, 0x59, - 0xBE, 0xAF, 0xD9, 0x4F, 0xCD, 0xEC, 0xA7, 0xC6, 0x41, 0xE2, 0xE7, 0x2E, 0x74, 0xC9, 0x4D, 0x95, - 0xBB, 0xD2, 0x91, 0xF4, 0xBC, 0xBF, 0xEE, 0x2C, 0xDB, 0xD7, 0xCA, 0x55, 0x35, 0x5C, 0x98, 0x69, - 0xFB, 0xDA, 0x3A, 0x32, 0x6D, 0x44, 0xE0, 0x74, 0xA6, 0xDD, 0x69, 0x77, 0x3A, 0xED, 0x0D, 0xD7, - 0xCE, 0xE3, 0xDA, 0xF1, 0x2D, 0x2D, 0xC5, 0xB5, 0x63, 0x4D, 0x9E, 0x39, 0xD7, 0x0E, 0x59, 0x52, - 0x1D, 0x5C, 0xBB, 0x9A, 0xF5, 0x3C, 0x08, 0x95, 0x7A, 0xD6, 0x96, 0x73, 0x5A, 0xC4, 0x5C, 0x86, - 0xF3, 0x68, 0xCB, 0x59, 0xF0, 0x46, 0x81, 0x93, 0xB0, 0x99, 0x53, 0x90, 0xD4, 0x93, 0x9B, 0xCC, - 0xB3, 0xA7, 0xBF, 0x46, 0x16, 0xF3, 0x0B, 0xD7, 0xA6, 0x9A, 0x63, 0x17, 0x83, 0x7E, 0xB3, 0xB0, - 0xDE, 0x59, 0x1D, 0xC1, 0x77, 0x72, 0xBC, 0x25, 0x1F, 0xE4, 0x68, 0xEB, 0xA1, 0xB4, 0xB2, 0x18, - 0x6C, 0x05, 0x6B, 0xEB, 0x75, 0x83, 0x24, 0x88, 0x61, 0xFA, 0x5A, 0x71, 0xB5, 0x07, 0x68, 0xDD, - 0xA4, 0x0F, 0x3B, 0x68, 0x16, 0x0A, 0x1F, 0x4D, 0xE0, 0x70, 0xD0, 0xC5, 0xDD, 0x9F, 0x88, 0xB8, - 0x43, 0xA7, 0x62, 0x8C, 0x28, 0x10, 0x51, 0xAD, 0x13, 0xDD, 0x75, 0x29, 0xAE, 0xF5, 0xA3, 0xF5, - 0xC0, 0xEF, 0x31, 0x2D, 0xDC, 0x29, 0xAC, 0xD4, 0xB3, 0x2C, 0x6F, 0xCC, 0x06, 0xFD, 0x3E, 0x8E, - 0x65, 0x5A, 0xDE, 0x74, 0x38, 0x51, 0x15, 0xC5, 0x45, 0xE3, 0x13, 0x26, 0x75, 0xFB, 0x19, 0x1F, - 0x47, 0x9A, 0x9C, 0x5E, 0x5D, 0x44, 0x8E, 0xA4, 0xCF, 0xC3, 0xE1, 0x5A, 0x3B, 0x18, 0x87, 0x14, - 0x36, 0x4F, 0x10, 0x7D, 0x3A, 0x32, 0xE7, 0xAC, 0x57, 0x90, 0xF9, 0xF5, 0xC9, 0xD9, 0x51, 0xC0, - 0x96, 0x69, 0x6C, 0x78, 0xD0, 0x60, 0xAE, 0xF7, 0x88, 0x9B, 0x2D, 0xEF, 0x4E, 0x8F, 0x04, 0x4B, - 0xFE, 0xB9, 0x71, 0x7C, 0x72, 0x72, 0x74, 0x7A, 0x7A, 0x74, 0x76, 0x76, 0x74, 0x7E, 0x7E, 0x74, - 0x71, 0x71, 0xF4, 0xFE, 0x7D, 0x55, 0x1F, 0x80, 0xB9, 0x66, 0xDA, 0x57, 0x74, 0x4C, 0xE5, 0x4C, - 0x13, 0x76, 0x8F, 0x2A, 0x86, 0x15, 0x95, 0x3B, 0x57, 0x6D, 0xCE, 0x1D, 0x58, 0xB9, 0x9B, 0xBD, - 0xF4, 0x4F, 0x96, 0xC9, 0x17, 0x3C, 0x55, 0x6B, 0x14, 0x0C, 0xB1, 0x91, 0x9C, 0xA9, 0x10, 0xFF, - 0x80, 0xC9, 0x01, 0x57, 0x9D, 0x1C, 0xED, 0xDB, 0xDF, 0x7E, 0x2E, 0x5A, 0xB2, 0x3C, 0xB2, 0xE2, - 0x47, 0x11, 0x42, 0x01, 0x4E, 0x28, 0x84, 0xB5, 0x00, 0x74, 0x23, 0xEB, 0x4C, 0x4B, 0x95, 0x39, - 0x8B, 0x8D, 0xC5, 0xA1, 0xDA, 0x61, 0x87, 0x43, 0x80, 0xE2, 0x81, 0xF7, 0xF3, 0xA4, 0x17, 0x00, - 0x5F, 0x72, 0x7C, 0x0E, 0x52, 0x2A, 0x7C, 0x2B, 0xB7, 0x3A, 0xBD, 0xF6, 0xCA, 0x0A, 0xEC, 0xD9, - 0x91, 0xF2, 0xD6, 0x0F, 0x96, 0xD4, 0x57, 0xDC, 0x1D, 0xC6, 0xBF, 0xE9, 0x1E, 0xFA, 0x39, 0x48, - 0xB9, 0x41, 0x38, 0x28, 0x90, 0x41, 0x8A, 0x4C, 0xDE, 0x2E, 0xF7, 0x60, 0xE3, 0x24, 0x70, 0x7D, - 0xD3, 0xD3, 0x0D, 0xF6, 0x0A, 0x57, 0xF3, 0x0A, 0x8D, 0x50, 0x2E, 0xC7, 0x82, 0xC3, 0x5F, 0x4C, - 0xDD, 0x93, 0xF1, 0x11, 0xEE, 0x83, 0x62, 0x23, 0xF5, 0x05, 0x16, 0x73, 0xEE, 0x4A, 0x2F, 0x06, - 0x80, 0x2B, 0xC3, 0x8A, 0x4D, 0xBE, 0x49, 0x89, 0x63, 0xCD, 0x11, 0x72, 0x39, 0xAA, 0x5F, 0x6A, - 0x03, 0x4F, 0x74, 0x00, 0x8E, 0xAD, 0xE7, 0x1B, 0x3F, 0x55, 0x0F, 0x43, 0x58, 0x49, 0x00, 0xE1, - 0x7B, 0x0B, 0xE5, 0x2D, 0x49, 0x0B, 0x41, 0xF4, 0xA0, 0x78, 0x88, 0xE1, 0x2E, 0x85, 0x3B, 0x10, - 0xE0, 0xF0, 0x6A, 0x42, 0x07, 0x63, 0xB3, 0x05, 0xEC, 0x93, 0x45, 0x73, 0x9F, 0x80, 0x74, 0x80, - 0x18, 0x28, 0x79, 0x85, 0xA2, 0xAA, 0xBA, 0x26, 0xEA, 0x2F, 0x6A, 0xDC, 0xE0, 0x41, 0xD2, 0x1D, - 0x5B, 0x30, 0x73, 0x3A, 0x6B, 0x44, 0x64, 0x6E, 0xB0, 0x2E, 0x36, 0xF1, 0xF1, 0x9A, 0x4B, 0x77, - 0x5C, 0x4F, 0x24, 0x55, 0xA6, 0x15, 0xC0, 0xC7, 0x21, 0x26, 0xE1, 0xA1, 0x10, 0x22, 0x41, 0x5B, - 0x40, 0x4E, 0x44, 0x71, 0xF9, 0x16, 0xDD, 0x75, 0xA5, 0x84, 0xF9, 0x8F, 0xAA, 0x3C, 0xBE, 0x1D, - 0xDF, 0xFF, 0x74, 0xCE, 0x5D, 0x81, 0x47, 0x0F, 0xA9, 0x3B, 0x71, 0xF0, 0xCE, 0xF2, 0xEA, 0xE3, - 0x29, 0x19, 0x54, 0x63, 0xD5, 0x76, 0xDA, 0x74, 0xAF, 0xDD, 0x51, 0x42, 0xF9, 0x1B, 0xF8, 0xE4, - 0x23, 0xB6, 0xB0, 0x1A, 0x5B, 0x7F, 0xB8, 0x66, 0x24, 0xBB, 0x06, 0xEB, 0x3B, 0xBA, 0x85, 0xB9, - 0x75, 0x9E, 0xBB, 0x1E, 0x19, 0x59, 0x53, 0xB0, 0xA4, 0x5C, 0xAD, 0x72, 0xA6, 0xDB, 0x0C, 0x2D, - 0x33, 0xBB, 0xDF, 0xD9, 0x4D, 0x8B, 0xC2, 0x35, 0x55, 0xF3, 0x8C, 0x84, 0xFC, 0x2F, 0x49, 0xFF, - 0xAC, 0xA0, 0x80, 0x96, 0x5D, 0x59, 0x2D, 0xA1, 0xA0, 0xE5, 0x5C, 0x98, 0x23, 0xF0, 0x11, 0x49, - 0x28, 0xDC, 0x2B, 0x7D, 0xC8, 0x51, 0x27, 0xCA, 0xA6, 0xFA, 0x19, 0x1B, 0xE2, 0x5E, 0x28, 0xCF, - 0x1D, 0xD0, 0x87, 0x83, 0x19, 0x1B, 0x62, 0x74, 0x9F, 0xC4, 0x38, 0x2C, 0x18, 0xE7, 0xE8, 0xA7, - 0x25, 0x1F, 0x33, 0xF2, 0x88, 0x39, 0x89, 0xA4, 0x7F, 0x90, 0x59, 0x1D, 0x40, 0x32, 0xB3, 0x29, - 0x27, 0x9B, 0x3E, 0x64, 0xA6, 0x25, 0x5C, 0x0B, 0x44, 0xE5, 0x4B, 0xAE, 0xDF, 0xCB, 0x52, 0x27, - 0x94, 0x10, 0x62, 0xA2, 0x98, 0x8F, 0xB2, 0x3A, 0x8B, 0xDB, 0x9A, 0x12, 0x70, 0xE0, 0x86, 0x20, - 0x6E, 0x11, 0xA5, 0x8F, 0x16, 0x89, 0x5C, 0x98, 0x2D, 0x12, 0xE3, 0x56, 0x83, 0xEC, 0x11, 0x57, - 0xFA, 0x44, 0xC7, 0x42, 0x51, 0xF8, 0x52, 0x07, 0xC4, 0xDF, 0xA0, 0xAF, 0x2A, 0xA1, 0xFA, 0x75, - 0x9C, 0x41, 0xF9, 0xBA, 0x67, 0x39, 0xE7, 0xF3, 0x57, 0x72, 0xAF, 0x85, 0xA5, 0x78, 0xEF, 0x55, - 0x39, 0xE7, 0xF3, 0x57, 0x22, 0xD9, 0xEE, 0xAB, 0xA0, 0x93, 0xA8, 0x59, 0xF3, 0x55, 0x92, 0x54, - 0x93, 0xA8, 0x58, 0x5D, 0x57, 0xB4, 0x0B, 0xBA, 0x5C, 0xDA, 0x8D, 0x4F, 0x61, 0x1C, 0xF6, 0x2C, - 0x29, 0x4C, 0x8F, 0x84, 0x65, 0xC7, 0x66, 0x63, 0x0D, 0xF9, 0x91, 0xF0, 0x6F, 0xB6, 0x03, 0x24, - 0x06, 0xD9, 0x8A, 0x2B, 0xEA, 0x38, 0x96, 0x1C, 0x25, 0x40, 0x5B, 0x3A, 0xD5, 0xD1, 0x23, 0x5A, - 0x09, 0x28, 0x06, 0x0B, 0xCC, 0x9B, 0xAA, 0xC3, 0x31, 0x0D, 0x3F, 0xEA, 0x24, 0x41, 0x37, 0xC1, - 0xBB, 0xE4, 0xBC, 0x23, 0x91, 0x9F, 0xCA, 0x5A, 0x7C, 0xC5, 0xF7, 0x64, 0x0D, 0xDA, 0x07, 0x78, - 0xDA, 0xA2, 0x3A, 0x5E, 0x23, 0x2E, 0x32, 0xB0, 0xB8, 0x0A, 0xD2, 0x19, 0x5D, 0xBD, 0xBF, 0x1A, - 0xC0, 0xE7, 0x38, 0x13, 0x7F, 0x55, 0x52, 0x64, 0x5B, 0x9B, 0x18, 0xEF, 0xE8, 0x41, 0x2D, 0x39, - 0xE1, 0xE4, 0x5B, 0x13, 0x2B, 0x2B, 0x09, 0x8C, 0x48, 0x22, 0x65, 0xB0, 0xEF, 0x57, 0x7A, 0xA6, - 0x27, 0x4E, 0xBA, 0xF4, 0x96, 0x21, 0xA8, 0x85, 0xFD, 0x63, 0xC7, 0xA7, 0xF4, 0x6E, 0xBB, 0x71, - 0xDC, 0xCE, 0x97, 0xB2, 0x16, 0x1D, 0xA1, 0xD3, 0x38, 0xEE, 0x2C, 0x77, 0x04, 0xAC, 0x48, 0xBD, - 0xDC, 0x11, 0x40, 0xFF, 0xEB, 0x2D, 0x77, 0x84, 0xBD, 0xC6, 0xF1, 0xDE, 0x72, 0x47, 0xD8, 0x6F, - 0x1C, 0xEF, 0x2F, 0x77, 0x84, 0x83, 0xC6, 0xF1, 0xC1, 0x72, 0x47, 0x78, 0xDD, 0x38, 0x7E, 0x5D, - 0x34, 0x82, 0x53, 0x65, 0xE8, 0x0C, 0x82, 0x93, 0xB6, 0xDD, 0x39, 0x54, 0x9E, 0x50, 0xD5, 0x01, - 0xB6, 0xC4, 0xBD, 0x5B, 0xEB, 0x2C, 0xBB, 0x73, 0xBC, 0x1F, 0xBF, 0xC1, 0xB7, 0x90, 0x13, 0x06, - 0x0F, 0xB3, 0x57, 0xB7, 0xB0, 0x92, 0x71, 0x69, 0xBA, 0x9E, 0xE3, 0xE3, 0x79, 0xF0, 0x24, 0xAA, - 0x05, 0x82, 0x5A, 0x0F, 0xA7, 0xB0, 0x50, 0x55, 0xE8, 0x74, 0x85, 0xE3, 0x72, 0xA6, 0xF3, 0x4A, - 0xB7, 0x57, 0x33, 0xCD, 0x67, 0xB7, 0x60, 0x06, 0x82, 0x09, 0x6D, 0x22, 0xB2, 0xBC, 0xA7, 0xBE, - 0xCC, 0x2A, 0x58, 0xCD, 0x1C, 0x2A, 0x04, 0x79, 0xF7, 0xE8, 0x46, 0x45, 0xB7, 0xFC, 0x52, 0x26, - 0xB4, 0x2A, 0x0E, 0x8F, 0x34, 0x83, 0x89, 0xCD, 0x4D, 0x97, 0x40, 0x1F, 0x9A, 0xD0, 0xF0, 0x8B, - 0x5C, 0x61, 0x39, 0xDA, 0xAA, 0xF8, 0xA2, 0xBE, 0x06, 0x2F, 0xC9, 0x99, 0x99, 0xAE, 0x4A, 0x93, - 0x21, 0x4F, 0x47, 0xDC, 0x2A, 0x34, 0xF8, 0x86, 0xE3, 0x93, 0x61, 0x19, 0x59, 0x0D, 0x68, 0x24, - 0xE8, 0x0F, 0xE3, 0x70, 0x6D, 0xB6, 0xDA, 0xD1, 0x9A, 0x69, 0x1C, 0x55, 0x8D, 0xBB, 0xB5, 0x20, - 0x9A, 0xC8, 0xE2, 0x76, 0xAB, 0xDB, 0x27, 0x06, 0x40, 0xD4, 0xD7, 0x40, 0xBF, 0x90, 0x19, 0xCC, - 0xE0, 0x19, 0x0B, 0x1E, 0x2E, 0x17, 0x85, 0x52, 0xE6, 0xB0, 0x22, 0xEC, 0x91, 0x4B, 0xB5, 0x2D, - 0xDC, 0x4F, 0x58, 0xAF, 0x22, 0x27, 0x10, 0xCD, 0xC3, 0xA6, 0xA0, 0x3B, 0x95, 0xA9, 0x84, 0xDF, - 0xA5, 0x64, 0x29, 0x5F, 0x47, 0x44, 0xAA, 0x7C, 0x6B, 0x2A, 0xD7, 0xD9, 0x1F, 0x83, 0x3A, 0x73, - 0x46, 0x34, 0xF3, 0xC7, 0x64, 0xB2, 0x5C, 0x7F, 0xAC, 0xD4, 0x21, 0x1B, 0x09, 0x9F, 0xA1, 0xBD, - 0x0C, 0x33, 0xCA, 0x89, 0xDC, 0x17, 0x6A, 0x9D, 0xCF, 0x0C, 0xA9, 0x6B, 0xB6, 0x35, 0x99, 0x6C, - 0xAF, 0x3A, 0xAC, 0xE3, 0xA4, 0x4F, 0xC5, 0x62, 0x65, 0x10, 0xAD, 0xA7, 0x98, 0xA0, 0x36, 0x0E, - 0x1D, 0x6B, 0x22, 0xAB, 0x22, 0xBA, 0x3C, 0x08, 0xF2, 0x08, 0xB0, 0x4C, 0x1A, 0x4E, 0x82, 0x3F, - 0x6D, 0x5C, 0x1C, 0x53, 0x69, 0x01, 0x2D, 0x76, 0x8B, 0xF6, 0x17, 0xAA, 0x3D, 0xEB, 0x2B, 0x86, - 0xF1, 0x88, 0x0A, 0x27, 0x7C, 0xA1, 0x05, 0x61, 0xBA, 0xAE, 0xAE, 0xCD, 0xF4, 0x87, 0xF7, 0x61, - 0xE8, 0xBF, 0xAD, 0x18, 0x2A, 0xE6, 0xF3, 0x87, 0x97, 0x35, 0xDF, 0xA1, 0x0B, 0x31, 0xF9, 0x02, - 0x7C, 0xA3, 0xDF, 0x39, 0x32, 0x31, 0xFF, 0xC9, 0xC4, 0xF2, 0x85, 0xC3, 0xB7, 0xA2, 0x69, 0xA2, - 0x18, 0xE3, 0xC7, 0x93, 0x8B, 0xE0, 0xFA, 0x00, 0xE6, 0xEF, 0xD0, 0x65, 0xDA, 0x50, 0xFF, 0x86, - 0x97, 0x0A, 0x0A, 0x3A, 0xAB, 0x01, 0xD7, 0x9F, 0x58, 0x18, 0xBA, 0x7C, 0xE6, 0x1E, 0xB1, 0x5B, - 0xCB, 0x51, 0xC7, 0x5B, 0x9D, 0xCE, 0x01, 0x80, 0xFA, 0x25, 0xF9, 0xAD, 0x49, 0x1C, 0xAC, 0xE2, - 0xB7, 0x56, 0x58, 0x4F, 0x29, 0x1D, 0xF9, 0x4B, 0x19, 0xFF, 0x53, 0x9B, 0xAE, 0xDC, 0x93, 0xAD, - 0x90, 0x95, 0x7C, 0xE4, 0x48, 0x2B, 0x7F, 0xAC, 0x86, 0x89, 0x04, 0x83, 0x55, 0x65, 0x1F, 0xA2, - 0x1D, 0xDB, 0x52, 0x5A, 0x5F, 0x5B, 0x4A, 0x2B, 0x17, 0xFA, 0x7D, 0x3C, 0x26, 0x44, 0xC1, 0xAA, - 0x6D, 0xE0, 0x26, 0xDB, 0xAB, 0x8F, 0x11, 0x13, 0xE4, 0x4F, 0x06, 0x24, 0x51, 0x93, 0x51, 0x52, - 0x3B, 0x50, 0x89, 0x3B, 0x11, 0xC7, 0x18, 0x12, 0x3C, 0x5A, 0x68, 0x75, 0x53, 0x35, 0x7C, 0xA4, - 0x61, 0xCC, 0xCE, 0x6D, 0xBA, 0xB2, 0x5A, 0xB7, 0x15, 0x2D, 0x8B, 0x7D, 0x72, 0xD3, 0xC7, 0x24, - 0xB4, 0xBE, 0x41, 0x81, 0xFF, 0x41, 0x83, 0xA8, 0xFF, 0x69, 0xEB, 0x70, 0xB2, 0x21, 0xE3, 0x52, - 0x64, 0x1C, 0xA2, 0x5F, 0x15, 0x02, 0x0E, 0x1A, 0x3D, 0x2D, 0xE9, 0x66, 0x28, 0xD6, 0x59, 0x9A, - 0xF5, 0xE0, 0x11, 0x44, 0xA3, 0xC9, 0x73, 0xBF, 0xB0, 0x13, 0xAB, 0x98, 0x4B, 0x77, 0x8E, 0x35, - 0x9D, 0x05, 0x71, 0x0C, 0x3E, 0x09, 0x9D, 0xD9, 0x15, 0x4D, 0x9F, 0xFC, 0xF2, 0x2D, 0x67, 0x09, - 0x73, 0x2A, 0xCB, 0xBE, 0x6D, 0x58, 0x8A, 0xF6, 0x89, 0x3F, 0xBC, 0xD7, 0x9D, 0x09, 0x96, 0x48, - 0x3A, 0xD7, 0xEF, 0xCB, 0x54, 0x9A, 0x29, 0xA5, 0xA4, 0xCC, 0x74, 0xDE, 0x38, 0x96, 0x50, 0x0E, - 0x1E, 0x14, 0x64, 0x0B, 0x22, 0x06, 0x45, 0xEE, 0x79, 0xDE, 0xD7, 0xA0, 0xC9, 0xDF, 0xB8, 0x83, - 0x5C, 0xF1, 0x8B, 0x3D, 0x72, 0x14, 0x50, 0x39, 0x32, 0x9D, 0xD6, 0xEE, 0xDB, 0xAD, 0xF6, 0x3C, - 0x76, 0xF0, 0xEC, 0xE3, 0x2E, 0x87, 0xA0, 0xF3, 0xDC, 0x13, 0xCE, 0x10, 0x2E, 0x51, 0x20, 0xCC, - 0xE5, 0xA2, 0x10, 0xDA, 0xEC, 0xD4, 0x44, 0x77, 0x68, 0xA1, 0xA3, 0x21, 0xE8, 0xAA, 0x0F, 0xBE, - 0x08, 0x81, 0x3B, 0xC5, 0xB8, 0x15, 0xA9, 0x65, 0x62, 0x1A, 0x03, 0x5B, 0x71, 0xBE, 0xBE, 0xF7, - 0xE9, 0x32, 0xD1, 0xE5, 0x9C, 0x2E, 0x26, 0x61, 0x56, 0x43, 0x39, 0x2B, 0x92, 0x52, 0xC3, 0x14, - 0xB8, 0xE1, 0xF5, 0xA4, 0xF0, 0x34, 0x5B, 0x2B, 0x8D, 0x2C, 0xC2, 0xF8, 0x83, 0xC9, 0x07, 0x7B, - 0x89, 0x7E, 0x1B, 0x82, 0xC7, 0x3F, 0xAD, 0xA3, 0xD6, 0xCD, 0xD9, 0x94, 0xB4, 0x84, 0x49, 0xE5, - 0x94, 0x7B, 0x4A, 0x04, 0x03, 0x56, 0xE3, 0x81, 0x15, 0x9D, 0xC6, 0x8A, 0x85, 0x2B, 0x5A, 0x6F, - 0x88, 0x5B, 0xC8, 0xF5, 0x15, 0xDD, 0x74, 0xE5, 0x2D, 0x36, 0x5E, 0xD6, 0xB1, 0x21, 0x57, 0x3C, - 0x1F, 0x6F, 0xC8, 0x81, 0x1A, 0xD8, 0x44, 0x79, 0x64, 0xD2, 0x8B, 0x1A, 0xD4, 0x22, 0x98, 0x3A, - 0x0A, 0x57, 0x1E, 0x5E, 0x97, 0x83, 0x3E, 0xC4, 0xF1, 0x18, 0x21, 0x94, 0x1C, 0xEA, 0x1C, 0xA4, - 0x2B, 0x4C, 0x07, 0xB6, 0xEE, 0x6E, 0x56, 0x4F, 0x8B, 0x7F, 0x27, 0xBE, 0x67, 0x05, 0x5B, 0xFF, - 0xC5, 0x86, 0xCD, 0x9C, 0xD6, 0x8F, 0xC7, 0xAF, 0xB0, 0x70, 0x9C, 0x1A, 0x62, 0x63, 0x71, 0xB9, - 0x01, 0xEA, 0x61, 0x65, 0x7E, 0x83, 0x69, 0x93, 0x5F, 0x31, 0xF6, 0x66, 0xC5, 0x06, 0xDA, 0xDC, - 0xD1, 0x2D, 0x4D, 0x57, 0xC9, 0x5C, 0xA0, 0x86, 0xDC, 0x3D, 0xCA, 0x47, 0x5B, 0x0C, 0x1A, 0x2B, - 0xF4, 0xC8, 0x76, 0x2C, 0xCD, 0x17, 0x4E, 0x21, 0xF7, 0xE2, 0x74, 0x4C, 0xE7, 0xB6, 0x3B, 0x78, - 0x8D, 0x1D, 0x38, 0x7C, 0xA0, 0xA9, 0x4C, 0x64, 0x20, 0x53, 0x82, 0x9D, 0xC2, 0xD1, 0x9E, 0x37, - 0xBE, 0xC7, 0x37, 0x97, 0x16, 0x15, 0xDF, 0xE1, 0x45, 0x6A, 0xF4, 0x2D, 0x54, 0xF5, 0x3A, 0xA6, - 0xFA, 0x46, 0x10, 0x8F, 0x4E, 0x94, 0x6B, 0xDD, 0xF4, 0x01, 0xF1, 0xCB, 0x15, 0x86, 0xC9, 0x71, - 0x5D, 0x12, 0xE1, 0x8F, 0xAF, 0x67, 0x94, 0x66, 0xD9, 0x7F, 0x58, 0xDC, 0x9D, 0x30, 0xCA, 0x3D, - 0x7A, 0xE2, 0xB2, 0x36, 0x88, 0xBF, 0x21, 0x93, 0x08, 0x11, 0xD6, 0xA7, 0x7D, 0x42, 0xBC, 0x0D, - 0x29, 0x63, 0x26, 0x11, 0x5E, 0x2A, 0x41, 0x30, 0x65, 0xE8, 0xF1, 0xA8, 0xB3, 0xD3, 0x44, 0xAE, - 0x7A, 0x8C, 0x4E, 0x19, 0x9C, 0xB6, 0x39, 0xA6, 0x25, 0xEF, 0x01, 0xE0, 0xB6, 0x3A, 0xB0, 0x9E, - 0xC7, 0xED, 0xE7, 0x57, 0xF1, 0xA6, 0x64, 0x6D, 0xA7, 0xB2, 0x4A, 0x31, 0x45, 0x36, 0xB8, 0x13, - 0xE0, 0x00, 0x52, 0x3D, 0xCE, 0x42, 0xD1, 0x12, 0x43, 0xDA, 0xB9, 0x3D, 0x2C, 0x52, 0x33, 0x7C, - 0x81, 0x2A, 0x3E, 0x79, 0x3A, 0x37, 0x5E, 0xC7, 0x67, 0x1B, 0xB9, 0x14, 0x43, 0x1F, 0x99, 0xC0, - 0x29, 0xC8, 0x60, 0x27, 0xA0, 0x03, 0x8F, 0x3F, 0x70, 0x2F, 0x26, 0xD3, 0x27, 0xD4, 0x10, 0xD3, - 0x32, 0x73, 0xAF, 0x43, 0xF2, 0x14, 0x86, 0x64, 0xD7, 0x25, 0x62, 0x51, 0x4A, 0xEA, 0x0E, 0xA3, - 0x58, 0xCF, 0xA8, 0x39, 0x08, 0xAE, 0x88, 0xA2, 0xFA, 0x7D, 0xAF, 0xD5, 0xD9, 0x6B, 0x75, 0xF6, - 0xCB, 0x68, 0x0D, 0x02, 0x16, 0xC7, 0x6F, 0xE1, 0xE0, 0x19, 0x51, 0xFC, 0x47, 0x54, 0x46, 0x16, - 0x5D, 0xF6, 0xE5, 0x57, 0xA7, 0x8A, 0x13, 0x1E, 0xBE, 0x9D, 0x6E, 0x03, 0x28, 0xF3, 0x1B, 0x7C, - 0x68, 0xB7, 0x8B, 0xB9, 0x85, 0x84, 0xE8, 0x83, 0xAE, 0x79, 0xE3, 0xA3, 0x5E, 0xBB, 0x4D, 0xD1, - 0x3D, 0x80, 0x22, 0xB2, 0xE3, 0x52, 0x06, 0x9B, 0xF4, 0x39, 0xE5, 0x78, 0x5D, 0xF7, 0x5E, 0xFF, - 0x63, 0x81, 0xE9, 0x46, 0xAE, 0xBD, 0x2E, 0xC3, 0x6B, 0x19, 0xF5, 0x3A, 0xA9, 0x28, 0x96, 0x4C, - 0x95, 0x3B, 0xD4, 0x0D, 0xC0, 0x1E, 0x91, 0xCC, 0xF5, 0x0E, 0x98, 0x14, 0xFD, 0x49, 0xE6, 0x0C, - 0xFF, 0x6E, 0xA2, 0x7B, 0x01, 0x1A, 0xBC, 0xA7, 0xE7, 0x96, 0xA9, 0x92, 0x4F, 0x5B, 0x14, 0x66, - 0xA8, 0xBD, 0xFF, 0xA2, 0xE8, 0x1E, 0xFA, 0xBF, 0xEF, 0x66, 0x0F, 0x2A, 0x5E, 0x64, 0xA7, 0x97, - 0x9F, 0xE6, 0xF0, 0xC9, 0xAC, 0xCD, 0x2F, 0x30, 0xC0, 0x64, 0x38, 0x2B, 0x7C, 0x53, 0xF7, 0x5E, - 0xB9, 0xD3, 0x83, 0xE1, 0xEE, 0x91, 0x09, 0x53, 0x04, 0x5D, 0xA0, 0x30, 0x80, 0x05, 0xD2, 0x0F, - 0xC2, 0x63, 0x7A, 0xA9, 0x13, 0x66, 0xCA, 0x61, 0xF6, 0x18, 0x68, 0x17, 0x03, 0x37, 0xFB, 0x67, - 0xAB, 0x76, 0xD8, 0xCB, 0x76, 0x0C, 0x4A, 0xA2, 0x33, 0xAE, 0xA6, 0x6A, 0xF0, 0x40, 0x16, 0x76, - 0xA6, 0xB2, 0xBF, 0x50, 0x9C, 0x82, 0xFE, 0xBD, 0x81, 0x87, 0xA2, 0x53, 0x85, 0x42, 0xC4, 0x51, - 0x69, 0x27, 0xEC, 0x20, 0xB4, 0xFE, 0x5C, 0xC2, 0xFE, 0x60, 0x81, 0x2D, 0x7A, 0x5A, 0x29, 0x27, - 0xF1, 0xB4, 0xAF, 0xF8, 0xDC, 0x16, 0xCD, 0x43, 0xDC, 0x6E, 0x1C, 0xDF, 0x58, 0x94, 0x8A, 0xA4, - 0x62, 0x2A, 0xE2, 0x4E, 0xE3, 0xF8, 0x54, 0x71, 0x79, 0xE5, 0x76, 0x00, 0xB8, 0x4F, 0xB7, 0xFD, - 0xF5, 0xC8, 0x60, 0xDC, 0xF7, 0x65, 0x28, 0xB1, 0xD8, 0x1D, 0xDD, 0x84, 0xD3, 0xC0, 0xB1, 0x28, - 0x02, 0x59, 0x5C, 0x75, 0x3A, 0x0C, 0xE6, 0x2A, 0x5C, 0x33, 0x82, 0x78, 0xBC, 0x3E, 0xC5, 0xE3, - 0x7D, 0x36, 0xF1, 0x4B, 0xF2, 0x0F, 0x6B, 0xAD, 0x7D, 0x78, 0xB1, 0x61, 0x8D, 0x6E, 0xAD, 0xC1, - 0xF9, 0x99, 0x92, 0x99, 0x10, 0x7C, 0xE9, 0x8E, 0x41, 0x61, 0xE9, 0x79, 0xAC, 0xFD, 0x0E, 0x50, - 0x1E, 0x9C, 0x33, 0x9C, 0xCE, 0x2A, 0x3C, 0x7D, 0x8A, 0xAB, 0xDE, 0xD7, 0x6B, 0x0B, 0x24, 0xE5, - 0x74, 0xA2, 0xAB, 0x0E, 0x80, 0x9C, 0x6C, 0xD1, 0x8C, 0x8C, 0x7C, 0x1E, 0xF1, 0xD8, 0x1D, 0xCC, - 0x74, 0x16, 0x96, 0xC8, 0x4B, 0xD4, 0x7A, 0x9E, 0x75, 0xF8, 0x79, 0x56, 0xFE, 0x3E, 0x33, 0x20, - 0x2F, 0x52, 0x39, 0xCB, 0x5B, 0x70, 0xCA, 0xEA, 0x9B, 0x51, 0xEE, 0x0B, 0xF2, 0x16, 0xCC, 0xE3, - 0x16, 0x23, 0x10, 0xE6, 0xD2, 0x1C, 0x95, 0x6F, 0x4C, 0xAE, 0xA3, 0x50, 0x60, 0xC3, 0x41, 0xD8, - 0x16, 0x68, 0x5D, 0xDB, 0x47, 0xD5, 0x4C, 0x08, 0x8B, 0x6B, 0x95, 0x81, 0x5F, 0x10, 0xFA, 0x69, - 0x20, 0x2B, 0x83, 0x55, 0x23, 0x36, 0x51, 0x62, 0x04, 0x32, 0x81, 0xA8, 0x63, 0x9D, 0xDF, 0x23, - 0xE2, 0x19, 0x62, 0x31, 0x52, 0x91, 0xE4, 0xE4, 0x0B, 0x31, 0xF5, 0xCF, 0xE0, 0x43, 0x9F, 0xE0, - 0xC6, 0x0C, 0x0C, 0x76, 0xC1, 0xF7, 0x0C, 0x0B, 0x7E, 0x80, 0xC0, 0x37, 0xD9, 0xA1, 0xBC, 0x4C, - 0x26, 0xCE, 0x69, 0x87, 0x8A, 0x3C, 0x82, 0xD2, 0xEA, 0xFA, 0xCE, 0x3D, 0x7F, 0x74, 0x91, 0x94, - 0x15, 0xE8, 0xCC, 0x41, 0xDB, 0x63, 0xF4, 0x8A, 0x17, 0x46, 0x4F, 0x2A, 0x9C, 0x52, 0x29, 0x0D, - 0xC3, 0x69, 0x3A, 0xD8, 0xB8, 0x7B, 0x78, 0x38, 0xFD, 0x66, 0x9E, 0xF2, 0xD1, 0x75, 0xEA, 0xA1, - 0xE5, 0x8C, 0x35, 0xE5, 0x4D, 0x74, 0x95, 0x75, 0xCF, 0x08, 0xCA, 0x96, 0x12, 0xF2, 0xA7, 0xEF, - 0x2F, 0x78, 0x21, 0xBB, 0x0A, 0x4A, 0x14, 0x7E, 0x08, 0x8B, 0xD0, 0x62, 0xE1, 0x06, 0xA2, 0x40, + 0x1F, 0x8B, 0x08, 0x08, 0x17, 0x68, 0x78, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, + 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x07, 0x49, 0x96, 0xF5, + 0x6C, 0x9D, 0x43, 0x4D, 0xB6, 0xFA, 0x49, 0x36, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, + 0x01, 0x49, 0x12, 0x4F, 0x20, 0x80, 0x8B, 0x41, 0xB2, 0x6E, 0x9D, 0xAA, 0x53, 0xCB, 0xE8, 0x5E, + 0x48, 0x6F, 0xA0, 0x97, 0x52, 0x2B, 0xE9, 0x88, 0xC8, 0x04, 0x08, 0x80, 0x00, 0x01, 0x90, 0x20, + 0x45, 0xCA, 0xF4, 0x7B, 0x57, 0x12, 0x41, 0xE4, 0x14, 0x19, 0x11, 0x19, 0x11, 0x19, 0xC3, 0x87, + 0x7F, 0x38, 0xFF, 0x7A, 0x76, 0xF7, 0x6B, 0xEF, 0x82, 0x8D, 0xBC, 0xB1, 0x71, 0xF2, 0xD3, 0x07, + 0xFC, 0xC5, 0x0C, 0xC5, 0x1C, 0x7E, 0xAC, 0x71, 0xB3, 0x76, 0xF2, 0x13, 0x3C, 0xE1, 0x8A, 0x76, + 0xF2, 0x13, 0x83, 0x7F, 0x1F, 0xC6, 0xDC, 0x53, 0x98, 0x3A, 0x52, 0x1C, 0x97, 0x7B, 0x1F, 0x6B, + 0xBE, 0x37, 0xA8, 0x1F, 0xD5, 0xD8, 0x5E, 0xF4, 0xCB, 0x91, 0xE7, 0xD9, 0x75, 0xFE, 0x87, 0xAF, + 0x3F, 0x7E, 0xAC, 0xFD, 0x52, 0xFF, 0xD6, 0xAD, 0x9F, 0x59, 0x63, 0x5B, 0xF1, 0xF4, 0x7B, 0x83, + 0xD7, 0x98, 0x6A, 0x99, 0x1E, 0x37, 0xA1, 0xE5, 0xD5, 0xC5, 0x47, 0xAE, 0x0D, 0xF9, 0xAE, 0x3A, + 0x72, 0xAC, 0x31, 0xFF, 0xD8, 0x9A, 0x74, 0xE2, 0xE9, 0x9E, 0xC1, 0x4F, 0xFA, 0xB6, 0xE2, 0x3C, + 0x5C, 0xFA, 0x26, 0xBB, 0xBD, 0xFB, 0x2B, 0xEB, 0x73, 0xCF, 0xB7, 0x3F, 0xEC, 0x89, 0x6F, 0x22, + 0x43, 0x99, 0x0A, 0x34, 0xAD, 0x3D, 0xEA, 0xFC, 0xC9, 0xB6, 0x1C, 0xAF, 0x46, 0xDF, 0xE0, 0xBF, + 0x70, 0x94, 0x27, 0x5D, 0xF3, 0x46, 0x1F, 0x35, 0xFE, 0xA8, 0xAB, 0xBC, 0x4E, 0x1F, 0x76, 0x99, + 0x6E, 0xEA, 0x9E, 0xAE, 0x18, 0x75, 0x57, 0x55, 0x0C, 0x18, 0x78, 0x97, 0x8D, 0x95, 0xEF, 0xFA, + 0xD8, 0x1F, 0x4F, 0x1E, 0xF8, 0x2E, 0x77, 0xE8, 0x93, 0x02, 0x73, 0xFE, 0xD8, 0xDC, 0x65, 0xEE, + 0xC8, 0xD1, 0xCD, 0x87, 0xBA, 0x67, 0xD5, 0x07, 0xBA, 0xF7, 0xF1, 0x99, 0xBB, 0x93, 0xD9, 0x1A, + 0xF0, 0x05, 0x73, 0xB8, 0xF1, 0xB1, 0xE6, 0x7A, 0xCF, 0x06, 0x77, 0x47, 0x9C, 0x7B, 0x35, 0x36, + 0x72, 0xF8, 0x00, 0x9E, 0x38, 0xEA, 0xDE, 0xBD, 0x65, 0x79, 0xAE, 0xE7, 0x28, 0x76, 0x63, 0xAC, + 0x9B, 0x0D, 0xD5, 0x75, 0x6B, 0x05, 0x1B, 0xD2, 0xD3, 0x68, 0x03, 0x57, 0x75, 0x74, 0xDB, 0x63, + 0xF0, 0x9D, 0x78, 0xE1, 0xEF, 0x7F, 0xF8, 0xDC, 0x79, 0xAE, 0x77, 0x1A, 0x87, 0x8D, 0x26, 0x75, + 0xFE, 0x77, 0x78, 0xF5, 0xC3, 0x9E, 0x78, 0x2D, 0xA3, 0x4D, 0x7C, 0x36, 0xA5, 0x1A, 0xDC, 0xFB, + 0xA6, 0x06, 0x13, 0x9A, 0x6E, 0x17, 0x6D, 0x78, 0x12, 0x6E, 0xC1, 0x7F, 0xD9, 0xD1, 0x2C, 0xD5, + 0x1F, 0xC3, 0x2E, 0xBC, 0x6D, 0x58, 0xE6, 0xCE, 0x1B, 0xD5, 0xD0, 0xD5, 0x87, 0x37, 0xBB, 0xEC, + 0x4D, 0xC3, 0xB3, 0x86, 0x43, 0x83, 0xD7, 0xEF, 0x3D, 0x13, 0x3E, 0x0E, 0x7C, 0x53, 0xF5, 0x74, + 0xCB, 0x64, 0x3B, 0xFC, 0x2D, 0xFB, 0xD7, 0xB0, 0xB5, 0xE8, 0x01, 0x96, 0xEF, 0x3B, 0x0E, 0x74, + 0x71, 0xA7, 0x38, 0x43, 0xEE, 0x35, 0xD4, 0x91, 0x6E, 0x68, 0xF0, 0xF9, 0x7F, 0x34, 0xFF, 0xE7, + 0x5B, 0xD9, 0xCD, 0x99, 0xA1, 0xB8, 0xEE, 0xCE, 0x1B, 0x1D, 0x76, 0xBC, 0xAE, 0x2A, 0x0E, 0xF7, + 0xEA, 0x9A, 0xF5, 0x64, 0xB2, 0xC8, 0x67, 0xDF, 0x7E, 0xF3, 0xF6, 0x2F, 0x61, 0xC7, 0xFF, 0xF6, + 0x56, 0x4C, 0x37, 0x39, 0x7B, 0x04, 0xF6, 0x64, 0xF2, 0x0D, 0xD7, 0x03, 0x84, 0x55, 0xEB, 0x43, + 0xC7, 0xF2, 0xED, 0xC4, 0xB4, 0x46, 0x5C, 0x1F, 0x8E, 0xBC, 0x63, 0xD6, 0xFC, 0x4B, 0xEC, 0xB1, + 0xF5, 0xC8, 0x9D, 0x81, 0x61, 0x3D, 0x1D, 0xB3, 0x91, 0xAE, 0x69, 0xDC, 0x8C, 0x7F, 0x0B, 0x10, + 0x34, 0x5D, 0x1D, 0x17, 0x7A, 0x2C, 0x3B, 0x60, 0xCD, 0xC6, 0xBE, 0xCB, 0xB8, 0xE2, 0xF2, 0xF8, + 0x9B, 0xF7, 0x96, 0xA3, 0x01, 0xF6, 0xDD, 0x5B, 0x9E, 0x67, 0x8D, 0x8F, 0x99, 0x6B, 0x19, 0xBA, + 0xC6, 0x5A, 0xF6, 0x77, 0xF6, 0x8F, 0x6A, 0x13, 0xFF, 0x17, 0x59, 0xCA, 0x4F, 0x93, 0xF9, 0x1A, + 0xBA, 0xEB, 0xAD, 0xF7, 0x6C, 0xF1, 0x9F, 0xAD, 0x68, 0x9A, 0x6E, 0x0E, 0xEB, 0x8E, 0x98, 0xD3, + 0x41, 0xD3, 0xFE, 0x9E, 0xBE, 0x1C, 0xD1, 0x2D, 0x10, 0x85, 0xCB, 0x3C, 0x6D, 0x37, 0xFD, 0xF9, + 0x28, 0xB1, 0x52, 0xF1, 0xDD, 0x31, 0x33, 0x2D, 0x33, 0x31, 0xC9, 0x31, 0x60, 0x8F, 0x6E, 0xD6, + 0x0D, 0x3E, 0x40, 0x40, 0x64, 0x8C, 0x79, 0xEF, 0xC3, 0x12, 0xCC, 0xE3, 0x01, 0x20, 0xAD, 0x9B, + 0xE8, 0xD9, 0xF2, 0x3D, 0x20, 0x56, 0x1E, 0x03, 0x62, 0x74, 0xB6, 0xBA, 0x89, 0x5F, 0x5F, 0x38, + 0x8E, 0xE5, 0x24, 0x5A, 0x6A, 0xBA, 0x6B, 0x1B, 0xCA, 0xF3, 0x31, 0x13, 0xAF, 0xC4, 0xA7, 0xA5, + 0x5A, 0x86, 0x05, 0xF3, 0x75, 0xB8, 0x16, 0x7F, 0x3E, 0x00, 0xE6, 0x55, 0x77, 0xF5, 0x3F, 0x61, + 0x40, 0x77, 0xAC, 0x18, 0x06, 0x77, 0x66, 0x0D, 0xDB, 0xF7, 0x55, 0x15, 0xE1, 0x51, 0x7E, 0xE0, + 0xA1, 0xC3, 0x93, 0x1B, 0x3F, 0x6B, 0xE8, 0xF0, 0xFB, 0x27, 0x89, 0x52, 0xF7, 0x96, 0xA1, 0x65, + 0x6D, 0xDF, 0xF7, 0x3A, 0xB5, 0x4F, 0xCC, 0x2A, 0x7B, 0x23, 0xF0, 0x1F, 0xB1, 0xE7, 0x63, 0xD6, + 0x69, 0xFE, 0xD7, 0xEC, 0x5E, 0x45, 0x0F, 0xED, 0xE6, 0xAC, 0x8E, 0xDB, 0x33, 0xD0, 0x2A, 0xE8, + 0x61, 0x7F, 0x66, 0x0F, 0xFB, 0xD9, 0x3D, 0x28, 0x9E, 0x07, 0x4C, 0x37, 0xD1, 0xD8, 0xB6, 0x02, + 0x6A, 0x51, 0xEE, 0x81, 0x04, 0x7C, 0x2F, 0x01, 0xF0, 0x3F, 0xEB, 0xBA, 0xA9, 0xF1, 0xEF, 0xC7, + 0xAC, 0xD5, 0x6C, 0x26, 0x48, 0x42, 0x92, 0x42, 0x6B, 0x0A, 0x1A, 0x70, 0x28, 0xD5, 0x25, 0x44, + 0x0E, 0x9B, 0x29, 0xDF, 0xD2, 0x74, 0x3D, 0xCB, 0x06, 0x32, 0x8A, 0x4F, 0x56, 0xB2, 0x37, 0xC1, + 0xD0, 0x3E, 0xEC, 0x89, 0xA3, 0xFB, 0xA7, 0x0F, 0xF7, 0x96, 0xF6, 0x2C, 0x79, 0xBC, 0xA6, 0x3F, + 0x32, 0x15, 0xF9, 0xE6, 0xC7, 0x1A, 0x1E, 0x94, 0x0A, 0x20, 0x88, 0x53, 0x63, 0xBA, 0xF6, 0xB1, + 0x26, 0x97, 0x77, 0x05, 0x8F, 0x6B, 0x13, 0x6E, 0x48, 0x0D, 0x14, 0x43, 0x1F, 0x9A, 0x1F, 0x6B, + 0x34, 0xDF, 0x5A, 0xD0, 0x5C, 0xBE, 0x1F, 0x79, 0x97, 0xDE, 0xD7, 0xC7, 0xC3, 0x64, 0x77, 0x97, + 0xBA, 0xC1, 0xBF, 0xC0, 0x69, 0x5D, 0x9B, 0x1C, 0x2D, 0xA7, 0xE2, 0xDB, 0x53, 0x90, 0x34, 0x1E, + 0x1A, 0xB6, 0x39, 0xAC, 0xC1, 0x18, 0x70, 0x64, 0xCB, 0xC7, 0xCC, 0xE0, 0x8F, 0xDC, 0xA8, 0x9D, + 0x00, 0x6F, 0xB6, 0x15, 0x33, 0xDA, 0x5D, 0x8F, 0x3B, 0x2A, 0x9C, 0x09, 0xB5, 0xD8, 0x98, 0x84, + 0xD7, 0x62, 0x52, 0x84, 0x79, 0x30, 0x0E, 0x42, 0xE0, 0x63, 0x2D, 0xA0, 0x04, 0x49, 0x08, 0x74, + 0x70, 0x41, 0x87, 0x91, 0xD5, 0xED, 0xC1, 0xF2, 0x24, 0x64, 0xC4, 0x9F, 0xB3, 0xA0, 0x94, 0xE8, + 0x95, 0x98, 0x4D, 0x74, 0x37, 0x08, 0xF9, 0x26, 0x7B, 0x27, 0xB6, 0x4E, 0x00, 0xD7, 0xE1, 0x20, + 0x32, 0x5D, 0x99, 0x3D, 0xC7, 0x42, 0x82, 0x8D, 0xC2, 0xF7, 0xFE, 0xE4, 0x16, 0xBF, 0xF3, 0x80, + 0x37, 0x7E, 0xD8, 0xBB, 0x3F, 0xF9, 0x70, 0xEF, 0xD0, 0x7F, 0x28, 0xF9, 0x08, 0xD1, 0x85, 0xE9, + 0x2E, 0xF0, 0x09, 0x3C, 0x8B, 0xE1, 0x95, 0x06, 0xEB, 0x19, 0xC8, 0x89, 0xD9, 0x93, 0xA2, 0x7B, + 0x8D, 0x46, 0x63, 0x55, 0x53, 0x47, 0x31, 0xCE, 0xE0, 0x1E, 0x4F, 0x99, 0x39, 0x3B, 0x87, 0xCE, + 0x32, 0xA6, 0x3E, 0x52, 0x5C, 0xE0, 0xC9, 0x4F, 0x8C, 0xFA, 0x58, 0xC5, 0x64, 0x07, 0xBA, 0x33, + 0x7E, 0x82, 0xA3, 0xFF, 0x9B, 0x6D, 0x58, 0x8A, 0x96, 0x3E, 0xEB, 0xE4, 0x7C, 0x2F, 0x65, 0x1B, + 0xE6, 0xDB, 0x9A, 0xE2, 0x71, 0x60, 0x91, 0xA2, 0x55, 0x83, 0xC5, 0x37, 0x41, 0x2C, 0x24, 0xD8, + 0x88, 0x82, 0x8B, 0x39, 0xF9, 0x29, 0x95, 0x94, 0x10, 0x89, 0x71, 0xA9, 0xE1, 0xFB, 0x20, 0x92, + 0x8E, 0xEB, 0xAD, 0x36, 0xA0, 0x28, 0x12, 0x50, 0x48, 0x27, 0x8E, 0xF7, 0x50, 0x77, 0x51, 0x00, + 0x8E, 0x10, 0x49, 0x4C, 0x3A, 0xFE, 0x59, 0xBF, 0xD4, 0x85, 0x88, 0x8C, 0xD8, 0x1D, 0x99, 0x4D, + 0x61, 0x30, 0x47, 0x00, 0xDB, 0xCA, 0x06, 0xEC, 0x18, 0x1A, 0xF5, 0x94, 0x21, 0x2F, 0xB8, 0x20, + 0xC7, 0x7A, 0x9A, 0xDA, 0xC7, 0x7B, 0xC3, 0x52, 0x1F, 0xFE, 0x12, 0xED, 0x20, 0xA7, 0x13, 0x71, + 0x8C, 0x20, 0x5B, 0x4E, 0x30, 0x19, 0xFC, 0x87, 0x8B, 0xBF, 0x00, 0x49, 0xE6, 0xF9, 0x69, 0xC4, + 0x61, 0xEF, 0x82, 0x4D, 0x3C, 0x8E, 0xF0, 0x0C, 0x00, 0x5E, 0xF0, 0xF8, 0x6F, 0xDC, 0x71, 0x81, + 0x49, 0x67, 0x73, 0x86, 0xC7, 0x66, 0xA3, 0x29, 0xB9, 0x03, 0xE2, 0xC4, 0xD4, 0x70, 0x93, 0x5E, + 0x87, 0xA6, 0xEB, 0x16, 0xEE, 0xF6, 0xD3, 0x97, 0x7E, 0x3F, 0x32, 0xB7, 0xC8, 0x28, 0x2C, 0x67, + 0x18, 0x81, 0x77, 0xA7, 0x77, 0x57, 0xE7, 0xD9, 0xBD, 0x9F, 0x0B, 0xDC, 0x3C, 0x35, 0x7C, 0xEE, + 0x01, 0x5A, 0x8E, 0xD8, 0xD5, 0x39, 0x9C, 0xAD, 0xF0, 0xAF, 0xE0, 0x18, 0xAA, 0x05, 0x72, 0x93, + 0x6E, 0x02, 0xD2, 0xBB, 0xD7, 0xD7, 0x9F, 0xB3, 0xC7, 0xB9, 0xBE, 0x1E, 0x1D, 0x4F, 0x75, 0x93, + 0x80, 0x0A, 0xB7, 0x34, 0x0E, 0x62, 0xF3, 0xB5, 0xE2, 0x65, 0xF7, 0xB3, 0x0F, 0xCB, 0x7F, 0xDF, + 0x6C, 0xBF, 0xDF, 0x7F, 0xF7, 0x5E, 0xCE, 0x70, 0xB7, 0x68, 0xB7, 0xB3, 0x80, 0x5C, 0x6F, 0x35, + 0x0F, 0x1A, 0xAD, 0xA3, 0x83, 0xE6, 0xC1, 0xBB, 0xC3, 0x56, 0xC9, 0x8E, 0xBB, 0xC6, 0x8C, 0xF9, + 0xB6, 0x0E, 0x0E, 0x61, 0xC6, 0x47, 0xC1, 0x64, 0xD9, 0x4E, 0xB7, 0x77, 0xF6, 0x76, 0x1A, 0x9E, + 0x85, 0xD0, 0x26, 0x02, 0xEB, 0x8B, 0xB3, 0x8B, 0xCB, 0xEC, 0x41, 0xF1, 0xDB, 0x3C, 0x68, 0x73, + 0x95, 0x0F, 0x7E, 0x99, 0x05, 0x90, 0xF6, 0x51, 0xB3, 0xDD, 0x3C, 0x6C, 0x1C, 0x1C, 0x1E, 0x15, + 0x84, 0x07, 0xF6, 0xF8, 0xEB, 0x8C, 0x1E, 0xF7, 0xDF, 0xB5, 0x0E, 0x8F, 0x9A, 0xFB, 0x8D, 0xFD, + 0x66, 0xA7, 0x44, 0x8F, 0xBF, 0xCD, 0xC2, 0x85, 0xA3, 0xC3, 0xC3, 0xC3, 0x83, 0xC6, 0xFE, 0xD1, + 0x7E, 0xF2, 0x54, 0xCE, 0x03, 0x6C, 0x94, 0xB7, 0xA5, 0x7E, 0x1E, 0x39, 0x01, 0x0B, 0x19, 0x7B, + 0xF5, 0x66, 0x52, 0x9A, 0x99, 0xE6, 0x7B, 0x74, 0xA0, 0x4C, 0x31, 0xA6, 0x7F, 0xA8, 0xD7, 0x59, + 0x3D, 0xF8, 0xC7, 0xE0, 0xE8, 0x1E, 0x80, 0x1C, 0xC3, 0xCE, 0x2C, 0x73, 0xA0, 0x0F, 0x23, 0x5F, + 0xD4, 0xEB, 0x27, 0xD3, 0x0C, 0x4D, 0x0E, 0xAF, 0x81, 0x5E, 0x06, 0x4A, 0xD1, 0x50, 0xB1, 0xEB, + 0xED, 0x14, 0x1E, 0xF6, 0x41, 0x28, 0x1E, 0xA1, 0x44, 0xE5, 0x99, 0x0C, 0xFE, 0xAB, 0xDB, 0x8E, + 0x0E, 0x93, 0x7B, 0x66, 0x13, 0x65, 0x59, 0xF0, 0x60, 0x5B, 0x4C, 0x41, 0xCC, 0xA0, 0xC6, 0xBC, + 0x67, 0x1B, 0x96, 0x21, 0xBA, 0xA8, 0x31, 0x38, 0xBA, 0x94, 0xBA, 0x68, 0x41, 0xE7, 0x89, 0xA1, + 0xD8, 0x2E, 0xAF, 0xA5, 0xEE, 0x91, 0x78, 0x95, 0xD4, 0xEA, 0x8F, 0xB5, 0x7F, 0x0C, 0xDE, 0xED, + 0xC5, 0x7B, 0x57, 0x1C, 0x5D, 0xA9, 0xF3, 0xEF, 0xB0, 0x01, 0x1A, 0xC7, 0x83, 0x55, 0x31, 0xA0, + 0x3B, 0xF1, 0x14, 0xCF, 0x10, 0xC7, 0x32, 0xDC, 0xC9, 0x38, 0xF1, 0xB6, 0x27, 0xA9, 0xA3, 0xC6, + 0x01, 0xE8, 0x3B, 0x0A, 0xA9, 0xFE, 0x1F, 0xF4, 0xD8, 0xD2, 0x50, 0x6B, 0x9F, 0x9C, 0x8A, 0xA4, + 0xC3, 0xA3, 0x3A, 0xCF, 0xEE, 0x75, 0x96, 0x50, 0xF3, 0xF1, 0xB8, 0xD3, 0xD3, 0x70, 0x46, 0x00, + 0x24, 0x15, 0x63, 0xB2, 0xB6, 0x29, 0x58, 0x06, 0x1B, 0xDF, 0xC3, 0x3E, 0x49, 0x72, 0x2D, 0xB6, + 0x32, 0xC2, 0x92, 0xD4, 0xBE, 0xDC, 0x11, 0xC8, 0x0B, 0xB9, 0x1D, 0x4E, 0xA1, 0xCF, 0xD4, 0xDC, + 0x14, 0x47, 0x63, 0xF8, 0xA3, 0x8E, 0x52, 0x7C, 0x12, 0x49, 0xD3, 0x5A, 0x0C, 0x2C, 0x67, 0x2C, + 0xED, 0x01, 0x80, 0xFE, 0xED, 0x8C, 0xED, 0x88, 0x6C, 0xC9, 0x71, 0xE6, 0x0B, 0x82, 0x9A, 0x65, + 0xBF, 0x9E, 0x27, 0xB1, 0xEC, 0xDE, 0xAD, 0x03, 0x2D, 0xAB, 0x7C, 0x4C, 0x66, 0x36, 0xA1, 0x15, + 0x64, 0x76, 0x41, 0x36, 0x05, 0xB4, 0xDD, 0x81, 0xE0, 0xC2, 0x0D, 0xAE, 0x7A, 0x4C, 0x61, 0x72, + 0xB7, 0x19, 0xE0, 0x16, 0xE8, 0xF2, 0xDC, 0x64, 0xD0, 0x3F, 0x08, 0x00, 0x4C, 0xCA, 0xC1, 0xA0, + 0xE0, 0x5B, 0xF0, 0x5C, 0xF1, 0x82, 0x17, 0x1B, 0xAC, 0xEB, 0x09, 0x19, 0x72, 0x37, 0x2A, 0x93, + 0x3D, 0xE9, 0x20, 0x1E, 0xF8, 0x08, 0x6A, 0xEA, 0x98, 0x6B, 0x93, 0xF7, 0x03, 0x64, 0x53, 0x47, + 0x8A, 0x39, 0xE4, 0x2E, 0x43, 0xF1, 0xCE, 0x55, 0x1E, 0xE1, 0x95, 0x27, 0x1A, 0x0F, 0x94, 0xE4, + 0xC1, 0x80, 0xA3, 0x79, 0x29, 0x9C, 0x0C, 0x48, 0x78, 0x61, 0x3F, 0xA0, 0xCC, 0xD3, 0x7B, 0x6F, + 0xFA, 0xD0, 0x26, 0x8E, 0xB1, 0x6F, 0xF0, 0x45, 0x1B, 0x26, 0xE3, 0x72, 0xAD, 0x31, 0x03, 0xB6, + 0x53, 0xE0, 0x23, 0xFC, 0xD5, 0xCD, 0x81, 0x55, 0x57, 0x75, 0x47, 0x85, 0x01, 0x3D, 0xFE, 0xDD, + 0x0B, 0x69, 0x7D, 0xEC, 0xE2, 0x4E, 0x65, 0x71, 0xC2, 0x04, 0x47, 0x4C, 0x47, 0x81, 0x04, 0x17, + 0x2C, 0x80, 0x1E, 0x28, 0xA5, 0x9D, 0xE4, 0x6C, 0x7E, 0x3A, 0xFF, 0x8E, 0xE9, 0xCC, 0x01, 0xFB, + 0x9C, 0x09, 0x0A, 0xDD, 0xB4, 0x7D, 0x4F, 0xF2, 0x2C, 0x47, 0xD1, 0x74, 0xAB, 0x26, 0x2D, 0xB8, + 0x12, 0xFE, 0xB7, 0xE2, 0xD9, 0xA3, 0x02, 0xC2, 0xCC, 0xC7, 0x5A, 0x33, 0xAF, 0x3B, 0x43, 0xB9, + 0xE7, 0x46, 0x94, 0x75, 0x34, 0x49, 0xC3, 0x3C, 0x91, 0x1B, 0x0F, 0x62, 0x00, 0xBD, 0xB1, 0x10, + 0x28, 0x5F, 0x05, 0x24, 0x5B, 0xA5, 0x21, 0xD9, 0x12, 0x90, 0x6C, 0xB5, 0x3B, 0xFB, 0x07, 0x87, + 0xEF, 0x8E, 0xDE, 0x37, 0x27, 0x7F, 0x6D, 0xA1, 0x2A, 0xA1, 0xDA, 0x2E, 0x0D, 0xD5, 0xB6, 0x80, + 0xEA, 0x16, 0x82, 0x12, 0x82, 0x9D, 0xD2, 0x10, 0xEC, 0x6C, 0x21, 0x18, 0x83, 0xE0, 0x7E, 0x69, + 0x08, 0xEE, 0x6F, 0x21, 0x18, 0x83, 0xE0, 0x41, 0x69, 0x08, 0x1E, 0x6C, 0x21, 0x18, 0x83, 0xE0, + 0x61, 0x69, 0x08, 0x1E, 0x6E, 0x21, 0x18, 0x83, 0xE0, 0xBB, 0xD2, 0x10, 0x7C, 0x57, 0x1D, 0x04, + 0x2B, 0x04, 0xA1, 0x98, 0x26, 0xBC, 0x1F, 0xCE, 0x53, 0x98, 0xFC, 0x03, 0xDD, 0x36, 0x7A, 0x81, + 0x23, 0xCD, 0x9D, 0x1D, 0xFA, 0x63, 0x9F, 0x7E, 0xD2, 0x40, 0xD4, 0x47, 0x28, 0xC3, 0xCD, 0x04, + 0x0B, 0x76, 0x7E, 0x9C, 0x0F, 0x82, 0xB8, 0x62, 0x86, 0x83, 0x1E, 0xD1, 0x70, 0xEF, 0xCA, 0x6C, + 0x22, 0x0A, 0xEA, 0xB5, 0x18, 0x44, 0xA4, 0x06, 0x1C, 0x53, 0xCB, 0xC5, 0xAE, 0xCC, 0xEE, 0xD5, + 0x4E, 0x36, 0xA0, 0x8B, 0xC3, 0xB0, 0xEF, 0xC8, 0x65, 0x22, 0xEE, 0xAF, 0x3D, 0x6B, 0x6F, 0x33, + 0x29, 0x60, 0x7A, 0xA0, 0x33, 0x52, 0x82, 0x6E, 0x40, 0x65, 0x41, 0x03, 0x6E, 0x7C, 0x30, 0x79, + 0x85, 0x38, 0x63, 0xB8, 0xEA, 0x51, 0x65, 0xDA, 0x08, 0x23, 0xEF, 0x90, 0x0F, 0x0A, 0x50, 0x97, + 0x34, 0x99, 0xC4, 0x8D, 0x1F, 0x74, 0x43, 0xE4, 0x99, 0x74, 0x1F, 0x21, 0xB1, 0xA7, 0x96, 0x65, + 0x55, 0x49, 0xC5, 0xC4, 0xD9, 0xFA, 0x2B, 0x5D, 0x04, 0x9B, 0x67, 0xE8, 0xC5, 0x30, 0x35, 0xCE, + 0xCE, 0xDB, 0x9A, 0xBC, 0x07, 0x91, 0x0F, 0xD2, 0x2D, 0x10, 0x4B, 0xD2, 0xAC, 0x23, 0xDA, 0xB5, + 0x98, 0x44, 0x52, 0x15, 0x46, 0x55, 0x7A, 0xA0, 0xA8, 0x9E, 0x05, 0x2B, 0xD7, 0xF8, 0x40, 0xF1, + 0x0D, 0xCF, 0xCD, 0x53, 0x5B, 0x97, 0xA2, 0xBA, 0xE6, 0x71, 0xA4, 0xE2, 0x58, 0xED, 0x44, 0xA0, + 0x7F, 0xE3, 0x0E, 0x2B, 0x43, 0xE8, 0x34, 0x23, 0x51, 0xCA, 0xAB, 0x09, 0xBB, 0x20, 0x59, 0xF8, + 0x57, 0x68, 0x14, 0x1C, 0x7B, 0xC0, 0x37, 0xA3, 0x96, 0xC1, 0x8A, 0xCD, 0x80, 0xB8, 0x9E, 0xB9, + 0x6C, 0x80, 0x91, 0x86, 0xE9, 0x70, 0x8F, 0x40, 0x2A, 0x61, 0xFD, 0xC3, 0x2B, 0x95, 0x17, 0x36, + 0xFD, 0xC5, 0x8D, 0x74, 0x33, 0xD7, 0x92, 0x6D, 0x9D, 0x63, 0xB6, 0x57, 0x6F, 0xCD, 0x34, 0xD1, + 0xD1, 0x55, 0x1A, 0x57, 0x5C, 0xDF, 0x21, 0x1A, 0xBF, 0x55, 0x3C, 0x7E, 0x85, 0x27, 0xCD, 0x0C, + 0x8A, 0xBC, 0x99, 0xBC, 0xCE, 0xF0, 0xFD, 0xE3, 0x42, 0xA7, 0xDD, 0x6C, 0x16, 0x9C, 0x71, 0x36, + 0xB6, 0x89, 0x1F, 0xB6, 0xDA, 0x48, 0xD2, 0x1D, 0x36, 0x61, 0xE8, 0x45, 0xF8, 0x45, 0xE4, 0xFC, + 0x4F, 0x2C, 0xF0, 0xF3, 0x9F, 0xB1, 0x7B, 0xCE, 0xE8, 0x49, 0x7F, 0x65, 0xE6, 0x76, 0x8C, 0xFF, + 0x3E, 0xFF, 0x79, 0x5C, 0xE8, 0xBD, 0x0A, 0x99, 0x6A, 0x82, 0xB9, 0xDE, 0x8D, 0x38, 0x33, 0xFD, + 0xF1, 0x3D, 0x77, 0x98, 0x35, 0x60, 0xE4, 0xE7, 0x01, 0xF8, 0xEB, 0xA2, 0xA1, 0xD0, 0xB0, 0x54, + 0x81, 0xCC, 0xFF, 0xF9, 0x1F, 0xFF, 0x7B, 0xA0, 0x7F, 0xE7, 0xEE, 0x7F, 0xFE, 0xC7, 0xFF, 0x61, + 0x36, 0xBC, 0xE8, 0x72, 0x40, 0x5B, 0xAD, 0xC1, 0xBA, 0xE6, 0xB3, 0x37, 0xD2, 0xCD, 0x21, 0x53, + 0xEE, 0xAD, 0x47, 0xCE, 0xF6, 0x3F, 0xFF, 0x09, 0x32, 0xE5, 0x33, 0x60, 0x0D, 0x9A, 0x2E, 0x27, + 0x77, 0x77, 0xF0, 0xF2, 0x90, 0xBB, 0xD4, 0x13, 0xD0, 0xDB, 0x1E, 0xF5, 0x3C, 0x1C, 0x62, 0x3B, + 0x90, 0x48, 0x55, 0x87, 0xC3, 0xD2, 0x54, 0x9D, 0xBB, 0x0D, 0xF6, 0xC5, 0x02, 0x24, 0x60, 0x38, + 0xA3, 0x08, 0xA0, 0x99, 0x83, 0x57, 0xD7, 0xBA, 0x4B, 0xDE, 0x5D, 0x0E, 0xF9, 0x75, 0x21, 0xEB, + 0x6F, 0xC1, 0x60, 0x64, 0xC9, 0xD4, 0x4D, 0x76, 0x8A, 0x7E, 0x03, 0x63, 0x4B, 0xE3, 0x0D, 0x76, + 0x2E, 0x4E, 0x82, 0x63, 0x9C, 0x4C, 0x83, 0x5D, 0xEB, 0x63, 0x1D, 0x9D, 0x72, 0x1A, 0xCD, 0x66, + 0xB3, 0xD5, 0x6E, 0x53, 0xBB, 0x26, 0x7C, 0x51, 0x60, 0xDB, 0x97, 0x7A, 0x5C, 0x14, 0x3D, 0x36, + 0x26, 0xEF, 0xE5, 0x88, 0x83, 0x05, 0xCE, 0x98, 0x0C, 0xCA, 0x10, 0x42, 0xEA, 0xC1, 0x3C, 0x84, + 0x11, 0x95, 0x24, 0x05, 0x0A, 0xA5, 0xCA, 0x92, 0x91, 0xAB, 0x82, 0x69, 0xFA, 0x29, 0x30, 0x8C, + 0x9D, 0xDE, 0x74, 0x5E, 0x01, 0x33, 0x4F, 0xF2, 0x8B, 0x8C, 0x1B, 0xBB, 0xAD, 0x27, 0x00, 0xE1, + 0xAD, 0x1B, 0xAE, 0xA7, 0x09, 0x83, 0xF0, 0xF1, 0x89, 0xE5, 0x7C, 0xD8, 0x83, 0x5F, 0x34, 0xDE, + 0x7A, 0xB0, 0xA4, 0x3E, 0x57, 0x6B, 0x27, 0x7D, 0xA2, 0x4F, 0x97, 0xDD, 0x73, 0xEF, 0x89, 0x03, + 0x89, 0x44, 0xDE, 0x71, 0xD7, 0x8C, 0xDF, 0xCC, 0x98, 0x69, 0x03, 0x38, 0x01, 0x90, 0xBD, 0xC0, + 0x32, 0x1D, 0x7D, 0x23, 0x81, 0x0D, 0x98, 0xC0, 0x04, 0x80, 0xD8, 0xA1, 0xA9, 0x97, 0xC6, 0x26, + 0xF0, 0xDE, 0x05, 0x5E, 0x05, 0xFE, 0x33, 0xF0, 0x0D, 0xC1, 0x1F, 0x3C, 0xE5, 0x81, 0x58, 0x54, + 0xEC, 0x65, 0x8E, 0xFE, 0x15, 0x6C, 0xC0, 0x9F, 0xC2, 0x19, 0x28, 0xAA, 0x63, 0xB9, 0xF0, 0x0B, + 0x78, 0x13, 0xBC, 0x0D, 0x2F, 0x3E, 0xF2, 0x67, 0xB6, 0xD3, 0xDE, 0xFF, 0x6F, 0x6C, 0x64, 0xF9, + 0x8E, 0xFB, 0xB6, 0x0A, 0xEE, 0x14, 0xB2, 0xA3, 0x16, 0xBE, 0x73, 0xD4, 0x7A, 0x7F, 0x18, 0x0C, + 0x0F, 0x1C, 0x89, 0x40, 0x5E, 0x18, 0x9A, 0x11, 0xCF, 0xB0, 0x2D, 0x53, 0xAA, 0x94, 0x29, 0x11, + 0x05, 0xCD, 0xC9, 0x95, 0xA0, 0x6D, 0x05, 0x6C, 0x69, 0x8E, 0xAF, 0xE7, 0x54, 0x65, 0x85, 0x3F, + 0xCE, 0xB3, 0xA9, 0x8C, 0x75, 0xF5, 0x06, 0x30, 0xD4, 0x38, 0x77, 0x2C, 0x5B, 0x08, 0xA2, 0x85, + 0xEC, 0x21, 0xD1, 0xA6, 0xB5, 0xD4, 0x3D, 0x3C, 0x9C, 0xB2, 0x81, 0x9C, 0x8B, 0x36, 0x8C, 0x1A, + 0x1D, 0xAF, 0x58, 0x95, 0xEC, 0x6A, 0x7F, 0xF7, 0x5D, 0x2F, 0xE0, 0x25, 0x1E, 0x77, 0x4C, 0xC5, + 0x60, 0x8A, 0x31, 0xB4, 0x1C, 0xDD, 0x1B, 0x8D, 0x91, 0x2A, 0xC7, 0x8A, 0xA7, 0x8E, 0xE8, 0x7B, + 0x50, 0x0F, 0x84, 0xC2, 0xA9, 0xD8, 0x36, 0x28, 0xC8, 0x42, 0x14, 0xE2, 0xE6, 0xA3, 0xEE, 0x58, + 0x26, 0x8E, 0x2D, 0xF9, 0x93, 0xBC, 0xDA, 0x65, 0xFA, 0x18, 0x14, 0xD3, 0x47, 0x2E, 0xFA, 0x76, + 0xB8, 0xCA, 0x75, 0xE0, 0x08, 0x6F, 0x5C, 0x31, 0x8C, 0x0D, 0x12, 0xBE, 0xE8, 0x00, 0x38, 0x57, + 0x94, 0xC9, 0xC9, 0x9B, 0x62, 0x1F, 0x6F, 0x5E, 0xAD, 0x47, 0x5D, 0xC3, 0x1B, 0x5D, 0x60, 0x16, + 0x0E, 0xB0, 0x32, 0x55, 0xF5, 0x89, 0xB9, 0x04, 0x7E, 0xB8, 0xE8, 0xB1, 0x0D, 0xB8, 0xDD, 0x40, + 0xA7, 0x38, 0x1A, 0x31, 0x3A, 0x10, 0x4E, 0x1D, 0x60, 0xE5, 0x9B, 0xAE, 0xAF, 0x7B, 0x18, 0xE0, + 0xC1, 0x00, 0x46, 0x1E, 0xC2, 0x9D, 0x58, 0x0F, 0xED, 0x17, 0x35, 0x18, 0xC2, 0xDB, 0x66, 0xD6, + 0x92, 0x90, 0x91, 0x19, 0xFA, 0x03, 0x37, 0xD0, 0x45, 0x03, 0xEF, 0xA5, 0x41, 0x94, 0x42, 0x16, + 0x86, 0x5C, 0x11, 0x98, 0x23, 0xCC, 0x3D, 0x1C, 0x0F, 0xE4, 0x40, 0xEC, 0x1D, 0x44, 0x37, 0xC1, + 0x75, 0xC3, 0x59, 0x8A, 0x79, 0xAB, 0xCF, 0xEB, 0xAB, 0x8A, 0x97, 0x37, 0xAD, 0x49, 0x5C, 0xCE, + 0xBD, 0x14, 0x17, 0x6E, 0x00, 0xC2, 0x26, 0x1A, 0xA7, 0x8D, 0x24, 0xA1, 0xC5, 0x99, 0x92, 0x26, + 0xC9, 0x4E, 0x70, 0xA5, 0xDC, 0xF5, 0xD1, 0x30, 0x2B, 0xE7, 0x13, 0x63, 0xDD, 0xBC, 0x30, 0xF8, + 0xE3, 0x4C, 0x4D, 0x78, 0x6E, 0xD3, 0xD9, 0x94, 0x58, 0x23, 0x06, 0x2B, 0xCA, 0x54, 0x6E, 0x00, + 0x49, 0xFB, 0x7F, 0x63, 0xD8, 0x84, 0x90, 0xFA, 0xF8, 0xA7, 0x15, 0x4B, 0x38, 0x92, 0xBF, 0xC0, + 0x3C, 0x30, 0xE8, 0x8A, 0xF1, 0x60, 0x22, 0x48, 0x3D, 0x1A, 0xC7, 0xA0, 0x04, 0x97, 0x48, 0x50, + 0x11, 0xC6, 0x02, 0x17, 0x08, 0xDB, 0x30, 0x74, 0x8F, 0xAC, 0x58, 0xF7, 0x1C, 0x05, 0x16, 0x4D, + 0x10, 0x1A, 0x28, 0x5A, 0x45, 0xD5, 0x93, 0xA5, 0xA9, 0x26, 0xC5, 0xC8, 0xAC, 0xC8, 0xE9, 0x3F, + 0x2F, 0x29, 0x95, 0x39, 0xCA, 0x63, 0xD8, 0x59, 0xE2, 0xE8, 0x16, 0x0D, 0x36, 0xEF, 0xBC, 0x86, + 0x89, 0x9F, 0x7D, 0xF9, 0xBA, 0x32, 0x32, 0x84, 0xB1, 0xCA, 0x50, 0xE1, 0xD9, 0xDE, 0x97, 0xE6, + 0x4B, 0x53, 0xDF, 0x84, 0xBA, 0xD0, 0xF9, 0x4A, 0x31, 0x44, 0xD4, 0x45, 0x2A, 0xA9, 0x4D, 0x0C, + 0x06, 0x87, 0xDA, 0x29, 0x08, 0xED, 0x48, 0xA3, 0xBF, 0x5D, 0x9C, 0xD7, 0x2F, 0xDF, 0xF7, 0xE8, + 0x58, 0x6B, 0x35, 0xC3, 0xC7, 0xDF, 0x6E, 0xDE, 0x1F, 0x35, 0xB7, 0xB4, 0x39, 0x1F, 0x6D, 0x22, + 0x16, 0x95, 0x21, 0x4D, 0x78, 0x7F, 0x63, 0x28, 0x13, 0x0D, 0xD7, 0x81, 0x95, 0xD5, 0x74, 0x11, + 0xF5, 0x88, 0xF5, 0x9F, 0x8D, 0xB8, 0xFA, 0x70, 0x6A, 0x7D, 0xE7, 0x6E, 0x41, 0x69, 0x9A, 0x8C, + 0xC5, 0xD1, 0x1E, 0xA0, 0x61, 0xFC, 0x73, 0x81, 0x7B, 0xC1, 0x4A, 0xFD, 0x1A, 0xEF, 0xA2, 0x12, + 0x26, 0xC8, 0x86, 0xAA, 0x62, 0x93, 0x6C, 0x09, 0x82, 0x20, 0x2C, 0x55, 0x86, 0xB1, 0x82, 0xB0, + 0x28, 0xDE, 0x41, 0x99, 0x54, 0x10, 0x1C, 0x9C, 0x75, 0x8E, 0x05, 0x92, 0x27, 0x10, 0x96, 0x6E, + 0x1B, 0x7C, 0x42, 0x90, 0xA1, 0x9E, 0x1D, 0x7E, 0x15, 0x03, 0x19, 0xE8, 0xFC, 0x7D, 0x6B, 0xCC, + 0xA3, 0xE2, 0xA9, 0xCB, 0x34, 0x5D, 0xF5, 0x50, 0x0E, 0x46, 0xE9, 0xD5, 0xE4, 0x40, 0xBC, 0xE8, + 0x43, 0xE9, 0x3B, 0x28, 0x4A, 0xC3, 0x34, 0xB8, 0x83, 0x51, 0x1F, 0xF1, 0x6E, 0x68, 0x3E, 0x36, + 0xFE, 0x85, 0xF4, 0x2D, 0xC4, 0x25, 0x61, 0x03, 0x10, 0xD2, 0x6F, 0xFC, 0x65, 0x72, 0xB6, 0x14, + 0x36, 0xCB, 0xA4, 0x44, 0x0D, 0x8B, 0x41, 0x51, 0xDC, 0x1B, 0x59, 0x2E, 0x0F, 0x97, 0x06, 0xB2, + 0x3C, 0x74, 0x12, 0x48, 0xE0, 0x63, 0xB1, 0xD4, 0x7B, 0x8E, 0x9F, 0x89, 0xB7, 0x68, 0xBE, 0x83, + 0x7F, 0x87, 0x02, 0xB1, 0xAA, 0x18, 0xAA, 0x1F, 0xAE, 0x2F, 0xE4, 0x37, 0x5D, 0x18, 0x95, 0x9B, + 0x08, 0xCE, 0xF5, 0xF2, 0xB6, 0x8C, 0x59, 0xF4, 0x63, 0x90, 0x3A, 0xE5, 0xFA, 0xB9, 0xE5, 0x27, + 0xE8, 0x1C, 0x91, 0x5C, 0x5C, 0xDD, 0x44, 0xAF, 0x1F, 0x8B, 0x1D, 0x31, 0x53, 0x1D, 0xC9, 0x83, + 0x44, 0x90, 0x43, 0x6C, 0xEC, 0xDF, 0xE5, 0xE0, 0x27, 0xE2, 0x77, 0x31, 0x0E, 0x27, 0x98, 0xD4, + 0xF4, 0x28, 0xF4, 0x3C, 0xB8, 0x5F, 0xA2, 0x47, 0x30, 0xF7, 0xD0, 0x6F, 0x21, 0x85, 0x94, 0xC3, + 0xD1, 0xE7, 0xBE, 0xE0, 0x4B, 0x05, 0xE8, 0x27, 0xC5, 0xD0, 0x0D, 0x6E, 0xBD, 0x10, 0x44, 0x83, + 0xD1, 0x4F, 0xE4, 0x1F, 0xAB, 0x86, 0x69, 0x38, 0x7E, 0xC5, 0x40, 0x35, 0x2C, 0x13, 0x26, 0xF7, + 0x52, 0x40, 0xBD, 0xFE, 0xFA, 0xA5, 0xDB, 0xEF, 0x03, 0x50, 0xC5, 0x1F, 0x2B, 0x07, 0x6A, 0x30, + 0x7E, 0xC5, 0x40, 0xB5, 0x5F, 0x0C, 0xA0, 0x3D, 0x04, 0x66, 0x6F, 0xF5, 0x80, 0xEC, 0x55, 0x0E, + 0xC4, 0x2F, 0xCA, 0xA3, 0xAE, 0xBE, 0x10, 0x18, 0x61, 0xEC, 0xAB, 0xB3, 0xDA, 0xC9, 0x97, 0xEE, + 0xDF, 0xAE, 0xCE, 0x56, 0x0D, 0x4A, 0x39, 0x76, 0xB5, 0xC0, 0xFC, 0x97, 0x3F, 0x5F, 0x8C, 0xC6, + 0xFF, 0xE5, 0x37, 0x24, 0x30, 0xFC, 0xB9, 0x6A, 0x48, 0x8A, 0x91, 0xAB, 0x05, 0x64, 0xFF, 0x5E, + 0x79, 0x29, 0x40, 0xF6, 0x4F, 0xBB, 0xB0, 0x1C, 0xFC, 0xB9, 0x6A, 0x40, 0x8A, 0x91, 0x17, 0x02, + 0xE4, 0x5C, 0xAA, 0xB5, 0x3D, 0xF1, 0x0A, 0x89, 0xC9, 0xBD, 0x4B, 0xF0, 0x96, 0xCB, 0x55, 0x64, + 0x68, 0x26, 0xE2, 0x0C, 0xFE, 0xAC, 0xB8, 0xD2, 0xA8, 0x5C, 0xC6, 0xA0, 0x30, 0xC1, 0x93, 0x2A, + 0x50, 0x43, 0xC8, 0xC2, 0x9F, 0xC2, 0x09, 0xD5, 0x4E, 0x2E, 0xE8, 0x09, 0x93, 0x8F, 0xD8, 0xE7, + 0x6E, 0x7F, 0xEF, 0xE2, 0x30, 0x57, 0x87, 0x3C, 0xB3, 0x40, 0x2B, 0xA1, 0xEC, 0x3B, 0xEE, 0xF2, + 0xB1, 0x6A, 0x7A, 0xD2, 0x2B, 0xBE, 0xD0, 0xF8, 0x06, 0x8A, 0xC9, 0x67, 0x68, 0xC1, 0xBA, 0xD2, + 0xEC, 0xCE, 0xFA, 0xDC, 0xA1, 0x18, 0x32, 0x75, 0x02, 0x87, 0xE0, 0x6E, 0x41, 0xA3, 0x5B, 0x4A, + 0xD2, 0x72, 0x02, 0xA0, 0xC6, 0xC8, 0x22, 0xA2, 0x9D, 0x5C, 0x14, 0xD3, 0x4C, 0xD6, 0xD1, 0xA1, + 0xAE, 0x94, 0x06, 0x5F, 0x08, 0x87, 0x4B, 0xE0, 0xEF, 0x17, 0xCF, 0xD1, 0xED, 0x33, 0x43, 0xC7, + 0x54, 0x1E, 0x01, 0x02, 0x7F, 0xB9, 0xBB, 0xBD, 0xEA, 0x31, 0xF1, 0x30, 0x5F, 0x81, 0x5F, 0x1C, + 0x1D, 0x63, 0x73, 0x58, 0x91, 0xA5, 0xE0, 0x1B, 0x69, 0xCF, 0xBA, 0x2B, 0x17, 0xAB, 0xD2, 0xE8, + 0xA8, 0x42, 0xE3, 0xB5, 0x06, 0x66, 0xAC, 0x88, 0xE0, 0x23, 0x8D, 0x24, 0xD4, 0x66, 0x05, 0xB4, + 0x63, 0x97, 0x54, 0x69, 0x57, 0xA0, 0x6D, 0x83, 0xFD, 0x6A, 0xF9, 0x4E, 0x10, 0x07, 0x39, 0xF6, + 0x5D, 0x0F, 0x6D, 0x76, 0x4F, 0x3A, 0xFA, 0x19, 0x89, 0x94, 0x10, 0x0E, 0xBA, 0xFC, 0x32, 0xC5, + 0x63, 0xE8, 0x94, 0xE1, 0xE9, 0x63, 0x1E, 0x55, 0xAA, 0xCF, 0x75, 0x77, 0xFD, 0x34, 0xEA, 0x42, + 0x9C, 0xD8, 0x9C, 0x6C, 0x5A, 0xE0, 0xA4, 0x98, 0x1A, 0xC3, 0xBB, 0x64, 0x83, 0x6F, 0x74, 0x1A, + 0xB0, 0x33, 0xDC, 0xF9, 0x6C, 0xB9, 0x5E, 0x01, 0x5F, 0xF7, 0x83, 0x29, 0x63, 0xB0, 0x68, 0x9E, + 0xCB, 0x3D, 0xB0, 0xFF, 0xE3, 0x79, 0x0D, 0x96, 0x47, 0xF3, 0x19, 0x2C, 0x73, 0xDC, 0xDE, 0xD3, + 0x61, 0x50, 0xD8, 0x7A, 0x99, 0xDA, 0x7C, 0xF9, 0xC6, 0xCC, 0x15, 0xE3, 0x45, 0x0F, 0x53, 0x13, + 0x2E, 0x11, 0x2F, 0xB0, 0xFF, 0x55, 0xE3, 0x45, 0xAE, 0x21, 0x3B, 0x1D, 0x0A, 0xF3, 0x63, 0x06, + 0x36, 0x7F, 0x75, 0x98, 0x01, 0x47, 0x81, 0xB3, 0x4C, 0xCC, 0xC0, 0xFE, 0xD7, 0x9D, 0x63, 0x10, + 0x0C, 0xE6, 0xC7, 0x0B, 0x6C, 0xFE, 0x2A, 0xF1, 0xA2, 0xF7, 0x73, 0xBE, 0x64, 0x3B, 0x03, 0x73, + 0xB2, 0x2E, 0x1E, 0x4B, 0x60, 0x0E, 0xEB, 0xFD, 0x3C, 0x37, 0xF2, 0xBC, 0x13, 0x88, 0xBB, 0x0A, + 0xE4, 0x01, 0x40, 0x2D, 0x86, 0x3E, 0xBD, 0x9F, 0x5F, 0x11, 0x02, 0xDD, 0x58, 0xBE, 0xE9, 0xF5, + 0x2C, 0xDD, 0x9C, 0xEF, 0xC8, 0xA1, 0xE6, 0x05, 0x4E, 0x1C, 0xE8, 0x7F, 0x7D, 0x19, 0x4B, 0x04, + 0x06, 0xF3, 0x60, 0xC6, 0xA4, 0xF9, 0xAB, 0xC4, 0x8B, 0x25, 0x31, 0x96, 0x12, 0x98, 0x93, 0xFF, + 0xD6, 0x1A, 0x33, 0x9E, 0x18, 0x20, 0x17, 0x43, 0xAF, 0xF5, 0x62, 0x3C, 0xA1, 0x7E, 0xDF, 0xAA, + 0xDC, 0x96, 0x19, 0x59, 0xFD, 0x1D, 0xA6, 0x16, 0x1E, 0xEB, 0xDE, 0xA7, 0x4F, 0xDD, 0xDA, 0x49, + 0xF0, 0x81, 0xC1, 0x27, 0xD4, 0x80, 0x05, 0x4F, 0x5E, 0xBE, 0x2D, 0x2A, 0x63, 0x3E, 0xB9, 0x9B, + 0xE9, 0x9B, 0xD4, 0x21, 0xD7, 0x56, 0x6D, 0xBB, 0xA2, 0xAB, 0x7E, 0x95, 0xA0, 0x83, 0x89, 0x40, + 0xFF, 0xF0, 0x75, 0x74, 0x7B, 0x85, 0xBF, 0x86, 0xBE, 0xA1, 0x38, 0x93, 0x0B, 0x74, 0x99, 0xBD, + 0x92, 0x0C, 0x06, 0x74, 0x43, 0x4F, 0x56, 0xAC, 0x1D, 0x04, 0xEF, 0x58, 0x84, 0xFE, 0xBE, 0x65, + 0xAE, 0xCC, 0xAB, 0x84, 0xDF, 0x8B, 0x2E, 0xE1, 0x97, 0xC9, 0x14, 0xDF, 0xB3, 0xC6, 0x98, 0xF4, + 0x5A, 0x31, 0x8C, 0x67, 0x19, 0x42, 0x2A, 0x1D, 0x09, 0x14, 0x87, 0xBB, 0x1E, 0x53, 0x1E, 0x15, + 0x9D, 0x12, 0xA2, 0x27, 0xED, 0x13, 0x29, 0x46, 0x85, 0xD7, 0x68, 0x0B, 0x13, 0x4E, 0xEC, 0x04, + 0x44, 0x74, 0x60, 0x3F, 0x15, 0xC1, 0x96, 0x33, 0xC6, 0x92, 0x31, 0x9C, 0x61, 0xD0, 0xF0, 0x90, + 0x7B, 0x32, 0xFE, 0xFA, 0x5A, 0x77, 0xBD, 0x9D, 0xB7, 0x53, 0xD1, 0xC9, 0x63, 0x8D, 0x7E, 0xC9, + 0x74, 0xD3, 0x99, 0xD1, 0x9E, 0xB3, 0x8D, 0x4C, 0x05, 0x22, 0x41, 0x73, 0xA3, 0x3E, 0x31, 0xA2, + 0x76, 0xE6, 0x28, 0x73, 0x06, 0x85, 0x62, 0xBF, 0xB3, 0x37, 0x50, 0x02, 0x88, 0x82, 0x1C, 0xDD, + 0x68, 0x68, 0x28, 0x34, 0x5D, 0x3C, 0x3A, 0x74, 0xB2, 0xD7, 0x79, 0xE1, 0xD9, 0xC5, 0x49, 0x38, + 0x89, 0x17, 0x57, 0x80, 0xC5, 0x77, 0x78, 0x9A, 0x14, 0xB1, 0x05, 0x7E, 0xB9, 0xB9, 0xE8, 0x92, + 0xF3, 0xDC, 0x6D, 0xF7, 0xE7, 0x5F, 0x28, 0x41, 0x19, 0x52, 0x9C, 0xF7, 0x64, 0xB1, 0xB1, 0x05, + 0x24, 0xA7, 0x5A, 0xE3, 0xB1, 0x65, 0x92, 0xD7, 0x10, 0xD6, 0x37, 0x40, 0x87, 0x1E, 0xD8, 0x5E, + 0x57, 0x78, 0xC6, 0x0B, 0x40, 0xDD, 0xFB, 0x5E, 0xDC, 0x17, 0xC7, 0xF5, 0x6D, 0x7C, 0xD7, 0x15, + 0xAE, 0xF1, 0x40, 0xE9, 0x26, 0x7B, 0xD7, 0x8C, 0xA4, 0x3A, 0x93, 0x0D, 0xDD, 0x06, 0xBB, 0x50, + 0xD4, 0x51, 0xD8, 0x8F, 0x08, 0xCE, 0x11, 0x3C, 0x55, 0xEE, 0x20, 0x7B, 0x1A, 0xE9, 0x93, 0x37, + 0x44, 0xFE, 0x34, 0x4D, 0x12, 0x38, 0xDB, 0x69, 0xBE, 0xA5, 0x89, 0x63, 0x82, 0x3B, 0x6B, 0xE0, + 0x61, 0x2C, 0x0F, 0x85, 0xFB, 0x88, 0xDE, 0x28, 0x5D, 0xB1, 0x9C, 0xF2, 0x4E, 0x8B, 0x7D, 0x04, + 0x22, 0x98, 0x7C, 0x19, 0x7E, 0x83, 0x01, 0x92, 0x2D, 0xF4, 0x2D, 0xDC, 0x65, 0x07, 0xF2, 0x1D, + 0xF1, 0x9D, 0x0C, 0x3A, 0x3A, 0x60, 0x14, 0x4B, 0xF9, 0x36, 0xC2, 0x60, 0x08, 0x60, 0xC0, 0xCE, + 0x76, 0xD9, 0xA7, 0x3E, 0xFD, 0xB8, 0xC3, 0x1F, 0x7F, 0xDB, 0x15, 0x40, 0xBC, 0x39, 0x93, 0x81, + 0x8C, 0xEE, 0x31, 0x6B, 0xE2, 0x81, 0xD2, 0x6E, 0x6E, 0x64, 0x7A, 0xB6, 0xBC, 0x80, 0xE4, 0xD9, + 0x74, 0x34, 0x23, 0x73, 0x60, 0x4A, 0xDE, 0xCB, 0x83, 0x94, 0xB4, 0x97, 0xA9, 0x3D, 0xCE, 0x9B, + 0xAD, 0x21, 0xCA, 0x0B, 0xA7, 0x33, 0x36, 0x98, 0x63, 0xAE, 0xC8, 0xDD, 0x75, 0xB3, 0xD2, 0x35, + 0x14, 0xF3, 0x6C, 0x0D, 0xF9, 0x2C, 0xE5, 0x06, 0xB8, 0xB3, 0xFA, 0x14, 0x98, 0xA6, 0x9B, 0xC3, + 0xA0, 0xFB, 0x49, 0x96, 0x06, 0xC0, 0x8C, 0xF0, 0xDB, 0x00, 0xB7, 0xDC, 0x82, 0x39, 0x1B, 0x0A, + 0x46, 0x69, 0x2D, 0x07, 0x5A, 0x32, 0x1A, 0x78, 0x39, 0x00, 0xBB, 0x8E, 0x77, 0x1E, 0x03, 0x97, + 0xFC, 0x6E, 0x09, 0xC0, 0x4A, 0xCB, 0x98, 0x9B, 0x7E, 0xF6, 0x5A, 0xAE, 0xA2, 0xAB, 0xC8, 0x00, + 0xFA, 0x9E, 0xC3, 0x95, 0x71, 0x10, 0x80, 0xE5, 0x16, 0x81, 0x68, 0x56, 0x27, 0xAD, 0x02, 0x61, + 0x5C, 0x59, 0xDA, 0x95, 0x4B, 0x3D, 0x5C, 0x61, 0xD0, 0x12, 0x48, 0x97, 0xD8, 0xE7, 0xEF, 0x20, + 0x2D, 0x13, 0x87, 0x92, 0x9D, 0x8B, 0x88, 0x26, 0xF8, 0xF2, 0xB8, 0x98, 0xA3, 0xF1, 0x84, 0x29, + 0x45, 0xC3, 0x63, 0x52, 0xC7, 0xA1, 0xD5, 0xA4, 0x7E, 0x53, 0x38, 0x30, 0x72, 0xDE, 0xB0, 0x9A, + 0xD8, 0x4C, 0x2D, 0x72, 0x1E, 0x8D, 0xA4, 0x6C, 0x6C, 0x35, 0xC7, 0x80, 0x1D, 0xE2, 0xF1, 0xDC, + 0xFD, 0xB4, 0x6A, 0x27, 0xED, 0x2A, 0xFA, 0x69, 0x63, 0x8E, 0xE1, 0x0A, 0xFA, 0xE9, 0xD4, 0x4E, + 0x0E, 0xAA, 0xE8, 0x67, 0x1F, 0xE1, 0x53, 0x45, 0x47, 0x07, 0x08, 0xA0, 0x2A, 0x3A, 0x3A, 0xC4, + 0x95, 0x55, 0xD1, 0xD1, 0x3B, 0x58, 0xDA, 0xE2, 0xBD, 0x1C, 0xC1, 0xBA, 0x16, 0xEF, 0xE5, 0x3D, + 0x2C, 0xAA, 0x02, 0x24, 0x24, 0x6C, 0xAE, 0xA0, 0x9F, 0x16, 0x66, 0x11, 0xAF, 0xA0, 0x1F, 0xC0, + 0xE6, 0x4E, 0x15, 0xF3, 0x01, 0x6C, 0x3E, 0xAC, 0xA2, 0x1F, 0xC0, 0xE6, 0xF6, 0x58, 0x37, 0x17, + 0xEF, 0x08, 0xB0, 0xF9, 0xA0, 0x92, 0x8E, 0x0E, 0x89, 0xFF, 0x54, 0xD1, 0x13, 0xA2, 0x73, 0x35, + 0x73, 0x3A, 0xC2, 0x5D, 0xAB, 0xA4, 0xA7, 0xF7, 0xB8, 0x6F, 0xA5, 0x7B, 0xCA, 0x8F, 0x82, 0x5C, + 0x92, 0xED, 0x22, 0x69, 0xC3, 0x98, 0x98, 0x14, 0x82, 0x63, 0x91, 0x82, 0x85, 0xA2, 0x07, 0xE6, + 0xA6, 0x65, 0x1B, 0x29, 0x24, 0xC1, 0x14, 0x94, 0x84, 0x66, 0xCA, 0x29, 0xED, 0x6A, 0xE5, 0x94, + 0x56, 0x4C, 0x4E, 0x69, 0x2F, 0x4D, 0x4E, 0x69, 0x65, 0xCA, 0x29, 0xAD, 0xAD, 0x9C, 0xB2, 0x95, + 0x53, 0xB6, 0x72, 0xCA, 0x56, 0x4E, 0xD9, 0xCA, 0x29, 0x5B, 0x39, 0x65, 0xD3, 0xE4, 0x94, 0xF6, + 0xE6, 0x65, 0x45, 0xCB, 0x37, 0xC4, 0x14, 0x34, 0x6C, 0x45, 0xCC, 0xDD, 0x78, 0x8D, 0x81, 0xA6, + 0xC3, 0xE5, 0xC6, 0x17, 0x17, 0x78, 0x1C, 0xD8, 0x55, 0x67, 0xE5, 0xE8, 0xA4, 0xDC, 0x52, 0x2F, + 0x99, 0xA3, 0x53, 0x54, 0x30, 0x74, 0x97, 0x55, 0xBA, 0xE7, 0x34, 0xD2, 0x75, 0xA9, 0xEB, 0x99, + 0x48, 0xC3, 0x8C, 0x7D, 0x40, 0x40, 0xA6, 0xD4, 0xE3, 0xCB, 0x28, 0x5C, 0x83, 0xFF, 0x22, 0xC0, + 0x4E, 0xA4, 0xF9, 0x24, 0x08, 0xAC, 0x53, 0x9A, 0xCF, 0x99, 0xCB, 0x9F, 0xB3, 0x08, 0x0F, 0xC9, + 0xBC, 0x64, 0x60, 0xBE, 0x32, 0x45, 0xA6, 0xEF, 0x5C, 0x2F, 0xF6, 0x58, 0xAA, 0xF0, 0x00, 0x50, + 0x77, 0xF0, 0xB0, 0x2F, 0xFB, 0x09, 0x12, 0x88, 0x07, 0xCF, 0xE3, 0xDE, 0x0A, 0xB2, 0x61, 0xEE, + 0xF5, 0x74, 0x54, 0x2F, 0x98, 0x1A, 0xE1, 0x44, 0xFC, 0x55, 0xBF, 0x32, 0x57, 0x1C, 0x3C, 0x7F, + 0x25, 0x72, 0xD4, 0xD9, 0x0E, 0x57, 0x75, 0x40, 0x9C, 0x30, 0x9B, 0xA6, 0x35, 0x60, 0x0A, 0xC3, + 0x69, 0x32, 0x57, 0xE6, 0x84, 0xA2, 0x12, 0x8C, 0x1E, 0x7B, 0x30, 0xA9, 0xC8, 0xB3, 0x47, 0x49, + 0x34, 0xEF, 0x39, 0xB3, 0xEE, 0xA9, 0xA0, 0xA1, 0xC6, 0xEE, 0x9F, 0x31, 0x05, 0xA7, 0x1B, 0x18, + 0xF7, 0x31, 0x0D, 0x27, 0xF6, 0x1C, 0xF4, 0xD8, 0xA0, 0xA4, 0x74, 0xD4, 0x23, 0xF4, 0x84, 0xB7, + 0x4B, 0x94, 0xE0, 0x02, 0x6F, 0x9E, 0x68, 0xE2, 0x22, 0xC7, 0x94, 0xF2, 0x80, 0xB7, 0x5D, 0xB6, + 0xED, 0x58, 0xDF, 0x81, 0x96, 0x3D, 0xCC, 0xF1, 0x74, 0xD8, 0x0C, 0xD3, 0xDF, 0x3D, 0x59, 0x8E, + 0x37, 0x12, 0x09, 0x9E, 0x14, 0x2D, 0xA8, 0x54, 0x24, 0x26, 0x80, 0xB3, 0xC5, 0xAB, 0xF2, 0x01, + 0xCC, 0x2C, 0x5C, 0x04, 0x8E, 0xA6, 0x31, 0xCB, 0x4C, 0xA6, 0xE1, 0x0B, 0xB2, 0xF6, 0x8D, 0xB9, + 0x37, 0xB2, 0x34, 0xA6, 0xA8, 0x23, 0x9D, 0x63, 0x52, 0xAC, 0x7F, 0xEF, 0x34, 0xD5, 0x71, 0x4A, + 0x4E, 0x2B, 0xBC, 0xE9, 0xC3, 0x8B, 0xFA, 0x47, 0xE0, 0x2E, 0x0D, 0x76, 0x65, 0xAA, 0x30, 0xBE, + 0x1B, 0x24, 0xB7, 0x0A, 0xF2, 0x79, 0x7C, 0xBD, 0xC7, 0xE8, 0x00, 0x31, 0xF0, 0x9D, 0x3E, 0xE6, + 0x41, 0x1A, 0xD1, 0x5B, 0xE1, 0x33, 0xA0, 0x61, 0x26, 0x59, 0x93, 0x61, 0xCD, 0xC0, 0x48, 0x44, + 0xBF, 0x2E, 0xFA, 0xE2, 0x61, 0x42, 0x2A, 0x1A, 0x8B, 0x2E, 0x1E, 0x31, 0x57, 0x16, 0x4C, 0x41, + 0xC7, 0x1C, 0x5E, 0xA7, 0x1C, 0xCB, 0xAF, 0x4E, 0x5E, 0xD2, 0xDD, 0x60, 0xD2, 0x1A, 0x85, 0x1D, + 0x50, 0x3E, 0xC0, 0x3A, 0xBC, 0x32, 0x0E, 0xB3, 0x96, 0xCA, 0x74, 0x57, 0x54, 0x60, 0x09, 0x33, + 0x32, 0x53, 0xF5, 0xD2, 0x49, 0x1E, 0x91, 0xA6, 0x48, 0xEA, 0x75, 0xD0, 0x68, 0x8E, 0x27, 0x17, + 0x77, 0x87, 0x74, 0x73, 0x77, 0xD8, 0x6C, 0xBA, 0xBB, 0xAC, 0xD5, 0xA0, 0x0F, 0xF4, 0xC2, 0xC6, + 0xC5, 0x29, 0x04, 0x1C, 0x40, 0xC6, 0x8B, 0xB9, 0xB5, 0x02, 0xF1, 0x86, 0x41, 0x9B, 0x39, 0x03, + 0x1B, 0x16, 0xF2, 0x1C, 0x4B, 0xF2, 0x07, 0x6B, 0x82, 0x4B, 0x32, 0x4D, 0xE6, 0x4C, 0x97, 0xC2, + 0x56, 0x3B, 0x2D, 0xCB, 0x0D, 0x62, 0x65, 0xB1, 0xDB, 0xA8, 0x08, 0xE6, 0x62, 0xAC, 0x0A, 0xDB, + 0x71, 0xDF, 0x1E, 0x17, 0xB6, 0x46, 0xE4, 0x65, 0x46, 0x2C, 0x61, 0x2E, 0x28, 0xE7, 0xE7, 0x9E, + 0x02, 0xA4, 0x82, 0xC3, 0xD8, 0x19, 0xED, 0x17, 0xF1, 0x09, 0x2B, 0x27, 0xEB, 0xAD, 0x1C, 0x8D, + 0x7A, 0x92, 0x97, 0x05, 0x11, 0x78, 0xC5, 0x64, 0xF3, 0x72, 0x38, 0x17, 0x70, 0xBA, 0x42, 0x5D, + 0x13, 0x37, 0xEC, 0x9C, 0x83, 0x58, 0x0F, 0x7C, 0x08, 0xCF, 0xF7, 0x90, 0x33, 0x16, 0x6A, 0xBE, + 0x33, 0x5E, 0x14, 0x45, 0x09, 0x39, 0x25, 0x9E, 0xDE, 0xE7, 0x46, 0x87, 0x2E, 0x8C, 0xA2, 0x53, + 0x1B, 0x30, 0x2F, 0xAE, 0x26, 0x3B, 0x5A, 0x1D, 0xD2, 0x2E, 0xCB, 0xB5, 0x8B, 0x84, 0x81, 0x45, + 0x85, 0xB5, 0x4B, 0xEC, 0x64, 0x5A, 0x52, 0x0B, 0xAD, 0x85, 0x29, 0x32, 0x5B, 0x39, 0x59, 0x4D, + 0x0C, 0x70, 0x42, 0xBF, 0x62, 0x27, 0x9E, 0x28, 0x7A, 0x7E, 0xC2, 0x76, 0xCE, 0x46, 0x16, 0xA6, + 0xE0, 0xC1, 0x0A, 0xB2, 0xCC, 0xCA, 0x77, 0xF4, 0xFF, 0x24, 0x6B, 0xE0, 0xBE, 0x0D, 0x0A, 0xAD, + 0xBE, 0x88, 0xE4, 0x17, 0x95, 0xF8, 0xBC, 0x88, 0x84, 0x16, 0xCA, 0x79, 0x28, 0xF8, 0x80, 0x9C, + 0x47, 0xB5, 0xA1, 0x85, 0xCC, 0xC6, 0x41, 0xE2, 0x00, 0x69, 0x44, 0xAE, 0x33, 0x5C, 0x07, 0x8B, + 0xD4, 0xD8, 0x45, 0x29, 0x49, 0x84, 0x5A, 0x62, 0x62, 0xCF, 0xB8, 0x9B, 0x94, 0x10, 0x7C, 0xC6, + 0x63, 0xAE, 0xE9, 0x42, 0xC2, 0xBB, 0xE7, 0x43, 0x3D, 0x48, 0x1C, 0x4A, 0x61, 0x96, 0xB7, 0x77, + 0x67, 0x37, 0xD3, 0xAE, 0x8E, 0x5D, 0x29, 0x35, 0x86, 0x62, 0x99, 0xEE, 0x0A, 0x99, 0x2F, 0x14, + 0x41, 0x49, 0x14, 0xEA, 0xF5, 0x7A, 0x6C, 0xC7, 0x16, 0x65, 0xDA, 0x5D, 0x0E, 0x02, 0xAA, 0xEF, + 0x30, 0xCF, 0xF7, 0x2C, 0x50, 0xC1, 0x8C, 0xB7, 0x54, 0x5A, 0x12, 0xDF, 0x4A, 0x88, 0x46, 0x4C, + 0x19, 0x42, 0x17, 0xE8, 0x6A, 0x09, 0xF3, 0x24, 0x77, 0x2D, 0x35, 0x94, 0x7C, 0x23, 0x62, 0x53, + 0x50, 0xFB, 0xFB, 0x8D, 0x3B, 0x81, 0x1B, 0x26, 0x4F, 0xB6, 0x7C, 0x43, 0xE3, 0xCE, 0x2E, 0xE8, + 0x5D, 0x86, 0x05, 0xB8, 0x65, 0x6D, 0x9E, 0xC4, 0x44, 0xA0, 0xAD, 0x20, 0xA6, 0xB3, 0x48, 0xA0, + 0x7D, 0x06, 0x25, 0xD3, 0x14, 0x84, 0x4E, 0x18, 0xE0, 0x11, 0xD2, 0x9D, 0x28, 0xD7, 0x2C, 0x4B, + 0x38, 0xC9, 0xAD, 0x8F, 0xD1, 0x76, 0xB3, 0xB0, 0x53, 0xFD, 0x84, 0xF6, 0xE7, 0xF0, 0xB3, 0x26, + 0x66, 0x30, 0x6B, 0x8E, 0x54, 0x3A, 0x9A, 0x4D, 0xBE, 0x08, 0x23, 0xFB, 0x67, 0x5E, 0x53, 0x15, + 0x72, 0x16, 0x0F, 0x0A, 0x3A, 0xE7, 0x6C, 0xD0, 0x12, 0xA5, 0x8A, 0x48, 0xE3, 0x09, 0xE8, 0xF6, + 0x43, 0x69, 0x40, 0x04, 0x96, 0x1C, 0x4D, 0x89, 0x04, 0x05, 0xAF, 0xF1, 0xB2, 0x9C, 0xAE, 0x7C, + 0x97, 0x40, 0x1B, 0x81, 0x69, 0xA1, 0xBA, 0x42, 0xC5, 0x0D, 0x8F, 0xA1, 0x23, 0xD6, 0xF4, 0x48, + 0xE8, 0x84, 0x75, 0x8D, 0x31, 0xE1, 0xB4, 0xAD, 0x97, 0xE8, 0xD7, 0x8D, 0x6E, 0x80, 0xC5, 0xDC, + 0xAF, 0x96, 0x6F, 0x2B, 0xED, 0xF9, 0x32, 0x43, 0xB4, 0x4C, 0x70, 0x27, 0xA6, 0x19, 0x61, 0xC1, + 0x68, 0x42, 0xB5, 0xE8, 0x0D, 0xC1, 0x36, 0x7F, 0xD9, 0xFB, 0x75, 0xEF, 0x37, 0x04, 0x13, 0x77, + 0x1B, 0xAF, 0xD7, 0x88, 0xBA, 0x1A, 0x12, 0x88, 0x55, 0x47, 0xE8, 0xCC, 0x71, 0x31, 0x4C, 0x5B, + 0x72, 0x21, 0xCA, 0xC8, 0x67, 0x91, 0x55, 0x94, 0x8E, 0x7E, 0x29, 0x21, 0xEC, 0x96, 0xB8, 0xEF, + 0x4E, 0x53, 0xDB, 0x8E, 0x96, 0x22, 0x09, 0x47, 0x16, 0x5C, 0x4A, 0xF0, 0x9D, 0xB4, 0x7B, 0x15, + 0xCA, 0xD9, 0x52, 0x70, 0xE8, 0xD7, 0x62, 0x38, 0xF4, 0xEB, 0xAB, 0xC1, 0xA1, 0x5F, 0xE7, 0xC4, + 0xA1, 0x5F, 0xB7, 0x38, 0x94, 0x85, 0x43, 0xBF, 0x15, 0xC3, 0xA1, 0xDF, 0x5E, 0x0D, 0x0E, 0xFD, + 0x36, 0x27, 0x0E, 0xFD, 0xB6, 0xC5, 0xA1, 0x04, 0x0E, 0x99, 0x20, 0x40, 0xA1, 0x78, 0x2E, 0x04, + 0xF5, 0x22, 0x58, 0x54, 0xAC, 0x7A, 0xE8, 0x8B, 0x22, 0x52, 0x5E, 0x54, 0x6A, 0x74, 0xCD, 0xA5, + 0x10, 0x29, 0xDA, 0xF2, 0xF5, 0xD8, 0x1B, 0x4F, 0xCE, 0x82, 0x78, 0xA9, 0x6F, 0x78, 0xE5, 0x12, + 0x11, 0xA3, 0x5F, 0xBC, 0x92, 0x13, 0x55, 0x0B, 0x41, 0x2B, 0xC1, 0x20, 0x26, 0x1D, 0x4B, 0xB3, + 0x06, 0x25, 0x43, 0x06, 0x39, 0xF9, 0x0F, 0x1F, 0xF6, 0x05, 0xA6, 0xAF, 0x5A, 0xF6, 0xF3, 0x9E, + 0x8D, 0xB1, 0x99, 0xD2, 0x02, 0x32, 0x25, 0x51, 0x6F, 0xB6, 0x1C, 0x5D, 0xBC, 0x1A, 0xD2, 0x72, + 0xB9, 0x4F, 0x19, 0xF5, 0x29, 0x49, 0x36, 0x14, 0xE3, 0x97, 0x51, 0x2F, 0x1A, 0x98, 0x8B, 0x7C, + 0xF3, 0x58, 0xEC, 0x94, 0x04, 0x4D, 0x31, 0x5F, 0x51, 0x31, 0x66, 0xD4, 0xB3, 0xB2, 0x2F, 0x6C, + 0x40, 0x11, 0x84, 0x16, 0x6C, 0x0E, 0xE7, 0x94, 0xF5, 0x9D, 0xAB, 0xFF, 0x49, 0xFE, 0x77, 0x85, + 0x71, 0x23, 0x8C, 0x58, 0xFA, 0x5E, 0x7F, 0xD2, 0x35, 0x6F, 0x74, 0xDC, 0x39, 0x68, 0x16, 0x8B, + 0x57, 0xCA, 0xF2, 0x03, 0x42, 0xD5, 0x55, 0xD8, 0xA7, 0xBA, 0xAC, 0xDE, 0x6A, 0x1F, 0x35, 0xDB, + 0xCD, 0xC3, 0xC6, 0xC1, 0xE1, 0x11, 0xAB, 0xEF, 0xBF, 0x6B, 0x1D, 0x1E, 0x35, 0xF7, 0x1B, 0xFB, + 0xCD, 0x0E, 0xDB, 0x6F, 0x1E, 0x1D, 0x1E, 0x1E, 0x1E, 0x34, 0xF6, 0x8F, 0xF6, 0xAB, 0xF0, 0xA3, + 0x0C, 0x86, 0x3C, 0x5D, 0xD1, 0x90, 0x1D, 0x1A, 0xF2, 0x6C, 0x45, 0xA3, 0xED, 0xD7, 0x4E, 0xBA, + 0x78, 0x70, 0xDD, 0x8D, 0x14, 0xEF, 0xCA, 0xBD, 0xB3, 0xAC, 0x6B, 0xCB, 0x1C, 0xDE, 0x59, 0xA7, + 0xFC, 0x5C, 0x60, 0x20, 0xF0, 0x91, 0xCC, 0x89, 0x94, 0xAA, 0x98, 0x36, 0xF7, 0xA4, 0x8B, 0xBB, + 0x71, 0xAD, 0x9B, 0x0C, 0x32, 0x75, 0xC1, 0x54, 0xA1, 0x0D, 0x49, 0xD1, 0xB4, 0xB8, 0x64, 0x52, + 0xAD, 0xE1, 0x48, 0x76, 0x8F, 0xD6, 0xA2, 0xAE, 0xA6, 0x95, 0xB4, 0x0E, 0xCD, 0x88, 0x36, 0x54, + 0x96, 0x3A, 0xEB, 0xA0, 0xFF, 0xC0, 0xC8, 0x55, 0xD5, 0xBC, 0x35, 0x40, 0x40, 0x8F, 0x2F, 0x73, + 0xE6, 0x93, 0x11, 0x70, 0xEE, 0xE7, 0xF4, 0x69, 0x5D, 0x6C, 0x72, 0x80, 0x00, 0x20, 0x4B, 0xEC, + 0x8A, 0xB2, 0xB4, 0x8A, 0x46, 0xC9, 0x20, 0x76, 0xC9, 0x04, 0x17, 0xD6, 0x05, 0x77, 0xB8, 0x0A, + 0xA7, 0x45, 0x44, 0x92, 0xA0, 0xB7, 0xC5, 0xA2, 0x98, 0xEE, 0x35, 0x7E, 0x3C, 0xF7, 0xC6, 0x32, + 0xD9, 0x52, 0xAA, 0xBF, 0x5D, 0xF8, 0x84, 0x95, 0x0D, 0x66, 0x5C, 0x2E, 0xB4, 0x5E, 0xFE, 0x72, + 0xE1, 0x13, 0x95, 0x3F, 0x90, 0x97, 0x6C, 0xD5, 0xDE, 0x29, 0x0C, 0x65, 0xAF, 0x2F, 0xE6, 0xF3, + 0xF2, 0x62, 0xD7, 0x0A, 0x9F, 0xC2, 0x95, 0x4F, 0xAE, 0x16, 0xCA, 0x86, 0xC5, 0xCC, 0xE4, 0x6C, + 0xB1, 0xAB, 0x85, 0x94, 0xD1, 0xC2, 0xEB, 0x85, 0xEB, 0xEB, 0x51, 0xE1, 0x81, 0xD7, 0xFF, 0x16, + 0x02, 0x56, 0x93, 0xBC, 0x78, 0xC0, 0x47, 0xDB, 0x6B, 0x87, 0x2A, 0xFC, 0x79, 0x08, 0x9E, 0xD7, + 0x8A, 0x97, 0x9F, 0xE4, 0x24, 0xD3, 0x81, 0x67, 0x3F, 0x91, 0x87, 0x6E, 0x7F, 0x8A, 0xB6, 0xA0, + 0x7F, 0xDD, 0xF3, 0x35, 0x5E, 0x81, 0x07, 0xD8, 0xE1, 0x12, 0x2C, 0x2F, 0x31, 0x18, 0x94, 0x37, + 0xE1, 0xC9, 0x96, 0xAF, 0xCD, 0xD3, 0x4B, 0xAC, 0x0D, 0x15, 0x92, 0xA5, 0xA2, 0x06, 0x0C, 0xB0, + 0xFE, 0xB8, 0x11, 0x40, 0x61, 0x0E, 0xE4, 0x90, 0x4D, 0x5F, 0x8D, 0x89, 0x57, 0x88, 0xE4, 0x1E, + 0x89, 0x9E, 0x97, 0x58, 0x08, 0xD7, 0x4B, 0x35, 0xD0, 0x96, 0x33, 0xFA, 0x66, 0x25, 0x9C, 0x03, + 0x61, 0x5C, 0x8C, 0xC4, 0xC4, 0x50, 0xC7, 0x25, 0x03, 0x5A, 0x03, 0x53, 0x4F, 0x7C, 0xC2, 0xB3, + 0x8D, 0x3D, 0x9B, 0x7A, 0x81, 0x5C, 0xBA, 0x71, 0x2A, 0xC1, 0x77, 0x0D, 0xC1, 0xAA, 0x6B, 0xF9, + 0xC4, 0x3C, 0x9D, 0x35, 0xF2, 0x73, 0xF7, 0xA2, 0xF0, 0x69, 0x7C, 0xA3, 0x38, 0x0F, 0x7B, 0x30, + 0x1A, 0x7A, 0x5D, 0xCE, 0x77, 0x84, 0x57, 0x23, 0x75, 0x44, 0x24, 0x8F, 0xCF, 0x1C, 0x9B, 0xB2, + 0xEE, 0xBD, 0xF5, 0xC8, 0xD9, 0x85, 0x61, 0xE8, 0xB6, 0x6B, 0xE9, 0x5A, 0xE0, 0xC5, 0x06, 0x40, + 0x78, 0x90, 0x4E, 0xFE, 0xBA, 0x14, 0x50, 0x42, 0xD1, 0x0B, 0x15, 0x2E, 0x45, 0x42, 0x2E, 0xFA, + 0x3E, 0x3E, 0x1F, 0x5B, 0xA6, 0x4F, 0x35, 0xA6, 0x65, 0xD0, 0x00, 0x6E, 0x91, 0xA9, 0x95, 0x11, + 0x5C, 0x96, 0x2E, 0xBC, 0x94, 0x11, 0x60, 0x0A, 0xDB, 0x7C, 0x73, 0xD9, 0xF5, 0x7E, 0x19, 0xD9, + 0xAD, 0xFC, 0x8D, 0x5C, 0x88, 0xC9, 0x45, 0xD7, 0x54, 0xEC, 0x4A, 0xA8, 0xE0, 0x6B, 0xF6, 0xF4, + 0x44, 0x2A, 0x48, 0x0F, 0xBA, 0x44, 0x4E, 0x42, 0xF8, 0x95, 0xCE, 0x13, 0x99, 0xCC, 0x7B, 0x65, + 0xF0, 0x81, 0x77, 0xBC, 0x5F, 0xC2, 0x8C, 0x9C, 0xA6, 0x38, 0x0B, 0xC5, 0x18, 0x89, 0x43, 0xB8, + 0xE7, 0x46, 0xDC, 0x69, 0x23, 0x06, 0x30, 0xAC, 0x56, 0x0F, 0xDC, 0x04, 0x35, 0x9A, 0x32, 0x7C, + 0x8C, 0x42, 0xC1, 0x14, 0x43, 0x85, 0xA6, 0xC8, 0x5F, 0x30, 0x41, 0xB6, 0xA8, 0x41, 0xC9, 0x19, + 0x3C, 0x22, 0x9E, 0x33, 0xC7, 0x09, 0xB2, 0x0C, 0x2D, 0xE7, 0x6A, 0x10, 0x14, 0xC1, 0xDC, 0x0D, + 0xA7, 0x26, 0x2A, 0x8D, 0xCA, 0x09, 0x53, 0xF4, 0xD3, 0x3F, 0xBB, 0xFE, 0xBD, 0xE7, 0x28, 0x54, + 0xC5, 0xF3, 0x9F, 0x89, 0x7B, 0x04, 0x3E, 0xB3, 0x5D, 0xF8, 0x6D, 0x9A, 0x0A, 0x93, 0x3C, 0x0B, + 0x03, 0x6F, 0xBA, 0xB7, 0xBD, 0x49, 0xAE, 0xD0, 0x90, 0x1B, 0x85, 0xF9, 0xF9, 0xA0, 0x3B, 0x2A, + 0x80, 0x83, 0x65, 0xB8, 0x03, 0xC7, 0xD9, 0x09, 0x3F, 0x1B, 0x41, 0x0F, 0xCF, 0xEC, 0x69, 0xC4, + 0x4D, 0x19, 0xD5, 0x24, 0xEA, 0x86, 0x12, 0x13, 0x23, 0xEF, 0x56, 0x45, 0x5E, 0x5E, 0xD9, 0x16, + 0xF0, 0x9B, 0x51, 0x6C, 0xD4, 0x5D, 0x8A, 0x30, 0xF2, 0x4D, 0xF1, 0x02, 0x35, 0x09, 0xEB, 0x80, + 0x37, 0xD8, 0x17, 0xCB, 0xE3, 0xC7, 0x14, 0xA9, 0x15, 0xAE, 0x93, 0xB6, 0x9C, 0x22, 0x8E, 0x8C, + 0x27, 0xE5, 0xD9, 0x95, 0x16, 0x2C, 0x59, 0xE1, 0x74, 0x84, 0xB1, 0x86, 0x19, 0x37, 0x7F, 0xCC, + 0x43, 0x90, 0x6D, 0xA0, 0xD2, 0x57, 0x24, 0xD9, 0x69, 0xB1, 0x88, 0xDD, 0x8D, 0x25, 0xF0, 0x76, + 0x06, 0x81, 0xB3, 0x42, 0x59, 0x78, 0xD3, 0x09, 0xDD, 0x80, 0x2E, 0xBA, 0xBD, 0xB3, 0x24, 0x9D, + 0xC3, 0xA3, 0x35, 0x25, 0x73, 0x98, 0x59, 0x0A, 0x95, 0x2B, 0x9A, 0x56, 0x94, 0xC0, 0x25, 0x85, + 0x14, 0x25, 0xEF, 0x2D, 0xF1, 0x95, 0x21, 0xBE, 0x15, 0x2A, 0xD6, 0x12, 0x71, 0xF3, 0xA5, 0xEC, + 0x83, 0x34, 0x29, 0x1B, 0xF1, 0xA8, 0xB0, 0xE0, 0xBC, 0x3C, 0xEC, 0x9E, 0x2D, 0x30, 0x07, 0x18, + 0xDC, 0x1B, 0x51, 0xFC, 0x38, 0x21, 0x76, 0x5C, 0x80, 0x76, 0xFD, 0x71, 0xF0, 0xB2, 0x22, 0x5F, + 0x16, 0x27, 0xCB, 0x2E, 0xB3, 0xA9, 0x91, 0x4A, 0x8D, 0x44, 0x3E, 0x58, 0x3A, 0x57, 0xC4, 0xD7, + 0x84, 0xD7, 0xE8, 0x67, 0xE1, 0x30, 0xAE, 0xE9, 0x84, 0x96, 0xBB, 0xCC, 0x1D, 0xE1, 0xE9, 0x83, + 0xB9, 0x1D, 0x10, 0xC9, 0x50, 0xCF, 0xA3, 0x10, 0x14, 0xC0, 0xE4, 0xD7, 0xE9, 0x53, 0x31, 0x53, + 0xB6, 0x3E, 0x58, 0x9E, 0xA7, 0x5B, 0x80, 0xB9, 0x41, 0xF2, 0xE0, 0xF2, 0x36, 0x11, 0xD1, 0xC3, + 0xCA, 0x2C, 0x22, 0x74, 0xAF, 0xB1, 0x1A, 0xD2, 0x0E, 0x5C, 0x4A, 0x02, 0xE3, 0x7C, 0x6D, 0x1E, + 0x93, 0x18, 0xB9, 0xB2, 0xBD, 0x30, 0x65, 0x7F, 0x82, 0xE3, 0x43, 0x04, 0x5B, 0x51, 0xB8, 0x38, + 0x48, 0x7F, 0xC1, 0xD2, 0xD8, 0x3D, 0x1F, 0x60, 0x2E, 0x6A, 0x71, 0x66, 0x61, 0x34, 0x97, 0x3C, + 0x37, 0xC2, 0xF4, 0xD6, 0xE4, 0xFF, 0x14, 0xF5, 0x71, 0x42, 0x5F, 0xA9, 0x1F, 0x90, 0x06, 0x0F, + 0x97, 0xE8, 0x24, 0x18, 0x22, 0xD8, 0x5C, 0x8E, 0x82, 0x41, 0xEB, 0xAD, 0xB3, 0xE0, 0xD2, 0x09, + 0xA9, 0x7A, 0x67, 0xC1, 0x6B, 0xC5, 0xDB, 0x43, 0xAB, 0x32, 0x1A, 0xCF, 0xB6, 0x3E, 0x83, 0x2F, + 0xE4, 0x33, 0x18, 0x50, 0x50, 0x41, 0xBF, 0xC1, 0xC2, 0xDB, 0x13, 0xDD, 0xDC, 0xCA, 0xDD, 0x0C, + 0x27, 0xA7, 0x52, 0xBA, 0xAB, 0xE1, 0xE4, 0xFB, 0x35, 0x73, 0x37, 0xDC, 0x6F, 0x36, 0x9A, 0xEF, + 0x9B, 0xED, 0xF7, 0xFB, 0xEF, 0xDE, 0xB3, 0x7A, 0xAB, 0x79, 0xD0, 0x68, 0x1D, 0x1D, 0x34, 0x0F, + 0xDE, 0x1D, 0xB6, 0x58, 0xEB, 0xE0, 0x10, 0xBE, 0x3B, 0x7A, 0x5F, 0xAD, 0xAF, 0xE1, 0x0A, 0xC6, + 0x0B, 0x1C, 0x0D, 0x57, 0x30, 0x54, 0x01, 0x2F, 0xC3, 0xCC, 0x59, 0x94, 0xB2, 0x51, 0xCF, 0x37, + 0xE3, 0xAD, 0x8B, 0x61, 0x86, 0x8B, 0xE1, 0xB4, 0x10, 0x59, 0xB9, 0x9B, 0x61, 0x30, 0xC4, 0x12, + 0x5C, 0x0D, 0x97, 0x3D, 0xFB, 0xE8, 0x18, 0xCB, 0x71, 0x39, 0x5C, 0xF6, 0x0A, 0xE2, 0xA3, 0x6C, + 0xBC, 0xEB, 0x61, 0xF4, 0xE8, 0xFA, 0x61, 0x3C, 0x10, 0x37, 0xB3, 0x4E, 0x7B, 0x9F, 0x3B, 0x8F, + 0x58, 0xA7, 0x35, 0x56, 0xA7, 0x5D, 0x3C, 0x5C, 0x59, 0x9D, 0xF6, 0x60, 0x0E, 0x2F, 0x53, 0xA7, + 0xDD, 0xA5, 0xD1, 0x51, 0xF0, 0xF6, 0x6D, 0x42, 0xEE, 0x20, 0x4F, 0xC9, 0x1B, 0x77, 0xAA, 0x60, + 0x3B, 0x65, 0x4D, 0x9B, 0x2A, 0xD7, 0xFE, 0x95, 0x12, 0x96, 0x88, 0x7A, 0xED, 0x42, 0x9A, 0xF7, + 0xF0, 0xF2, 0x44, 0x51, 0x31, 0xFD, 0x87, 0x54, 0x88, 0xE3, 0xFD, 0xF8, 0x22, 0x2B, 0x88, 0x19, + 0x2B, 0x15, 0xFF, 0x7A, 0x6A, 0xB8, 0x8B, 0x0D, 0x9D, 0x37, 0x9D, 0xC4, 0x87, 0x02, 0xB5, 0x65, + 0x52, 0x33, 0x74, 0x16, 0x2C, 0xB3, 0x16, 0xE7, 0xF2, 0xB9, 0x1C, 0xA0, 0x50, 0xA9, 0xB5, 0xA9, + 0x65, 0x37, 0x33, 0x92, 0x75, 0xE6, 0x0E, 0x97, 0x48, 0xE6, 0x99, 0xD2, 0x71, 0x3E, 0xD3, 0x8A, + 0x52, 0x31, 0x6B, 0x61, 0x86, 0xCE, 0x0A, 0x6A, 0xAB, 0x09, 0x14, 0xC8, 0xAD, 0xAF, 0x56, 0xC2, + 0xDF, 0x3A, 0x9E, 0xB7, 0xB3, 0xF4, 0x4A, 0xAB, 0x2F, 0x87, 0x55, 0xB9, 0x1F, 0x4D, 0x74, 0x4D, + 0x54, 0x91, 0xF1, 0xB3, 0xE5, 0x7A, 0x73, 0x94, 0xF2, 0x59, 0x42, 0x09, 0xF1, 0xE0, 0x1F, 0xCE, + 0xE8, 0x78, 0x51, 0x2F, 0x8E, 0xA3, 0x52, 0x56, 0xAE, 0xD2, 0x96, 0xAE, 0x0C, 0x28, 0x96, 0x18, + 0xCD, 0x9E, 0xD5, 0xD1, 0xA2, 0xB6, 0xAF, 0xF2, 0x3E, 0x23, 0x2F, 0x8C, 0x85, 0x3D, 0xCB, 0x59, + 0x33, 0x2C, 0xC4, 0x19, 0xBD, 0x34, 0x16, 0xE6, 0xDE, 0x79, 0x64, 0xC1, 0x71, 0x71, 0x3C, 0x14, + 0x1D, 0xFD, 0x70, 0x78, 0x88, 0x45, 0xDA, 0xD7, 0x0B, 0x0F, 0x71, 0x46, 0x9B, 0xC6, 0x0D, 0x25, + 0x14, 0x17, 0xC7, 0x42, 0xD1, 0xD1, 0x0F, 0x89, 0x85, 0xBD, 0x9F, 0x2B, 0xC2, 0xC3, 0xAC, 0x2A, + 0xEA, 0x73, 0xE0, 0x61, 0xE1, 0x6A, 0xE9, 0x33, 0x50, 0xF1, 0x5D, 0xA9, 0x2B, 0xE0, 0x4A, 0x50, + 0x91, 0x40, 0x59, 0x0D, 0x32, 0x62, 0x57, 0x3F, 0x10, 0x3A, 0x4E, 0x0A, 0xC8, 0x2F, 0x99, 0x29, + 0xD2, 0x40, 0x25, 0xCE, 0x66, 0x98, 0xD1, 0xE6, 0x30, 0xC5, 0x18, 0x14, 0x17, 0xC1, 0xC3, 0x68, + 0x47, 0x3F, 0x24, 0x16, 0x2E, 0x9D, 0x29, 0xCE, 0x81, 0x87, 0x1B, 0xC5, 0x14, 0x13, 0xA0, 0xAC, + 0x06, 0x19, 0x5F, 0x86, 0x29, 0x2E, 0xF0, 0x4A, 0x11, 0x93, 0xC0, 0xC6, 0xDB, 0x7B, 0x5A, 0xCB, + 0xB2, 0xF7, 0xB4, 0xCA, 0xDA, 0x7B, 0xDA, 0x9B, 0x6A, 0xEF, 0x69, 0xBD, 0x56, 0x7B, 0x4F, 0x6B, + 0x6B, 0xEF, 0xA9, 0xC0, 0xDE, 0xD3, 0xAA, 0xCA, 0xDE, 0xD3, 0xFA, 0x31, 0xED, 0x3D, 0xAD, 0xAD, + 0xBD, 0xA7, 0x12, 0x7B, 0x4F, 0xAB, 0x2A, 0x7B, 0x4F, 0xEB, 0xC7, 0xB4, 0xF7, 0xB4, 0xB6, 0xF6, + 0x9E, 0x0A, 0xEC, 0x3D, 0xAD, 0xAA, 0xEC, 0x3D, 0xAD, 0x1F, 0xD5, 0xDE, 0xD3, 0xDA, 0xDA, 0x7B, + 0xAA, 0xB2, 0xF7, 0xB4, 0xAA, 0xB3, 0xF7, 0xB4, 0x7E, 0x4C, 0x7B, 0x4F, 0x6B, 0x6B, 0xEF, 0xA9, + 0xC0, 0xDE, 0xD3, 0xAA, 0xCA, 0xDE, 0xD3, 0xFA, 0x51, 0xED, 0x3D, 0xAD, 0xAD, 0xBD, 0xA7, 0x2A, + 0x7B, 0x4F, 0xAB, 0x3A, 0x7B, 0x4F, 0x6B, 0x6B, 0xEF, 0x59, 0x37, 0x7B, 0x4F, 0x7B, 0x59, 0xF6, + 0x9E, 0x76, 0x59, 0x7B, 0x4F, 0x67, 0x53, 0xED, 0x3D, 0xED, 0xD7, 0x6A, 0xEF, 0x69, 0x6F, 0xED, + 0x3D, 0x15, 0xD8, 0x7B, 0xDA, 0x55, 0xD9, 0x7B, 0xDA, 0x3F, 0xA6, 0xBD, 0xA7, 0xBD, 0xB5, 0xF7, + 0x54, 0x62, 0xEF, 0x69, 0x57, 0x65, 0xEF, 0x69, 0xFF, 0x98, 0xF6, 0x9E, 0xF6, 0xD6, 0xDE, 0x53, + 0x81, 0xBD, 0xA7, 0x5D, 0x95, 0xBD, 0xA7, 0xFD, 0xA3, 0xDA, 0x7B, 0xDA, 0x5B, 0x7B, 0x4F, 0x55, + 0xF6, 0x9E, 0x76, 0x75, 0xF6, 0x9E, 0xF6, 0x8F, 0x69, 0xEF, 0x69, 0x6F, 0xED, 0x3D, 0x15, 0xD8, + 0x7B, 0xDA, 0x55, 0xD9, 0x7B, 0xDA, 0x3F, 0xAA, 0xBD, 0xA7, 0xBD, 0xB5, 0xF7, 0x54, 0x65, 0xEF, + 0x69, 0x57, 0x67, 0xEF, 0x69, 0x6F, 0xED, 0x3D, 0xEB, 0x66, 0xEF, 0xE9, 0x2C, 0xCB, 0xDE, 0xD3, + 0x29, 0x6B, 0xEF, 0xD9, 0xDF, 0x54, 0x7B, 0x4F, 0xE7, 0xB5, 0xDA, 0x7B, 0x3A, 0x5B, 0x7B, 0x4F, + 0x05, 0xF6, 0x9E, 0x4E, 0x55, 0xF6, 0x9E, 0xCE, 0x8F, 0x69, 0xEF, 0xE9, 0x6C, 0xED, 0x3D, 0x95, + 0xD8, 0x7B, 0x3A, 0x55, 0xD9, 0x7B, 0x3A, 0x3F, 0xA6, 0xBD, 0xA7, 0xB3, 0xB5, 0xF7, 0x54, 0x60, + 0xEF, 0xE9, 0x54, 0x65, 0xEF, 0xE9, 0xFC, 0xA8, 0xF6, 0x9E, 0xCE, 0xD6, 0xDE, 0x53, 0x95, 0xBD, + 0xA7, 0x53, 0x9D, 0xBD, 0xA7, 0xF3, 0x63, 0xDA, 0x7B, 0x3A, 0x5B, 0x7B, 0x4F, 0x05, 0xF6, 0x9E, + 0x4E, 0x55, 0xF6, 0x9E, 0xCE, 0x8F, 0x6A, 0xEF, 0xE9, 0x6C, 0xED, 0x3D, 0x55, 0xD9, 0x7B, 0x3A, + 0xD5, 0xD9, 0x7B, 0x3A, 0xAF, 0xC6, 0xDE, 0x93, 0x97, 0x23, 0x68, 0x46, 0xAF, 0xD2, 0x06, 0x14, + 0xE6, 0x44, 0x1B, 0x72, 0xEF, 0x86, 0xBB, 0xAE, 0x32, 0xE4, 0xD7, 0xBA, 0xEB, 0x61, 0xE1, 0x4A, + 0xAA, 0x10, 0x30, 0x97, 0x89, 0x68, 0x76, 0x5A, 0xA8, 0x58, 0xD2, 0xB7, 0x42, 0xE6, 0xA1, 0xE0, + 0x39, 0xA6, 0xD8, 0x17, 0xC6, 0x8D, 0x1B, 0x77, 0x88, 0x53, 0x9C, 0x3D, 0x52, 0xAA, 0x05, 0x29, + 0x69, 0x21, 0xCA, 0xEE, 0x7B, 0xF6, 0xAE, 0xDD, 0xDE, 0x9D, 0xDD, 0xB0, 0x5B, 0x4A, 0x0E, 0xFB, + 0x41, 0x27, 0x74, 0xC3, 0x24, 0x56, 0xD0, 0xF6, 0x0C, 0x2D, 0x42, 0xB5, 0x2A, 0x4C, 0x46, 0x05, + 0xCC, 0x45, 0x85, 0x33, 0x75, 0xD1, 0x0C, 0x1D, 0x4F, 0x1D, 0xE3, 0x94, 0xAF, 0xCC, 0x81, 0x95, + 0x5F, 0x5B, 0x4E, 0xE6, 0xEF, 0xA2, 0x85, 0x62, 0xDA, 0x78, 0x47, 0x31, 0xDD, 0xB1, 0xEE, 0x45, + 0x4A, 0x1E, 0xE0, 0x8A, 0x99, 0x82, 0x39, 0xAA, 0x35, 0x91, 0x4A, 0x0B, 0x53, 0xED, 0xB6, 0x3E, + 0xFF, 0x49, 0xB9, 0xE0, 0xC7, 0x02, 0x9B, 0x5C, 0xD6, 0x6A, 0x36, 0x0F, 0x76, 0xE1, 0xE7, 0xBB, + 0x7D, 0xFC, 0x79, 0x44, 0x3F, 0xDF, 0xE3, 0xCF, 0x56, 0x7B, 0x5F, 0x24, 0x98, 0x6F, 0x36, 0x82, + 0x46, 0xAD, 0x76, 0xA7, 0x29, 0x33, 0xD5, 0xCB, 0x34, 0xBD, 0x86, 0xF5, 0x44, 0x55, 0x19, 0xF0, + 0x5B, 0xAA, 0x73, 0xE1, 0x8A, 0xAA, 0x28, 0xF0, 0x1C, 0xC6, 0x37, 0x35, 0x4A, 0x7A, 0x8A, 0x49, + 0xEF, 0x3C, 0x45, 0x37, 0x2C, 0x47, 0x56, 0x53, 0x90, 0x73, 0x85, 0xDE, 0x9F, 0xF7, 0x14, 0xC3, + 0x10, 0xBB, 0x15, 0xCC, 0xA8, 0xC1, 0xAE, 0x75, 0xF8, 0xD2, 0x3D, 0x66, 0x4D, 0x7C, 0xB9, 0xDD, + 0x8C, 0x56, 0x6B, 0x10, 0x35, 0x58, 0x08, 0x76, 0x30, 0x9E, 0x47, 0xF5, 0x1A, 0x2C, 0xE0, 0x20, + 0x8E, 0xAE, 0x69, 0xDC, 0xC4, 0xF7, 0x71, 0xAE, 0x54, 0xAE, 0x45, 0x37, 0x19, 0x22, 0x0A, 0x1B, + 0x5B, 0x1A, 0xDF, 0xAC, 0xD4, 0x61, 0xA9, 0x16, 0xC4, 0x79, 0x28, 0xA1, 0x7A, 0x23, 0x22, 0xF5, + 0x18, 0x6F, 0x7A, 0x6F, 0x01, 0x15, 0x8C, 0x83, 0xD6, 0xB9, 0x1C, 0x37, 0x35, 0xB9, 0x64, 0x7A, + 0x22, 0xC9, 0x48, 0x61, 0x14, 0x87, 0xBB, 0xDC, 0xBB, 0xB3, 0x10, 0x51, 0x64, 0x5E, 0x38, 0xAA, + 0xEA, 0x7A, 0x8B, 0x8F, 0x61, 0xD7, 0x0B, 0x9D, 0x09, 0x41, 0xC3, 0x62, 0x79, 0x24, 0x8B, 0xD6, + 0x9D, 0x79, 0x59, 0x60, 0x5C, 0x5B, 0x4F, 0xA7, 0x01, 0x99, 0x85, 0x00, 0x29, 0x04, 0x0D, 0xCC, + 0x4C, 0x09, 0x44, 0x1A, 0xB6, 0x06, 0xAA, 0x33, 0x1F, 0x4A, 0x81, 0x26, 0x1F, 0x36, 0x88, 0xB7, + 0xE3, 0xF8, 0xB1, 0x55, 0x5B, 0x76, 0xFA, 0xC8, 0x02, 0x8F, 0xD3, 0x06, 0xF9, 0xF0, 0x0F, 0xF5, + 0x3A, 0xAB, 0x07, 0xFF, 0x02, 0x71, 0x8C, 0x3B, 0x03, 0x4C, 0x1C, 0x2D, 0xE8, 0x2D, 0xF2, 0x75, + 0xBD, 0x9E, 0xE8, 0x31, 0x42, 0x68, 0x1A, 0xC8, 0xAA, 0xBA, 0xC6, 0x86, 0x8A, 0x9D, 0x5A, 0xD0, + 0x39, 0xE3, 0x7A, 0x27, 0xF3, 0x3E, 0x07, 0x61, 0x68, 0xDB, 0x41, 0xFA, 0xC0, 0x22, 0xC7, 0xF3, + 0x4F, 0xD9, 0x17, 0x3D, 0xC9, 0x23, 0xBB, 0xD7, 0x0B, 0x3A, 0x2E, 0x75, 0x1A, 0x87, 0xCD, 0x52, + 0x87, 0x8A, 0x67, 0xFD, 0xCE, 0xD8, 0x70, 0x21, 0xED, 0xC5, 0xE0, 0xEB, 0x3B, 0xA2, 0x34, 0x89, + 0x3C, 0xB0, 0xED, 0xC8, 0x1B, 0x8B, 0x9F, 0xDA, 0xE9, 0x98, 0x9D, 0x86, 0x1C, 0xB9, 0x1C, 0x38, + 0x5C, 0x7D, 0xCA, 0x28, 0xD9, 0x0C, 0x77, 0x2E, 0x39, 0xF0, 0x9C, 0xD2, 0x68, 0xB2, 0xAB, 0xF3, + 0xE3, 0x40, 0x6A, 0x1E, 0x41, 0x87, 0x4F, 0xB0, 0xD8, 0xAB, 0xF3, 0x19, 0xE9, 0xD5, 0xF7, 0xBA, + 0x28, 0x28, 0xCF, 0xCC, 0x8F, 0x7E, 0x8E, 0x25, 0x8E, 0x40, 0xEA, 0xD6, 0x0D, 0xF6, 0xC0, 0xE1, + 0x4F, 0xD8, 0x7A, 0xDD, 0xE1, 0xE1, 0x30, 0x1A, 0x7C, 0x7D, 0xCB, 0xC7, 0x8A, 0x6E, 0xEA, 0xE6, + 0x70, 0xC6, 0x48, 0x16, 0xFB, 0x2B, 0xB4, 0xCE, 0x14, 0xCB, 0x5F, 0x34, 0xA5, 0x6B, 0x14, 0xC5, + 0xCE, 0xC2, 0x9C, 0xA3, 0x6E, 0x98, 0xDE, 0x35, 0xFA, 0xFD, 0x4C, 0xA6, 0x14, 0x69, 0xCC, 0x56, + 0x91, 0x07, 0x36, 0x73, 0xE2, 0x2B, 0xCC, 0x09, 0x7B, 0x5D, 0xC7, 0x93, 0x81, 0xED, 0xB1, 0xAB, + 0x5E, 0x9C, 0x56, 0xD5, 0x08, 0x30, 0x48, 0xCE, 0x52, 0x1E, 0x41, 0xB4, 0xA3, 0x0A, 0x58, 0xD3, + 0x29, 0x5B, 0x37, 0x2E, 0x63, 0xEB, 0x90, 0x5B, 0x43, 0x47, 0xB1, 0x47, 0xBA, 0x7A, 0xCB, 0x87, + 0xB0, 0xC6, 0x73, 0xC7, 0xB2, 0x05, 0x57, 0xC9, 0xC3, 0x48, 0x42, 0xBC, 0x64, 0xF3, 0xDA, 0xC9, + 0xA7, 0xF0, 0x09, 0x13, 0x8F, 0xF2, 0x15, 0xFC, 0x78, 0xB9, 0x82, 0xA9, 0x2E, 0x53, 0xE7, 0x19, + 0x57, 0xD9, 0x35, 0x39, 0xEB, 0x20, 0xBB, 0xEC, 0xCC, 0x3D, 0x88, 0x27, 0xC5, 0x6F, 0xD6, 0x4E, + 0xBE, 0xF5, 0x8B, 0x25, 0xAA, 0x9F, 0xAE, 0x4C, 0x70, 0xF1, 0x6D, 0xAE, 0x96, 0x30, 0xC5, 0xEE, + 0x7C, 0x2D, 0x81, 0x53, 0xFC, 0xF5, 0x76, 0xAE, 0x96, 0xFB, 0xB5, 0x93, 0xFF, 0xAE, 0x00, 0xAE, + 0xE4, 0x37, 0xCE, 0xCF, 0xC3, 0x5F, 0x2D, 0xF5, 0xF5, 0xC5, 0xEE, 0x3F, 0x5B, 0xBE, 0xC3, 0x26, + 0xDB, 0xCC, 0x1C, 0xDA, 0x67, 0xA9, 0x7D, 0x81, 0x42, 0x07, 0x0C, 0x58, 0xA4, 0x53, 0x96, 0x94, + 0x3A, 0x70, 0xF8, 0x1F, 0x3E, 0x37, 0xD5, 0x67, 0xD2, 0xD9, 0x04, 0x56, 0x28, 0x46, 0x84, 0x77, + 0x81, 0x54, 0x61, 0xEB, 0x6A, 0x84, 0x48, 0xBF, 0xF5, 0xD7, 0x89, 0x3C, 0x85, 0x6C, 0xE4, 0x2C, + 0x40, 0xBB, 0xB6, 0xDD, 0xE7, 0x1E, 0x26, 0xA3, 0x76, 0x33, 0xCF, 0xE7, 0xC5, 0xCE, 0x9E, 0xC2, + 0xE7, 0x8F, 0xE2, 0x7B, 0x16, 0x9C, 0x8B, 0xB7, 0xDC, 0xE4, 0x4F, 0x8A, 0x01, 0xD8, 0x0D, 0x9F, + 0xF1, 0xA0, 0x64, 0xF2, 0x49, 0xC1, 0x42, 0x2F, 0x8B, 0x9C, 0x24, 0xC9, 0x29, 0x14, 0xDF, 0xE8, + 0xC5, 0x72, 0xE5, 0x4B, 0x24, 0xFE, 0x19, 0x4F, 0x06, 0x12, 0x2C, 0x90, 0x17, 0x31, 0x58, 0x2B, + 0xE8, 0x1A, 0xED, 0x23, 0x86, 0x72, 0x05, 0xAA, 0x1E, 0x24, 0x6E, 0x3C, 0xEF, 0x32, 0x9C, 0x26, + 0x56, 0xA4, 0xC3, 0x9A, 0x95, 0x80, 0xB9, 0x9E, 0xC7, 0xC7, 0x36, 0x55, 0xCE, 0x02, 0x6C, 0x33, + 0x91, 0x0C, 0xE0, 0xCF, 0x37, 0x9F, 0xAD, 0x31, 0x7F, 0xC3, 0x4C, 0xEE, 0x3D, 0x59, 0xCE, 0xC3, + 0x2E, 0xE8, 0x41, 0x20, 0x12, 0x29, 0xD8, 0xD5, 0x2E, 0x7E, 0xED, 0xE0, 0x12, 0x69, 0xAC, 0x08, + 0x6E, 0x8B, 0x23, 0x5E, 0x2B, 0x5C, 0xFF, 0xB3, 0xE2, 0xC4, 0xFA, 0xF9, 0x84, 0x50, 0xDC, 0x91, + 0xA8, 0x94, 0xF9, 0x3B, 0x7A, 0x18, 0x45, 0x05, 0x68, 0x21, 0x48, 0xF6, 0x1C, 0x6B, 0xA0, 0x1B, + 0xFC, 0xCE, 0x7A, 0xE0, 0x05, 0x7C, 0xC3, 0x72, 0xEF, 0x5E, 0xA6, 0x4B, 0xB4, 0x49, 0x79, 0x55, + 0x8E, 0xC3, 0x68, 0xA0, 0xE3, 0x72, 0x5B, 0xB0, 0x78, 0xA9, 0x86, 0x49, 0x89, 0x51, 0xE2, 0xA1, + 0x96, 0x33, 0x54, 0x4C, 0xFD, 0x4F, 0xA1, 0x5B, 0x8C, 0x14, 0x17, 0x93, 0xD6, 0x5B, 0x8E, 0x6D, + 0x91, 0xF9, 0x08, 0xB8, 0xA9, 0x39, 0xEC, 0x7B, 0x0E, 0x57, 0xC6, 0xC4, 0x37, 0x63, 0xA2, 0x8E, + 0xA2, 0xAA, 0x68, 0x98, 0xDE, 0x15, 0x09, 0xF2, 0x75, 0x92, 0x77, 0x1C, 0x8E, 0xBD, 0x32, 0x24, + 0x4C, 0xEA, 0x5D, 0xF5, 0x5D, 0xC0, 0x60, 0x99, 0xEF, 0x9E, 0xD9, 0x72, 0xE1, 0x1E, 0x2E, 0x3C, + 0x8A, 0x8E, 0x80, 0xD5, 0xCF, 0xAC, 0xCE, 0x44, 0xB6, 0x7D, 0xCE, 0xFA, 0xB6, 0xE2, 0x3C, 0x5C, + 0xFA, 0xA6, 0x80, 0x50, 0x6D, 0x8E, 0x8A, 0x16, 0x55, 0x96, 0x80, 0x28, 0x86, 0xD1, 0x45, 0x38, + 0x56, 0xD6, 0xCD, 0xD8, 0xBB, 0x22, 0x84, 0x58, 0xE2, 0x1A, 0x22, 0x07, 0xB5, 0x0B, 0xD7, 0x21, + 0x9F, 0xDD, 0x4F, 0x05, 0x85, 0xC9, 0x2B, 0x63, 0x00, 0xD5, 0x1E, 0x50, 0x24, 0x2B, 0xB8, 0x1E, + 0x1C, 0x10, 0xDF, 0x6C, 0x20, 0x36, 0x8E, 0x86, 0x23, 0x7A, 0x42, 0xA7, 0x94, 0x78, 0xB6, 0x82, + 0x43, 0x6A, 0x7A, 0x1A, 0x2F, 0x71, 0x4C, 0xC9, 0x3A, 0xCB, 0xA2, 0x84, 0x4B, 0x8C, 0x01, 0xD0, + 0x01, 0xF6, 0xA4, 0x1B, 0x06, 0x9A, 0xBA, 0xE5, 0x64, 0xB9, 0x46, 0x8C, 0xC2, 0xA7, 0x09, 0x6B, + 0x68, 0x5F, 0xC7, 0x66, 0x26, 0xE0, 0x2B, 0xB3, 0x6C, 0xAC, 0x39, 0xEC, 0x9B, 0xBA, 0xF7, 0x5C, + 0x5E, 0x17, 0x5A, 0xEF, 0xB3, 0x08, 0x77, 0xCB, 0x77, 0x79, 0xD7, 0x75, 0x75, 0xD7, 0xFB, 0x62, + 0x3D, 0x9D, 0x05, 0x1B, 0x5A, 0xB2, 0x32, 0x77, 0x61, 0x34, 0x2E, 0x8C, 0xCA, 0xD1, 0x59, 0x81, + 0xA4, 0x15, 0xFC, 0x59, 0xA2, 0x4E, 0xE5, 0x22, 0x18, 0x1C, 0x1F, 0xFD, 0x85, 0x4E, 0x3A, 0xC2, + 0xE2, 0xB0, 0x9C, 0xF6, 0x04, 0x04, 0x37, 0x9F, 0xBA, 0xA2, 0xC2, 0xCA, 0x34, 0x0A, 0x83, 0xDC, + 0xA4, 0x8F, 0xE1, 0xB4, 0x7A, 0x94, 0x95, 0xB1, 0x15, 0xF5, 0x0F, 0x5F, 0x77, 0x75, 0x3A, 0x23, + 0x6D, 0xC0, 0x7E, 0xAC, 0x13, 0x6C, 0xAA, 0x7C, 0x3E, 0x34, 0x5E, 0x83, 0xC3, 0x6A, 0x71, 0xE6, + 0x2B, 0x77, 0x17, 0x8B, 0xDF, 0x19, 0xFA, 0x9F, 0x5C, 0x83, 0xF5, 0x7B, 0x8E, 0x7E, 0xEF, 0x53, + 0x6D, 0xC0, 0x75, 0xC2, 0xFE, 0xD4, 0x19, 0x8A, 0xAA, 0x7D, 0xF4, 0x98, 0x45, 0x9F, 0x57, 0x58, + 0xDE, 0x75, 0x41, 0xB2, 0xC9, 0x98, 0xF6, 0x5A, 0x90, 0x90, 0x11, 0xC2, 0x2E, 0x6A, 0xED, 0xC2, + 0x3B, 0x4E, 0x92, 0xF9, 0x0C, 0x59, 0x10, 0x31, 0xA4, 0x2B, 0x2A, 0x56, 0xAA, 0x9B, 0x40, 0x59, + 0x4A, 0x58, 0xE5, 0x1B, 0xE5, 0x15, 0x90, 0x17, 0x4C, 0x0F, 0xD4, 0xBD, 0x48, 0x2F, 0x9B, 0x4D, + 0x51, 0xC5, 0xAE, 0x7C, 0x8C, 0xB4, 0xAD, 0xBD, 0x03, 0xA9, 0xEA, 0x9A, 0x3F, 0x72, 0xA3, 0x80, + 0x49, 0x2D, 0x4D, 0x9B, 0x99, 0xDD, 0x69, 0x16, 0xBE, 0x33, 0x7C, 0x83, 0xD1, 0x2B, 0xC5, 0x3D, + 0x6B, 0xE2, 0x06, 0xB8, 0x9C, 0x81, 0x0B, 0xAC, 0xB8, 0x18, 0x26, 0xCE, 0x6B, 0xC0, 0xCB, 0x36, + 0xE4, 0xB5, 0x9A, 0xCD, 0x26, 0xFB, 0x8E, 0x37, 0xFC, 0xCD, 0x87, 0x31, 0xE9, 0x1C, 0x2E, 0x2F, + 0x59, 0x83, 0x72, 0xCA, 0xC4, 0x77, 0x40, 0x5D, 0x1E, 0x54, 0xD5, 0x23, 0x2C, 0xAE, 0x7D, 0x80, + 0x3D, 0xC2, 0xCF, 0x6A, 0x7A, 0xEC, 0x24, 0xD7, 0xFD, 0x19, 0x98, 0x01, 0x10, 0x9D, 0x09, 0xA7, + 0xDB, 0xF3, 0x42, 0x3D, 0xEF, 0xC7, 0x57, 0x5F, 0x59, 0xBF, 0x07, 0x71, 0x18, 0xCC, 0xD7, 0x6F, + 0x89, 0x6A, 0xA1, 0x4B, 0x61, 0xA0, 0xD2, 0x6A, 0x89, 0x9C, 0x6F, 0xC2, 0x3D, 0xB5, 0x28, 0x25, + 0x7A, 0x48, 0x89, 0x06, 0xD2, 0x43, 0x23, 0xB6, 0x46, 0x54, 0xAC, 0xB1, 0x5E, 0xE2, 0x18, 0x86, + 0xD6, 0xB8, 0xD6, 0x90, 0x48, 0xC0, 0xC6, 0xCA, 0x33, 0xF2, 0x56, 0x8D, 0xDB, 0xF0, 0x2D, 0xCA, + 0xDA, 0x11, 0xD6, 0x99, 0x05, 0xAF, 0x4D, 0x60, 0xA5, 0x33, 0x0D, 0x9D, 0x25, 0x25, 0x98, 0x55, + 0x5C, 0x84, 0x3B, 0x9E, 0xFB, 0xF2, 0x17, 0xE0, 0x38, 0x8B, 0x65, 0xDD, 0x81, 0x47, 0xFB, 0x2E, + 0x77, 0x0D, 0x1E, 0x69, 0x99, 0x75, 0xCB, 0x3D, 0x81, 0xDE, 0xD4, 0xF5, 0x36, 0x36, 0x5E, 0xAB, + 0x7B, 0xED, 0x99, 0xCB, 0x99, 0xEF, 0x6A, 0x3B, 0xC5, 0x88, 0x09, 0x1B, 0x3C, 0xBB, 0xE2, 0x21, + 0x22, 0xE0, 0xA5, 0x15, 0xD4, 0x90, 0x14, 0xFE, 0x64, 0x40, 0xAE, 0x40, 0x95, 0xDC, 0xC1, 0x2B, + 0x8D, 0xF3, 0xEE, 0x5D, 0x97, 0x21, 0xF8, 0x76, 0x99, 0x3B, 0x02, 0x35, 0x67, 0xE0, 0x83, 0x14, + 0x26, 0x59, 0x2A, 0xBA, 0x03, 0x25, 0x71, 0x33, 0x55, 0x46, 0x09, 0x7A, 0xC3, 0x45, 0x7F, 0xB5, + 0xF3, 0xEE, 0x57, 0x63, 0x4D, 0xC9, 0xCF, 0x0D, 0xDB, 0x9D, 0x8D, 0x14, 0xD3, 0x8C, 0x08, 0x34, + 0xC1, 0x62, 0x0B, 0x1E, 0xDA, 0x51, 0xE9, 0x26, 0xEC, 0xF3, 0x54, 0xF1, 0x41, 0x20, 0xBC, 0xC5, + 0x8F, 0x84, 0x3D, 0x0C, 0x1F, 0x90, 0x27, 0xE3, 0x31, 0x9B, 0x53, 0x80, 0x89, 0xF7, 0x1D, 0x5F, + 0x82, 0x78, 0x94, 0x26, 0x7A, 0xCC, 0x27, 0x75, 0xEC, 0x1F, 0x35, 0x41, 0xF0, 0xC0, 0x9F, 0x0B, + 0x1D, 0x89, 0xEF, 0x0F, 0xB1, 0x1B, 0xFC, 0xB9, 0x98, 0xBC, 0xF2, 0xBE, 0x8D, 0xFD, 0xD0, 0xAF, + 0xC5, 0x84, 0x8A, 0xA3, 0x7D, 0xEC, 0x88, 0x7E, 0x2D, 0x76, 0xD6, 0xBF, 0xA3, 0x95, 0xD1, 0xAF, + 0xC5, 0x96, 0xD6, 0x3A, 0x10, 0x6B, 0xA3, 0xDF, 0x8B, 0xC9, 0x60, 0x9D, 0x26, 0xAD, 0x4E, 0xFC, + 0x5E, 0x4C, 0x44, 0x3A, 0x6C, 0x0A, 0x04, 0xA0, 0xDF, 0x8B, 0xA1, 0x40, 0xBB, 0x25, 0x90, 0x80, + 0x7E, 0x6F, 0x8E, 0x20, 0x74, 0x47, 0x9E, 0xB7, 0x40, 0xB3, 0x74, 0xBF, 0x80, 0x3A, 0x23, 0xCA, + 0x44, 0xB7, 0xDD, 0xF3, 0xAB, 0xAF, 0xC4, 0xB4, 0x02, 0xCF, 0x59, 0x15, 0x98, 0xC7, 0x50, 0x58, + 0x62, 0xC6, 0x8A, 0xA7, 0x02, 0x8B, 0x43, 0x35, 0xD2, 0xC1, 0x3A, 0xBB, 0x23, 0x0B, 0xF9, 0x1E, + 0xE8, 0x91, 0x44, 0xA6, 0x11, 0xB1, 0x87, 0xD0, 0xE6, 0xDE, 0x76, 0x5F, 0x9B, 0x98, 0x53, 0x8C, + 0xEF, 0xE2, 0xF6, 0x54, 0xCC, 0x76, 0x13, 0x5D, 0xD6, 0x4E, 0x6E, 0xFC, 0xEF, 0x4C, 0x7E, 0x98, + 0x9B, 0xDF, 0x26, 0x3B, 0x4D, 0x9B, 0x7C, 0x95, 0x3C, 0x17, 0x88, 0xE4, 0xCB, 0xCD, 0x45, 0x77, + 0x51, 0xCD, 0xAE, 0xD7, 0xEB, 0xEF, 0x5D, 0x3C, 0xA2, 0x63, 0xF5, 0x1D, 0x60, 0xFD, 0x10, 0x4B, + 0x5E, 0x2F, 0xA4, 0xD8, 0x09, 0xEF, 0x4F, 0xFF, 0xBB, 0x5C, 0x31, 0x6C, 0xCD, 0x55, 0xFB, 0x6C, + 0x51, 0xD5, 0xAE, 0x7B, 0x7E, 0xB6, 0x77, 0xDE, 0x3D, 0xDB, 0x2C, 0x76, 0x10, 0x0A, 0x2C, 0x21, + 0xED, 0x4B, 0x81, 0x50, 0x3A, 0xCE, 0x6B, 0xFA, 0x60, 0xC0, 0x1D, 0x84, 0xBC, 0x62, 0xDB, 0x86, + 0x2E, 0x8C, 0x4B, 0x6E, 0x83, 0xE1, 0xAE, 0xA2, 0x76, 0x44, 0xE6, 0x25, 0x7C, 0x11, 0xF8, 0x83, + 0x0E, 0x02, 0xD0, 0xDD, 0x2F, 0x7B, 0xB7, 0xBF, 0x20, 0x7F, 0x08, 0x0D, 0x51, 0x48, 0xD7, 0xCE, + 0x98, 0xFE, 0x6E, 0x30, 0xDC, 0x48, 0xB9, 0x85, 0xB1, 0xD6, 0xB6, 0x0F, 0xC2, 0x2C, 0x5A, 0x77, + 0xA1, 0x1F, 0x98, 0x81, 0xC6, 0x2C, 0xDF, 0x43, 0x13, 0x1E, 0x5E, 0x67, 0x1C, 0x98, 0x2E, 0x5E, + 0x77, 0xFA, 0xC4, 0xB4, 0xBC, 0xA0, 0x31, 0x5A, 0xF2, 0x60, 0x1E, 0xB0, 0x6F, 0x61, 0x47, 0x78, + 0x7F, 0x6A, 0x32, 0x45, 0xD3, 0xC8, 0x56, 0x0C, 0x93, 0xE9, 0x9F, 0x77, 0xF7, 0xFA, 0x67, 0xD7, + 0xC2, 0xD0, 0xAC, 0x8A, 0xBD, 0x6E, 0xB0, 0x9F, 0x47, 0x9C, 0x1B, 0x7B, 0xE7, 0xBA, 0xC3, 0xEE, + 0x74, 0xF5, 0x21, 0x36, 0x0D, 0xBA, 0xF2, 0xB7, 0x3C, 0xFD, 0x91, 0xC3, 0x00, 0x20, 0x84, 0x0D, + 0x14, 0x55, 0x37, 0x87, 0x0D, 0x26, 0xB7, 0x36, 0xF6, 0xAE, 0xBC, 0x5D, 0x1D, 0xE8, 0xCE, 0x18, + 0x9D, 0x1E, 0x13, 0xF0, 0x09, 0xF9, 0x22, 0x02, 0xEA, 0xD5, 0x59, 0xD1, 0x02, 0x8E, 0x81, 0x22, + 0x5A, 0x95, 0xBC, 0x4E, 0x48, 0x98, 0xE7, 0xB8, 0x5D, 0x15, 0x09, 0x98, 0xB1, 0x9E, 0xA7, 0xE6, + 0xBE, 0x15, 0x2F, 0xB7, 0xE2, 0xE5, 0x56, 0xBC, 0xAC, 0xCC, 0xAB, 0xC5, 0x14, 0xC7, 0x02, 0x46, + 0x35, 0xED, 0xCA, 0x30, 0xAF, 0xA4, 0xB0, 0x39, 0x7D, 0xDE, 0x64, 0xCA, 0x9A, 0x11, 0x86, 0x1A, + 0xE1, 0xA7, 0x02, 0xBE, 0x1B, 0x22, 0x68, 0x96, 0x62, 0xAA, 0xA1, 0xDA, 0x8F, 0x67, 0x61, 0x60, + 0xF4, 0x49, 0x58, 0x45, 0x8A, 0x1A, 0xDD, 0x17, 0xBB, 0xDE, 0x2B, 0x7C, 0xC5, 0x27, 0x6E, 0xA5, + 0x2E, 0xA2, 0x13, 0x0F, 0x5D, 0xD8, 0x83, 0xA7, 0xC5, 0xC3, 0x8C, 0xB1, 0x79, 0xB9, 0x10, 0xE3, + 0xC5, 0xFD, 0xD9, 0x13, 0x73, 0x2F, 0x8F, 0x52, 0x8B, 0x53, 0x4F, 0x84, 0x82, 0x3E, 0x71, 0x93, + 0x13, 0xB9, 0x28, 0x02, 0x1A, 0x18, 0xE5, 0xC3, 0xFA, 0x52, 0x22, 0x02, 0xF1, 0x04, 0xDE, 0x1B, + 0xCB, 0xE0, 0xC9, 0xB1, 0x0F, 0xB4, 0x32, 0xA0, 0x8C, 0x0D, 0xBB, 0xC2, 0x0E, 0x05, 0xF8, 0x83, + 0xD1, 0x87, 0x52, 0x56, 0x52, 0x9F, 0x1B, 0x0C, 0x1D, 0x67, 0x74, 0x87, 0xBB, 0xE2, 0x1E, 0xDD, + 0xE1, 0x2A, 0xB7, 0x13, 0xD4, 0x24, 0x7D, 0x11, 0x45, 0x07, 0xAD, 0x66, 0x73, 0xB7, 0xD9, 0x6C, + 0xFA, 0xAE, 0x14, 0xC7, 0x0C, 0x6E, 0x0E, 0xC9, 0xBE, 0xA5, 0xB1, 0xF7, 0xE1, 0x57, 0x62, 0x06, + 0xDC, 0x7B, 0xE2, 0xDC, 0x14, 0xEF, 0xB9, 0x8D, 0x32, 0x01, 0xD6, 0xCB, 0x22, 0xC7, 0x52, 0xBA, + 0x5F, 0x99, 0x48, 0xFF, 0x0C, 0xD2, 0x3C, 0xE7, 0x18, 0x36, 0xEA, 0xCE, 0x4D, 0xA1, 0x0B, 0xB9, + 0x52, 0x66, 0xC9, 0x51, 0xB1, 0x79, 0xDE, 0xC1, 0x4E, 0x9D, 0x8A, 0x8D, 0x12, 0xD8, 0x5D, 0xB8, + 0xCB, 0x39, 0x3D, 0x2C, 0xEF, 0xA6, 0x51, 0x83, 0xED, 0xFC, 0xBF, 0xFF, 0xEB, 0xBE, 0x3D, 0x2E, + 0xBE, 0x98, 0x32, 0xE4, 0xBF, 0xB0, 0x5B, 0x5F, 0xA6, 0x8B, 0xDF, 0xAC, 0x8C, 0x54, 0xA5, 0x7A, + 0xC5, 0x7F, 0x53, 0x08, 0x34, 0xB5, 0x31, 0x25, 0x67, 0x6A, 0xE7, 0x77, 0x59, 0x45, 0x9E, 0x82, + 0x02, 0x77, 0x3D, 0xF3, 0x10, 0xD5, 0xF2, 0x11, 0xFF, 0x9A, 0xF8, 0xD6, 0xD2, 0xD1, 0xBD, 0x17, + 0x61, 0x92, 0xA5, 0xC6, 0x12, 0x34, 0xB1, 0x01, 0xA8, 0x3E, 0x8D, 0x67, 0x12, 0xB4, 0x8B, 0x23, + 0xAC, 0xE8, 0x68, 0x13, 0xD0, 0x94, 0x2E, 0xC4, 0x88, 0xA6, 0xB4, 0x21, 0x9F, 0x57, 0xD9, 0xCD, + 0xC5, 0xD9, 0x9E, 0x65, 0x28, 0x0E, 0xDE, 0x12, 0xAF, 0x06, 0x6B, 0x83, 0xE1, 0x8E, 0xE7, 0xE0, + 0xB8, 0x31, 0xFD, 0x3A, 0x7D, 0x11, 0xD3, 0xFB, 0xBD, 0xD0, 0xFA, 0xE6, 0xD1, 0xCE, 0xB3, 0x0D, + 0x92, 0xB7, 0xBA, 0xAB, 0x9B, 0x43, 0x86, 0xDB, 0x59, 0x4E, 0x4D, 0xCB, 0xB6, 0x4F, 0x5E, 0x2A, + 0x86, 0x31, 0x7F, 0x9F, 0xC5, 0xF5, 0xB6, 0x25, 0x4A, 0xA0, 0x09, 0xBB, 0xA0, 0x90, 0x00, 0x5D, + 0x7D, 0x88, 0x76, 0xB4, 0xC0, 0x97, 0x6C, 0x84, 0xEE, 0x0C, 0x22, 0xB0, 0x52, 0x25, 0x23, 0xD9, + 0x8E, 0x23, 0x60, 0xC9, 0x61, 0xDD, 0x6F, 0x51, 0x42, 0xC5, 0x50, 0x9A, 0xD8, 0x0B, 0x03, 0x09, + 0x19, 0x7A, 0x23, 0x22, 0x78, 0x46, 0x36, 0xA1, 0xEC, 0x86, 0x2E, 0x53, 0x82, 0x2C, 0x23, 0x45, + 0x96, 0x60, 0x3C, 0x73, 0xA7, 0x96, 0x5A, 0x85, 0xDA, 0xF6, 0x59, 0x86, 0x6D, 0x93, 0x81, 0xFD, + 0xDA, 0x1A, 0x0E, 0x31, 0xAC, 0x5A, 0x6A, 0x71, 0x85, 0x81, 0x56, 0x5A, 0xDB, 0x13, 0xE6, 0x7C, + 0x39, 0xDC, 0x4A, 0xB4, 0xBE, 0xC2, 0x53, 0x9B, 0xD6, 0x0E, 0xD3, 0x41, 0xF4, 0xC2, 0xCA, 0x22, + 0xCC, 0x63, 0xE2, 0x78, 0x10, 0x88, 0xDB, 0x1C, 0x67, 0xE8, 0xBE, 0x15, 0x0A, 0x5D, 0xA7, 0x19, + 0x9A, 0xCE, 0xD5, 0x67, 0x76, 0x7B, 0xD3, 0x6F, 0x60, 0x94, 0xCF, 0xC0, 0x37, 0xA4, 0x39, 0x06, + 0xE3, 0x11, 0x99, 0xA1, 0x3F, 0x80, 0xCE, 0xE8, 0xE3, 0xA5, 0xBE, 0xE7, 0xE8, 0x8A, 0x39, 0xF4, + 0x0D, 0x69, 0x73, 0xE9, 0x73, 0x11, 0x11, 0x84, 0xC2, 0x25, 0xD0, 0xD3, 0x03, 0xDA, 0xE6, 0x89, + 0xF1, 0x49, 0x37, 0xD2, 0xDF, 0x2E, 0xCE, 0xEB, 0x97, 0xEF, 0x7B, 0xEC, 0xCA, 0xF4, 0xF8, 0x50, + 0x7A, 0x90, 0xDC, 0x28, 0xA6, 0xAF, 0x88, 0xFE, 0xC7, 0x96, 0xC3, 0xE3, 0xD6, 0xFF, 0x7C, 0x7D, + 0xB4, 0xA4, 0xDF, 0xE9, 0xE6, 0x6B, 0x94, 0x51, 0x8C, 0xAA, 0x4C, 0xA5, 0xA4, 0x01, 0xB0, 0xE3, + 0x65, 0x89, 0x2C, 0x34, 0xEB, 0x95, 0x89, 0x2C, 0x82, 0x55, 0x54, 0x2E, 0xB2, 0xC4, 0x17, 0x31, + 0xBD, 0x2B, 0x6B, 0x24, 0xB2, 0x60, 0x36, 0x1C, 0xCF, 0x22, 0x77, 0xC2, 0xAA, 0x44, 0x16, 0x72, + 0x4D, 0x14, 0x89, 0x76, 0x5E, 0x87, 0xC4, 0x12, 0xB2, 0x42, 0xC2, 0xFC, 0x50, 0x66, 0x31, 0x80, + 0xB6, 0xB8, 0xC6, 0xD0, 0xC9, 0x73, 0x14, 0xE4, 0x22, 0xD3, 0x13, 0x5C, 0x27, 0x02, 0xDE, 0xAD, + 0x30, 0x52, 0xDE, 0x70, 0xED, 0x83, 0x6E, 0x14, 0x1C, 0x97, 0x18, 0xD3, 0x4F, 0x1E, 0x62, 0x6B, + 0x68, 0xA4, 0x8E, 0xCC, 0x2D, 0x61, 0xA3, 0x66, 0xF4, 0xB8, 0xF0, 0xA6, 0x44, 0x12, 0x9F, 0xBC, + 0x80, 0xBD, 0xBA, 0x0C, 0x88, 0xCB, 0x91, 0x5E, 0xC6, 0x38, 0xC5, 0x92, 0xFE, 0xA5, 0x90, 0xA5, + 0x84, 0x72, 0x48, 0x99, 0xE4, 0x33, 0x14, 0x8D, 0x38, 0x39, 0xA6, 0xF4, 0x7A, 0x7B, 0xDF, 0x4E, + 0x7F, 0xD9, 0xEB, 0xF7, 0xBA, 0xB7, 0x77, 0x5F, 0x90, 0x4E, 0x03, 0xB1, 0xE2, 0x1B, 0x3C, 0x68, + 0x47, 0xA8, 0xF4, 0x52, 0x29, 0x67, 0x2B, 0xDB, 0x58, 0xC1, 0x20, 0x04, 0xBC, 0x80, 0x49, 0xDF, + 0xF2, 0x1D, 0x35, 0xE5, 0x18, 0x2F, 0x4D, 0x26, 0xC1, 0x11, 0x9E, 0xDA, 0x3F, 0xD0, 0x44, 0xB0, + 0x4D, 0x72, 0x2B, 0xC4, 0xF3, 0x92, 0xC7, 0xED, 0xD4, 0x51, 0x9B, 0x3A, 0xD8, 0x1D, 0x20, 0x7A, + 0x6D, 0xE6, 0x72, 0x4B, 0xA7, 0xBF, 0x9D, 0xF7, 0xC0, 0x9D, 0x3E, 0x19, 0x45, 0xD2, 0x92, 0x39, + 0x0E, 0xC5, 0xA9, 0x63, 0xFB, 0xAA, 0x57, 0xF2, 0x1E, 0xB8, 0xD4, 0xB1, 0xBA, 0x3C, 0xCD, 0x82, + 0x22, 0xCE, 0x24, 0x16, 0x44, 0xA3, 0xCC, 0xD0, 0xCD, 0x05, 0x03, 0x33, 0x75, 0x4D, 0x9C, 0xA8, + 0x44, 0xA1, 0x32, 0x05, 0x41, 0x34, 0xED, 0x8B, 0x4B, 0x5B, 0xD8, 0x20, 0x4F, 0xE9, 0x2F, 0x17, + 0x5F, 0xEB, 0xE7, 0xEF, 0xCF, 0x8E, 0x99, 0x44, 0x0C, 0x01, 0xDD, 0x08, 0x59, 0x5F, 0xF5, 0x36, + 0xF5, 0xFE, 0x68, 0x81, 0x57, 0x72, 0xC3, 0x3C, 0xD1, 0xD1, 0xBC, 0x6B, 0x3C, 0x61, 0x4A, 0x12, + 0x72, 0x24, 0x97, 0xAC, 0x94, 0x14, 0x27, 0xE9, 0x1B, 0x85, 0xB9, 0x45, 0xD9, 0xB7, 0xFE, 0x69, + 0xBE, 0x53, 0xF9, 0xF2, 0x82, 0xF5, 0xC5, 0x61, 0xF1, 0xC9, 0x74, 0xDD, 0x3B, 0xEB, 0x9B, 0x7B, + 0xDF, 0x27, 0x27, 0xB0, 0xF0, 0x78, 0x4D, 0xCE, 0x36, 0x17, 0xB0, 0xB0, 0x9A, 0xE5, 0x47, 0xF6, + 0x67, 0xCC, 0x79, 0xC5, 0xE1, 0xFD, 0x5F, 0x05, 0x58, 0x08, 0x44, 0xD2, 0x77, 0x8E, 0xDC, 0xD4, + 0x76, 0x74, 0xBE, 0x2B, 0xDC, 0x28, 0x28, 0x57, 0x12, 0x1C, 0x8F, 0x6F, 0xC5, 0x4E, 0x23, 0x61, + 0xE1, 0x6E, 0x93, 0xF3, 0x44, 0x24, 0xA0, 0xD3, 0xF5, 0x14, 0xCF, 0x77, 0x23, 0x29, 0x6A, 0x4B, + 0x1F, 0x98, 0x2F, 0x19, 0xDA, 0x5F, 0xE2, 0xAB, 0xEC, 0x20, 0xA1, 0x2C, 0xAA, 0x4A, 0xC4, 0x0B, + 0xFD, 0xAC, 0x5F, 0xEA, 0xB3, 0xC3, 0x85, 0x0A, 0x86, 0x0A, 0x95, 0x0D, 0x13, 0x9A, 0x2B, 0x2A, + 0x28, 0x3D, 0x22, 0x08, 0xD7, 0x30, 0x57, 0x40, 0x50, 0xA4, 0xE1, 0x34, 0x68, 0x23, 0x90, 0x49, + 0x84, 0x02, 0x3D, 0xE9, 0x03, 0x7D, 0xB1, 0x48, 0xA0, 0xE9, 0x28, 0xA0, 0xE4, 0xAE, 0xE5, 0x46, + 0xFF, 0x64, 0xCE, 0xBD, 0x5C, 0xE0, 0xCF, 0xEC, 0xA0, 0x9F, 0x34, 0x4C, 0xFC, 0x22, 0xF2, 0x3A, + 0xB9, 0xE9, 0x17, 0xD8, 0x15, 0x30, 0x85, 0x50, 0x50, 0x06, 0xD1, 0x8B, 0xA9, 0x0E, 0xD7, 0xA0, + 0x11, 0xB0, 0x02, 0x11, 0xD0, 0x0D, 0x73, 0x03, 0xAD, 0x74, 0x5F, 0xEC, 0x8E, 0x4C, 0x31, 0x05, + 0xF4, 0xDD, 0x05, 0xC5, 0x36, 0xF8, 0x14, 0xAA, 0xB9, 0x9E, 0xA3, 0xCB, 0xEC, 0x1F, 0xE4, 0x77, + 0x85, 0xE9, 0x52, 0xE4, 0x3B, 0x93, 0x24, 0x88, 0xB1, 0x98, 0xF0, 0x46, 0xD1, 0x94, 0x8D, 0x8B, + 0x32, 0x84, 0xAC, 0xEF, 0xB2, 0x8E, 0xC0, 0xD2, 0x77, 0xC3, 0x51, 0xE9, 0x16, 0xD1, 0x55, 0x6E, + 0xDA, 0xEF, 0xCD, 0x7E, 0x1F, 0x33, 0x91, 0x46, 0x6E, 0x4C, 0x3B, 0x53, 0xA6, 0x25, 0x7C, 0x85, + 0xB5, 0x66, 0xDF, 0xC5, 0xCE, 0x75, 0xEF, 0x5A, 0x26, 0x63, 0x50, 0xCA, 0xA4, 0xE5, 0x81, 0xE5, + 0xC1, 0x3E, 0xCE, 0x1A, 0xC4, 0x4E, 0x6F, 0x3F, 0xCF, 0xB5, 0xEA, 0x6C, 0xA6, 0xBB, 0xC4, 0x5D, + 0xEA, 0x41, 0x1F, 0xF0, 0x97, 0x96, 0xB3, 0x53, 0xBD, 0x9F, 0x33, 0xC1, 0xB0, 0x56, 0xFB, 0x17, + 0x2E, 0xA7, 0xDC, 0xB6, 0x05, 0xCD, 0x36, 0x69, 0xEB, 0x5A, 0x45, 0x09, 0xAC, 0xBD, 0x46, 0x1B, + 0x24, 0x26, 0x5D, 0x6A, 0x73, 0x5A, 0x9B, 0x46, 0x53, 0xAD, 0xC5, 0x69, 0x6A, 0xAD, 0xB6, 0x6C, + 0x3E, 0x9A, 0x6A, 0x6D, 0x22, 0x4D, 0xB5, 0x8B, 0xD2, 0x54, 0x67, 0x8D, 0x36, 0xA8, 0x5D, 0x9E, + 0xA6, 0xDA, 0x9B, 0x46, 0x53, 0xED, 0xC5, 0x69, 0x6A, 0xAD, 0xB6, 0x6C, 0x3E, 0x9A, 0x6A, 0x6F, + 0x22, 0x4D, 0x75, 0x8A, 0xD2, 0xD4, 0xFE, 0x1A, 0x6D, 0x50, 0xA7, 0x3C, 0x4D, 0x75, 0x36, 0x8D, + 0xA6, 0x3A, 0x8B, 0xD3, 0xD4, 0x5A, 0x6D, 0xD9, 0x7C, 0x34, 0xD5, 0x59, 0x35, 0x4D, 0x85, 0x7A, + 0x3D, 0xA9, 0xD4, 0x68, 0x8B, 0x2F, 0x73, 0xB9, 0x90, 0xDC, 0x4C, 0xD1, 0xCB, 0xD7, 0x47, 0xEE, + 0x74, 0x7B, 0xB5, 0x93, 0xC0, 0x88, 0xC0, 0xD9, 0x8D, 0xA5, 0xE5, 0x5D, 0x1E, 0xC4, 0x2F, 0x0B, + 0xE2, 0x53, 0xAA, 0x25, 0xA6, 0x29, 0x07, 0x28, 0x6B, 0xEE, 0x9F, 0x36, 0xEF, 0x77, 0x0B, 0x18, + 0xE5, 0xA7, 0x4D, 0xF9, 0xA8, 0x83, 0xCF, 0x6E, 0x37, 0xDB, 0x78, 0x5F, 0x9D, 0xAD, 0xE0, 0xCA, + 0x64, 0xDD, 0x5E, 0x24, 0xC6, 0x2A, 0x4C, 0x45, 0x82, 0xBA, 0xBD, 0x63, 0x29, 0x9A, 0xAA, 0x80, + 0xF2, 0x2F, 0x63, 0x61, 0x55, 0x95, 0xBB, 0x2E, 0xA3, 0x54, 0xB2, 0x0C, 0xF3, 0x58, 0x73, 0x34, + 0x29, 0xFE, 0xB5, 0x2E, 0x40, 0xDA, 0x60, 0xD0, 0x17, 0x19, 0x17, 0xD2, 0x7B, 0x8B, 0xE4, 0xB9, + 0xA6, 0xBC, 0x49, 0xE2, 0x5D, 0xB4, 0x31, 0x44, 0xE2, 0x84, 0xC9, 0xB0, 0x40, 0xB7, 0xEB, 0x9C, + 0xC9, 0x1A, 0x1C, 0x30, 0xC8, 0x55, 0x0F, 0xE3, 0x70, 0x1D, 0x18, 0x7C, 0x2D, 0xED, 0x0C, 0xE5, + 0xEC, 0x86, 0x77, 0x67, 0x3D, 0xB6, 0xC7, 0xBE, 0x9D, 0xF7, 0x36, 0xDD, 0x78, 0x08, 0x0B, 0x81, + 0x55, 0xCC, 0x65, 0x3E, 0x8C, 0x35, 0x9D, 0x06, 0x72, 0x12, 0x44, 0x09, 0x2B, 0xA2, 0xA7, 0xDA, + 0xDF, 0x34, 0xFB, 0xC5, 0xED, 0x88, 0x33, 0x16, 0xB1, 0xA0, 0x25, 0x31, 0xF7, 0x56, 0xA5, 0xC4, + 0x6D, 0xCA, 0x9D, 0x6A, 0x9F, 0x19, 0x3A, 0x70, 0x84, 0xDA, 0x09, 0x82, 0x55, 0xFC, 0x3D, 0x9B, + 0x8F, 0x2E, 0x7E, 0x1D, 0x32, 0x19, 0x34, 0x93, 0x5A, 0xC3, 0x1A, 0x5F, 0x5E, 0xF0, 0xEE, 0xA9, + 0xF5, 0x9D, 0x53, 0xAD, 0xB3, 0x65, 0xB3, 0xBC, 0xC1, 0x24, 0xFF, 0x65, 0x06, 0x83, 0x0A, 0x59, + 0x93, 0xED, 0xBB, 0x23, 0x71, 0x7F, 0x82, 0xD5, 0xFC, 0x80, 0x29, 0x0D, 0xF5, 0x47, 0x6E, 0x12, + 0x82, 0xBA, 0x54, 0xD0, 0x73, 0x72, 0x9B, 0x22, 0xBE, 0xC1, 0xFB, 0x94, 0x75, 0x61, 0x52, 0x99, + 0xC7, 0x75, 0x08, 0xF2, 0x99, 0x29, 0xBD, 0xE6, 0x0A, 0xAB, 0x89, 0x9E, 0xE7, 0xE1, 0x30, 0x18, + 0x20, 0x5F, 0x9B, 0x2B, 0xBC, 0x00, 0x1A, 0x1E, 0x57, 0x74, 0x95, 0x16, 0x7A, 0x77, 0xC1, 0xDE, + 0xD1, 0xAD, 0x17, 0xEC, 0xA8, 0xEF, 0x46, 0x13, 0xFF, 0xB6, 0xDF, 0xEF, 0x1F, 0xAD, 0xEF, 0x05, + 0x57, 0x5E, 0x2D, 0x9D, 0x79, 0xE3, 0x79, 0xCA, 0xC8, 0xA7, 0xF1, 0x1D, 0xCD, 0xE9, 0xD7, 0x9E, + 0x6E, 0x32, 0x6F, 0x84, 0x4E, 0xF9, 0xEB, 0xBD, 0x6A, 0x11, 0xF8, 0xB3, 0xE5, 0xCE, 0x87, 0xC0, + 0xD8, 0x10, 0xFB, 0x9A, 0x09, 0xA9, 0x09, 0x5F, 0x3E, 0x5E, 0xF1, 0xB5, 0x31, 0x7A, 0x3A, 0xA2, + 0xB8, 0x4C, 0xE1, 0xC0, 0x42, 0xC2, 0x0A, 0xDC, 0xB1, 0x47, 0x38, 0xF3, 0xA7, 0x91, 0xAE, 0x8E, + 0x84, 0xD7, 0x36, 0xCC, 0x51, 0xA5, 0x39, 0xC6, 0x13, 0x6D, 0x23, 0x83, 0xA4, 0x78, 0xFB, 0xC6, + 0x96, 0x72, 0x0A, 0x51, 0x8E, 0x40, 0xA5, 0x62, 0x37, 0x32, 0x69, 0x64, 0x84, 0xED, 0x57, 0x47, + 0x46, 0xB3, 0x4E, 0x92, 0x52, 0x3A, 0xBB, 0x9D, 0x26, 0x1D, 0x94, 0x5D, 0x47, 0x61, 0x13, 0x42, + 0xC5, 0x02, 0x94, 0xA8, 0xDD, 0x2D, 0x04, 0x28, 0xF1, 0xF7, 0x0A, 0x04, 0x28, 0x39, 0x68, 0x21, + 0x01, 0x4A, 0xBC, 0xFB, 0xD2, 0x02, 0x14, 0x68, 0x84, 0xD6, 0x13, 0xD3, 0xCD, 0x7B, 0xCB, 0x07, + 0xD1, 0x89, 0x38, 0x86, 0x10, 0xA9, 0x84, 0xBB, 0x57, 0x4C, 0x9C, 0x4A, 0x11, 0x9B, 0x64, 0xA8, + 0x57, 0xC0, 0x66, 0xB0, 0xF4, 0xB2, 0x68, 0xBE, 0x3E, 0xD7, 0xCB, 0xB3, 0x24, 0x2A, 0xB1, 0x07, + 0x4B, 0x97, 0xA8, 0xC4, 0x30, 0x5B, 0x89, 0xEA, 0xF5, 0x9C, 0x0B, 0x91, 0x1D, 0x2D, 0x7A, 0x14, + 0x4C, 0x9A, 0x2C, 0xEF, 0x28, 0xA8, 0xB2, 0x94, 0x69, 0x14, 0x20, 0x33, 0xF9, 0xDE, 0x17, 0xCF, + 0xD1, 0x41, 0xB3, 0xC7, 0x3C, 0x24, 0xB5, 0xD2, 0x1C, 0x6E, 0xCA, 0x39, 0x79, 0xAA, 0xCB, 0x93, + 0x2F, 0x77, 0xB7, 0x57, 0x20, 0x6C, 0xD1, 0xA7, 0x02, 0xE5, 0x29, 0xAB, 0xAC, 0x76, 0x98, 0xC5, + 0x35, 0xF9, 0x18, 0x43, 0xE4, 0x38, 0x1A, 0xD8, 0xC4, 0xEC, 0x54, 0x99, 0x86, 0x85, 0xD8, 0x29, + 0x86, 0xB5, 0x06, 0x1C, 0x55, 0x4E, 0x9E, 0xD8, 0xA3, 0x1B, 0x2D, 0x1D, 0x87, 0xAC, 0x75, 0xC8, + 0x3D, 0x51, 0x5D, 0xBE, 0xA4, 0x42, 0xBA, 0x14, 0xFA, 0x2B, 0x50, 0x9D, 0x74, 0x55, 0x92, 0x86, + 0x40, 0x9C, 0x8D, 0x90, 0x34, 0xBE, 0x69, 0xA1, 0xA4, 0x81, 0xB6, 0xAF, 0xD5, 0x48, 0x1A, 0x93, + 0x41, 0x27, 0xF4, 0xE6, 0x6B, 0xF6, 0x4B, 0xCB, 0x12, 0x13, 0xDB, 0x33, 0x89, 0x0B, 0x2E, 0x74, + 0xC9, 0x4D, 0x95, 0xBB, 0xD2, 0x4F, 0xF9, 0xBC, 0xB7, 0xEE, 0x12, 0x81, 0xAF, 0x15, 0x2B, 0xD2, + 0xB9, 0xB0, 0x4C, 0xE0, 0x6B, 0xEB, 0x28, 0x13, 0x20, 0x02, 0xA7, 0xCB, 0x04, 0xAD, 0x66, 0xAB, + 0xD5, 0xDC, 0x0A, 0x05, 0xB3, 0x84, 0x82, 0xF8, 0x96, 0x16, 0x12, 0x0A, 0x62, 0x4D, 0x36, 0x5C, + 0x3F, 0x0C, 0x59, 0x52, 0x15, 0x5C, 0xBB, 0xDC, 0xE5, 0x8C, 0x48, 0x47, 0xBF, 0xE1, 0x17, 0x33, + 0xB4, 0x88, 0xB9, 0xEE, 0x65, 0xA2, 0x2D, 0xA7, 0xC1, 0x1B, 0x05, 0x4E, 0xE2, 0x4A, 0x86, 0x62, + 0xF1, 0x5E, 0xFC, 0x46, 0x26, 0x7B, 0xFA, 0x6B, 0x74, 0x21, 0x73, 0xE1, 0xDA, 0x54, 0x42, 0xEF, + 0xA2, 0xDF, 0xAB, 0x7F, 0xF9, 0xFA, 0xF3, 0xB2, 0xCF, 0xF7, 0x60, 0xB8, 0x25, 0x9F, 0xE3, 0x68, + 0x49, 0xA4, 0x24, 0xC7, 0x18, 0xF2, 0x07, 0x4B, 0xEB, 0xB4, 0x83, 0x94, 0x9C, 0x61, 0x32, 0x65, + 0x71, 0x71, 0x0C, 0x58, 0x5D, 0xA7, 0x3F, 0x76, 0xD1, 0xE8, 0x18, 0x3E, 0x02, 0x21, 0xD8, 0xD3, + 0xC5, 0xCD, 0xB2, 0x88, 0xEB, 0x44, 0x97, 0x75, 0x92, 0x67, 0x29, 0xC6, 0x7A, 0xAC, 0xBB, 0x6E, + 0x3C, 0xCA, 0xFA, 0xEB, 0x60, 0xB0, 0xD6, 0x3E, 0xE7, 0x21, 0x55, 0xCC, 0x93, 0x87, 0x21, 0x1D, + 0x01, 0x67, 0xAC, 0x57, 0x90, 0xE6, 0x4D, 0xF7, 0xEC, 0x38, 0x60, 0xA5, 0x34, 0x36, 0x3C, 0xA8, + 0x31, 0xD7, 0x7B, 0xC6, 0x1D, 0x92, 0xD7, 0xE9, 0xC7, 0x82, 0x8D, 0xFE, 0xA5, 0x76, 0xD2, 0xED, + 0x1E, 0x9F, 0x9E, 0x1E, 0x9F, 0x9D, 0x1D, 0x9F, 0x9F, 0x1F, 0x5F, 0x5C, 0x1C, 0x5F, 0x5E, 0x96, + 0x75, 0x0B, 0x99, 0x6B, 0xA6, 0x3D, 0x45, 0xC7, 0x6C, 0xE0, 0x34, 0x61, 0xF7, 0xB8, 0x64, 0xA4, + 0x59, 0xB1, 0xB3, 0xD0, 0xE6, 0xDC, 0x81, 0x95, 0xBB, 0xD9, 0x4B, 0xFF, 0x62, 0x99, 0x7C, 0x25, + 0xEA, 0x71, 0x21, 0x61, 0x0E, 0x1B, 0xC9, 0x99, 0x0A, 0x91, 0x0D, 0x18, 0x13, 0x70, 0xC2, 0xF1, + 0xF1, 0x81, 0xFD, 0xFD, 0x2F, 0x79, 0x4B, 0x96, 0xC7, 0x4C, 0xFC, 0xF8, 0x40, 0x28, 0xC0, 0xA9, + 0x82, 0xB0, 0x16, 0x80, 0xAE, 0x65, 0x9D, 0x43, 0xA9, 0x72, 0x62, 0xFE, 0xFD, 0x41, 0xA8, 0x2A, + 0xD8, 0xE1, 0x10, 0xA0, 0x2C, 0xA0, 0xCB, 0x06, 0xC9, 0xF2, 0xC0, 0x4C, 0x1C, 0x9F, 0x83, 0x64, + 0x09, 0xDF, 0xCA, 0xAD, 0x4E, 0x2F, 0xDF, 0xB3, 0x82, 0x2B, 0x8E, 0x48, 0x85, 0xF5, 0x27, 0x4B, + 0xEA, 0x18, 0xEE, 0x2E, 0xE3, 0xDF, 0x75, 0x0F, 0x5D, 0x5F, 0xE4, 0x59, 0x2F, 0x7C, 0x56, 0xC8, + 0x46, 0x49, 0xB7, 0x20, 0x2E, 0xF7, 0x60, 0xE3, 0x24, 0x70, 0x7D, 0xD3, 0xD3, 0x0D, 0xF6, 0x06, + 0x57, 0xF3, 0x06, 0xED, 0x92, 0x2E, 0xC7, 0x9A, 0xD7, 0xDF, 0x4C, 0xDD, 0x93, 0x21, 0x33, 0xEE, + 0x93, 0x62, 0x23, 0xF5, 0x05, 0x97, 0x28, 0xDC, 0x95, 0x8E, 0x2D, 0x00, 0x57, 0x86, 0x05, 0xBF, + 0x7C, 0x93, 0x72, 0x0F, 0x83, 0x32, 0xAF, 0x78, 0xA2, 0x84, 0xAE, 0x6D, 0x3D, 0xE1, 0xED, 0xB1, + 0xD9, 0xD8, 0xDC, 0x90, 0xBA, 0x6A, 0x18, 0xC2, 0x4A, 0x62, 0x4A, 0x2F, 0x2D, 0x94, 0x91, 0x24, + 0x2D, 0x04, 0x01, 0xA5, 0xE2, 0x21, 0x46, 0x40, 0xE5, 0xEE, 0x40, 0x80, 0xC3, 0xAB, 0x89, 0x26, + 0x8D, 0xCD, 0x16, 0xB0, 0x4F, 0xD6, 0x6D, 0x7E, 0x01, 0xD2, 0x01, 0x62, 0xA0, 0xFC, 0x27, 0x8A, + 0xAA, 0xEA, 0x9A, 0x28, 0xF1, 0xA9, 0x71, 0x83, 0x07, 0x79, 0x9B, 0x6C, 0xC1, 0xCC, 0xE9, 0xAC, + 0x11, 0xC1, 0xDA, 0xC1, 0xBA, 0xD8, 0xD8, 0xC7, 0x9B, 0x4F, 0xDD, 0x81, 0x9F, 0xF7, 0x3C, 0xA8, + 0x3C, 0x0D, 0x7F, 0x0E, 0x30, 0x8F, 0x13, 0x45, 0x95, 0x09, 0xDA, 0x02, 0x72, 0x22, 0x8A, 0x9B, + 0x6D, 0xE4, 0x5F, 0x57, 0x4A, 0x98, 0xFF, 0xA8, 0x9A, 0xC5, 0xB7, 0xE3, 0xFB, 0x9F, 0xCE, 0xB9, + 0x4B, 0xF0, 0xE8, 0x01, 0x75, 0x27, 0x0E, 0xDE, 0x69, 0x5E, 0x7D, 0x32, 0x21, 0x83, 0x72, 0xAC, + 0xDA, 0x4E, 0x9B, 0xEE, 0x8D, 0x3B, 0x4C, 0x28, 0x6C, 0x7D, 0x9F, 0xDC, 0x06, 0x97, 0xA5, 0x7A, + 0x66, 0x4B, 0x5F, 0x86, 0xE5, 0x28, 0x33, 0x13, 0x9F, 0x27, 0xC5, 0x03, 0x13, 0xA4, 0x82, 0x52, + 0x02, 0x59, 0xAE, 0xDD, 0xBB, 0x38, 0x83, 0xBA, 0x86, 0xC9, 0x62, 0x66, 0xA6, 0x5B, 0x25, 0xDF, + 0x04, 0xB1, 0x38, 0x83, 0x11, 0xA3, 0xAD, 0xC8, 0xF0, 0x1D, 0x53, 0x0D, 0x70, 0x85, 0x52, 0x5A, + 0x7D, 0x49, 0xFD, 0xE0, 0xA5, 0xAC, 0xDE, 0xD9, 0xC8, 0x15, 0x60, 0xEC, 0xBC, 0x69, 0xDB, 0xE6, + 0xE2, 0x42, 0x67, 0x96, 0xE5, 0x68, 0xBA, 0x29, 0x54, 0xF9, 0x4B, 0x2A, 0x9A, 0x6E, 0xAA, 0xCF, + 0x6C, 0xE7, 0xE6, 0xF3, 0x9F, 0x6F, 0x5F, 0xC2, 0x17, 0x85, 0x72, 0xD1, 0x0F, 0xC2, 0x79, 0x10, + 0x6A, 0x88, 0x7B, 0x0E, 0x34, 0x54, 0xB0, 0x91, 0x65, 0xDB, 0x28, 0x43, 0x05, 0x59, 0xC1, 0x65, + 0x11, 0x1E, 0xB7, 0x21, 0x19, 0x17, 0x9C, 0x2B, 0x24, 0x5E, 0x89, 0x56, 0x23, 0xAE, 0x38, 0x8C, + 0x2B, 0xEA, 0x88, 0x59, 0x70, 0xDE, 0x38, 0xE2, 0x44, 0x82, 0x2E, 0x45, 0x52, 0x11, 0xF4, 0x7A, + 0x51, 0xA3, 0xCB, 0x0F, 0x87, 0x8D, 0x20, 0xD1, 0xFB, 0x56, 0x13, 0x40, 0xD1, 0x60, 0xD7, 0xFA, + 0x58, 0xC7, 0x8F, 0x4D, 0xB4, 0xD9, 0xB0, 0xF7, 0xED, 0x77, 0xF8, 0xF4, 0x15, 0x1C, 0x57, 0x52, + 0xE0, 0x17, 0x26, 0xE1, 0x03, 0x9C, 0x43, 0x87, 0x4D, 0xF4, 0x96, 0x32, 0x16, 0xCD, 0x19, 0x89, + 0x9F, 0x25, 0xB3, 0x9D, 0xB0, 0xE4, 0x09, 0xD0, 0x43, 0x94, 0x2B, 0xA6, 0xD8, 0x65, 0x36, 0x5F, + 0xD0, 0xE0, 0x59, 0x2D, 0x51, 0x89, 0x0A, 0x0B, 0x6E, 0x20, 0xEB, 0x68, 0x5C, 0xD3, 0xA9, 0xAA, + 0x2F, 0x33, 0x74, 0xD7, 0xE3, 0x26, 0x22, 0x30, 0x6A, 0x1B, 0xAB, 0xA6, 0xAF, 0xEE, 0xC0, 0xA3, + 0x8B, 0x41, 0x10, 0xB8, 0xC4, 0x66, 0x51, 0xBA, 0x0F, 0x31, 0xD7, 0x5D, 0x60, 0xD0, 0xA0, 0xA6, + 0xE0, 0xD4, 0x64, 0xF6, 0x90, 0x30, 0x1D, 0x0C, 0xBC, 0xAE, 0x0F, 0x4D, 0x0B, 0xC5, 0x3C, 0xD7, + 0x12, 0x04, 0x46, 0x3C, 0x5C, 0xBE, 0x87, 0x4C, 0x7C, 0x80, 0x6E, 0x1F, 0x01, 0x4D, 0x4A, 0x05, + 0x0B, 0xD3, 0x73, 0x62, 0x89, 0xD2, 0x48, 0x14, 0x00, 0x50, 0x8E, 0xC3, 0xEB, 0xE2, 0x00, 0x4A, + 0x0E, 0x13, 0xA1, 0xB9, 0x4E, 0xD3, 0x0D, 0x09, 0xAE, 0xD5, 0xC4, 0x56, 0x87, 0xCD, 0xA6, 0xBB, + 0xA5, 0xB6, 0xF9, 0xA8, 0x4D, 0xE4, 0xA3, 0xC1, 0x9C, 0xAA, 0x8E, 0xA2, 0x8A, 0x5A, 0xED, 0x63, + 0x6E, 0xF9, 0xDE, 0xEF, 0x6E, 0x71, 0x92, 0xCB, 0xEE, 0x63, 0x19, 0x74, 0x57, 0x42, 0xDC, 0x2B, + 0x67, 0xDB, 0x8F, 0xE4, 0xD9, 0x63, 0x3D, 0x47, 0xB7, 0x30, 0x1B, 0xE7, 0xA6, 0x9B, 0xFA, 0x23, + 0x6B, 0x0A, 0x96, 0x34, 0xD3, 0xF0, 0x3F, 0xD5, 0x6D, 0xC6, 0x45, 0x40, 0x76, 0xBF, 0xD3, 0x3B, + 0x13, 0x85, 0x6B, 0xEA, 0xE5, 0x40, 0x24, 0xE9, 0xD7, 0x92, 0xAE, 0x08, 0x4A, 0xDC, 0x11, 0x14, + 0x5D, 0x59, 0x25, 0xC9, 0x60, 0x8A, 0x05, 0x31, 0x46, 0xE0, 0x23, 0xD2, 0xD5, 0xB9, 0xD7, 0xFA, + 0x80, 0x63, 0x69, 0x9C, 0x6C, 0xE6, 0x3E, 0x75, 0xCD, 0xBB, 0x1F, 0x9A, 0xEF, 0x0E, 0xE9, 0x8F, + 0xC3, 0xA9, 0x6B, 0xDE, 0xE8, 0x3E, 0x89, 0x71, 0x58, 0x30, 0xCE, 0xF1, 0x8A, 0x54, 0x81, 0x6E, + 0x24, 0x01, 0x9C, 0xCC, 0xEB, 0xC6, 0x00, 0x45, 0x29, 0x8B, 0xB3, 0x3E, 0x60, 0xA6, 0x25, 0x9C, + 0x8B, 0xE1, 0xCC, 0xC1, 0x74, 0xCE, 0xFA, 0xA3, 0x2C, 0x8E, 0x48, 0x87, 0xD6, 0x58, 0x31, 0x9F, + 0x83, 0xF3, 0xAA, 0x31, 0x21, 0xE0, 0xC0, 0x11, 0x59, 0x78, 0xBB, 0xC8, 0x28, 0x0D, 0xB2, 0xB0, + 0x61, 0x7E, 0x79, 0xCC, 0x5C, 0x13, 0xE4, 0x8F, 0x93, 0x67, 0xCA, 0x01, 0xBE, 0xD4, 0x6A, 0x37, + 0xC3, 0xBE, 0xD6, 0x4B, 0x4D, 0x28, 0x16, 0x7E, 0xFA, 0x26, 0x76, 0x96, 0xEC, 0xBF, 0x29, 0xE6, + 0x7B, 0xF5, 0x46, 0x9C, 0x1B, 0x6F, 0x82, 0x4E, 0xA2, 0xE7, 0xC6, 0x9B, 0x24, 0xA9, 0x26, 0x51, + 0xB1, 0xFC, 0xD5, 0x80, 0x9D, 0xD3, 0xE5, 0xD2, 0x9C, 0x72, 0x72, 0x33, 0x31, 0x4D, 0x93, 0xC2, + 0xE4, 0x48, 0x58, 0x76, 0x76, 0xA6, 0xAE, 0x8B, 0x75, 0x10, 0x08, 0x4D, 0xED, 0x00, 0x89, 0x41, + 0x12, 0x23, 0x45, 0x25, 0x9A, 0x1E, 0x31, 0x40, 0x5B, 0x32, 0xE2, 0x60, 0x4C, 0xA4, 0x12, 0x50, + 0x0C, 0xE0, 0x2F, 0x88, 0x6B, 0x0E, 0x47, 0x65, 0x09, 0x4D, 0xD0, 0x41, 0x37, 0xC1, 0xBB, 0xE4, + 0xBE, 0x2F, 0x91, 0x9F, 0x0A, 0xE1, 0x3D, 0xE0, 0x7B, 0xF4, 0x18, 0x24, 0x35, 0x78, 0xDA, 0xA0, + 0xCA, 0xBF, 0x43, 0x2E, 0x72, 0x30, 0xBA, 0x0A, 0xD2, 0x19, 0x39, 0xDF, 0xBE, 0xE9, 0xC3, 0xDF, + 0x71, 0x26, 0xFE, 0xA6, 0xA0, 0x85, 0x6E, 0x6D, 0xB2, 0x3C, 0x45, 0x0F, 0x6A, 0xC9, 0x09, 0xC7, + 0xDF, 0xEB, 0x58, 0x8B, 0x55, 0x60, 0x44, 0x12, 0x29, 0x83, 0x7D, 0xBF, 0xD6, 0x33, 0x7D, 0xF1, + 0xD3, 0x8D, 0x75, 0x19, 0x76, 0xB9, 0xB0, 0x7F, 0xEC, 0xF8, 0x94, 0xDE, 0x6D, 0xD6, 0x4E, 0x9A, + 0xB3, 0x8D, 0x6A, 0x8B, 0x8E, 0xD0, 0xAA, 0x9D, 0xB4, 0x96, 0x3B, 0x02, 0xEC, 0x58, 0x7B, 0xB9, + 0x23, 0x74, 0x6A, 0x27, 0x9D, 0xE5, 0x8E, 0xB0, 0x5F, 0x3B, 0xD9, 0x5F, 0xEE, 0x08, 0x07, 0xB5, + 0x93, 0x83, 0xE5, 0x8E, 0x70, 0x58, 0x3B, 0x39, 0x5C, 0xEE, 0x08, 0xEF, 0x6A, 0x27, 0xEF, 0xF2, + 0x46, 0x70, 0xCA, 0x0C, 0x9D, 0x41, 0x70, 0x52, 0xE3, 0x9B, 0xC3, 0xC2, 0x1D, 0x5A, 0xB6, 0x1D, + 0xD4, 0x31, 0xEF, 0xAC, 0xB3, 0xEC, 0xCE, 0xD1, 0x85, 0x51, 0x6A, 0xA2, 0x56, 0xA0, 0x63, 0xCE, + 0x30, 0x70, 0x2F, 0x9C, 0x15, 0xF2, 0xCA, 0x74, 0x3D, 0xC7, 0xC7, 0xF3, 0xE0, 0x45, 0x54, 0x0B, + 0x04, 0xB5, 0x1E, 0x4E, 0x21, 0x50, 0x05, 0x2A, 0x54, 0x38, 0xAE, 0xA6, 0x3A, 0x2F, 0xE5, 0x60, + 0x34, 0xD5, 0x7C, 0x7A, 0x0B, 0xA6, 0x20, 0x98, 0xD0, 0x26, 0x22, 0xCB, 0x7B, 0x69, 0x7F, 0xA3, + 0x9C, 0xD5, 0xCC, 0xA1, 0x42, 0x90, 0x7F, 0xBF, 0x6E, 0x94, 0x0C, 0xCC, 0xAD, 0xFA, 0x32, 0xE2, + 0x8E, 0x66, 0x30, 0xB6, 0xB9, 0xE9, 0x12, 0xE8, 0xC3, 0x1B, 0x53, 0xFC, 0x22, 0xC7, 0xA0, 0x3C, + 0x69, 0xB5, 0x8A, 0x8B, 0x8C, 0xE9, 0x99, 0xAE, 0x4A, 0x93, 0xA1, 0x58, 0x27, 0xDC, 0x2A, 0xBC, + 0xDF, 0x0F, 0xC7, 0x27, 0xCB, 0x1E, 0xB2, 0x1A, 0xD0, 0x48, 0xD0, 0x65, 0xD9, 0xE1, 0xDA, 0x74, + 0x7D, 0xD4, 0xC6, 0x46, 0x5D, 0x4C, 0x2C, 0x07, 0xD1, 0x44, 0x1E, 0xE7, 0x3B, 0xDD, 0xEE, 0x1A, + 0x00, 0x51, 0x5F, 0x03, 0xFD, 0x42, 0xE6, 0x30, 0x86, 0x67, 0x2C, 0x78, 0xB8, 0x5C, 0x14, 0x4A, + 0x99, 0xC3, 0x8A, 0xB0, 0x47, 0x2E, 0xD5, 0xB6, 0x70, 0x3F, 0x61, 0xBD, 0x8A, 0x9C, 0x40, 0x34, + 0x13, 0xB3, 0x82, 0x1E, 0xEF, 0xA6, 0x12, 0x7E, 0x97, 0x52, 0xD7, 0x68, 0x83, 0xE2, 0x3A, 0xB2, + 0xD9, 0x9D, 0x5C, 0x67, 0x6F, 0x04, 0xEA, 0xCC, 0x19, 0xD1, 0xCC, 0xEF, 0xE3, 0xF1, 0x72, 0x5D, + 0xE6, 0x53, 0x87, 0xAC, 0xA5, 0x9A, 0x69, 0xA7, 0xCD, 0x28, 0x5D, 0xB9, 0x2F, 0xD4, 0x7A, 0x36, + 0x33, 0xA4, 0xAE, 0xD9, 0xCE, 0x78, 0xBC, 0xF2, 0xCB, 0xB4, 0x6E, 0xEF, 0x0C, 0xF5, 0x36, 0x99, + 0x46, 0xC7, 0x53, 0x4C, 0x15, 0xEF, 0xD5, 0xAC, 0xB1, 0xAC, 0xA3, 0x0E, 0x8A, 0xA3, 0x0C, 0xF3, + 0x0E, 0xB0, 0x4C, 0x1A, 0x4E, 0x82, 0x8F, 0x36, 0x2E, 0x8E, 0xA9, 0xB4, 0x80, 0x06, 0xBB, 0x43, + 0xFB, 0x0B, 0xFC, 0xDF, 0x77, 0x7D, 0xC5, 0x30, 0x9E, 0x51, 0xE1, 0x34, 0xBD, 0xA0, 0x0C, 0x0E, + 0xD6, 0xF5, 0xD3, 0xA6, 0xFA, 0x43, 0xF7, 0x27, 0x8C, 0xE0, 0x54, 0x0C, 0x95, 0xC2, 0x9B, 0x34, + 0xA6, 0xF9, 0x0E, 0xF9, 0x3F, 0xC9, 0x17, 0xE0, 0x1B, 0xFD, 0xDE, 0x91, 0xA5, 0xBC, 0xBA, 0x63, + 0xCB, 0x17, 0x21, 0x9F, 0x8A, 0xA6, 0x89, 0xDB, 0xBB, 0xCF, 0xDD, 0x8B, 0xE0, 0x06, 0x05, 0xE6, + 0xEF, 0x90, 0xEF, 0xD4, 0x40, 0xFF, 0x8E, 0x3E, 0x24, 0x0A, 0xC6, 0x13, 0x00, 0xD7, 0x1F, 0x5B, + 0x98, 0xBC, 0xE8, 0xCC, 0x3D, 0x66, 0x77, 0x96, 0xA3, 0x8E, 0x76, 0x5A, 0xAD, 0x77, 0x00, 0x6A, + 0x76, 0xF1, 0xB7, 0xBF, 0xEE, 0xEC, 0xB7, 0xF1, 0xAF, 0x4B, 0x80, 0x9E, 0x07, 0x2C, 0xD9, 0x55, + 0x74, 0x75, 0xE7, 0xF0, 0xFD, 0xE4, 0x91, 0x28, 0x1B, 0xC0, 0x1E, 0xDB, 0xB1, 0xA7, 0xF0, 0xF1, + 0x5D, 0x13, 0x3E, 0xBE, 0xA6, 0xE0, 0x04, 0x89, 0xC5, 0x15, 0x5D, 0x2E, 0xD4, 0xB2, 0x29, 0xB6, + 0xD8, 0x75, 0x42, 0x6A, 0xD3, 0x95, 0x87, 0x2B, 0xE4, 0x32, 0xA3, 0xCF, 0x1C, 0xA9, 0xED, 0xF7, + 0xD5, 0xB0, 0xA1, 0x60, 0xB0, 0xB2, 0x0C, 0x48, 0xB4, 0x63, 0x3B, 0x4A, 0xE3, 0xA1, 0xA1, 0x34, + 0x66, 0x42, 0xBF, 0x87, 0x07, 0x8D, 0x28, 0x92, 0xFB, 0x16, 0xF8, 0xD1, 0x0B, 0xDC, 0xED, 0x0B, + 0x06, 0x42, 0x26, 0x28, 0x51, 0x07, 0x5E, 0xF2, 0x0B, 0xA0, 0x12, 0x77, 0x2C, 0x0E, 0x42, 0xA4, + 0x48, 0xB4, 0xF1, 0xEA, 0xA6, 0x6A, 0xF8, 0xC8, 0x05, 0xB0, 0xD2, 0x8F, 0x89, 0x6E, 0x1D, 0x6E, + 0x83, 0x7D, 0xB1, 0x90, 0x35, 0x50, 0xA9, 0x2D, 0xC5, 0x60, 0xDD, 0xDB, 0x1E, 0x16, 0xB2, 0xF0, + 0x0D, 0x4A, 0x1E, 0x16, 0x34, 0x88, 0x06, 0x19, 0x35, 0x8E, 0xC6, 0x5B, 0x32, 0x2E, 0x44, 0xC6, + 0x21, 0xFA, 0x95, 0x21, 0xE0, 0xA0, 0xD1, 0xCB, 0x92, 0x6E, 0x86, 0x6A, 0x9E, 0xA5, 0x9B, 0xF7, + 0x9F, 0x41, 0xB8, 0x1A, 0x6F, 0xFA, 0x95, 0x9F, 0x58, 0xC5, 0x5C, 0xDA, 0x77, 0xAC, 0xE9, 0x34, + 0x88, 0x63, 0xF0, 0x49, 0x68, 0xDD, 0xAE, 0x68, 0xFA, 0xE2, 0xD7, 0x77, 0x33, 0x96, 0x30, 0xA7, + 0xBA, 0xED, 0xDB, 0x86, 0xA5, 0x68, 0x5F, 0xF8, 0xD3, 0xA5, 0xEE, 0x8C, 0xB1, 0x2C, 0xEB, 0xB9, + 0xFE, 0x58, 0xA4, 0xBA, 0x65, 0x21, 0x35, 0x67, 0xAA, 0xF3, 0xDA, 0x89, 0x84, 0x72, 0xF0, 0x20, + 0x27, 0xE3, 0x28, 0x31, 0x28, 0x8A, 0xE7, 0xF0, 0x1E, 0x82, 0x26, 0x7F, 0xE3, 0x0E, 0x72, 0xC5, + 0x6F, 0xF6, 0xD0, 0x51, 0x40, 0x69, 0xC9, 0x8C, 0x72, 0x78, 0x6C, 0x36, 0x9A, 0xF3, 0x58, 0xD2, + 0xB3, 0x8F, 0xBB, 0x19, 0x04, 0x3D, 0xCB, 0x9F, 0xF5, 0x0C, 0xE1, 0x12, 0x05, 0xC2, 0x5C, 0x3E, + 0xAD, 0xA1, 0xD5, 0x4F, 0x4D, 0x74, 0x87, 0x36, 0x3E, 0x1A, 0x82, 0x2E, 0x0B, 0xE1, 0x8B, 0x10, + 0xB8, 0x13, 0x8C, 0x5B, 0x91, 0x62, 0x27, 0xA6, 0xD1, 0xB7, 0x15, 0xE7, 0xE1, 0xD2, 0xA7, 0xEB, + 0x48, 0x97, 0x73, 0xBA, 0xDA, 0x84, 0x59, 0x0D, 0xE4, 0xAC, 0x48, 0xCE, 0x0D, 0xCB, 0x68, 0x84, + 0x17, 0x9C, 0xC2, 0x4D, 0x66, 0xAD, 0x74, 0xBA, 0x08, 0xE3, 0x0F, 0x26, 0x1F, 0xEC, 0x25, 0x3A, + 0xFA, 0x0A, 0x1E, 0xFF, 0xB2, 0x9E, 0xFD, 0xB7, 0x67, 0x13, 0xD2, 0x12, 0x46, 0x99, 0x53, 0xEE, + 0x29, 0x11, 0x0C, 0x58, 0x8D, 0xCB, 0x7E, 0x74, 0x1A, 0x2B, 0x16, 0xAE, 0x68, 0xBD, 0x21, 0x6E, + 0x21, 0xD7, 0x57, 0x74, 0xD3, 0x95, 0xF7, 0xE0, 0x78, 0xDD, 0xC7, 0x06, 0x5C, 0xF1, 0x7C, 0xBC, + 0x63, 0x07, 0x6A, 0x60, 0x63, 0xE5, 0x99, 0x99, 0x16, 0x79, 0xE5, 0x83, 0x62, 0x05, 0x53, 0x47, + 0xE1, 0xCA, 0xC3, 0x0B, 0x77, 0xD0, 0xA8, 0x38, 0x1E, 0x23, 0x84, 0x92, 0x03, 0x9D, 0x83, 0x74, + 0x85, 0x29, 0x85, 0xD7, 0xDD, 0xF5, 0xEA, 0x65, 0xF1, 0xAF, 0xEB, 0x7B, 0x56, 0xB0, 0xF5, 0xDF, + 0x6C, 0xD8, 0x4C, 0x1E, 0x5A, 0x4B, 0xF1, 0x2B, 0x2C, 0x56, 0xAD, 0x86, 0xD8, 0x98, 0x5F, 0xB2, + 0x8C, 0x7A, 0x58, 0x59, 0xA0, 0x49, 0xDA, 0xE4, 0x57, 0x8C, 0xBD, 0x59, 0x09, 0x20, 0x6C, 0xEE, + 0xE8, 0x16, 0x7A, 0x4E, 0xA2, 0xC1, 0x41, 0x0D, 0xB9, 0x7B, 0x94, 0x8F, 0x36, 0x18, 0x34, 0x56, + 0xE8, 0x91, 0xED, 0x58, 0x9A, 0x2F, 0xDC, 0x4A, 0x1E, 0xC5, 0xE9, 0x98, 0xCE, 0x6D, 0x77, 0xF1, + 0x22, 0x3C, 0x70, 0x19, 0x41, 0x63, 0x9B, 0xC8, 0x62, 0xAC, 0x04, 0x3B, 0x85, 0xA3, 0x6D, 0x36, + 0xBE, 0xC7, 0x37, 0x97, 0x16, 0x15, 0xDF, 0xE1, 0x45, 0xEA, 0x82, 0xCF, 0xA5, 0xF2, 0xA6, 0xAA, + 0xBE, 0x11, 0xC4, 0xA3, 0x13, 0xE5, 0x46, 0x37, 0x7D, 0x40, 0xFC, 0x62, 0xC5, 0x25, 0x67, 0x38, + 0x3F, 0x89, 0x1C, 0x17, 0xEF, 0xA6, 0x94, 0x66, 0xD9, 0x7F, 0xC4, 0x75, 0x1C, 0x06, 0x75, 0x8F, + 0x5F, 0xB8, 0x34, 0x26, 0xE2, 0x6F, 0xC8, 0x24, 0x42, 0x84, 0xF5, 0x69, 0x9F, 0x10, 0x6F, 0x43, + 0xCA, 0x98, 0x4A, 0xA6, 0x9D, 0x4A, 0x10, 0x4C, 0x99, 0xF8, 0xF8, 0x92, 0xBB, 0xD4, 0x58, 0xAE, + 0x7A, 0x84, 0x6E, 0x1D, 0x9C, 0xB6, 0x39, 0xA6, 0x25, 0xEF, 0x03, 0xE0, 0x76, 0x5A, 0xB0, 0x9E, + 0xE7, 0xB7, 0x9B, 0x57, 0x35, 0xB3, 0x60, 0x1D, 0xD9, 0xC2, 0x8E, 0xB3, 0x88, 0x4E, 0xEE, 0x18, + 0x38, 0x80, 0x54, 0x8F, 0xB3, 0x50, 0xB4, 0xC0, 0x90, 0xF6, 0xCC, 0x1E, 0xE6, 0x55, 0x9A, 0x8B, + 0xB8, 0x1B, 0x97, 0x77, 0xAC, 0x0D, 0x2F, 0xF4, 0xB3, 0x8D, 0x5C, 0x8A, 0xA1, 0x0F, 0x4D, 0xE0, + 0x14, 0x64, 0xB0, 0x13, 0xD0, 0x81, 0xC7, 0x9F, 0xB8, 0x17, 0x93, 0xE9, 0x8B, 0x47, 0x53, 0xE5, + 0x2A, 0x0C, 0xC9, 0xAE, 0x0B, 0x04, 0x2F, 0x17, 0xD4, 0x1D, 0x86, 0xB1, 0x9E, 0x51, 0x73, 0x10, + 0x5C, 0x11, 0x45, 0xF5, 0xC7, 0x4E, 0xA3, 0xB5, 0xDF, 0x68, 0x1D, 0x14, 0xD1, 0x1A, 0x04, 0x2C, + 0x4E, 0x3E, 0xC0, 0xC1, 0x33, 0xA4, 0x80, 0xE1, 0xA8, 0x8C, 0x2C, 0xBA, 0xEC, 0xC9, 0xAF, 0x4E, + 0x15, 0x27, 0x3C, 0x7C, 0x5B, 0xED, 0x1A, 0x50, 0xE6, 0x77, 0xF8, 0xA3, 0xD9, 0xCC, 0xE7, 0x16, + 0x12, 0xA2, 0x4F, 0xBA, 0xE6, 0x8D, 0x8E, 0x3B, 0xCD, 0x26, 0x85, 0x83, 0x03, 0x8A, 0xC8, 0x8E, + 0x0B, 0x19, 0x6C, 0xD2, 0xE7, 0x34, 0x23, 0x4C, 0xAF, 0xF3, 0xEE, 0xBF, 0xE6, 0x98, 0x6E, 0xE4, + 0xDA, 0xAB, 0x32, 0xBC, 0x16, 0x51, 0xAF, 0x93, 0x8A, 0x62, 0xC1, 0x5C, 0x73, 0x03, 0xDD, 0x00, + 0xEC, 0x11, 0x05, 0x21, 0xEE, 0x81, 0x49, 0xD1, 0x47, 0x32, 0x67, 0xF8, 0xF7, 0x63, 0xDD, 0x0B, + 0xD0, 0xE0, 0x92, 0x9E, 0x5B, 0xA6, 0x4A, 0x5E, 0x71, 0x51, 0x98, 0xA1, 0xF6, 0xFE, 0xB3, 0xA2, + 0x7B, 0x18, 0x30, 0xB9, 0x97, 0x3D, 0xA8, 0x78, 0x91, 0x9D, 0x5E, 0x7D, 0x99, 0xC3, 0xAB, 0xB3, + 0x32, 0xCF, 0xC2, 0x00, 0x93, 0xE1, 0xAC, 0xF0, 0x4D, 0xDD, 0x7B, 0xE3, 0x4E, 0x0E, 0x86, 0xFB, + 0x67, 0x26, 0x4C, 0x11, 0x74, 0x05, 0xC3, 0x00, 0x16, 0x48, 0x3F, 0x08, 0x8F, 0xC9, 0xB5, 0x50, + 0x98, 0x6D, 0x93, 0xD9, 0x23, 0xA0, 0x5D, 0x0C, 0xBF, 0xEB, 0x9D, 0xAD, 0xDA, 0xE5, 0x2F, 0xDB, + 0xB5, 0x28, 0x89, 0xCE, 0xB8, 0x9A, 0xB2, 0xD1, 0xA6, 0x59, 0xD8, 0x99, 0xCA, 0xFE, 0x26, 0x61, + 0x79, 0x8A, 0xEB, 0xF5, 0x3D, 0x14, 0x9D, 0xA6, 0x0A, 0x9B, 0xE4, 0x9A, 0x87, 0x48, 0xDA, 0x09, + 0x3B, 0x08, 0xAD, 0x3F, 0x57, 0xB0, 0x3F, 0x18, 0xFF, 0x42, 0x4F, 0x4B, 0xD5, 0x35, 0x99, 0xF4, + 0x15, 0x9F, 0xDB, 0xA2, 0xB5, 0x4C, 0x9A, 0xB5, 0x93, 0x5B, 0x8B, 0xF2, 0xCD, 0x95, 0x2C, 0x67, + 0xD2, 0xAA, 0x9D, 0x9C, 0x2A, 0x2E, 0x2F, 0xDD, 0xAE, 0x8D, 0xD9, 0x18, 0x7B, 0xEB, 0x51, 0x05, + 0xA5, 0xE7, 0x0B, 0xF7, 0x58, 0x61, 0xE5, 0xC4, 0x68, 0x55, 0x0B, 0x84, 0xDA, 0x47, 0xCC, 0xC2, + 0x28, 0x2E, 0x4B, 0x1D, 0x06, 0x73, 0x15, 0xCE, 0x1D, 0x41, 0x02, 0x87, 0x1E, 0x25, 0x70, 0xF8, + 0x6A, 0xE2, 0x97, 0xE4, 0x61, 0xD6, 0x58, 0xFB, 0x7C, 0x34, 0x86, 0x35, 0xBC, 0xB3, 0xFA, 0xE7, + 0x67, 0x4A, 0x66, 0x51, 0xA1, 0x15, 0xC4, 0x39, 0x0F, 0xE1, 0xB8, 0x1E, 0x62, 0xA8, 0xF3, 0x10, + 0xCF, 0xDC, 0xFE, 0x39, 0xC3, 0xE9, 0xAC, 0x26, 0xE8, 0x59, 0x0E, 0xBD, 0xBA, 0x84, 0x9F, 0x0A, + 0x48, 0xE0, 0xAA, 0x03, 0x20, 0x27, 0x5B, 0x34, 0x23, 0x23, 0x9F, 0x47, 0x3C, 0x96, 0xD2, 0x7B, + 0x86, 0x65, 0xB6, 0x43, 0x95, 0x14, 0x76, 0x68, 0x98, 0xE6, 0x32, 0xB4, 0x71, 0xA1, 0xCC, 0x31, + 0x90, 0xE7, 0xA9, 0x9C, 0xC5, 0x2D, 0x38, 0x45, 0xF5, 0xCD, 0x28, 0xF7, 0x05, 0x79, 0x0B, 0xE6, + 0x81, 0x31, 0x6B, 0xB5, 0xB9, 0x34, 0x47, 0xE5, 0x3B, 0x93, 0xEB, 0xC8, 0x15, 0xD8, 0x70, 0x10, + 0xB6, 0x03, 0x5A, 0xD7, 0xDB, 0xE3, 0x72, 0x26, 0x84, 0xC5, 0xB5, 0xCA, 0xC0, 0xB3, 0x08, 0x3D, + 0x3D, 0x90, 0x95, 0xC1, 0xAA, 0x11, 0x9B, 0x18, 0x06, 0x5A, 0x90, 0x09, 0x44, 0x1D, 0xE9, 0xFC, + 0x11, 0x11, 0xCF, 0x10, 0x8B, 0x91, 0x8A, 0x24, 0x27, 0x6F, 0x8A, 0x89, 0x87, 0x07, 0x1F, 0xF8, + 0x04, 0x37, 0x66, 0x60, 0xB8, 0x0C, 0xBE, 0x67, 0x58, 0xF0, 0x03, 0x04, 0xBE, 0xF1, 0x2E, 0x85, + 0x6B, 0x9A, 0x38, 0xA7, 0x5D, 0x2A, 0x14, 0x0F, 0x4A, 0xAB, 0xEB, 0x3B, 0x8F, 0xFC, 0x99, 0xB2, + 0xD1, 0x2A, 0xD0, 0x99, 0x83, 0xB6, 0xC7, 0xE8, 0x15, 0x2F, 0x8C, 0x9E, 0x54, 0x38, 0xA5, 0x52, + 0x3A, 0x09, 0xF2, 0xC4, 0xC6, 0xED, 0xA3, 0xA3, 0xC9, 0x37, 0x05, 0x75, 0xD1, 0xA5, 0xE9, 0xA1, + 0xC5, 0x8C, 0x35, 0xC5, 0x4D, 0x74, 0xA5, 0x75, 0xCF, 0x08, 0xCA, 0x16, 0x12, 0xF2, 0x27, 0xEF, + 0xAF, 0x2C, 0x12, 0x7A, 0x7E, 0x4A, 0x14, 0x7E, 0x08, 0x8B, 0xD0, 0x62, 0xEE, 0x06, 0xA2, 0x40, 0x2F, 0xFD, 0x1D, 0x24, 0x39, 0x2E, 0x95, 0xDA, 0x80, 0x70, 0xE2, 0x28, 0x1F, 0x27, 0x38, 0x61, - 0xA2, 0x44, 0x62, 0x0C, 0xD8, 0x3C, 0x86, 0xDE, 0x60, 0x4A, 0xCA, 0x34, 0xBA, 0xA3, 0xEF, 0x90, - 0xEE, 0x44, 0xB2, 0x14, 0x83, 0x0E, 0x05, 0x99, 0x12, 0x4D, 0x11, 0xC4, 0x28, 0x88, 0xEE, 0x85, - 0xD3, 0xD5, 0x12, 0x09, 0x4B, 0x62, 0x60, 0x05, 0xD2, 0x12, 0x2D, 0x96, 0x4A, 0x5C, 0x52, 0x40, - 0x13, 0xBA, 0xA8, 0x1C, 0xA2, 0x04, 0x79, 0x45, 0xE8, 0xB2, 0x84, 0x01, 0x77, 0x46, 0x33, 0x49, - 0x0C, 0x18, 0x21, 0xED, 0x98, 0x71, 0x85, 0xC4, 0x35, 0x52, 0x17, 0x51, 0x0B, 0x39, 0x12, 0x28, - 0x52, 0xDA, 0x60, 0x18, 0x59, 0xDA, 0x27, 0x65, 0x92, 0x73, 0x63, 0x3D, 0x78, 0x7F, 0xF1, 0x07, - 0x8C, 0xD4, 0xF2, 0xEF, 0xBE, 0xD5, 0x6A, 0x07, 0x5C, 0xB4, 0xF6, 0xF5, 0xDC, 0xCC, 0x6F, 0x91, - 0x4C, 0x2D, 0xF9, 0x56, 0x32, 0x72, 0x69, 0xFC, 0xC4, 0x1F, 0x00, 0x5C, 0x35, 0xD8, 0xC7, 0x66, - 0xEC, 0x64, 0x91, 0xEE, 0xD1, 0x48, 0x36, 0xC0, 0x3F, 0xE9, 0x6A, 0x1D, 0x1E, 0x94, 0x0B, 0xF7, - 0x5F, 0x9E, 0x8C, 0x73, 0x66, 0x58, 0xAE, 0xAC, 0xEB, 0xAE, 0xFA, 0x8E, 0x83, 0x71, 0x1E, 0xC8, - 0x5C, 0xD1, 0x7F, 0x8C, 0xA6, 0xED, 0x4A, 0x8E, 0x6B, 0x99, 0xFC, 0x99, 0xB0, 0xBC, 0x7A, 0xB1, - 0x33, 0xD4, 0xD9, 0x3A, 0x09, 0x22, 0xAE, 0xED, 0xCE, 0xF3, 0xA6, 0x1F, 0x2A, 0x53, 0xC1, 0x5D, - 0xE7, 0x4D, 0x3F, 0x90, 0x92, 0x57, 0x76, 0x79, 0x39, 0x9D, 0xC5, 0xD3, 0xA5, 0x3C, 0x89, 0x5E, - 0x5F, 0x22, 0x42, 0x06, 0xCE, 0x99, 0x37, 0x7C, 0xC8, 0x1D, 0x4C, 0x66, 0xCA, 0xFA, 0x96, 0x4B, - 0x6E, 0x8B, 0xC2, 0xD0, 0x46, 0xC9, 0xCE, 0x3A, 0xED, 0xF6, 0xFE, 0x2E, 0xFC, 0x38, 0x08, 0x05, - 0x82, 0xD0, 0x69, 0x59, 0x84, 0xD8, 0x8E, 0x5E, 0xCC, 0x1D, 0x64, 0xB8, 0x47, 0x6B, 0x71, 0xED, - 0x38, 0x9D, 0xCE, 0x25, 0x9A, 0xB0, 0x01, 0xA9, 0xE6, 0x12, 0x43, 0xA1, 0x9B, 0x52, 0x5C, 0x45, - 0x8E, 0xC5, 0x82, 0xC1, 0xD8, 0x96, 0xBB, 0xBD, 0x06, 0x57, 0x8E, 0x48, 0xAB, 0x81, 0x12, 0x98, - 0xBC, 0x64, 0xCC, 0xC1, 0xDF, 0xB8, 0x8D, 0x02, 0xED, 0x60, 0xBA, 0x5C, 0x97, 0x2C, 0xF8, 0x90, - 0x4C, 0xB1, 0xB0, 0xB9, 0x52, 0x4C, 0x48, 0x9F, 0x29, 0xE8, 0x57, 0xFA, 0x32, 0x71, 0xB6, 0xED, - 0xF2, 0xAF, 0x11, 0x6B, 0xB5, 0xFE, 0x5C, 0x5B, 0xAE, 0xA2, 0xAB, 0x35, 0xD8, 0x80, 0xE4, 0xF1, - 0x06, 0xCD, 0x84, 0x9F, 0xED, 0x72, 0xCE, 0x38, 0x39, 0xF9, 0x9B, 0xCB, 0x4F, 0x17, 0xBF, 0x86, - 0xA7, 0x1C, 0xFD, 0xB5, 0xEA, 0x73, 0x2E, 0x36, 0x93, 0xF5, 0x38, 0xE9, 0x04, 0x1C, 0x62, 0x45, - 0x5C, 0x24, 0x57, 0x10, 0x26, 0xDD, 0x07, 0xDD, 0x1B, 0xCB, 0xEC, 0x5E, 0x20, 0xAA, 0x99, 0x21, - 0xA3, 0x20, 0x19, 0x8D, 0xD4, 0x08, 0x4D, 0xFA, 0x17, 0xBF, 0x94, 0x83, 0x2E, 0xBA, 0x49, 0x0B, - 0x1F, 0x75, 0xE4, 0xEF, 0x0B, 0xD4, 0xFC, 0x0D, 0x35, 0xA6, 0x73, 0x09, 0xA9, 0xD4, 0xCB, 0xA7, - 0x32, 0xCE, 0x6C, 0xC9, 0x43, 0x90, 0xE6, 0x18, 0xED, 0x79, 0xAE, 0x7C, 0xE2, 0x02, 0x05, 0x62, - 0x7B, 0x79, 0x54, 0x81, 0x83, 0xC6, 0xEE, 0xB4, 0x52, 0x66, 0x84, 0x20, 0xC8, 0x9E, 0x68, 0xD9, - 0x3B, 0xAE, 0xFC, 0xFB, 0xAE, 0x0E, 0xFB, 0x68, 0xF9, 0x25, 0x2E, 0xBC, 0xF2, 0x2F, 0xBF, 0x0E, - 0xA8, 0x17, 0x77, 0xA1, 0x6E, 0x30, 0x35, 0xC6, 0x5E, 0x0D, 0xFD, 0x00, 0x2A, 0x74, 0xF6, 0x99, - 0x74, 0x33, 0x29, 0xDF, 0x53, 0xFE, 0x35, 0xDB, 0xF2, 0x15, 0xBA, 0x6C, 0x76, 0x12, 0xCF, 0xDD, - 0x14, 0xB8, 0x33, 0xED, 0xB2, 0x31, 0x82, 0x2A, 0x88, 0xEE, 0x53, 0xA4, 0x13, 0x94, 0x41, 0x76, - 0x37, 0xCB, 0xE6, 0x66, 0xEC, 0x0A, 0x25, 0x80, 0xEC, 0x73, 0xD2, 0x05, 0x2B, 0xF0, 0x88, 0xCF, - 0x77, 0x58, 0x45, 0x90, 0xE8, 0x23, 0x90, 0x0C, 0xEA, 0x65, 0x15, 0x30, 0x40, 0x8E, 0xB4, 0x5C, - 0x96, 0x53, 0x58, 0xD3, 0x69, 0x86, 0xC7, 0xC1, 0x62, 0x0C, 0x23, 0x36, 0xAF, 0x90, 0x5F, 0xA4, - 0xCD, 0xB6, 0x26, 0x76, 0xE1, 0x2E, 0xCA, 0x2A, 0xBA, 0x0B, 0x73, 0x89, 0xFD, 0xC5, 0xF9, 0x43, - 0x7B, 0xB1, 0x2E, 0xF6, 0x90, 0xC5, 0x2C, 0xD6, 0xC5, 0x7E, 0xE3, 0xB8, 0xB7, 0xE0, 0x2C, 0x30, - 0x87, 0x4D, 0xFB, 0x45, 0x70, 0x38, 0xCC, 0x73, 0xFE, 0x98, 0x96, 0x9F, 0x2E, 0xE4, 0x5F, 0x00, - 0xAB, 0x17, 0x64, 0xC6, 0xAA, 0xC9, 0x69, 0x4C, 0x78, 0x0A, 0x06, 0xA9, 0xDE, 0x29, 0x95, 0x68, - 0x7A, 0xD9, 0xF0, 0x02, 0xCE, 0x17, 0xE5, 0x76, 0xB3, 0xDD, 0x35, 0x8E, 0xA7, 0xD9, 0xE4, 0xFB, - 0x8E, 0xE5, 0x59, 0xC0, 0xDB, 0x2A, 0x79, 0xEB, 0xA4, 0x74, 0x99, 0x31, 0xF3, 0x1A, 0xFC, 0x77, - 0x06, 0xFD, 0xFE, 0x5C, 0xDE, 0x3B, 0x57, 0x17, 0xF3, 0x38, 0xEF, 0x60, 0x42, 0xFE, 0x7F, 0x62, - 0xF3, 0x34, 0x86, 0xBD, 0xF8, 0x3C, 0x1C, 0xAE, 0x87, 0xE7, 0xCF, 0x59, 0x98, 0x6B, 0x1B, 0x8B, - 0x0A, 0xA0, 0x45, 0xE4, 0x0C, 0x7B, 0xD5, 0xD5, 0x68, 0xE9, 0x01, 0xEE, 0xA0, 0xAF, 0x16, 0x16, - 0x5D, 0x41, 0x2C, 0x20, 0x41, 0x63, 0x0B, 0x96, 0xBF, 0x1D, 0xAD, 0x4F, 0x70, 0x65, 0x3D, 0x34, - 0x2F, 0x4C, 0xEE, 0x8C, 0x1E, 0xD9, 0x16, 0x00, 0x65, 0x9B, 0x0A, 0x1F, 0x78, 0xBE, 0x63, 0x46, - 0xDE, 0xB1, 0x86, 0xC3, 0x08, 0x5D, 0x87, 0x00, 0x5C, 0x7F, 0xC7, 0xA1, 0x3B, 0xCE, 0x6D, 0xAA, - 0x4B, 0x27, 0xA2, 0x87, 0x97, 0x55, 0x35, 0xE3, 0x94, 0x86, 0x89, 0xC4, 0xCF, 0x68, 0x3A, 0xFE, - 0x16, 0x8F, 0x97, 0x5D, 0x42, 0x23, 0x18, 0x7C, 0xD9, 0xC9, 0x1B, 0x65, 0x81, 0x43, 0x59, 0x44, - 0xE3, 0xCE, 0xFF, 0xFE, 0x1D, 0x5D, 0xF6, 0x2D, 0x4A, 0x3F, 0xCA, 0x14, 0x9F, 0xAA, 0x62, 0x70, - 0xAE, 0xDD, 0x29, 0x98, 0x87, 0x51, 0x18, 0x84, 0x7D, 0x17, 0x73, 0x68, 0x54, 0xF0, 0x09, 0x5A, - 0x0F, 0xAC, 0x99, 0x70, 0xC5, 0xF5, 0x1D, 0x82, 0xCE, 0x40, 0x55, 0x8C, 0xC5, 0x98, 0x73, 0xB2, - 0xB3, 0xC6, 0xF1, 0xF5, 0xF4, 0x09, 0xA3, 0x47, 0x95, 0x38, 0xF3, 0x4C, 0x7F, 0xA9, 0x53, 0xAE, - 0x81, 0x2B, 0x5F, 0x73, 0xD8, 0x6A, 0x77, 0x1E, 0xC6, 0xFC, 0x9E, 0x73, 0x6F, 0xF7, 0x12, 0xED, - 0x3D, 0xEE, 0x7A, 0x30, 0xCB, 0x73, 0x71, 0x5F, 0x2B, 0xAB, 0x1E, 0x60, 0x15, 0x17, 0x9F, 0x4A, - 0x1A, 0xE8, 0x26, 0x9B, 0xD0, 0x2A, 0x91, 0xE7, 0x01, 0xF2, 0x7A, 0xD2, 0xB1, 0x41, 0xB3, 0x40, - 0x59, 0xC3, 0x58, 0x43, 0x65, 0x38, 0x44, 0xC8, 0x8B, 0xAA, 0x9D, 0x94, 0xB9, 0x08, 0xD8, 0xA3, - 0x69, 0x3C, 0x4E, 0xE9, 0x40, 0x06, 0xB7, 0x50, 0xAF, 0xA2, 0x16, 0x82, 0xBC, 0x1C, 0x8E, 0x4A, - 0x42, 0x02, 0x94, 0xCF, 0x21, 0x85, 0x68, 0xED, 0xAC, 0x11, 0x83, 0xB9, 0xC8, 0xCB, 0x34, 0x25, - 0xBA, 0xF0, 0x5C, 0xC0, 0x0E, 0xBE, 0xC6, 0xDB, 0xCF, 0x65, 0xF3, 0xC9, 0xC8, 0x4C, 0x9E, 0xA8, - 0x6C, 0x60, 0x2C, 0x34, 0xD0, 0x11, 0xAB, 0x9E, 0xBA, 0xD2, 0x8C, 0xB9, 0x61, 0xA3, 0x2F, 0x0D, - 0xA5, 0xA3, 0xD5, 0xB8, 0x6D, 0x58, 0x8F, 0xC2, 0xE9, 0x5D, 0x76, 0xA1, 0x63, 0x1E, 0x5C, 0x20, - 0x71, 0xCB, 0x43, 0x19, 0x5C, 0x95, 0xF9, 0x83, 0x66, 0x32, 0x63, 0xAD, 0x3D, 0x77, 0x4D, 0x04, - 0xF9, 0xD1, 0x96, 0xD4, 0x52, 0x3A, 0xA8, 0x6A, 0x1A, 0x1B, 0x87, 0xDF, 0x81, 0x74, 0x13, 0x44, - 0x47, 0xD5, 0x10, 0x9C, 0x97, 0xAB, 0x65, 0xC8, 0xFD, 0x76, 0x8F, 0x56, 0x6F, 0xFE, 0x9E, 0x86, - 0xEA, 0xC9, 0x49, 0xE4, 0x86, 0xE8, 0x51, 0x66, 0xD1, 0x52, 0x11, 0x79, 0xCF, 0x37, 0x51, 0xCD, - 0x9C, 0xF7, 0x60, 0x71, 0x8C, 0x29, 0x4C, 0x3D, 0x10, 0x7B, 0x7D, 0x9E, 0x5B, 0xAF, 0x02, 0xFD, - 0x72, 0xB5, 0x9C, 0xFC, 0xBD, 0xA2, 0x7A, 0x96, 0x33, 0xCD, 0x5D, 0x1B, 0x16, 0x97, 0x11, 0xCF, - 0x23, 0x29, 0x66, 0x97, 0xCB, 0xC7, 0x93, 0xF3, 0x28, 0xBA, 0x59, 0xAA, 0x8F, 0xAF, 0x27, 0x57, - 0x2A, 0xE8, 0x85, 0x3B, 0x18, 0x69, 0x81, 0x34, 0x82, 0xE2, 0x2E, 0xD6, 0x53, 0xA2, 0xBA, 0xAA, - 0x24, 0x0B, 0x08, 0x5A, 0xF2, 0xA2, 0xD5, 0xE7, 0x64, 0x7A, 0x7F, 0x12, 0x9D, 0x5D, 0x50, 0xCC, - 0xBF, 0x86, 0x2D, 0x5A, 0xEC, 0x04, 0x3A, 0x11, 0x4E, 0x93, 0x26, 0xDE, 0x46, 0x61, 0x00, 0xD4, - 0x44, 0xD1, 0x29, 0x2F, 0x02, 0x39, 0x5D, 0xA6, 0x96, 0xA9, 0x99, 0x8E, 0xB1, 0xA4, 0x92, 0x34, - 0x4F, 0x5E, 0xB1, 0xB6, 0x6C, 0xC9, 0x99, 0x6C, 0xA7, 0xB3, 0x61, 0x12, 0x67, 0x16, 0xCD, 0xBB, - 0x9C, 0x40, 0xC2, 0x58, 0x99, 0x99, 0x30, 0xE9, 0xF2, 0x2C, 0x65, 0xE4, 0xA6, 0x96, 0xB6, 0xD3, - 0xA6, 0x5A, 0x43, 0xA4, 0x58, 0xB5, 0x34, 0xCE, 0x17, 0x80, 0x1F, 0x8E, 0xC9, 0x9F, 0x2E, 0x89, - 0x33, 0x97, 0x13, 0x58, 0x42, 0x0A, 0xE7, 0x8B, 0x44, 0xD7, 0x95, 0x92, 0x50, 0x25, 0x1A, 0xCF, - 0x0C, 0x59, 0x2E, 0x8C, 0x38, 0x01, 0xDE, 0x44, 0xB6, 0xAA, 0x70, 0xED, 0x4F, 0x9D, 0xDF, 0x39, - 0xB1, 0xD8, 0x75, 0xAC, 0x57, 0x2A, 0x67, 0x78, 0xFE, 0xF1, 0xAC, 0x0F, 0x67, 0x51, 0x00, 0x56, - 0x1F, 0x3D, 0x2C, 0xF1, 0xD9, 0x12, 0x8F, 0xA1, 0xE8, 0xC8, 0x53, 0xCE, 0xA0, 0x8D, 0x55, 0x3B, - 0x98, 0x06, 0xF0, 0x83, 0xEC, 0xFA, 0x35, 0xAB, 0x39, 0xAC, 0xA2, 0x4A, 0x48, 0x08, 0x1D, 0x3A, - 0xB0, 0xB0, 0xD8, 0x28, 0xCE, 0xBD, 0x15, 0xE8, 0x0C, 0xB2, 0x0C, 0x36, 0x53, 0x64, 0x9A, 0xD1, - 0xCB, 0x3E, 0x3B, 0x11, 0xE5, 0xFD, 0x76, 0xD8, 0xF9, 0xA7, 0xC1, 0x0E, 0xFB, 0xA0, 0x78, 0xFC, - 0x41, 0xEA, 0xCF, 0x03, 0xFF, 0x0E, 0x7B, 0xBA, 0x56, 0xDC, 0xAF, 0xCF, 0xC8, 0xB4, 0x93, 0x1F, - 0x28, 0x4B, 0xCB, 0xBE, 0xEC, 0xC7, 0x4B, 0xA2, 0x07, 0x40, 0x5B, 0x96, 0xFA, 0x11, 0xA0, 0xD1, - 0x65, 0x3F, 0x96, 0x40, 0x73, 0x7F, 0x46, 0xCB, 0x78, 0x9F, 0xD8, 0x94, 0x27, 0xD0, 0x20, 0x10, - 0x5D, 0x28, 0x0A, 0x50, 0x9E, 0x71, 0x69, 0x28, 0x45, 0xBA, 0x42, 0x12, 0x81, 0x5E, 0x52, 0x2E, - 0xCB, 0xFD, 0x1A, 0x8B, 0xA8, 0x47, 0x36, 0xBF, 0x54, 0x34, 0xC7, 0xF4, 0xFD, 0xD5, 0x65, 0xAE, - 0xAC, 0x15, 0xCB, 0x81, 0x8F, 0x14, 0xA0, 0x39, 0xBC, 0xB1, 0xCE, 0x98, 0x8D, 0x0B, 0xD8, 0x20, - 0x73, 0x2E, 0x32, 0x17, 0x83, 0x28, 0x81, 0xCD, 0xD0, 0xE0, 0x99, 0xA2, 0xB3, 0x3C, 0x11, 0x0B, - 0x50, 0x5A, 0xBE, 0xB5, 0xCE, 0x68, 0x1D, 0x2C, 0x64, 0x83, 0xDA, 0xB9, 0xA8, 0x5D, 0x0E, 0x4C, - 0x09, 0xF4, 0x96, 0x8D, 0x9E, 0x29, 0x8A, 0x0B, 0x41, 0xAF, 0x00, 0xC3, 0x23, 0xD2, 0xE0, 0x3A, - 0x63, 0xB9, 0x2B, 0xA6, 0x39, 0x81, 0x69, 0x6E, 0x30, 0x3D, 0x1F, 0xD3, 0xE5, 0xB6, 0x57, 0x42, - 0x74, 0xD1, 0x66, 0x0D, 0xD2, 0xE1, 0x67, 0x8B, 0xF9, 0xF3, 0x56, 0x28, 0x0D, 0x96, 0xF8, 0xC9, - 0xB3, 0xD1, 0x8F, 0xA2, 0x80, 0x1C, 0x42, 0xF4, 0xC3, 0xAC, 0x2B, 0xF8, 0x7E, 0x1D, 0xE5, 0x45, - 0x03, 0x84, 0x9F, 0xE9, 0x3C, 0xD4, 0xBF, 0x90, 0x06, 0x3A, 0xDD, 0xDE, 0x73, 0x2C, 0xE7, 0x59, - 0x06, 0x95, 0xAB, 0xA5, 0x87, 0x4F, 0xEE, 0x58, 0xA1, 0x99, 0x3E, 0xD1, 0x60, 0x09, 0x86, 0xFA, - 0xF9, 0xAD, 0x71, 0xB8, 0xD5, 0x4F, 0x65, 0x88, 0x33, 0x3D, 0x7B, 0x09, 0x36, 0x38, 0x58, 0xD1, - 0x5C, 0xE6, 0xB7, 0x69, 0xBB, 0x39, 0x2D, 0x6F, 0x53, 0x50, 0x26, 0x8C, 0x6E, 0xB8, 0xCE, 0xA7, - 0xB6, 0xB7, 0x4D, 0x57, 0xF7, 0x64, 0xB5, 0x98, 0x4D, 0x44, 0x7F, 0xC3, 0xB8, 0xF8, 0x66, 0x03, - 0xFC, 0xCC, 0x22, 0x4E, 0x87, 0xAF, 0xB2, 0xE0, 0xDD, 0x55, 0x15, 0x51, 0x16, 0x57, 0xE5, 0xA6, - 0x46, 0x6E, 0x6F, 0x6E, 0x90, 0x2E, 0x46, 0x9F, 0xF8, 0x93, 0x69, 0xA4, 0x4E, 0x90, 0x28, 0xD5, - 0x15, 0x66, 0x72, 0x74, 0x4E, 0x0A, 0xB2, 0x15, 0xB5, 0xD8, 0x45, 0x6B, 0xD4, 0x92, 0x17, 0x9E, - 0x82, 0x71, 0x92, 0x61, 0x0F, 0xA3, 0x00, 0x0F, 0xF0, 0x1A, 0xC6, 0x9D, 0x5E, 0xD5, 0x60, 0x57, - 0x98, 0x86, 0xE2, 0x7F, 0x1D, 0xB0, 0x77, 0xEC, 0x60, 0xCF, 0xDD, 0xF0, 0x56, 0x49, 0x2A, 0x31, - 0x1C, 0x29, 0xE4, 0xAD, 0x89, 0x06, 0xF5, 0xF3, 0xD6, 0xDA, 0x49, 0xC0, 0xE1, 0xAA, 0xEE, 0x46, - 0x63, 0x76, 0x32, 0xF0, 0x3F, 0x78, 0xEF, 0x09, 0x71, 0xDF, 0x0E, 0xE6, 0x10, 0x14, 0xA5, 0x91, - 0x69, 0xE0, 0x54, 0xC3, 0x52, 0xBF, 0xE6, 0x21, 0x7B, 0x93, 0x6A, 0x80, 0x7B, 0xC9, 0x5E, 0x08, - 0xDF, 0xF1, 0xBB, 0x77, 0xEC, 0x3F, 0x3A, 0xFE, 0x06, 0xE5, 0x43, 0x0C, 0x0E, 0x71, 0xA2, 0x14, - 0xBE, 0x07, 0x6F, 0xAF, 0x3F, 0xB2, 0xDF, 0x58, 0x96, 0x77, 0xCE, 0x8D, 0x42, 0x3B, 0x06, 0xBE, - 0xC7, 0xE8, 0xC5, 0x27, 0xC4, 0x76, 0xCF, 0xA2, 0xDB, 0x6E, 0xCB, 0x37, 0xB5, 0xA6, 0xE7, 0xE8, - 0x36, 0xA0, 0x35, 0xFA, 0xF4, 0x49, 0x57, 0x53, 0x27, 0x8C, 0xFB, 0x26, 0xEC, 0x47, 0x6F, 0x29, - 0x3F, 0xEA, 0x82, 0xD7, 0xDE, 0x60, 0xB3, 0xC4, 0xCF, 0xE9, 0xA6, 0x97, 0xC1, 0xE6, 0xF0, 0xED, - 0x67, 0x82, 0xCD, 0x20, 0x03, 0x8A, 0x3C, 0xFA, 0xA5, 0x50, 0x3A, 0x7C, 0x7B, 0x0D, 0x24, 0x18, - 0x8E, 0xC0, 0x04, 0x3C, 0x36, 0x40, 0x38, 0xBD, 0xE7, 0x65, 0xF1, 0xBA, 0xD3, 0x6E, 0x6F, 0x50, - 0x3B, 0x86, 0xAC, 0x53, 0x0C, 0x28, 0x8D, 0xDF, 0x61, 0x93, 0x67, 0x80, 0xE4, 0x01, 0x3E, 0x5C, - 0x6A, 0x45, 0x18, 0x1E, 0x62, 0xCE, 0xE5, 0xF9, 0x4A, 0xD1, 0x5B, 0xC5, 0x6C, 0xB3, 0xE4, 0x9D, - 0xA4, 0x0F, 0x75, 0x89, 0xE4, 0x09, 0x34, 0x8E, 0x20, 0xF0, 0x87, 0xFE, 0x60, 0x9A, 0xF9, 0x0D, - 0xA3, 0x30, 0xC7, 0x8A, 0xA3, 0xA8, 0x05, 0xFE, 0xD2, 0x2F, 0x07, 0xAD, 0x0B, 0xAC, 0x72, 0x89, - 0x1D, 0x2F, 0x85, 0xD1, 0xD3, 0xF7, 0xD7, 0xCA, 0x94, 0x41, 0xB9, 0x0D, 0xAF, 0x15, 0x13, 0x34, - 0x31, 0xA7, 0x1E, 0x63, 0x86, 0x65, 0xAA, 0x61, 0x72, 0x7C, 0xEC, 0xFD, 0x4A, 0x77, 0x29, 0xE1, - 0xB9, 0xB8, 0xD2, 0x37, 0xB8, 0x1C, 0xAC, 0x31, 0x5F, 0xB5, 0xBB, 0x0C, 0x7B, 0x46, 0xD2, 0xEC, - 0x91, 0x61, 0xE6, 0x78, 0x1F, 0x1D, 0x3F, 0xD5, 0xD0, 0x31, 0xD3, 0x7F, 0x86, 0xE1, 0x23, 0xD6, - 0x53, 0x39, 0x53, 0x47, 0x0C, 0xD4, 0xD2, 0xCA, 0x11, 0x01, 0xC8, 0x93, 0x5B, 0x3B, 0xA2, 0x4B, - 0x5A, 0xD8, 0xDE, 0x11, 0x2F, 0xF2, 0x90, 0x8E, 0xD4, 0x83, 0x73, 0x36, 0xD0, 0xBF, 0x63, 0xA0, - 0x8D, 0x20, 0x13, 0x57, 0xC3, 0x3F, 0xB3, 0xF3, 0xF9, 0xB5, 0xD9, 0xF5, 0x29, 0x52, 0x08, 0xDB, - 0x65, 0xEF, 0x1D, 0x1E, 0x6D, 0x87, 0x7F, 0x0E, 0x6C, 0x60, 0x8D, 0xD9, 0xFC, 0xB0, 0xA8, 0xD3, - 0xF2, 0xE6, 0x6C, 0x2A, 0x73, 0x95, 0xDC, 0xBD, 0x5B, 0x7C, 0x98, 0x75, 0x58, 0x78, 0x8E, 0x84, - 0xC7, 0x2B, 0x83, 0x0F, 0xBD, 0x57, 0x39, 0xFC, 0xC2, 0x1B, 0x1F, 0x63, 0x4E, 0xC3, 0xB7, 0xBB, - 0xF0, 0x21, 0xF7, 0x2D, 0x84, 0x54, 0xD1, 0x5B, 0xDA, 0x71, 0x8C, 0xA9, 0x4D, 0x1D, 0xA7, 0x82, - 0xB9, 0x0F, 0x28, 0xCE, 0xE7, 0xC4, 0x48, 0x0B, 0xC2, 0x93, 0x4E, 0x57, 0x85, 0xD7, 0x32, 0xA1, - 0xA7, 0x55, 0x14, 0x18, 0x44, 0x8E, 0x98, 0xE9, 0x0F, 0xA6, 0x98, 0xE5, 0x53, 0xB5, 0xEB, 0x39, - 0x8B, 0x83, 0x4B, 0xA3, 0x24, 0x8F, 0x17, 0xDF, 0xC8, 0x61, 0xF6, 0x8F, 0xC0, 0x55, 0xE8, 0x8F, - 0x76, 0xCB, 0xFB, 0xE6, 0x65, 0x8F, 0x1D, 0xB4, 0xDD, 0xA7, 0xBD, 0x2F, 0x7A, 0x2B, 0x03, 0x88, - 0x22, 0xF0, 0x0B, 0x57, 0x7D, 0x79, 0x2E, 0x40, 0x9A, 0x3D, 0x95, 0x62, 0x30, 0x66, 0xC0, 0x9F, - 0x45, 0x19, 0x44, 0x8E, 0x93, 0xAD, 0x84, 0xE8, 0x0A, 0x61, 0xDD, 0xED, 0x76, 0xDA, 0xBD, 0xCE, - 0x1F, 0xED, 0x6E, 0xBB, 0xD3, 0x3E, 0x10, 0x29, 0x36, 0x8B, 0x00, 0x09, 0x4D, 0xD8, 0x5F, 0x97, - 0x05, 0xF0, 0x99, 0xF9, 0xBC, 0x68, 0x98, 0x77, 0xDB, 0x6F, 0xCA, 0xC1, 0x7C, 0xAF, 0x7D, 0xB8, - 0x0A, 0x98, 0xCB, 0xF9, 0xAC, 0x25, 0xCC, 0xE1, 0x29, 0x32, 0xE7, 0xE3, 0x0C, 0x4E, 0x5E, 0xB8, - 0x49, 0xE2, 0x0C, 0x2B, 0xD8, 0xA6, 0xFC, 0xAB, 0x9C, 0xC6, 0x54, 0x2A, 0x8A, 0x2C, 0x14, 0x34, - 0x78, 0xEE, 0x11, 0x9B, 0x14, 0x9F, 0x8A, 0x33, 0xA1, 0x96, 0xD8, 0xC7, 0x3A, 0xDE, 0x98, 0x67, - 0x2D, 0x20, 0x96, 0x60, 0x0D, 0x15, 0x5A, 0x8D, 0xFC, 0xBC, 0xC8, 0x7A, 0x0A, 0xB6, 0x32, 0xFD, - 0x92, 0x39, 0xDF, 0x65, 0xB9, 0x5C, 0xD5, 0x9F, 0xCC, 0x8A, 0x3F, 0xF8, 0xB9, 0x33, 0x3D, 0x3B, - 0x3B, 0xD1, 0x12, 0x3F, 0xA2, 0x1A, 0x0E, 0x0A, 0x50, 0x39, 0xA5, 0x7D, 0x44, 0x91, 0x99, 0x9F, - 0x4A, 0x2B, 0x31, 0xE9, 0x55, 0xA1, 0xEC, 0x94, 0x3A, 0x50, 0xED, 0x48, 0x19, 0xA8, 0xC2, 0x32, - 0x4F, 0xD9, 0x15, 0x97, 0xA4, 0x38, 0x25, 0x16, 0x83, 0x65, 0x60, 0x7C, 0x37, 0xAD, 0x28, 0x6B, - 0xC5, 0xC8, 0x05, 0x53, 0x4B, 0xE8, 0x15, 0xD3, 0x37, 0xC7, 0x4E, 0xBA, 0x7C, 0x3A, 0xAB, 0x77, - 0xA7, 0x15, 0x0E, 0x4B, 0xE8, 0x76, 0x98, 0x0F, 0xC1, 0x05, 0x01, 0x19, 0x3E, 0x77, 0x48, 0xED, - 0xEE, 0x74, 0x83, 0x47, 0xED, 0xAC, 0x88, 0xC5, 0x9C, 0x84, 0xC8, 0xCA, 0x3D, 0x3F, 0xF5, 0xCC, - 0x19, 0x2D, 0x45, 0x24, 0x54, 0x89, 0x93, 0x01, 0xBE, 0x2B, 0xEE, 0x09, 0x29, 0xB9, 0x31, 0xFC, - 0x95, 0xBA, 0xFF, 0x89, 0x6B, 0xCE, 0x19, 0x45, 0x19, 0xBB, 0x41, 0xA5, 0xB8, 0x13, 0x2A, 0xC5, - 0xD9, 0x04, 0x14, 0x48, 0xBE, 0x62, 0x96, 0x55, 0x35, 0xCA, 0x78, 0xEB, 0x20, 0x74, 0xA5, 0x6C, - 0x40, 0x4B, 0x5A, 0x30, 0x4B, 0x89, 0xED, 0x11, 0x5B, 0x52, 0x69, 0x13, 0xF8, 0x37, 0xDD, 0x4B, - 0xDB, 0x04, 0xCB, 0xF7, 0x70, 0x8A, 0xA9, 0x9B, 0x81, 0x6D, 0xA6, 0x9B, 0x71, 0x01, 0x7F, 0xA1, - 0x83, 0x7C, 0xEA, 0x86, 0x50, 0x48, 0xD0, 0xEC, 0x3E, 0x60, 0x34, 0xEF, 0xBD, 0xB4, 0x55, 0x84, - 0x23, 0x54, 0xDC, 0x18, 0x39, 0xF3, 0xB4, 0x8D, 0x29, 0x88, 0x14, 0xB2, 0x8F, 0xFF, 0xC9, 0xBC, - 0x73, 0xED, 0x9F, 0x8B, 0xC0, 0x1E, 0xF9, 0x33, 0xFA, 0xD1, 0x55, 0x1D, 0xDD, 0xF6, 0x98, 0xEB, - 0xA8, 0xB0, 0xBF, 0x8E, 0xBA, 0x8B, 0x91, 0x6A, 0xAD, 0xBF, 0xD3, 0x68, 0xE2, 0xAB, 0xAC, 0x26, - 0xD3, 0x9E, 0x61, 0xC5, 0x2E, 0x46, 0x4A, 0x59, 0x58, 0x30, 0xC0, 0x65, 0xEF, 0x98, 0x66, 0xA9, - 0x3E, 0xDA, 0x9C, 0x5A, 0x7F, 0xFA, 0xDC, 0x79, 0x14, 0x4A, 0x83, 0xE5, 0x80, 0xDA, 0xB0, 0xF5, - 0xAA, 0xE5, 0x79, 0xAF, 0xB6, 0xC3, 0x96, 0x41, 0x9B, 0x16, 0x1C, 0xEF, 0x17, 0x8A, 0x3A, 0xDE, - 0xF2, 0xD8, 0xBB, 0x63, 0xF6, 0x6F, 0xB1, 0x65, 0x60, 0x72, 0x35, 0x0C, 0xC0, 0x74, 0x3D, 0x47, - 0xB1, 0x5B, 0xB7, 0xA2, 0xC5, 0x96, 0x37, 0xED, 0xE4, 0xDF, 0xB7, 0xE5, 0x0C, 0x83, 0x79, 0x01, - 0xB0, 0x41, 0xD3, 0x04, 0xBE, 0xF1, 0x76, 0x77, 0xEC, 0x4D, 0x8C, 0xE3, 0xFF, 0x0F, 0x60, 0xEA, - 0x12, 0x48, 0x97, 0x42, 0x00 + 0xA2, 0x44, 0x62, 0x0C, 0xD8, 0x3C, 0x06, 0xEF, 0x60, 0x5A, 0xFB, 0x34, 0xBA, 0xA3, 0xEF, 0x28, + 0x48, 0x9C, 0x52, 0x5E, 0x18, 0x74, 0x28, 0xC8, 0xBC, 0xB7, 0x8A, 0x20, 0x46, 0x41, 0x74, 0xAF, + 0x9C, 0xAE, 0x96, 0x48, 0x58, 0x12, 0x03, 0x4B, 0x90, 0x96, 0x68, 0xB1, 0x54, 0xE2, 0x92, 0x02, + 0x9A, 0xD0, 0x45, 0xE5, 0x10, 0x05, 0xC8, 0x2B, 0x42, 0x97, 0x05, 0x0C, 0xB8, 0x53, 0x9A, 0x49, + 0x62, 0xC0, 0x08, 0x69, 0xC7, 0x8C, 0x2B, 0x24, 0xAE, 0x91, 0xBA, 0x88, 0x5A, 0xC8, 0xB1, 0x40, + 0x91, 0xC2, 0x06, 0xC3, 0xC8, 0xD2, 0xBE, 0x28, 0xE3, 0x19, 0x37, 0xD6, 0xFD, 0xCB, 0x8B, 0xDF, + 0x61, 0xA4, 0x86, 0x7F, 0xFF, 0xBD, 0x52, 0x3B, 0xE0, 0x02, 0x56, 0xB3, 0xC5, 0x98, 0xDF, 0x22, + 0xA9, 0xFD, 0x66, 0x5B, 0xC9, 0xC8, 0x29, 0xF2, 0x0B, 0x7F, 0x02, 0x70, 0x55, 0x60, 0x1F, 0x9B, + 0xB2, 0x93, 0x45, 0xBA, 0x47, 0x23, 0x59, 0x1F, 0x3F, 0xD2, 0xD5, 0x3A, 0x3C, 0x28, 0x96, 0x1F, + 0x6A, 0x79, 0x32, 0xCE, 0x99, 0x61, 0x61, 0x86, 0x3D, 0xB2, 0x59, 0xF8, 0x8E, 0x83, 0x91, 0x22, + 0xC8, 0x5C, 0xD1, 0x7F, 0x8C, 0xA6, 0xED, 0x4A, 0x8E, 0x6B, 0x99, 0x7C, 0x43, 0x58, 0x5E, 0xB5, + 0xD8, 0x19, 0xEA, 0x6C, 0xAD, 0x04, 0x11, 0x57, 0x76, 0xE7, 0x79, 0xDB, 0x0B, 0x95, 0xA9, 0xE0, + 0xAE, 0xF3, 0xB6, 0x17, 0x48, 0xC9, 0x2B, 0xBB, 0xBC, 0x9C, 0xCC, 0xE2, 0xE5, 0x72, 0xE4, 0x45, + 0xAF, 0x2F, 0x11, 0x21, 0x03, 0xE7, 0xCC, 0x5B, 0x3E, 0xE0, 0x0E, 0x66, 0xAC, 0x67, 0x3D, 0xCB, + 0xD5, 0x65, 0x82, 0x21, 0x6B, 0x2C, 0x52, 0x56, 0xB5, 0x9A, 0xCD, 0x83, 0x3D, 0xF8, 0x71, 0x18, + 0x0A, 0x04, 0xA1, 0xDB, 0xB3, 0x08, 0xD2, 0x1D, 0xBE, 0x9A, 0x3B, 0xC8, 0x70, 0x8F, 0xD6, 0xE2, + 0xDA, 0x71, 0x32, 0x1D, 0xCA, 0x66, 0x02, 0x48, 0x35, 0x97, 0x18, 0x0A, 0xDD, 0x14, 0xE2, 0x2A, + 0x72, 0x2C, 0x16, 0x0C, 0xC6, 0x76, 0xDC, 0xB7, 0x6B, 0x70, 0xE5, 0x88, 0xB4, 0x1A, 0x28, 0x81, + 0xC9, 0x4B, 0xC6, 0x19, 0xF8, 0x1B, 0xB7, 0x51, 0xA0, 0x1D, 0x4C, 0x97, 0xEB, 0x92, 0x45, 0xE3, + 0x92, 0x49, 0x1A, 0xB6, 0x57, 0x8A, 0x09, 0xE9, 0x33, 0x05, 0xFD, 0x0A, 0x5F, 0x26, 0x4E, 0xB7, + 0x5D, 0xFE, 0x35, 0x62, 0xA5, 0xD6, 0x9F, 0x1B, 0x0A, 0xC3, 0xA8, 0xC0, 0x06, 0x24, 0x8F, 0x37, + 0x68, 0x26, 0xFC, 0x6C, 0x97, 0x73, 0xC6, 0xC9, 0xC9, 0xDF, 0x5E, 0x7D, 0xB9, 0xF8, 0x25, 0x3C, + 0xE5, 0xE8, 0xD3, 0xAA, 0xCF, 0xB9, 0xD8, 0x4C, 0xD6, 0xE3, 0xA4, 0x13, 0x70, 0x88, 0x15, 0x82, + 0x94, 0x5C, 0x41, 0x98, 0x74, 0x9F, 0x74, 0x6F, 0x24, 0xD3, 0xC1, 0x82, 0xA8, 0x66, 0x86, 0x8C, + 0x82, 0x64, 0x34, 0x52, 0x23, 0x34, 0xE9, 0x5F, 0xFC, 0x5A, 0x0E, 0xBA, 0xE8, 0x26, 0x2D, 0x7C, + 0xD4, 0x91, 0xBF, 0x2F, 0x50, 0xF3, 0x77, 0xD4, 0x98, 0xCE, 0x25, 0xA4, 0x52, 0x2F, 0x9F, 0x8A, + 0x38, 0xB3, 0x25, 0x0F, 0x41, 0x9A, 0x63, 0xB4, 0xE7, 0xB9, 0x8A, 0xC6, 0x50, 0x2F, 0x85, 0xD8, + 0x6F, 0x6C, 0xBF, 0x8F, 0x4B, 0x70, 0xD9, 0xD8, 0xBD, 0x57, 0xCA, 0xAC, 0x11, 0x4C, 0xD9, 0x8B, + 0x29, 0x7A, 0x0F, 0x36, 0xFB, 0x4E, 0xAC, 0xC5, 0x3E, 0x5B, 0x7E, 0x81, 0x4B, 0xB1, 0xD9, 0x17, + 0x64, 0x87, 0xD4, 0x8B, 0xBB, 0x50, 0x37, 0x98, 0x80, 0x63, 0xBF, 0x82, 0x7E, 0x00, 0x5D, 0x5A, + 0x07, 0x4C, 0xBA, 0xA2, 0x14, 0xEF, 0x69, 0xF6, 0x55, 0xDC, 0xF2, 0x95, 0xBE, 0x6C, 0x96, 0x13, + 0xCF, 0x10, 0x15, 0xB8, 0x3C, 0xED, 0xB1, 0x11, 0x82, 0x2A, 0x88, 0x21, 0x54, 0xA4, 0xA3, 0x94, + 0x41, 0xB6, 0x39, 0xCB, 0xE6, 0x66, 0xEC, 0x9A, 0x25, 0x80, 0xEC, 0x26, 0xE9, 0x8B, 0x25, 0xF8, + 0xC8, 0xD7, 0x7B, 0xAC, 0x56, 0x4E, 0xF4, 0x11, 0x48, 0x0F, 0xD5, 0xB2, 0x13, 0x18, 0x60, 0x86, + 0x44, 0x5D, 0x25, 0x37, 0xB1, 0x26, 0x4B, 0x09, 0x8F, 0x95, 0xC5, 0x98, 0x4A, 0x6C, 0xEE, 0x21, + 0x4F, 0x49, 0x5B, 0x51, 0x45, 0x2C, 0xC5, 0x5D, 0x94, 0x9D, 0xB4, 0x17, 0xE6, 0x24, 0x07, 0x8B, + 0xF3, 0x90, 0xE6, 0x62, 0x5D, 0xEC, 0x23, 0x1B, 0x5A, 0xAC, 0x8B, 0x83, 0xDA, 0x49, 0x67, 0xC1, + 0x59, 0x60, 0x36, 0x9D, 0xE6, 0xAB, 0xE0, 0x82, 0xFC, 0x91, 0x03, 0xB3, 0x49, 0xC9, 0x94, 0x17, + 0x4B, 0xAC, 0xFA, 0x7A, 0xCC, 0x61, 0x15, 0x39, 0x9F, 0x09, 0x8F, 0x43, 0xC0, 0x05, 0xCF, 0xB2, + 0xBC, 0x11, 0xA5, 0x91, 0xBE, 0x03, 0x91, 0xBC, 0x34, 0x77, 0x8C, 0x72, 0xC4, 0xE9, 0xEE, 0x6A, + 0x27, 0xA7, 0xC1, 0x33, 0xD6, 0x73, 0x2C, 0xCF, 0x02, 0xFE, 0x57, 0xCA, 0xEB, 0x27, 0xA5, 0xCB, + 0x8C, 0x99, 0x57, 0xE0, 0x07, 0xD4, 0xEF, 0xF5, 0xE6, 0xF2, 0x02, 0xBA, 0xBE, 0x98, 0xC7, 0x09, + 0x08, 0x46, 0x63, 0xFF, 0xC4, 0xE6, 0x69, 0x0C, 0x7B, 0xF1, 0x75, 0x30, 0x58, 0x0F, 0x0F, 0xA2, + 0xB3, 0xB0, 0xC8, 0x0B, 0x66, 0xB4, 0x47, 0xCB, 0xCA, 0x19, 0xF6, 0xAA, 0xAB, 0x6C, 0xB2, 0xF3, + 0x22, 0x8F, 0x2E, 0xC3, 0x0A, 0x7D, 0x88, 0x05, 0x24, 0x8C, 0xEC, 0xC0, 0xF2, 0xDF, 0xEE, 0x46, + 0x5E, 0xBA, 0xB6, 0x9E, 0xEA, 0x17, 0x26, 0x77, 0x86, 0xCF, 0x6C, 0x07, 0x80, 0xF2, 0x96, 0xD2, + 0xE0, 0x7B, 0xBE, 0x63, 0x46, 0xDE, 0xB1, 0x06, 0x83, 0x08, 0x5D, 0x87, 0x00, 0x5C, 0x7F, 0x07, + 0xA4, 0x7B, 0xCE, 0x6D, 0xAA, 0x91, 0x2D, 0xA2, 0x90, 0x97, 0x55, 0x62, 0xED, 0x94, 0x86, 0x89, + 0xC4, 0xE1, 0x68, 0x3A, 0xFE, 0x16, 0x8F, 0x97, 0x5D, 0x70, 0x2D, 0x18, 0x7C, 0xD9, 0x69, 0x24, + 0x65, 0xB1, 0x75, 0x59, 0x57, 0xE1, 0xDE, 0xFF, 0xF3, 0x4F, 0x74, 0xFD, 0xB7, 0x28, 0x11, 0x2A, + 0x53, 0x7C, 0xAA, 0x91, 0xC0, 0xB9, 0x76, 0xAF, 0x60, 0x46, 0x48, 0x61, 0x58, 0xF6, 0x5D, 0xCC, + 0xE6, 0x51, 0xC2, 0xB7, 0x68, 0x3D, 0xB0, 0x66, 0xCC, 0x15, 0xD7, 0x77, 0x08, 0x3A, 0x7D, 0x55, + 0x31, 0x16, 0x63, 0xCE, 0xC9, 0xCE, 0x6A, 0x27, 0x37, 0x93, 0x27, 0x8C, 0x1E, 0x95, 0xE2, 0xCC, + 0x53, 0xFD, 0xA5, 0x4E, 0xB9, 0x02, 0xAE, 0x7C, 0xC3, 0x61, 0xAB, 0xDD, 0x79, 0x18, 0xF3, 0x25, + 0xE7, 0xDE, 0xDE, 0x15, 0xDA, 0x8D, 0xDC, 0xF5, 0x60, 0x96, 0xE7, 0xE2, 0xDE, 0x57, 0x96, 0xDB, + 0xC2, 0x9A, 0x1E, 0x3E, 0xD5, 0xD2, 0xD2, 0x4D, 0x36, 0xA6, 0x55, 0x22, 0xCF, 0x03, 0xE4, 0xF5, + 0xA4, 0x83, 0x84, 0x66, 0x81, 0x42, 0x87, 0x31, 0x8B, 0xCA, 0x60, 0x80, 0x90, 0xA7, 0x92, 0xC0, + 0x22, 0x7B, 0x13, 0xB0, 0x47, 0xD3, 0x78, 0x9E, 0xD0, 0x81, 0x0C, 0x92, 0xA1, 0x5E, 0x45, 0x11, + 0x2E, 0x79, 0xC9, 0x1C, 0x95, 0x84, 0x04, 0x28, 0x37, 0x21, 0x99, 0x69, 0xE5, 0xAC, 0x11, 0x83, + 0xC2, 0xC8, 0x5B, 0x35, 0x25, 0x4A, 0xF1, 0x5C, 0xC0, 0x0E, 0xBE, 0xC6, 0x5B, 0xD4, 0x65, 0xF3, + 0xC9, 0xC8, 0x4C, 0x5E, 0xA8, 0xC6, 0x74, 0x2C, 0xC4, 0xD0, 0x11, 0xAB, 0x9E, 0xB8, 0xE4, 0x8C, + 0xB8, 0x61, 0xA3, 0x4F, 0x0E, 0x25, 0xC6, 0xD5, 0xB8, 0x6D, 0x58, 0xCF, 0xC2, 0x79, 0x5E, 0x76, + 0xA1, 0x63, 0x46, 0x5E, 0x20, 0x71, 0xCB, 0x43, 0x19, 0x5C, 0x95, 0x99, 0x8C, 0xA6, 0x72, 0x74, + 0xAD, 0x3D, 0x77, 0x4D, 0x04, 0x0B, 0xD2, 0x96, 0x54, 0x52, 0xB3, 0xB2, 0x6C, 0x3A, 0x1C, 0x87, + 0xDF, 0x83, 0x74, 0x13, 0x44, 0x59, 0x55, 0x10, 0xE4, 0x37, 0x53, 0xCB, 0x90, 0xFB, 0xED, 0x1E, + 0xAF, 0xDE, 0x8C, 0x3E, 0x09, 0xF9, 0x93, 0x93, 0x98, 0x19, 0xEA, 0x47, 0x39, 0x4E, 0x0B, 0x45, + 0xF6, 0x6D, 0x6E, 0xC2, 0x9B, 0x39, 0xEF, 0xD3, 0xE2, 0x18, 0x93, 0x9B, 0xC2, 0x20, 0xF6, 0xFA, + 0x3C, 0xB7, 0x67, 0x39, 0xFA, 0xE5, 0x6A, 0x39, 0xF9, 0xA5, 0xA2, 0x7A, 0x96, 0x33, 0xC9, 0xA2, + 0x1B, 0x56, 0x35, 0x14, 0xCF, 0x23, 0xC9, 0x6E, 0x97, 0xCB, 0xC7, 0x93, 0xF3, 0xC8, 0xBB, 0xA1, + 0xAA, 0x8E, 0xAF, 0x27, 0x57, 0x2A, 0xE8, 0x85, 0x3B, 0x18, 0xB1, 0x81, 0x34, 0x82, 0xE2, 0x2E, + 0x16, 0xF2, 0x44, 0x6F, 0x4A, 0x21, 0x0B, 0x38, 0x61, 0x4D, 0x9A, 0x50, 0x60, 0x90, 0x85, 0x06, + 0x48, 0x74, 0x76, 0x41, 0x31, 0x7F, 0x08, 0x5B, 0x34, 0x58, 0x17, 0x3A, 0x11, 0xCE, 0x97, 0x26, + 0xDE, 0x6A, 0x61, 0x20, 0xD5, 0x58, 0xD1, 0x29, 0xBF, 0x02, 0x39, 0x6F, 0xA6, 0xD6, 0x47, 0x9C, + 0x8C, 0xB1, 0xA4, 0x5A, 0x88, 0xAB, 0x3C, 0x36, 0x8A, 0x61, 0x74, 0xAD, 0x6C, 0x36, 0xE8, 0x41, + 0x12, 0x67, 0x16, 0xCD, 0x00, 0x9D, 0x40, 0xC2, 0x58, 0x7D, 0xC3, 0x30, 0xFD, 0xF3, 0x34, 0x65, + 0xCC, 0x4C, 0x72, 0x6D, 0xA7, 0x4D, 0xB5, 0x82, 0x88, 0xB3, 0x72, 0x09, 0xA5, 0x2F, 0xB0, 0x76, + 0x99, 0xC9, 0x5F, 0x2E, 0x9D, 0x34, 0x97, 0x13, 0x58, 0x42, 0x32, 0xE9, 0x8B, 0x44, 0xD7, 0xA5, + 0x92, 0x59, 0x25, 0x1A, 0x4F, 0x0D, 0x59, 0x2C, 0x1C, 0x39, 0x01, 0xDE, 0x44, 0xD6, 0xAB, 0x70, + 0xED, 0x2F, 0x9D, 0x69, 0x3A, 0xB1, 0xD8, 0x75, 0x2C, 0x6E, 0x2F, 0x67, 0x78, 0xFE, 0xF9, 0xAC, + 0x07, 0x67, 0x51, 0x00, 0x56, 0x1F, 0x3D, 0x35, 0xF1, 0xD9, 0x12, 0x8F, 0xA1, 0xE8, 0xC8, 0x13, + 0xCE, 0xA0, 0x8D, 0x54, 0x3B, 0x98, 0x06, 0xF0, 0x83, 0xEC, 0x4A, 0x3A, 0xAB, 0x39, 0xAC, 0xA2, + 0x4A, 0x48, 0x08, 0x1D, 0x3A, 0xB0, 0xB0, 0x24, 0x21, 0xCE, 0xBD, 0x11, 0xE8, 0x0C, 0xC8, 0xAB, + 0xF0, 0xA1, 0x22, 0x13, 0x9E, 0x5E, 0xF5, 0x58, 0x57, 0xD4, 0x95, 0xDE, 0x65, 0xE7, 0x5F, 0xFA, + 0xBB, 0xEC, 0x93, 0xE2, 0xF1, 0x27, 0xA9, 0x3F, 0xF7, 0xFD, 0x7B, 0xEC, 0xE9, 0x46, 0x71, 0x1F, + 0x36, 0xC8, 0xB4, 0x33, 0x3B, 0xE0, 0x96, 0x96, 0x7D, 0xD5, 0xEB, 0xCB, 0x83, 0x58, 0x20, 0x7D, + 0x00, 0xB4, 0x65, 0xA9, 0x1F, 0x01, 0x1A, 0x5D, 0xF5, 0x62, 0x89, 0x38, 0x0F, 0xA6, 0xB4, 0x8C, + 0xCB, 0xC4, 0xA6, 0xBC, 0x80, 0x06, 0x81, 0xE8, 0x42, 0xD1, 0x84, 0xF2, 0x8C, 0x4B, 0x43, 0x29, + 0xD2, 0x15, 0x92, 0x08, 0xF4, 0x9A, 0x72, 0x62, 0x1E, 0x94, 0xC9, 0x86, 0x89, 0xF3, 0x9E, 0x91, + 0x0B, 0x33, 0xB2, 0xF9, 0x85, 0xA2, 0x42, 0x26, 0xEF, 0xAF, 0x2E, 0x03, 0x66, 0xA5, 0x58, 0x0E, + 0x7C, 0x24, 0x07, 0xCD, 0xE1, 0x8D, 0x75, 0xC6, 0x6C, 0x5C, 0xC0, 0x16, 0x99, 0x67, 0x22, 0x73, + 0x3E, 0x88, 0x12, 0xD8, 0x0C, 0x0D, 0x36, 0x14, 0x9D, 0xE5, 0x89, 0x98, 0x83, 0xD2, 0xF2, 0xAD, + 0x75, 0x46, 0xEB, 0x60, 0x21, 0x5B, 0xD4, 0x9E, 0x89, 0xDA, 0xC5, 0xC0, 0x94, 0x40, 0x6F, 0xD9, + 0x68, 0x43, 0x51, 0x5C, 0x08, 0x7A, 0x39, 0x18, 0x1E, 0x91, 0x06, 0xD7, 0x19, 0xCB, 0x5D, 0x31, + 0xCD, 0x31, 0x4C, 0x73, 0x8B, 0xE9, 0xB3, 0x31, 0x5D, 0x6E, 0x7B, 0x29, 0x44, 0x17, 0x6D, 0xD6, + 0x20, 0xAD, 0x7E, 0xB6, 0x98, 0x3F, 0x6F, 0xAD, 0xD4, 0x60, 0x89, 0x5F, 0x3C, 0x1B, 0xFD, 0x28, + 0x72, 0xC8, 0x21, 0x44, 0x3F, 0xCC, 0xDE, 0x82, 0xEF, 0x57, 0x51, 0xE8, 0x34, 0x40, 0xF8, 0xA9, + 0xCE, 0x43, 0xFD, 0x0B, 0x69, 0xA0, 0xD5, 0xEE, 0x6C, 0x62, 0x61, 0xD1, 0x22, 0xA8, 0x5C, 0x2E, + 0xCD, 0x7C, 0x72, 0xC7, 0x72, 0xCD, 0xF4, 0x89, 0x06, 0x4B, 0x30, 0xD4, 0xCF, 0x6F, 0x8D, 0xC3, + 0xAD, 0x7E, 0x29, 0x43, 0x9C, 0xE9, 0xD9, 0x4B, 0xB0, 0xC1, 0xC1, 0x8A, 0xE6, 0x32, 0xBF, 0x4D, + 0xDA, 0xCD, 0x69, 0x79, 0x9B, 0x80, 0x52, 0x1A, 0xDD, 0xA4, 0xCD, 0x0D, 0x97, 0xF9, 0xD2, 0xE6, + 0xB6, 0xC9, 0xE2, 0x5E, 0xAC, 0x28, 0xB4, 0x89, 0xD8, 0x6F, 0x18, 0x17, 0xDF, 0x6D, 0x00, 0x9F, + 0x99, 0xC7, 0xE8, 0xF0, 0x55, 0x16, 0xBC, 0xBB, 0xAA, 0x6A, 0xCE, 0xE2, 0xA6, 0xDC, 0xD4, 0xC8, + 0xEB, 0xCD, 0x0D, 0xB2, 0xCE, 0xE8, 0x63, 0x7F, 0x3C, 0x09, 0xF8, 0x09, 0xF2, 0xAD, 0xBA, 0xC2, + 0x4A, 0x8E, 0xBE, 0x49, 0x41, 0xD2, 0xA3, 0x06, 0xBB, 0x68, 0x0C, 0x1B, 0xF2, 0xBE, 0x53, 0xF0, + 0x4D, 0xB2, 0xEB, 0x61, 0x30, 0xE1, 0x21, 0xDE, 0xC2, 0xB8, 0x93, 0x9B, 0x1A, 0xEC, 0x0A, 0xB3, + 0x59, 0xFC, 0xAF, 0x43, 0xF6, 0x91, 0x1D, 0xEE, 0xBB, 0x5B, 0xD6, 0x2A, 0x49, 0x25, 0x86, 0x23, + 0xB9, 0xAC, 0x35, 0xD1, 0xA0, 0x7A, 0xD6, 0x5A, 0x39, 0x09, 0x38, 0x5C, 0xD5, 0xDD, 0x68, 0x58, + 0x4F, 0x06, 0xFE, 0x07, 0xEF, 0xBD, 0x20, 0xEE, 0xDB, 0xC1, 0x1C, 0x82, 0xDA, 0x36, 0x32, 0x9B, + 0x9C, 0x6A, 0x58, 0xEA, 0xC3, 0x2C, 0x64, 0xAF, 0x53, 0x31, 0x72, 0x2F, 0xD9, 0x0B, 0xE1, 0x3B, + 0x7E, 0xF7, 0x91, 0xFD, 0x7B, 0xCB, 0xDF, 0xA2, 0x7C, 0x88, 0xC1, 0x21, 0x4E, 0x14, 0xC2, 0xF7, + 0xE0, 0xED, 0xF5, 0x47, 0xF6, 0x5B, 0xCB, 0xF2, 0xCE, 0xB9, 0x91, 0x6B, 0xC6, 0xC0, 0xF7, 0x18, + 0xBD, 0xF8, 0x82, 0xD8, 0xEE, 0x59, 0x74, 0xD9, 0x6D, 0xF9, 0xA6, 0x56, 0xF7, 0x1C, 0xDD, 0x06, + 0xB4, 0x46, 0x97, 0x3E, 0xE9, 0x69, 0xEA, 0x84, 0xE1, 0xE3, 0x84, 0xFD, 0xE8, 0x2C, 0xE5, 0x47, + 0x3D, 0xF0, 0x9A, 0x5B, 0x6C, 0x96, 0xF8, 0x39, 0xD9, 0xF4, 0x22, 0xD8, 0x1C, 0xBE, 0xBD, 0x21, + 0xD8, 0x0C, 0x22, 0xA0, 0x48, 0xC7, 0x5F, 0x08, 0xA5, 0xC3, 0xB7, 0xD7, 0x40, 0x82, 0xE1, 0x08, + 0x4C, 0xC0, 0x63, 0x03, 0x64, 0xD3, 0x47, 0x5E, 0x14, 0xAF, 0x5B, 0xCD, 0xE6, 0x16, 0xB5, 0x63, + 0xC8, 0x3A, 0xC1, 0x80, 0xC2, 0xF8, 0x1D, 0x36, 0xD9, 0x00, 0x24, 0x0F, 0xF0, 0xE1, 0x4A, 0xCB, + 0xC3, 0xF0, 0x10, 0x73, 0xAE, 0xCE, 0x57, 0x8A, 0xDE, 0x2A, 0x26, 0xAD, 0x25, 0xE7, 0x24, 0x7D, + 0xA0, 0x4B, 0x24, 0x4F, 0xA0, 0x71, 0x04, 0x81, 0x3F, 0xF5, 0xFA, 0x93, 0x04, 0x72, 0x18, 0xA8, + 0x39, 0x52, 0x1C, 0x45, 0xCD, 0x71, 0x97, 0x7E, 0x3D, 0x68, 0x9D, 0x63, 0x94, 0x4B, 0xEC, 0x78, + 0x21, 0x8C, 0x9E, 0xBC, 0xBF, 0x56, 0x96, 0x0C, 0x4A, 0x91, 0x78, 0xA3, 0x98, 0xA0, 0x89, 0x39, + 0xD5, 0xD8, 0x32, 0x2C, 0x53, 0x0D, 0x73, 0xEC, 0x63, 0xEF, 0xD7, 0xBA, 0x4B, 0x79, 0xD3, 0xC5, + 0x8D, 0xBE, 0xC1, 0xE5, 0x60, 0xB5, 0xF9, 0x8A, 0xE6, 0x65, 0x98, 0x33, 0x92, 0x56, 0x8F, 0x0C, + 0x2B, 0xC7, 0x65, 0x74, 0xFC, 0x54, 0x3B, 0xC7, 0x54, 0xFF, 0x19, 0x76, 0x8F, 0x58, 0x4F, 0xC5, + 0x2C, 0x1D, 0x31, 0x50, 0x4B, 0x2B, 0x47, 0x04, 0x20, 0x2F, 0x6E, 0xED, 0x88, 0x2E, 0x69, 0x61, + 0x7B, 0x47, 0xBC, 0x56, 0x44, 0x3A, 0x52, 0xF7, 0xCF, 0x59, 0x5F, 0xFF, 0x13, 0xE3, 0x6C, 0x04, + 0x99, 0xB8, 0x1A, 0x7E, 0xCC, 0x4E, 0x0B, 0xD8, 0x64, 0x37, 0xA7, 0x48, 0x21, 0x6C, 0x8F, 0x5D, + 0x3A, 0x3C, 0xDA, 0x0E, 0x3F, 0xF6, 0x6D, 0x60, 0x8D, 0xD9, 0xFC, 0x30, 0xAF, 0xD3, 0xE2, 0xD6, + 0x6C, 0xAA, 0x96, 0x95, 0xDC, 0xBD, 0x3B, 0x7C, 0x98, 0x75, 0x58, 0x78, 0x8E, 0x84, 0xC7, 0x1B, + 0x83, 0x0F, 0xBC, 0x37, 0x33, 0xF8, 0x85, 0x37, 0x3A, 0xC1, 0xD4, 0x88, 0x1F, 0xF6, 0xE0, 0x8F, + 0x99, 0x6F, 0x21, 0xA4, 0xF2, 0xDE, 0xD2, 0x4E, 0x62, 0x4C, 0x6D, 0xE2, 0x37, 0x15, 0xCC, 0xBD, + 0x4F, 0x61, 0x3E, 0x5D, 0x23, 0x2D, 0x06, 0x4F, 0xFA, 0x5C, 0xE5, 0xDE, 0xCA, 0x84, 0x8E, 0x56, + 0x51, 0x60, 0x10, 0x39, 0x62, 0xC2, 0x40, 0x98, 0x62, 0x96, 0x4B, 0xD5, 0x9E, 0xE7, 0x2C, 0x0E, + 0x2E, 0x8D, 0x72, 0x45, 0x5E, 0x7C, 0x27, 0x7F, 0xD9, 0xDF, 0x03, 0x4F, 0xA1, 0xDF, 0x9B, 0x0D, + 0xEF, 0xBB, 0x97, 0x3D, 0x76, 0xD0, 0xF6, 0x80, 0xF6, 0x3E, 0xEF, 0xAD, 0x0C, 0x20, 0x8A, 0xB8, + 0x2F, 0x5C, 0xF5, 0xD5, 0xB9, 0x00, 0x69, 0xF6, 0x54, 0xF2, 0xC1, 0x98, 0x01, 0x7F, 0x16, 0x65, + 0x10, 0x33, 0x7C, 0x6C, 0x25, 0x44, 0x57, 0x08, 0xEB, 0x76, 0xBB, 0xD5, 0xEC, 0xB4, 0x7E, 0x6F, + 0xB6, 0x9B, 0xAD, 0xE6, 0xA1, 0xC8, 0xD4, 0x99, 0x07, 0x48, 0x68, 0xC2, 0xFE, 0xBA, 0x2C, 0x80, + 0x4F, 0xCD, 0xE7, 0x55, 0xC3, 0xBC, 0xDD, 0x7C, 0x5F, 0x0C, 0xE6, 0xFB, 0xCD, 0xA3, 0x55, 0xC0, + 0x5C, 0xCE, 0x67, 0x2D, 0x61, 0x0E, 0x4F, 0x91, 0x39, 0x9F, 0x64, 0x70, 0xF2, 0xDC, 0x4D, 0x12, + 0x67, 0x58, 0xCE, 0x36, 0xCD, 0xBE, 0xC9, 0xA9, 0x4D, 0xA4, 0xA2, 0xC8, 0x42, 0x41, 0x83, 0xE7, + 0x1E, 0xB1, 0x49, 0xF1, 0x57, 0x7E, 0x42, 0xD5, 0x02, 0xFB, 0x58, 0xC5, 0x1B, 0xF3, 0xAC, 0x05, + 0xC4, 0x12, 0x2C, 0xC5, 0x42, 0xAB, 0x91, 0x7F, 0x2F, 0xB2, 0x9E, 0x9C, 0xAD, 0x4C, 0xBF, 0x63, + 0x9E, 0xED, 0xB1, 0x5C, 0xAC, 0x78, 0x50, 0x66, 0xE1, 0x20, 0xFC, 0xBB, 0x35, 0x39, 0x3B, 0x5B, + 0xD1, 0x4A, 0x41, 0xA2, 0xA8, 0x0E, 0x0A, 0x50, 0x33, 0x2A, 0x04, 0x89, 0x5A, 0x35, 0x3F, 0x15, + 0x56, 0x62, 0xD2, 0x8B, 0x4B, 0xD9, 0x29, 0xE5, 0xA4, 0x9A, 0x91, 0x6A, 0x52, 0xB9, 0xD5, 0xA2, + 0xB2, 0x0B, 0x37, 0x49, 0x71, 0x4A, 0x2C, 0x06, 0xAB, 0xC9, 0xF8, 0x6E, 0x5A, 0x6D, 0xD7, 0x92, + 0x81, 0x0B, 0xA6, 0x96, 0xD0, 0x2B, 0x26, 0x6F, 0x8E, 0x9C, 0x74, 0xF9, 0x74, 0x5A, 0xEF, 0x4E, + 0xAB, 0x3F, 0x96, 0xD0, 0xED, 0x30, 0x1D, 0x82, 0x0B, 0x02, 0x32, 0xFC, 0xDD, 0x22, 0xB5, 0xBB, + 0xD5, 0x0E, 0x1E, 0x35, 0xB3, 0x02, 0x16, 0x67, 0xE4, 0x55, 0x56, 0x1E, 0xF9, 0xA9, 0x67, 0x4E, + 0x69, 0x29, 0x22, 0x9F, 0x4A, 0x9C, 0x0C, 0xF0, 0x5D, 0x71, 0x4F, 0x48, 0x39, 0x92, 0xE1, 0x53, + 0xEA, 0xFE, 0x27, 0x42, 0x0B, 0xA6, 0x14, 0x65, 0xEC, 0x06, 0x95, 0xE2, 0x56, 0xA8, 0x14, 0x67, + 0x13, 0x50, 0x20, 0xF9, 0x8A, 0x59, 0x96, 0xD5, 0x28, 0xE3, 0xAD, 0x83, 0xC8, 0x95, 0xA2, 0xF1, + 0x2C, 0x69, 0xB1, 0x2C, 0x05, 0xB6, 0x47, 0x6C, 0x49, 0xA9, 0x4D, 0xE0, 0xDF, 0x75, 0x2F, 0x6D, + 0x13, 0x2C, 0xDF, 0xC3, 0x29, 0xA6, 0x6E, 0x06, 0xB6, 0x99, 0x6C, 0xC6, 0x05, 0x7C, 0x42, 0xFF, + 0xF8, 0xD4, 0x0D, 0xA1, 0x88, 0xA0, 0xE9, 0x7D, 0xC0, 0x60, 0xDE, 0x47, 0x69, 0xAB, 0x08, 0x47, + 0x28, 0xB9, 0x31, 0x72, 0xE6, 0x69, 0x1B, 0x93, 0x13, 0x28, 0x64, 0x9F, 0xFC, 0x93, 0x79, 0xEF, + 0xDA, 0x7F, 0xC9, 0x03, 0x7B, 0xE4, 0x63, 0xF4, 0x4F, 0x57, 0x75, 0x74, 0xDB, 0x63, 0xAE, 0xA3, + 0xC2, 0xFE, 0x3A, 0xEA, 0x1E, 0x06, 0xAA, 0x35, 0xFE, 0x4E, 0xA3, 0x89, 0xAF, 0xB2, 0x9A, 0x4C, + 0x7A, 0x86, 0x15, 0xBB, 0x18, 0x28, 0x65, 0x61, 0xDD, 0x01, 0x97, 0x7D, 0x64, 0x9A, 0xA5, 0xFA, + 0x68, 0x73, 0x6A, 0xFC, 0xE1, 0x73, 0xE7, 0x59, 0x28, 0x0D, 0x96, 0x03, 0x6A, 0xC3, 0xCE, 0x9B, + 0x86, 0xE7, 0xBD, 0x79, 0x1B, 0xB6, 0x0C, 0xDA, 0x34, 0xE0, 0x78, 0xBF, 0x50, 0xD4, 0xD1, 0x8E, + 0xC7, 0x3E, 0x9E, 0xB0, 0x7F, 0x8D, 0x2D, 0x03, 0xF3, 0xAF, 0x61, 0xFC, 0xA5, 0xEB, 0x39, 0x8A, + 0xDD, 0xB8, 0x13, 0x2D, 0x76, 0xBC, 0x49, 0x27, 0xFF, 0xF6, 0x56, 0xCE, 0x30, 0x98, 0x17, 0x00, + 0x1B, 0x34, 0x4D, 0xE0, 0x1B, 0x1F, 0xF6, 0x46, 0xDE, 0xD8, 0x38, 0xF9, 0xFF, 0x52, 0x31, 0x57, + 0x1C, 0xD9, 0x50, 0x00 }; ///index_html //Content of bootstrap.bundle.min.jss with gzip compression From 29cb7cacb0c38ec1935e38f6a17f907684e85987 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 15:49:44 -0700 Subject: [PATCH 082/276] Typo fixes --- Firmware/RTK_Everywhere/AP-Config/src/main.js | 2 +- Firmware/RTK_Everywhere/Display.ino | 4 ++-- Firmware/RTK_Everywhere/Network.ino | 6 +++--- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 8 ++++---- Firmware/RTK_Everywhere/menuFirmware.ino | 2 +- Firmware/RTK_Everywhere/menuMain.ino | 2 +- Firmware/RTK_Everywhere/settings.h | 2 +- Firmware/Test Sketches/Hookup_Display/Display.ino | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/src/main.js b/Firmware/RTK_Everywhere/AP-Config/src/main.js index d22d2c14c..ba38d34e0 100644 --- a/Firmware/RTK_Everywhere/AP-Config/src/main.js +++ b/Firmware/RTK_Everywhere/AP-Config/src/main.js @@ -398,7 +398,7 @@ function parseIncoming(msg) { else if (id.includes("messageRate") || id.includes("messageIntervalRTCM")) { // messageRateNMEA_GPDTM // messageRateRTCMRover_RTCM1001 - // messagRatesRTCMBase_RTCM1001 + // messageRatesRTCMBase_RTCM1001 // messageIntervalRTCMRover_RTCM1230 // messageIntervalRTCMBase_RTCM1230 var messageName = id; diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 4c1d3d999..26b0f9db2 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -1034,7 +1034,7 @@ void setESPNowIcon_TwoRadios(std::vector *iconList) prop.icon = ESPNowSymbol1Left64x48; else // if (espnowRSSI > -255) prop.icon = - ESPNowSymbol0Left64x48; // Always show the synbol because we've got incoming or outgoing data + ESPNowSymbol0Left64x48; // Always show the symbol because we've got incoming or outgoing data iconList->push_back(prop); // Share the spot. Determine if we need to indicate Up, or Down @@ -2161,7 +2161,7 @@ void displayWiFiConnect() } // When user does a factory reset, let us know -void displaySytemReset() +void displaySystemReset() { displayMessage("Factory Reset", 0); } diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 166c59b12..4c40ff9b0 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -364,9 +364,9 @@ void networkDisplayInterface(NetIndex_t index) if (hasIP) { if (netif->hasGlobalIPv6()) - systemPrintf(" Global IPv6 Adress: %s\r\n", netif->globalIPv6().toString().c_str()); + systemPrintf(" Global IPv6 Address: %s\r\n", netif->globalIPv6().toString().c_str()); if (netif->hasLinkLocalIPv6()) - systemPrintf(" Link Local IPv6 Adress: %s\r\n", netif->linkLocalIPv6().toString().c_str()); + systemPrintf(" Link Local IPv6 Address: %s\r\n", netif->linkLocalIPv6().toString().c_str()); systemPrintf(" IPv4 Address: %s (%s)\r\n", netif->localIP().toString().c_str(), settings.ethernetDHCP ? "DHCP" : "Static"); systemPrintf(" Subnet Mask: %s\r\n", netif->subnetMask().toString().c_str()); @@ -671,7 +671,7 @@ void networkMarkOffline(NetIndex_t index) // Leave this network on in hopes that it will regain a connection previousPriority = networkPriority; - // Search in decending priority order for the next online network + // Search in descending priority order for the next online network priority = networkPriorityTable[index]; for (priority += 1; priority < NETWORK_OFFLINE; priority += 1) { diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index adec3f3a5..02d18081a 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -545,7 +545,7 @@ const int shutDownButtonTime = 2000; // ms press and hold before shutdown bool firstButtonThrownOut = false; //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- -// Webserver for serving config page from ESP32 as Acess Point +// Webserver for serving config page from ESP32 as Access Point //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // Because the incoming string is longer than max len, there are multiple callbacks so we @@ -737,7 +737,7 @@ uint32_t lastSetupMenuChange; // Limits how much time is spent in the setup menu uint32_t lastTestMenuChange; // Avoids exiting the test menu for at least 1 second uint8_t setupSelectedButton = 0; // In Display Setup, start displaying at this button. This is the selected (highlighted) button. -std::vector setupButtons; // A vector (linked list) of the setup 'butttons' +std::vector setupButtons; // A vector (linked list) of the setup 'buttons' bool firstRoverStart; // Used to detect if the user is toggling the power button at POR to enter the test menu @@ -1038,7 +1038,7 @@ void setup() um980FirmwareBeginUpdate(); DMW_b("beginPsram"); - beginPsram(); // Inialize PSRAM (if available). Needs to occur before beginGnssUart and other malloc users. + beginPsram(); // Initialize PSRAM (if available). Needs to occur before beginGnssUart and other malloc users. DMW_b("beginMux"); beginMux(); // Must come before I2C activity to avoid external devices from corrupting the bus. See issue #474: @@ -1089,7 +1089,7 @@ void setup() networkBegin(); DMW_b("beginFuelGauge"); - beginFuelGauge(); // Configure battery fuel guage monitor + beginFuelGauge(); // Configure battery fuel gauge monitor DMW_b("beginCharger"); beginCharger(); // Configure battery charger diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index e9e7b3bfb..c080520fe 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -317,7 +317,7 @@ void updateFromSD(const char *firmwareFileName) // Bulk write from the SD file to flash while (firmwareFile.available()) { - bluetoothLedBlink(); // Toggle LED to indcate activity + bluetoothLedBlink(); // Toggle LED to indicate activity int bytesToWrite = pageSize; // Max number of bytes to read if (firmwareFile.available() < bytesToWrite) diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index a2a0f482e..275fb5628 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -486,7 +486,7 @@ void changeProfileNumber(byte newProfileNumber) // Erase all settings. Upon restart, unit will use defaults void factoryReset(bool alreadyHasSemaphore) { - displaySytemReset(); // Display friendly message on OLED + displaySystemReset(); // Display friendly message on OLED tasksStopGnssUart(); diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 34e9134e6..816e079db 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -761,7 +761,7 @@ struct Settings uint8_t gnssUartInterruptsCore = 1; // Core where hardware is started and interrupts are assigned to, 0=core, 1=Arduino uint8_t handleGnssDataTaskCore = 1; // Core where task should run, 0=core, 1=Arduino - uint8_t handleGnssDataTaskPriority = 1; // Read from the cicular buffer and dole out to end points (SD, TCP, BT). + uint8_t handleGnssDataTaskPriority = 1; // Read from the circular buffer and dole out to end points (SD, TCP, BT). uint8_t i2cInterruptsCore = 1; // Core where hardware is started and interrupts are assigned to, 0=core, 1=Arduino uint8_t measurementScale = MEASUREMENT_UNITS_METERS; bool printBootTimes = false; // Print times and deltas during boot diff --git a/Firmware/Test Sketches/Hookup_Display/Display.ino b/Firmware/Test Sketches/Hookup_Display/Display.ino index 4b0344604..4fb46fdc2 100644 --- a/Firmware/Test Sketches/Hookup_Display/Display.ino +++ b/Firmware/Test Sketches/Hookup_Display/Display.ino @@ -1566,7 +1566,7 @@ void displayWiFiConfig() } //When user does a factory reset, let us know -void displaySytemReset() +void displaySystemReset() { displayMessage("Factory Reset", 0); } From 4f43e4840b2f80d46a5c2b90bdcfc6739873eb8c Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 15:56:40 -0700 Subject: [PATCH 083/276] Don't restart WiFi if there are no consumers --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 2 +- Firmware/RTK_Everywhere/menuMain.ino | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 02d18081a..5e3304589 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -32,7 +32,7 @@ #endif // COMPILE_WIFI #define COMPILE_ZED // Comment out to remove ZED-F9x functionality - #define COMPILE_L_BAND // Comment out to remove L-Band functionality +#define COMPILE_L_BAND // Comment out to remove L-Band functionality #define COMPILE_UM980 // Comment out to remove UM980 functionality #define COMPILE_MOSAICX5 // Comment out to remove mosaic-X5 functionality #define COMPILE_LG290P // Comment out to remove LG290P functionality diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 275fb5628..39783414a 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -299,8 +299,8 @@ void menuMain() gnss->debuggingEnable(); } - // Restart WiFi if anything changes - if (restartWiFi == true) + // Restart WiFi if anything changes and we have consumers + if (restartWiFi == true && networkConsumers() > 0) { restartWiFi = false; From 9c96098a957ba542cfff3ba35a9779ab58ea2907 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 3 Jan 2025 16:27:41 -0700 Subject: [PATCH 084/276] Disable Bluetooth and ESP-NOW during web config This frees ~50k of RAM. --- Firmware/RTK_Everywhere/States.ino | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index b7132d943..5fb3bf66a 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -420,11 +420,10 @@ void stateUpdate() displayWebConfigNotStarted(); // Display immediately while we wait for server to start - // TODO - Do we need to stop BT and ESP-NOW during web config or can we leave it running? - // bluetoothStop(); - // espnowStop(); + bluetoothStop(); // Bluetooth must be stopped to allow enough RAM for AP+STA (firmware check) + espnowStop(); // We don't need ESP-NOW during web config - // tasksStopGnssUart(); // Delete serial tasks if running + // The GNSS UART task is left running to allow non-ZED platforms to obtain LLh data for 1Hz page updates // Stop any running NTRIP Client or Server ntripClientStop(true); // Do not allocate new wifiClient From 54fb316feb2a4c775888d9a5ee22dced720ad54c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Jan 2025 23:28:56 +0000 Subject: [PATCH 085/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 1592 ++++++++++++++++---------------- 1 file changed, 796 insertions(+), 796 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index b86752087..902b5a2fe 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x17, 0x68, 0x78, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0xB7, 0x72, 0x78, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0x1B, 0x39, 0xB2, 0xE8, 0xFF, 0x79, 0x0A, 0xAD, 0xEF, 0xDE, 0x31, 0x2C, 0xC6, 0xD8, 0xE6, 0x23, 0x21, 0x84, 0xEC, 0x25, 0x40, 0x12, 0xEE, 0x02, 0xE1, 0x62, 0x32, 0x33, 0x99, 0x6C, 0x0E, 0xA7, 0x71, 0x0B, 0xD3, 0x27, 0x76, @@ -236,800 +236,800 @@ static const uint8_t main_js[] PROGMEM = { 0xE8, 0xFB, 0x5E, 0xC2, 0xA8, 0xE3, 0x8E, 0x1C, 0x97, 0xF2, 0x6F, 0x60, 0xF5, 0x27, 0x85, 0x78, 0xD7, 0x40, 0x22, 0xAF, 0xF9, 0xCF, 0x0A, 0x96, 0x7F, 0x2C, 0x9B, 0xEA, 0xD4, 0x56, 0x81, 0x28, 0x3D, 0x12, 0xE1, 0x72, 0xA8, 0x9B, 0xA6, 0xC3, 0x1A, 0x59, 0x08, 0xCC, 0x40, 0xBD, 0x3B, 0x03, - 0x13, 0x95, 0x53, 0x09, 0x11, 0x9D, 0xE3, 0x51, 0x13, 0x53, 0x7E, 0x18, 0xAB, 0x5D, 0x73, 0x65, - 0xAC, 0x1B, 0x60, 0x95, 0x78, 0x90, 0x67, 0xD7, 0x55, 0xB8, 0x94, 0x90, 0xF7, 0xD6, 0x3B, 0x25, - 0x00, 0x12, 0x02, 0x7A, 0xFD, 0x3A, 0xF3, 0x0E, 0xBB, 0x46, 0xF9, 0x16, 0x16, 0x8C, 0xA1, 0xE6, - 0x6E, 0x15, 0xCC, 0x41, 0x7A, 0xB5, 0x7F, 0x4C, 0xC1, 0xFB, 0xB9, 0x76, 0xD8, 0x52, 0x5D, 0x2F, - 0xCF, 0xEA, 0xCA, 0xFC, 0xCE, 0xC2, 0x7F, 0x0A, 0xD6, 0x38, 0x16, 0xB2, 0x91, 0x67, 0x5C, 0xEA, - 0xCD, 0x87, 0x85, 0xC6, 0x73, 0xE7, 0x5F, 0xD0, 0x84, 0x25, 0xD2, 0xFD, 0x61, 0xCE, 0xBE, 0x97, - 0x39, 0xE3, 0xC1, 0x22, 0x68, 0x8A, 0xF2, 0xCC, 0x55, 0x52, 0xEB, 0xF2, 0xDD, 0xBB, 0xBD, 0xFA, - 0x83, 0x7E, 0x01, 0x9E, 0xE4, 0x5C, 0x46, 0xCE, 0xBF, 0xC0, 0x2C, 0x2F, 0x8E, 0xB2, 0xF8, 0x6A, - 0xC9, 0xC8, 0x48, 0xA6, 0x52, 0xCB, 0x23, 0xC4, 0x16, 0x71, 0x2C, 0x64, 0x7C, 0xB5, 0xDA, 0x2B, - 0x6E, 0xBC, 0xC7, 0xCF, 0xA5, 0xC4, 0xB0, 0xE8, 0x34, 0x5F, 0x7F, 0xB8, 0xBE, 0x7E, 0xB5, 0xC6, - 0xBF, 0x56, 0x04, 0xEE, 0x36, 0x5F, 0x73, 0x35, 0xEB, 0xD6, 0x44, 0xD0, 0x8B, 0x10, 0xF4, 0x4A, - 0x23, 0x58, 0xE3, 0x52, 0x2B, 0x37, 0xC4, 0x74, 0x7D, 0x85, 0xE1, 0xD1, 0xB7, 0x6E, 0x29, 0x0B, - 0x76, 0x41, 0xB1, 0xB3, 0x20, 0x44, 0xC6, 0x0B, 0xB1, 0x02, 0x72, 0x47, 0x31, 0x58, 0xA5, 0x19, - 0xB2, 0x40, 0x7A, 0xAC, 0xC2, 0x4B, 0xEE, 0x69, 0xD8, 0x56, 0xF0, 0xDF, 0x40, 0x5D, 0xD7, 0x0B, - 0xB1, 0x80, 0x5C, 0x51, 0xEA, 0x12, 0xCB, 0xB6, 0x79, 0xBC, 0x4A, 0xBC, 0xC3, 0xA2, 0x2E, 0x34, - 0xF5, 0xB4, 0x2C, 0x7C, 0xAF, 0x42, 0xEA, 0x54, 0x6D, 0x80, 0xA4, 0x73, 0xB5, 0xD4, 0xD9, 0xDD, - 0x10, 0xF8, 0x79, 0x2C, 0x97, 0x5D, 0xE4, 0xDE, 0x48, 0xD5, 0x4A, 0xF9, 0x17, 0x52, 0xFD, 0x39, - 0xB9, 0x17, 0x4F, 0xD5, 0xD2, 0xA4, 0xF6, 0x2F, 0xC8, 0x38, 0x5C, 0x5D, 0x2F, 0x6B, 0x65, 0xD2, - 0xBB, 0x1F, 0xDC, 0x7C, 0x64, 0x9B, 0x9F, 0xD7, 0x22, 0xF6, 0x3F, 0xCB, 0xBE, 0x94, 0x35, 0x2F, - 0x7C, 0x66, 0xCD, 0xD8, 0x7D, 0x69, 0x66, 0x6E, 0xE7, 0x54, 0xB6, 0xA6, 0xB3, 0x8E, 0xB4, 0xF8, - 0x38, 0x65, 0x4E, 0x23, 0x4D, 0xC9, 0x63, 0x54, 0x6A, 0xA8, 0xA9, 0xC9, 0x8D, 0xEA, 0x8C, 0x35, - 0xE9, 0x62, 0x86, 0xC8, 0x07, 0x74, 0x9F, 0x1E, 0x6C, 0x6A, 0xFA, 0xA0, 0x9C, 0x01, 0x91, 0x54, - 0x8A, 0x90, 0x45, 0x6E, 0x37, 0xF8, 0xBF, 0x19, 0x4E, 0x77, 0x02, 0x23, 0xC6, 0x87, 0x4A, 0x29, - 0x73, 0x88, 0xA4, 0x99, 0x8A, 0x46, 0x8A, 0x8A, 0x31, 0x3D, 0x58, 0x50, 0x08, 0xE6, 0x74, 0x49, - 0xD1, 0xDE, 0xC3, 0x2B, 0x73, 0xB6, 0x25, 0x93, 0xDB, 0x9E, 0x81, 0x88, 0x75, 0x85, 0x81, 0x3D, - 0x43, 0x04, 0x44, 0x4E, 0x62, 0x26, 0x1D, 0x4D, 0x24, 0xD5, 0xC2, 0xBB, 0x31, 0x06, 0x22, 0x52, - 0xA2, 0x95, 0x0B, 0xCF, 0x23, 0x63, 0xCB, 0xBD, 0x97, 0x49, 0x93, 0x80, 0xB7, 0xB1, 0x51, 0x45, - 0x79, 0x50, 0xFD, 0x1C, 0x77, 0x28, 0x65, 0xAD, 0x32, 0x9C, 0x71, 0xA6, 0x2B, 0x55, 0xD9, 0xB8, - 0x74, 0x13, 0xB0, 0xCC, 0xE3, 0xEA, 0x74, 0x9D, 0xCA, 0x67, 0x81, 0x2C, 0xA0, 0x31, 0xB7, 0x1D, - 0xE9, 0x3A, 0x55, 0x9A, 0xE1, 0x85, 0x56, 0x04, 0x96, 0x75, 0xA6, 0x99, 0xAA, 0x52, 0xB1, 0x11, - 0x22, 0x82, 0xE0, 0x08, 0xBA, 0x3A, 0x89, 0x39, 0x30, 0x9D, 0xEC, 0x1B, 0x2B, 0xB6, 0x03, 0x7F, - 0x50, 0xFD, 0x5C, 0x3E, 0x95, 0xE1, 0xC8, 0x74, 0x82, 0x6E, 0x4A, 0x83, 0x54, 0xED, 0x68, 0x42, - 0x24, 0x18, 0x34, 0x1D, 0x4E, 0xC4, 0xA9, 0x07, 0x6B, 0x60, 0xF4, 0x30, 0xCE, 0xC6, 0x8C, 0x92, - 0xE7, 0x2E, 0xAC, 0x16, 0x58, 0x41, 0xAF, 0x3C, 0x2F, 0x3C, 0x71, 0xDC, 0x69, 0x48, 0x83, 0xFC, - 0xA3, 0xB8, 0x8C, 0x23, 0x2F, 0x0D, 0x43, 0x9B, 0x4F, 0x3B, 0x86, 0x0D, 0x73, 0xF5, 0xC6, 0x1E, - 0x06, 0x55, 0x8A, 0xD8, 0x88, 0xB6, 0x98, 0x92, 0x8C, 0x59, 0x76, 0xA4, 0xD0, 0xF7, 0x18, 0x6E, - 0x8C, 0x77, 0xA5, 0x19, 0xF0, 0x01, 0xC5, 0x00, 0xE6, 0xA0, 0x44, 0xB2, 0x84, 0x6A, 0xCC, 0x77, - 0xAA, 0xB3, 0x2E, 0x12, 0xEB, 0x65, 0x5C, 0x09, 0xA9, 0xC3, 0xFB, 0x83, 0x9C, 0x3D, 0x6A, 0x9F, - 0xE7, 0xED, 0x82, 0xA9, 0x38, 0x4A, 0x97, 0x35, 0xC6, 0x99, 0x19, 0x93, 0x84, 0xE2, 0x6D, 0x52, - 0x18, 0x1B, 0x41, 0x41, 0x57, 0x5B, 0x6E, 0x48, 0x5D, 0xD7, 0x7A, 0x4F, 0x9D, 0xE1, 0x4D, 0x78, - 0x39, 0x1E, 0x9B, 0xC7, 0x99, 0x56, 0x4B, 0xED, 0x50, 0xB2, 0x86, 0xF1, 0xE8, 0x2C, 0x59, 0x98, - 0x59, 0xD4, 0x32, 0xC3, 0xCC, 0x79, 0x83, 0x79, 0x9E, 0x06, 0x00, 0xC6, 0x6F, 0x54, 0x5E, 0x4D, - 0xC3, 0x50, 0x0E, 0xB3, 0x2E, 0x97, 0x56, 0x2A, 0xF4, 0xEF, 0xCD, 0xDD, 0x87, 0xC7, 0xD0, 0x79, - 0xBA, 0xF3, 0x00, 0x7E, 0x4F, 0x38, 0xB8, 0x21, 0x4B, 0x14, 0x37, 0x0B, 0xCC, 0x13, 0xA1, 0x34, - 0xC3, 0xF4, 0xC1, 0xEF, 0xB9, 0x00, 0x24, 0xC4, 0x09, 0x02, 0xF8, 0xC9, 0x02, 0xE6, 0x8F, 0x0E, - 0xA2, 0xF4, 0x5E, 0x55, 0x22, 0xD5, 0xF3, 0xF3, 0x6F, 0x95, 0x6C, 0x8F, 0x41, 0xA1, 0x6A, 0x34, - 0x88, 0xDD, 0x4B, 0xAD, 0xDC, 0x22, 0xA9, 0x1F, 0xF7, 0x46, 0x23, 0xE2, 0xD3, 0xE1, 0x74, 0x84, - 0x09, 0xD3, 0x98, 0x93, 0xCB, 0xFB, 0x34, 0x76, 0x31, 0xB5, 0xEE, 0xAC, 0xD0, 0xD6, 0x4C, 0x53, - 0x51, 0xB1, 0x9D, 0x47, 0x35, 0xFA, 0xEB, 0xC1, 0x94, 0x8B, 0x2E, 0xBA, 0xE8, 0x43, 0x30, 0x40, - 0x87, 0x26, 0x17, 0xA4, 0xD8, 0xD1, 0x3E, 0x8F, 0x50, 0xDA, 0xBF, 0xB1, 0xDC, 0x21, 0x15, 0xCB, - 0x45, 0x2D, 0x00, 0xA1, 0xD9, 0xDC, 0x79, 0x96, 0x58, 0x16, 0x18, 0xE2, 0x22, 0xAA, 0xE9, 0x24, - 0x18, 0x1A, 0x6A, 0x0A, 0x06, 0x0E, 0x3C, 0x74, 0xCD, 0xA7, 0x3C, 0xCF, 0x18, 0x28, 0x0F, 0x5E, - 0xBC, 0x00, 0x8F, 0xDD, 0xC7, 0xC0, 0x2D, 0xF0, 0x96, 0xC9, 0x1D, 0x78, 0xE5, 0xC9, 0x74, 0x04, - 0x5D, 0x70, 0xED, 0x3D, 0x8B, 0x4C, 0xB3, 0x9E, 0xA5, 0x8C, 0x0F, 0x02, 0x59, 0x5E, 0x99, 0xF9, - 0x3F, 0x93, 0x0E, 0x7E, 0xEB, 0x81, 0x0B, 0x05, 0x7D, 0xC7, 0x6F, 0x6F, 0x70, 0x46, 0x92, 0x3E, - 0x1D, 0xA6, 0x93, 0x8F, 0xBC, 0xFF, 0x1D, 0x5A, 0x63, 0x3B, 0xC1, 0x04, 0xFB, 0x88, 0x25, 0x1C, - 0xC6, 0xB8, 0x59, 0xB2, 0x3F, 0x0D, 0xC0, 0xBC, 0xF1, 0xBF, 0x61, 0x95, 0x81, 0x62, 0x6A, 0x2E, - 0x4B, 0xBD, 0x60, 0xC0, 0xD4, 0xA7, 0x83, 0xDA, 0xA8, 0xF0, 0xFA, 0x0C, 0xCE, 0xCB, 0x7D, 0x71, - 0x49, 0x6B, 0x66, 0x44, 0x6F, 0x71, 0x0E, 0xAD, 0x8D, 0x85, 0xCD, 0xC0, 0x6F, 0xD8, 0xFD, 0x41, - 0x39, 0x57, 0x22, 0x8F, 0xD6, 0x98, 0x2F, 0xCE, 0x77, 0xD4, 0xAB, 0x8D, 0x92, 0x4F, 0x44, 0xA7, - 0xA1, 0xEF, 0x4C, 0xFA, 0x14, 0x04, 0xE7, 0xCF, 0x03, 0xD3, 0xFE, 0xC8, 0x61, 0xE1, 0x9F, 0x35, - 0x31, 0xE1, 0xED, 0x29, 0xBC, 0xA8, 0x82, 0x43, 0xCB, 0xC5, 0xD0, 0xF2, 0x99, 0x38, 0x3A, 0xF3, - 0x1C, 0x37, 0x3C, 0xA3, 0xFE, 0x35, 0xAC, 0x11, 0xA4, 0xD5, 0xD0, 0x8C, 0x58, 0x0F, 0xA3, 0x3B, - 0x96, 0x53, 0x66, 0xD1, 0xE7, 0x82, 0xEB, 0xBD, 0x08, 0xCB, 0xE6, 0x39, 0xBB, 0xBD, 0xE1, 0x90, - 0x85, 0x50, 0xCF, 0x86, 0x3A, 0x98, 0x9C, 0x7A, 0x77, 0x33, 0x22, 0x39, 0xF6, 0x7C, 0xAB, 0x36, - 0x0A, 0xE1, 0x3F, 0x9C, 0xDD, 0xA0, 0xDA, 0x52, 0x3C, 0x10, 0x62, 0xAE, 0xC6, 0x8C, 0x0C, 0xCD, - 0x43, 0x36, 0x02, 0xCB, 0xF9, 0xD1, 0xE9, 0xE1, 0xAF, 0x33, 0xA2, 0xDA, 0x3B, 0x3F, 0x9B, 0x0F, - 0x4F, 0xE8, 0x11, 0xBE, 0x8D, 0xC3, 0x42, 0x6D, 0x76, 0x74, 0x3A, 0x33, 0xC2, 0xC8, 0x37, 0xAD, - 0x87, 0x27, 0xEB, 0x2A, 0x6B, 0x25, 0x84, 0x31, 0x46, 0x3E, 0x9D, 0xA0, 0x15, 0xC4, 0x04, 0xDE, - 0xF2, 0xE2, 0x93, 0x97, 0x44, 0x01, 0x65, 0x7A, 0x69, 0x38, 0x10, 0x56, 0xE5, 0x0D, 0x3A, 0x1B, - 0x5A, 0x09, 0xB7, 0x5C, 0xA9, 0x92, 0xA9, 0x3D, 0x49, 0x7D, 0xB3, 0x6F, 0x06, 0x93, 0x43, 0x71, - 0x1F, 0x3B, 0x4D, 0x1D, 0x16, 0x61, 0xB8, 0x68, 0x4A, 0x17, 0xEC, 0xA7, 0x76, 0x98, 0x9C, 0x04, - 0xEF, 0x83, 0x92, 0x7E, 0x9E, 0x39, 0xF8, 0xE0, 0x6E, 0x88, 0x49, 0x57, 0xB8, 0x36, 0x41, 0x78, - 0x0F, 0x4E, 0x05, 0x0A, 0x6C, 0xC4, 0x72, 0xFB, 0x37, 0x5C, 0xCF, 0xA5, 0x0D, 0x35, 0x71, 0x3D, - 0x5B, 0xD6, 0x14, 0x43, 0x5E, 0x81, 0x8F, 0xFF, 0x95, 0x83, 0x82, 0x57, 0xED, 0x53, 0x9C, 0xC7, - 0xF7, 0xFB, 0x3F, 0xE3, 0x6D, 0x51, 0xF4, 0x15, 0xC4, 0xBD, 0x46, 0x96, 0xAC, 0x56, 0xC2, 0x2D, - 0x12, 0x79, 0xC7, 0x89, 0xFA, 0x79, 0x76, 0x6F, 0x56, 0x15, 0x81, 0xA5, 0x4D, 0xDF, 0xB5, 0xB5, - 0xA3, 0xC4, 0xAD, 0x8B, 0xEB, 0x0E, 0x46, 0x81, 0xC8, 0x9C, 0x8F, 0xC9, 0xB4, 0xE3, 0x7C, 0xAA, - 0xFF, 0x98, 0xC2, 0x22, 0x9C, 0xA7, 0x8A, 0xF7, 0x7C, 0x70, 0x0D, 0x97, 0x1A, 0x6D, 0xF9, 0xE0, - 0xB0, 0x45, 0xDA, 0xCA, 0x29, 0x49, 0x23, 0x27, 0x49, 0xAF, 0x44, 0x41, 0x6C, 0x61, 0xC1, 0xF7, - 0x95, 0x15, 0xD9, 0x7B, 0x91, 0x18, 0x5E, 0xD9, 0x95, 0x01, 0x3E, 0x7F, 0xFB, 0xD2, 0x16, 0x19, - 0x77, 0x59, 0x10, 0xB9, 0x5A, 0xC2, 0xFD, 0x4A, 0x56, 0x18, 0xF5, 0xD8, 0xB3, 0xD4, 0xA2, 0xA4, - 0x65, 0x58, 0x93, 0xAC, 0xAD, 0x9D, 0xD3, 0xB1, 0x77, 0x4B, 0x59, 0x1C, 0x1C, 0xEE, 0x36, 0x61, - 0xB8, 0x1C, 0xFB, 0x83, 0x97, 0x57, 0x15, 0x4A, 0xB2, 0x03, 0xFC, 0xD2, 0xF5, 0xC2, 0xA5, 0xB6, - 0x1E, 0x84, 0xB7, 0x1C, 0xC9, 0xCB, 0x97, 0x6F, 0x7D, 0x3F, 0xAE, 0xB0, 0xA2, 0x05, 0x47, 0x5A, - 0x5C, 0x26, 0x3E, 0xE4, 0x38, 0xD3, 0x52, 0x7C, 0x28, 0x61, 0xAB, 0x40, 0x04, 0x53, 0xEE, 0x36, - 0x5B, 0x4D, 0xF8, 0x29, 0xA1, 0x02, 0x3E, 0xAA, 0xD1, 0x8F, 0xE3, 0x50, 0x2B, 0xF1, 0x10, 0x87, - 0xB7, 0x9A, 0xF8, 0x88, 0x0A, 0xCB, 0xF3, 0x92, 0xBB, 0x1D, 0x5B, 0xC4, 0x92, 0x61, 0x0F, 0x9B, - 0x05, 0x79, 0x99, 0x91, 0x72, 0xA6, 0x38, 0xBF, 0x39, 0x5B, 0xAF, 0x66, 0xDE, 0xB5, 0x25, 0x8E, - 0x0B, 0x9E, 0xE4, 0x90, 0xAF, 0x92, 0x12, 0x9E, 0x52, 0xCF, 0x74, 0xA0, 0x01, 0x59, 0x52, 0xCA, - 0x9F, 0x45, 0x61, 0x9C, 0xD2, 0x03, 0x01, 0x20, 0x8C, 0xE4, 0x09, 0x81, 0xA5, 0xA8, 0xB0, 0x45, - 0x7A, 0x9D, 0x4E, 0x67, 0x39, 0x6D, 0xED, 0xD8, 0xA1, 0x3D, 0x58, 0xB9, 0x16, 0x61, 0x0B, 0x3B, - 0x3C, 0x75, 0x50, 0xAC, 0x1F, 0xB6, 0x91, 0x1F, 0xEC, 0x6B, 0xCB, 0x25, 0x0C, 0x9C, 0x66, 0x05, - 0x2F, 0x09, 0x8A, 0x20, 0x86, 0x46, 0x12, 0x31, 0x85, 0xC1, 0x88, 0x5A, 0x7E, 0x44, 0xA2, 0x1C, - 0xDE, 0x66, 0x9A, 0xC7, 0xFE, 0x74, 0x30, 0x80, 0xD5, 0x1D, 0xE3, 0x52, 0xCA, 0x5A, 0x1E, 0xE3, - 0x11, 0xE5, 0x26, 0x0E, 0x9B, 0x3C, 0x71, 0x79, 0x9A, 0xA9, 0x04, 0x67, 0x59, 0x74, 0x06, 0xC6, - 0x60, 0x15, 0x19, 0x31, 0x25, 0xE4, 0x17, 0x2D, 0xE7, 0xE2, 0xF7, 0x5B, 0xAE, 0xC5, 0x8A, 0xD9, - 0xB4, 0x12, 0x4C, 0xAF, 0xC4, 0xA3, 0x1D, 0x07, 0x3C, 0xB3, 0xC2, 0xF9, 0xB7, 0xED, 0x33, 0xE3, - 0xB7, 0x24, 0x22, 0x2C, 0x62, 0xCE, 0x76, 0xF2, 0xA1, 0xF0, 0xDE, 0xA4, 0x12, 0x94, 0x61, 0xDC, - 0xFE, 0xE5, 0x0B, 0xFA, 0x7F, 0x2A, 0xAB, 0x6F, 0x6D, 0xBF, 0xA0, 0x32, 0x87, 0x29, 0x72, 0x45, - 0xFC, 0x19, 0x9A, 0x94, 0xCF, 0xA1, 0xE1, 0xAE, 0x43, 0x66, 0x4F, 0x8B, 0x3E, 0x4A, 0x74, 0x5C, - 0xD2, 0x1E, 0xB9, 0xFF, 0x1A, 0x42, 0x91, 0x45, 0x9A, 0xFB, 0xF8, 0x5A, 0x93, 0xAE, 0x34, 0x52, - 0x7F, 0x6B, 0x2E, 0x82, 0x41, 0x53, 0xD8, 0x93, 0x30, 0x88, 0x97, 0xDD, 0xA9, 0xE0, 0x3B, 0x98, - 0x12, 0x3E, 0xB4, 0xF1, 0xF2, 0x11, 0xF7, 0xC7, 0x37, 0xBF, 0x4A, 0xCA, 0xC8, 0x8A, 0xC5, 0x9C, - 0xC0, 0x8A, 0x19, 0xDD, 0x0E, 0x0C, 0xE3, 0xCD, 0x4D, 0xE0, 0xF7, 0x04, 0x9C, 0x3C, 0x4C, 0x2A, - 0x71, 0x45, 0xC3, 0x3B, 0x3C, 0x16, 0xEC, 0xB0, 0xBD, 0x1F, 0x28, 0x6B, 0xB4, 0xD0, 0x8E, 0x8D, - 0x46, 0xD6, 0x24, 0xA0, 0x98, 0x9F, 0x8F, 0x27, 0xD8, 0x60, 0xBB, 0x1D, 0xAA, 0xFA, 0x9A, 0xE8, - 0xE3, 0xBA, 0x76, 0x91, 0x3C, 0x20, 0xFE, 0x62, 0x3E, 0x30, 0xBF, 0x57, 0x19, 0x2E, 0xB6, 0xB2, - 0x99, 0xD8, 0x9A, 0x45, 0x0E, 0x48, 0xBF, 0xAC, 0x24, 0xEA, 0xF1, 0x60, 0x94, 0x83, 0xA8, 0xD8, - 0xE7, 0xF3, 0x08, 0x18, 0xEE, 0x01, 0xBF, 0xF4, 0x3C, 0x80, 0x75, 0x88, 0x6C, 0x92, 0x45, 0x81, - 0x69, 0x08, 0xA2, 0x4A, 0x47, 0x03, 0x09, 0x6A, 0x72, 0x48, 0xD3, 0x50, 0x85, 0xE9, 0x67, 0x95, - 0x95, 0xAE, 0xA2, 0x47, 0x58, 0x11, 0x64, 0x3A, 0xC9, 0x03, 0xE0, 0x43, 0x3B, 0x4D, 0x40, 0x6E, - 0x2B, 0x38, 0x83, 0x0E, 0xBA, 0xF4, 0x6F, 0x1D, 0x3A, 0xB2, 0x83, 0xA5, 0xE4, 0x15, 0x8A, 0x7D, - 0x21, 0x04, 0xE1, 0x45, 0x0F, 0x92, 0x0C, 0x20, 0xBA, 0x78, 0x62, 0xC1, 0x8A, 0xFD, 0x3C, 0x91, - 0x48, 0x06, 0x24, 0x1E, 0x6D, 0x0A, 0x22, 0xF5, 0xC8, 0x7D, 0xCB, 0x84, 0x4E, 0xBA, 0x05, 0x41, - 0xF1, 0xAE, 0x75, 0x55, 0x38, 0x54, 0x29, 0x01, 0x0A, 0xBF, 0x96, 0x83, 0x7E, 0x93, 0xE4, 0xB4, - 0x02, 0x50, 0x96, 0xE1, 0xAA, 0x3A, 0x55, 0xA6, 0x44, 0x02, 0xBC, 0x34, 0xE5, 0xB3, 0x33, 0x49, - 0x50, 0xF2, 0xAE, 0x4C, 0x39, 0x68, 0x29, 0xF5, 0x15, 0x43, 0x80, 0x7F, 0x96, 0x82, 0xFC, 0xC5, - 0x79, 0xEB, 0x24, 0x80, 0x77, 0xCE, 0xB5, 0x53, 0x0E, 0xEE, 0x62, 0xFF, 0xEC, 0xE3, 0x81, 0xC4, - 0x33, 0xAC, 0x34, 0x3F, 0xDA, 0x93, 0x72, 0xB0, 0xEC, 0x5E, 0x6B, 0x02, 0xCA, 0xFC, 0xF9, 0x72, - 0x90, 0xE9, 0xA5, 0xE6, 0x7D, 0x82, 0x47, 0xF2, 0xF5, 0xCA, 0x61, 0xEB, 0xDF, 0x07, 0x21, 0x1D, - 0x27, 0x08, 0x02, 0xFE, 0x77, 0x29, 0xD8, 0x43, 0x35, 0x6F, 0x19, 0x40, 0xC7, 0x99, 0xCC, 0x4A, - 0xC1, 0x9F, 0x5E, 0x48, 0xC2, 0xC3, 0xE4, 0x66, 0xA5, 0xA0, 0xDE, 0x4A, 0x4F, 0x85, 0x00, 0x9C, - 0xBC, 0x44, 0x8A, 0xE0, 0xB9, 0xB3, 0xA0, 0xCF, 0x6E, 0x7C, 0x14, 0x8B, 0x21, 0x49, 0x38, 0xE5, - 0x94, 0x01, 0xE5, 0x59, 0x18, 0x92, 0x3B, 0xCD, 0x78, 0x6C, 0xDC, 0xC2, 0x17, 0x9C, 0x36, 0xB6, - 0x25, 0x63, 0xCA, 0xB2, 0x8C, 0x6E, 0x6C, 0x03, 0xA4, 0xE5, 0x5B, 0x03, 0x3C, 0x4B, 0x93, 0xCD, - 0xA9, 0x3A, 0xEA, 0x97, 0x63, 0xD2, 0x2C, 0x25, 0x6D, 0x06, 0x5D, 0x6E, 0xB8, 0x0D, 0x3B, 0xE7, - 0x2D, 0x7C, 0x6B, 0xA7, 0xD3, 0xE9, 0xF6, 0x5A, 0xEC, 0xB1, 0xA0, 0xB4, 0x3D, 0xE7, 0xA5, 0xCC, - 0xAA, 0x77, 0x3B, 0x0C, 0xC0, 0x64, 0x40, 0x22, 0xA9, 0x22, 0xC9, 0x7D, 0x39, 0x27, 0x17, 0xDB, - 0xA5, 0xC8, 0x64, 0x87, 0x27, 0xD2, 0x6A, 0xB0, 0xE9, 0x64, 0xBB, 0x93, 0x39, 0x9D, 0x6C, 0x77, - 0x4A, 0x90, 0x4D, 0xA1, 0xDE, 0x3F, 0xFD, 0x30, 0x13, 0xE6, 0xD8, 0x87, 0xCD, 0xDA, 0x5E, 0x8E, - 0xCF, 0xC6, 0xD2, 0xDE, 0xAD, 0xA9, 0xCF, 0xDD, 0x04, 0x78, 0xDF, 0x02, 0x09, 0xF9, 0xEF, 0xBD, - 0x20, 0x14, 0xBD, 0xBF, 0x99, 0xEA, 0xFD, 0xCD, 0x8C, 0xDE, 0x4F, 0xB7, 0x3E, 0x43, 0x02, 0x29, - 0x72, 0x68, 0xC1, 0x38, 0xB9, 0x6D, 0xFC, 0xA7, 0x53, 0x64, 0x1F, 0xAB, 0x51, 0x32, 0xB4, 0x8C, - 0xBD, 0x14, 0xC4, 0xF6, 0xBC, 0x39, 0xA9, 0xF5, 0x8E, 0x4E, 0x67, 0xBD, 0x53, 0xBB, 0x65, 0xBC, - 0x1D, 0x1F, 0x03, 0xEA, 0x67, 0x4B, 0x33, 0x5D, 0x80, 0xF5, 0x99, 0x11, 0x0C, 0xBF, 0xF6, 0x86, - 0x5E, 0x7B, 0xE0, 0x8D, 0xF1, 0x2F, 0xFC, 0x4A, 0xC6, 0xC8, 0x18, 0x26, 0x44, 0x05, 0xC3, 0xE2, - 0x80, 0xC7, 0x3A, 0xB6, 0x9C, 0x11, 0x86, 0x99, 0xF9, 0xE0, 0x13, 0xE5, 0xB3, 0x16, 0x9D, 0xD7, - 0x11, 0x7E, 0x5E, 0x86, 0x41, 0x93, 0x77, 0x60, 0x2B, 0xC5, 0xB1, 0x1F, 0x06, 0xBE, 0x89, 0x2C, - 0x6A, 0x01, 0x01, 0x9B, 0x45, 0xDB, 0x84, 0xD3, 0xB3, 0xEE, 0xC9, 0x9D, 0x05, 0x26, 0x03, 0xE4, - 0x60, 0x3B, 0x01, 0x8B, 0xF4, 0x3B, 0xBD, 0x38, 0x3F, 0x3A, 0xC3, 0x6D, 0x1F, 0x16, 0xEC, 0x36, - 0xF2, 0x38, 0x37, 0x84, 0x7E, 0x03, 0x8F, 0x02, 0x37, 0xD2, 0xA2, 0x44, 0x61, 0xED, 0x88, 0xA2, - 0xB4, 0x4C, 0x81, 0xBF, 0xF8, 0x3E, 0x10, 0xAE, 0x34, 0xB9, 0x8C, 0x72, 0x24, 0x23, 0x09, 0x40, - 0xB4, 0xA2, 0x1C, 0xBC, 0x50, 0x9C, 0x5E, 0xB7, 0xD3, 0x2D, 0x09, 0xA7, 0x68, 0x41, 0xE3, 0x6A, - 0x64, 0xFB, 0x97, 0xFD, 0x89, 0xE5, 0x7F, 0x7D, 0x3B, 0x75, 0xBB, 0x8D, 0xCA, 0x38, 0xCE, 0x7E, - 0xA9, 0xC6, 0x6F, 0xD4, 0xE1, 0x21, 0x0D, 0xC2, 0xFF, 0x83, 0x3F, 0xAA, 0x37, 0x19, 0x51, 0x00, - 0x59, 0x40, 0xA2, 0xC1, 0x0D, 0xD5, 0x91, 0x75, 0x21, 0x72, 0xD4, 0xBD, 0x7B, 0xB7, 0x97, 0x11, - 0x38, 0x02, 0x70, 0xDA, 0x76, 0x1F, 0xFA, 0x77, 0xB0, 0xE0, 0x88, 0x13, 0x73, 0x27, 0x1B, 0x9D, - 0x6B, 0x6B, 0x63, 0xB6, 0xE8, 0xC3, 0x1A, 0x8E, 0x1D, 0x90, 0x20, 0xB4, 0x7C, 0xA6, 0x03, 0x4C, - 0xA9, 0xB4, 0xCB, 0x75, 0xCF, 0xBE, 0x53, 0x52, 0x38, 0x5C, 0xDA, 0x25, 0xAC, 0xE4, 0x6F, 0x3C, - 0x36, 0x79, 0xC6, 0x0D, 0xC7, 0xFE, 0xB7, 0x5D, 0x8D, 0xFB, 0x2F, 0xF2, 0xA2, 0xD7, 0xB4, 0x9B, - 0x25, 0x91, 0xC8, 0xDA, 0xC2, 0x32, 0x07, 0x19, 0x4B, 0x80, 0x7C, 0xA7, 0x71, 0x27, 0x1D, 0x4A, - 0xA7, 0xAF, 0x3D, 0xCD, 0x21, 0xA2, 0x72, 0xFA, 0xA4, 0xF2, 0x1D, 0xC3, 0x02, 0xA2, 0xE7, 0x2B, - 0x2D, 0x86, 0xF2, 0x49, 0x49, 0x8C, 0xAD, 0x11, 0xF3, 0xA4, 0x66, 0xD2, 0x79, 0x5C, 0x5C, 0x1A, - 0xB4, 0xBE, 0x5A, 0x1E, 0x72, 0x89, 0xFD, 0xD2, 0xD2, 0xD4, 0x2F, 0xF1, 0x15, 0x8A, 0x72, 0x5C, - 0x4B, 0x8E, 0xE3, 0x4A, 0x42, 0x64, 0x4B, 0xFD, 0x22, 0xC5, 0x9B, 0xB1, 0xB5, 0x49, 0x40, 0xFF, - 0xFF, 0xA8, 0x26, 0x97, 0x1B, 0x2F, 0x8F, 0xD5, 0xE2, 0xAA, 0x63, 0x45, 0x7D, 0x30, 0x89, 0x67, - 0x3D, 0x8D, 0xAE, 0x32, 0x16, 0x8F, 0x98, 0x9C, 0xE7, 0x96, 0x66, 0x90, 0x6C, 0xEA, 0x06, 0xEA, - 0xF7, 0x92, 0xAE, 0xE2, 0xE3, 0x4A, 0xB0, 0xB8, 0x8E, 0x01, 0x77, 0x13, 0x9F, 0x66, 0x30, 0x2F, - 0x63, 0xBA, 0x7C, 0x63, 0x0A, 0xCB, 0x73, 0xF7, 0xC7, 0xE6, 0xAA, 0x90, 0xFA, 0x3D, 0xDC, 0x7F, - 0x49, 0xA9, 0x45, 0x3B, 0x7A, 0x19, 0x4A, 0xCD, 0xB2, 0xEB, 0x4A, 0xCB, 0xD2, 0x68, 0x45, 0x65, - 0x08, 0x98, 0x2A, 0xB9, 0xA0, 0x12, 0x0B, 0x1C, 0xEF, 0x2A, 0x40, 0xE1, 0xB2, 0xF4, 0xD1, 0x74, - 0xE0, 0xB9, 0x36, 0xBA, 0xEC, 0x5B, 0x1D, 0xD6, 0x1C, 0x43, 0x63, 0xB6, 0x3A, 0xE2, 0xED, 0x0E, - 0xB9, 0x21, 0x6F, 0x8C, 0x19, 0xD6, 0xF3, 0x89, 0x9D, 0x79, 0x81, 0x83, 0xFF, 0xDF, 0x1B, 0x0C, - 0xA6, 0xB0, 0x8C, 0xB9, 0xE7, 0x0B, 0x9D, 0x4D, 0x14, 0x64, 0x8A, 0x68, 0xB7, 0xCD, 0xA8, 0x6E, - 0xB6, 0x73, 0xA8, 0x26, 0x64, 0x15, 0x9F, 0x94, 0x45, 0x5B, 0x1D, 0xB2, 0x64, 0x4F, 0x2D, 0xE5, - 0x29, 0x76, 0x99, 0x51, 0x33, 0xC4, 0x27, 0x84, 0x90, 0x9E, 0x68, 0x2F, 0x86, 0xF8, 0x0D, 0x20, - 0xA4, 0xA7, 0xDB, 0xF3, 0x01, 0x8E, 0xAD, 0x90, 0xA5, 0x9D, 0x6E, 0xB1, 0x97, 0xE6, 0xB7, 0x3B, - 0xBD, 0xED, 0x8D, 0xE7, 0xDB, 0x05, 0x20, 0x9E, 0x3B, 0x14, 0x30, 0xFC, 0x11, 0xFA, 0x17, 0x9B, - 0x9D, 0xCD, 0xE7, 0x5B, 0xDD, 0x7C, 0xA8, 0xBD, 0x51, 0xE8, 0x84, 0x53, 0x9B, 0x6D, 0x91, 0x6C, - 0x6E, 0x01, 0xAD, 0x17, 0xDB, 0xCA, 0xF2, 0x4B, 0x3B, 0xB0, 0x51, 0x31, 0x64, 0xA8, 0x47, 0x26, - 0xC5, 0xFC, 0x1E, 0x86, 0x1E, 0x94, 0xBB, 0x2A, 0x52, 0xE2, 0xFC, 0x30, 0xBB, 0x1C, 0x7D, 0xAE, - 0x29, 0xDA, 0xFA, 0xE2, 0xAD, 0x24, 0xE2, 0x02, 0x0B, 0xA2, 0xE9, 0xE6, 0xF3, 0x0E, 0xFB, 0xD7, - 0x22, 0xF1, 0x2F, 0xF1, 0x38, 0x88, 0xCA, 0x70, 0x10, 0x88, 0x5F, 0x8B, 0x87, 0x5F, 0x11, 0xD1, - 0x4F, 0xDF, 0x83, 0xE8, 0x6F, 0x8B, 0x20, 0xFA, 0x90, 0x17, 0xAB, 0x5C, 0xDD, 0x1C, 0xD4, 0x33, - 0x09, 0x95, 0xCC, 0x42, 0x5A, 0x5E, 0x49, 0xD0, 0x12, 0x18, 0xFB, 0x9F, 0xA9, 0x8F, 0xC9, 0xCD, - 0xE1, 0xDB, 0x1A, 0xBB, 0xFE, 0x91, 0x5C, 0xF0, 0x2F, 0x25, 0x68, 0x49, 0x1B, 0x57, 0xBB, 0xDD, - 0xCE, 0xFA, 0x46, 0x8B, 0xBC, 0x78, 0xA1, 0x6C, 0x8D, 0xF2, 0xCF, 0x28, 0x64, 0x2C, 0x28, 0x61, - 0x54, 0x33, 0xC8, 0xE9, 0xF7, 0x0A, 0x90, 0x20, 0x26, 0xB6, 0xDF, 0x54, 0x68, 0x6D, 0xB2, 0x54, - 0xF1, 0x9B, 0xB5, 0xB5, 0xC7, 0x1C, 0x7D, 0x08, 0xB4, 0x7A, 0x7C, 0xC6, 0xED, 0x69, 0x13, 0x2F, - 0xFF, 0xCE, 0xF3, 0xD9, 0x77, 0xDA, 0xA5, 0x15, 0xE8, 0x21, 0x73, 0xAF, 0x32, 0x0E, 0xAA, 0xAD, - 0xB3, 0x57, 0xC9, 0x81, 0x93, 0x3D, 0xA4, 0xCB, 0x4E, 0xE9, 0xBD, 0x6A, 0x19, 0x9E, 0x31, 0xDD, - 0x29, 0xB3, 0x5B, 0x29, 0x13, 0xC4, 0x4D, 0xA7, 0x88, 0x60, 0xFE, 0x7E, 0x65, 0x79, 0x5A, 0x99, - 0xAD, 0xC3, 0xED, 0x1E, 0x46, 0xAC, 0xA3, 0xB5, 0xAE, 0x33, 0x63, 0xEB, 0x72, 0x29, 0x9E, 0xFD, - 0xF2, 0x58, 0x34, 0x93, 0xBD, 0xB4, 0x85, 0xF4, 0x61, 0x2E, 0xC5, 0xC7, 0x6B, 0xA5, 0xA4, 0xA9, - 0xDD, 0xFA, 0x14, 0xBB, 0xB5, 0x34, 0x55, 0x10, 0xD4, 0x35, 0xB5, 0x93, 0xAF, 0xA9, 0xDD, 0x7A, - 0x9A, 0xBA, 0x88, 0xD6, 0x15, 0x69, 0xEA, 0x23, 0xD1, 0x94, 0x34, 0xF5, 0xD1, 0x29, 0x3E, 0x5E, - 0x2B, 0x25, 0x4D, 0xED, 0xD5, 0xA7, 0xD8, 0xAB, 0xA5, 0xA9, 0xBD, 0x5A, 0x9A, 0xDA, 0xAB, 0xA7, - 0xA9, 0x8B, 0x68, 0x5D, 0x91, 0xA6, 0x3E, 0x12, 0x4D, 0x49, 0x53, 0x1F, 0x9D, 0xE2, 0xE3, 0xB5, - 0x52, 0xD2, 0xD4, 0xF5, 0xFA, 0x14, 0xD7, 0x6B, 0x69, 0xEA, 0x7A, 0x2D, 0x4D, 0x5D, 0xAF, 0xA7, - 0xA9, 0x8B, 0x68, 0x5D, 0x91, 0xA6, 0x3E, 0x12, 0x4D, 0x49, 0x53, 0x1F, 0x9D, 0xE2, 0x9C, 0x5A, - 0xF9, 0xD4, 0x8F, 0x5B, 0x8D, 0xAE, 0x72, 0xA5, 0x03, 0x57, 0xA3, 0xEF, 0x5B, 0xEA, 0xC8, 0xD5, - 0xE8, 0xC8, 0x56, 0x3D, 0xFC, 0xCC, 0xF0, 0x4D, 0x1B, 0x65, 0x21, 0x35, 0x0F, 0x93, 0x9F, 0xF9, - 0xDA, 0x77, 0x6E, 0x78, 0xE7, 0xF6, 0xAA, 0xE3, 0x88, 0xA8, 0xFF, 0x72, 0xBE, 0x79, 0x77, 0xEE, - 0x6D, 0xBC, 0xAF, 0xC6, 0x7F, 0xEC, 0x01, 0x36, 0x6A, 0x88, 0x9D, 0x79, 0x00, 0xD5, 0x65, 0x5E, - 0x83, 0x9C, 0xE4, 0x58, 0xD5, 0x11, 0x73, 0x4D, 0xB8, 0xAA, 0x14, 0x35, 0x57, 0xA5, 0x8E, 0x48, - 0x7B, 0xF5, 0x44, 0xDA, 0xAB, 0x2D, 0xD2, 0x5E, 0x4D, 0x91, 0xF6, 0x6A, 0x8B, 0xB4, 0x57, 0x53, - 0xA4, 0xEB, 0x35, 0x45, 0xBA, 0x5E, 0x4F, 0xA4, 0xEB, 0xB5, 0x45, 0xBA, 0x5E, 0x53, 0xA4, 0xEB, - 0xB5, 0x45, 0xAA, 0x43, 0xC6, 0x07, 0x0A, 0xF2, 0x8D, 0x5A, 0xD3, 0xC1, 0x42, 0xD1, 0xBD, 0xDB, - 0x9C, 0xAD, 0x90, 0x28, 0x03, 0x00, 0xBB, 0x60, 0x2F, 0x21, 0x38, 0x60, 0x6F, 0xD5, 0x88, 0xC0, - 0xBB, 0x0B, 0xEF, 0x2B, 0x75, 0xA3, 0x44, 0x14, 0x3B, 0xCF, 0xB4, 0xDC, 0x24, 0x53, 0x1A, 0x27, - 0xC7, 0xD6, 0xDF, 0x0B, 0x30, 0x06, 0x02, 0xE6, 0x53, 0x69, 0x91, 0xF5, 0x2D, 0xFE, 0x5F, 0x3C, - 0x75, 0xAE, 0x6F, 0x65, 0xC5, 0x05, 0x9E, 0x99, 0x42, 0x94, 0x72, 0xF7, 0xC8, 0x0B, 0xA9, 0x37, - 0x1A, 0xFA, 0x7D, 0xDA, 0x69, 0xE8, 0xFD, 0x8D, 0xDE, 0x9F, 0x53, 0x97, 0xDE, 0x59, 0xA3, 0x8C, - 0x98, 0x17, 0xA9, 0xAB, 0xFC, 0x9C, 0x2E, 0xD2, 0x2F, 0x31, 0x57, 0x3B, 0xFE, 0xA1, 0x32, 0x34, - 0x5E, 0xF9, 0x79, 0xC3, 0xCF, 0x5C, 0x38, 0x36, 0xB6, 0xC9, 0xB1, 0xD5, 0x49, 0x6D, 0xD3, 0x8A, - 0x07, 0xDC, 0x5B, 0xF8, 0x55, 0xDB, 0xA2, 0x3D, 0x33, 0x3F, 0x6E, 0x5B, 0x44, 0xFA, 0x98, 0xF5, - 0xF6, 0x9C, 0x08, 0xC6, 0x92, 0xC3, 0xA0, 0xE1, 0xA2, 0x20, 0x52, 0x0C, 0x25, 0x3E, 0x85, 0x46, - 0x7B, 0xFE, 0xD7, 0xCB, 0x4E, 0xBF, 0x7F, 0x74, 0x50, 0xDA, 0xD1, 0x32, 0x84, 0x26, 0x1B, 0x42, - 0x29, 0x8D, 0x74, 0xCE, 0xAC, 0x20, 0x80, 0xDF, 0xEC, 0x47, 0xA0, 0xD5, 0x7D, 0xA4, 0x36, 0x75, - 0x1F, 0xB1, 0x4D, 0xBD, 0x47, 0x6A, 0x53, 0xEF, 0x11, 0xDB, 0xB4, 0xFE, 0x48, 0x6D, 0x5A, 0x9F, - 0x53, 0x9B, 0xC4, 0x10, 0xBB, 0xD8, 0x3F, 0x5B, 0xFB, 0x78, 0x70, 0x96, 0x6D, 0x9F, 0x2E, 0x06, - 0x95, 0x63, 0x7D, 0x85, 0x81, 0x88, 0xAF, 0x8B, 0x27, 0x31, 0xB7, 0x5B, 0x9B, 0x9B, 0xEB, 0xA9, - 0x28, 0x5F, 0xF6, 0x51, 0x66, 0x54, 0x89, 0xF9, 0x2F, 0x58, 0x6F, 0xC5, 0x44, 0xA4, 0x38, 0xE2, - 0xF2, 0x51, 0xE4, 0x26, 0x4A, 0x0F, 0x66, 0x21, 0x54, 0x3D, 0x44, 0x48, 0x84, 0xC0, 0x21, 0xE7, - 0x21, 0x04, 0x13, 0x6B, 0x1F, 0xED, 0xBA, 0xAC, 0x4D, 0xED, 0xB9, 0xB3, 0xB6, 0xB6, 0xF6, 0xC1, - 0x25, 0xD1, 0x95, 0x85, 0x16, 0x81, 0x8A, 0x84, 0xF7, 0x0E, 0x8B, 0xA0, 0xE0, 0xD4, 0xD8, 0x73, - 0xC8, 0xB8, 0xEC, 0x04, 0xFC, 0xBC, 0x09, 0x36, 0xBE, 0xB8, 0x8C, 0xEB, 0xCF, 0x00, 0x23, 0x39, - 0x42, 0x98, 0xC5, 0xA2, 0xA8, 0x89, 0x29, 0x20, 0xF1, 0x5C, 0x82, 0x9A, 0xDB, 0xC2, 0x1A, 0xF7, - 0xE2, 0x2D, 0xE5, 0x76, 0x3B, 0x5A, 0x99, 0xF2, 0x60, 0x7B, 0x91, 0xBD, 0xF2, 0x64, 0x1A, 0xD2, - 0x6F, 0x69, 0xC5, 0xC5, 0x4B, 0x13, 0x5A, 0x37, 0xC2, 0xA7, 0xDA, 0xCC, 0xE5, 0x89, 0x22, 0xBA, - 0xB1, 0xCE, 0x6E, 0xB1, 0x67, 0x8E, 0x29, 0x91, 0xCC, 0xA3, 0x5A, 0x77, 0x8D, 0x00, 0x28, 0x3E, - 0x60, 0x07, 0x2F, 0xEE, 0xAD, 0x4F, 0xFF, 0x31, 0xA5, 0x2E, 0x3B, 0x98, 0xDF, 0xEE, 0xAC, 0xC3, - 0x8F, 0xDE, 0x73, 0xA9, 0xEB, 0xE0, 0x13, 0xDB, 0x22, 0xEA, 0x3D, 0x97, 0xF9, 0x95, 0xAF, 0xC4, - 0xE4, 0x4F, 0xEF, 0x48, 0x0E, 0x64, 0xE2, 0x58, 0x23, 0x16, 0xBF, 0x63, 0x31, 0xCF, 0x51, 0x5C, - 0x2A, 0xBE, 0xC4, 0x41, 0xD4, 0x4D, 0x05, 0x99, 0x74, 0x4D, 0xC1, 0x25, 0x06, 0x8A, 0x49, 0xA8, - 0x97, 0x94, 0x35, 0x32, 0xFF, 0xCE, 0x46, 0xEA, 0x7E, 0x75, 0x70, 0xEC, 0x5C, 0x53, 0xD1, 0x1B, - 0x78, 0x64, 0xD9, 0x93, 0x19, 0xE1, 0x27, 0x96, 0x3D, 0x85, 0x8F, 0xEC, 0x2B, 0x3D, 0xCB, 0x52, - 0xCE, 0x85, 0x00, 0x3A, 0x82, 0xA5, 0x5C, 0xCA, 0x67, 0x67, 0x8E, 0x07, 0xA7, 0x8F, 0x79, 0x60, - 0x2A, 0x9A, 0xC9, 0xEF, 0x23, 0xE5, 0xA9, 0x67, 0x94, 0x46, 0xA5, 0x9A, 0x86, 0x8E, 0xAD, 0x6F, - 0x00, 0x7A, 0xE1, 0x44, 0xD7, 0x79, 0xBA, 0x9D, 0x4D, 0xE8, 0x84, 0x94, 0x1F, 0xD8, 0x6D, 0xC1, - 0xF7, 0x56, 0x4F, 0x55, 0x13, 0xE5, 0x8E, 0x54, 0xBE, 0x66, 0x72, 0x32, 0xB2, 0xC7, 0x39, 0x2B, - 0xA1, 0x12, 0x8B, 0x04, 0xA5, 0x6D, 0x5B, 0x1D, 0xF2, 0x17, 0xD2, 0xCB, 0x0E, 0x10, 0xD2, 0x38, - 0x54, 0xAB, 0x1B, 0xCF, 0xA9, 0x95, 0xE4, 0x35, 0xD5, 0xA4, 0x9E, 0x80, 0x46, 0x81, 0x76, 0xB1, - 0x1B, 0x9E, 0xF6, 0xC0, 0xE7, 0x21, 0x0A, 0x33, 0xC1, 0x4E, 0x6E, 0xF3, 0x4C, 0x29, 0x75, 0xAA, - 0x35, 0xD3, 0x92, 0x50, 0x30, 0x7B, 0x1F, 0x25, 0x88, 0x4C, 0x0E, 0xC7, 0xCD, 0xA7, 0xE3, 0xDB, - 0x73, 0x68, 0x72, 0x0E, 0xF1, 0xC2, 0x76, 0xA7, 0xB2, 0x52, 0x96, 0x6A, 0xAE, 0x9A, 0x04, 0x93, - 0xFB, 0x35, 0xBD, 0xED, 0x8D, 0xED, 0xAD, 0xE7, 0x29, 0xE7, 0x86, 0x7F, 0x9E, 0x43, 0x2B, 0x75, - 0x9A, 0x1D, 0x16, 0xCD, 0x82, 0xAF, 0x16, 0x89, 0x7D, 0xE3, 0xA8, 0xA1, 0xC2, 0x8E, 0x44, 0x13, - 0x7D, 0xDC, 0xF0, 0xCC, 0x3B, 0x18, 0xE6, 0xA6, 0x1E, 0x9D, 0xED, 0xF1, 0x5B, 0x46, 0x4B, 0xF1, - 0xA5, 0xC6, 0xA3, 0xB3, 0x86, 0xD4, 0x3E, 0xD7, 0x75, 0xDB, 0xD2, 0x7F, 0x72, 0x13, 0xB5, 0x7B, - 0x91, 0x19, 0x16, 0xC3, 0x40, 0xE1, 0xE0, 0xB4, 0xBF, 0x68, 0x12, 0xEF, 0x40, 0xBF, 0xEF, 0xAC, - 0xFB, 0x45, 0x93, 0xE9, 0x4F, 0xAF, 0xE0, 0xE7, 0x5C, 0xA9, 0x44, 0x4B, 0x7B, 0x51, 0xF9, 0x34, - 0x9C, 0x08, 0xDF, 0xB0, 0x93, 0xF6, 0x0D, 0x3B, 0x46, 0xDF, 0xD0, 0x4C, 0x27, 0x9E, 0xF1, 0x4F, - 0x2F, 0xCE, 0xEA, 0x6A, 0x4B, 0x7C, 0x4A, 0x06, 0x3C, 0x8D, 0x46, 0x87, 0xDF, 0x26, 0x9E, 0xCB, - 0x9D, 0x3B, 0x70, 0x7D, 0xBA, 0xF2, 0xA8, 0x60, 0x7E, 0x4F, 0x57, 0x19, 0x10, 0xC9, 0x2D, 0xD8, - 0xA2, 0x23, 0xB8, 0x09, 0x70, 0x33, 0x70, 0x58, 0x76, 0x68, 0x98, 0x70, 0xF1, 0xE2, 0x9E, 0x32, - 0xD3, 0xAE, 0xB3, 0x56, 0x77, 0x6A, 0xE2, 0x3E, 0x87, 0xE1, 0x75, 0x40, 0x47, 0x4C, 0x35, 0x3A, - 0x2D, 0x96, 0xB6, 0x55, 0xDB, 0x28, 0x61, 0xE8, 0xBB, 0xC6, 0x8D, 0x92, 0xAA, 0x74, 0x9C, 0x60, - 0x22, 0xD2, 0x5C, 0x2F, 0x82, 0x58, 0x72, 0xDE, 0x35, 0x39, 0xA7, 0xD7, 0xD4, 0x07, 0x47, 0x94, - 0x1E, 0xD9, 0xC2, 0x50, 0xA5, 0x4C, 0x14, 0x5B, 0x7E, 0x05, 0xB9, 0x04, 0x1E, 0xA2, 0x8C, 0x19, - 0x19, 0x4F, 0x19, 0x6B, 0xB9, 0x33, 0x30, 0xAB, 0x99, 0xA8, 0x22, 0xA5, 0xD3, 0x52, 0xB3, 0x0A, - 0x48, 0xB7, 0x57, 0xE5, 0x8B, 0xCA, 0xBB, 0xA4, 0xAB, 0xE4, 0x00, 0x8A, 0x73, 0xE0, 0x34, 0x31, - 0x15, 0xFE, 0x9B, 0xD0, 0x6D, 0x02, 0x9F, 0x67, 0x60, 0x19, 0xC1, 0x54, 0x32, 0x03, 0xC9, 0xB2, - 0x82, 0x48, 0x18, 0x56, 0xE0, 0x03, 0xFB, 0xB3, 0xA1, 0x7B, 0x00, 0x51, 0x4E, 0x99, 0x18, 0x93, - 0x54, 0x61, 0xA1, 0x4F, 0x2F, 0x3F, 0xA8, 0x57, 0x22, 0x24, 0x66, 0x5F, 0xCF, 0xAD, 0xB5, 0xC1, - 0x93, 0x6C, 0xEE, 0x3F, 0x95, 0x9D, 0xD9, 0x32, 0x09, 0x61, 0x8F, 0x3D, 0x0B, 0xB3, 0x2D, 0xB5, - 0x89, 0x68, 0xF5, 0x9D, 0xE5, 0x84, 0xB0, 0xA0, 0x6C, 0xCA, 0x41, 0xE8, 0x66, 0x1D, 0x34, 0xDF, - 0x7A, 0x88, 0xAE, 0x3C, 0xA4, 0x1B, 0xFA, 0x32, 0x62, 0x3E, 0xDE, 0x27, 0x7F, 0x26, 0x3F, 0xBD, - 0xC9, 0x73, 0xC1, 0xE9, 0x4E, 0xA4, 0xDA, 0x39, 0x52, 0xB1, 0x9C, 0x08, 0x49, 0xEE, 0xBC, 0xBE, - 0x75, 0x8B, 0xCD, 0x69, 0xB7, 0x95, 0x90, 0x4F, 0x2D, 0x6B, 0x54, 0x23, 0xC9, 0x7C, 0xDB, 0xCA, - 0x13, 0x7C, 0x4B, 0x41, 0x32, 0xA4, 0x59, 0x79, 0x36, 0x52, 0x19, 0x3F, 0xE4, 0xD4, 0x23, 0xB3, - 0x64, 0xDC, 0x98, 0x3D, 0xEB, 0xC6, 0x2C, 0x99, 0x37, 0xE6, 0x93, 0x7D, 0x63, 0xF6, 0x0C, 0x1C, - 0xB3, 0x65, 0xE1, 0x98, 0x25, 0x13, 0xC7, 0xAC, 0xD9, 0x38, 0x66, 0xCB, 0xC8, 0x31, 0xFF, 0xAC, - 0x1C, 0xB9, 0x18, 0x93, 0x05, 0x7F, 0x82, 0xC8, 0x49, 0xBE, 0x95, 0xC6, 0x53, 0x90, 0xE1, 0xA3, - 0x18, 0x41, 0xC9, 0x34, 0x1F, 0xF5, 0x53, 0x7D, 0xCC, 0x9A, 0xEE, 0x23, 0x9D, 0x63, 0x13, 0x2D, - 0x10, 0xA7, 0xF7, 0x07, 0x98, 0x80, 0x9F, 0xD6, 0xFC, 0x68, 0x9C, 0xBE, 0x16, 0x35, 0x23, 0x08, - 0xFF, 0x3B, 0x95, 0xF2, 0x4A, 0xCF, 0x50, 0x22, 0xE5, 0xAB, 0x5B, 0xE2, 0x76, 0x5F, 0x2A, 0xBF, - 0x7C, 0x77, 0xD6, 0x57, 0xD7, 0xB0, 0x3C, 0xC9, 0x5D, 0xCC, 0xCA, 0x4F, 0x3F, 0x11, 0x13, 0x14, - 0x28, 0xC4, 0x88, 0x65, 0xC6, 0xAE, 0x0A, 0xF9, 0x86, 0x3A, 0x07, 0xDE, 0xB4, 0x0E, 0xC9, 0xE3, - 0x0F, 0xA7, 0x7B, 0x7D, 0x23, 0xB3, 0xCB, 0x9A, 0xB3, 0x60, 0x4A, 0x6C, 0x51, 0x34, 0xAD, 0x49, - 0xFA, 0xC1, 0xA6, 0x2E, 0x45, 0x88, 0xB2, 0xAA, 0xDC, 0x78, 0x18, 0x55, 0x05, 0x6B, 0x14, 0xA2, - 0xF0, 0x27, 0xEB, 0x48, 0xA2, 0x44, 0x2B, 0x2B, 0xBA, 0x62, 0x98, 0x54, 0xA0, 0x91, 0xA6, 0x68, - 0x4C, 0x66, 0xF6, 0xC6, 0x09, 0x4F, 0xAC, 0x49, 0x92, 0xA6, 0x6C, 0xEC, 0xB8, 0xF0, 0xC3, 0xFA, - 0xD6, 0x22, 0x57, 0xAC, 0x44, 0xCA, 0xF4, 0xD8, 0x8A, 0x8D, 0xC2, 0xD1, 0x81, 0x34, 0x8A, 0xA3, - 0xF3, 0xFF, 0xF8, 0x41, 0x00, 0xCE, 0xDE, 0xD8, 0x0A, 0xBE, 0xF2, 0x02, 0x8E, 0x48, 0x29, 0x64, - 0x8A, 0xC3, 0x61, 0x5F, 0x21, 0x49, 0x9E, 0x57, 0x81, 0x7F, 0x78, 0x8D, 0xE4, 0xF9, 0x87, 0x25, - 0x86, 0x04, 0xBA, 0xAE, 0x4B, 0x5E, 0xBD, 0xE2, 0xB4, 0xA0, 0x63, 0xA0, 0x8F, 0x3A, 0x7A, 0xFF, - 0xE4, 0xA4, 0x88, 0x34, 0xA7, 0x9D, 0x94, 0x60, 0xA5, 0x56, 0x15, 0xF5, 0x68, 0x5E, 0x2F, 0xA4, - 0xB6, 0x4A, 0xA2, 0x44, 0x96, 0x92, 0x41, 0x8C, 0x6E, 0x2C, 0x43, 0xFB, 0x0D, 0x37, 0x7E, 0x02, - 0x02, 0x16, 0x94, 0xD8, 0xB0, 0xA6, 0x9C, 0x80, 0x3D, 0x67, 0x9B, 0x28, 0x6A, 0x67, 0xC5, 0x37, - 0x87, 0xA4, 0x9C, 0xC0, 0x0E, 0x46, 0x12, 0xA8, 0x77, 0xE1, 0x76, 0x92, 0x24, 0xC0, 0x71, 0xD3, - 0xC8, 0xAE, 0x71, 0xA3, 0x37, 0x79, 0xEF, 0xC0, 0xA6, 0x21, 0x98, 0x7A, 0x6A, 0xBF, 0x85, 0x55, - 0xB6, 0xC0, 0x93, 0x3C, 0xF0, 0x10, 0xE7, 0x1A, 0xBE, 0x8D, 0x1E, 0x91, 0xC0, 0x4B, 0x7B, 0xFC, - 0x09, 0x1C, 0xC7, 0x86, 0xE9, 0xCF, 0xB9, 0xBE, 0x8F, 0x1F, 0xDA, 0x59, 0x92, 0x95, 0x61, 0x39, - 0xEE, 0x6F, 0x15, 0x6C, 0x97, 0xA8, 0x17, 0x00, 0x83, 0xF6, 0xFE, 0x87, 0x0F, 0xE7, 0x07, 0x47, - 0xA7, 0x7B, 0x17, 0x87, 0x97, 0x47, 0xA7, 0x67, 0x1F, 0x2F, 0x2E, 0x2F, 0x3E, 0x9D, 0xE1, 0xAF, - 0x3F, 0xEF, 0x1D, 0x1F, 0x1D, 0x5C, 0x7E, 0x3C, 0xFD, 0xDB, 0xE9, 0x87, 0x5F, 0x4E, 0xF5, 0xDB, - 0xD9, 0x71, 0x8F, 0x22, 0x93, 0x09, 0x46, 0xBC, 0x2A, 0x0C, 0xAD, 0x20, 0x53, 0xF7, 0xAB, 0x8B, - 0x59, 0x8C, 0x77, 0x9E, 0x9A, 0xAE, 0xB0, 0x01, 0x30, 0xE0, 0x4F, 0xC2, 0x50, 0x5B, 0x62, 0xFC, - 0x15, 0x59, 0xED, 0xBE, 0xE8, 0x70, 0xF5, 0x37, 0x95, 0xC3, 0x14, 0xF4, 0xA2, 0xB3, 0x9C, 0x2B, - 0x86, 0xE4, 0x50, 0xE1, 0x05, 0x5F, 0xB5, 0xBF, 0xE8, 0x3C, 0x39, 0x01, 0x64, 0x0E, 0x15, 0xAE, - 0x2E, 0x92, 0x4E, 0x47, 0x17, 0x35, 0x77, 0x0C, 0xFA, 0xC7, 0xDF, 0x4B, 0xAA, 0xAE, 0x80, 0x0C, - 0xEE, 0x87, 0x06, 0xFE, 0xD0, 0xC0, 0x6C, 0x0D, 0x4C, 0xE9, 0xCB, 0x9F, 0x76, 0x15, 0xC3, 0x97, - 0xDB, 0x7E, 0x6E, 0x43, 0x03, 0x9E, 0x2D, 0x8B, 0x25, 0xC2, 0x79, 0x22, 0xCD, 0xCF, 0x35, 0xF6, - 0x32, 0x1F, 0x13, 0x1F, 0x16, 0x9B, 0x38, 0x03, 0x25, 0x83, 0xAA, 0xDE, 0x68, 0xC9, 0x14, 0x7B, - 0x5D, 0x36, 0x94, 0x4E, 0x10, 0x49, 0xF5, 0x71, 0x42, 0xB3, 0xF1, 0xF0, 0x1F, 0xCF, 0xDE, 0x0D, - 0x4F, 0xBF, 0xB5, 0xA2, 0xD1, 0x88, 0xE5, 0xE0, 0x0D, 0xAD, 0x8D, 0xB0, 0x47, 0x43, 0xEC, 0x2D, - 0x9E, 0x55, 0x27, 0x9E, 0x66, 0xB5, 0x67, 0x05, 0x92, 0x44, 0xAA, 0xEA, 0x0C, 0x9B, 0xCC, 0x8C, - 0x62, 0x84, 0x30, 0x52, 0x4B, 0x51, 0x9D, 0x96, 0x89, 0x89, 0x24, 0x0D, 0xAA, 0x66, 0xD9, 0x72, - 0x91, 0x41, 0xA5, 0x3C, 0x6C, 0xE9, 0x0B, 0xC5, 0xFC, 0xC8, 0x2C, 0x10, 0x21, 0xFE, 0x5C, 0xBE, - 0xA2, 0xF9, 0x69, 0xEF, 0x2F, 0x95, 0xA5, 0x36, 0x71, 0xFF, 0x6A, 0xBA, 0x7D, 0x25, 0x3D, 0x3B, - 0x81, 0x00, 0x3D, 0x8B, 0xEF, 0xE4, 0xCA, 0xF1, 0xF7, 0x38, 0x13, 0xF7, 0x68, 0x37, 0x33, 0xC5, - 0x89, 0xE1, 0x91, 0xB5, 0x3A, 0xAB, 0x81, 0x87, 0xCA, 0xA4, 0x79, 0x9E, 0x90, 0x1C, 0xF2, 0xF2, - 0x89, 0x7D, 0x79, 0xF2, 0xB5, 0xAC, 0x62, 0x96, 0xEA, 0x88, 0xBD, 0xFD, 0x39, 0xEB, 0x4E, 0xF2, - 0x24, 0xAA, 0xAA, 0x42, 0x49, 0xA4, 0x30, 0x6A, 0xD2, 0xBC, 0x14, 0xC7, 0xD0, 0x1F, 0xA6, 0x6B, - 0xB5, 0x73, 0xEA, 0x08, 0x25, 0x29, 0x9E, 0x4C, 0x62, 0x06, 0xD0, 0x4E, 0xA5, 0xFE, 0x8F, 0xA6, - 0xFF, 0xA2, 0x36, 0x77, 0x9F, 0x74, 0x9B, 0xBB, 0x0B, 0x69, 0x73, 0xEF, 0x49, 0xB7, 0xB9, 0xB7, - 0x90, 0x36, 0xAF, 0x3F, 0xE9, 0x36, 0xAF, 0x57, 0x6D, 0xB3, 0x8E, 0x72, 0xD1, 0x0E, 0x63, 0x96, - 0x69, 0x4C, 0x8E, 0xE1, 0x95, 0x07, 0x33, 0xAA, 0xD9, 0x44, 0xF4, 0x2D, 0x6D, 0xFE, 0x44, 0x35, - 0xB7, 0x80, 0xE2, 0x65, 0xEA, 0x76, 0xC4, 0x36, 0x33, 0x9A, 0x58, 0x23, 0xB2, 0x8D, 0xE0, 0xA8, - 0x6E, 0x24, 0x1B, 0x5F, 0x6C, 0x1B, 0x05, 0x8B, 0x3F, 0x77, 0xBE, 0x88, 0xF9, 0x96, 0x7D, 0x73, - 0x82, 0x53, 0xEB, 0x74, 0x89, 0x9F, 0xE5, 0x44, 0xE5, 0xCB, 0xCB, 0xBC, 0x2C, 0xAA, 0xFE, 0x8A, - 0x74, 0xD4, 0x0F, 0xAF, 0x31, 0x61, 0xFF, 0xB2, 0x09, 0x79, 0xB7, 0x00, 0x79, 0x57, 0x45, 0xDE, - 0xD5, 0x91, 0x77, 0xF3, 0x90, 0xF7, 0x0A, 0x90, 0xF7, 0x54, 0xE4, 0x3D, 0x1D, 0x79, 0x2F, 0x0F, - 0xF9, 0x7A, 0x01, 0xF2, 0x75, 0x15, 0xF9, 0xBA, 0x8E, 0x7C, 0x3D, 0x46, 0xFE, 0xF4, 0xB6, 0xA4, - 0x2A, 0xAB, 0xAC, 0x94, 0x2F, 0xF8, 0xC6, 0x0B, 0x40, 0x55, 0xA7, 0xF0, 0x2B, 0xFC, 0xF4, 0x47, - 0x05, 0x0A, 0x2C, 0x42, 0x99, 0x10, 0x48, 0xA8, 0x6F, 0x3B, 0xF4, 0x8E, 0xBD, 0x3B, 0x76, 0x29, - 0x8A, 0x2E, 0x2D, 0x27, 0xCF, 0xD8, 0x02, 0xAE, 0xE5, 0x8C, 0x1B, 0x44, 0x48, 0xCC, 0x78, 0x4B, - 0x48, 0x77, 0x0A, 0xBA, 0x46, 0x97, 0x60, 0x63, 0xDB, 0xF4, 0x20, 0x2E, 0x22, 0xAD, 0xD9, 0x11, - 0xD5, 0x3B, 0x23, 0x7B, 0xD5, 0x95, 0x63, 0xA2, 0xA4, 0xCE, 0x61, 0x12, 0x28, 0xD3, 0x8B, 0xA2, - 0x62, 0x7A, 0xA3, 0x5E, 0x89, 0x6E, 0x76, 0xEC, 0x6E, 0x8B, 0x38, 0x76, 0xAF, 0x44, 0xE7, 0xF1, - 0x3D, 0x93, 0xAE, 0x21, 0xF4, 0x4C, 0x6C, 0x9D, 0x03, 0x9A, 0x74, 0x61, 0x4A, 0xE5, 0xBB, 0xF5, - 0x75, 0x1E, 0x08, 0x3C, 0xD9, 0x3D, 0xDC, 0xAE, 0xF9, 0x9C, 0x05, 0x65, 0x62, 0x3A, 0xEE, 0x52, - 0x42, 0xE5, 0xD0, 0xF8, 0xF3, 0x9D, 0x28, 0xF5, 0x11, 0x18, 0xE9, 0xF1, 0xDC, 0x48, 0xDF, 0xF3, - 0x86, 0x29, 0x7B, 0x8F, 0xF6, 0xC2, 0x7B, 0x6B, 0x61, 0x18, 0xC1, 0xFD, 0x81, 0xB8, 0xBC, 0xAD, - 0x2E, 0x51, 0xD5, 0xB2, 0xF4, 0xAB, 0xB5, 0x8D, 0xA8, 0x88, 0xEC, 0x4D, 0x60, 0x1A, 0xA1, 0xB6, - 0x12, 0xD7, 0xC0, 0xF2, 0x2B, 0xDA, 0xEC, 0x52, 0x1B, 0xA7, 0x86, 0x87, 0x42, 0xC6, 0x67, 0xA5, - 0x34, 0x4A, 0x2C, 0x6A, 0xB1, 0xD5, 0x6D, 0x35, 0xCC, 0x2C, 0x1B, 0x8E, 0x62, 0x53, 0xEC, 0x97, - 0x7A, 0x9E, 0x2B, 0x79, 0x27, 0x2B, 0x2B, 0xDB, 0x63, 0xC1, 0xD3, 0x5A, 0xBB, 0xE4, 0x9B, 0x12, - 0x63, 0x56, 0xF0, 0x56, 0xA0, 0xDC, 0x96, 0xDF, 0xA9, 0xEF, 0x45, 0x39, 0x7F, 0xA5, 0x37, 0x48, - 0xA4, 0x2C, 0xC7, 0x6C, 0x1B, 0xBF, 0x30, 0x09, 0x35, 0x59, 0xC2, 0x1B, 0x03, 0x86, 0x6C, 0xC5, - 0xCB, 0xCF, 0x16, 0x90, 0x2B, 0xBA, 0x66, 0xD6, 0xE3, 0x4A, 0x19, 0x8F, 0x87, 0x6A, 0xAE, 0x56, - 0xFD, 0x09, 0xF6, 0x07, 0x45, 0x52, 0x7A, 0x62, 0xE1, 0x67, 0x73, 0xCF, 0x50, 0x5C, 0x27, 0x49, - 0x68, 0xF9, 0x04, 0xA1, 0x99, 0x8D, 0x6D, 0x77, 0x8A, 0xDA, 0x9B, 0xA4, 0x16, 0xE6, 0xE7, 0x63, - 0x73, 0x4D, 0x52, 0xFC, 0xB4, 0x5A, 0xCD, 0x1F, 0xE4, 0xC1, 0x66, 0x18, 0x06, 0x84, 0xC0, 0xD4, - 0x0F, 0x7D, 0x6A, 0x8D, 0x13, 0x25, 0x28, 0x27, 0x0F, 0x8E, 0x55, 0x16, 0x88, 0x84, 0xE7, 0x7B, - 0x4B, 0x23, 0x47, 0x01, 0x52, 0xE9, 0x80, 0x67, 0x52, 0x82, 0x34, 0xB6, 0xEF, 0xDC, 0xF4, 0x6E, - 0x3B, 0xAF, 0xF1, 0x87, 0xFC, 0x72, 0xD4, 0x7C, 0xDA, 0x9E, 0x42, 0xF6, 0x9D, 0x9A, 0x9E, 0x5C, - 0xE3, 0x16, 0x2F, 0xB2, 0xA7, 0xDD, 0x00, 0x9C, 0x33, 0xD0, 0xB6, 0xE7, 0xCF, 0x1B, 0x65, 0xB2, - 0xE3, 0x9B, 0x66, 0x8D, 0x79, 0xCE, 0x18, 0x6A, 0xFE, 0xEF, 0xA7, 0x3C, 0x6B, 0xC4, 0xD9, 0xCA, - 0xE7, 0x31, 0x73, 0xA4, 0x53, 0x9F, 0x3F, 0xC9, 0xD9, 0x43, 0x4F, 0x8A, 0x3D, 0x37, 0xDB, 0xF1, - 0x14, 0xDA, 0x5E, 0xDA, 0x74, 0xCC, 0xDC, 0x72, 0x1D, 0xD7, 0xD3, 0x35, 0x1C, 0xC2, 0x71, 0xE6, - 0x89, 0xBE, 0xC1, 0x2E, 0xA4, 0xDC, 0x65, 0xD5, 0x1B, 0xDD, 0xF9, 0x5E, 0x2F, 0x9B, 0xB0, 0xE7, - 0xC6, 0x55, 0xA3, 0xC4, 0x26, 0x62, 0xFE, 0xB8, 0x4B, 0xDC, 0xC3, 0x3B, 0xC5, 0x00, 0xFD, 0xCA, - 0x00, 0x17, 0x55, 0x01, 0x7E, 0x96, 0x00, 0x36, 0x8A, 0x01, 0xCE, 0x4F, 0xF6, 0xD3, 0x14, 0x1E, - 0x6A, 0xBC, 0xBF, 0x31, 0x64, 0xCF, 0x88, 0xA9, 0xDE, 0xEA, 0xBB, 0x33, 0x55, 0x44, 0x9D, 0xF6, - 0xE6, 0x4E, 0x11, 0x40, 0xBF, 0x32, 0xC0, 0x45, 0x55, 0x00, 0x59, 0x44, 0xF1, 0xB8, 0xCC, 0x06, - 0x50, 0x45, 0x14, 0x53, 0x78, 0x98, 0xE5, 0xC9, 0x05, 0xA4, 0x14, 0x30, 0x97, 0x2E, 0x32, 0x54, - 0x8C, 0x58, 0x47, 0x22, 0xB4, 0x85, 0xC7, 0x9C, 0xE3, 0x80, 0x0E, 0x36, 0x3B, 0x9D, 0x22, 0xB8, - 0xAE, 0x04, 0xF7, 0x1C, 0xE1, 0x00, 0xAC, 0x6B, 0x6A, 0x96, 0xE4, 0x46, 0xE6, 0x6A, 0xAF, 0xA1, - 0x7A, 0xBF, 0x62, 0xF5, 0x8B, 0x6A, 0xD5, 0xE5, 0x4E, 0xE9, 0x15, 0x55, 0x4F, 0x69, 0xAD, 0xA9, - 0x7E, 0xDA, 0x7D, 0xC4, 0xDF, 0xBA, 0x9D, 0xF5, 0x75, 0x19, 0xB6, 0x93, 0x18, 0xE6, 0x87, 0x94, - 0x69, 0x12, 0x97, 0x3A, 0x7F, 0x18, 0xA6, 0x27, 0x60, 0x98, 0xF2, 0x20, 0xCE, 0x7F, 0x3D, 0xB9, - 0x3C, 0xDF, 0xFB, 0xE5, 0xD7, 0xD2, 0x3C, 0x21, 0x40, 0xFF, 0xED, 0xF9, 0x9B, 0x5F, 0x7F, 0x18, - 0xBF, 0xCA, 0xC6, 0x2F, 0x0B, 0x42, 0x1F, 0x67, 0xDD, 0xED, 0x92, 0xA4, 0x74, 0xC0, 0x5E, 0xA7, - 0x26, 0xE0, 0x46, 0xAF, 0x2E, 0xE0, 0x56, 0x23, 0xD3, 0x55, 0xFB, 0x61, 0xE1, 0xFF, 0x15, 0x2C, - 0xBC, 0x09, 0x3C, 0xB5, 0xC6, 0x96, 0xF4, 0xD6, 0x94, 0xBE, 0xAC, 0x1C, 0x38, 0xD3, 0xDE, 0xFA, - 0xE0, 0x4C, 0x87, 0x67, 0x00, 0xDF, 0xCA, 0xCC, 0xBD, 0x66, 0x70, 0xBD, 0x11, 0xC6, 0x38, 0xB9, - 0xA9, 0xEB, 0xF9, 0x27, 0x34, 0xC1, 0xB1, 0x25, 0x0D, 0xB2, 0x7D, 0xD9, 0xED, 0x74, 0x36, 0xCB, - 0xDA, 0x7B, 0x19, 0xEA, 0xF9, 0x46, 0x2D, 0xA8, 0xE7, 0x8D, 0xD4, 0xEA, 0xBD, 0x18, 0xEA, 0x45, - 0x2D, 0x5A, 0x2F, 0x34, 0x5A, 0x25, 0xC1, 0xB6, 0x6B, 0x11, 0xDB, 0xAE, 0xD3, 0xB0, 0x6E, 0xAF, - 0x0E, 0xAD, 0x6E, 0xAF, 0x0E, 0xAD, 0xDE, 0xBA, 0x32, 0x1D, 0x94, 0x95, 0xC7, 0x46, 0xE7, 0x79, - 0x4F, 0xB1, 0xB6, 0x25, 0xE9, 0x31, 0xB8, 0x6E, 0x23, 0x63, 0xAB, 0x66, 0x26, 0xB7, 0x20, 0x5E, - 0x92, 0xF3, 0xA1, 0xAA, 0xAA, 0x6F, 0xC1, 0x6C, 0x25, 0xC1, 0x65, 0xF8, 0xAF, 0xC5, 0x80, 0xAA, - 0xE6, 0x97, 0x87, 0x7B, 0x51, 0x13, 0x6E, 0xBB, 0x1E, 0x9C, 0xA6, 0x5C, 0x73, 0x9B, 0x8D, 0xB3, - 0x76, 0x86, 0xEA, 0xCE, 0x19, 0x7A, 0x57, 0x56, 0x33, 0xDA, 0x3A, 0xE9, 0x1A, 0xD0, 0x27, 0xFD, - 0x93, 0x8D, 0xAA, 0xD6, 0xFE, 0xD8, 0xBB, 0x43, 0x33, 0x7B, 0xE7, 0xD8, 0xE1, 0xCD, 0x1F, 0xDD, - 0xE2, 0x77, 0x6A, 0x99, 0xFC, 0xDE, 0x23, 0x9A, 0xFC, 0xDE, 0x63, 0x9A, 0xFC, 0xDE, 0x23, 0x9A, - 0xFC, 0xDE, 0x0F, 0x93, 0x3F, 0xB3, 0xC9, 0xEF, 0x3D, 0xB6, 0xC9, 0xEF, 0xD5, 0x34, 0xF9, 0xBD, - 0x9A, 0x26, 0xBF, 0x57, 0xD3, 0xE4, 0xF7, 0x1E, 0xC9, 0xE4, 0x77, 0x36, 0xFF, 0x73, 0xAB, 0x8C, - 0x5C, 0xCB, 0xCF, 0x18, 0x65, 0x80, 0x85, 0xD5, 0x56, 0x1A, 0xFB, 0x2F, 0x33, 0xD3, 0x4C, 0x03, - 0xF6, 0xC6, 0x61, 0x72, 0x89, 0x26, 0x48, 0xDF, 0x2E, 0xE1, 0x8F, 0xD5, 0x25, 0x12, 0xA0, 0xF8, - 0xF7, 0x4E, 0xBA, 0xCE, 0x27, 0xAD, 0xCE, 0x27, 0x43, 0x9D, 0xDF, 0xB4, 0x3A, 0xBF, 0xED, 0xC8, - 0xBB, 0x78, 0xC0, 0xCD, 0x3B, 0xEA, 0xD9, 0x34, 0x74, 0x06, 0xB9, 0x1C, 0xA5, 0xEF, 0xBB, 0x0C, - 0x05, 0x18, 0x94, 0x14, 0xDF, 0x67, 0x89, 0x2B, 0x7B, 0xAE, 0x56, 0xF9, 0xFD, 0xDE, 0xE1, 0xDE, - 0xD9, 0xBE, 0xA1, 0xEA, 0xDE, 0x28, 0x14, 0xBD, 0xAE, 0x26, 0x85, 0x19, 0x5B, 0xFE, 0x57, 0x25, - 0x23, 0x4C, 0xB7, 0x20, 0xED, 0x4B, 0x01, 0x78, 0xCF, 0x04, 0xCE, 0xAF, 0x7E, 0x0B, 0xFA, 0x96, - 0xFD, 0x1F, 0xD3, 0x20, 0x04, 0x46, 0xF5, 0x50, 0x20, 0x76, 0x5A, 0x7B, 0x4A, 0xEF, 0x8E, 0xBD, - 0xE4, 0x86, 0x50, 0x2A, 0x83, 0x4A, 0x52, 0xC7, 0x10, 0x18, 0x45, 0xBF, 0x39, 0xA1, 0x96, 0x0E, - 0xE1, 0xC6, 0xB1, 0x59, 0xBA, 0x42, 0xC7, 0x3D, 0x63, 0x69, 0x68, 0x78, 0x23, 0x30, 0x76, 0x0D, - 0x73, 0xAD, 0x81, 0x97, 0x72, 0xE4, 0x9E, 0xF9, 0x1E, 0xDE, 0xDE, 0x8F, 0x93, 0x44, 0xE8, 0x34, - 0x11, 0xEB, 0x9E, 0x6B, 0xCB, 0xD1, 0x58, 0x58, 0x8D, 0xFB, 0x38, 0x3C, 0x19, 0x27, 0x08, 0x3A, - 0xF9, 0x63, 0x29, 0x61, 0x83, 0xE5, 0x89, 0xEC, 0x98, 0xC2, 0xB7, 0xF6, 0xBD, 0xF1, 0x64, 0x44, - 0xC3, 0x24, 0x71, 0x12, 0x8B, 0x51, 0x8B, 0x30, 0xC8, 0xB8, 0x05, 0x39, 0x73, 0x43, 0xF8, 0xD7, - 0x74, 0x43, 0xB4, 0x46, 0x46, 0xD4, 0x1A, 0xD1, 0xCD, 0xAE, 0x7D, 0x6B, 0x84, 0x69, 0x55, 0xEF, - 0x6E, 0x28, 0xBF, 0xDC, 0x75, 0xD8, 0x3F, 0x5B, 0xEF, 0x91, 0x1B, 0x2B, 0xC0, 0xBB, 0x52, 0xD7, - 0x8E, 0x3F, 0x86, 0x42, 0x1F, 0xF4, 0xDB, 0x99, 0x84, 0xC4, 0xBB, 0xE6, 0x91, 0xD2, 0xB8, 0xE8, - 0x4F, 0x84, 0x43, 0xAE, 0x7D, 0x6F, 0x4C, 0xF6, 0xCE, 0x38, 0xC0, 0x90, 0x4C, 0x80, 0x2B, 0x29, - 0x52, 0x8F, 0x63, 0xC1, 0x5C, 0x0A, 0xE7, 0x1C, 0x8D, 0x74, 0x48, 0x7F, 0x00, 0x9C, 0xF8, 0x63, - 0xC7, 0xA5, 0x40, 0xDF, 0x19, 0xDC, 0x90, 0x44, 0x03, 0x30, 0xEB, 0x27, 0xB2, 0xE3, 0xF9, 0xCE, - 0x10, 0xC6, 0xCE, 0x88, 0x11, 0x8E, 0x3D, 0xC3, 0x28, 0x3B, 0x43, 0x24, 0xF4, 0x3F, 0xED, 0x12, - 0x77, 0x3A, 0x1A, 0x2D, 0xEB, 0xD1, 0x85, 0x91, 0x14, 0xB5, 0xFA, 0x65, 0x92, 0x36, 0xF0, 0x6F, - 0x2F, 0xC9, 0xDE, 0x68, 0x44, 0xFA, 0xF0, 0xDD, 0xCE, 0x4F, 0xDD, 0xE7, 0xB9, 0x81, 0x37, 0xA2, - 0xED, 0x11, 0x68, 0x6C, 0xE3, 0x23, 0xBF, 0x91, 0x4A, 0xE0, 0x3F, 0x90, 0x13, 0x08, 0x2D, 0x2D, - 0x03, 0x73, 0x12, 0x8F, 0xEB, 0x38, 0x29, 0xE3, 0xC8, 0xB3, 0xEC, 0x5F, 0x2C, 0x27, 0x54, 0x2E, - 0xA2, 0x63, 0x26, 0x10, 0xF1, 0x12, 0x40, 0x30, 0xBD, 0x1A, 0x3B, 0x61, 0x94, 0x04, 0x11, 0x33, - 0x86, 0xC0, 0x60, 0xC3, 0xF2, 0xE0, 0x73, 0xE7, 0x4B, 0x12, 0xD7, 0x8E, 0x53, 0x96, 0x88, 0x6D, - 0x77, 0xE9, 0x1D, 0xC1, 0x5B, 0x80, 0x72, 0x52, 0x8B, 0xA8, 0xB8, 0x6D, 0x4D, 0x26, 0x7C, 0x50, - 0xA5, 0xD1, 0xB6, 0x18, 0xD9, 0xE5, 0x04, 0xA7, 0xF5, 0x1F, 0xD6, 0x37, 0x81, 0xEF, 0xD7, 0x93, - 0xE3, 0xF7, 0x21, 0xA6, 0x1C, 0xFB, 0xC7, 0x94, 0x06, 0x61, 0x84, 0x15, 0x2B, 0xB4, 0x3D, 0x40, - 0xB8, 0xD4, 0x38, 0xFB, 0xD0, 0xBF, 0xC0, 0x1C, 0x26, 0x6B, 0x53, 0xD6, 0xA2, 0x08, 0x71, 0x43, - 0xAE, 0xC9, 0x86, 0x56, 0xC4, 0x49, 0x34, 0xF2, 0xB8, 0x19, 0x93, 0xA5, 0x61, 0x88, 0xB5, 0x7C, - 0x75, 0xE5, 0xBF, 0xE6, 0x85, 0x0E, 0xDE, 0xE1, 0x9B, 0x28, 0x09, 0xA4, 0x1A, 0x3B, 0x39, 0xA2, - 0xED, 0x87, 0x56, 0x38, 0x0D, 0x30, 0xBC, 0x59, 0x35, 0xC8, 0xF9, 0x04, 0xA1, 0x7A, 0x1E, 0xD2, - 0xD4, 0x40, 0xE6, 0xC3, 0xCE, 0x5C, 0xA9, 0x91, 0x39, 0x98, 0x15, 0x02, 0x9E, 0x3F, 0xA4, 0xE1, - 0x99, 0xE5, 0xF8, 0x30, 0x23, 0xA2, 0x71, 0x55, 0x67, 0x90, 0xAB, 0xD0, 0x7D, 0xCB, 0x6A, 0xF0, - 0x32, 0x83, 0x88, 0x50, 0x7B, 0x59, 0x5E, 0x9F, 0x80, 0xE1, 0xF2, 0xC2, 0x90, 0xBA, 0x6D, 0x29, - 0x27, 0xC1, 0x84, 0x52, 0xFF, 0x64, 0x6F, 0x3F, 0xD0, 0xE1, 0x4E, 0x3D, 0x97, 0x66, 0x45, 0xA6, - 0x32, 0x8A, 0x87, 0xC1, 0xE4, 0xD4, 0xBB, 0x3B, 0x03, 0xF0, 0xC0, 0x60, 0x7E, 0x81, 0x31, 0x66, - 0x24, 0xF5, 0x9C, 0x70, 0xC3, 0xC8, 0x44, 0x89, 0x02, 0x03, 0xC7, 0x0C, 0x8E, 0x85, 0xEA, 0x88, - 0xE4, 0x5D, 0x59, 0x11, 0xB2, 0x32, 0x9E, 0x84, 0x85, 0x38, 0x5C, 0xC1, 0xB2, 0xED, 0xC3, 0x5B, - 0xF8, 0x05, 0xC3, 0x94, 0x29, 0xE0, 0x5F, 0x6A, 0x1C, 0x7C, 0x38, 0x01, 0x5B, 0x1C, 0xE2, 0x37, - 0xE8, 0x08, 0x8A, 0xE9, 0xF1, 0x96, 0x28, 0x56, 0x59, 0x26, 0xBB, 0xAF, 0x81, 0xC1, 0x58, 0xC3, - 0x85, 0xC0, 0x4A, 0xC4, 0x3E, 0xA4, 0x93, 0x8C, 0x29, 0x11, 0x0F, 0xEC, 0x2E, 0x3D, 0x3A, 0xF5, - 0xEC, 0xD6, 0x1E, 0xFC, 0xC2, 0x31, 0xC7, 0x11, 0x0F, 0x0E, 0x86, 0x41, 0x58, 0xDF, 0xE0, 0x17, - 0x35, 0xF4, 0x81, 0x57, 0xFB, 0xEC, 0x7C, 0x69, 0x7B, 0xEE, 0x60, 0xE4, 0x0C, 0x30, 0xCD, 0x47, - 0x2C, 0xDB, 0xA5, 0xD4, 0x9B, 0xCD, 0x6A, 0xFA, 0xBD, 0x8C, 0x97, 0x58, 0xB9, 0x8B, 0x65, 0x05, - 0x53, 0x9F, 0x05, 0x4D, 0xA3, 0x23, 0xFC, 0xFE, 0x77, 0x10, 0x7E, 0x5A, 0x4E, 0x1C, 0x1F, 0x0E, - 0x7C, 0x23, 0x49, 0x03, 0xA2, 0x3E, 0x1D, 0xA8, 0xDB, 0x26, 0x64, 0x2D, 0x93, 0x9E, 0x14, 0x8C, - 0xFD, 0x20, 0x8F, 0x76, 0x23, 0xCA, 0x79, 0x30, 0x97, 0x50, 0xCD, 0xE3, 0x4D, 0x6A, 0x82, 0x81, - 0x39, 0xC3, 0xC3, 0xF0, 0x95, 0x59, 0xAB, 0xF7, 0xC8, 0x7C, 0x62, 0x47, 0x02, 0x51, 0xDF, 0xFC, - 0xD2, 0x2F, 0xB7, 0x23, 0xCC, 0xF3, 0xCB, 0x7C, 0x92, 0xD7, 0xD4, 0xA2, 0xB7, 0x08, 0x31, 0x8F, - 0xE6, 0x44, 0x88, 0x4A, 0xB5, 0x25, 0x83, 0xCF, 0xA4, 0x21, 0xD9, 0x8D, 0x35, 0xB4, 0x25, 0xFF, - 0xC5, 0xF3, 0xDA, 0x2D, 0x9B, 0xE9, 0x21, 0x75, 0xDE, 0x4E, 0x5C, 0x17, 0xE4, 0x35, 0x73, 0x18, - 0x2F, 0x11, 0xEA, 0x37, 0xF3, 0x1D, 0xCB, 0xE8, 0x34, 0xEF, 0x56, 0xBE, 0xD3, 0xF3, 0x44, 0x99, - 0x1A, 0xC9, 0x1B, 0x91, 0xDD, 0x48, 0x2E, 0x84, 0x74, 0x23, 0x95, 0x4A, 0x59, 0x3B, 0x7D, 0xA9, - 0xF5, 0x75, 0x8D, 0x2D, 0x3D, 0xE5, 0x99, 0x20, 0x63, 0x1E, 0x77, 0xE9, 0x48, 0xF4, 0x45, 0x7B, - 0x13, 0x4F, 0x37, 0xF7, 0xC0, 0xB9, 0x85, 0xA9, 0x18, 0xFD, 0xB6, 0xE3, 0xEE, 0xDA, 0x71, 0x4F, - 0x41, 0xF6, 0xA0, 0x5E, 0x44, 0x2A, 0xDC, 0x1E, 0xB8, 0x4D, 0xDF, 0x76, 0x2D, 0xCD, 0xCF, 0x76, - 0x7B, 0x6B, 0x8E, 0xFC, 0xA4, 0xF7, 0x8B, 0xAA, 0x30, 0xD3, 0xED, 0x6E, 0xCD, 0x55, 0x3A, 0x7A, - 0x6A, 0xE1, 0x2A, 0xBC, 0x6C, 0xE0, 0xBE, 0x45, 0x0D, 0x56, 0xEA, 0x51, 0x53, 0x36, 0x57, 0x54, - 0xCC, 0x86, 0x31, 0x6A, 0x7A, 0xE7, 0xBC, 0xF6, 0xD0, 0xAC, 0xF8, 0x68, 0x7A, 0x32, 0xE2, 0x0C, - 0x97, 0x83, 0x33, 0xAF, 0x2F, 0x9B, 0x46, 0x74, 0x09, 0xF8, 0xAC, 0x56, 0xC7, 0xAF, 0xD3, 0xCC, - 0xA3, 0xD5, 0x65, 0x9E, 0xBA, 0xD1, 0x5A, 0xCD, 0x41, 0xEA, 0xB7, 0x3A, 0x1F, 0xDE, 0xD0, 0x6A, - 0xED, 0xBA, 0xD8, 0xEC, 0x2D, 0x4F, 0x23, 0x2C, 0x68, 0xBD, 0xE1, 0x62, 0x1A, 0x00, 0x89, 0x24, - 0xF1, 0x5A, 0x14, 0x6C, 0xA1, 0x28, 0x0A, 0x91, 0xA9, 0x1B, 0x77, 0x06, 0xB1, 0xE0, 0x32, 0x0E, - 0x73, 0xA2, 0x62, 0xD6, 0x5F, 0x97, 0x8E, 0x66, 0x11, 0x48, 0x1A, 0x55, 0x9C, 0xD5, 0xA4, 0x63, - 0xD6, 0x81, 0x08, 0xE2, 0x8D, 0x35, 0xB5, 0x0F, 0x7C, 0x6F, 0x62, 0x63, 0x66, 0x28, 0xE3, 0xD4, - 0xAB, 0x3C, 0x98, 0x56, 0xA8, 0x2F, 0x25, 0x38, 0xEA, 0x9A, 0x67, 0xC7, 0x32, 0x1C, 0x09, 0x67, - 0xA1, 0x12, 0x47, 0x75, 0x69, 0x55, 0x68, 0xBD, 0x41, 0xDB, 0xB3, 0x9F, 0x30, 0x9C, 0x51, 0xEB, - 0x0B, 0xDF, 0x46, 0x34, 0xF7, 0xF7, 0x04, 0xCC, 0x14, 0x7F, 0x1C, 0xB7, 0x96, 0xC0, 0x8A, 0xC1, - 0x15, 0x19, 0x4C, 0x03, 0x7A, 0xEC, 0x0D, 0xAC, 0x91, 0xF3, 0x3B, 0xB5, 0x0F, 0xA0, 0x9D, 0xBE, - 0x73, 0x35, 0xE5, 0x69, 0x24, 0xEB, 0x37, 0x3F, 0x07, 0x67, 0x6E, 0xCB, 0x47, 0x26, 0xA0, 0x0B, - 0x58, 0x01, 0x1E, 0xC3, 0x9A, 0x76, 0x64, 0xEA, 0xFD, 0x12, 0xF2, 0xA8, 0x8B, 0xD4, 0xA0, 0x29, - 0xFA, 0x4B, 0x8A, 0x33, 0xEA, 0x47, 0x85, 0x87, 0x19, 0x73, 0x47, 0xD4, 0x01, 0x0D, 0x2D, 0x67, - 0x14, 0x54, 0x94, 0x4B, 0x15, 0x44, 0x39, 0xB2, 0x78, 0x6F, 0xF9, 0x36, 0x6E, 0x05, 0x71, 0x41, - 0xC4, 0x2F, 0xCC, 0xCC, 0x49, 0x34, 0x19, 0xD8, 0x2B, 0x49, 0x4A, 0x86, 0x9D, 0x4D, 0x54, 0xA5, - 0x30, 0x99, 0x64, 0xC5, 0x36, 0x96, 0xE6, 0x20, 0x95, 0x08, 0x4F, 0xA9, 0xF6, 0xB3, 0x1D, 0x97, - 0x7A, 0x0D, 0xCE, 0x07, 0x35, 0x79, 0x0C, 0xD2, 0x96, 0xDD, 0x1C, 0xDC, 0x05, 0x15, 0x5B, 0x86, - 0xCD, 0x30, 0xEC, 0x16, 0xCE, 0xE6, 0x23, 0xE4, 0x22, 0x2B, 0xF4, 0x11, 0x94, 0x87, 0xD7, 0x66, - 0x14, 0x40, 0xF1, 0xF3, 0x6D, 0xB2, 0xD1, 0xF4, 0xAD, 0x7A, 0xBD, 0x9C, 0x0B, 0x69, 0x6C, 0x5B, - 0xED, 0xD1, 0x8D, 0xAC, 0xBE, 0x07, 0xA2, 0xEA, 0xE0, 0x89, 0x36, 0xF6, 0xB2, 0x69, 0x9D, 0x1F, - 0x9D, 0x1E, 0xFE, 0x3A, 0x0F, 0x79, 0x2A, 0xD8, 0xCA, 0x99, 0x8F, 0x14, 0x64, 0x4D, 0xE3, 0x51, - 0x1E, 0x8F, 0x41, 0x0E, 0xCA, 0xB3, 0x5D, 0x33, 0x4A, 0xA1, 0xEC, 0x13, 0x60, 0xBA, 0x0C, 0x12, - 0xB8, 0x59, 0x24, 0x50, 0x02, 0x8B, 0xA9, 0xFD, 0xA6, 0x77, 0xBD, 0x66, 0x95, 0x43, 0xC5, 0xB7, - 0xC2, 0x52, 0xF2, 0x00, 0xF8, 0xB1, 0x15, 0x3A, 0x03, 0x15, 0xC9, 0x4C, 0xC2, 0xA9, 0x88, 0x32, - 0x43, 0x52, 0xD1, 0x4B, 0x60, 0x73, 0x10, 0x50, 0x89, 0x47, 0xC5, 0x32, 0xE5, 0xC2, 0x60, 0xE7, - 0x22, 0x8E, 0x7C, 0x4C, 0xE9, 0xAD, 0xC4, 0xBD, 0x51, 0xE8, 0x84, 0x53, 0xBB, 0x96, 0x92, 0x28, - 0x47, 0xF7, 0x29, 0xF4, 0xFA, 0x83, 0x8C, 0x8B, 0x22, 0x90, 0xDA, 0xB4, 0x99, 0x33, 0x19, 0x35, - 0x90, 0x62, 0x8E, 0xC8, 0xE3, 0xFB, 0xB0, 0xF7, 0xFC, 0x3E, 0xEC, 0x3D, 0x79, 0x45, 0xDC, 0xE9, - 0x78, 0x3F, 0xF5, 0xAE, 0x26, 0x14, 0xA5, 0x6F, 0xC5, 0x82, 0x5B, 0x1E, 0x7A, 0xAE, 0xB8, 0x14, - 0xCB, 0x9E, 0xDA, 0xC0, 0xAC, 0x2A, 0x6F, 0xD8, 0x57, 0x7C, 0x0E, 0xE1, 0x5E, 0x09, 0xAC, 0x49, - 0x6A, 0x1B, 0x9B, 0x80, 0xC7, 0x4B, 0x99, 0x2D, 0x88, 0x32, 0xBE, 0x24, 0xF8, 0xF7, 0xB1, 0xFE, - 0xD2, 0xBD, 0xAC, 0x5E, 0xD2, 0xAB, 0x06, 0xCB, 0x72, 0x10, 0x47, 0xC6, 0x34, 0x26, 0xA5, 0x44, - 0xAA, 0x16, 0x55, 0x55, 0xF0, 0x2C, 0x66, 0x89, 0x99, 0x49, 0xF0, 0x70, 0xC2, 0xB0, 0xCF, 0x32, - 0x35, 0x15, 0x20, 0x32, 0x86, 0x08, 0xCC, 0x8D, 0xFD, 0x39, 0x30, 0x6E, 0x62, 0x59, 0x89, 0xA5, - 0xCA, 0x4B, 0xDB, 0x93, 0x93, 0x50, 0x28, 0x43, 0x87, 0xB5, 0x9B, 0xDD, 0xF5, 0xB5, 0x3F, 0xC9, - 0x25, 0x9A, 0x9D, 0x85, 0xE8, 0x9E, 0xA5, 0x9B, 0xFB, 0x66, 0xDA, 0x5D, 0x2E, 0x33, 0x78, 0xBE, - 0xED, 0x98, 0xB6, 0x89, 0xE5, 0x41, 0x84, 0x59, 0x8D, 0xC5, 0x41, 0x32, 0xCB, 0x28, 0xAC, 0xB1, - 0x82, 0x95, 0x90, 0x8B, 0x82, 0x5D, 0x63, 0x35, 0x9D, 0x95, 0x61, 0x8C, 0xE1, 0x37, 0xFE, 0x77, - 0x12, 0x2F, 0x43, 0x8E, 0xDC, 0x81, 0xCF, 0xA2, 0x1C, 0x26, 0x22, 0xCF, 0x13, 0x59, 0x25, 0xC1, - 0x9D, 0x35, 0xE1, 0x6F, 0x22, 0xB3, 0x03, 0x6A, 0x98, 0x7F, 0x12, 0x9E, 0x48, 0xC0, 0x78, 0xE2, - 0x69, 0x2F, 0xB0, 0x8E, 0x8B, 0x29, 0x99, 0x6F, 0xC0, 0x2E, 0xD3, 0x20, 0x79, 0x29, 0x32, 0x21, - 0x45, 0x5E, 0xAB, 0x3B, 0x6B, 0xEC, 0x12, 0xBE, 0xF5, 0x95, 0x9E, 0xD0, 0xF7, 0x08, 0xE3, 0xEF, - 0x18, 0x4A, 0x58, 0x12, 0xBA, 0x9D, 0x74, 0xEF, 0x56, 0xD6, 0x8B, 0x32, 0xBD, 0xFB, 0x8D, 0xF5, - 0x6E, 0x5A, 0x36, 0xF2, 0x3F, 0x99, 0xE1, 0x24, 0x23, 0x95, 0xF9, 0x64, 0xA0, 0x1C, 0x3D, 0x59, - 0x42, 0xAB, 0xA4, 0xBB, 0x9C, 0x4D, 0x95, 0x09, 0x23, 0x8F, 0xE8, 0xC3, 0x1C, 0x05, 0xC5, 0x4C, - 0xA6, 0xDC, 0x5A, 0x13, 0x5F, 0x05, 0xAD, 0x5B, 0xC5, 0x4B, 0x34, 0xB2, 0x6A, 0x15, 0x08, 0x4B, - 0xA2, 0xC9, 0xDA, 0x6A, 0x22, 0x09, 0xD8, 0x4E, 0xBD, 0x90, 0xBE, 0x24, 0x8D, 0x02, 0xE2, 0x2B, - 0x40, 0xBC, 0x41, 0x3C, 0x77, 0x74, 0x4F, 0xEE, 0x3C, 0xFF, 0x6B, 0x10, 0x31, 0x0B, 0x7F, 0x3B, - 0xD7, 0x26, 0xB4, 0x39, 0xF8, 0xD8, 0xD3, 0x1E, 0x8E, 0x1B, 0xB6, 0xD8, 0x8B, 0xE1, 0x01, 0xCB, - 0x9A, 0xDC, 0x26, 0x1F, 0x71, 0xAC, 0x58, 0x3E, 0x3E, 0x2E, 0x15, 0xE2, 0x58, 0xA1, 0x94, 0x58, - 0x57, 0xDE, 0x2D, 0xAD, 0x2A, 0xA6, 0x95, 0x48, 0x4C, 0x07, 0x34, 0x57, 0x4C, 0x0F, 0x4A, 0xA6, - 0x0D, 0x72, 0x74, 0x4D, 0xAC, 0x11, 0xD4, 0xB7, 0xEF, 0xD9, 0xE8, 0x13, 0x03, 0x2F, 0x1E, 0xBD, - 0x2D, 0x26, 0x49, 0xE2, 0x84, 0x64, 0x04, 0xB2, 0x14, 0x23, 0x52, 0xB3, 0xE4, 0x2C, 0x88, 0x64, - 0x6F, 0xFC, 0x9E, 0x83, 0x3E, 0xEE, 0x38, 0x43, 0x5B, 0x80, 0xCD, 0xE8, 0x10, 0x27, 0x20, 0xEF, - 0x25, 0xAB, 0xA1, 0xA0, 0x8A, 0x99, 0x4B, 0xEB, 0x3D, 0xFE, 0xBB, 0x82, 0xF6, 0x7F, 0x7D, 0x9C, - 0xE1, 0x80, 0x4F, 0x08, 0xC4, 0xDC, 0x2C, 0x78, 0x30, 0x64, 0x9C, 0x29, 0x16, 0x26, 0xC8, 0x33, - 0xB6, 0x09, 0xAD, 0x0A, 0x23, 0x7C, 0x9C, 0xE8, 0x41, 0xB6, 0x72, 0x55, 0x4D, 0xAD, 0x87, 0x6E, - 0xDF, 0xFE, 0xE1, 0xDB, 0x78, 0xEA, 0x96, 0x9F, 0xFF, 0x8A, 0xAF, 0x7C, 0xB8, 0x30, 0xE9, 0x60, - 0x3C, 0x13, 0xD6, 0x8C, 0x4F, 0x3F, 0x7D, 0x3A, 0x86, 0xC1, 0xF2, 0xC6, 0xB2, 0xF7, 0xF1, 0xC9, - 0xD0, 0xA5, 0x74, 0x9D, 0xC8, 0xA3, 0x35, 0xBE, 0x46, 0x2A, 0xD5, 0x16, 0x6F, 0x91, 0xA6, 0x1E, - 0x85, 0xDE, 0xD8, 0x66, 0xAF, 0x91, 0x5A, 0x30, 0x6F, 0xA9, 0x4F, 0x92, 0x96, 0x7A, 0x9B, 0x5D, - 0x0A, 0xEA, 0x6E, 0x91, 0xD5, 0xE7, 0xD1, 0x9B, 0xAA, 0xCF, 0x53, 0x8F, 0xAB, 0x46, 0x65, 0x48, - 0x52, 0xFC, 0x5A, 0x9F, 0xD8, 0xA7, 0xC7, 0x24, 0xF6, 0xDB, 0x3C, 0x89, 0x65, 0x3C, 0x00, 0xA7, - 0x4C, 0xF9, 0xD1, 0x0B, 0x4A, 0xD8, 0x73, 0xC4, 0x1A, 0x5A, 0xF8, 0x02, 0x1F, 0x7F, 0xD6, 0xC1, - 0x91, 0x14, 0x93, 0x3F, 0x13, 0x63, 0xD3, 0x6F, 0xEA, 0x5D, 0x17, 0x36, 0x88, 0x77, 0x44, 0xC9, - 0x2B, 0x0C, 0x1C, 0xF6, 0x7C, 0x3B, 0x60, 0xEA, 0x12, 0x05, 0xBD, 0xAD, 0xAC, 0xB0, 0x52, 0x7D, - 0x74, 0x22, 0x42, 0x30, 0xD4, 0x61, 0xC0, 0xB4, 0x2E, 0x06, 0xFB, 0xCC, 0x2A, 0x7F, 0x89, 0x92, - 0x32, 0x13, 0x3D, 0x17, 0x6C, 0xE4, 0x55, 0x2B, 0xBA, 0x26, 0x9D, 0xCA, 0x31, 0x94, 0x98, 0x79, - 0xD9, 0x30, 0x54, 0xD3, 0x64, 0x70, 0x78, 0xA6, 0x87, 0xC1, 0x0A, 0x69, 0xB2, 0xC4, 0xA8, 0x89, - 0xB6, 0x65, 0x15, 0x7C, 0xCA, 0x2A, 0xF8, 0x4D, 0x4F, 0xBA, 0x5B, 0xD1, 0x38, 0xF2, 0xD7, 0x52, - 0x98, 0xB8, 0x77, 0x0D, 0x52, 0x5D, 0x7E, 0x96, 0xD1, 0xAE, 0xF6, 0x64, 0x1A, 0xDC, 0x2C, 0x2D, - 0xB4, 0x4D, 0xCB, 0x86, 0x84, 0x9F, 0x48, 0x08, 0xD7, 0x98, 0xBA, 0x21, 0xB2, 0x29, 0xC6, 0xBE, - 0xC6, 0xB6, 0x28, 0x8E, 0xB8, 0x04, 0x44, 0x22, 0xB0, 0x19, 0x23, 0x73, 0xA1, 0xA6, 0x74, 0x67, - 0x42, 0xEE, 0xD1, 0xE4, 0x6E, 0x20, 0x42, 0xBC, 0x66, 0x49, 0xA5, 0xD5, 0x99, 0xD2, 0xA4, 0x42, - 0x50, 0xD7, 0xAC, 0x40, 0x08, 0x80, 0xB2, 0x11, 0xAB, 0x81, 0x48, 0x57, 0xA4, 0x00, 0x25, 0x3E, - 0x4D, 0xB2, 0xE8, 0xED, 0xA5, 0xC6, 0x01, 0xE3, 0x9E, 0xE0, 0x21, 0x19, 0x6B, 0x0D, 0x2E, 0x17, - 0x62, 0xF0, 0x15, 0xD2, 0xF8, 0x6B, 0x63, 0x39, 0x6B, 0xEB, 0x47, 0xEE, 0x12, 0xE4, 0x64, 0x40, - 0xB1, 0x05, 0x60, 0x13, 0x33, 0xD6, 0x8E, 0xF9, 0x62, 0xC4, 0x40, 0x62, 0xC5, 0xA0, 0x7F, 0x47, - 0x19, 0x66, 0xDE, 0xAD, 0xE1, 0xD2, 0xEC, 0x7E, 0xC9, 0xA8, 0xFA, 0x29, 0x55, 0xB5, 0x97, 0x55, - 0xF5, 0xB7, 0x54, 0xD5, 0x75, 0xAD, 0xAA, 0x79, 0xF4, 0x4B, 0x1D, 0x6A, 0x7A, 0xBF, 0x4F, 0xE6, - 0xBA, 0xA0, 0xC6, 0xA7, 0xC2, 0x1A, 0xBF, 0x65, 0xD5, 0x50, 0x59, 0x53, 0x5E, 0xAA, 0x8B, 0x1F, - 0xD5, 0x91, 0x04, 0x0D, 0x5E, 0xAC, 0x6F, 0x81, 0x5F, 0xC8, 0x15, 0x80, 0x58, 0xAE, 0x4D, 0xC6, - 0x9E, 0xEB, 0x05, 0x13, 0x0B, 0x56, 0x71, 0x2C, 0x46, 0x9A, 0x99, 0x61, 0x6D, 0xA5, 0x9E, 0x28, - 0x8A, 0x14, 0x68, 0x9D, 0xA9, 0x06, 0x22, 0x9F, 0x77, 0x32, 0xF5, 0xA3, 0x32, 0xA4, 0x8D, 0x4A, - 0x6A, 0x66, 0xE0, 0xFB, 0x09, 0x59, 0x68, 0x93, 0xE6, 0xCB, 0x4D, 0xC6, 0xFB, 0x4A, 0x7A, 0x68, - 0xB9, 0xF4, 0xDA, 0x0E, 0x66, 0x66, 0xF4, 0x7C, 0x6A, 0x37, 0xF2, 0x9E, 0xE2, 0x64, 0x3B, 0x21, - 0x33, 0x93, 0x15, 0xA5, 0x2F, 0xC9, 0xAF, 0x6B, 0x9F, 0xD6, 0x7E, 0x6B, 0xA8, 0xF9, 0xCF, 0x0D, - 0xAD, 0x7F, 0x45, 0x36, 0x97, 0x53, 0xC7, 0x5E, 0x99, 0x32, 0x0D, 0x9C, 0xDF, 0x29, 0x31, 0x99, - 0x66, 0xC5, 0x3A, 0xC6, 0x3E, 0x6E, 0x32, 0x75, 0x56, 0x9D, 0x2B, 0x71, 0x80, 0x7A, 0x13, 0xD6, - 0xF7, 0x52, 0x80, 0x3A, 0x7A, 0xAB, 0xA0, 0x06, 0x22, 0x21, 0x76, 0x93, 0x57, 0x90, 0x87, 0x29, - 0xFF, 0xC2, 0xF6, 0x2E, 0x8C, 0x13, 0x6C, 0xAA, 0x66, 0x34, 0x86, 0x58, 0xB1, 0x3A, 0xDA, 0x32, - 0x85, 0x80, 0xD9, 0xC0, 0x39, 0xB8, 0x3A, 0x29, 0xFC, 0x79, 0xA9, 0xF1, 0xBF, 0xCC, 0x40, 0x82, - 0x1A, 0xC0, 0x52, 0x6B, 0x70, 0xB3, 0x64, 0xDE, 0x85, 0x94, 0x6D, 0xD2, 0x9F, 0x97, 0xC2, 0x1B, - 0x27, 0xE0, 0x9B, 0x30, 0x4B, 0xCB, 0xB9, 0x56, 0xDD, 0x55, 0xAD, 0x7A, 0x3B, 0x98, 0x5E, 0xF1, - 0x55, 0xE1, 0x12, 0xF8, 0x4F, 0xDD, 0x4D, 0xE5, 0x75, 0x74, 0x09, 0x69, 0x0C, 0x0A, 0x13, 0x1E, - 0x4F, 0x88, 0x1E, 0x59, 0xB2, 0x78, 0x0A, 0x8C, 0xEC, 0x95, 0xF6, 0x61, 0xFD, 0x0B, 0x47, 0x91, - 0x6C, 0xF6, 0x6A, 0x4E, 0x78, 0x74, 0x23, 0xB0, 0x9C, 0x23, 0x1E, 0xD5, 0x2E, 0x72, 0xC6, 0xD5, - 0x7A, 0x65, 0x1C, 0xF2, 0x08, 0x62, 0x5E, 0x4E, 0x79, 0xF2, 0x3C, 0x56, 0xAE, 0x3B, 0x1B, 0x1F, - 0x38, 0x80, 0x47, 0xDB, 0xED, 0x76, 0xD6, 0x37, 0x5A, 0xE4, 0xC5, 0x0B, 0x85, 0x3A, 0xFF, 0x8C, - 0x2C, 0x60, 0x41, 0x65, 0xA7, 0x59, 0x3F, 0x77, 0x40, 0x3A, 0x9B, 0xD8, 0xD7, 0x0A, 0x89, 0x4D, - 0xF6, 0x60, 0xDE, 0x66, 0x5D, 0xEC, 0xDA, 0xA1, 0x03, 0xD0, 0xE8, 0x75, 0x3A, 0xED, 0x0E, 0xBB, - 0xE0, 0xD7, 0x56, 0x3C, 0x73, 0xF6, 0x01, 0x89, 0xB1, 0x5F, 0x9E, 0x9C, 0x57, 0x1E, 0xEB, 0x4D, - 0x75, 0xCF, 0x3C, 0x02, 0xAD, 0xEA, 0x9D, 0xC7, 0x8A, 0x57, 0xCD, 0x43, 0xD7, 0xC8, 0x49, 0x5E, - 0xBA, 0x36, 0x46, 0x14, 0x1F, 0x55, 0x5C, 0xAD, 0x35, 0x16, 0x89, 0x9B, 0xB4, 0xA6, 0xB2, 0x48, - 0x4B, 0xB5, 0x32, 0x4D, 0xB7, 0xCC, 0xA5, 0xAA, 0x6E, 0x2C, 0xC0, 0xE7, 0xD7, 0xFA, 0xCC, 0xE8, - 0xF7, 0xC7, 0x75, 0x14, 0xDF, 0xFF, 0x0F, 0x20, 0x29, 0xD3, 0x4A, 0x22, 0x62, 0x3B, 0x7B, 0x35, - 0x91, 0x32, 0xAA, 0x45, 0xCE, 0xB0, 0xAE, 0x84, 0x95, 0x1D, 0xE2, 0x58, 0x1D, 0x9F, 0xCE, 0xC2, - 0x22, 0xEE, 0xDD, 0xF2, 0x8B, 0x8B, 0x3C, 0xC9, 0x4A, 0x27, 0x97, 0xF2, 0x32, 0xED, 0xC6, 0xA2, - 0x27, 0x34, 0xBC, 0xF1, 0xEC, 0xCC, 0xBB, 0x71, 0xCA, 0xC5, 0xB8, 0xE4, 0x4A, 0xF8, 0xCB, 0xE8, - 0x06, 0x78, 0xEA, 0xE5, 0x25, 0x40, 0x99, 0xC8, 0x5F, 0xC2, 0xAF, 0xC5, 0xD3, 0xA6, 0x4F, 0x63, - 0xB3, 0x63, 0x97, 0x4C, 0x07, 0xDC, 0x99, 0xC1, 0x49, 0x40, 0x12, 0xBE, 0x89, 0xE7, 0x88, 0x32, - 0x2E, 0xCF, 0x2F, 0x93, 0x55, 0xB2, 0x24, 0x55, 0x49, 0x1F, 0x6F, 0x8B, 0x6A, 0x2B, 0x24, 0x5D, - 0xCB, 0x7C, 0xB1, 0x60, 0x99, 0xAC, 0x91, 0x2E, 0xBF, 0x10, 0x9E, 0xC7, 0x76, 0x34, 0xF3, 0x03, - 0x97, 0x6D, 0x8C, 0xC3, 0x80, 0xD2, 0xA5, 0xF5, 0xBC, 0x7B, 0xC8, 0xB9, 0x72, 0x4A, 0xE7, 0x5C, - 0xC8, 0x11, 0x93, 0x26, 0x54, 0xB3, 0x9C, 0x74, 0x56, 0x51, 0x04, 0x8F, 0x28, 0xA9, 0x54, 0x8E, - 0x03, 0xB3, 0x9C, 0xF4, 0xA5, 0xF3, 0x93, 0xB5, 0x18, 0xD3, 0xF1, 0x99, 0x80, 0x63, 0xF0, 0xCA, - 0x0A, 0x22, 0xA2, 0x18, 0x57, 0x7A, 0xBD, 0x4B, 0xB6, 0x4C, 0x53, 0xF5, 0xC8, 0x0A, 0x23, 0x2C, - 0x49, 0xE5, 0x55, 0xB2, 0x81, 0x82, 0xEC, 0x19, 0x5E, 0x83, 0xCB, 0x9C, 0x9A, 0x0D, 0xCB, 0xE7, - 0x82, 0xD4, 0x15, 0xE9, 0x25, 0x7F, 0xC4, 0x75, 0xCC, 0xD4, 0xEB, 0x74, 0x9C, 0xBC, 0xB2, 0x30, - 0x1A, 0xC3, 0x6A, 0x30, 0x62, 0xBF, 0xBB, 0x23, 0xFD, 0xF9, 0x2A, 0x6E, 0x98, 0xF4, 0x35, 0x7D, - 0x0E, 0x50, 0xC8, 0xE5, 0xCA, 0xAE, 0xE2, 0xB3, 0x27, 0x04, 0x56, 0x88, 0xCE, 0x78, 0x7A, 0xCF, - 0xFF, 0x21, 0x43, 0x12, 0xE9, 0xC4, 0x1C, 0x42, 0x14, 0x80, 0x35, 0x62, 0xFB, 0x69, 0x49, 0x45, - 0xE7, 0x38, 0x4F, 0x2C, 0xD9, 0x8D, 0x28, 0x2D, 0x21, 0x83, 0x4D, 0xE3, 0x84, 0x24, 0x0D, 0x5D, - 0x37, 0x28, 0x5A, 0x86, 0x01, 0x31, 0x81, 0xF7, 0xB2, 0xC1, 0x33, 0x2F, 0x77, 0xA5, 0x90, 0x74, - 0xBF, 0x68, 0xB7, 0x13, 0xEB, 0xE4, 0x48, 0x89, 0x92, 0x9C, 0x54, 0xC0, 0xD3, 0xCB, 0xC9, 0xB5, - 0xA2, 0xE0, 0x51, 0x62, 0x8A, 0xB2, 0x1E, 0x39, 0x33, 0x0C, 0xEA, 0x9D, 0xCC, 0xBA, 0xEA, 0x28, - 0x29, 0xAA, 0x17, 0xEB, 0x4D, 0x41, 0xC5, 0xA4, 0xC3, 0xB3, 0x2B, 0xA6, 0x3A, 0xB7, 0xB0, 0xAA, - 0xDE, 0x91, 0x25, 0x03, 0x61, 0x94, 0xEC, 0x1C, 0x01, 0x37, 0xEF, 0x91, 0x68, 0x08, 0xB3, 0xC6, - 0x7C, 0x25, 0x9E, 0x11, 0x16, 0x93, 0xDE, 0xA9, 0x8B, 0x81, 0x6B, 0xED, 0xD6, 0xA9, 0x9E, 0x57, - 0xEE, 0x8E, 0x9D, 0x64, 0x95, 0xF3, 0x76, 0xED, 0xB4, 0x65, 0x41, 0xE9, 0x9D, 0x3B, 0x93, 0x7E, - 0xE8, 0xBA, 0xB3, 0xC0, 0x1D, 0xBC, 0x9A, 0xE4, 0xE3, 0x9D, 0x3C, 0xD0, 0xDA, 0x35, 0xD4, 0xC8, - 0x35, 0xD0, 0x36, 0xF3, 0x86, 0x9E, 0x2E, 0x98, 0x92, 0x9B, 0x7A, 0x92, 0xD8, 0xD5, 0x8D, 0x3D, - 0x7D, 0xCD, 0x5C, 0x71, 0x73, 0xAF, 0xCC, 0x92, 0x7B, 0x9E, 0x1B, 0x7C, 0xDA, 0xC2, 0x79, 0xB6, - 0x4D, 0x3E, 0x49, 0x28, 0xD5, 0x36, 0xFA, 0xE2, 0xD1, 0xF2, 0x5D, 0x37, 0xFB, 0x14, 0xF5, 0x90, - 0xFD, 0x2B, 0xF4, 0xA4, 0x9E, 0xEB, 0x33, 0xE6, 0xDC, 0xB6, 0x04, 0x53, 0xF3, 0xA5, 0x5A, 0x61, - 0x43, 0x87, 0xD8, 0xD4, 0x3F, 0x6C, 0x15, 0xA1, 0x78, 0xAE, 0x6C, 0x3B, 0x16, 0x1A, 0xC3, 0x85, - 0x6C, 0x76, 0x4A, 0x3A, 0xF0, 0x90, 0x4A, 0x72, 0xA5, 0xEC, 0x5A, 0x4A, 0x39, 0x77, 0xB8, 0xCB, - 0x0D, 0x3F, 0xA5, 0x9E, 0x6D, 0xFF, 0x87, 0xE7, 0xB8, 0x4B, 0xCD, 0x66, 0x9C, 0x70, 0x48, 0xAB, - 0xD2, 0x2A, 0xAE, 0xF2, 0xF7, 0xBF, 0xA7, 0xEA, 0xF8, 0x34, 0x9C, 0xFA, 0x2E, 0x73, 0xD7, 0x35, - 0xEE, 0x86, 0x34, 0xC4, 0x34, 0x47, 0x8A, 0x29, 0x66, 0x19, 0xA6, 0xC0, 0x64, 0x81, 0xF6, 0x44, - 0x65, 0x68, 0x51, 0xF9, 0xB4, 0xAE, 0x99, 0x35, 0xA5, 0x8E, 0x58, 0x61, 0x49, 0x9B, 0x76, 0x47, - 0xD7, 0x6C, 0x93, 0x2E, 0xB4, 0xAE, 0xC8, 0x9D, 0x15, 0x10, 0x9C, 0xBB, 0x09, 0xA6, 0x46, 0xA2, - 0x76, 0x8B, 0xF0, 0x21, 0x8D, 0x65, 0x23, 0xCA, 0x73, 0x68, 0x05, 0x03, 0x1F, 0x9F, 0xE6, 0xD1, - 0x16, 0x3A, 0x23, 0x7A, 0x62, 0xB9, 0xD6, 0x90, 0xFA, 0x17, 0x58, 0x33, 0x95, 0x04, 0x89, 0xC1, - 0xBF, 0x7E, 0x15, 0xFA, 0xC4, 0x1A, 0x39, 0x43, 0x77, 0xB7, 0x39, 0xA2, 0xD7, 0x61, 0x13, 0x3E, - 0xDC, 0xBC, 0xC6, 0xFD, 0x83, 0x57, 0x6B, 0xF0, 0x0B, 0xFE, 0xD1, 0x07, 0x43, 0x26, 0xFE, 0xB0, - 0x5F, 0xBF, 0xE2, 0x8F, 0x29, 0x86, 0xF7, 0x13, 0xBA, 0xCB, 0x3D, 0x8E, 0x2B, 0xEF, 0x5B, 0x93, - 0x38, 0xF6, 0x6E, 0x13, 0x09, 0xF2, 0xE5, 0xFC, 0xDE, 0x68, 0xD4, 0x24, 0xEC, 0xAD, 0x4F, 0xF8, - 0xEA, 0xF9, 0xE3, 0x55, 0x56, 0x71, 0x95, 0x83, 0x4A, 0x7C, 0xB1, 0x9D, 0xC9, 0x26, 0x11, 0x81, - 0x8B, 0x1C, 0x43, 0xC4, 0xB2, 0x37, 0x1C, 0x62, 0x52, 0x1A, 0xE0, 0x67, 0x0D, 0xC9, 0xAE, 0x85, - 0x7E, 0xFC, 0x83, 0xF1, 0x2D, 0x99, 0x6D, 0x04, 0x63, 0x4D, 0xBC, 0xE0, 0x36, 0xAC, 0xD1, 0x90, - 0x44, 0xF9, 0x6D, 0x3C, 0xBA, 0x09, 0xC3, 0x49, 0x6E, 0xE2, 0x29, 0xA9, 0x9E, 0xC8, 0x3F, 0xF5, - 0xEE, 0x90, 0xA7, 0x9F, 0xC2, 0x59, 0x98, 0x65, 0xC7, 0x6A, 0xA4, 0xBD, 0xB3, 0x08, 0x82, 0x65, - 0x15, 0x92, 0xED, 0x84, 0x08, 0x1B, 0x1B, 0x78, 0x63, 0x34, 0x23, 0x51, 0x35, 0x9F, 0x06, 0x13, - 0x70, 0x27, 0x18, 0x93, 0xCB, 0x18, 0xB2, 0x23, 0x72, 0xAD, 0x91, 0xFD, 0xFE, 0xCF, 0x3C, 0x3B, - 0x9A, 0xE3, 0x86, 0x1E, 0x9B, 0xFC, 0x9F, 0x95, 0xEF, 0x48, 0x70, 0xBF, 0x95, 0xE6, 0x17, 0x4C, - 0xA6, 0xAA, 0xD6, 0x65, 0xBE, 0x72, 0x04, 0xCA, 0x2D, 0xB2, 0x8E, 0xA6, 0xF4, 0xDB, 0xBB, 0x0A, - 0x2D, 0x07, 0xD4, 0x50, 0x2A, 0x37, 0xEA, 0xB8, 0xB1, 0x9E, 0xAE, 0xE7, 0x52, 0xFA, 0x46, 0xAC, - 0xA0, 0xAB, 0xA8, 0xD4, 0xC7, 0xA2, 0x96, 0xD4, 0xC3, 0x71, 0xB3, 0x30, 0xC7, 0xDA, 0x49, 0xF2, - 0x8C, 0x13, 0xDA, 0xFF, 0xCF, 0x5F, 0xCC, 0xE5, 0x6C, 0x43, 0xDE, 0x58, 0x21, 0x7A, 0x9D, 0x37, - 0x13, 0x43, 0x54, 0x41, 0x41, 0x31, 0x47, 0x2D, 0x8B, 0xF2, 0x18, 0x7F, 0x47, 0x45, 0xCB, 0xEA, - 0x89, 0x95, 0x5D, 0x59, 0xFC, 0x8A, 0x99, 0x22, 0xE7, 0x74, 0x22, 0xB0, 0x5B, 0xEE, 0x3D, 0x97, - 0x54, 0x54, 0x99, 0x1D, 0x39, 0x04, 0xCC, 0xB7, 0xBD, 0xE5, 0x42, 0x5B, 0x25, 0x4E, 0x9B, 0xB6, - 0x99, 0x61, 0x13, 0x5F, 0xD0, 0xF5, 0xC1, 0x3F, 0xF1, 0xFD, 0x04, 0xC2, 0x9F, 0x90, 0x20, 0xB6, - 0xB8, 0x2D, 0x1C, 0xE4, 0x46, 0xF8, 0xA5, 0xBA, 0x3D, 0xEB, 0x39, 0x30, 0xD1, 0xBA, 0x54, 0xFD, - 0xCF, 0xDF, 0xBE, 0x24, 0xEB, 0xB9, 0xB4, 0x92, 0x7C, 0x96, 0xBD, 0x9E, 0x87, 0xC2, 0x36, 0x47, - 0xA6, 0xB0, 0x4A, 0xA3, 0x31, 0x55, 0x29, 0xE1, 0x51, 0xF6, 0x09, 0x02, 0x5A, 0xA2, 0xD9, 0x8A, - 0xB2, 0xE6, 0xB5, 0x9B, 0x4D, 0x48, 0x69, 0xED, 0x15, 0x41, 0x9A, 0x0D, 0x1C, 0x8D, 0x59, 0xD9, - 0x54, 0xD2, 0x84, 0x98, 0xC0, 0xB2, 0x12, 0xB1, 0xE6, 0x64, 0x71, 0xC9, 0x61, 0x80, 0x69, 0x7A, - 0x6D, 0x0E, 0xB4, 0x9D, 0xC6, 0x0A, 0x91, 0x96, 0xD2, 0xAA, 0x4E, 0x35, 0x75, 0xE4, 0x28, 0x08, - 0xA6, 0x22, 0xEA, 0xFD, 0xE8, 0xE0, 0x25, 0xDB, 0x50, 0x37, 0xF3, 0x51, 0x25, 0x4A, 0x5F, 0xA5, - 0xF1, 0x86, 0x3D, 0xBB, 0x9E, 0x6F, 0x52, 0xB1, 0x4E, 0x59, 0xB3, 0xCA, 0xEB, 0x16, 0x98, 0x56, - 0xAC, 0x54, 0xDF, 0xBC, 0x3E, 0x19, 0xEB, 0xC8, 0x9A, 0xF1, 0x24, 0x2C, 0x64, 0x4A, 0xA0, 0x55, - 0xAD, 0xE4, 0x0F, 0x8B, 0xF1, 0x2F, 0x61, 0x31, 0xD8, 0xE8, 0x73, 0x16, 0x61, 0x35, 0x24, 0xBF, - 0xEF, 0x00, 0xA6, 0x43, 0x3C, 0x80, 0x48, 0x32, 0x84, 0x8A, 0x1B, 0x3B, 0xE8, 0xCC, 0x95, 0x4F, - 0x38, 0x89, 0x18, 0x8F, 0x0E, 0xA4, 0x43, 0x35, 0xCE, 0x8E, 0xCB, 0x4E, 0x54, 0x3E, 0x5C, 0x33, - 0x64, 0xFD, 0xE8, 0x2E, 0x50, 0x6D, 0xA4, 0xCA, 0x16, 0x07, 0x96, 0xF2, 0x13, 0x9B, 0x24, 0xB2, - 0x00, 0x47, 0xE9, 0x5B, 0x9E, 0x72, 0x12, 0x06, 0x47, 0x1F, 0xF3, 0x31, 0x63, 0x46, 0x54, 0xB0, - 0xBE, 0x58, 0xA2, 0x26, 0x74, 0x8E, 0xAB, 0x4A, 0xF6, 0x52, 0xC6, 0xB9, 0x6B, 0xE6, 0x7E, 0x59, - 0xAC, 0xDC, 0x92, 0xF3, 0xC2, 0xA9, 0x3F, 0x0A, 0x31, 0x49, 0x09, 0xAE, 0xF9, 0x1A, 0x6B, 0x88, - 0xE2, 0xAF, 0x8C, 0x7D, 0xD6, 0x57, 0xB2, 0x34, 0x3F, 0x27, 0xE8, 0xF1, 0xB5, 0x50, 0x3C, 0x46, - 0xFD, 0xC9, 0x62, 0xDC, 0xEC, 0xDA, 0xA2, 0x1B, 0x84, 0x79, 0x94, 0xB5, 0x22, 0x46, 0x2F, 0x64, - 0x0A, 0x9E, 0x36, 0xD4, 0x6E, 0x47, 0x27, 0xB3, 0xED, 0x1B, 0x9F, 0x5E, 0xE3, 0xB3, 0xBB, 0x51, - 0xB5, 0xE8, 0x3E, 0x67, 0x4C, 0x6B, 0x65, 0x65, 0x27, 0xAB, 0xF7, 0xA3, 0xB5, 0x90, 0x74, 0xE8, - 0x94, 0x8C, 0xFD, 0xAA, 0xFD, 0x94, 0x95, 0x67, 0x14, 0x37, 0x8D, 0x12, 0xAC, 0x4A, 0xA6, 0x51, - 0x37, 0x95, 0x67, 0x34, 0xA9, 0x88, 0xB9, 0x46, 0x93, 0xF1, 0x15, 0x2D, 0x57, 0xE2, 0x65, 0x60, - 0x72, 0x4D, 0x71, 0xA7, 0x40, 0xC3, 0xA9, 0x9A, 0x01, 0x77, 0x5E, 0xFA, 0xFD, 0x2C, 0xEB, 0xCC, - 0x3C, 0xD5, 0xEF, 0xD1, 0xA6, 0x0E, 0xF4, 0x37, 0x63, 0x2C, 0x10, 0x87, 0xE7, 0xA9, 0x29, 0x58, - 0xD6, 0x2C, 0x7D, 0x07, 0x4F, 0xB6, 0xBB, 0x06, 0xE4, 0xC6, 0xB7, 0x6A, 0xCB, 0x6B, 0xE6, 0xB7, - 0x94, 0x42, 0xB2, 0xB6, 0x34, 0x76, 0x4A, 0xCF, 0xB4, 0xB9, 0x53, 0x6D, 0xCC, 0x48, 0xF1, 0x04, - 0x2B, 0xB5, 0x7D, 0x6D, 0xED, 0x9C, 0x5E, 0xC3, 0x8C, 0x7A, 0xC3, 0xD3, 0x4C, 0xC7, 0x61, 0x45, - 0xB9, 0xCB, 0x4D, 0x65, 0xF7, 0x64, 0x47, 0xBB, 0x42, 0xCA, 0x33, 0x3E, 0x6B, 0x1A, 0x2F, 0xE5, - 0xB0, 0xC6, 0x5F, 0xBB, 0x73, 0x49, 0x5B, 0xCD, 0x31, 0xD5, 0xCC, 0x54, 0xCD, 0x19, 0x35, 0x5C, - 0x8D, 0x86, 0xB9, 0x7E, 0xE8, 0x63, 0x16, 0xF5, 0x16, 0x89, 0x7E, 0x7D, 0x0F, 0xD3, 0xFB, 0x88, - 0xFA, 0xAA, 0x60, 0x19, 0x96, 0x34, 0x38, 0xB3, 0x30, 0x2D, 0xB0, 0x2E, 0x3C, 0xE1, 0x73, 0x15, - 0x50, 0x7E, 0x18, 0xD1, 0xE2, 0x87, 0x12, 0x55, 0x00, 0xAD, 0x2B, 0xCF, 0x0F, 0x01, 0x90, 0xFD, - 0x3F, 0x1B, 0x30, 0x23, 0x39, 0xF7, 0x28, 0x3F, 0x31, 0xB7, 0xF4, 0xBA, 0x81, 0x26, 0x8F, 0x28, - 0x8D, 0x72, 0xD2, 0xCD, 0x13, 0xEA, 0x0F, 0xF8, 0xFD, 0x58, 0x5E, 0xD6, 0x1E, 0xB1, 0x94, 0xCB, - 0x64, 0x8D, 0xF0, 0x3F, 0x43, 0x2F, 0xC4, 0x7D, 0xC0, 0xBF, 0xE0, 0xD1, 0xBE, 0x94, 0x8D, 0x5A, - 0xA0, 0x7D, 0x63, 0xF9, 0xD2, 0x21, 0xDD, 0x89, 0x15, 0xDE, 0xB4, 0x7D, 0x6F, 0x0A, 0xDC, 0x08, - 0xB4, 0xCB, 0x09, 0xC8, 0x54, 0xCA, 0xE7, 0xAD, 0x39, 0xC6, 0x06, 0x38, 0x1C, 0x74, 0xFF, 0x5B, - 0xA8, 0x26, 0xB5, 0x79, 0x96, 0xF0, 0x78, 0x4B, 0x58, 0xB0, 0xFC, 0x1A, 0x5F, 0xD4, 0xE8, 0xA4, - 0x1E, 0x06, 0xCA, 0xA6, 0xD3, 0x38, 0x4B, 0x12, 0x8F, 0xB7, 0xC8, 0x1D, 0x5E, 0xC1, 0x72, 0x87, - 0x5C, 0xD1, 0xC1, 0xFB, 0x64, 0xDA, 0x7D, 0x0F, 0x1D, 0x34, 0x6E, 0x18, 0x1E, 0x7B, 0xD5, 0xB4, - 0x43, 0x15, 0x64, 0x11, 0x5D, 0x9E, 0x51, 0x9C, 0xC4, 0x29, 0xC5, 0x8B, 0x04, 0x19, 0x1D, 0x1C, - 0xCD, 0x63, 0xA8, 0xB3, 0x6F, 0xB1, 0x39, 0xC7, 0x84, 0xE0, 0xFC, 0x68, 0xE2, 0xCD, 0xFD, 0x91, - 0x5D, 0x95, 0x6B, 0x49, 0x1E, 0xB2, 0xC6, 0xD7, 0x12, 0xC6, 0x5B, 0x0B, 0x98, 0xB4, 0x55, 0xA4, - 0xF2, 0x68, 0xA8, 0x85, 0x74, 0x0F, 0x11, 0x08, 0xAC, 0x09, 0xDA, 0x70, 0x20, 0xB2, 0x45, 0xBE, - 0xC1, 0x19, 0x54, 0x71, 0x6D, 0x92, 0x7B, 0xFE, 0x17, 0x83, 0x52, 0x59, 0x2C, 0xF9, 0x09, 0x59, - 0x8C, 0x51, 0x8D, 0x45, 0x35, 0x6E, 0x03, 0xF2, 0x23, 0xBD, 0x0C, 0x88, 0xA8, 0x6D, 0x71, 0x31, - 0x66, 0x05, 0x94, 0x5F, 0x7E, 0xD9, 0xDE, 0x78, 0x61, 0x9A, 0xC9, 0xA1, 0x3E, 0x4F, 0xFB, 0x59, - 0xD0, 0xA4, 0x32, 0xE9, 0x48, 0xE3, 0x26, 0x99, 0x12, 0x89, 0xE6, 0x37, 0x29, 0x2B, 0xF5, 0xE8, - 0x50, 0x2E, 0x2E, 0xD9, 0xA4, 0xA9, 0x3D, 0xC9, 0x6B, 0xCC, 0x47, 0xBB, 0x42, 0x63, 0xA6, 0x76, - 0x46, 0xBE, 0xC0, 0x9C, 0xE6, 0x64, 0xC2, 0xC4, 0xFA, 0x67, 0x9B, 0x1B, 0xD4, 0xED, 0x74, 0xBB, - 0x1D, 0x53, 0x8B, 0xEC, 0x9B, 0xC1, 0xE4, 0x10, 0x96, 0x91, 0xBE, 0x4B, 0xC3, 0x74, 0xAB, 0x44, - 0xC1, 0xC1, 0xFB, 0xFD, 0xB3, 0xFC, 0x26, 0x49, 0x19, 0xC3, 0x8F, 0xCE, 0x54, 0x16, 0x23, 0xEC, - 0xB9, 0xCD, 0x93, 0x32, 0x79, 0x17, 0xC3, 0xCB, 0xFC, 0x43, 0x01, 0x5E, 0xF6, 0x66, 0x71, 0xCE, - 0xAA, 0x37, 0xAC, 0x05, 0xC2, 0xE3, 0xB7, 0x3B, 0xE7, 0xDA, 0x39, 0xE5, 0x00, 0xA5, 0x1C, 0x48, - 0xC7, 0xFE, 0xB7, 0x5D, 0x09, 0xE6, 0x4B, 0x93, 0xFC, 0xF4, 0x13, 0x89, 0xCB, 0xFE, 0xBC, 0xDB, - 0xEF, 0xEB, 0xCE, 0xB3, 0xE6, 0xEF, 0xC9, 0x04, 0xB3, 0xDC, 0x3D, 0x14, 0xB6, 0x5C, 0x0F, 0x3D, - 0x3A, 0xD6, 0x6D, 0xF1, 0x89, 0x22, 0xE9, 0x2C, 0x6B, 0x11, 0x08, 0xD0, 0x34, 0x5C, 0x1B, 0x48, - 0x1E, 0x57, 0x74, 0x28, 0xC5, 0xCA, 0x34, 0xEF, 0x89, 0xF5, 0xDB, 0x29, 0xBD, 0x8B, 0x52, 0x1C, - 0x29, 0xFD, 0xAC, 0xE7, 0x4D, 0xF9, 0x53, 0x9C, 0x50, 0x19, 0xDA, 0xBA, 0xA4, 0x89, 0x97, 0x85, - 0x02, 0xE8, 0xAA, 0x7C, 0x12, 0x0C, 0x79, 0x60, 0x45, 0x33, 0x7A, 0x9D, 0x62, 0x5F, 0x10, 0x84, - 0x12, 0x7C, 0xFE, 0xE4, 0x17, 0xE7, 0xAD, 0xC3, 0x26, 0x06, 0xBC, 0xF8, 0x4D, 0xC7, 0x93, 0xF0, - 0x5E, 0x56, 0x5B, 0x83, 0xEB, 0x2C, 0x72, 0xC2, 0xED, 0x6B, 0x7C, 0x67, 0x05, 0x20, 0x0A, 0x26, - 0x32, 0xE9, 0x83, 0x1E, 0xB9, 0x78, 0xAD, 0x19, 0x26, 0x52, 0x98, 0x43, 0x45, 0x93, 0x1A, 0xDA, - 0xFB, 0x41, 0xA8, 0x1F, 0xE2, 0xB1, 0x08, 0xDC, 0xF1, 0x91, 0x4E, 0x8C, 0x60, 0x39, 0x0A, 0xCE, - 0x0B, 0x19, 0x4C, 0x7D, 0x1F, 0xA7, 0x74, 0xD6, 0x1A, 0xEC, 0x79, 0xB6, 0x3D, 0x73, 0xF6, 0x4B, - 0x90, 0xA8, 0xDC, 0x28, 0x10, 0x13, 0x57, 0x3D, 0xED, 0xCA, 0x51, 0x24, 0x09, 0x75, 0x96, 0x1E, - 0x49, 0xCC, 0xAF, 0xEC, 0xCA, 0x00, 0xC9, 0x12, 0xA1, 0x85, 0xCB, 0x07, 0xAD, 0x24, 0x0A, 0xA8, - 0x86, 0x42, 0xA5, 0x0F, 0x54, 0xCB, 0x76, 0xBE, 0x2F, 0x75, 0x82, 0x6E, 0x07, 0x32, 0x58, 0x48, - 0x81, 0xB6, 0xB0, 0x76, 0x44, 0x06, 0x0D, 0x40, 0x69, 0x40, 0xD6, 0x53, 0xAD, 0xA8, 0x43, 0xB4, - 0xDA, 0xBA, 0x7A, 0xE3, 0xFB, 0x1D, 0xD1, 0xBD, 0x15, 0x79, 0x8F, 0x26, 0x2A, 0x67, 0x1B, 0x08, - 0x00, 0x2F, 0xF6, 0x64, 0x62, 0x64, 0xCB, 0xC6, 0xA7, 0x41, 0x94, 0xF2, 0xE4, 0x36, 0x87, 0x44, - 0xCF, 0xF8, 0x58, 0x53, 0x8A, 0x29, 0xD3, 0x93, 0x4D, 0xAC, 0x12, 0x20, 0x37, 0x8D, 0x4D, 0xE5, - 0xC9, 0xA1, 0x0C, 0x92, 0xCB, 0xE9, 0x3D, 0x87, 0xC6, 0x3E, 0xC2, 0x31, 0x55, 0x17, 0x6C, 0xA1, - 0x3A, 0x65, 0xC0, 0xC7, 0xF7, 0x45, 0x0A, 0x47, 0x90, 0x60, 0x34, 0x7E, 0xA4, 0x86, 0xC0, 0x14, - 0x13, 0xB0, 0xF0, 0x8B, 0x1D, 0xCD, 0x1C, 0xC7, 0x34, 0x7E, 0xE6, 0x35, 0x96, 0xAE, 0xD5, 0xBF, - 0x95, 0xF6, 0x65, 0xD2, 0x94, 0x1E, 0xEE, 0xD4, 0xE0, 0x79, 0xC6, 0xF7, 0xF3, 0xF3, 0x0F, 0xE7, - 0x8D, 0xCA, 0x86, 0x48, 0x8C, 0x34, 0x02, 0x12, 0xE1, 0xB3, 0x24, 0xCB, 0xEE, 0x61, 0xDD, 0x82, - 0x9B, 0xC7, 0x0F, 0x51, 0x77, 0xB4, 0x09, 0xCD, 0x76, 0x6E, 0xDF, 0xD1, 0x50, 0x31, 0x41, 0xEA, - 0x7C, 0x5B, 0x68, 0xA5, 0xB4, 0xDD, 0x45, 0xD5, 0xD8, 0x29, 0x1B, 0x9C, 0xA6, 0x76, 0xEE, 0x7F, - 0x3C, 0x3F, 0x3F, 0x3C, 0xBD, 0x30, 0xB5, 0x34, 0xB3, 0x91, 0xB1, 0x9A, 0x83, 0xB1, 0x9D, 0x4E, - 0xD0, 0xE2, 0xF1, 0x44, 0x7B, 0x8F, 0xDC, 0x36, 0xD9, 0x90, 0xEB, 0x74, 0x74, 0xBF, 0x98, 0xC5, - 0xBB, 0x01, 0xA3, 0xB7, 0x0D, 0x76, 0x1B, 0x44, 0x91, 0xC3, 0x4E, 0x2E, 0x22, 0x33, 0x37, 0xEA, - 0xFB, 0x4B, 0x88, 0xFD, 0x2C, 0x6B, 0x0D, 0x63, 0x56, 0x45, 0x15, 0x48, 0x52, 0x48, 0x91, 0x18, - 0xDC, 0x24, 0x3A, 0xED, 0x70, 0x47, 0x1F, 0xD3, 0x4F, 0x67, 0xC2, 0xFD, 0xFE, 0xDD, 0x6F, 0x9C, - 0xC5, 0x4B, 0x19, 0x84, 0x94, 0xF2, 0xA7, 0x7B, 0x0A, 0xDA, 0xFF, 0x4E, 0x3C, 0xFA, 0x84, 0x9B, - 0x35, 0xD7, 0x52, 0xF3, 0x7E, 0x4C, 0xF4, 0xEA, 0x44, 0x6F, 0x98, 0x4C, 0x55, 0xCD, 0x5D, 0xF4, - 0x54, 0xAA, 0x52, 0x33, 0x4E, 0xA4, 0x1A, 0x43, 0xA6, 0x69, 0x74, 0xC8, 0xF1, 0xCA, 0x23, 0x4E, - 0x0A, 0x0C, 0x8B, 0x6E, 0x56, 0xA0, 0x3D, 0xED, 0x36, 0x32, 0x5F, 0xF5, 0x33, 0xB2, 0xB2, 0x6C, - 0xB4, 0xD4, 0x11, 0xB6, 0xF4, 0x2C, 0xB4, 0xA0, 0xA1, 0x55, 0x64, 0xF2, 0x99, 0x35, 0x88, 0xC4, - 0xA0, 0x6A, 0xBD, 0xF2, 0xC8, 0xA6, 0xBA, 0x74, 0xF2, 0x42, 0x2B, 0xA2, 0x2E, 0x9E, 0xB0, 0x13, - 0xBB, 0x56, 0xD1, 0x6E, 0x8A, 0xD1, 0x15, 0xC9, 0x92, 0x53, 0xF9, 0xE1, 0xA9, 0x51, 0xE1, 0xDB, - 0x68, 0xFA, 0x53, 0x76, 0x65, 0x4D, 0xB8, 0x86, 0x4C, 0xDA, 0xDC, 0xD7, 0xC9, 0xEC, 0xA6, 0xB6, - 0xE2, 0xB4, 0x17, 0x33, 0x95, 0x74, 0x0A, 0xEF, 0x9C, 0x5B, 0xEA, 0x12, 0x0B, 0x9F, 0x5E, 0xF5, - 0x9B, 0x81, 0xC8, 0x00, 0x86, 0xC2, 0xBC, 0xC7, 0x89, 0x0A, 0xBA, 0xD9, 0x0D, 0x9D, 0x6B, 0x9E, - 0x87, 0x0B, 0xE3, 0xDE, 0x98, 0x89, 0x10, 0x6B, 0x30, 0xFC, 0x96, 0x84, 0x34, 0x13, 0xC7, 0x25, - 0x07, 0x07, 0x6D, 0x3B, 0xFA, 0xC7, 0x36, 0x9C, 0x2D, 0x29, 0x8C, 0x3B, 0xC2, 0x75, 0x84, 0xB6, - 0x02, 0x5F, 0x4B, 0x5A, 0x42, 0x9A, 0x87, 0x2E, 0x90, 0x52, 0xD7, 0xB3, 0x11, 0xC6, 0xB8, 0x22, - 0x34, 0x5F, 0x7D, 0x67, 0x29, 0x68, 0xEF, 0x7F, 0xF8, 0x70, 0x7E, 0x70, 0x74, 0xBA, 0x77, 0x71, - 0x78, 0x79, 0x74, 0x7A, 0xF6, 0xF1, 0xE2, 0xF2, 0xE2, 0xD3, 0x19, 0xFE, 0xFA, 0xF3, 0xDE, 0xF1, - 0xD1, 0xC1, 0xE5, 0xC7, 0xD3, 0xBF, 0x9D, 0x7E, 0xF8, 0xE5, 0x34, 0xD9, 0xD4, 0xB6, 0xAD, 0xE0, - 0x46, 0xBA, 0x31, 0x1E, 0x9B, 0x47, 0x0C, 0x39, 0x37, 0x7C, 0xB7, 0xE9, 0xC0, 0x19, 0x5B, 0x23, - 0x43, 0x09, 0x37, 0x55, 0x1F, 0xAE, 0x8F, 0x29, 0x7B, 0x3F, 0x51, 0x3F, 0xDD, 0x03, 0xE3, 0x01, - 0xDE, 0x56, 0x88, 0xCF, 0x74, 0xC5, 0x72, 0xE1, 0xAF, 0xE1, 0xE0, 0x5D, 0x64, 0x54, 0x2F, 0x72, - 0x77, 0x63, 0xB1, 0xE9, 0x6A, 0xC8, 0x04, 0x0F, 0x32, 0x9E, 0x06, 0xB1, 0x55, 0x1E, 0x58, 0x2E, - 0xA1, 0x28, 0x10, 0x66, 0x32, 0x1D, 0x17, 0x3A, 0xDF, 0xB1, 0xD9, 0xAD, 0xF2, 0x40, 0x54, 0xD9, - 0x23, 0xFC, 0x1B, 0xAF, 0x85, 0x0F, 0x8E, 0xB2, 0x3C, 0x70, 0xFC, 0x1C, 0x30, 0x68, 0x91, 0xD5, - 0x16, 0xC6, 0x9B, 0xB6, 0x58, 0x37, 0xB5, 0xD5, 0xB3, 0x2E, 0xC9, 0xF8, 0xC6, 0x82, 0xD7, 0x4D, - 0xAF, 0x7A, 0x8D, 0x36, 0xB0, 0x9D, 0xA1, 0x13, 0x26, 0xDD, 0x84, 0x87, 0xB8, 0x59, 0x57, 0x2A, - 0x11, 0x40, 0x15, 0x1B, 0x8B, 0xA6, 0x37, 0xCA, 0x6B, 0x65, 0x25, 0xEF, 0xC5, 0x10, 0x99, 0x1C, - 0x62, 0x69, 0xAE, 0x36, 0x97, 0x93, 0x0E, 0x5C, 0x59, 0x61, 0xAF, 0x18, 0x8D, 0x46, 0x64, 0xE8, - 0x79, 0x76, 0x09, 0x68, 0x02, 0xD0, 0x49, 0x3F, 0x57, 0x06, 0x6F, 0x23, 0x71, 0xA9, 0x5D, 0x79, - 0x08, 0xA2, 0xBD, 0x89, 0x5A, 0xCA, 0x2A, 0xCE, 0x83, 0xD9, 0x92, 0x06, 0xD4, 0x08, 0x23, 0x5D, - 0x02, 0x45, 0x05, 0x58, 0x62, 0x01, 0xF5, 0xF0, 0x09, 0xBC, 0x7B, 0x54, 0xA2, 0x89, 0x17, 0x04, - 0x0E, 0xC6, 0xC3, 0x72, 0xAD, 0xC0, 0x71, 0x1A, 0xE9, 0x4B, 0x32, 0x24, 0x93, 0x0F, 0x27, 0x27, - 0xED, 0x31, 0xFF, 0x97, 0x7C, 0x23, 0xA6, 0x8F, 0xAB, 0xA6, 0x8F, 0x27, 0x27, 0xFD, 0x7E, 0x3B, - 0x60, 0xFF, 0x14, 0x70, 0x62, 0xF8, 0x0C, 0x08, 0x56, 0x93, 0xCF, 0xCF, 0x8C, 0x7A, 0xC2, 0x6E, - 0x71, 0xCD, 0x2E, 0xB9, 0xFF, 0x8B, 0x41, 0xC2, 0xAE, 0xD7, 0x26, 0x1B, 0x30, 0xDA, 0xB6, 0x3B, - 0xEB, 0xEB, 0x1B, 0xCF, 0x59, 0xFE, 0x3D, 0x26, 0xBF, 0x76, 0x12, 0xA1, 0x9C, 0x8C, 0xF8, 0xD7, - 0xA4, 0x37, 0x0F, 0xC2, 0x1F, 0x70, 0xFC, 0x75, 0x58, 0x4E, 0x08, 0x18, 0x69, 0x3D, 0x62, 0x8D, - 0x30, 0x2B, 0xA1, 0x8D, 0x8C, 0x90, 0xCE, 0x26, 0xE9, 0x6D, 0xB6, 0x7B, 0x9D, 0x8D, 0x6D, 0x03, - 0x2B, 0x89, 0x4D, 0x7A, 0x4D, 0xD6, 0xE7, 0xCC, 0x49, 0x8F, 0x31, 0xB3, 0x9E, 0x30, 0xB3, 0xDA, - 0xED, 0x6C, 0xAE, 0x76, 0xBB, 0xAB, 0x9D, 0xCD, 0x76, 0x77, 0xAB, 0x67, 0x62, 0xC7, 0x6C, 0xD9, - 0x5E, 0x63, 0x90, 0xFF, 0x9C, 0x58, 0x7B, 0x8E, 0x3C, 0x5D, 0xD3, 0x3B, 0xEA, 0x73, 0x7E, 0xBA, - 0x5D, 0xE4, 0xE6, 0xC5, 0x8B, 0xED, 0xED, 0x1E, 0x59, 0x3A, 0xE0, 0x9A, 0x85, 0x55, 0xF8, 0x6F, - 0xCB, 0x31, 0x8F, 0x89, 0x3B, 0xEB, 0xD2, 0xA1, 0x15, 0x82, 0xDD, 0xEC, 0x3B, 0x43, 0x57, 0xF5, - 0x1E, 0xD4, 0xB1, 0xDB, 0x49, 0x0C, 0x47, 0x62, 0xA5, 0xE2, 0x62, 0xEE, 0x77, 0x61, 0x60, 0xFD, - 0x9E, 0x64, 0xDC, 0x5A, 0x28, 0x3A, 0x8C, 0x7D, 0x67, 0x27, 0x3D, 0x18, 0x7D, 0x0F, 0xC6, 0x8B, - 0x89, 0x82, 0x9B, 0x8F, 0xE4, 0xAE, 0x8D, 0xCA, 0x84, 0x1A, 0xD8, 0x13, 0x77, 0xEA, 0xEA, 0x2A, - 0x22, 0xC2, 0x44, 0x9A, 0x49, 0x3F, 0x83, 0xB5, 0xC6, 0x39, 0xD3, 0x71, 0xF9, 0x63, 0x1F, 0xAC, - 0x84, 0x72, 0x0B, 0xCE, 0xF3, 0x6F, 0xB2, 0xD4, 0x14, 0x82, 0x68, 0x44, 0x86, 0x04, 0x40, 0x47, - 0xDF, 0xB0, 0x92, 0xF5, 0x98, 0x1B, 0x5A, 0x5C, 0x53, 0x49, 0xB3, 0x5C, 0xFC, 0x2D, 0xA3, 0x5F, - 0x77, 0xD9, 0xED, 0x0D, 0x7C, 0x1C, 0x30, 0xB3, 0x7C, 0x6B, 0x19, 0x16, 0x64, 0x6B, 0x6B, 0xE9, - 0x11, 0x2F, 0x3F, 0xE0, 0x5C, 0x7F, 0xAE, 0xE6, 0x78, 0xA5, 0x53, 0x79, 0x9E, 0x86, 0x83, 0x1D, - 0xBA, 0xF0, 0x6B, 0x3C, 0xEC, 0x28, 0x12, 0xC4, 0xEB, 0x0E, 0xA2, 0xDB, 0xD1, 0x89, 0xC3, 0xC0, - 0xBA, 0x09, 0x9C, 0x4F, 0x22, 0xF4, 0x46, 0xC1, 0x22, 0xEC, 0x8B, 0x8A, 0x42, 0x42, 0xCD, 0xEF, - 0x46, 0x77, 0x64, 0x1C, 0xC9, 0xC4, 0x97, 0x54, 0x5B, 0xDD, 0x8D, 0x4D, 0x15, 0x3F, 0x73, 0x55, - 0xEE, 0x53, 0xB3, 0x54, 0xBE, 0x8E, 0x3B, 0x0D, 0x59, 0x8C, 0x46, 0x0E, 0xA1, 0x98, 0xCC, 0xC9, - 0x89, 0x1C, 0x17, 0xF7, 0xD6, 0x81, 0x29, 0x1A, 0xA6, 0x17, 0x65, 0xCA, 0x4D, 0x26, 0x66, 0x76, - 0xB9, 0xE8, 0xC3, 0xF5, 0x12, 0x9B, 0x80, 0xA0, 0x37, 0x56, 0xBB, 0xFA, 0xDE, 0xF8, 0xAC, 0xA2, - 0xBF, 0x3C, 0xFD, 0x70, 0x79, 0x70, 0xB8, 0x7F, 0x74, 0xB2, 0x77, 0xAC, 0xF5, 0x42, 0x40, 0x61, - 0x02, 0xB2, 0xB1, 0x59, 0x31, 0x3F, 0x9A, 0xB8, 0x65, 0x75, 0xE0, 0x8B, 0x2B, 0x0E, 0x61, 0x14, - 0x59, 0x32, 0xA0, 0x64, 0x41, 0xCB, 0x20, 0x91, 0x1C, 0xFF, 0x12, 0xCB, 0x4B, 0x00, 0x80, 0xC8, - 0xA4, 0x30, 0x34, 0x83, 0x6B, 0x15, 0x11, 0x5B, 0x49, 0x90, 0xAC, 0x91, 0x2D, 0x98, 0x02, 0xD8, - 0xA5, 0xFA, 0x88, 0xC6, 0x1A, 0x59, 0xDF, 0xC2, 0x6C, 0x32, 0xCB, 0xDA, 0xAD, 0x70, 0x65, 0x24, - 0x9B, 0xFD, 0x1A, 0x13, 0xD9, 0xBF, 0x60, 0x77, 0xC8, 0x2F, 0x1C, 0x3E, 0x98, 0x56, 0x4F, 0xDA, - 0x10, 0xC5, 0xD1, 0xA8, 0x0E, 0x50, 0x36, 0x3E, 0x33, 0x87, 0xDF, 0x26, 0x8E, 0xCE, 0xCC, 0xD2, - 0x8D, 0x78, 0x6C, 0x2A, 0x33, 0xF4, 0xFC, 0x86, 0x66, 0xC9, 0x81, 0x99, 0x8C, 0x48, 0x45, 0x43, - 0x32, 0x86, 0xA3, 0x3E, 0x34, 0xAA, 0x0E, 0xC0, 0xCC, 0xE1, 0x67, 0xD6, 0x53, 0x45, 0x34, 0x2C, - 0xD2, 0x57, 0x00, 0x18, 0x10, 0x9B, 0x95, 0xB4, 0xAA, 0xD2, 0x2D, 0x58, 0xBF, 0x54, 0x05, 0x53, - 0xB4, 0xA9, 0xCB, 0xF5, 0x61, 0x75, 0x41, 0x0A, 0x71, 0x79, 0x72, 0x72, 0x79, 0xB0, 0xD7, 0x7F, - 0xAF, 0xA9, 0x85, 0x88, 0x37, 0x4A, 0xCC, 0x96, 0xB8, 0x4D, 0xB6, 0xAA, 0xDF, 0x36, 0x4C, 0x74, - 0x40, 0x98, 0x72, 0x84, 0xC4, 0xFC, 0x45, 0x49, 0x87, 0x65, 0x74, 0xAD, 0x5C, 0xBF, 0xFB, 0x45, - 0x32, 0xA6, 0xA9, 0xDE, 0x7D, 0x62, 0x9D, 0x95, 0xDD, 0x57, 0xBD, 0xB8, 0xAF, 0x22, 0xEF, 0x78, - 0xEE, 0x7D, 0x05, 0xE6, 0xFD, 0x89, 0x75, 0xD7, 0x93, 0x99, 0xFB, 0x24, 0xF1, 0x94, 0x99, 0x02, - 0xE5, 0x06, 0xF5, 0x92, 0x06, 0xA5, 0xE7, 0xC0, 0x3F, 0xFA, 0x04, 0xC5, 0x95, 0x32, 0xD9, 0xC0, - 0x99, 0xAB, 0x4E, 0xEE, 0x14, 0x88, 0x29, 0x31, 0xE0, 0xDF, 0x4D, 0x00, 0xC2, 0x82, 0x92, 0xC5, - 0x59, 0xD0, 0x92, 0xA3, 0x91, 0xFC, 0x30, 0x9E, 0x79, 0xFD, 0xD4, 0x8B, 0xFB, 0x89, 0x2C, 0x66, - 0x5D, 0xC2, 0x0D, 0xC4, 0x13, 0xEA, 0xAC, 0xA7, 0x66, 0x3A, 0xFF, 0xA7, 0x59, 0x4D, 0xB1, 0xA1, - 0xA5, 0x9C, 0x0C, 0x19, 0x10, 0xF0, 0xC3, 0x21, 0x43, 0x41, 0x9C, 0x5D, 0x6B, 0x7B, 0x59, 0xBB, - 0x5A, 0x6F, 0xE8, 0x0E, 0x7E, 0xE6, 0x93, 0x6C, 0xCC, 0x4B, 0x3B, 0xEC, 0xB8, 0xA9, 0x9B, 0x5C, - 0x41, 0x6F, 0x11, 0x6F, 0x1A, 0xE2, 0x1F, 0x96, 0xD8, 0xB5, 0x07, 0xA0, 0xBE, 0xA7, 0xEE, 0xC1, - 0xE3, 0x86, 0xF2, 0x15, 0x48, 0x6B, 0x4C, 0x49, 0x53, 0x1B, 0x32, 0xCD, 0x16, 0xA1, 0xE1, 0x40, - 0x0E, 0xAA, 0x65, 0x7C, 0x33, 0x3E, 0x24, 0xBE, 0x5A, 0x26, 0x95, 0x31, 0xEF, 0xD7, 0x8B, 0xCD, - 0x4B, 0xE9, 0xA0, 0x91, 0xDF, 0x3D, 0x30, 0x68, 0x5C, 0x79, 0x95, 0x5B, 0x36, 0x0E, 0xEB, 0x44, - 0xC3, 0x92, 0x6F, 0xCB, 0x92, 0x98, 0xF5, 0xD3, 0x5A, 0x99, 0x0D, 0xF3, 0x59, 0xD7, 0x8C, 0x6C, - 0x5E, 0x4A, 0x6B, 0x1E, 0x58, 0xB7, 0xCD, 0x88, 0x6D, 0xAE, 0xC8, 0x22, 0xD7, 0x7D, 0xCE, 0x28, - 0xFB, 0x9F, 0x4E, 0xDE, 0x7C, 0x38, 0x66, 0x48, 0xF5, 0x4B, 0x1D, 0x23, 0xCF, 0x1D, 0xB2, 0x3C, - 0x46, 0x07, 0x74, 0xE8, 0x53, 0x7D, 0x7F, 0x24, 0xD5, 0x13, 0x5A, 0xD7, 0xC2, 0xE2, 0x4C, 0x47, - 0x60, 0xAC, 0x07, 0xC3, 0x75, 0xAB, 0xB3, 0xA3, 0xE5, 0x86, 0x8C, 0x4B, 0x5F, 0x91, 0x4C, 0xCB, - 0xC7, 0x07, 0xBA, 0x64, 0xBA, 0x14, 0xBD, 0x1A, 0xA4, 0x87, 0xED, 0xF3, 0xE5, 0x54, 0x0E, 0xCA, - 0x19, 0xBB, 0x37, 0x8B, 0xB5, 0x78, 0x08, 0xA5, 0x44, 0xB8, 0x02, 0xA3, 0x8A, 0x59, 0x97, 0xA8, - 0xEA, 0x4E, 0xFA, 0xF0, 0x62, 0x4E, 0x8A, 0x52, 0x8B, 0xB9, 0xD5, 0xC7, 0xE0, 0x8E, 0xEB, 0x5C, - 0x2D, 0xFE, 0xFE, 0xFB, 0xBF, 0x54, 0x06, 0xF1, 0x5B, 0xB3, 0xA1, 0xB2, 0x59, 0x07, 0x2F, 0x31, - 0xB5, 0x5B, 0xB3, 0x2D, 0x73, 0x69, 0x7A, 0x7F, 0x59, 0x1E, 0xC0, 0xB3, 0xAB, 0xE0, 0x9C, 0x11, - 0x4A, 0xAB, 0xAA, 0x45, 0xE0, 0xD5, 0x7B, 0x7E, 0x4E, 0x22, 0x90, 0x5C, 0x99, 0x45, 0x70, 0xBD, - 0x58, 0xEC, 0xDA, 0x0A, 0x76, 0xF9, 0x8F, 0x6E, 0x86, 0x15, 0x9E, 0x4F, 0x4C, 0x5B, 0xEB, 0x55, - 0x78, 0x16, 0x08, 0xF2, 0x78, 0x2E, 0x3D, 0x01, 0x6C, 0xCD, 0x7D, 0x02, 0x90, 0x47, 0x5F, 0xC5, - 0x29, 0x20, 0x25, 0xA2, 0x47, 0x9A, 0x1A, 0x52, 0xA3, 0xBB, 0xEA, 0xEC, 0x60, 0x62, 0x7C, 0xF5, - 0x91, 0x38, 0x9F, 0x79, 0xE6, 0x30, 0x31, 0xDF, 0x4C, 0x4F, 0x29, 0x7F, 0x6F, 0x34, 0x16, 0xD5, - 0x86, 0xE5, 0xDA, 0xD3, 0x93, 0x89, 0x77, 0xB2, 0x68, 0xC1, 0x67, 0x9A, 0xD7, 0x39, 0xA9, 0xBB, - 0x74, 0x51, 0xD1, 0x68, 0x16, 0xE6, 0xAC, 0x40, 0x33, 0xB6, 0x24, 0xBF, 0x1F, 0x1E, 0xB9, 0x2D, - 0xFA, 0xC4, 0x31, 0xFF, 0x11, 0x9D, 0xD7, 0xA0, 0xD4, 0x45, 0x1E, 0x95, 0x9E, 0x16, 0xF3, 0x18, - 0x05, 0x21, 0x0D, 0xF0, 0x51, 0x45, 0x01, 0xB3, 0xF6, 0x77, 0x7B, 0xAD, 0x1D, 0xE2, 0x95, 0xE4, - 0xC1, 0xF2, 0x0E, 0x51, 0x53, 0x26, 0x44, 0xE7, 0xFA, 0xB0, 0x24, 0x6E, 0xF1, 0x0C, 0x8D, 0xB0, - 0x82, 0xBD, 0xF1, 0xE5, 0x20, 0x49, 0x9E, 0x5E, 0xF2, 0x35, 0xAE, 0x9A, 0xA3, 0xAB, 0x47, 0xAB, - 0x52, 0x10, 0x0A, 0x7C, 0x56, 0x16, 0xE9, 0x58, 0x4D, 0x49, 0x8C, 0x28, 0x92, 0x4F, 0xAE, 0x20, - 0x5E, 0x8C, 0x06, 0x55, 0xCA, 0x39, 0xF2, 0x15, 0x96, 0x46, 0x5E, 0x5E, 0xC7, 0xBB, 0xCA, 0xCA, - 0x5D, 0xA0, 0xB6, 0xF0, 0x4D, 0x4B, 0x97, 0xE7, 0xB2, 0x13, 0x6B, 0x78, 0xE9, 0xB6, 0xB0, 0x28, - 0x49, 0xE2, 0xE5, 0x72, 0x56, 0xE2, 0xC1, 0x9D, 0x13, 0x0E, 0x6E, 0x48, 0x5E, 0x15, 0x16, 0x9E, - 0x40, 0xAF, 0xAD, 0xE9, 0x28, 0x7C, 0xA9, 0x65, 0xC3, 0xE7, 0x3D, 0xD1, 0xF8, 0xE8, 0x7E, 0x75, - 0xBD, 0x3B, 0x57, 0x4F, 0x29, 0xAB, 0xBD, 0xBC, 0x30, 0xC0, 0x6B, 0xBB, 0x4B, 0xA5, 0xD7, 0xEF, - 0x19, 0xB4, 0xE4, 0x6D, 0x8A, 0xB9, 0x12, 0x84, 0xC5, 0x55, 0x26, 0xC9, 0x64, 0xDF, 0x73, 0xAE, - 0x24, 0x2F, 0xF3, 0x68, 0x92, 0xC5, 0x11, 0xE5, 0xF3, 0x71, 0x26, 0xE5, 0xD5, 0x05, 0x51, 0x66, - 0xDE, 0x4B, 0x8E, 0x8C, 0xE3, 0x2D, 0xA6, 0xB9, 0xB7, 0x37, 0x8F, 0xAE, 0xB2, 0xB9, 0xB5, 0x00, - 0xCA, 0xC5, 0xC2, 0x5E, 0x5D, 0x0C, 0x79, 0x7D, 0x22, 0xCD, 0x95, 0xFC, 0x22, 0x1A, 0x5E, 0x86, - 0x36, 0x97, 0xFE, 0xA2, 0xC4, 0x5E, 0x8A, 0x05, 0xDE, 0x03, 0x39, 0x2C, 0x3C, 0x3C, 0xCB, 0xB2, - 0x76, 0x0F, 0xFF, 0x1F, 0xFC, 0x51, 0x1D, 0xD3, 0x31, 0x95, 0x00 + 0x13, 0x95, 0x53, 0x09, 0x11, 0x9D, 0xE3, 0x51, 0x13, 0x53, 0x7E, 0x18, 0xAB, 0xDD, 0x9C, 0xCA, + 0x01, 0xD6, 0x89, 0x47, 0x79, 0x4E, 0x65, 0x99, 0x4D, 0x09, 0x7B, 0x6F, 0xBD, 0x53, 0x02, 0x20, + 0x21, 0xA0, 0xD7, 0xAF, 0x33, 0xF1, 0xB0, 0x7B, 0x94, 0x6F, 0x61, 0xC5, 0x18, 0x6A, 0xFE, 0x56, + 0xC1, 0x24, 0xA4, 0x57, 0xFB, 0xC7, 0x14, 0xDC, 0x9F, 0x6B, 0x87, 0xAD, 0xD5, 0xF5, 0xF2, 0xAC, + 0xBE, 0xCC, 0xEF, 0x2D, 0xFC, 0xA7, 0x60, 0x8D, 0x83, 0x21, 0x1B, 0x79, 0xD6, 0xA5, 0xDE, 0x84, + 0x58, 0x68, 0x3D, 0x77, 0xFE, 0x05, 0x6D, 0x58, 0x22, 0xDD, 0x1F, 0xF6, 0xEC, 0x7B, 0xD9, 0x33, + 0x1E, 0x2D, 0x82, 0xB6, 0x28, 0xCF, 0x5E, 0x25, 0xB5, 0x2E, 0xDF, 0xBD, 0xDB, 0xAB, 0x3F, 0xE8, + 0x17, 0xE0, 0x4A, 0xCE, 0x65, 0xE4, 0xFC, 0x0B, 0x4C, 0xF3, 0xE2, 0x2C, 0x8B, 0x2F, 0x97, 0x8C, + 0x8C, 0x64, 0x2A, 0xB5, 0x3C, 0x42, 0x6C, 0x11, 0xC8, 0x42, 0xC6, 0x57, 0xAB, 0xBD, 0xE2, 0xC6, + 0x7B, 0xFC, 0x60, 0x4A, 0x0C, 0x8B, 0x4E, 0xF3, 0xF5, 0x87, 0xEB, 0xEB, 0x57, 0x6B, 0xFC, 0x6B, + 0x45, 0xE0, 0x6E, 0xF3, 0x35, 0x57, 0xB3, 0x6E, 0x4D, 0x04, 0xBD, 0x08, 0x41, 0xAF, 0x34, 0x82, + 0x35, 0x2E, 0xB5, 0x72, 0x43, 0x4C, 0xD7, 0x57, 0x18, 0x1E, 0x7D, 0xEB, 0x96, 0xB2, 0x68, 0x17, + 0x14, 0x3B, 0x8B, 0x42, 0x64, 0xBC, 0x10, 0x2B, 0x20, 0x77, 0x14, 0xA3, 0x55, 0x9A, 0x21, 0x8B, + 0xA4, 0xC7, 0x2A, 0xBC, 0xE4, 0x9E, 0x86, 0x6D, 0x05, 0xFF, 0x0D, 0xD4, 0x75, 0xBD, 0x10, 0x0B, + 0xC8, 0x15, 0xA5, 0x2E, 0xB1, 0x6C, 0x9B, 0x07, 0xAC, 0xC4, 0x5B, 0x2C, 0xEA, 0x4A, 0x53, 0xCF, + 0xCB, 0xC2, 0x37, 0x2B, 0xA4, 0x4E, 0xD5, 0x06, 0x48, 0x3A, 0x59, 0x4B, 0x9D, 0xED, 0x0D, 0x81, + 0x9F, 0x07, 0x73, 0xD9, 0x45, 0xFE, 0x8D, 0x54, 0xAD, 0x94, 0x7F, 0x21, 0xD5, 0x9F, 0x93, 0x7B, + 0xF1, 0x54, 0x2D, 0x4D, 0x6A, 0x03, 0x83, 0x8C, 0xC3, 0xD5, 0xF5, 0xB2, 0x56, 0x26, 0xBD, 0xFD, + 0xC1, 0xCD, 0x47, 0xB6, 0xF9, 0x79, 0x2D, 0x82, 0xFF, 0xB3, 0xEC, 0x4B, 0x59, 0xF3, 0xC2, 0x67, + 0xD6, 0x8C, 0xED, 0x97, 0x66, 0xE6, 0x7E, 0x4E, 0x65, 0x6B, 0x3A, 0xEB, 0x48, 0x8B, 0xCF, 0x53, + 0xE6, 0x34, 0xD2, 0x94, 0x44, 0x46, 0xA5, 0x86, 0x9A, 0x9A, 0xDD, 0xA8, 0xCE, 0x58, 0x93, 0x6E, + 0x66, 0x88, 0x84, 0x40, 0xF7, 0xE9, 0xC1, 0xA6, 0xE6, 0x0F, 0xCA, 0x19, 0x10, 0x49, 0xA5, 0x08, + 0x59, 0xE4, 0x76, 0x83, 0xFF, 0x9B, 0xE1, 0x74, 0x27, 0x30, 0x62, 0x7C, 0xA8, 0x94, 0x32, 0x87, + 0x48, 0x9A, 0xA9, 0x68, 0xA4, 0xA8, 0x18, 0xD3, 0x83, 0x05, 0x85, 0x60, 0xCE, 0x97, 0x14, 0x6D, + 0x3E, 0xBC, 0x32, 0xA7, 0x5B, 0x32, 0xB9, 0xED, 0x19, 0x88, 0x58, 0x57, 0x18, 0xD8, 0x33, 0x84, + 0x40, 0xE4, 0x64, 0x66, 0xD2, 0xD1, 0x44, 0x52, 0x2D, 0xBC, 0x1C, 0x63, 0x20, 0x22, 0x65, 0x5A, + 0xB9, 0xF0, 0x3C, 0x32, 0xB6, 0xDC, 0x7B, 0x99, 0x34, 0x09, 0x78, 0x1B, 0x1B, 0x55, 0x94, 0x07, + 0xD5, 0xCF, 0x71, 0x87, 0x52, 0xDA, 0x2A, 0xC3, 0x21, 0x67, 0xBA, 0x52, 0x95, 0x9D, 0x4B, 0x37, + 0x01, 0xCB, 0x3C, 0xAF, 0x4E, 0xD7, 0xA9, 0x7C, 0x18, 0xC8, 0x22, 0x1A, 0x73, 0xDB, 0x91, 0xAE, + 0x53, 0xA5, 0x19, 0x5E, 0x68, 0x45, 0x60, 0x59, 0x87, 0x9A, 0xA9, 0x2A, 0x15, 0x1B, 0x21, 0x42, + 0x08, 0x8E, 0xA0, 0xAB, 0x93, 0xA0, 0x03, 0xD3, 0xD1, 0xBE, 0xB1, 0x62, 0x3B, 0xF0, 0x07, 0xD5, + 0x0F, 0xE6, 0x53, 0x29, 0x8E, 0x4C, 0x47, 0xE8, 0xA6, 0x3C, 0x48, 0xD5, 0xCE, 0x26, 0x44, 0x86, + 0x41, 0xD3, 0xE9, 0x44, 0x9C, 0x7B, 0xB0, 0x06, 0x46, 0x0F, 0x03, 0x6D, 0xCC, 0x28, 0x79, 0xF2, + 0xC2, 0x6A, 0x91, 0x15, 0xF4, 0xCA, 0xF3, 0xC2, 0x13, 0xC7, 0x9D, 0x86, 0x34, 0xC8, 0x3F, 0x8B, + 0xCB, 0x38, 0xF3, 0xD2, 0x30, 0xB4, 0xF9, 0xB4, 0x63, 0xD8, 0x31, 0x57, 0xAF, 0xEC, 0x61, 0x54, + 0xA5, 0x08, 0x8E, 0x68, 0x8B, 0x29, 0xC9, 0x98, 0x66, 0x47, 0x8A, 0x7D, 0x8F, 0xE1, 0xC6, 0x78, + 0x59, 0x9A, 0x01, 0x1F, 0x50, 0x8C, 0x60, 0x0E, 0x4A, 0x64, 0x4B, 0xA8, 0xC6, 0x7C, 0xA7, 0x3A, + 0xEB, 0x22, 0xB3, 0x5E, 0xC6, 0x9D, 0x90, 0x3A, 0xBC, 0x3F, 0xC8, 0xE9, 0xA3, 0xF6, 0x79, 0xE2, + 0x2E, 0x98, 0x8A, 0xA3, 0x7C, 0x59, 0x63, 0x9C, 0x99, 0x31, 0x4B, 0x28, 0x5E, 0x27, 0x85, 0xB1, + 0x11, 0x14, 0x74, 0xB5, 0xE5, 0x86, 0xD4, 0x75, 0xAD, 0xF7, 0xD4, 0x19, 0xDE, 0x84, 0x97, 0xE3, + 0xB1, 0x79, 0x9C, 0x69, 0xB5, 0xD4, 0x0E, 0x25, 0x6B, 0x18, 0x90, 0xCE, 0xB2, 0x85, 0x99, 0x45, + 0x2D, 0x33, 0xCC, 0x9C, 0x37, 0x98, 0xE7, 0x69, 0x00, 0x60, 0xFC, 0x4A, 0xE5, 0xD5, 0x34, 0x0C, + 0xE5, 0x38, 0xEB, 0x72, 0x79, 0xA5, 0x42, 0xFF, 0xDE, 0xDC, 0x7D, 0x78, 0x0E, 0x9D, 0xA7, 0x3B, + 0x0F, 0xE0, 0xF7, 0x84, 0x83, 0x1B, 0xB2, 0x44, 0x71, 0xB3, 0xC0, 0x3C, 0x11, 0x4A, 0x33, 0x4C, + 0x1F, 0xFC, 0x9E, 0x0B, 0x40, 0x42, 0x9C, 0x20, 0x80, 0x9F, 0x2C, 0x62, 0xFE, 0xE8, 0x20, 0xCA, + 0xEF, 0x55, 0x25, 0x54, 0x3D, 0x3F, 0x01, 0x57, 0xC9, 0xF6, 0x18, 0x14, 0xAA, 0x46, 0x83, 0xD8, + 0xC5, 0xD4, 0xCA, 0x2D, 0x92, 0xFA, 0x71, 0x6F, 0x34, 0x22, 0x3E, 0x1D, 0x4E, 0x47, 0x98, 0x31, + 0x8D, 0x39, 0xB9, 0xBC, 0x4F, 0x63, 0x17, 0x53, 0xEB, 0xCE, 0x0A, 0x6D, 0xCD, 0x34, 0x15, 0x15, + 0xDB, 0x79, 0x54, 0xA3, 0xBF, 0x1E, 0x4C, 0xC9, 0xE8, 0xA2, 0x9B, 0x3E, 0x04, 0x23, 0x74, 0x68, + 0x72, 0x43, 0x8A, 0x9D, 0xED, 0xF3, 0x10, 0xA5, 0xFD, 0x1B, 0xCB, 0x1D, 0x52, 0xB1, 0x5C, 0xD4, + 0x22, 0x10, 0x9A, 0xCD, 0x9D, 0x67, 0x89, 0x65, 0x81, 0x21, 0x2E, 0xC2, 0x9A, 0x4E, 0x82, 0xA1, + 0xA1, 0xA6, 0x60, 0xE0, 0xC0, 0x43, 0xD7, 0x7C, 0xCA, 0x13, 0x8D, 0x81, 0xF2, 0xE0, 0xCD, 0x0B, + 0xF0, 0xD8, 0x7D, 0x8C, 0xDC, 0x02, 0x6F, 0x99, 0xDC, 0x81, 0x57, 0x9E, 0x4C, 0x47, 0xD0, 0x05, + 0xD7, 0xDE, 0xB3, 0xC8, 0x34, 0xEB, 0x69, 0xCA, 0xF8, 0x20, 0x90, 0xE5, 0x95, 0x99, 0x00, 0x34, + 0xE9, 0xE0, 0xB7, 0x1E, 0xB8, 0x50, 0xD0, 0x77, 0xFC, 0xFA, 0x06, 0x67, 0x24, 0xE9, 0xD3, 0x61, + 0x3A, 0xFB, 0xC8, 0xFB, 0xDF, 0xA1, 0x35, 0xB6, 0x13, 0x4C, 0xB0, 0x8F, 0x58, 0xC6, 0x61, 0x0C, + 0x9C, 0x25, 0xFB, 0xD3, 0x00, 0xCC, 0x1B, 0xFF, 0x1B, 0x56, 0x19, 0x28, 0xA6, 0xE6, 0xB2, 0xD4, + 0x0B, 0x06, 0x4C, 0x7D, 0x3A, 0xA8, 0x8D, 0x0A, 0xEF, 0xCF, 0xE0, 0xBC, 0xDC, 0x17, 0xB7, 0xB4, + 0x66, 0x46, 0xF4, 0x16, 0xE7, 0xD0, 0xDA, 0x58, 0xD8, 0x0C, 0xFC, 0x86, 0x5D, 0x20, 0x94, 0x93, + 0x25, 0xF2, 0x70, 0x8D, 0xF9, 0xE2, 0x7C, 0x47, 0xBD, 0xDA, 0x28, 0xF9, 0x44, 0x74, 0x1A, 0xFA, + 0xCE, 0xA4, 0x4F, 0x41, 0x70, 0xFE, 0x3C, 0x30, 0xED, 0x8F, 0x1C, 0x16, 0xFF, 0x59, 0x13, 0x13, + 0x5E, 0x9F, 0xC2, 0x9B, 0x2A, 0x38, 0xB4, 0x5C, 0x8C, 0x2D, 0x9F, 0x89, 0xA3, 0x33, 0xCF, 0x71, + 0xC3, 0x33, 0xEA, 0x5F, 0xC3, 0x1A, 0x41, 0x5A, 0x0D, 0xCD, 0x88, 0xF5, 0x30, 0xBA, 0x64, 0x39, + 0x65, 0x16, 0x7D, 0x2E, 0xB8, 0xDE, 0x8B, 0xB8, 0x6C, 0x9E, 0xB4, 0xDB, 0x1B, 0x0E, 0x59, 0x0C, + 0xF5, 0x6C, 0xA8, 0x83, 0xC9, 0xA9, 0x77, 0x37, 0x23, 0x92, 0x63, 0xCF, 0xB7, 0x6A, 0xA3, 0x10, + 0xFE, 0xC3, 0xD9, 0x0D, 0xAA, 0x2D, 0xC5, 0x03, 0x21, 0xE6, 0x6A, 0xCC, 0xC8, 0xD0, 0x3C, 0x64, + 0x23, 0xB0, 0x9C, 0x1F, 0x9D, 0x1E, 0xFE, 0x3A, 0x23, 0xAA, 0xBD, 0xF3, 0xB3, 0xF9, 0xF0, 0x84, + 0x1E, 0xE1, 0xDB, 0x38, 0x2E, 0xD4, 0x66, 0x67, 0xA7, 0x33, 0x23, 0x8C, 0x7C, 0xD3, 0x7A, 0x78, + 0xB2, 0xEE, 0xB2, 0x56, 0x42, 0x18, 0x63, 0xE4, 0xD3, 0x09, 0x5A, 0x41, 0xCC, 0xE0, 0x2D, 0x2F, + 0x3E, 0x79, 0x49, 0x14, 0x51, 0xA6, 0x97, 0x86, 0x03, 0x61, 0x55, 0xDE, 0xA0, 0xB3, 0xA1, 0x95, + 0x70, 0xCB, 0x95, 0x2A, 0x99, 0xDA, 0x93, 0xD4, 0x37, 0xFB, 0x66, 0x30, 0x39, 0x14, 0x17, 0xB2, + 0xD3, 0xD4, 0x61, 0x11, 0x86, 0x8B, 0xA6, 0x74, 0xC1, 0x7E, 0x6A, 0x87, 0xC9, 0x49, 0xF0, 0x3E, + 0x28, 0xF9, 0xE7, 0x99, 0x83, 0x0F, 0xEE, 0x86, 0x98, 0x74, 0x85, 0x6B, 0x13, 0x84, 0xF7, 0xE0, + 0x54, 0xA0, 0xC0, 0x46, 0x2C, 0xB9, 0x7F, 0xC3, 0xF5, 0x5C, 0xDA, 0x50, 0x33, 0xD7, 0xB3, 0x65, + 0x4D, 0x31, 0xE4, 0x15, 0xF8, 0xF8, 0x5F, 0x39, 0x28, 0x78, 0xD5, 0x3E, 0xC5, 0x79, 0x7C, 0xBF, + 0xFF, 0x33, 0x5E, 0x17, 0x45, 0x5F, 0x41, 0x5C, 0x6C, 0x64, 0xD9, 0x6A, 0x25, 0xDC, 0x22, 0x93, + 0x77, 0x9C, 0xA9, 0x9F, 0xA7, 0xF7, 0x66, 0x55, 0x11, 0x58, 0xDA, 0xF4, 0x5D, 0x5B, 0x3B, 0x4A, + 0xDC, 0xBA, 0xB8, 0xEE, 0x60, 0x14, 0x88, 0xD4, 0xF9, 0x98, 0x4D, 0x3B, 0x4E, 0xA8, 0xFA, 0x8F, + 0x29, 0x2C, 0xC2, 0x79, 0xAE, 0x78, 0xCF, 0x07, 0xD7, 0x70, 0xA9, 0xD1, 0x96, 0x0F, 0x0E, 0x5B, + 0xA4, 0xAD, 0x9C, 0x92, 0x34, 0x72, 0xB2, 0xF4, 0x4A, 0x14, 0xC4, 0x16, 0x16, 0x7C, 0x5F, 0x59, + 0x91, 0xBD, 0x17, 0x89, 0xE1, 0x95, 0x5D, 0x19, 0xE0, 0xF3, 0xB7, 0x2F, 0x6D, 0x91, 0x72, 0x97, + 0x45, 0x91, 0xAB, 0x25, 0xDC, 0xAF, 0x64, 0x85, 0x51, 0x8F, 0x3D, 0x4B, 0x2D, 0x4A, 0x5A, 0x86, + 0x35, 0xC9, 0xDA, 0xDA, 0x39, 0x1D, 0x7B, 0xB7, 0x94, 0x05, 0xC2, 0xE1, 0x6E, 0x13, 0xC6, 0xCB, + 0xB1, 0x3F, 0x78, 0x79, 0x55, 0xA1, 0x24, 0x3B, 0xC0, 0x2F, 0x5D, 0x2F, 0x5C, 0x6A, 0xEB, 0x51, + 0x78, 0xCB, 0x91, 0xBC, 0x7C, 0xF9, 0xDA, 0xF7, 0xE3, 0x0A, 0x2B, 0x5A, 0x70, 0xA4, 0xC5, 0x65, + 0xE2, 0x43, 0x0E, 0x34, 0x2D, 0xC5, 0x87, 0x12, 0xB7, 0x0A, 0x44, 0x30, 0xE7, 0x6E, 0xB3, 0xD5, + 0x84, 0x9F, 0x12, 0x2A, 0xE0, 0xA3, 0x1A, 0xFD, 0x38, 0x10, 0xB5, 0x12, 0x0F, 0x71, 0x7C, 0xAB, + 0x89, 0x8F, 0xA8, 0xB0, 0x3C, 0x2F, 0xB9, 0xDB, 0xB1, 0x45, 0x2C, 0x19, 0xF6, 0xB0, 0x59, 0x94, + 0x97, 0x19, 0x29, 0x67, 0x8A, 0xF3, 0x9B, 0xB3, 0xF5, 0x6A, 0xE6, 0x5D, 0x5B, 0xE2, 0xB8, 0xE0, + 0x49, 0x0E, 0xF9, 0x2A, 0x29, 0xE1, 0x29, 0xF5, 0x4E, 0x07, 0x1A, 0x90, 0x25, 0xA5, 0xFC, 0x59, + 0x14, 0xC7, 0x29, 0xBD, 0x10, 0x00, 0xC2, 0x48, 0xDE, 0x10, 0x58, 0x8A, 0x0A, 0x5B, 0xA4, 0xD7, + 0xE9, 0x74, 0x96, 0xD3, 0xD6, 0x8E, 0x1D, 0xDA, 0x83, 0x95, 0x6B, 0x11, 0xB6, 0xB0, 0xC3, 0x53, + 0x07, 0xC5, 0xFA, 0x61, 0x1B, 0xF9, 0xC1, 0xBE, 0xB6, 0x5C, 0xC2, 0xC8, 0x69, 0x56, 0xF0, 0x92, + 0xA0, 0x08, 0x62, 0x68, 0x24, 0x11, 0x53, 0x18, 0x8C, 0xA8, 0xE5, 0x47, 0x24, 0xCA, 0xE1, 0x6D, + 0xA6, 0x79, 0xEC, 0x4F, 0x07, 0x03, 0x58, 0xDD, 0x31, 0x2E, 0xA5, 0xB4, 0xE5, 0x31, 0x1E, 0x51, + 0x6E, 0xE2, 0xB0, 0xC9, 0x33, 0x97, 0xA7, 0x99, 0x4A, 0x70, 0x96, 0x45, 0x67, 0x60, 0x0C, 0x56, + 0x91, 0x11, 0x53, 0x42, 0x7E, 0xD1, 0x72, 0x2E, 0x7E, 0xC0, 0xE5, 0x5A, 0xAC, 0x98, 0x4D, 0x2B, + 0xC1, 0xF4, 0x4A, 0x3C, 0xDA, 0x71, 0xC0, 0x33, 0x2B, 0x9C, 0x7F, 0xDB, 0x3E, 0x33, 0x7E, 0x4B, + 0x22, 0xC2, 0x22, 0xE6, 0x6C, 0x27, 0x1F, 0x0A, 0x2F, 0x4E, 0x2A, 0x41, 0x19, 0xC6, 0xED, 0x5F, + 0xBE, 0xA0, 0xFF, 0xA7, 0xB2, 0xFA, 0xD6, 0xF6, 0x0B, 0x2A, 0x73, 0x98, 0x22, 0x57, 0xC4, 0x9F, + 0xA1, 0x49, 0xF9, 0x1C, 0x1A, 0x2E, 0x3B, 0x64, 0xF6, 0xB4, 0xE8, 0xA3, 0x44, 0xC7, 0x25, 0xED, + 0x91, 0xFB, 0xAF, 0x21, 0x14, 0x59, 0xE4, 0xB9, 0x8F, 0xEF, 0x35, 0xE9, 0x4A, 0x23, 0xF5, 0xB7, + 0xE6, 0x22, 0x18, 0x34, 0x85, 0xBD, 0x09, 0x83, 0x78, 0xD9, 0xA5, 0x0A, 0xBE, 0x83, 0x29, 0xE1, + 0x43, 0x1B, 0x2F, 0x1F, 0x71, 0x7F, 0x7C, 0xF3, 0xAB, 0xA4, 0x8C, 0xAC, 0x58, 0xCC, 0x09, 0xAC, + 0x98, 0xD1, 0xED, 0xC0, 0x30, 0xDE, 0xDC, 0x04, 0x7E, 0x4F, 0xC0, 0xC9, 0xC3, 0xAC, 0x12, 0x57, + 0x34, 0xBC, 0xC3, 0x63, 0xC1, 0x0E, 0xDB, 0xFB, 0x81, 0xB2, 0x46, 0x0B, 0xED, 0xD8, 0x68, 0x64, + 0x4D, 0x02, 0x8A, 0x09, 0xFA, 0x78, 0x86, 0x0D, 0xB6, 0xDB, 0xA1, 0xAA, 0xAF, 0x89, 0x3E, 0xAE, + 0x6B, 0x17, 0xC9, 0x03, 0xE2, 0x2F, 0xE6, 0x03, 0x13, 0x7C, 0x95, 0xE1, 0x62, 0x2B, 0x9B, 0x89, + 0xAD, 0x59, 0xE4, 0x80, 0xF4, 0xCB, 0x4A, 0xA2, 0x1E, 0x0F, 0x46, 0x39, 0x88, 0x8A, 0x7D, 0x3E, + 0x8F, 0x80, 0xE1, 0x1E, 0xF0, 0x5B, 0xCF, 0x03, 0x58, 0x87, 0xC8, 0x26, 0x59, 0x14, 0x98, 0x86, + 0x20, 0xAA, 0x74, 0x34, 0x90, 0xA0, 0x26, 0x87, 0x34, 0x0D, 0x55, 0x98, 0x7E, 0x56, 0x59, 0xE9, + 0x2A, 0x7A, 0x84, 0x15, 0x41, 0xA6, 0x93, 0x3C, 0x00, 0x3E, 0xB4, 0xD3, 0x04, 0xE4, 0xB6, 0x82, + 0x33, 0xE8, 0xA0, 0x4B, 0xFF, 0xD6, 0xA1, 0x23, 0x3B, 0x58, 0x4A, 0x9E, 0xA1, 0xD8, 0x17, 0x42, + 0x10, 0x5E, 0xF4, 0x20, 0x49, 0x01, 0xA2, 0x8B, 0x27, 0x16, 0xAC, 0xD8, 0xCF, 0x13, 0x99, 0x64, + 0x40, 0xE2, 0xD1, 0xA6, 0x20, 0x52, 0x8F, 0xDC, 0xB7, 0x4C, 0xE8, 0xA4, 0x5B, 0x10, 0x14, 0x2F, + 0x5B, 0x57, 0x85, 0x43, 0x95, 0x12, 0xA0, 0xF0, 0x6B, 0x39, 0xE8, 0x37, 0x49, 0x52, 0x2B, 0x00, + 0x65, 0x29, 0xAE, 0xAA, 0x53, 0x65, 0x4A, 0x24, 0xC0, 0x4B, 0x53, 0x3E, 0x3B, 0x93, 0x04, 0x25, + 0xEF, 0xCA, 0x94, 0x83, 0x96, 0x72, 0x5F, 0x31, 0x04, 0xF8, 0x67, 0x29, 0xC8, 0x5F, 0x9C, 0xB7, + 0x4E, 0x02, 0x78, 0xE7, 0x5C, 0x3B, 0xE5, 0xE0, 0x2E, 0xF6, 0xCF, 0x3E, 0x1E, 0x48, 0x3C, 0xC3, + 0x4A, 0xF3, 0xA3, 0x3D, 0x29, 0x07, 0xCB, 0x2E, 0xB6, 0x26, 0xA0, 0xCC, 0x9F, 0x2F, 0x07, 0x99, + 0x5E, 0x6A, 0xDE, 0x27, 0x78, 0x24, 0x5F, 0xAF, 0x1C, 0xB6, 0xFE, 0x7D, 0x10, 0xD2, 0x71, 0x82, + 0x20, 0xE0, 0x7F, 0x97, 0x82, 0x3D, 0x54, 0x13, 0x97, 0x01, 0x74, 0x9C, 0xCA, 0xAC, 0x14, 0xFC, + 0xE9, 0x85, 0x24, 0x3C, 0xCC, 0x6E, 0x56, 0x0A, 0xEA, 0xAD, 0xF4, 0x56, 0x08, 0xC0, 0xC9, 0x4B, + 0xA4, 0x08, 0x9E, 0x3B, 0x0B, 0xFA, 0xEC, 0xC6, 0x47, 0xB1, 0x18, 0x92, 0x84, 0x53, 0x4E, 0x19, + 0x50, 0x9E, 0x86, 0x21, 0xB9, 0xD4, 0x8C, 0xC7, 0xC6, 0x2D, 0x7C, 0xC2, 0x69, 0x63, 0x5B, 0x32, + 0xA6, 0x2C, 0xCD, 0xE8, 0xC6, 0x36, 0x40, 0x5A, 0xBE, 0x35, 0xC0, 0xB3, 0x34, 0xD9, 0x9C, 0xAA, + 0xA3, 0x7E, 0x39, 0x26, 0xCD, 0x72, 0xD2, 0x66, 0xD0, 0xE5, 0x86, 0xDB, 0xB0, 0x73, 0xDE, 0xC2, + 0xC7, 0x76, 0x3A, 0x9D, 0x6E, 0xAF, 0xC5, 0x5E, 0x0B, 0x4A, 0xDB, 0x73, 0x5E, 0xCA, 0xAC, 0x7A, + 0xB7, 0xC3, 0x00, 0x4C, 0x06, 0x24, 0x92, 0x2A, 0x92, 0xDC, 0x97, 0x93, 0x72, 0xB1, 0x5D, 0x8A, + 0x4C, 0x76, 0x78, 0x26, 0xAD, 0x06, 0x9B, 0x4E, 0xB6, 0x3B, 0x99, 0xD3, 0xC9, 0x76, 0xA7, 0x04, + 0xD9, 0x14, 0xEA, 0xFD, 0xD3, 0x0F, 0x33, 0x61, 0x8E, 0x7D, 0xD8, 0xAC, 0xED, 0xE5, 0xF8, 0x6C, + 0x2C, 0xED, 0xDD, 0x9A, 0xFA, 0xDC, 0x4D, 0x80, 0xF7, 0x2D, 0x90, 0x90, 0xFF, 0xDE, 0x0B, 0x42, + 0xD1, 0xFB, 0x9B, 0xA9, 0xDE, 0xDF, 0xCC, 0xE8, 0xFD, 0x74, 0xEB, 0x33, 0x24, 0x90, 0x22, 0x87, + 0x16, 0x8C, 0x93, 0xDB, 0xC6, 0x7F, 0x3A, 0x45, 0xF6, 0xB1, 0x1A, 0x25, 0x43, 0xCB, 0xD8, 0x53, + 0x41, 0x6C, 0xCF, 0x9B, 0x93, 0x5A, 0xEF, 0xE8, 0x74, 0xD6, 0x3B, 0xB5, 0x5B, 0xC6, 0xDB, 0xF1, + 0x31, 0xA0, 0x7E, 0xB6, 0x34, 0xD3, 0x05, 0x58, 0x9F, 0x19, 0xC1, 0xF0, 0x6B, 0x6F, 0xE8, 0xB5, + 0x07, 0xDE, 0x18, 0xFF, 0xC2, 0xAF, 0x64, 0x8C, 0x8C, 0x61, 0x46, 0x54, 0x30, 0x2C, 0x0E, 0x78, + 0xAC, 0x63, 0xCB, 0x19, 0x61, 0x98, 0x99, 0x0F, 0x3E, 0x51, 0x3E, 0x6B, 0xD1, 0x79, 0x1D, 0xE1, + 0xE7, 0x65, 0x18, 0x34, 0x79, 0x07, 0xB6, 0x52, 0x1C, 0xFB, 0x61, 0xE0, 0x9B, 0x48, 0xA3, 0x16, + 0x10, 0xB0, 0x59, 0xB4, 0x4D, 0x38, 0x3D, 0xEB, 0x9E, 0xDC, 0x59, 0x60, 0x32, 0x40, 0x0E, 0xB6, + 0x13, 0xB0, 0x48, 0xBF, 0xD3, 0x8B, 0xF3, 0xA3, 0x33, 0xDC, 0xF6, 0x61, 0xC1, 0x6E, 0x23, 0x8F, + 0x73, 0x43, 0xE8, 0x37, 0xF0, 0x28, 0x70, 0x23, 0x2D, 0xCA, 0x14, 0xD6, 0x8E, 0x28, 0x4A, 0xCB, + 0x14, 0xF8, 0x8B, 0xEF, 0x03, 0xE1, 0x4A, 0x93, 0xCB, 0x28, 0x47, 0x32, 0x92, 0x00, 0x44, 0x2B, + 0xCA, 0xC1, 0x0B, 0xC5, 0xE9, 0x75, 0x3B, 0xDD, 0x92, 0x70, 0x8A, 0x16, 0x34, 0xAE, 0x46, 0xB6, + 0x7F, 0xD9, 0x9F, 0x58, 0xFE, 0xD7, 0xB7, 0x53, 0xB7, 0xDB, 0xA8, 0x8C, 0xE3, 0xEC, 0x97, 0x6A, + 0xFC, 0x46, 0x1D, 0x1E, 0xD2, 0x20, 0xFC, 0x3F, 0xF8, 0xA3, 0x7A, 0x93, 0x11, 0x05, 0x90, 0x05, + 0x24, 0x1A, 0xDC, 0x50, 0x1D, 0x59, 0x17, 0x22, 0x49, 0xDD, 0xBB, 0x77, 0x7B, 0x19, 0x81, 0x23, + 0x00, 0xA7, 0x6D, 0xF7, 0xA1, 0x7F, 0x07, 0x0B, 0x8E, 0x38, 0x33, 0x77, 0xB2, 0xD1, 0xB9, 0xB6, + 0x36, 0x66, 0x8B, 0x3E, 0xAC, 0xE1, 0xD8, 0x01, 0x09, 0x42, 0xCB, 0x67, 0x3A, 0xC0, 0x94, 0x4A, + 0xBB, 0x5D, 0xF7, 0xEC, 0x3B, 0x65, 0x85, 0xC3, 0xA5, 0x5D, 0xC2, 0x4A, 0xFE, 0xC6, 0x63, 0x93, + 0xA7, 0xDC, 0x70, 0xEC, 0x7F, 0xDB, 0xD5, 0xB8, 0xFF, 0x22, 0x2F, 0x7A, 0x4D, 0xBB, 0x59, 0x12, + 0x89, 0xAC, 0x2D, 0x2C, 0x73, 0x90, 0xB1, 0x04, 0xC8, 0x77, 0x1A, 0x77, 0xD2, 0xA1, 0x74, 0xFA, + 0xDA, 0xD3, 0x1C, 0x22, 0x2A, 0xE7, 0x4F, 0x2A, 0xDF, 0x31, 0x2C, 0x20, 0x7A, 0xBE, 0xD2, 0x62, + 0x28, 0x9F, 0x94, 0xC4, 0xD8, 0x1A, 0x31, 0x4F, 0x6A, 0x26, 0x9D, 0xC7, 0xC5, 0xA5, 0x41, 0xEB, + 0xAB, 0x25, 0x22, 0x97, 0xD8, 0x2F, 0x2D, 0x4D, 0xFD, 0x16, 0x5F, 0xA1, 0x28, 0xC7, 0xB5, 0xE4, + 0x38, 0xAE, 0x24, 0x44, 0xB6, 0xD4, 0x2F, 0x52, 0xBC, 0x19, 0x5B, 0x9B, 0x04, 0xF4, 0xFF, 0x8F, + 0x6A, 0x72, 0xB9, 0xF1, 0xF2, 0x58, 0x2D, 0xAE, 0x3A, 0x56, 0xD4, 0x17, 0x93, 0x78, 0xDA, 0xD3, + 0xE8, 0x2A, 0x63, 0xF1, 0x88, 0xC9, 0x79, 0x6F, 0x69, 0x06, 0xC9, 0xA6, 0x6E, 0xA0, 0x7E, 0x2F, + 0xE9, 0x2A, 0x3E, 0xAE, 0x04, 0x8B, 0xEB, 0x18, 0x70, 0x37, 0xF1, 0x6D, 0x06, 0xF3, 0x32, 0xA6, + 0xCB, 0x37, 0xA6, 0xB0, 0x3C, 0x77, 0x7F, 0x6C, 0xAE, 0x0A, 0xA9, 0xDF, 0xC3, 0xFD, 0x97, 0x94, + 0x5A, 0xB4, 0xA3, 0x97, 0xA1, 0xD4, 0x2C, 0xBD, 0xAE, 0xB4, 0x2C, 0x8D, 0x56, 0x54, 0x86, 0x80, + 0xA9, 0x92, 0x0B, 0x2A, 0xB1, 0xC0, 0xF1, 0xAE, 0x02, 0x14, 0x2E, 0xCB, 0x1F, 0x4D, 0x07, 0x9E, + 0x6B, 0xA3, 0xCB, 0xBE, 0xD5, 0x61, 0xCD, 0x31, 0x34, 0x66, 0xAB, 0x23, 0x1E, 0xEF, 0x90, 0x1B, + 0xF2, 0xC6, 0x98, 0x62, 0x3D, 0x9F, 0xD8, 0x99, 0x17, 0x38, 0xF8, 0xFF, 0xBD, 0xC1, 0x60, 0x0A, + 0xCB, 0x98, 0x7B, 0xBE, 0xD0, 0xD9, 0x44, 0x41, 0xA6, 0x88, 0x76, 0xDB, 0x8C, 0xEA, 0x66, 0x3B, + 0x87, 0x6A, 0x42, 0x56, 0xF1, 0x49, 0x59, 0xB4, 0xD5, 0x21, 0xCB, 0xF6, 0xD4, 0x52, 0xDE, 0x62, + 0x97, 0x19, 0x35, 0x43, 0x7C, 0x42, 0x08, 0xE9, 0x8D, 0xF6, 0x62, 0x88, 0xDF, 0x00, 0x42, 0x7A, + 0xBB, 0x3D, 0x1F, 0xE0, 0xD8, 0x0A, 0x59, 0xDE, 0xE9, 0x16, 0x7B, 0x6A, 0x7E, 0xBB, 0xD3, 0xDB, + 0xDE, 0x78, 0xBE, 0x5D, 0x00, 0xE2, 0xB9, 0x43, 0x01, 0xC3, 0x5F, 0xA1, 0x7F, 0xB1, 0xD9, 0xD9, + 0x7C, 0xBE, 0xD5, 0xCD, 0x87, 0xDA, 0x1B, 0x85, 0x4E, 0x38, 0xB5, 0xD9, 0x16, 0xC9, 0xE6, 0x16, + 0xD0, 0x7A, 0xB1, 0xAD, 0x2C, 0xBF, 0xB4, 0x03, 0x1B, 0x15, 0x43, 0x86, 0x7A, 0x64, 0x52, 0xCC, + 0xEF, 0x61, 0xE8, 0x41, 0xB9, 0xAB, 0x22, 0x25, 0xCE, 0x0F, 0xB3, 0xCB, 0xD1, 0xE7, 0x9A, 0xA2, + 0xAD, 0x2F, 0xDE, 0x4A, 0x22, 0x2E, 0xB0, 0x20, 0x9A, 0x6E, 0x3E, 0xEF, 0xB0, 0x7F, 0x2D, 0x12, + 0xFF, 0x12, 0x8F, 0x83, 0xA8, 0x0C, 0x07, 0x81, 0xF8, 0xB5, 0x78, 0xF8, 0x15, 0x11, 0xFD, 0xF4, + 0x3D, 0x88, 0xFE, 0xB6, 0x08, 0xA2, 0x0F, 0x79, 0xB1, 0xCA, 0xD5, 0xCD, 0x41, 0x3D, 0x93, 0x50, + 0xC9, 0x2C, 0xA4, 0xE5, 0x95, 0x04, 0x2D, 0x81, 0xB1, 0xFF, 0x99, 0xFA, 0x98, 0xDD, 0x1C, 0xBE, + 0xAD, 0xB1, 0xEB, 0x1F, 0xC9, 0x05, 0xFF, 0x52, 0x82, 0x96, 0xB4, 0x71, 0xB5, 0xDB, 0xED, 0xAC, + 0x6F, 0xB4, 0xC8, 0x8B, 0x17, 0xCA, 0xD6, 0x28, 0xFF, 0x8C, 0x42, 0xC6, 0x82, 0x12, 0x46, 0x35, + 0x83, 0x9C, 0x7E, 0xAF, 0x00, 0x09, 0x62, 0x66, 0xFB, 0x4D, 0x85, 0xD6, 0x26, 0xCB, 0x15, 0xBF, + 0x59, 0x5B, 0x7B, 0xCC, 0xD1, 0x87, 0x40, 0xAB, 0xC7, 0x67, 0xDC, 0x9E, 0x36, 0xF1, 0xF2, 0xEF, + 0x3C, 0xA1, 0x7D, 0xA7, 0x5D, 0x5A, 0x81, 0x1E, 0x32, 0xF7, 0x2A, 0xE3, 0xA0, 0xDA, 0x3A, 0x7B, + 0x95, 0x1C, 0x38, 0xD9, 0x43, 0xBA, 0xEC, 0x94, 0xDE, 0xAB, 0x96, 0xE1, 0x19, 0xD3, 0x9D, 0x32, + 0xBB, 0x95, 0x32, 0x41, 0xDC, 0x74, 0x8A, 0x08, 0xE6, 0xEF, 0x57, 0x96, 0xA7, 0x95, 0xD9, 0x3A, + 0xDC, 0xEE, 0x61, 0xC4, 0x3A, 0x5A, 0xEB, 0x3A, 0x33, 0xB6, 0x2E, 0x97, 0xE2, 0xD9, 0x2F, 0x8F, + 0x45, 0x33, 0xD9, 0x4B, 0x5B, 0x48, 0x1F, 0xE6, 0x52, 0x7C, 0xBC, 0x56, 0x4A, 0x9A, 0xDA, 0xAD, + 0x4F, 0xB1, 0x5B, 0x4B, 0x53, 0x05, 0x41, 0x5D, 0x53, 0x3B, 0xF9, 0x9A, 0xDA, 0xAD, 0xA7, 0xA9, + 0x8B, 0x68, 0x5D, 0x91, 0xA6, 0x3E, 0x12, 0x4D, 0x49, 0x53, 0x1F, 0x9D, 0xE2, 0xE3, 0xB5, 0x52, + 0xD2, 0xD4, 0x5E, 0x7D, 0x8A, 0xBD, 0x5A, 0x9A, 0xDA, 0xAB, 0xA5, 0xA9, 0xBD, 0x7A, 0x9A, 0xBA, + 0x88, 0xD6, 0x15, 0x69, 0xEA, 0x23, 0xD1, 0x94, 0x34, 0xF5, 0xD1, 0x29, 0x3E, 0x5E, 0x2B, 0x25, + 0x4D, 0x5D, 0xAF, 0x4F, 0x71, 0xBD, 0x96, 0xA6, 0xAE, 0xD7, 0xD2, 0xD4, 0xF5, 0x7A, 0x9A, 0xBA, + 0x88, 0xD6, 0x15, 0x69, 0xEA, 0x23, 0xD1, 0x94, 0x34, 0xF5, 0xD1, 0x29, 0xCE, 0xA9, 0x95, 0x4F, + 0xFD, 0xB8, 0xD5, 0xE8, 0x2A, 0x57, 0x3A, 0x70, 0x35, 0xFA, 0xBE, 0xA5, 0x8E, 0x5C, 0x8D, 0x8E, + 0x6C, 0xD5, 0xC3, 0xCF, 0x0C, 0xDF, 0xB4, 0x51, 0x16, 0x52, 0xF3, 0x30, 0xF9, 0x99, 0xAF, 0x7D, + 0xE7, 0x86, 0x77, 0x6E, 0xAF, 0x3A, 0x8E, 0x88, 0xFA, 0x2F, 0xE7, 0x9B, 0x77, 0xE7, 0xDE, 0xC6, + 0xFB, 0x6A, 0xFC, 0xC7, 0x1E, 0x60, 0xA3, 0x86, 0xD8, 0x99, 0x07, 0x50, 0x5D, 0xE6, 0x35, 0xC8, + 0x49, 0x8E, 0x55, 0x1D, 0x31, 0xD7, 0x84, 0xAB, 0x4A, 0x51, 0x73, 0x55, 0xEA, 0x88, 0xB4, 0x57, + 0x4F, 0xA4, 0xBD, 0xDA, 0x22, 0xED, 0xD5, 0x14, 0x69, 0xAF, 0xB6, 0x48, 0x7B, 0x35, 0x45, 0xBA, + 0x5E, 0x53, 0xA4, 0xEB, 0xF5, 0x44, 0xBA, 0x5E, 0x5B, 0xA4, 0xEB, 0x35, 0x45, 0xBA, 0x5E, 0x5B, + 0xA4, 0x3A, 0x64, 0x7C, 0xA0, 0x20, 0xDF, 0xA8, 0x35, 0x1D, 0x2C, 0x14, 0xDD, 0xBB, 0xCD, 0xD9, + 0x0A, 0x89, 0x32, 0x00, 0xB0, 0x0B, 0xF6, 0x12, 0x82, 0x03, 0xF6, 0x58, 0x8D, 0x08, 0xBC, 0xBB, + 0xF0, 0xBE, 0x52, 0x37, 0x4A, 0x44, 0xB1, 0xF3, 0x4C, 0xCB, 0x4D, 0x32, 0xA5, 0x71, 0x76, 0x6C, + 0xFD, 0xC1, 0x00, 0x63, 0x20, 0x60, 0x3E, 0x95, 0x16, 0x59, 0xDF, 0xE2, 0xFF, 0xC5, 0x53, 0xE7, + 0xFA, 0x56, 0x56, 0x5C, 0xE0, 0x99, 0x29, 0x44, 0x29, 0x77, 0x8F, 0xBC, 0x90, 0x7A, 0xA3, 0xA1, + 0xDF, 0xA7, 0x9D, 0x86, 0xDE, 0xDF, 0xE8, 0xFD, 0x39, 0x75, 0xE9, 0x9D, 0x35, 0xCA, 0x88, 0x79, + 0x91, 0xBA, 0xCA, 0xCF, 0xE9, 0x22, 0xFD, 0x12, 0x73, 0xB5, 0xE3, 0x1F, 0x2A, 0x43, 0xE3, 0x95, + 0x9F, 0x37, 0xFC, 0xCC, 0x85, 0x63, 0x63, 0x9B, 0x1C, 0x5B, 0x9D, 0xD4, 0x36, 0xAD, 0x78, 0xC1, + 0xBD, 0x85, 0x5F, 0xB5, 0x2D, 0xDA, 0x33, 0xF3, 0xEB, 0xB6, 0x45, 0xA4, 0x8F, 0x59, 0x6F, 0xCF, + 0x89, 0x60, 0x2C, 0x39, 0x0C, 0x1A, 0x2E, 0x0A, 0x22, 0xC5, 0x50, 0xE2, 0x53, 0x68, 0xB4, 0xE7, + 0x7F, 0xBD, 0xEC, 0xF4, 0xFB, 0x47, 0x07, 0xA5, 0x1D, 0x2D, 0x43, 0x68, 0xB2, 0x21, 0x94, 0xD2, + 0x48, 0xE7, 0xCC, 0x0A, 0x02, 0xF8, 0xCD, 0x7E, 0x04, 0x5A, 0xDD, 0x47, 0x6A, 0x53, 0xF7, 0x11, + 0xDB, 0xD4, 0x7B, 0xA4, 0x36, 0xF5, 0x1E, 0xB1, 0x4D, 0xEB, 0x8F, 0xD4, 0xA6, 0xF5, 0x39, 0xB5, + 0x49, 0x0C, 0xB1, 0x8B, 0xFD, 0xB3, 0xB5, 0x8F, 0x07, 0x67, 0xD9, 0xF6, 0xE9, 0x62, 0x50, 0x39, + 0xD6, 0x57, 0x18, 0x88, 0xF8, 0xBA, 0x78, 0x12, 0x73, 0xBB, 0xB5, 0xB9, 0xB9, 0x9E, 0x8A, 0xF2, + 0x65, 0x1F, 0x65, 0x46, 0x95, 0x98, 0xFF, 0x82, 0xF5, 0x56, 0x4C, 0x44, 0x8A, 0x23, 0x2E, 0x1F, + 0x45, 0x6E, 0xA2, 0xF4, 0x60, 0x16, 0x42, 0xD5, 0x43, 0x84, 0x44, 0x08, 0x1C, 0x72, 0x1E, 0x42, + 0x30, 0xB1, 0xF6, 0xD1, 0xAE, 0xCB, 0xDA, 0xD4, 0x9E, 0x3B, 0x6B, 0x6B, 0x6B, 0x1F, 0x5C, 0x12, + 0x5D, 0x59, 0x68, 0x11, 0xA8, 0x48, 0x78, 0xEF, 0xB0, 0x08, 0x0A, 0x4E, 0x8D, 0xBD, 0x87, 0x8C, + 0xCB, 0x4E, 0xC0, 0xCF, 0x9B, 0x60, 0xE3, 0x93, 0xCB, 0xB8, 0xFE, 0x0C, 0x30, 0x92, 0x23, 0x84, + 0x59, 0x2C, 0x8A, 0x9A, 0x98, 0x02, 0x12, 0xCF, 0x25, 0xA8, 0xB9, 0x2D, 0xAC, 0x71, 0x2F, 0x1E, + 0x53, 0x6E, 0xB7, 0xA3, 0x95, 0x29, 0x0F, 0xB6, 0x17, 0xD9, 0x2B, 0x4F, 0xA6, 0x21, 0xFD, 0x96, + 0x56, 0x5C, 0xBC, 0x34, 0xA1, 0x75, 0x23, 0x7C, 0xAA, 0xCD, 0x5C, 0x9E, 0x28, 0xA2, 0x1B, 0xEB, + 0xEC, 0x16, 0x7B, 0xE6, 0x98, 0x12, 0xC9, 0x3C, 0xAA, 0x75, 0xD7, 0x08, 0x80, 0xE2, 0x03, 0x76, + 0xF0, 0xE2, 0xDE, 0xFA, 0xF4, 0x1F, 0x53, 0xEA, 0xB2, 0x83, 0xF9, 0xED, 0xCE, 0x3A, 0xFC, 0xE8, + 0x3D, 0x97, 0xBA, 0x0E, 0x3E, 0xB1, 0x2D, 0xA2, 0xDE, 0x73, 0x99, 0x5F, 0xF9, 0x4A, 0x4C, 0xFE, + 0xF4, 0x8E, 0xE4, 0x40, 0x26, 0x8E, 0x35, 0x62, 0xF1, 0x3B, 0x16, 0xF3, 0x1C, 0xC5, 0xA5, 0xE2, + 0x4B, 0x1C, 0x44, 0xDD, 0x54, 0x90, 0x49, 0xD7, 0x14, 0x5C, 0x62, 0xA0, 0x98, 0x84, 0x7A, 0x49, + 0x59, 0x23, 0xF3, 0xEF, 0x6C, 0xA4, 0xEE, 0x57, 0x07, 0xC7, 0xCE, 0x35, 0x15, 0xBD, 0x81, 0x47, + 0x96, 0x3D, 0x99, 0x11, 0x7E, 0x62, 0xD9, 0x53, 0xF8, 0xC8, 0xBE, 0xD2, 0xB3, 0x2C, 0xE5, 0x5C, + 0x08, 0xA0, 0x23, 0x58, 0xCA, 0xA5, 0x7C, 0x76, 0xE6, 0x78, 0x70, 0xFA, 0x98, 0x07, 0xA6, 0xA2, + 0x99, 0xFC, 0x3E, 0x52, 0x9E, 0x7A, 0x46, 0x69, 0x54, 0xAA, 0x69, 0xE8, 0xD8, 0xFA, 0x06, 0xA0, + 0x17, 0x4E, 0x74, 0x9D, 0xA7, 0xDB, 0xD9, 0x84, 0x4E, 0x48, 0xF9, 0x81, 0xDD, 0x16, 0x7C, 0x6F, + 0xF5, 0x54, 0x35, 0x51, 0xEE, 0x48, 0xE5, 0x6B, 0x26, 0x27, 0x23, 0x7B, 0x9C, 0xB3, 0x12, 0x2A, + 0xB1, 0x48, 0x50, 0xDA, 0xB6, 0xD5, 0x21, 0x7F, 0x21, 0xBD, 0xEC, 0x00, 0x21, 0x8D, 0x43, 0xB5, + 0xBA, 0xF1, 0x9C, 0x5A, 0x49, 0x5E, 0x53, 0x4D, 0xEA, 0x09, 0x68, 0x14, 0x68, 0x17, 0xBB, 0xE1, + 0x69, 0x0F, 0x7C, 0x1E, 0xA2, 0x30, 0x13, 0xEC, 0xE4, 0x36, 0xCF, 0x94, 0x52, 0xA7, 0x5A, 0x33, + 0x2D, 0x09, 0x05, 0xB3, 0xF7, 0x51, 0x82, 0xC8, 0xE4, 0x70, 0xDC, 0x7C, 0x3A, 0xBE, 0x3D, 0x87, + 0x26, 0xE7, 0x10, 0x2F, 0x6C, 0x77, 0x2A, 0x2B, 0x65, 0xA9, 0xE6, 0xAA, 0x49, 0x30, 0xB9, 0x5F, + 0xD3, 0xDB, 0xDE, 0xD8, 0xDE, 0x7A, 0x9E, 0x72, 0x6E, 0xF8, 0xE7, 0x39, 0xB4, 0x52, 0xA7, 0xD9, + 0x61, 0xD1, 0x2C, 0xF8, 0x6C, 0x91, 0xD8, 0x37, 0x8E, 0x1A, 0x2A, 0xEC, 0x48, 0x34, 0xD1, 0xC7, + 0x0D, 0xCF, 0xBC, 0x83, 0x61, 0x6E, 0xEA, 0xD1, 0xD9, 0x1E, 0xBF, 0x65, 0xB4, 0x14, 0x5F, 0x6A, + 0x3C, 0x3A, 0x6B, 0x48, 0xED, 0x73, 0x5D, 0xB7, 0x2D, 0xFD, 0x27, 0x37, 0x51, 0xBB, 0x17, 0x99, + 0x61, 0x31, 0x0C, 0x14, 0x0E, 0x4E, 0xFB, 0x8B, 0x26, 0xF1, 0x0E, 0xF4, 0xFB, 0xCE, 0xBA, 0x5F, + 0x34, 0x99, 0xFE, 0xF4, 0x0A, 0x7E, 0xCE, 0x95, 0x4A, 0xB4, 0xB4, 0x17, 0x95, 0x4F, 0xC3, 0x89, + 0xF0, 0x0D, 0x3B, 0x69, 0xDF, 0xB0, 0x63, 0xF4, 0x0D, 0xCD, 0x74, 0xE2, 0x19, 0xFF, 0xF4, 0xE2, + 0xAC, 0xAE, 0xB6, 0xC4, 0xA7, 0x64, 0xC0, 0xD3, 0x68, 0x74, 0xF8, 0x6D, 0xE2, 0xB9, 0xDC, 0xB9, + 0x03, 0xD7, 0xA7, 0x2B, 0x8F, 0x0A, 0xE6, 0xF7, 0x74, 0x95, 0x01, 0x91, 0xDC, 0x82, 0x2D, 0x3A, + 0x82, 0x9B, 0x00, 0x37, 0x03, 0x87, 0x65, 0x87, 0x86, 0x09, 0x17, 0x2F, 0xEE, 0x29, 0x33, 0xED, + 0x3A, 0x6B, 0x75, 0xA7, 0x26, 0xEE, 0x73, 0x18, 0x5E, 0x07, 0x74, 0xC4, 0x54, 0xA3, 0xD3, 0x62, + 0x69, 0x5B, 0xB5, 0x8D, 0x12, 0x86, 0xBE, 0x6B, 0xDC, 0x28, 0xA9, 0x4A, 0xC7, 0x09, 0x26, 0x22, + 0xCD, 0xF5, 0x22, 0x88, 0x25, 0xE7, 0x5D, 0x93, 0x73, 0x7A, 0x4D, 0x7D, 0x70, 0x44, 0xE9, 0x91, + 0x2D, 0x0C, 0x55, 0xCA, 0x44, 0xB1, 0xE5, 0x57, 0x90, 0x4B, 0xE0, 0x21, 0xCA, 0x98, 0x91, 0xF1, + 0x96, 0xB1, 0x96, 0x3B, 0x03, 0xB3, 0x9A, 0x89, 0x2A, 0x52, 0x3A, 0x2D, 0x35, 0xAB, 0x80, 0x74, + 0x7B, 0x55, 0xBE, 0xA8, 0xBC, 0x4B, 0xBA, 0x4A, 0x0E, 0xA0, 0x38, 0x07, 0x4E, 0x13, 0x53, 0xE1, + 0xBF, 0x09, 0xDD, 0x26, 0xF0, 0x79, 0x06, 0x96, 0x11, 0x4C, 0x25, 0x33, 0x90, 0x2C, 0x2B, 0x88, + 0x84, 0x61, 0x05, 0x3E, 0xB0, 0x3F, 0x1B, 0xBA, 0x07, 0x10, 0xE5, 0x94, 0x89, 0x31, 0x49, 0x15, + 0x16, 0xFA, 0xF6, 0xF2, 0x83, 0x7A, 0x25, 0x42, 0x62, 0xF6, 0xF5, 0xDC, 0x5A, 0x1B, 0x3C, 0xC9, + 0xE6, 0xFE, 0x53, 0xD9, 0x99, 0x2D, 0x93, 0x10, 0xF6, 0xD8, 0xB3, 0x30, 0xDB, 0x52, 0x9B, 0x88, + 0x56, 0xDF, 0x59, 0x4E, 0x08, 0x0B, 0xCA, 0xA6, 0x1C, 0x84, 0x6E, 0xD6, 0x41, 0xF3, 0xAD, 0x87, + 0xE8, 0xCA, 0x43, 0xBA, 0xA1, 0x2F, 0x23, 0xE6, 0xE3, 0x7D, 0xF2, 0x67, 0xF2, 0xDB, 0x9B, 0x3C, + 0x17, 0x9C, 0xEE, 0x44, 0xAA, 0x9D, 0x23, 0x15, 0xCB, 0x89, 0x90, 0xE4, 0xCE, 0xEB, 0x5B, 0xB7, + 0xD8, 0x9C, 0x76, 0x5B, 0x09, 0xF9, 0xD4, 0xB2, 0x46, 0x35, 0x92, 0xCC, 0xB7, 0xAD, 0x3C, 0xC1, + 0xB7, 0x14, 0x24, 0x43, 0x9A, 0x95, 0x67, 0x23, 0x95, 0xF1, 0x43, 0x4E, 0x3D, 0x32, 0x4B, 0xC6, + 0x8D, 0xD9, 0xB3, 0x6E, 0xCC, 0x92, 0x79, 0x63, 0x3E, 0xD9, 0x37, 0x66, 0xCF, 0xC0, 0x31, 0x5B, + 0x16, 0x8E, 0x59, 0x32, 0x71, 0xCC, 0x9A, 0x8D, 0x63, 0xB6, 0x8C, 0x1C, 0xF3, 0xCF, 0xCA, 0x91, + 0x8B, 0x31, 0x59, 0xF0, 0x27, 0x88, 0x9C, 0xE4, 0x5B, 0x69, 0x3C, 0x05, 0x19, 0x3E, 0x8A, 0x11, + 0x94, 0x4C, 0xF3, 0x51, 0x3F, 0xD5, 0xC7, 0xAC, 0xE9, 0x3E, 0xD2, 0x39, 0x36, 0xD1, 0x02, 0x71, + 0x7A, 0x7F, 0x80, 0x09, 0xF8, 0x69, 0xCD, 0x8F, 0xC6, 0xE9, 0x6B, 0x51, 0x33, 0x82, 0xF0, 0xBF, + 0x53, 0x29, 0xAF, 0xF4, 0x0C, 0x25, 0x52, 0xBE, 0xBA, 0x25, 0x6E, 0xF7, 0xA5, 0xF2, 0xCB, 0x77, + 0x67, 0x7D, 0x75, 0x0D, 0xCB, 0x93, 0xDC, 0xC5, 0xAC, 0xFC, 0xF4, 0x13, 0x31, 0x41, 0x81, 0x42, + 0x8C, 0x58, 0x66, 0xEC, 0xAA, 0x90, 0x6F, 0xA8, 0x73, 0xE0, 0x4D, 0xEB, 0x90, 0x3C, 0xFE, 0x70, + 0xBA, 0xD7, 0x37, 0x32, 0xBB, 0xAC, 0x39, 0x0B, 0xA6, 0xC4, 0x16, 0x45, 0xD3, 0x9A, 0xA4, 0x1F, + 0x6C, 0xEA, 0x52, 0x84, 0x28, 0xAB, 0xCA, 0x8D, 0x87, 0x51, 0x55, 0xB0, 0x46, 0x21, 0x0A, 0x7F, + 0xB2, 0x8E, 0x24, 0x4A, 0xB4, 0xB2, 0xA2, 0x2B, 0x86, 0x49, 0x05, 0x1A, 0x69, 0x8A, 0xC6, 0x64, + 0x66, 0x6F, 0x9C, 0xF0, 0xC4, 0x9A, 0x24, 0x69, 0xCA, 0xC6, 0x8E, 0x0B, 0x3F, 0xAC, 0x6F, 0x2D, + 0x72, 0xC5, 0x4A, 0xA4, 0x4C, 0x8F, 0xAD, 0xD8, 0x28, 0x1C, 0x1D, 0x48, 0xA3, 0x38, 0x3A, 0xFF, + 0x8F, 0x1F, 0x04, 0xE0, 0xEC, 0x8D, 0xAD, 0xE0, 0x2B, 0x2F, 0xE0, 0x88, 0x94, 0x42, 0xA6, 0x38, + 0x1C, 0xF6, 0x15, 0x92, 0xE4, 0x79, 0x15, 0xF8, 0x87, 0xD7, 0x48, 0x9E, 0x7F, 0x58, 0x62, 0x48, + 0xA0, 0xEB, 0xBA, 0xE4, 0xD5, 0x2B, 0x4E, 0x0B, 0x3A, 0x06, 0xFA, 0xA8, 0xA3, 0xF7, 0x4F, 0x4E, + 0x8A, 0x48, 0x73, 0xDA, 0x49, 0x09, 0x56, 0x6A, 0x55, 0x51, 0x8F, 0xE6, 0xF5, 0x42, 0x6A, 0xAB, + 0x24, 0x4A, 0x64, 0x29, 0x19, 0xC4, 0xE8, 0xC6, 0x32, 0xB4, 0xDF, 0x70, 0xE3, 0x27, 0x20, 0x60, + 0x41, 0x89, 0x0D, 0x6B, 0xCA, 0x09, 0xD8, 0x73, 0xB6, 0x89, 0xA2, 0x76, 0x56, 0x7C, 0x73, 0x48, + 0xCA, 0x09, 0xEC, 0x60, 0x24, 0x81, 0x7A, 0x17, 0x6E, 0x27, 0x49, 0x02, 0x1C, 0x37, 0x8D, 0xEC, + 0x1A, 0x37, 0x7A, 0x93, 0xF7, 0x0E, 0x6C, 0x1A, 0x82, 0xA9, 0xA7, 0xF6, 0x5B, 0x58, 0x65, 0x0B, + 0x3C, 0xC9, 0x03, 0x0F, 0x71, 0xAE, 0xE1, 0xDB, 0xE8, 0x11, 0x09, 0xBC, 0xB4, 0xC7, 0x9F, 0xC0, + 0x71, 0x6C, 0x98, 0xFE, 0x9C, 0xEB, 0xFB, 0xF8, 0xA1, 0x9D, 0x25, 0x59, 0x19, 0x96, 0xE3, 0xFE, + 0x56, 0xC1, 0x76, 0x89, 0x7A, 0x01, 0x30, 0x68, 0xEF, 0x7F, 0xF8, 0x70, 0x7E, 0x70, 0x74, 0xBA, + 0x77, 0x71, 0x78, 0x79, 0x74, 0x7A, 0xF6, 0xF1, 0xE2, 0xF2, 0xE2, 0xD3, 0x19, 0xFE, 0xFA, 0xF3, + 0xDE, 0xF1, 0xD1, 0xC1, 0xE5, 0xC7, 0xD3, 0xBF, 0x9D, 0x7E, 0xF8, 0xE5, 0x54, 0xBF, 0x9D, 0x1D, + 0xF7, 0x28, 0x32, 0x99, 0x60, 0xC4, 0xAB, 0xC2, 0xD0, 0x0A, 0x32, 0x75, 0xBF, 0xBA, 0x98, 0xC5, + 0x78, 0xE7, 0xA9, 0xE9, 0x0A, 0x1B, 0x00, 0x03, 0xFE, 0x24, 0x0C, 0xB5, 0x25, 0xC6, 0x5F, 0x91, + 0xD5, 0xEE, 0x8B, 0x0E, 0x57, 0x7F, 0x53, 0x39, 0x4C, 0x41, 0x2F, 0x3A, 0xCB, 0xB9, 0x62, 0x48, + 0x0E, 0x15, 0x5E, 0xF0, 0x55, 0xFB, 0x8B, 0xCE, 0x93, 0x13, 0x40, 0xE6, 0x50, 0xE1, 0xEA, 0x22, + 0xE9, 0x74, 0x74, 0x51, 0x73, 0xC7, 0xA0, 0x7F, 0xFC, 0xBD, 0xA4, 0xEA, 0x0A, 0xC8, 0xE0, 0x7E, + 0x68, 0xE0, 0x0F, 0x0D, 0xCC, 0xD6, 0xC0, 0x94, 0xBE, 0xFC, 0x69, 0x57, 0x31, 0x7C, 0xB9, 0xED, + 0xE7, 0x36, 0x34, 0xE0, 0xD9, 0xB2, 0x58, 0x22, 0x9C, 0x27, 0xD2, 0xFC, 0x5C, 0x63, 0x2F, 0xF3, + 0x31, 0xF1, 0x61, 0xB1, 0x89, 0x33, 0x50, 0x32, 0xA8, 0xEA, 0x8D, 0x96, 0x4C, 0xB1, 0xD7, 0x65, + 0x43, 0xE9, 0x04, 0x91, 0x54, 0x1F, 0x27, 0x34, 0x1B, 0x0F, 0xFF, 0xF1, 0xEC, 0xDD, 0xF0, 0xF4, + 0x5B, 0x2B, 0x1A, 0x8D, 0x58, 0x0E, 0xDE, 0xD0, 0xDA, 0x08, 0x7B, 0x34, 0xC4, 0xDE, 0xE2, 0x59, + 0x75, 0xE2, 0x69, 0x56, 0x7B, 0x56, 0x20, 0x49, 0xA4, 0xAA, 0xCE, 0xB0, 0xC9, 0xCC, 0x28, 0x46, + 0x08, 0x23, 0xB5, 0x14, 0xD5, 0x69, 0x99, 0x98, 0x48, 0xD2, 0xA0, 0x6A, 0x96, 0x2D, 0x17, 0x19, + 0x54, 0xCA, 0xC3, 0x96, 0xBE, 0x50, 0xCC, 0x8F, 0xCC, 0x02, 0x11, 0xE2, 0xCF, 0xE5, 0x2B, 0x9A, + 0x9F, 0xF6, 0xFE, 0x52, 0x59, 0x6A, 0x13, 0xF7, 0xAF, 0xA6, 0xDB, 0x57, 0xD2, 0xB3, 0x13, 0x08, + 0xD0, 0xB3, 0xF8, 0x4E, 0xAE, 0x1C, 0x7F, 0x8F, 0x33, 0x71, 0x8F, 0x76, 0x33, 0x53, 0x9C, 0x18, + 0x1E, 0x59, 0xAB, 0xB3, 0x1A, 0x78, 0xA8, 0x4C, 0x9A, 0xE7, 0x09, 0xC9, 0x21, 0x2F, 0x9F, 0xD8, + 0x97, 0x27, 0x5F, 0xCB, 0x2A, 0x66, 0xA9, 0x8E, 0xD8, 0xDB, 0x9F, 0xB3, 0xEE, 0x24, 0x4F, 0xA2, + 0xAA, 0x2A, 0x94, 0x44, 0x0A, 0xA3, 0x26, 0xCD, 0x4B, 0x71, 0x0C, 0xFD, 0x61, 0xBA, 0x56, 0x3B, + 0xA7, 0x8E, 0x50, 0x92, 0xE2, 0xC9, 0x24, 0x66, 0x00, 0xED, 0x54, 0xEA, 0xFF, 0x68, 0xFA, 0x2F, + 0x6A, 0x73, 0xF7, 0x49, 0xB7, 0xB9, 0xBB, 0x90, 0x36, 0xF7, 0x9E, 0x74, 0x9B, 0x7B, 0x0B, 0x69, + 0xF3, 0xFA, 0x93, 0x6E, 0xF3, 0x7A, 0xD5, 0x36, 0xEB, 0x28, 0x17, 0xED, 0x30, 0x66, 0x99, 0xC6, + 0xE4, 0x18, 0x5E, 0x79, 0x30, 0xA3, 0x9A, 0x4D, 0x44, 0xDF, 0xD2, 0xE6, 0x4F, 0x54, 0x73, 0x0B, + 0x28, 0x5E, 0xA6, 0x6E, 0x47, 0x6C, 0x33, 0xA3, 0x89, 0x35, 0x22, 0xDB, 0x08, 0x8E, 0xEA, 0x46, + 0xB2, 0xF1, 0xC5, 0xB6, 0x51, 0xB0, 0xF8, 0x73, 0xE7, 0x8B, 0x98, 0x6F, 0xD9, 0x37, 0x27, 0x38, + 0xB5, 0x4E, 0x97, 0xF8, 0x59, 0x4E, 0x54, 0xBE, 0xBC, 0xCC, 0xCB, 0xA2, 0xEA, 0xAF, 0x48, 0x47, + 0xFD, 0xF0, 0x1A, 0x13, 0xF6, 0x2F, 0x9B, 0x90, 0x77, 0x0B, 0x90, 0x77, 0x55, 0xE4, 0x5D, 0x1D, + 0x79, 0x37, 0x0F, 0x79, 0xAF, 0x00, 0x79, 0x4F, 0x45, 0xDE, 0xD3, 0x91, 0xF7, 0xF2, 0x90, 0xAF, + 0x17, 0x20, 0x5F, 0x57, 0x91, 0xAF, 0xEB, 0xC8, 0xD7, 0x63, 0xE4, 0x4F, 0x6F, 0x4B, 0xAA, 0xB2, + 0xCA, 0x4A, 0xF9, 0x82, 0x6F, 0xBC, 0x00, 0x54, 0x75, 0x0A, 0xBF, 0xC2, 0x4F, 0x7F, 0x54, 0xA0, + 0xC0, 0x22, 0x94, 0x09, 0x81, 0x84, 0xFA, 0xB6, 0x43, 0xEF, 0xD8, 0xBB, 0x63, 0x97, 0xA2, 0xE8, + 0xD2, 0x72, 0xF2, 0x8C, 0x2D, 0xE0, 0x5A, 0xCE, 0xB8, 0x41, 0x84, 0xC4, 0x8C, 0xB7, 0x84, 0x74, + 0xA7, 0xA0, 0x6B, 0x74, 0x09, 0x36, 0xB6, 0x4D, 0x0F, 0xE2, 0x22, 0xD2, 0x9A, 0x1D, 0x51, 0xBD, + 0x33, 0xB2, 0x57, 0x5D, 0x39, 0x26, 0x4A, 0xEA, 0x1C, 0x26, 0x81, 0x32, 0xBD, 0x28, 0x2A, 0xA6, + 0x37, 0xEA, 0x95, 0xE8, 0x66, 0xC7, 0xEE, 0xB6, 0x88, 0x63, 0xF7, 0x4A, 0x74, 0x1E, 0xDF, 0x33, + 0xE9, 0x1A, 0x42, 0xCF, 0xC4, 0xD6, 0x39, 0xA0, 0x49, 0x17, 0xA6, 0x54, 0xBE, 0x5B, 0x5F, 0xE7, + 0x81, 0xC0, 0x93, 0xDD, 0xC3, 0xED, 0x9A, 0xCF, 0x59, 0x50, 0x26, 0xA6, 0xE3, 0x2E, 0x25, 0x54, + 0x0E, 0x8D, 0x3F, 0xDF, 0x89, 0x52, 0x1F, 0x81, 0x91, 0x1E, 0xCF, 0x8D, 0xF4, 0x3D, 0x6F, 0x98, + 0xB2, 0xF7, 0x68, 0x2F, 0xBC, 0xB7, 0x16, 0x86, 0x11, 0xDC, 0x1F, 0x88, 0xCB, 0xDB, 0xEA, 0x12, + 0x55, 0x2D, 0x4B, 0xBF, 0x5A, 0xDB, 0x88, 0x8A, 0xC8, 0xDE, 0x04, 0xA6, 0x11, 0x6A, 0x2B, 0x71, + 0x0D, 0x2C, 0xBF, 0xA2, 0xCD, 0x2E, 0xB5, 0x71, 0x6A, 0x78, 0x28, 0x64, 0x7C, 0x56, 0x4A, 0xA3, + 0xC4, 0xA2, 0x16, 0x5B, 0xDD, 0x56, 0xC3, 0xCC, 0xB2, 0xE1, 0x28, 0x36, 0xC5, 0x7E, 0xA9, 0xE7, + 0xB9, 0x92, 0x77, 0xB2, 0xB2, 0xB2, 0x3D, 0x16, 0x3C, 0xAD, 0xB5, 0x4B, 0xBE, 0x29, 0x31, 0x66, + 0x05, 0x6F, 0x05, 0xCA, 0x6D, 0xF9, 0x9D, 0xFA, 0x5E, 0x94, 0xF3, 0x57, 0x7A, 0x83, 0x44, 0xCA, + 0x72, 0xCC, 0xB6, 0xF1, 0x0B, 0x93, 0x50, 0x93, 0x25, 0xBC, 0x31, 0x60, 0xC8, 0x56, 0xBC, 0xFC, + 0x6C, 0x01, 0xB9, 0xA2, 0x6B, 0x66, 0x3D, 0xAE, 0x94, 0xF1, 0x78, 0xA8, 0xE6, 0x6A, 0xD5, 0x9F, + 0x60, 0x7F, 0x50, 0x24, 0xA5, 0x27, 0x16, 0x7E, 0x36, 0xF7, 0x0C, 0xC5, 0x75, 0x92, 0x84, 0x96, + 0x4F, 0x10, 0x9A, 0xD9, 0xD8, 0x76, 0xA7, 0xA8, 0xBD, 0x49, 0x6A, 0x61, 0x7E, 0x3E, 0x36, 0xD7, + 0x24, 0xC5, 0x4F, 0xAB, 0xD5, 0xFC, 0x41, 0x1E, 0x6C, 0x86, 0x61, 0x40, 0x08, 0x4C, 0xFD, 0xD0, + 0xA7, 0xD6, 0x38, 0x51, 0x82, 0x72, 0xF2, 0xE0, 0x58, 0x65, 0x81, 0x48, 0x78, 0xBE, 0xB7, 0x34, + 0x72, 0x14, 0x20, 0x95, 0x0E, 0x78, 0x26, 0x25, 0x48, 0x63, 0xFB, 0xCE, 0x4D, 0xEF, 0xB6, 0xF3, + 0x1A, 0x7F, 0xC8, 0x2F, 0x47, 0xCD, 0xA7, 0xED, 0x29, 0x64, 0xDF, 0xA9, 0xE9, 0xC9, 0x35, 0x6E, + 0xF1, 0x22, 0x7B, 0xDA, 0x0D, 0xC0, 0x39, 0x03, 0x6D, 0x7B, 0xFE, 0xBC, 0x51, 0x26, 0x3B, 0xBE, + 0x69, 0xD6, 0x98, 0xE7, 0x8C, 0xA1, 0xE6, 0xFF, 0x7E, 0xCA, 0xB3, 0x46, 0x9C, 0xAD, 0x7C, 0x1E, + 0x33, 0x47, 0x3A, 0xF5, 0xF9, 0x93, 0x9C, 0x3D, 0xF4, 0xA4, 0xD8, 0x73, 0xB3, 0x1D, 0x4F, 0xA1, + 0xED, 0xA5, 0x4D, 0xC7, 0xCC, 0x2D, 0xD7, 0x71, 0x3D, 0x5D, 0xC3, 0x21, 0x1C, 0x67, 0x9E, 0xE8, + 0x1B, 0xEC, 0x42, 0xCA, 0x5D, 0x56, 0xBD, 0xD1, 0x9D, 0xEF, 0xF5, 0xB2, 0x09, 0x7B, 0x6E, 0x5C, + 0x35, 0x4A, 0x6C, 0x22, 0xE6, 0x8F, 0xBB, 0xC4, 0x3D, 0xBC, 0x53, 0x0C, 0xD0, 0xAF, 0x0C, 0x70, + 0x51, 0x15, 0xE0, 0x67, 0x09, 0x60, 0xA3, 0x18, 0xE0, 0xFC, 0x64, 0x3F, 0x4D, 0xE1, 0xA1, 0xC6, + 0xFB, 0x1B, 0x43, 0xF6, 0x8C, 0x98, 0xEA, 0xAD, 0xBE, 0x3B, 0x53, 0x45, 0xD4, 0x69, 0x6F, 0xEE, + 0x14, 0x01, 0xF4, 0x2B, 0x03, 0x5C, 0x54, 0x05, 0x90, 0x45, 0x14, 0x8F, 0xCB, 0x6C, 0x00, 0x55, + 0x44, 0x31, 0x85, 0x87, 0x59, 0x9E, 0x5C, 0x40, 0x4A, 0x01, 0x73, 0xE9, 0x22, 0x43, 0xC5, 0x88, + 0x75, 0x24, 0x42, 0x5B, 0x78, 0xCC, 0x39, 0x0E, 0xE8, 0x60, 0xB3, 0xD3, 0x29, 0x82, 0xEB, 0x4A, + 0x70, 0xCF, 0x11, 0x0E, 0xC0, 0xBA, 0xA6, 0x66, 0x49, 0x6E, 0x64, 0xAE, 0xF6, 0x1A, 0xAA, 0xF7, + 0x2B, 0x56, 0xBF, 0xA8, 0x56, 0x5D, 0xEE, 0x94, 0x5E, 0x51, 0xF5, 0x94, 0xD6, 0x9A, 0xEA, 0xA7, + 0xDD, 0x47, 0xFC, 0xAD, 0xDB, 0x59, 0x5F, 0x97, 0x61, 0x3B, 0x89, 0x61, 0x7E, 0x48, 0x99, 0x26, + 0x71, 0xA9, 0xF3, 0x87, 0x61, 0x7A, 0x02, 0x86, 0x29, 0x0F, 0xE2, 0xFC, 0xD7, 0x93, 0xCB, 0xF3, + 0xBD, 0x5F, 0x7E, 0x2D, 0xCD, 0x13, 0x02, 0xF4, 0xDF, 0x9E, 0xBF, 0xF9, 0xF5, 0x87, 0xF1, 0xAB, + 0x6C, 0xFC, 0xB2, 0x20, 0xF4, 0x71, 0xD6, 0xDD, 0x2E, 0x49, 0x4A, 0x07, 0xEC, 0x75, 0x6A, 0x02, + 0x6E, 0xF4, 0xEA, 0x02, 0x6E, 0x35, 0x32, 0x5D, 0xB5, 0x1F, 0x16, 0xFE, 0x5F, 0xC1, 0xC2, 0x9B, + 0xC0, 0x53, 0x6B, 0x6C, 0x49, 0x6F, 0x4D, 0xE9, 0xCB, 0xCA, 0x81, 0x33, 0xED, 0xAD, 0x0F, 0xCE, + 0x74, 0x78, 0x06, 0xF0, 0xAD, 0xCC, 0xDC, 0x6B, 0x06, 0xD7, 0x1B, 0x61, 0x8C, 0x93, 0x9B, 0xBA, + 0x9E, 0x7F, 0x42, 0x13, 0x1C, 0x5B, 0xD2, 0x20, 0xDB, 0x97, 0xDD, 0x4E, 0x67, 0xB3, 0xAC, 0xBD, + 0x97, 0xA1, 0x9E, 0x6F, 0xD4, 0x82, 0x7A, 0xDE, 0x48, 0xAD, 0xDE, 0x8B, 0xA1, 0x5E, 0xD4, 0xA2, + 0xF5, 0x42, 0xA3, 0x55, 0x12, 0x6C, 0xBB, 0x16, 0xB1, 0xED, 0x3A, 0x0D, 0xEB, 0xF6, 0xEA, 0xD0, + 0xEA, 0xF6, 0xEA, 0xD0, 0xEA, 0xAD, 0x2B, 0xD3, 0x41, 0x59, 0x79, 0x6C, 0x74, 0x9E, 0xF7, 0x14, + 0x6B, 0x5B, 0x92, 0x1E, 0x83, 0xEB, 0x36, 0x32, 0xB6, 0x6A, 0x66, 0x72, 0x0B, 0xE2, 0x25, 0x39, + 0x1F, 0xAA, 0xAA, 0xFA, 0x16, 0xCC, 0x56, 0x12, 0x5C, 0x86, 0xFF, 0x5A, 0x0C, 0xA8, 0x6A, 0x7E, + 0x79, 0xB8, 0x17, 0x35, 0xE1, 0xB6, 0xEB, 0xC1, 0x69, 0xCA, 0x35, 0xB7, 0xD9, 0x38, 0x6B, 0x67, + 0xA8, 0xEE, 0x9C, 0xA1, 0x77, 0x65, 0x35, 0xA3, 0xAD, 0x93, 0xAE, 0x01, 0x7D, 0xD2, 0x3F, 0xD9, + 0xA8, 0x6A, 0xED, 0x8F, 0xBD, 0x3B, 0x34, 0xB3, 0x77, 0x8E, 0x1D, 0xDE, 0xFC, 0xD1, 0x2D, 0x7E, + 0xA7, 0x96, 0xC9, 0xEF, 0x3D, 0xA2, 0xC9, 0xEF, 0x3D, 0xA6, 0xC9, 0xEF, 0x3D, 0xA2, 0xC9, 0xEF, + 0xFD, 0x30, 0xF9, 0x33, 0x9B, 0xFC, 0xDE, 0x63, 0x9B, 0xFC, 0x5E, 0x4D, 0x93, 0xDF, 0xAB, 0x69, + 0xF2, 0x7B, 0x35, 0x4D, 0x7E, 0xEF, 0x91, 0x4C, 0x7E, 0x67, 0xF3, 0x3F, 0xB7, 0xCA, 0xC8, 0xB5, + 0xFC, 0x8C, 0x51, 0x06, 0x58, 0x58, 0x6D, 0xA5, 0xB1, 0xFF, 0x32, 0x33, 0xCD, 0x34, 0x60, 0x6F, + 0x1C, 0x26, 0x97, 0x68, 0x82, 0xF4, 0xED, 0x12, 0xFE, 0x58, 0x5D, 0x22, 0x01, 0x8A, 0x7F, 0xEF, + 0xA4, 0xEB, 0x7C, 0xD2, 0xEA, 0x7C, 0x32, 0xD4, 0xF9, 0x4D, 0xAB, 0xF3, 0xDB, 0x8E, 0xBC, 0x8B, + 0x07, 0xDC, 0xBC, 0xA3, 0x9E, 0x4D, 0x43, 0x67, 0x90, 0xCB, 0x51, 0xFA, 0xBE, 0xCB, 0x50, 0x80, + 0x41, 0x49, 0xF1, 0x7D, 0x96, 0xB8, 0xB2, 0xE7, 0x6A, 0x95, 0xDF, 0xEF, 0x1D, 0xEE, 0x9D, 0xED, + 0x1B, 0xAA, 0xEE, 0x8D, 0x42, 0xD1, 0xEB, 0x6A, 0x52, 0x98, 0xB1, 0xE5, 0x7F, 0x55, 0x32, 0xC2, + 0x74, 0x0B, 0xD2, 0xBE, 0x14, 0x80, 0xF7, 0x4C, 0xE0, 0xFC, 0xEA, 0xB7, 0xA0, 0x6F, 0xD9, 0xFF, + 0x31, 0x0D, 0x42, 0x60, 0x54, 0x0F, 0x05, 0x62, 0xA7, 0xB5, 0xA7, 0xF4, 0xEE, 0xD8, 0x4B, 0x6E, + 0x08, 0xA5, 0x32, 0xA8, 0x24, 0x75, 0x0C, 0x81, 0x51, 0xF4, 0x9B, 0x13, 0x6A, 0xE9, 0x10, 0x6E, + 0x1C, 0x9B, 0xA5, 0x2B, 0x74, 0xDC, 0x33, 0x96, 0x86, 0x86, 0x37, 0x02, 0x63, 0xD7, 0x30, 0xD7, + 0x1A, 0x78, 0x29, 0x47, 0xEE, 0x99, 0xEF, 0xE1, 0xED, 0xFD, 0x38, 0x49, 0x84, 0x4E, 0x13, 0xB1, + 0xEE, 0xB9, 0xB6, 0x1C, 0x8D, 0x85, 0xD5, 0xB8, 0x8F, 0xC3, 0x93, 0x71, 0x82, 0xA0, 0x93, 0x3F, + 0x96, 0x12, 0x36, 0x58, 0x9E, 0xC8, 0x8E, 0x29, 0x7C, 0x6B, 0xDF, 0x1B, 0x4F, 0x46, 0x34, 0x4C, + 0x12, 0x27, 0xB1, 0x18, 0xB5, 0x08, 0x83, 0x8C, 0x5B, 0x90, 0x33, 0x37, 0x84, 0x7F, 0x4D, 0x37, + 0x44, 0x6B, 0x64, 0x44, 0xAD, 0x11, 0xDD, 0xEC, 0xDA, 0xB7, 0x46, 0x98, 0x56, 0xF5, 0xEE, 0x86, + 0xF2, 0xCB, 0x5D, 0x87, 0xFD, 0xB3, 0xF5, 0x1E, 0xB9, 0xB1, 0x02, 0xBC, 0x2B, 0x75, 0xED, 0xF8, + 0x63, 0x28, 0xF4, 0x41, 0xBF, 0x9D, 0x49, 0x48, 0xBC, 0x6B, 0x1E, 0x29, 0x8D, 0x8B, 0xFE, 0x44, + 0x38, 0xE4, 0xDA, 0xF7, 0xC6, 0x64, 0xEF, 0x8C, 0x03, 0x0C, 0xC9, 0x04, 0xB8, 0x92, 0x22, 0xF5, + 0x38, 0x16, 0xCC, 0xA5, 0x70, 0xCE, 0xD1, 0x48, 0x87, 0xF4, 0x07, 0xC0, 0x89, 0x3F, 0x76, 0x5C, + 0x0A, 0xF4, 0x9D, 0xC1, 0x0D, 0x49, 0x34, 0x00, 0xB3, 0x7E, 0x22, 0x3B, 0x9E, 0xEF, 0x0C, 0x61, + 0xEC, 0x8C, 0x18, 0xE1, 0xD8, 0x33, 0x8C, 0xB2, 0x33, 0x44, 0x42, 0xFF, 0xD3, 0x2E, 0x71, 0xA7, + 0xA3, 0xD1, 0xB2, 0x1E, 0x5D, 0x18, 0x49, 0x51, 0xAB, 0x5F, 0x26, 0x69, 0x03, 0xFF, 0xF6, 0x92, + 0xEC, 0x8D, 0x46, 0xA4, 0x0F, 0xDF, 0xED, 0xFC, 0xD4, 0x7D, 0x9E, 0x1B, 0x78, 0x23, 0xDA, 0x1E, + 0x81, 0xC6, 0x36, 0x3E, 0xF2, 0x1B, 0xA9, 0x04, 0xFE, 0x03, 0x39, 0x81, 0xD0, 0xD2, 0x32, 0x30, + 0x27, 0xF1, 0xB8, 0x8E, 0x93, 0x32, 0x8E, 0x3C, 0xCB, 0xFE, 0xC5, 0x72, 0x42, 0xE5, 0x22, 0x3A, + 0x66, 0x02, 0x11, 0x2F, 0x01, 0x04, 0xD3, 0xAB, 0xB1, 0x13, 0x46, 0x49, 0x10, 0x31, 0x63, 0x08, + 0x0C, 0x36, 0x2C, 0x0F, 0x3E, 0x77, 0xBE, 0x24, 0x71, 0xED, 0x38, 0x65, 0x89, 0xD8, 0x76, 0x97, + 0xDE, 0x11, 0xBC, 0x05, 0x28, 0x27, 0xB5, 0x88, 0x8A, 0xDB, 0xD6, 0x64, 0xC2, 0x07, 0x55, 0x1A, + 0x6D, 0x8B, 0x91, 0x5D, 0x4E, 0x70, 0x5A, 0xFF, 0x61, 0x7D, 0x13, 0xF8, 0x7E, 0x3D, 0x39, 0x7E, + 0x1F, 0x62, 0xCA, 0xB1, 0x7F, 0x4C, 0x69, 0x10, 0x46, 0x58, 0xB1, 0x42, 0xDB, 0x03, 0x84, 0x4B, + 0x8D, 0xB3, 0x0F, 0xFD, 0x0B, 0xCC, 0x61, 0xB2, 0x36, 0x65, 0x2D, 0x8A, 0x10, 0x37, 0xE4, 0x9A, + 0x6C, 0x68, 0x45, 0x9C, 0x44, 0x23, 0x8F, 0x9B, 0x31, 0x59, 0x1A, 0x86, 0x58, 0xCB, 0x57, 0x57, + 0xFE, 0x6B, 0x5E, 0xE8, 0xE0, 0x1D, 0xBE, 0x89, 0x92, 0x40, 0xAA, 0xB1, 0x93, 0x23, 0xDA, 0x7E, + 0x68, 0x85, 0xD3, 0x00, 0xC3, 0x9B, 0x55, 0x83, 0x9C, 0x4F, 0x10, 0xAA, 0xE7, 0x21, 0x4D, 0x0D, + 0x64, 0x3E, 0xEC, 0xCC, 0x95, 0x1A, 0x99, 0x83, 0x59, 0x21, 0xE0, 0xF9, 0x43, 0x1A, 0x9E, 0x59, + 0x8E, 0x0F, 0x33, 0x22, 0x1A, 0x57, 0x75, 0x06, 0xB9, 0x0A, 0xDD, 0xB7, 0xAC, 0x06, 0x2F, 0x33, + 0x88, 0x08, 0xB5, 0x97, 0xE5, 0xF5, 0x09, 0x18, 0x2E, 0x2F, 0x0C, 0xA9, 0xDB, 0x96, 0x72, 0x12, + 0x4C, 0x28, 0xF5, 0x4F, 0xF6, 0xF6, 0x03, 0x1D, 0xEE, 0xD4, 0x73, 0x69, 0x56, 0x64, 0x2A, 0xA3, + 0x78, 0x18, 0x4C, 0x4E, 0xBD, 0xBB, 0x33, 0x00, 0x0F, 0x0C, 0xE6, 0x17, 0x18, 0x63, 0x46, 0x52, + 0xCF, 0x09, 0x37, 0x8C, 0x4C, 0x94, 0x28, 0x30, 0x70, 0xCC, 0xE0, 0x58, 0xA8, 0x8E, 0x48, 0xDE, + 0x95, 0x15, 0x21, 0x2B, 0xE3, 0x49, 0x58, 0x88, 0xC3, 0x15, 0x2C, 0xDB, 0x3E, 0xBC, 0x85, 0x5F, + 0x30, 0x4C, 0x99, 0x02, 0xFE, 0xA5, 0xC6, 0xC1, 0x87, 0x13, 0xB0, 0xC5, 0x21, 0x7E, 0x83, 0x8E, + 0xA0, 0x98, 0x1E, 0x6F, 0x89, 0x62, 0x95, 0x65, 0xB2, 0xFB, 0x1A, 0x18, 0x8C, 0x35, 0x5C, 0x08, + 0xAC, 0x44, 0xEC, 0x43, 0x3A, 0xC9, 0x98, 0x12, 0xF1, 0xC0, 0xEE, 0xD2, 0xA3, 0x53, 0xCF, 0x6E, + 0xED, 0xC1, 0x2F, 0x1C, 0x73, 0x1C, 0xF1, 0xE0, 0x60, 0x18, 0x84, 0xF5, 0x0D, 0x7E, 0x51, 0x43, + 0x1F, 0x78, 0xB5, 0xCF, 0xCE, 0x97, 0xB6, 0xE7, 0x0E, 0x46, 0xCE, 0x00, 0xD3, 0x7C, 0xC4, 0xB2, + 0x5D, 0x4A, 0xBD, 0xD9, 0xAC, 0xA6, 0xDF, 0xCB, 0x78, 0x89, 0x95, 0xBB, 0x58, 0x56, 0x30, 0xF5, + 0x59, 0xD0, 0x34, 0x3A, 0xC2, 0xEF, 0x7F, 0x07, 0xE1, 0xA7, 0xE5, 0xC4, 0xF1, 0xE1, 0xC0, 0x37, + 0x92, 0x34, 0x20, 0xEA, 0xD3, 0x81, 0xBA, 0x6D, 0x42, 0xD6, 0x32, 0xE9, 0x49, 0xC1, 0xD8, 0x0F, + 0xF2, 0x68, 0x37, 0xA2, 0x9C, 0x07, 0x73, 0x09, 0xD5, 0x3C, 0xDE, 0xA4, 0x26, 0x18, 0x98, 0x33, + 0x3C, 0x0C, 0x5F, 0x99, 0xB5, 0x7A, 0x8F, 0xCC, 0x27, 0x76, 0x24, 0x10, 0xF5, 0xCD, 0x2F, 0xFD, + 0x72, 0x3B, 0xC2, 0x3C, 0xBF, 0xCC, 0x27, 0x79, 0x4D, 0x2D, 0x7A, 0x8B, 0x10, 0xF3, 0x68, 0x4E, + 0x84, 0xA8, 0x54, 0x5B, 0x32, 0xF8, 0x4C, 0x1A, 0x92, 0xDD, 0x58, 0x43, 0x5B, 0xF2, 0x5F, 0x3C, + 0xAF, 0xDD, 0xB2, 0x99, 0x1E, 0x52, 0xE7, 0xED, 0xC4, 0x75, 0x41, 0x5E, 0x33, 0x87, 0xF1, 0x12, + 0xA1, 0x7E, 0x33, 0xDF, 0xB1, 0x8C, 0x4E, 0xF3, 0x6E, 0xE5, 0x3B, 0x3D, 0x4F, 0x94, 0xA9, 0x91, + 0xBC, 0x11, 0xD9, 0x8D, 0xE4, 0x42, 0x48, 0x37, 0x52, 0xA9, 0x94, 0xB5, 0xD3, 0x97, 0x5A, 0x5F, + 0xD7, 0xD8, 0xD2, 0x53, 0x9E, 0x09, 0x32, 0xE6, 0x71, 0x97, 0x8E, 0x44, 0x5F, 0xB4, 0x37, 0xF1, + 0x74, 0x73, 0x0F, 0x9C, 0x5B, 0x98, 0x8A, 0xD1, 0x6F, 0x3B, 0xEE, 0xAE, 0x1D, 0xF7, 0x14, 0x64, + 0x0F, 0xEA, 0x45, 0xA4, 0xC2, 0xED, 0x81, 0xDB, 0xF4, 0x6D, 0xD7, 0xD2, 0xFC, 0x6C, 0xB7, 0xB7, + 0xE6, 0xC8, 0x4F, 0x7A, 0xBF, 0xA8, 0x0A, 0x33, 0xDD, 0xEE, 0xD6, 0x5C, 0xA5, 0xA3, 0xA7, 0x16, + 0xAE, 0xC2, 0xCB, 0x06, 0xEE, 0x5B, 0xD4, 0x60, 0xA5, 0x1E, 0x35, 0x65, 0x73, 0x45, 0xC5, 0x6C, + 0x18, 0xA3, 0xA6, 0x77, 0xCE, 0x6B, 0x0F, 0xCD, 0x8A, 0x8F, 0xA6, 0x27, 0x23, 0xCE, 0x70, 0x39, + 0x38, 0xF3, 0xFA, 0xB2, 0x69, 0x44, 0x97, 0x80, 0xCF, 0x6A, 0x75, 0xFC, 0x3A, 0xCD, 0x3C, 0x5A, + 0x5D, 0xE6, 0xA9, 0x1B, 0xAD, 0xD5, 0x1C, 0xA4, 0x7E, 0xAB, 0xF3, 0xE1, 0x0D, 0xAD, 0xD6, 0xAE, + 0x8B, 0xCD, 0xDE, 0xF2, 0x34, 0xC2, 0x82, 0xD6, 0x1B, 0x2E, 0xA6, 0x01, 0x90, 0x48, 0x12, 0xAF, + 0x45, 0xC1, 0x16, 0x8A, 0xA2, 0x10, 0x99, 0xBA, 0x71, 0x67, 0x10, 0x0B, 0x2E, 0xE3, 0x30, 0x27, + 0x2A, 0x66, 0xFD, 0x75, 0xE9, 0x68, 0x16, 0x81, 0xA4, 0x51, 0xC5, 0x59, 0x4D, 0x3A, 0x66, 0x1D, + 0x88, 0x20, 0xDE, 0x58, 0x53, 0xFB, 0xC0, 0xF7, 0x26, 0x36, 0x66, 0x86, 0x32, 0x4E, 0xBD, 0xCA, + 0x83, 0x69, 0x85, 0xFA, 0x52, 0x82, 0xA3, 0xAE, 0x79, 0x76, 0x2C, 0xC3, 0x91, 0x70, 0x16, 0x2A, + 0x71, 0x54, 0x97, 0x56, 0x85, 0xD6, 0x1B, 0xB4, 0x3D, 0xFB, 0x09, 0xC3, 0x19, 0xB5, 0xBE, 0xF0, + 0x6D, 0x44, 0x73, 0x7F, 0x4F, 0xC0, 0x4C, 0xF1, 0xC7, 0x71, 0x6B, 0x09, 0xAC, 0x18, 0x5C, 0x91, + 0xC1, 0x34, 0xA0, 0xC7, 0xDE, 0xC0, 0x1A, 0x39, 0xBF, 0x53, 0xFB, 0x00, 0xDA, 0xE9, 0x3B, 0x57, + 0x53, 0x9E, 0x46, 0xB2, 0x7E, 0xF3, 0x73, 0x70, 0xE6, 0xB6, 0x7C, 0x64, 0x02, 0xBA, 0x80, 0x15, + 0xE0, 0x31, 0xAC, 0x69, 0x47, 0xA6, 0xDE, 0x2F, 0x21, 0x8F, 0xBA, 0x48, 0x0D, 0x9A, 0xA2, 0xBF, + 0xA4, 0x38, 0xA3, 0x7E, 0x54, 0x78, 0x98, 0x31, 0x77, 0x44, 0x1D, 0xD0, 0xD0, 0x72, 0x46, 0x41, + 0x45, 0xB9, 0x54, 0x41, 0x94, 0x23, 0x8B, 0xF7, 0x96, 0x6F, 0xE3, 0x56, 0x10, 0x17, 0x44, 0xFC, + 0xC2, 0xCC, 0x9C, 0x44, 0x93, 0x81, 0xBD, 0x92, 0xA4, 0x64, 0xD8, 0xD9, 0x44, 0x55, 0x0A, 0x93, + 0x49, 0x56, 0x6C, 0x63, 0x69, 0x0E, 0x52, 0x89, 0xF0, 0x94, 0x6A, 0x3F, 0xDB, 0x71, 0xA9, 0xD7, + 0xE0, 0x7C, 0x50, 0x93, 0xC7, 0x20, 0x6D, 0xD9, 0xCD, 0xC1, 0x5D, 0x50, 0xB1, 0x65, 0xD8, 0x0C, + 0xC3, 0x6E, 0xE1, 0x6C, 0x3E, 0x42, 0x2E, 0xB2, 0x42, 0x1F, 0x41, 0x79, 0x78, 0x6D, 0x46, 0x01, + 0x14, 0x3F, 0xDF, 0x26, 0x1B, 0x4D, 0xDF, 0xAA, 0xD7, 0xCB, 0xB9, 0x90, 0xC6, 0xB6, 0xD5, 0x1E, + 0xDD, 0xC8, 0xEA, 0x7B, 0x20, 0xAA, 0x0E, 0x9E, 0x68, 0x63, 0x2F, 0x9B, 0xD6, 0xF9, 0xD1, 0xE9, + 0xE1, 0xAF, 0xF3, 0x90, 0xA7, 0x82, 0xAD, 0x9C, 0xF9, 0x48, 0x41, 0xD6, 0x34, 0x1E, 0xE5, 0xF1, + 0x18, 0xE4, 0xA0, 0x3C, 0xDB, 0x35, 0xA3, 0x14, 0xCA, 0x3E, 0x01, 0xA6, 0xCB, 0x20, 0x81, 0x9B, + 0x45, 0x02, 0x25, 0xB0, 0x98, 0xDA, 0x6F, 0x7A, 0xD7, 0x6B, 0x56, 0x39, 0x54, 0x7C, 0x2B, 0x2C, + 0x25, 0x0F, 0x80, 0x1F, 0x5B, 0xA1, 0x33, 0x50, 0x91, 0xCC, 0x24, 0x9C, 0x8A, 0x28, 0x33, 0x24, + 0x15, 0xBD, 0x04, 0x36, 0x07, 0x01, 0x95, 0x78, 0x54, 0x2C, 0x53, 0x2E, 0x0C, 0x76, 0x2E, 0xE2, + 0xC8, 0xC7, 0x94, 0xDE, 0x4A, 0xDC, 0x1B, 0x85, 0x4E, 0x38, 0xB5, 0x6B, 0x29, 0x89, 0x72, 0x74, + 0x9F, 0x42, 0xAF, 0x3F, 0xC8, 0xB8, 0x28, 0x02, 0xA9, 0x4D, 0x9B, 0x39, 0x93, 0x51, 0x03, 0x29, + 0xE6, 0x88, 0x3C, 0xBE, 0x0F, 0x7B, 0xCF, 0xEF, 0xC3, 0xDE, 0x93, 0x57, 0xC4, 0x9D, 0x8E, 0xF7, + 0x53, 0xEF, 0x6A, 0x42, 0x51, 0xFA, 0x56, 0x2C, 0xB8, 0xE5, 0xA1, 0xE7, 0x8A, 0x4B, 0xB1, 0xEC, + 0xA9, 0x0D, 0xCC, 0xAA, 0xF2, 0x86, 0x7D, 0xC5, 0xE7, 0x10, 0xEE, 0x95, 0xC0, 0x9A, 0xA4, 0xB6, + 0xB1, 0x09, 0x78, 0xBC, 0x94, 0xD9, 0x82, 0x28, 0xE3, 0x4B, 0x82, 0x7F, 0x1F, 0xEB, 0x2F, 0xDD, + 0xCB, 0xEA, 0x25, 0xBD, 0x6A, 0xB0, 0x2C, 0x07, 0x71, 0x64, 0x4C, 0x63, 0x52, 0x4A, 0xA4, 0x6A, + 0x51, 0x55, 0x05, 0xCF, 0x62, 0x96, 0x98, 0x99, 0x04, 0x0F, 0x27, 0x0C, 0xFB, 0x2C, 0x53, 0x53, + 0x01, 0x22, 0x63, 0x88, 0xC0, 0xDC, 0xD8, 0x9F, 0x03, 0xE3, 0x26, 0x96, 0x95, 0x58, 0xAA, 0xBC, + 0xB4, 0x3D, 0x39, 0x09, 0x85, 0x32, 0x74, 0x58, 0xBB, 0xD9, 0x5D, 0x5F, 0xFB, 0x93, 0x5C, 0xA2, + 0xD9, 0x59, 0x88, 0xEE, 0x59, 0xBA, 0xB9, 0x6F, 0xA6, 0xDD, 0xE5, 0x32, 0x83, 0xE7, 0xDB, 0x8E, + 0x69, 0x9B, 0x58, 0x1E, 0x44, 0x98, 0xD5, 0x58, 0x1C, 0x24, 0xB3, 0x8C, 0xC2, 0x1A, 0x2B, 0x58, + 0x09, 0xB9, 0x28, 0xD8, 0x35, 0x56, 0xD3, 0x59, 0x19, 0xC6, 0x18, 0x7E, 0xE3, 0x7F, 0x27, 0xF1, + 0x32, 0xE4, 0xC8, 0x1D, 0xF8, 0x2C, 0xCA, 0x61, 0x22, 0xF2, 0x3C, 0x91, 0x55, 0x12, 0xDC, 0x59, + 0x13, 0xFE, 0x26, 0x32, 0x3B, 0xA0, 0x86, 0xF9, 0x27, 0xE1, 0x89, 0x04, 0x8C, 0x27, 0x9E, 0xF6, + 0x02, 0xEB, 0xB8, 0x98, 0x92, 0xF9, 0x06, 0xEC, 0x32, 0x0D, 0x92, 0x97, 0x22, 0x13, 0x52, 0xE4, + 0xB5, 0xBA, 0xB3, 0xC6, 0x2E, 0xE1, 0x5B, 0x5F, 0xE9, 0x09, 0x7D, 0x8F, 0x30, 0xFE, 0x8E, 0xA1, + 0x84, 0x25, 0xA1, 0xDB, 0x49, 0xF7, 0x6E, 0x65, 0xBD, 0x28, 0xD3, 0xBB, 0xDF, 0x58, 0xEF, 0xA6, + 0x65, 0x23, 0xFF, 0x93, 0x19, 0x4E, 0x32, 0x52, 0x99, 0x4F, 0x06, 0xCA, 0xD1, 0x93, 0x25, 0xB4, + 0x4A, 0xBA, 0xCB, 0xD9, 0x54, 0x99, 0x30, 0xF2, 0x88, 0x3E, 0xCC, 0x51, 0x50, 0xCC, 0x64, 0xCA, + 0xAD, 0x35, 0xF1, 0x55, 0xD0, 0xBA, 0x55, 0xBC, 0x44, 0x23, 0xAB, 0x56, 0x81, 0xB0, 0x24, 0x9A, + 0xAC, 0xAD, 0x26, 0x92, 0x80, 0xED, 0xD4, 0x0B, 0xE9, 0x4B, 0xD2, 0x28, 0x20, 0xBE, 0x02, 0xC4, + 0x1B, 0xC4, 0x73, 0x47, 0xF7, 0xE4, 0xCE, 0xF3, 0xBF, 0x06, 0x11, 0xB3, 0xF0, 0xB7, 0x73, 0x6D, + 0x42, 0x9B, 0x83, 0x8F, 0x3D, 0xED, 0xE1, 0xB8, 0x61, 0x8B, 0xBD, 0x18, 0x1E, 0xB0, 0xAC, 0xC9, + 0x6D, 0xF2, 0x11, 0xC7, 0x8A, 0xE5, 0xE3, 0xE3, 0x52, 0x21, 0x8E, 0x15, 0x4A, 0x89, 0x75, 0xE5, + 0xDD, 0xD2, 0xAA, 0x62, 0x5A, 0x89, 0xC4, 0x74, 0x40, 0x73, 0xC5, 0xF4, 0xA0, 0x64, 0xDA, 0x20, + 0x47, 0xD7, 0xC4, 0x1A, 0x41, 0x7D, 0xFB, 0x9E, 0x8D, 0x3E, 0x31, 0xF0, 0xE2, 0xD1, 0xDB, 0x62, + 0x92, 0x24, 0x4E, 0x48, 0x46, 0x20, 0x4B, 0x31, 0x22, 0x35, 0x4B, 0xCE, 0x82, 0x48, 0xF6, 0xC6, + 0xEF, 0x39, 0xE8, 0xE3, 0x8E, 0x33, 0xB4, 0x05, 0xD8, 0x8C, 0x0E, 0x71, 0x02, 0xF2, 0x5E, 0xB2, + 0x1A, 0x0A, 0xAA, 0x98, 0xB9, 0xB4, 0xDE, 0xE3, 0xBF, 0x2B, 0x68, 0xFF, 0xD7, 0xC7, 0x19, 0x0E, + 0xF8, 0x84, 0x40, 0xCC, 0xCD, 0x82, 0x07, 0x43, 0xC6, 0x99, 0x62, 0x61, 0x82, 0x3C, 0x63, 0x9B, + 0xD0, 0xAA, 0x30, 0xC2, 0xC7, 0x89, 0x1E, 0x64, 0x2B, 0x57, 0xD5, 0xD4, 0x7A, 0xE8, 0xF6, 0xED, + 0x1F, 0xBE, 0x8D, 0xA7, 0x6E, 0xF9, 0xF9, 0xAF, 0xF8, 0xCA, 0x87, 0x0B, 0x93, 0x0E, 0xC6, 0x33, + 0x61, 0xCD, 0xF8, 0xF4, 0xD3, 0xA7, 0x63, 0x18, 0x2C, 0x6F, 0x2C, 0x7B, 0x1F, 0x9F, 0x0C, 0x5D, + 0x4A, 0xD7, 0x89, 0x3C, 0x5A, 0xE3, 0x6B, 0xA4, 0x52, 0x6D, 0xF1, 0x16, 0x69, 0xEA, 0x51, 0xE8, + 0x8D, 0x6D, 0xF6, 0x1A, 0xA9, 0x05, 0xF3, 0x96, 0xFA, 0x24, 0x69, 0xA9, 0xB7, 0xD9, 0xA5, 0xA0, + 0xEE, 0x16, 0x59, 0x7D, 0x1E, 0xBD, 0xA9, 0xFA, 0x3C, 0xF5, 0xB8, 0x6A, 0x54, 0x86, 0x24, 0xC5, + 0xAF, 0xF5, 0x89, 0x7D, 0x7A, 0x4C, 0x62, 0xBF, 0xCD, 0x93, 0x58, 0xC6, 0x03, 0x70, 0xCA, 0x94, + 0x1F, 0xBD, 0xA0, 0x84, 0x3D, 0x47, 0xAC, 0xA1, 0x85, 0x2F, 0xF0, 0xF1, 0x67, 0x1D, 0x1C, 0x49, + 0x31, 0xF9, 0x33, 0x31, 0x36, 0xFD, 0xA6, 0xDE, 0x75, 0x61, 0x83, 0x78, 0x47, 0x94, 0xBC, 0xC2, + 0xC0, 0x61, 0xCF, 0xB7, 0x03, 0xA6, 0x2E, 0x51, 0xD0, 0xDB, 0xCA, 0x0A, 0x2B, 0xD5, 0x47, 0x27, + 0x22, 0x04, 0x43, 0x1D, 0x06, 0x4C, 0xEB, 0x62, 0xB0, 0xCF, 0xAC, 0xF2, 0x97, 0x28, 0x29, 0x33, + 0xD1, 0x73, 0xC1, 0x46, 0x5E, 0xB5, 0xA2, 0x6B, 0xD2, 0xA9, 0x1C, 0x43, 0x89, 0x99, 0x97, 0x0D, + 0x43, 0x35, 0x4D, 0x06, 0x87, 0x67, 0x7A, 0x18, 0xAC, 0x90, 0x26, 0x4B, 0x8C, 0x9A, 0x68, 0x5B, + 0x56, 0xC1, 0xA7, 0xAC, 0x82, 0xDF, 0xF4, 0xA4, 0xBB, 0x15, 0x8D, 0x23, 0x7F, 0x2D, 0x85, 0x89, + 0x7B, 0xD7, 0x20, 0xD5, 0xE5, 0x67, 0x19, 0xED, 0x6A, 0x4F, 0xA6, 0xC1, 0xCD, 0xD2, 0x42, 0xDB, + 0xB4, 0x6C, 0x48, 0xF8, 0x89, 0x84, 0x70, 0x8D, 0xA9, 0x1B, 0x22, 0x9B, 0x62, 0xEC, 0x6B, 0x6C, + 0x8B, 0xE2, 0x88, 0x4B, 0x40, 0x24, 0x02, 0x9B, 0x31, 0x32, 0x17, 0x6A, 0x4A, 0x77, 0x26, 0xE4, + 0x1E, 0x4D, 0xEE, 0x06, 0x22, 0xC4, 0x6B, 0x96, 0x54, 0x5A, 0x9D, 0x29, 0x4D, 0x2A, 0x04, 0x75, + 0xCD, 0x0A, 0x84, 0x00, 0x28, 0x1B, 0xB1, 0x1A, 0x88, 0x74, 0x45, 0x0A, 0x50, 0xE2, 0xD3, 0x24, + 0x8B, 0xDE, 0x5E, 0x6A, 0x1C, 0x30, 0xEE, 0x09, 0x1E, 0x92, 0xB1, 0xD6, 0xE0, 0x72, 0x21, 0x06, + 0x5F, 0x21, 0x8D, 0xBF, 0x36, 0x96, 0xB3, 0xB6, 0x7E, 0xE4, 0x2E, 0x41, 0x4E, 0x06, 0x14, 0x5B, + 0x00, 0x36, 0x31, 0x63, 0xED, 0x98, 0x2F, 0x46, 0x0C, 0x24, 0x56, 0x0C, 0xFA, 0x77, 0x94, 0x61, + 0xE6, 0xDD, 0x1A, 0x2E, 0xCD, 0xEE, 0x97, 0x8C, 0xAA, 0x9F, 0x52, 0x55, 0x7B, 0x59, 0x55, 0x7F, + 0x4B, 0x55, 0x5D, 0xD7, 0xAA, 0x9A, 0x47, 0xBF, 0xD4, 0xA1, 0xA6, 0xF7, 0xFB, 0x64, 0xAE, 0x0B, + 0x6A, 0x7C, 0x2A, 0xAC, 0xF1, 0x5B, 0x56, 0x0D, 0x95, 0x35, 0xE5, 0xA5, 0xBA, 0xF8, 0x51, 0x1D, + 0x49, 0xD0, 0xE0, 0xC5, 0xFA, 0x16, 0xF8, 0x85, 0x5C, 0x01, 0x88, 0xE5, 0xDA, 0x64, 0xEC, 0xB9, + 0x5E, 0x30, 0xB1, 0x60, 0x15, 0xC7, 0x62, 0xA4, 0x99, 0x19, 0xD6, 0x56, 0xEA, 0x89, 0xA2, 0x48, + 0x81, 0xD6, 0x99, 0x6A, 0x20, 0xF2, 0x79, 0x27, 0x53, 0x3F, 0x2A, 0x43, 0xDA, 0xA8, 0xA4, 0x66, + 0x06, 0xBE, 0x9F, 0x90, 0x85, 0x36, 0x69, 0xBE, 0xDC, 0x64, 0xBC, 0xAF, 0xA4, 0x87, 0x96, 0x4B, + 0xAF, 0xED, 0x60, 0x66, 0x46, 0xCF, 0xA7, 0x76, 0x23, 0xEF, 0x29, 0x4E, 0xB6, 0x13, 0x32, 0x33, + 0x59, 0x51, 0xFA, 0x92, 0xFC, 0xBA, 0xF6, 0x69, 0xED, 0xB7, 0x86, 0x9A, 0xFF, 0xDC, 0xD0, 0xFA, + 0x57, 0x64, 0x73, 0x39, 0x75, 0xEC, 0x95, 0x29, 0xD3, 0xC0, 0xF9, 0x9D, 0x12, 0x93, 0x69, 0x56, + 0xAC, 0x63, 0xEC, 0xE3, 0x26, 0x53, 0x67, 0xD5, 0xB9, 0x12, 0x07, 0xA8, 0x37, 0x61, 0x7D, 0x2F, + 0x05, 0xA8, 0xA3, 0xB7, 0x0A, 0x6A, 0x20, 0x12, 0x62, 0x37, 0x79, 0x05, 0x79, 0x98, 0xF2, 0x2F, + 0x6C, 0xEF, 0xC2, 0x38, 0xC1, 0xA6, 0x6A, 0x46, 0x63, 0x88, 0x15, 0xAB, 0xA3, 0x2D, 0x53, 0x08, + 0x98, 0x0D, 0x9C, 0x83, 0xAB, 0x93, 0xC2, 0x9F, 0x97, 0x1A, 0xFF, 0xCB, 0x0C, 0x24, 0xA8, 0x01, + 0x2C, 0xB5, 0x06, 0x37, 0x4B, 0xE6, 0x5D, 0x48, 0xD9, 0x26, 0xFD, 0x79, 0x29, 0xBC, 0x71, 0x02, + 0xBE, 0x09, 0xB3, 0xB4, 0x9C, 0x6B, 0xD5, 0x5D, 0xD5, 0xAA, 0xB7, 0x83, 0xE9, 0x15, 0x5F, 0x15, + 0x2E, 0x81, 0xFF, 0xD4, 0xDD, 0x54, 0x5E, 0x47, 0x97, 0x90, 0xC6, 0xA0, 0x30, 0xE1, 0xF1, 0x84, + 0xE8, 0x91, 0x25, 0x8B, 0xA7, 0xC0, 0xC8, 0x5E, 0x69, 0x1F, 0xD6, 0xBF, 0x70, 0x14, 0xC9, 0x66, + 0xAF, 0xE6, 0x84, 0x47, 0x37, 0x02, 0xCB, 0x39, 0xE2, 0x51, 0xED, 0x22, 0x67, 0x5C, 0xAD, 0x57, + 0xC6, 0x21, 0x8F, 0x20, 0xE6, 0xE5, 0x94, 0x27, 0xCF, 0x63, 0xE5, 0xBA, 0xB3, 0xF1, 0x81, 0x03, + 0x78, 0xB4, 0xDD, 0x6E, 0x67, 0x7D, 0xA3, 0x45, 0x5E, 0xBC, 0x50, 0xA8, 0xF3, 0xCF, 0xC8, 0x02, + 0x16, 0x54, 0x76, 0x9A, 0xF5, 0x73, 0x07, 0xA4, 0xB3, 0x89, 0x7D, 0xAD, 0x90, 0xD8, 0x64, 0x0F, + 0xE6, 0x6D, 0xD6, 0xC5, 0xAE, 0x1D, 0x3A, 0x00, 0x8D, 0x5E, 0xA7, 0xD3, 0xEE, 0xB0, 0x0B, 0x7E, + 0x6D, 0xC5, 0x33, 0x67, 0x1F, 0x90, 0x18, 0xFB, 0xE5, 0xC9, 0x79, 0xE5, 0xB1, 0xDE, 0x54, 0xF7, + 0xCC, 0x23, 0xD0, 0xAA, 0xDE, 0x79, 0xAC, 0x78, 0xD5, 0x3C, 0x74, 0x8D, 0x9C, 0xE4, 0xA5, 0x6B, + 0x63, 0x44, 0xF1, 0x51, 0xC5, 0xD5, 0x5A, 0x63, 0x91, 0xB8, 0x49, 0x6B, 0x2A, 0x8B, 0xB4, 0x54, + 0x2B, 0xD3, 0x74, 0xCB, 0x5C, 0xAA, 0xEA, 0xC6, 0x02, 0x7C, 0x7E, 0xAD, 0xCF, 0x8C, 0x7E, 0x7F, + 0x5C, 0x47, 0xF1, 0xFD, 0xFF, 0x00, 0x92, 0x32, 0xAD, 0x24, 0x22, 0xB6, 0xB3, 0x57, 0x13, 0x29, + 0xA3, 0x5A, 0xE4, 0x0C, 0xEB, 0x4A, 0x58, 0xD9, 0x21, 0x8E, 0xD5, 0xF1, 0xE9, 0x2C, 0x2C, 0xE2, + 0xDE, 0x2D, 0xBF, 0xB8, 0xC8, 0x93, 0xAC, 0x74, 0x72, 0x29, 0x2F, 0xD3, 0x6E, 0x2C, 0x7A, 0x42, + 0xC3, 0x1B, 0xCF, 0xCE, 0xBC, 0x1B, 0xA7, 0x5C, 0x8C, 0x4B, 0xAE, 0x84, 0xBF, 0x8C, 0x6E, 0x80, + 0xA7, 0x5E, 0x5E, 0x02, 0x94, 0x89, 0xFC, 0x25, 0xFC, 0x5A, 0x3C, 0x6D, 0xFA, 0x34, 0x36, 0x3B, + 0x76, 0xC9, 0x74, 0xC0, 0x9D, 0x19, 0x9C, 0x04, 0x24, 0xE1, 0x9B, 0x78, 0x8E, 0x28, 0xE3, 0xF2, + 0xFC, 0x32, 0x59, 0x25, 0x4B, 0x52, 0x95, 0xF4, 0xF1, 0xB6, 0xA8, 0xB6, 0x42, 0xD2, 0xB5, 0xCC, + 0x17, 0x0B, 0x96, 0xC9, 0x1A, 0xE9, 0xF2, 0x0B, 0xE1, 0x79, 0x6C, 0x47, 0x33, 0x3F, 0x70, 0xD9, + 0xC6, 0x38, 0x0C, 0x28, 0x5D, 0x5A, 0xCF, 0xBB, 0x87, 0x9C, 0x2B, 0xA7, 0x74, 0xCE, 0x85, 0x1C, + 0x31, 0x69, 0x42, 0x35, 0xCB, 0x49, 0x67, 0x15, 0x45, 0xF0, 0x88, 0x92, 0x4A, 0xE5, 0x38, 0x30, + 0xCB, 0x49, 0x5F, 0x3A, 0x3F, 0x59, 0x8B, 0x31, 0x1D, 0x9F, 0x09, 0x38, 0x06, 0xAF, 0xAC, 0x20, + 0x22, 0x8A, 0x71, 0xA5, 0xD7, 0xBB, 0x64, 0xCB, 0x34, 0x55, 0x8F, 0xAC, 0x30, 0xC2, 0x92, 0x54, + 0x5E, 0x25, 0x1B, 0x28, 0xC8, 0x9E, 0xE1, 0x35, 0xB8, 0xCC, 0xA9, 0xD9, 0xB0, 0x7C, 0x2E, 0x48, + 0x5D, 0x91, 0x5E, 0xF2, 0x47, 0x5C, 0xC7, 0x4C, 0xBD, 0x4E, 0xC7, 0xC9, 0x2B, 0x0B, 0xA3, 0x31, + 0xAC, 0x06, 0x23, 0xF6, 0xBB, 0x3B, 0xD2, 0x9F, 0xAF, 0xE2, 0x86, 0x49, 0x5F, 0xD3, 0xE7, 0x00, + 0x85, 0x5C, 0xAE, 0xEC, 0x2A, 0x3E, 0x7B, 0x42, 0x60, 0x85, 0xE8, 0x8C, 0xA7, 0xF7, 0xFC, 0x1F, + 0x32, 0x24, 0x91, 0x4E, 0xCC, 0x21, 0x44, 0x01, 0x58, 0x23, 0xB6, 0x9F, 0x96, 0x54, 0x74, 0x8E, + 0xF3, 0xC4, 0x92, 0xDD, 0x88, 0xD2, 0x12, 0x32, 0xD8, 0x34, 0x4E, 0x48, 0xD2, 0xD0, 0x75, 0x83, + 0xA2, 0x65, 0x18, 0x10, 0x13, 0x78, 0x2F, 0x1B, 0x3C, 0xF3, 0x72, 0x57, 0x0A, 0x49, 0xF7, 0x8B, + 0x76, 0x3B, 0xB1, 0x4E, 0x8E, 0x94, 0x28, 0xC9, 0x49, 0x05, 0x3C, 0xBD, 0x9C, 0x5C, 0x2B, 0x0A, + 0x1E, 0x25, 0xA6, 0x28, 0xEB, 0x91, 0x33, 0xC3, 0xA0, 0xDE, 0xC9, 0xAC, 0xAB, 0x8E, 0x92, 0xA2, + 0x7A, 0xB1, 0xDE, 0x14, 0x54, 0x4C, 0x3A, 0x3C, 0xBB, 0x62, 0xAA, 0x73, 0x0B, 0xAB, 0xEA, 0x1D, + 0x59, 0x32, 0x10, 0x46, 0xC9, 0xCE, 0x11, 0x70, 0xF3, 0x1E, 0x89, 0x86, 0x30, 0x6B, 0xCC, 0x57, + 0xE2, 0x19, 0x61, 0x31, 0xE9, 0x9D, 0xBA, 0x18, 0xB8, 0xD6, 0x6E, 0x9D, 0xEA, 0x79, 0xE5, 0xEE, + 0xD8, 0x49, 0x56, 0x39, 0x6F, 0xD7, 0x4E, 0x5B, 0x16, 0x94, 0xDE, 0xB9, 0x33, 0xE9, 0x87, 0xAE, + 0x3B, 0x0B, 0xDC, 0xC1, 0xAB, 0x49, 0x3E, 0xDE, 0xC9, 0x03, 0xAD, 0x5D, 0x43, 0x8D, 0x5C, 0x03, + 0x6D, 0x33, 0x6F, 0xE8, 0xE9, 0x82, 0x29, 0xB9, 0xA9, 0x27, 0x89, 0x5D, 0xDD, 0xD8, 0xD3, 0xD7, + 0xCC, 0x15, 0x37, 0xF7, 0xCA, 0x2C, 0xB9, 0xE7, 0xB9, 0xC1, 0xA7, 0x2D, 0x9C, 0x67, 0xDB, 0xE4, + 0x93, 0x84, 0x52, 0x6D, 0xA3, 0x2F, 0x1E, 0x2D, 0xDF, 0x75, 0xB3, 0x4F, 0x51, 0x0F, 0xD9, 0xBF, + 0x42, 0x4F, 0xEA, 0xB9, 0x3E, 0x63, 0xCE, 0x6D, 0x4B, 0x30, 0x35, 0x5F, 0xAA, 0x15, 0x36, 0x74, + 0x88, 0x4D, 0xFD, 0xC3, 0x56, 0x11, 0x8A, 0xE7, 0xCA, 0xB6, 0x63, 0xA1, 0x31, 0x5C, 0xC8, 0x66, + 0xA7, 0xA4, 0x03, 0x0F, 0xA9, 0x24, 0x57, 0xCA, 0xAE, 0xA5, 0x94, 0x73, 0x87, 0xBB, 0xDC, 0xF0, + 0x53, 0xEA, 0xD9, 0xF6, 0x7F, 0x78, 0x8E, 0xBB, 0xD4, 0x6C, 0xC6, 0x09, 0x87, 0xB4, 0x2A, 0xAD, + 0xE2, 0x2A, 0x7F, 0xFF, 0x7B, 0xAA, 0x8E, 0x4F, 0xC3, 0xA9, 0xEF, 0x32, 0x77, 0x5D, 0xE3, 0x6E, + 0x48, 0x43, 0x4C, 0x73, 0xA4, 0x98, 0x62, 0x96, 0x61, 0x0A, 0x4C, 0x16, 0x68, 0x4F, 0x54, 0x86, + 0x16, 0x95, 0x4F, 0xEB, 0x9A, 0x59, 0x53, 0xEA, 0x88, 0x15, 0x96, 0xB4, 0x69, 0x77, 0x74, 0xCD, + 0x36, 0xE9, 0x42, 0xEB, 0x8A, 0xDC, 0x59, 0x01, 0xC1, 0xB9, 0x9B, 0x60, 0x6A, 0x24, 0x6A, 0xB7, + 0x08, 0x1F, 0xD2, 0x58, 0x36, 0xA2, 0x3C, 0x87, 0x56, 0x30, 0xF0, 0xF1, 0x69, 0x1E, 0x6D, 0xA1, + 0x33, 0xA2, 0x27, 0x96, 0x6B, 0x0D, 0xA9, 0x7F, 0x81, 0x35, 0x53, 0x49, 0x90, 0x18, 0xFC, 0xEB, + 0x57, 0xA1, 0x4F, 0xAC, 0x91, 0x33, 0x74, 0x77, 0x9B, 0x23, 0x7A, 0x1D, 0x36, 0xE1, 0xC3, 0xCD, + 0x6B, 0xDC, 0x3F, 0x78, 0xB5, 0x06, 0xBF, 0xE0, 0x1F, 0x7D, 0x30, 0x64, 0xE2, 0x0F, 0xFB, 0xF5, + 0x2B, 0xFE, 0x98, 0x62, 0x78, 0x3F, 0xA1, 0xBB, 0xDC, 0xE3, 0xB8, 0xF2, 0xBE, 0x35, 0x89, 0x63, + 0xEF, 0x36, 0x91, 0x20, 0x5F, 0xCE, 0xEF, 0x8D, 0x46, 0x4D, 0xC2, 0xDE, 0xFA, 0x84, 0xAF, 0x9E, + 0x3F, 0x5E, 0x65, 0x15, 0x57, 0x39, 0xA8, 0xC4, 0x17, 0xDB, 0x99, 0x6C, 0x12, 0x11, 0xB8, 0xC8, + 0x31, 0x44, 0x2C, 0x7B, 0xC3, 0x21, 0x26, 0xA5, 0x01, 0x7E, 0xD6, 0x90, 0xEC, 0x5A, 0xE8, 0xC7, + 0x3F, 0x18, 0xDF, 0x92, 0xD9, 0x46, 0x30, 0xD6, 0xC4, 0x0B, 0x6E, 0xC3, 0x1A, 0x0D, 0x49, 0x94, + 0xDF, 0xC6, 0xA3, 0x9B, 0x30, 0x9C, 0xE4, 0x26, 0x9E, 0x92, 0xEA, 0x89, 0xFC, 0x53, 0xEF, 0x0E, + 0x79, 0xFA, 0x29, 0x9C, 0x85, 0x59, 0x76, 0xAC, 0x46, 0xDA, 0x3B, 0x8B, 0x20, 0x58, 0x56, 0x21, + 0xD9, 0x4E, 0x88, 0xB0, 0xB1, 0x81, 0x37, 0x46, 0x33, 0x12, 0x55, 0xF3, 0x69, 0x30, 0x01, 0x77, + 0x82, 0x31, 0xB9, 0x8C, 0x21, 0x3B, 0x22, 0xD7, 0x1A, 0xD9, 0xEF, 0xFF, 0xCC, 0xB3, 0xA3, 0x39, + 0x6E, 0xE8, 0xB1, 0xC9, 0xFF, 0x59, 0xF9, 0x8E, 0x04, 0xF7, 0x5B, 0x69, 0x7E, 0xC1, 0x64, 0xAA, + 0x6A, 0x5D, 0xE6, 0x2B, 0x47, 0xA0, 0xDC, 0x22, 0xEB, 0x68, 0x4A, 0xBF, 0xBD, 0xAB, 0xD0, 0x72, + 0x40, 0x0D, 0xA5, 0x72, 0xA3, 0x8E, 0x1B, 0xEB, 0xE9, 0x7A, 0x2E, 0xA5, 0x6F, 0xC4, 0x0A, 0xBA, + 0x8A, 0x4A, 0x7D, 0x2C, 0x6A, 0x49, 0x3D, 0x1C, 0x37, 0x0B, 0x73, 0xAC, 0x9D, 0x24, 0xCF, 0x38, + 0xA1, 0xFD, 0xFF, 0xFC, 0xC5, 0x5C, 0xCE, 0x36, 0xE4, 0x8D, 0x15, 0xA2, 0xD7, 0x79, 0x33, 0x31, + 0x44, 0x15, 0x14, 0x14, 0x73, 0xD4, 0xB2, 0x28, 0x8F, 0xF1, 0x77, 0x54, 0xB4, 0xAC, 0x9E, 0x58, + 0xD9, 0x95, 0xC5, 0xAF, 0x98, 0x29, 0x72, 0x4E, 0x27, 0x02, 0xBB, 0xE5, 0xDE, 0x73, 0x49, 0x45, + 0x95, 0xD9, 0x91, 0x43, 0xC0, 0x7C, 0xDB, 0x5B, 0x2E, 0xB4, 0x55, 0xE2, 0xB4, 0x69, 0x9B, 0x19, + 0x36, 0xF1, 0x05, 0x5D, 0x1F, 0xFC, 0x13, 0xDF, 0x4F, 0x20, 0xFC, 0x09, 0x09, 0x62, 0x8B, 0xDB, + 0xC2, 0x41, 0x6E, 0x84, 0x5F, 0xAA, 0xDB, 0xB3, 0x9E, 0x03, 0x13, 0xAD, 0x4B, 0xD5, 0xFF, 0xFC, + 0xED, 0x4B, 0xB2, 0x9E, 0x4B, 0x2B, 0xC9, 0x67, 0xD9, 0xEB, 0x79, 0x28, 0x6C, 0x73, 0x64, 0x0A, + 0xAB, 0x34, 0x1A, 0x53, 0x95, 0x12, 0x1E, 0x65, 0x9F, 0x20, 0xA0, 0x25, 0x9A, 0xAD, 0x28, 0x6B, + 0x5E, 0xBB, 0xD9, 0x84, 0x94, 0xD6, 0x5E, 0x11, 0xA4, 0xD9, 0xC0, 0xD1, 0x98, 0x95, 0x4D, 0x25, + 0x4D, 0x88, 0x09, 0x2C, 0x2B, 0x11, 0x6B, 0x4E, 0x16, 0x97, 0x1C, 0x06, 0x98, 0xA6, 0xD7, 0xE6, + 0x40, 0xDB, 0x69, 0xAC, 0x10, 0x69, 0x29, 0xAD, 0xEA, 0x54, 0x53, 0x47, 0x8E, 0x82, 0x60, 0x2A, + 0xA2, 0xDE, 0x8F, 0x0E, 0x5E, 0xB2, 0x0D, 0x75, 0x33, 0x1F, 0x55, 0xA2, 0xF4, 0x55, 0x1A, 0x6F, + 0xD8, 0xB3, 0xEB, 0xF9, 0x26, 0x15, 0xEB, 0x94, 0x35, 0xAB, 0xBC, 0x6E, 0x81, 0x69, 0xC5, 0x4A, + 0xF5, 0xCD, 0xEB, 0x93, 0xB1, 0x8E, 0xAC, 0x19, 0x4F, 0xC2, 0x42, 0xA6, 0x04, 0x5A, 0xD5, 0x4A, + 0xFE, 0xB0, 0x18, 0xFF, 0x12, 0x16, 0x83, 0x8D, 0x3E, 0x67, 0x11, 0x56, 0x43, 0xF2, 0xFB, 0x0E, + 0x60, 0x3A, 0xC4, 0x03, 0x88, 0x24, 0x43, 0xA8, 0xB8, 0xB1, 0x83, 0xCE, 0x5C, 0xF9, 0x84, 0x93, + 0x88, 0xF1, 0xE8, 0x40, 0x3A, 0x54, 0xE3, 0xEC, 0xB8, 0xEC, 0x44, 0xE5, 0xC3, 0x35, 0x43, 0xD6, + 0x8F, 0xEE, 0x02, 0xD5, 0x46, 0xAA, 0x6C, 0x71, 0x60, 0x29, 0x3F, 0xB1, 0x49, 0x22, 0x0B, 0x70, + 0x94, 0xBE, 0xE5, 0x29, 0x27, 0x61, 0x70, 0xF4, 0x31, 0x1F, 0x33, 0x66, 0x44, 0x05, 0xEB, 0x8B, + 0x25, 0x6A, 0x42, 0xE7, 0xB8, 0xAA, 0x64, 0x2F, 0x65, 0x9C, 0xBB, 0x66, 0xEE, 0x97, 0xC5, 0xCA, + 0x2D, 0x39, 0x2F, 0x9C, 0xFA, 0xA3, 0x10, 0x93, 0x94, 0xE0, 0x9A, 0xAF, 0xB1, 0x86, 0x28, 0xFE, + 0xCA, 0xD8, 0x67, 0x7D, 0x25, 0x4B, 0xF3, 0x73, 0x82, 0x1E, 0x5F, 0x0B, 0xC5, 0x63, 0xD4, 0x9F, + 0x2C, 0xC6, 0xCD, 0xAE, 0x2D, 0xBA, 0x41, 0x98, 0x47, 0x59, 0x2B, 0x62, 0xF4, 0x42, 0xA6, 0xE0, + 0x69, 0x43, 0xED, 0x76, 0x74, 0x32, 0xDB, 0xBE, 0xF1, 0xE9, 0x35, 0x3E, 0xBB, 0x1B, 0x55, 0x8B, + 0xEE, 0x73, 0xC6, 0xB4, 0x56, 0x56, 0x76, 0xB2, 0x7A, 0x3F, 0x5A, 0x0B, 0x49, 0x87, 0x4E, 0xC9, + 0xD8, 0xAF, 0xDA, 0x4F, 0x59, 0x79, 0x46, 0x71, 0xD3, 0x28, 0xC1, 0xAA, 0x64, 0x1A, 0x75, 0x53, + 0x79, 0x46, 0x93, 0x8A, 0x98, 0x6B, 0x34, 0x19, 0x5F, 0xD1, 0x72, 0x25, 0x5E, 0x06, 0x26, 0xD7, + 0x14, 0x77, 0x0A, 0x34, 0x9C, 0xAA, 0x19, 0x70, 0xE7, 0xA5, 0xDF, 0xCF, 0xB2, 0xCE, 0xCC, 0x53, + 0xFD, 0x1E, 0x6D, 0xEA, 0x40, 0x7F, 0x33, 0xC6, 0x02, 0x71, 0x78, 0x9E, 0x9A, 0x82, 0x65, 0xCD, + 0xD2, 0x77, 0xF0, 0x64, 0xBB, 0x6B, 0x40, 0x6E, 0x7C, 0xAB, 0xB6, 0xBC, 0x66, 0x7E, 0x4B, 0x29, + 0x24, 0x6B, 0x4B, 0x63, 0xA7, 0xF4, 0x4C, 0x9B, 0x3B, 0xD5, 0xC6, 0x8C, 0x14, 0x4F, 0xB0, 0x52, + 0xDB, 0xD7, 0xD6, 0xCE, 0xE9, 0x35, 0xCC, 0xA8, 0x37, 0x3C, 0xCD, 0x74, 0x1C, 0x56, 0x94, 0xBB, + 0xDC, 0x54, 0x76, 0x4F, 0x76, 0xB4, 0x2B, 0xA4, 0x3C, 0xE3, 0xB3, 0xA6, 0xF1, 0x52, 0x0E, 0x6B, + 0xFC, 0xB5, 0x3B, 0x97, 0xB4, 0xD5, 0x1C, 0x53, 0xCD, 0x4C, 0xD5, 0x9C, 0x51, 0xC3, 0xD5, 0x68, + 0x98, 0xEB, 0x87, 0x3E, 0x66, 0x51, 0x6F, 0x91, 0xE8, 0xD7, 0xF7, 0x30, 0xBD, 0x8F, 0xA8, 0xAF, + 0x0A, 0x96, 0x61, 0x49, 0x83, 0x33, 0x0B, 0xD3, 0x02, 0xEB, 0xC2, 0x13, 0x3E, 0x57, 0x01, 0xE5, + 0x87, 0x11, 0x2D, 0x7E, 0x28, 0x51, 0x05, 0xD0, 0xBA, 0xF2, 0xFC, 0x10, 0x00, 0xD9, 0xFF, 0xB3, + 0x01, 0x33, 0x92, 0x73, 0x8F, 0xF2, 0x13, 0x73, 0x4B, 0xAF, 0x1B, 0x68, 0xF2, 0x88, 0xD2, 0x28, + 0x27, 0xDD, 0x3C, 0xA1, 0xFE, 0x80, 0xDF, 0x8F, 0xE5, 0x65, 0xED, 0x11, 0x4B, 0xB9, 0x4C, 0xD6, + 0x08, 0xFF, 0x33, 0xF4, 0x42, 0xDC, 0x07, 0xFC, 0x0B, 0x1E, 0xED, 0x4B, 0xD9, 0xA8, 0x05, 0xDA, + 0x37, 0x96, 0x2F, 0x1D, 0xD2, 0x9D, 0x58, 0xE1, 0x4D, 0xDB, 0xF7, 0xA6, 0xC0, 0x8D, 0x40, 0xBB, + 0x9C, 0x80, 0x4C, 0xA5, 0x7C, 0xDE, 0x9A, 0x63, 0x6C, 0x80, 0xC3, 0x41, 0xF7, 0xBF, 0x85, 0x6A, + 0x52, 0x9B, 0x67, 0x09, 0x8F, 0xB7, 0x84, 0x05, 0xCB, 0xAF, 0xF1, 0x45, 0x8D, 0x4E, 0xEA, 0x61, + 0xA0, 0x6C, 0x3A, 0x8D, 0xB3, 0x24, 0xF1, 0x78, 0x8B, 0xDC, 0xE1, 0x15, 0x2C, 0x77, 0xC8, 0x15, + 0x1D, 0xBC, 0x4F, 0xA6, 0xDD, 0xF7, 0xD0, 0x41, 0xE3, 0x86, 0xE1, 0xB1, 0x57, 0x4D, 0x3B, 0x54, + 0x41, 0x16, 0xD1, 0xE5, 0x19, 0xC5, 0x49, 0x9C, 0x52, 0xBC, 0x48, 0x90, 0xD1, 0xC1, 0xD1, 0x3C, + 0x86, 0x3A, 0xFB, 0x16, 0x9B, 0x73, 0x4C, 0x08, 0xCE, 0x8F, 0x26, 0xDE, 0xDC, 0x1F, 0xD9, 0x55, + 0xB9, 0x96, 0xE4, 0x21, 0x6B, 0x7C, 0x2D, 0x61, 0xBC, 0xB5, 0x80, 0x49, 0x5B, 0x45, 0x2A, 0x8F, + 0x86, 0x5A, 0x48, 0xF7, 0x10, 0x81, 0xC0, 0x9A, 0xA0, 0x0D, 0x07, 0x22, 0x5B, 0xE4, 0x1B, 0x9C, + 0x41, 0x15, 0xD7, 0x26, 0xB9, 0xE7, 0x7F, 0x31, 0x28, 0x95, 0xC5, 0x92, 0x9F, 0x90, 0xC5, 0x18, + 0xD5, 0x58, 0x54, 0xE3, 0x36, 0x20, 0x3F, 0xD2, 0xCB, 0x80, 0x88, 0xDA, 0x16, 0x17, 0x63, 0x56, + 0x40, 0xF9, 0xE5, 0x97, 0xED, 0x8D, 0x17, 0xA6, 0x99, 0x1C, 0xEA, 0xF3, 0xB4, 0x9F, 0x05, 0x4D, + 0x2A, 0x93, 0x8E, 0x34, 0x6E, 0x92, 0x29, 0x91, 0x68, 0x7E, 0x93, 0xB2, 0x52, 0x8F, 0x0E, 0xE5, + 0xE2, 0x92, 0x4D, 0x9A, 0xDA, 0x93, 0xBC, 0xC6, 0x7C, 0xB4, 0x2B, 0x34, 0x66, 0x6A, 0x67, 0xE4, + 0x0B, 0xCC, 0x69, 0x4E, 0x26, 0x4C, 0xAC, 0x7F, 0xB6, 0xB9, 0x41, 0xDD, 0x4E, 0xB7, 0xDB, 0x31, + 0xB5, 0xC8, 0xBE, 0x19, 0x4C, 0x0E, 0x61, 0x19, 0xE9, 0xBB, 0x34, 0x4C, 0xB7, 0x4A, 0x14, 0x1C, + 0xBC, 0xDF, 0x3F, 0xCB, 0x6F, 0x92, 0x94, 0x31, 0xFC, 0xE8, 0x4C, 0x65, 0x31, 0xC2, 0x9E, 0xDB, + 0x3C, 0x29, 0x93, 0x77, 0x31, 0xBC, 0xCC, 0x3F, 0x14, 0xE0, 0x65, 0x6F, 0x16, 0xE7, 0xAC, 0x7A, + 0xC3, 0x5A, 0x20, 0x3C, 0x7E, 0xBB, 0x73, 0xAE, 0x9D, 0x53, 0x0E, 0x50, 0xCA, 0x81, 0x74, 0xEC, + 0x7F, 0xDB, 0x95, 0x60, 0xBE, 0x34, 0xC9, 0x4F, 0x3F, 0x91, 0xB8, 0xEC, 0xCF, 0xBB, 0xFD, 0xBE, + 0xEE, 0x3C, 0x6B, 0xFE, 0x9E, 0x4C, 0x30, 0xCB, 0xDD, 0x43, 0x61, 0xCB, 0xF5, 0xD0, 0xA3, 0x63, + 0xDD, 0x16, 0x9F, 0x28, 0x92, 0xCE, 0xB2, 0x16, 0x81, 0x00, 0x4D, 0xC3, 0xB5, 0x81, 0xE4, 0x71, + 0x45, 0x87, 0x52, 0xAC, 0x4C, 0xF3, 0x9E, 0x58, 0xBF, 0x9D, 0xD2, 0xBB, 0x28, 0xC5, 0x91, 0xD2, + 0xCF, 0x7A, 0xDE, 0x94, 0x3F, 0xC5, 0x09, 0x95, 0xA1, 0xAD, 0x4B, 0x9A, 0x78, 0x59, 0x28, 0x80, + 0xAE, 0xCA, 0x27, 0xC1, 0x90, 0x07, 0x56, 0x34, 0xA3, 0xD7, 0x29, 0xF6, 0x05, 0x41, 0x28, 0xC1, + 0xE7, 0x4F, 0x7E, 0x71, 0xDE, 0x3A, 0x6C, 0x62, 0xC0, 0x8B, 0xDF, 0x74, 0x3C, 0x09, 0xEF, 0x65, + 0xB5, 0x35, 0xB8, 0xCE, 0x22, 0x27, 0xDC, 0xBE, 0xC6, 0x77, 0x56, 0x00, 0xA2, 0x60, 0x22, 0x93, + 0x3E, 0xE8, 0x91, 0x8B, 0xD7, 0x9A, 0x61, 0x22, 0x85, 0x39, 0x54, 0x34, 0xA9, 0xA1, 0xBD, 0x1F, + 0x84, 0xFA, 0x21, 0x1E, 0x8B, 0xC0, 0x1D, 0x1F, 0xE9, 0xC4, 0x08, 0x96, 0xA3, 0xE0, 0xBC, 0x90, + 0xC1, 0xD4, 0xF7, 0x71, 0x4A, 0x67, 0xAD, 0xC1, 0x9E, 0x67, 0xDB, 0x33, 0x67, 0xBF, 0x04, 0x89, + 0xCA, 0x8D, 0x02, 0x31, 0x71, 0xD5, 0xD3, 0xAE, 0x1C, 0x45, 0x92, 0x50, 0x67, 0xE9, 0x91, 0xC4, + 0xFC, 0xCA, 0xAE, 0x0C, 0x90, 0x2C, 0x11, 0x5A, 0xB8, 0x7C, 0xD0, 0x4A, 0xA2, 0x80, 0x6A, 0x28, + 0x54, 0xFA, 0x40, 0xB5, 0x6C, 0xE7, 0xFB, 0x52, 0x27, 0xE8, 0x76, 0x20, 0x83, 0x85, 0x14, 0x68, + 0x0B, 0x6B, 0x47, 0x64, 0xD0, 0x00, 0x94, 0x06, 0x64, 0x3D, 0xD5, 0x8A, 0x3A, 0x44, 0xAB, 0xAD, + 0xAB, 0x37, 0xBE, 0xDF, 0x11, 0xDD, 0x5B, 0x91, 0xF7, 0x68, 0xA2, 0x72, 0xB6, 0x81, 0x00, 0xF0, + 0x62, 0x4F, 0x26, 0x46, 0xB6, 0x6C, 0x7C, 0x1A, 0x44, 0x29, 0x4F, 0x6E, 0x73, 0x48, 0xF4, 0x8C, + 0x8F, 0x35, 0xA5, 0x98, 0x32, 0x3D, 0xD9, 0xC4, 0x2A, 0x01, 0x72, 0xD3, 0xD8, 0x54, 0x9E, 0x1C, + 0xCA, 0x20, 0xB9, 0x9C, 0xDE, 0x73, 0x68, 0xEC, 0x23, 0x1C, 0x53, 0x75, 0xC1, 0x16, 0xAA, 0x53, + 0x06, 0x7C, 0x7C, 0x5F, 0xA4, 0x70, 0x04, 0x09, 0x46, 0xE3, 0x47, 0x6A, 0x08, 0x4C, 0x31, 0x01, + 0x0B, 0xBF, 0xD8, 0xD1, 0xCC, 0x71, 0x4C, 0xE3, 0x67, 0x5E, 0x63, 0xE9, 0x5A, 0xFD, 0x5B, 0x69, + 0x5F, 0x26, 0x4D, 0xE9, 0xE1, 0x4E, 0x0D, 0x9E, 0x67, 0x7C, 0x3F, 0x3F, 0xFF, 0x70, 0xDE, 0xA8, + 0x6C, 0x88, 0xC4, 0x48, 0x23, 0x20, 0x11, 0x3E, 0x4B, 0xB2, 0xEC, 0x1E, 0xD6, 0x2D, 0xB8, 0x79, + 0xFC, 0x10, 0x75, 0x47, 0x9B, 0xD0, 0x6C, 0xE7, 0xF6, 0x1D, 0x0D, 0x15, 0x13, 0xA4, 0xCE, 0xB7, + 0x85, 0x56, 0x4A, 0xDB, 0x5D, 0x54, 0x8D, 0x9D, 0xB2, 0xC1, 0x69, 0x6A, 0xE7, 0xFE, 0xC7, 0xF3, + 0xF3, 0xC3, 0xD3, 0x0B, 0x53, 0x4B, 0x33, 0x1B, 0x19, 0xAB, 0x39, 0x18, 0xDB, 0xE9, 0x04, 0x2D, + 0x1E, 0x4F, 0xB4, 0xF7, 0xC8, 0x6D, 0x93, 0x0D, 0xB9, 0x4E, 0x47, 0xF7, 0x8B, 0x59, 0xBC, 0x1B, + 0x30, 0x7A, 0xDB, 0x60, 0xB7, 0x41, 0x14, 0x39, 0xEC, 0xE4, 0x22, 0x32, 0x73, 0xA3, 0xBE, 0xBF, + 0x84, 0xD8, 0xCF, 0xB2, 0xD6, 0x30, 0x66, 0x55, 0x54, 0x81, 0x24, 0x85, 0x14, 0x89, 0xC1, 0x4D, + 0xA2, 0xD3, 0x0E, 0x77, 0xF4, 0x31, 0xFD, 0x74, 0x26, 0xDC, 0xEF, 0xDF, 0xFD, 0xC6, 0x59, 0xBC, + 0x94, 0x41, 0x48, 0x29, 0x7F, 0xBA, 0xA7, 0xA0, 0xFD, 0xEF, 0xC4, 0xA3, 0x4F, 0xB8, 0x59, 0x73, + 0x2D, 0x35, 0xEF, 0xC7, 0x44, 0xAF, 0x4E, 0xF4, 0x86, 0xC9, 0x54, 0xD5, 0xDC, 0x45, 0x4F, 0xA5, + 0x2A, 0x35, 0xE3, 0x44, 0xAA, 0x31, 0x64, 0x9A, 0x46, 0x87, 0x1C, 0xAF, 0x3C, 0xE2, 0xA4, 0xC0, + 0xB0, 0xE8, 0x66, 0x05, 0xDA, 0xD3, 0x6E, 0x23, 0xF3, 0x55, 0x3F, 0x23, 0x2B, 0xCB, 0x46, 0x4B, + 0x1D, 0x61, 0x4B, 0xCF, 0x42, 0x0B, 0x1A, 0x5A, 0x45, 0x26, 0x9F, 0x59, 0x83, 0x48, 0x0C, 0xAA, + 0xD6, 0x2B, 0x8F, 0x6C, 0xAA, 0x4B, 0x27, 0x2F, 0xB4, 0x22, 0xEA, 0xE2, 0x09, 0x3B, 0xB1, 0x6B, + 0x15, 0xED, 0xA6, 0x18, 0x5D, 0x91, 0x2C, 0x39, 0x95, 0x1F, 0x9E, 0x1A, 0x15, 0xBE, 0x8D, 0xA6, + 0x3F, 0x65, 0x57, 0xD6, 0x84, 0x6B, 0xC8, 0xA4, 0xCD, 0x7D, 0x9D, 0xCC, 0x6E, 0x6A, 0x2B, 0x4E, + 0x7B, 0x31, 0x53, 0x49, 0xA7, 0xF0, 0xCE, 0xB9, 0xA5, 0x2E, 0xB1, 0xF0, 0xE9, 0x55, 0xBF, 0x19, + 0x88, 0x0C, 0x60, 0x28, 0xCC, 0x7B, 0x9C, 0xA8, 0xA0, 0x9B, 0xDD, 0xD0, 0xB9, 0xE6, 0x79, 0xB8, + 0x30, 0xEE, 0x8D, 0x99, 0x08, 0xB1, 0x06, 0xC3, 0x6F, 0x49, 0x48, 0x33, 0x71, 0x5C, 0x72, 0x70, + 0xD0, 0xB6, 0xA3, 0x7F, 0x6C, 0xC3, 0xD9, 0x92, 0xC2, 0xB8, 0x23, 0x5C, 0x47, 0x68, 0x2B, 0xF0, + 0xB5, 0xA4, 0x25, 0xA4, 0x79, 0xE8, 0x02, 0x29, 0x75, 0x3D, 0x1B, 0x61, 0x8C, 0x2B, 0x42, 0xF3, + 0xD5, 0x77, 0x96, 0x82, 0xF6, 0xFE, 0x87, 0x0F, 0xE7, 0x07, 0x47, 0xA7, 0x7B, 0x17, 0x87, 0x97, + 0x47, 0xA7, 0x67, 0x1F, 0x2F, 0x2E, 0x2F, 0x3E, 0x9D, 0xE1, 0xAF, 0x3F, 0xEF, 0x1D, 0x1F, 0x1D, + 0x5C, 0x7E, 0x3C, 0xFD, 0xDB, 0xE9, 0x87, 0x5F, 0x4E, 0x93, 0x4D, 0x6D, 0xDB, 0x0A, 0x6E, 0xA4, + 0x1B, 0xE3, 0xB1, 0x79, 0xC4, 0x90, 0x73, 0xC3, 0x77, 0x9B, 0x0E, 0x9C, 0xB1, 0x35, 0x32, 0x94, + 0x70, 0x53, 0xF5, 0xE1, 0xFA, 0x98, 0xB2, 0xF7, 0x13, 0xF5, 0xD3, 0x3D, 0x30, 0x1E, 0xE0, 0x6D, + 0x85, 0xF8, 0x4C, 0x57, 0x2C, 0x17, 0xFE, 0x1A, 0x0E, 0xDE, 0x45, 0x46, 0xF5, 0x22, 0x77, 0x37, + 0x16, 0x9B, 0xAE, 0x86, 0x4C, 0xF0, 0x20, 0xE3, 0x69, 0x10, 0x5B, 0xE5, 0x81, 0xE5, 0x12, 0x8A, + 0x02, 0x61, 0x26, 0xD3, 0x71, 0xA1, 0xF3, 0x1D, 0x9B, 0xDD, 0x2A, 0x0F, 0x44, 0x95, 0x3D, 0xC2, + 0xBF, 0xF1, 0x5A, 0xF8, 0xE0, 0x28, 0xCB, 0x03, 0xC7, 0xCF, 0x01, 0x83, 0x16, 0x59, 0x6D, 0x61, + 0xBC, 0x69, 0x8B, 0x75, 0x53, 0x5B, 0x3D, 0xEB, 0x92, 0x8C, 0x6F, 0x2C, 0x78, 0xDD, 0xF4, 0xAA, + 0xD7, 0x68, 0x03, 0xDB, 0x19, 0x3A, 0x61, 0xD2, 0x4D, 0x78, 0x88, 0x9B, 0x75, 0xA5, 0x12, 0x01, + 0x54, 0xB1, 0xB1, 0x68, 0x7A, 0xA3, 0xBC, 0x56, 0x56, 0xF2, 0x5E, 0x0C, 0x91, 0xC9, 0x21, 0x96, + 0xE6, 0x6A, 0x73, 0x39, 0xE9, 0xC0, 0x95, 0x15, 0xF6, 0x8A, 0xD1, 0x68, 0x44, 0x86, 0x9E, 0x67, + 0x97, 0x80, 0x26, 0x00, 0x9D, 0xF4, 0x73, 0x65, 0xF0, 0x36, 0x12, 0x97, 0xDA, 0x95, 0x87, 0x20, + 0xDA, 0x9B, 0xA8, 0xA5, 0xAC, 0xE2, 0x3C, 0x98, 0x2D, 0x69, 0x40, 0x8D, 0x30, 0xD2, 0x25, 0x50, + 0x54, 0x80, 0x25, 0x16, 0x50, 0x0F, 0x9F, 0xC0, 0xBB, 0x47, 0x25, 0x9A, 0x78, 0x41, 0xE0, 0x60, + 0x3C, 0x2C, 0xD7, 0x0A, 0x1C, 0xA7, 0x91, 0xBE, 0x24, 0x43, 0x32, 0xF9, 0x70, 0x72, 0xD2, 0x1E, + 0xF3, 0x7F, 0xC9, 0x37, 0x62, 0xFA, 0xB8, 0x6A, 0xFA, 0x78, 0x72, 0xD2, 0xEF, 0xB7, 0x03, 0xF6, + 0x4F, 0x01, 0x27, 0x86, 0xCF, 0x80, 0x60, 0x35, 0xF9, 0xFC, 0xCC, 0xA8, 0x27, 0xEC, 0x16, 0xD7, + 0xEC, 0x92, 0xFB, 0xBF, 0x18, 0x24, 0xEC, 0x7A, 0x6D, 0xB2, 0x01, 0xA3, 0x6D, 0xBB, 0xB3, 0xBE, + 0xBE, 0xF1, 0x9C, 0xE5, 0xDF, 0x63, 0xF2, 0x6B, 0x27, 0x11, 0xCA, 0xC9, 0x88, 0x7F, 0x4D, 0x7A, + 0xF3, 0x20, 0xFC, 0x01, 0xC7, 0x5F, 0x87, 0xE5, 0x84, 0x80, 0x91, 0xD6, 0x23, 0xD6, 0x08, 0xB3, + 0x12, 0xDA, 0xC8, 0x08, 0xE9, 0x6C, 0x92, 0xDE, 0x66, 0xBB, 0xD7, 0xD9, 0xD8, 0x36, 0xB0, 0x92, + 0xD8, 0xA4, 0xD7, 0x64, 0x7D, 0xCE, 0x9C, 0xF4, 0x18, 0x33, 0xEB, 0x09, 0x33, 0xAB, 0xDD, 0xCE, + 0xE6, 0x6A, 0xB7, 0xBB, 0xDA, 0xD9, 0x6C, 0x77, 0xB7, 0x7A, 0x26, 0x76, 0xCC, 0x96, 0xED, 0x35, + 0x06, 0xF9, 0xCF, 0x89, 0xB5, 0xE7, 0xC8, 0xD3, 0x35, 0xBD, 0xA3, 0x3E, 0xE7, 0xA7, 0xDB, 0x45, + 0x6E, 0x5E, 0xBC, 0xD8, 0xDE, 0xEE, 0x91, 0xA5, 0x03, 0xAE, 0x59, 0x58, 0x85, 0xFF, 0xB6, 0x1C, + 0xF3, 0x98, 0xB8, 0xB3, 0x2E, 0x1D, 0x5A, 0x21, 0xD8, 0xCD, 0xBE, 0x33, 0x74, 0x55, 0xEF, 0x41, + 0x1D, 0xBB, 0x9D, 0xC4, 0x70, 0x24, 0x56, 0x2A, 0x2E, 0xE6, 0x7E, 0x17, 0x06, 0xD6, 0xEF, 0x49, + 0xC6, 0xAD, 0x85, 0xA2, 0xC3, 0xD8, 0x77, 0x76, 0xD2, 0x83, 0xD1, 0xF7, 0x60, 0xBC, 0x98, 0x28, + 0xB8, 0xF9, 0x48, 0xEE, 0xDA, 0xA8, 0x4C, 0xA8, 0x81, 0x3D, 0x71, 0xA7, 0xAE, 0xAE, 0x22, 0x22, + 0x4C, 0xA4, 0x99, 0xF4, 0x33, 0x58, 0x6B, 0x9C, 0x33, 0x1D, 0x97, 0x3F, 0xF6, 0xC1, 0x4A, 0x28, + 0xB7, 0xE0, 0x3C, 0xFF, 0x26, 0x4B, 0x4D, 0x21, 0x88, 0x46, 0x64, 0x48, 0x00, 0x74, 0xF4, 0x0D, + 0x2B, 0x59, 0x8F, 0xB9, 0xA1, 0xC5, 0x35, 0x95, 0x34, 0xCB, 0xC5, 0xDF, 0x32, 0xFA, 0x75, 0x97, + 0xDD, 0xDE, 0xC0, 0xC7, 0x01, 0x33, 0xCB, 0xB7, 0x96, 0x61, 0x41, 0xB6, 0xB6, 0x96, 0x1E, 0xF1, + 0xF2, 0x03, 0xCE, 0xF5, 0xE7, 0x6A, 0x8E, 0x57, 0x3A, 0x95, 0xE7, 0x69, 0x38, 0xD8, 0xA1, 0x0B, + 0xBF, 0xC6, 0xC3, 0x8E, 0x22, 0x41, 0xBC, 0xEE, 0x20, 0xBA, 0x1D, 0x9D, 0x38, 0x0C, 0xAC, 0x9B, + 0xC0, 0xF9, 0x24, 0x42, 0x6F, 0x14, 0x2C, 0xC2, 0xBE, 0xA8, 0x28, 0x24, 0xD4, 0xFC, 0x6E, 0x74, + 0x47, 0xC6, 0x91, 0x4C, 0x7C, 0x49, 0xB5, 0xD5, 0xDD, 0xD8, 0x54, 0xF1, 0x33, 0x57, 0xE5, 0x3E, + 0x35, 0x4B, 0xE5, 0xEB, 0xB8, 0xD3, 0x90, 0xC5, 0x68, 0xE4, 0x10, 0x8A, 0xC9, 0x9C, 0x9C, 0xC8, + 0x71, 0x71, 0x6F, 0x1D, 0x98, 0xA2, 0x61, 0x7A, 0x51, 0xA6, 0xDC, 0x64, 0x62, 0x66, 0x97, 0x8B, + 0x3E, 0x5C, 0x2F, 0xB1, 0x09, 0x08, 0x7A, 0x63, 0xB5, 0xAB, 0xEF, 0x8D, 0xCF, 0x2A, 0xFA, 0xCB, + 0xD3, 0x0F, 0x97, 0x07, 0x87, 0xFB, 0x47, 0x27, 0x7B, 0xC7, 0x5A, 0x2F, 0x04, 0x14, 0x26, 0x20, + 0x1B, 0x9B, 0x15, 0xF3, 0xA3, 0x89, 0x5B, 0x56, 0x07, 0xBE, 0xB8, 0xE2, 0x10, 0x46, 0x91, 0x25, + 0x03, 0x4A, 0x16, 0xB4, 0x0C, 0x12, 0xC9, 0xF1, 0x2F, 0xB1, 0xBC, 0x04, 0x00, 0x88, 0x4C, 0x0A, + 0x43, 0x33, 0xB8, 0x56, 0x11, 0xB1, 0x95, 0x04, 0xC9, 0x1A, 0xD9, 0x82, 0x29, 0x80, 0x5D, 0xAA, + 0x8F, 0x68, 0xAC, 0x91, 0xF5, 0x2D, 0xCC, 0x26, 0xB3, 0xAC, 0xDD, 0x0A, 0x57, 0x46, 0xB2, 0xD9, + 0xAF, 0x31, 0x91, 0xFD, 0x0B, 0x76, 0x87, 0xFC, 0xC2, 0xE1, 0x83, 0x69, 0xF5, 0xA4, 0x0D, 0x51, + 0x1C, 0x8D, 0xEA, 0x00, 0x65, 0xE3, 0x33, 0x73, 0xF8, 0x6D, 0xE2, 0xE8, 0xCC, 0x2C, 0xDD, 0x88, + 0xC7, 0xA6, 0x32, 0x43, 0xCF, 0x6F, 0x68, 0x96, 0x1C, 0x98, 0xC9, 0x88, 0x54, 0x34, 0x24, 0x63, + 0x38, 0xEA, 0x43, 0xA3, 0xEA, 0x00, 0xCC, 0x1C, 0x7E, 0x66, 0x3D, 0x55, 0x44, 0xC3, 0x22, 0x7D, + 0x05, 0x80, 0x01, 0xB1, 0x59, 0x49, 0xAB, 0x2A, 0xDD, 0x82, 0xF5, 0x4B, 0x55, 0x30, 0x45, 0x9B, + 0xBA, 0x5C, 0x1F, 0x56, 0x17, 0xA4, 0x10, 0x97, 0x27, 0x27, 0x97, 0x07, 0x7B, 0xFD, 0xF7, 0x9A, + 0x5A, 0x88, 0x78, 0xA3, 0xC4, 0x6C, 0x89, 0xDB, 0x64, 0xAB, 0xFA, 0x6D, 0xC3, 0x44, 0x07, 0x84, + 0x29, 0x47, 0x48, 0xCC, 0x5F, 0x94, 0x74, 0x58, 0x46, 0xD7, 0xCA, 0xF5, 0xBB, 0x5F, 0x24, 0x63, + 0x9A, 0xEA, 0xDD, 0x27, 0xD6, 0x59, 0xD9, 0x7D, 0xD5, 0x8B, 0xFB, 0x2A, 0xF2, 0x8E, 0xE7, 0xDE, + 0x57, 0x60, 0xDE, 0x9F, 0x58, 0x77, 0x3D, 0x99, 0xB9, 0x4F, 0x12, 0x4F, 0x99, 0x29, 0x50, 0x6E, + 0x50, 0x2F, 0x69, 0x50, 0x7A, 0x0E, 0xFC, 0xA3, 0x4F, 0x50, 0x5C, 0x29, 0x93, 0x0D, 0x9C, 0xB9, + 0xEA, 0xE4, 0x4E, 0x81, 0x98, 0x12, 0x03, 0xFE, 0xDD, 0x04, 0x20, 0x2C, 0x28, 0x59, 0x9C, 0x05, + 0x2D, 0x39, 0x1A, 0xC9, 0x0F, 0xE3, 0x99, 0xD7, 0x4F, 0xBD, 0xB8, 0x9F, 0xC8, 0x62, 0xD6, 0x25, + 0xDC, 0x40, 0x3C, 0xA1, 0xCE, 0x7A, 0x6A, 0xA6, 0xF3, 0x7F, 0x9A, 0xD5, 0x14, 0x1B, 0x5A, 0xCA, + 0xC9, 0x90, 0x01, 0x01, 0x3F, 0x1C, 0x32, 0x14, 0xC4, 0xD9, 0xB5, 0xB6, 0x97, 0xB5, 0xAB, 0xF5, + 0x86, 0xEE, 0xE0, 0x67, 0x3E, 0xC9, 0xC6, 0xBC, 0xB4, 0xC3, 0x8E, 0x9B, 0xBA, 0xC9, 0x15, 0xF4, + 0x16, 0xF1, 0xA6, 0x21, 0xFE, 0x61, 0x89, 0x5D, 0x7B, 0x00, 0xEA, 0x7B, 0xEA, 0x1E, 0x3C, 0x6E, + 0x28, 0x5F, 0x81, 0xB4, 0xC6, 0x94, 0x34, 0xB5, 0x21, 0xD3, 0x6C, 0x11, 0x1A, 0x0E, 0xE4, 0xA0, + 0x5A, 0xC6, 0x37, 0xE3, 0x43, 0xE2, 0xAB, 0x65, 0x52, 0x19, 0xF3, 0x7E, 0xBD, 0xD8, 0xBC, 0x94, + 0x0E, 0x1A, 0xF9, 0xDD, 0x03, 0x83, 0xC6, 0x95, 0x57, 0xB9, 0x65, 0xE3, 0xB0, 0x4E, 0x34, 0x2C, + 0xF9, 0xB6, 0x2C, 0x89, 0x59, 0x3F, 0xAD, 0x95, 0xD9, 0x30, 0x9F, 0x75, 0xCD, 0xC8, 0xE6, 0xA5, + 0xB4, 0xE6, 0x81, 0x75, 0xDB, 0x8C, 0xD8, 0xE6, 0x8A, 0x2C, 0x72, 0xDD, 0xE7, 0x8C, 0xB2, 0xFF, + 0xE9, 0xE4, 0xCD, 0x87, 0x63, 0x86, 0x54, 0xBF, 0xD4, 0x31, 0xF2, 0xDC, 0x21, 0xCB, 0x63, 0x74, + 0x40, 0x87, 0x3E, 0xD5, 0xF7, 0x47, 0x52, 0x3D, 0xA1, 0x75, 0x2D, 0x2C, 0xCE, 0x74, 0x04, 0xC6, + 0x7A, 0x30, 0x5C, 0xB7, 0x3A, 0x3B, 0x5A, 0x6E, 0xC8, 0xB8, 0xF4, 0x15, 0xC9, 0xB4, 0x7C, 0x7C, + 0xA0, 0x4B, 0xA6, 0x4B, 0xD1, 0xAB, 0x41, 0x7A, 0xD8, 0x3E, 0x5F, 0x4E, 0xE5, 0xA0, 0x9C, 0xB1, + 0x7B, 0xB3, 0x58, 0x8B, 0x87, 0x50, 0x4A, 0x84, 0x2B, 0x30, 0xAA, 0x98, 0x75, 0x89, 0xAA, 0xEE, + 0xA4, 0x0F, 0x2F, 0xE6, 0xA4, 0x28, 0xB5, 0x98, 0x5B, 0x7D, 0x0C, 0xEE, 0xB8, 0xCE, 0xD5, 0xE2, + 0xEF, 0xBF, 0xFF, 0x4B, 0x65, 0x10, 0xBF, 0x35, 0x1B, 0x2A, 0x9B, 0x75, 0xF0, 0x12, 0x53, 0xBB, + 0x35, 0xDB, 0x32, 0x97, 0xA6, 0xF7, 0x97, 0xE5, 0x01, 0x3C, 0xBB, 0x0A, 0xCE, 0x19, 0xA1, 0xB4, + 0xAA, 0x5A, 0x04, 0x5E, 0xBD, 0xE7, 0xE7, 0x24, 0x02, 0xC9, 0x95, 0x59, 0x04, 0xD7, 0x8B, 0xC5, + 0xAE, 0xAD, 0x60, 0x97, 0xFF, 0xE8, 0x66, 0x58, 0xE1, 0xF9, 0xC4, 0xB4, 0xB5, 0x5E, 0x85, 0x67, + 0x81, 0x20, 0x8F, 0xE7, 0xD2, 0x13, 0xC0, 0xD6, 0xDC, 0x27, 0x00, 0x79, 0xF4, 0x55, 0x9C, 0x02, + 0x52, 0x22, 0x7A, 0xA4, 0xA9, 0x21, 0x35, 0xBA, 0xAB, 0xCE, 0x0E, 0x26, 0xC6, 0x57, 0x1F, 0x89, + 0xF3, 0x99, 0x67, 0x0E, 0x13, 0xF3, 0xCD, 0xF4, 0x94, 0xF2, 0xF7, 0x46, 0x63, 0x51, 0x6D, 0x58, + 0xAE, 0x3D, 0x3D, 0x99, 0x78, 0x27, 0x8B, 0x16, 0x7C, 0xA6, 0x79, 0x9D, 0x93, 0xBA, 0x4B, 0x17, + 0x15, 0x8D, 0x66, 0x61, 0xCE, 0x0A, 0x34, 0x63, 0x4B, 0xF2, 0xFB, 0xE1, 0x91, 0xDB, 0xA2, 0x4F, + 0x1C, 0xF3, 0x1F, 0xD1, 0x79, 0x0D, 0x4A, 0x5D, 0xE4, 0x51, 0xE9, 0x69, 0x31, 0x8F, 0x51, 0x10, + 0xD2, 0x00, 0x1F, 0x55, 0x14, 0x30, 0x6B, 0x7F, 0xB7, 0xD7, 0xDA, 0x21, 0x5E, 0x49, 0x1E, 0x2C, + 0xEF, 0x10, 0x35, 0x65, 0x42, 0x74, 0xAE, 0x0F, 0x4B, 0xE2, 0x16, 0xCF, 0xD0, 0x08, 0x2B, 0xD8, + 0x1B, 0x5F, 0x0E, 0x92, 0xE4, 0xE9, 0x25, 0x5F, 0xE3, 0xAA, 0x39, 0xBA, 0x7A, 0xB4, 0x2A, 0x05, + 0xA1, 0xC0, 0x67, 0x65, 0x91, 0x8E, 0xD5, 0x94, 0xC4, 0x88, 0x22, 0xF9, 0xE4, 0x0A, 0xE2, 0xC5, + 0x68, 0x50, 0xA5, 0x9C, 0x23, 0x5F, 0x61, 0x69, 0xE4, 0xE5, 0x75, 0xBC, 0xAB, 0xAC, 0xDC, 0x05, + 0x6A, 0x0B, 0xDF, 0xB4, 0x74, 0x79, 0x2E, 0x3B, 0xB1, 0x86, 0x97, 0x6E, 0x0B, 0x8B, 0x92, 0x24, + 0x5E, 0x2E, 0x67, 0x25, 0x1E, 0xDC, 0x39, 0xE1, 0xE0, 0x86, 0xE4, 0x55, 0x61, 0xE1, 0x09, 0xF4, + 0xDA, 0x9A, 0x8E, 0xC2, 0x97, 0x5A, 0x36, 0x7C, 0xDE, 0x13, 0x8D, 0x8F, 0xEE, 0x57, 0xD7, 0xBB, + 0x73, 0xF5, 0x94, 0xB2, 0xDA, 0xCB, 0x0B, 0x03, 0xBC, 0xB6, 0xBB, 0x54, 0x7A, 0xFD, 0x9E, 0x41, + 0x4B, 0xDE, 0xA6, 0x98, 0x2B, 0x41, 0x58, 0x5C, 0x65, 0x92, 0x4C, 0xF6, 0x3D, 0xE7, 0x4A, 0xF2, + 0x32, 0x8F, 0x26, 0x59, 0x1C, 0x51, 0x3E, 0x1F, 0x67, 0x52, 0x5E, 0x5D, 0x10, 0x65, 0xE6, 0xBD, + 0xE4, 0xC8, 0x38, 0xDE, 0x62, 0x9A, 0x7B, 0x7B, 0xF3, 0xE8, 0x2A, 0x9B, 0x5B, 0x0B, 0xA0, 0x5C, + 0x2C, 0xEC, 0xD5, 0xC5, 0x90, 0xD7, 0x27, 0xD2, 0x5C, 0xC9, 0x2F, 0xA2, 0xE1, 0x65, 0x68, 0x73, + 0xE9, 0x2F, 0x4A, 0xEC, 0xA5, 0x58, 0xE0, 0x3D, 0x90, 0xC3, 0xC2, 0xC3, 0xB3, 0x2C, 0x6B, 0xF7, + 0xF0, 0xFF, 0x01, 0x0F, 0xF8, 0x5F, 0x58, 0x32, 0x95, 0x00 }; ///main_js //To convert AP-Config\index.html to index_html[], run the Python index_html_zipper.py script in the Tools folder: @@ -1037,7 +1037,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x17, 0x68, 0x78, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0xB7, 0x72, 0x78, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x07, 0x49, 0x96, 0xF5, 0x6C, 0x9D, 0x43, 0x4D, 0xB6, 0xFA, 0x49, 0x36, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From 98d979d771b05ec10cc6916508c93bd846dca544 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Sat, 4 Jan 2025 08:29:09 -0700 Subject: [PATCH 086/276] Explicitly define the network each consumer can use This allows NTRIP Caster to use any Eth/WiFi(AP)/Cellular network. --- Firmware/RTK_Everywhere/Network.ino | 70 +++++++++++------------------ Firmware/RTK_Everywhere/WiFi.ino | 29 ++++-------- Firmware/RTK_Everywhere/settings.h | 14 +++--- 3 files changed, 41 insertions(+), 72 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 4c40ff9b0..6a5e7a644 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1397,7 +1397,8 @@ void networkUpdate() // If there are no consumers, but the network is online, shut down all networks if (consumerCount == 0 && networkIsOnline() == true) { - if (settings.debugNetworkLayer && networkIsInterfaceOnline(NETWORK_ETHERNET) == false) //Ethernet is never stopped, so only print for other networks + if (settings.debugNetworkLayer && networkIsInterfaceOnline(NETWORK_ETHERNET) == + false) // Ethernet is never stopped, so only print for other networks systemPrintln("Stopping all networks because there are no consumers"); // Shutdown all networks @@ -1417,7 +1418,6 @@ void networkUpdate() // Shutdown all networks for (int index = 0; index < NETWORK_OFFLINE; index++) networkStop(index, settings.debugNetworkLayer); - } // Allow consumers to start networks @@ -1425,42 +1425,16 @@ void networkUpdate() // so that a networkStart() succeeds. if (consumerCount > 0 && networkIsOnline() == false) { - // Determine which type of network is needed - // If a consumer is requesting a particular type, it gets priority + // Attempt to start any network that is needed, in the order Ethernet/WiFi/Cellular - // Consumer is requesting WiFi specifically - if ((consumerTypes && (1 << NETCONSUMER_WIFI_STA)) || (consumerTypes && (1 << NETCONSUMER_WIFI_AP))) - { - if (settings.debugNetworkLayer) - systemPrintln("Starting WiFi Specific Network"); + if (consumerTypes && (1 << NETCONSUMER_ETHERNET)) + networkStart(NETWORK_ETHERNET, settings.debugNetworkLayer); + if ((consumerTypes && (1 << NETCONSUMER_WIFI_STA)) || (consumerTypes && (1 << NETCONSUMER_WIFI_AP))) networkStart(NETWORK_WIFI, settings.debugNetworkLayer); - //networkMulticastDNSSwitch(NETWORK_WIFI); This should be taken care of by networkMarkOnline() - } - - // We don't have this type of consumer yet but good to have... - else if (consumerTypes && (1 << NETCONSUMER_ETHERNET)) - { - networkStart(NETWORK_ETHERNET, settings.debugNetworkLayer); - //networkMulticastDNSSwitch(NETWORK_ETHERNET); - } - // We don't have this type of consumer yet but good to have... - else if (consumerTypes && (1 << NETCONSUMER_CELLULAR)) - { + if (consumerTypes && (1 << NETCONSUMER_CELLULAR)) networkStart(NETWORK_CELLULAR, settings.debugNetworkLayer); - } - - // Most consumers don't care and so they get whatever is available - else if (consumerTypes == NETCONSUMER_ANY) - { - if (settings.debugNetworkLayer) - systemPrintln("Starting any network"); - - // Start any network that is available, in the order Ethernet/WiFi/Cellular - for (int index = 0; index < NETWORK_OFFLINE; index++) - networkStart(index, settings.debugNetworkLayer); - } } // Walk the list of network priorities in descending order @@ -1548,7 +1522,8 @@ uint8_t networkConsumers(uint16_t *consumerTypes) { consumerCount++; consumerId |= (1 << 0); - *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + + *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } // Network needed for NTRIP Server @@ -1567,8 +1542,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) consumerCount++; consumerId |= (1 << 1); - // TODO - Base type. If AP then limit to NETCONSUMER_WIFI_AP - *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } // Network needed for TCP Client @@ -1576,7 +1550,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) { consumerCount++; consumerId |= (1 << 2); - *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } // Network needed for TCP Server @@ -1584,7 +1558,14 @@ uint8_t networkConsumers(uint16_t *consumerTypes) { consumerCount++; consumerId |= (1 << 3); - *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + + *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular + + // If NTRIP Caster is enabled then add AP mode + // Caster us available over ethernet, WiFi AP, WiFi STA, and cellular + // Caster is available in all mode: Rover, and Base + if (settings.enableNtripCaster == true) + *consumerTypes |= (1 << NETCONSUMER_WIFI_AP); } // Network needed for UDP Server @@ -1592,7 +1573,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) { consumerCount++; consumerId |= (1 << 4); - *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } // Network needed for PointPerfect ZTP or key update requested by scheduler, from menu, or display menu @@ -1600,7 +1581,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) { consumerCount++; consumerId |= (1 << 5); - *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } // Network needed for PointPerfect Corrections MQTT client @@ -1609,7 +1590,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) // PointPerfect is enabled, allow MQTT to begin consumerCount++; consumerId |= (1 << 6); - *consumerTypes |= (1 << NETCONSUMER_ANY); // Ask for any network access + *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } // Network needed to obtain the latest firmware version or do a firmware update @@ -1617,7 +1598,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) { consumerCount++; consumerId |= (1 << 7); - *consumerTypes |= (1 << NETCONSUMER_WIFI_STA); // OTA Pull library only supports WiFi + *consumerTypes = (1 << NETCONSUMER_WIFI_STA); // OTA Pull library only supports WiFi } // Network needed for Web Config @@ -1626,9 +1607,10 @@ uint8_t networkConsumers(uint16_t *consumerTypes) consumerCount++; consumerId |= (1 << 8); - // TODO Make web server over ethernet work here as well + *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular + if (settings.wifiConfigOverAP == true) - *consumerTypes |= ((1 << NETCONSUMER_WIFI_AP) | (1 << NETCONSUMER_WIFI_STA)); //WebConfig requires both AP and STA (for firmware check) + *consumerTypes |= (1 << NETCONSUMER_WIFI_AP); // WebConfig requires both AP and STA (for firmware check) } // Debug diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 9ce1b3e0f..32a7de1df 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -517,33 +517,20 @@ bool wifiForceStart() uint16_t consumerTypes = networkGetConsumerTypes(); - // Only one bit is set, WiFi Station is default - if (consumerTypes == (1 << NETCONSUMER_ANY)) - { - startWiFiStation = true; - } - - // The consumers need both - else if ((consumerTypes & (1 << NETCONSUMER_WIFI_AP)) && (consumerTypes & (1 << NETCONSUMER_WIFI_STA))) - { - startWiFiStation = true; - startWiFiAP = true; - } - // The consumers need station - else if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) - { + if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) startWiFiStation = true; - } // The consumers need AP - else if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) - { + if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) startWiFiAP = true; - } - else - systemPrintln("wifiForceStart(): Unknown NETCONSUMER combination"); + if(startWiFiStation == false && startWiFiAP == false) + { + systemPrintln("wifiForceStart requested without any NETCONSUMER combination"); + WIFI_STOP(); + return (false); + } if (wifiNetworkCount() == 0) { diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 816e079db..109d5f8ed 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -550,19 +550,19 @@ const int numRegionalAreas = sizeof(Regional_Information_Table) / sizeof(Regiona #define NTRIP_SERVER_STRING_SIZE 50 -//Bitfield for describing the type of network the consumer needs +//Bitfield for describing the type of network the consumer can use enum { NETCONSUMER_NONE = 0, // No consumers - NETCONSUMER_WIFI_STA, // The consumer needs STA - NETCONSUMER_WIFI_AP, // The consumer needs AP - //NETCONSUMER_WIFI_AP_STA, // The consumer needs STA and AP - Don't use. Use combination of STA and AP bits - NETCONSUMER_CELLULAR, // The consumer needs Cellular - NETCONSUMER_ETHERNET, // The consumer needs Ethernet - NETCONSUMER_ANY, // The consumer doesn't care what type of network access is granted + NETCONSUMER_WIFI_STA, // The consumer can use STA + NETCONSUMER_WIFI_AP, // The consumer can use AP + NETCONSUMER_CELLULAR, // The consumer can use Cellular + NETCONSUMER_ETHERNET, // The consumer can use Ethernet NETCONSUMER_UNKNOWN }; +#define NETWORK_EWC ((1 << NETCONSUMER_ETHERNET) | (1 << NETCONSUMER_WIFI_STA) | (1 << NETCONSUMER_CELLULAR)) + // This is all the settings that can be set on RTK Product. It's recorded to NVM and the config file. // Avoid reordering. The order of these variables is mimicked in NVM/record/parse/create/update/get struct Settings From 1da49bc89718015f40ccc2cc677716e267aec0be Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2025 09:28:10 -0700 Subject: [PATCH 087/276] Allow the AP name to change based on mode --- Firmware/RTK_Everywhere/Display.ino | 6 +++--- Firmware/RTK_Everywhere/WiFi.ino | 23 +++++++++++++++++------ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 26b0f9db2..c9a9d1221 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -3020,7 +3020,7 @@ void displayConfigViaWiFi() #ifdef COMPILE_WIFI if (settings.wifiConfigOverAP == true) - snprintf(mySSID, sizeof(mySSID), "%s", "RTK Config"); + snprintf(mySSID, sizeof(mySSID), "%s", WiFi.softAPSSID().c_str()); else { if (WiFi.getMode() == WIFI_STA) @@ -3028,11 +3028,11 @@ void displayConfigViaWiFi() // If we failed to connect to a friendly WiFi, and then fell back to AP mode, still display RTK Config else if (WiFi.getMode() == WIFI_AP) - snprintf(mySSID, sizeof(mySSID), "%s", "RTK Config"); + snprintf(mySSID, sizeof(mySSID), "%s", WiFi.softAPSSID().c_str()); // If we are in AP+STA mode, still display RTK Config else if (WiFi.getMode() == WIFI_AP_STA) - snprintf(mySSID, sizeof(mySSID), "%s", "RTK Config"); + snprintf(mySSID, sizeof(mySSID), "%s", WiFi.softAPSSID().c_str()); else snprintf(mySSID, sizeof(mySSID), "%s", "Error"); diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 32a7de1df..da104bbfb 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -224,8 +224,20 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) WiFi.softAPConfig(local_IP, gateway, subnet); - const char *softApSsid = "RTK Config"; - if (WiFi.softAP(softApSsid) == false) // Must be short enough to fit OLED Width + // Determine the AP name + // If in web config mode then 'RTK Config' + // otherwise 'RTK Caster' + + char softApSsid[strlen("RTK Config")]; // Must be short enough to fit OLED Width + + if (inWebConfigMode()) + strncpy(softApSsid, "RTK Config", sizeof(softApSsid)); + //snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Config"); // TODO use settings.webconfigApName + else + strncpy(softApSsid, "RTK Caster", sizeof(softApSsid)); + //snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Caster"); + + if (WiFi.softAP(softApSsid) == false) { systemPrintln("WiFi AP failed to start"); return (false); @@ -233,6 +245,8 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) systemPrintf("WiFi AP '%s' started with IP: ", softApSsid); systemPrintln(WiFi.softAPIP()); + networkMarkOnline(NETWORK_WIFI); // Regardless of WiFi STA success of failure, we have some network access + // Start DNS Server if (dnsServer.start(53, "*", WiFi.softAPIP()) == false) { @@ -525,7 +539,7 @@ bool wifiForceStart() if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) startWiFiAP = true; - if(startWiFiStation == false && startWiFiAP == false) + if (startWiFiStation == false && startWiFiAP == false) { systemPrintln("wifiForceStart requested without any NETCONSUMER combination"); WIFI_STOP(); @@ -560,10 +574,7 @@ bool wifiForceStart() // If we are in AP only mode, as long as the AP is started, return true if (WiFi.getMode() == WIFI_MODE_AP) - { - networkMarkOnline(NETWORK_WIFI); return (true); - } // If we are in STA or AP+STA mode, return if the station connected successfully wifiStatus = WiFi.status(); From 5471650445e30c47fe28283e9502024ab728ec80 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2025 09:57:16 -0700 Subject: [PATCH 088/276] Set IP address on network layer for soft AP --- Firmware/RTK_Everywhere/Network.ino | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 6a5e7a644..37548aa9a 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -523,10 +523,18 @@ IPAddress networkGetIpAddress() if (index < NETWORK_OFFLINE) { index = networkIndexTable[index]; + + //NETIF doesn't capture the IP address of a soft AP + if (index == NETWORK_WIFI && (WiFi.getMode() == WIFI_AP || WiFi.getMode() == WIFI_AP_STA)) + return WiFi.softAPIP(); + return networkInterfaceTable[index].netif->localIP(); } // No IP address available + if (settings.debugNetworkLayer) + systemPrintln("No network online - No IP available"); + return IPAddress(0, 0, 0, 0); } @@ -1117,6 +1125,7 @@ void networkSequenceStop(NetIndex_t index, bool debug) // Start the sequence networkSeqStopping |= bitMask; networkStarted &= ~bitMask; + networkSequence[index] = sequence; } } @@ -1176,6 +1185,7 @@ void networkSequenceStopPolling(NetIndex_t index, bool debug, bool forcedStop) if (forcedStop) { networkStarted &= ~bitMask; + networkSeqRequest &= ~bitMask; networkSeqNext &= ~bitMask; } @@ -1472,6 +1482,14 @@ void networkUpdate() systemPrintf("%s: Link Up\r\n", networkInterfaceTable[index].name); else if (networkInterfaceTable[index].netif->started()) systemPrintf("%s: Started\r\n", networkInterfaceTable[index].name); + + else if (index == NETWORK_WIFI && (WiFi.getMode() == WIFI_AP || WiFi.getMode() == WIFI_AP_STA)) + { + //NETIF doesn't capture the IP address of a soft AP + ipAddress = WiFi.softAPIP(); + systemPrintf("%s: %s%s\r\n", networkInterfaceTable[index].name, ipAddress.toString().c_str(), + networkInterfaceTable[index].netif->isDefault() ? " (default)" : ""); + } else systemPrintf("%s: Stopped\r\n", networkInterfaceTable[index].name); } From 03c490e5742cc2bbc34ea56b35927e90cace31e8 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2025 10:18:45 -0700 Subject: [PATCH 089/276] Restart WiFi at network layer if settings have changed --- Firmware/RTK_Everywhere/Developer.ino | 1 - Firmware/RTK_Everywhere/Network.ino | 14 +++++++++++--- Firmware/RTK_Everywhere/Tasks.ino | 1 - Firmware/RTK_Everywhere/WiFi.ino | 23 ----------------------- Firmware/RTK_Everywhere/menuMain.ino | 8 -------- 5 files changed, 11 insertions(+), 36 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index d31ee7c87..8ae7f337e 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -170,7 +170,6 @@ void menuWiFi() {systemPrintln("**WiFi not compiled**");} bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) {return false;} int wifiNetworkCount() {return 0;} bool wifiIsRunning() {return false;} -void wifiRestart() {} #define WIFI_STOP() {} #endif // COMPILE_WIFI diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 37548aa9a..2f4741019 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -128,7 +128,7 @@ NETWORK_POLL_SEQUENCE *networkSequence[NETWORK_OFFLINE]; NetMask_t networkMdnsRunning; // Non-zero when mDNS is running -bool networkShutdownRequest = false; // Used to notify consumers that the network layer needs to shut down +extern bool restartWiFi; // From WiFi.ino //---------------------------------------- // Menu for configuring TCP/UDP interfaces @@ -524,7 +524,7 @@ IPAddress networkGetIpAddress() { index = networkIndexTable[index]; - //NETIF doesn't capture the IP address of a soft AP + // NETIF doesn't capture the IP address of a soft AP if (index == NETWORK_WIFI && (WiFi.getMode() == WIFI_AP || WiFi.getMode() == WIFI_AP_STA)) return WiFi.softAPIP(); @@ -1404,6 +1404,14 @@ void networkUpdate() int consumerCount = networkConsumers(&consumerTypes); // Update the current consumer types + // restartWiFi is used by the settings interface to indicate SSIDs or else has changed + // Stop WiFi to allow restart with new settings + if (restartWiFi == true && networkIsInterfaceOnline(NETWORK_WIFI)) + { + restartWiFi = false; + networkStop(NETWORK_WIFI, settings.debugNetworkLayer); + } + // If there are no consumers, but the network is online, shut down all networks if (consumerCount == 0 && networkIsOnline() == true) { @@ -1485,7 +1493,7 @@ void networkUpdate() else if (index == NETWORK_WIFI && (WiFi.getMode() == WIFI_AP || WiFi.getMode() == WIFI_AP_STA)) { - //NETIF doesn't capture the IP address of a soft AP + // NETIF doesn't capture the IP address of a soft AP ipAddress = WiFi.softAPIP(); systemPrintf("%s: %s%s\r\n", networkInterfaceTable[index].name, ipAddress.toString().c_str(), networkInterfaceTable[index].netif->isDefault() ? " (default)" : ""); diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index af3d432c4..d2c11657c 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -1680,7 +1680,6 @@ void buttonCheckTask(void *e) forceSystemStateUpdate = true; // Immediately go to this new state changeState(STATE_ROVER_NOT_STARTED); - wifiRestart(); } } diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index da104bbfb..b813ccbae 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -488,29 +488,6 @@ const char *wifiPrintState(wl_status_t wifiStatus) return ("WiFi Status Unknown"); } -//---------------------------------------- -// Restart WiFi -//---------------------------------------- -void wifiRestart() -{ - // Restart the AP webServer if we are in that state - if (systemState == STATE_WEB_CONFIG) - requestChangeState(STATE_WEB_CONFIG_NOT_STARTED); - else - { - // Restart WiFi if we are not in AP config mode - WIFI_STOP(); - - if (networkConsumers() == 0) - { - // Don't restart WiFi if there is no need for it - return; - } - - wifiForceStart(); - } -} - //---------------------------------------- // Starts the WiFi connection state machine (moves from WIFI_STATE_OFF to WIFI_STATE_CONNECTING) // Sets the appropriate protocols (WiFi + ESP-Now) diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 39783414a..362094ffd 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -299,14 +299,6 @@ void menuMain() gnss->debuggingEnable(); } - // Restart WiFi if anything changes and we have consumers - if (restartWiFi == true && networkConsumers() > 0) - { - restartWiFi = false; - - wifiRestart(); - } - clearBuffer(); // Empty buffer of any newline chars btPrintEchoExit = false; // We are out of the menu system inMainMenu = false; From fb8b5dfcd4e035193d81e5f45a7c472a3661e907 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2025 11:38:36 -0700 Subject: [PATCH 090/276] Display a SIV icon when in Base mode --- Firmware/RTK_Everywhere/Display.ino | 22 +++++++++++++++++++--- Firmware/RTK_Everywhere/icons.h | 6 ++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index c9a9d1221..3370e652b 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -333,6 +333,7 @@ void displayUpdate() displayFullIPAddress(&iconPropertyList); // Bottom left - 128x64 only setRadioIcons(&iconPropertyList); paintRTCM(&iconPropertyList); + displaySivVsOpenShort(&iconPropertyList); // 128x64 only break; case (STATE_BASE_FIXED_NOT_STARTED): displayBatteryVsEthernet(&iconPropertyList); // Top right @@ -345,6 +346,7 @@ void displayUpdate() displayFullIPAddress(&iconPropertyList); // Bottom left - 128x64 only setRadioIcons(&iconPropertyList); paintRTCM(&iconPropertyList); + displaySivVsOpenShort(&iconPropertyList); // 128x64 only break; case (STATE_NTPSERVER_NOT_STARTED): @@ -1653,10 +1655,22 @@ displayCoords paintSIVIcon(std::vector *iconList, const ic if (lbandCorrectionsReceived || spartnCorrectionsReceived) icon = &LBandIconProperties; else - icon = &SIVIconProperties; + { + if(inBaseMode() == false) + icon = &SIVIconProperties; + else if(inBaseMode() && present.display_type == DISPLAY_128x64) + icon = &BaseSIVIconProperties; //Move SIV down to avoid collision with 'Xmitting RTCM' text + } + + // if in base mode, don't blink + if(inBaseMode() == true) + { + // override duty - solid satellite dish icon regardless of fix state + duty = 0b11111111; + } // Determine if there is a fix - if (gnss->isFixed() == false) + else if (gnss->isFixed() == false) { // override duty - blink satellite dish icon if we don't have a fix duty = 0b01010101; @@ -1687,7 +1701,9 @@ void paintSIVText(displayCoords textCoords) if (online.gnss) { - if (gnss->isFixed() == false) + if(inBaseMode() == true) + oled->print(gnss->getSatellitesInView()); + else if (gnss->isFixed() == false) oled->print("0"); else oled->print(gnss->getSatellitesInView()); diff --git a/Firmware/RTK_Everywhere/icons.h b/Firmware/RTK_Everywhere/icons.h index 6bca2d264..551b24f94 100644 --- a/Firmware/RTK_Everywhere/icons.h +++ b/Firmware/RTK_Everywhere/icons.h @@ -1936,11 +1936,17 @@ const uint8_t SIVIconXPos64x48 = 2; // This aligns the SIV icon neatly under the const uint8_t SIVIconYPos64x48 = 35; const uint8_t SIVIconXPos128x64 = 74; // Just because we can, move SIV to the right on 128x64 const uint8_t SIVIconYPos128x64 = 26; +const uint8_t BaseSIVIconXPos128x64 = 74; // Move SIV info below the 'Xmitting RTCM' text on 128x64 +const uint8_t BaseSIVIconYPos128x64 = (26 + 15); // Assume font size 1; const int SIVTextStartXPosOffset[DISPLAY_MAX_NONE] = { -2, -2 }; // This is a bodge to allow the paintBaseTempSurveyStarted text to be printed in the correct place const iconProperties SIVIconProperties = {{{ &SIV_Antenna, SIV_Antenna_Width, SIV_Antenna_Height, SIVIconXPos64x48, SIVIconYPos64x48 }, { &SIV_Antenna, SIV_Antenna_Width, SIV_Antenna_Height, SIVIconXPos128x64, SIVIconYPos128x64 }}}; + +const iconProperties BaseSIVIconProperties = {{{ &SIV_Antenna, SIV_Antenna_Width, SIV_Antenna_Height, SIVIconXPos64x48, SIVIconYPos64x48 }, + { &SIV_Antenna, SIV_Antenna_Width, SIV_Antenna_Height, BaseSIVIconXPos128x64, BaseSIVIconYPos128x64 }}}; + const iconProperties LBandIconProperties = {{{ &SIV_Antenna_LBand, SIV_Antenna_LBand_Width, SIV_Antenna_LBand_Height, SIVIconXPos64x48, SIVIconYPos64x48 }, { &SIV_Antenna_LBand, SIV_Antenna_LBand_Width, SIV_Antenna_LBand_Height, SIVIconXPos128x64, SIVIconYPos128x64 }}}; const iconProperties ShortIconProperties = {{{ &Antenna_Short, Antenna_Short_Width, Antenna_Short_Height, SIVIconXPos64x48, SIVIconYPos64x48 }, From 19e3c112372b82d0df8422dc2aa5acf3b0131ecb Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2025 11:39:18 -0700 Subject: [PATCH 091/276] Rename wifiStart and wifiThrottledStart and allow WiFi resets --- Firmware/RTK_Everywhere/Developer.ino | 1 + Firmware/RTK_Everywhere/ESPNOW.ino | 2 +- Firmware/RTK_Everywhere/Network.ino | 5 +++++ Firmware/RTK_Everywhere/WiFi.ino | 23 +++++++++++++++++------ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 8ae7f337e..ad5344885 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -45,6 +45,7 @@ const uint8_t * networkGetMacAddress() } bool networkIsOnline() {return false;} bool networkIsOnline(NetIndex_t index) {return false;} +bool networkIsInterfaceOnline(NetIndex_t index) {return false;} void networkMarkOffline(NetIndex_t index) {} void networkMarkOnline(NetIndex_t index) {} void networkUpdate() {} diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index 51de217d5..267efd7ce 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -375,7 +375,7 @@ void espnowStop() { if (settings.debugEspNow == true) systemPrintln("ESP-Now starting WiFi"); - wifiForceStart(); // Force WiFi to restart + wifiStart(); // Force WiFi to restart } #endif // COMPILE_ESPNOW diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 2f4741019..d429140a6 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1408,7 +1408,12 @@ void networkUpdate() // Stop WiFi to allow restart with new settings if (restartWiFi == true && networkIsInterfaceOnline(NETWORK_WIFI)) { + if (settings.debugNetworkLayer) + systemPrintln("WiFi settings changed, restarting WiFi"); + restartWiFi = false; + wifiResetThrottleTimeout(); + WIFI_STOP(); networkStop(NETWORK_WIFI, settings.debugNetworkLayer); } diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index b813ccbae..3934cd064 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -46,6 +46,8 @@ static uint32_t wifiConnectionAttemptTimeout; // Start timeout static uint32_t wifiStartTimeout; +static uint32_t wifiStartLastTry; // The last time WiFi start was attempted + // WiFi Timer usage: // * Measure interval to display IP address static unsigned long wifiDisplayTimer; @@ -488,6 +490,7 @@ const char *wifiPrintState(wl_status_t wifiStatus) return ("WiFi Status Unknown"); } + //---------------------------------------- // Starts the WiFi connection state machine (moves from WIFI_STATE_OFF to WIFI_STATE_CONNECTING) // Sets the appropriate protocols (WiFi + ESP-Now) @@ -495,7 +498,7 @@ const char *wifiPrintState(wl_status_t wifiStatus) // If ESP-Now is active, only add the LR protocol // Returns true if WiFi has connected and false otherwise //---------------------------------------- -bool wifiForceStart() +bool wifiStart() { int wifiStatus; @@ -518,7 +521,7 @@ bool wifiForceStart() if (startWiFiStation == false && startWiFiAP == false) { - systemPrintln("wifiForceStart requested without any NETCONSUMER combination"); + systemPrintln("wifiStart() requested without any NETCONSUMER combination"); WIFI_STOP(); return (false); } @@ -567,12 +570,20 @@ void wifiResetTimeout() wifiStartTimeout = 0; } +//---------------------------------------- +// Reset the last WiFi start attempt +// Useful when WiFi settings have changed +//---------------------------------------- +void wifiResetThrottleTimeout() +{ + wifiStartLastTry = 0; +} + //---------------------------------------- // Start WiFi with throttling //---------------------------------------- -void wifiStart(NetIndex_t index, uintptr_t parameter, bool debug) +void wifiThrottledStart(NetIndex_t index, uintptr_t parameter, bool debug) { - static uint32_t wifiStartLastTry; int seconds; int minutes; @@ -582,7 +593,7 @@ void wifiStart(NetIndex_t index, uintptr_t parameter, bool debug) wifiStartLastTry = millis(); // Start WiFi - if (wifiForceStart()) + if (wifiStart()) networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); else { @@ -607,7 +618,7 @@ void wifiStart(NetIndex_t index, uintptr_t parameter, bool debug) //---------------------------------------- NETWORK_POLL_SEQUENCE wifiStartSequence[] = { // State Parameter Description - {wifiStart, 0, "Initialize WiFi"}, + {wifiThrottledStart, 0, "Initialize WiFi"}, {nullptr, 0, "Termination"}, }; From e0bf54af51266df5772760bf15b05cd47ce966b9 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2025 14:41:41 -0700 Subject: [PATCH 092/276] Add BaseCast mode --- Firmware/RTK_Everywhere/Base.ino | 13 +++++++++++++ Firmware/RTK_Everywhere/Display.ino | 2 ++ Firmware/RTK_Everywhere/Network.ino | 2 +- Firmware/RTK_Everywhere/States.ino | 17 ++++++++++++++--- Firmware/RTK_Everywhere/Tasks.ino | 6 ++++++ Firmware/RTK_Everywhere/TcpServer.ino | 22 +++++++++++++--------- Firmware/RTK_Everywhere/menuCommands.ino | 14 ++++---------- Firmware/RTK_Everywhere/menuSystem.ino | 7 +++++++ Firmware/RTK_Everywhere/settings.h | 4 ++++ 9 files changed, 64 insertions(+), 23 deletions(-) diff --git a/Firmware/RTK_Everywhere/Base.ino b/Firmware/RTK_Everywhere/Base.ino index e8857715d..f55370571 100644 --- a/Firmware/RTK_Everywhere/Base.ino +++ b/Firmware/RTK_Everywhere/Base.ino @@ -28,4 +28,17 @@ void processRTCM(uint8_t *rtcmData, uint16_t dataLength) if (rtcmPacketsSent > 999) rtcmPacketsSent = 1; // Trim to three digits to avoid log icon and increasing bar } +} + +//------------------------------ +// When settings.baseCasterOverride is true, override enableTcpServer, tcpServerPort, and enableNtripCaster settings +//------------------------------ +void baseCasterEnableOverride() +{ + settings.baseCasterOverride = true; +} + +void baseCasterDisableOverride() +{ + settings.baseCasterOverride = false; } \ No newline at end of file diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 3370e652b..6657f6644 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -304,6 +304,7 @@ void displayUpdate() setRadioIcons(&iconPropertyList); break; + case (STATE_BASE_CASTER_NOT_STARTED): case (STATE_BASE_NOT_STARTED): // Do nothing. Static display shown during state change. break; @@ -1276,6 +1277,7 @@ void setModeIcon(std::vector *iconList) paintDynamicModel(iconList); break; + case (STATE_BASE_CASTER_NOT_STARTED): case (STATE_BASE_NOT_STARTED): // Do nothing. Static display shown during state change. break; diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index d429140a6..a0ca485f7 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1595,7 +1595,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) // If NTRIP Caster is enabled then add AP mode // Caster us available over ethernet, WiFi AP, WiFi STA, and cellular // Caster is available in all mode: Rover, and Base - if (settings.enableNtripCaster == true) + if (settings.enableNtripCaster == true || settings.baseCasterOverride == true) *consumerTypes |= (1 << NETCONSUMER_WIFI_AP); } diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 5fb3bf66a..d43b1cab3 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -116,7 +116,8 @@ void stateUpdate() espnowStart(); // Start internal radio if enabled, otherwise disable webServerStop(); // Stop the web config server - + baseCasterDisableOverride(); // Disable casting overrides + // Start the UART connected to the GNSS receiver for NMEA and UBX data (enables logging) if (tasksStartGnssUart() == false) displayRoverFail(1000); @@ -207,6 +208,12 @@ void stateUpdate() */ + case (STATE_BASE_CASTER_NOT_STARTED): { + baseCasterEnableOverride(); + changeState(STATE_BASE_NOT_STARTED); + } + break; + case (STATE_BASE_NOT_STARTED): { RTK_MODE(RTK_MODE_BASE_SURVEY_IN); firstRoverStart = false; // If base is starting, no test menu, normal button use. @@ -228,7 +235,8 @@ void stateUpdate() { settings.updateGNSSSettings = false; // On the next boot, no need to update the GNSS on this profile settings.lastState = STATE_BASE_NOT_STARTED; // Record this state for next POR - recordSystemSettings(); // Record this state for next POR + + recordSystemSettings(); // Record this state for next POR displayBaseSuccess(500); // Show 'Base Started' @@ -421,7 +429,7 @@ void stateUpdate() displayWebConfigNotStarted(); // Display immediately while we wait for server to start bluetoothStop(); // Bluetooth must be stopped to allow enough RAM for AP+STA (firmware check) - espnowStop(); // We don't need ESP-NOW during web config + espnowStop(); // We don't need ESP-NOW during web config // The GNSS UART task is left running to allow non-ZED platforms to obtain LLh data for 1Hz page updates @@ -662,6 +670,8 @@ const char *getState(SystemState state, char *buffer) return "STATE_ROVER_RTK_FLOAT"; case (STATE_ROVER_RTK_FIX): return "STATE_ROVER_RTK_FIX"; + case (STATE_BASE_CASTER_NOT_STARTED): + return "STATE_BASE_CASTER_NOT_STARTED"; case (STATE_BASE_NOT_STARTED): return "STATE_BASE_NOT_STARTED"; case (STATE_BASE_TEMP_SETTLE): @@ -840,6 +850,7 @@ void constructSetupDisplay(std::vector *buttons) buttons->clear(); addSetupButton(buttons, "Base", STATE_BASE_NOT_STARTED); + addSetupButton(buttons, "BaseCast", STATE_BASE_CASTER_NOT_STARTED); addSetupButton(buttons, "Rover", STATE_ROVER_NOT_STARTED); if (present.ethernet_ws5500 == true) { diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index d2c11657c..4e04800ae 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -1809,6 +1809,7 @@ void buttonCheckTask(void *e) case STATE_TESTING: // If we are in testing, return to Base Not Started lastSetupMenuChange = millis(); // Prevent a timeout during state change + baseCasterDisableOverride(); // Leave Caster mode requestChangeState(STATE_BASE_NOT_STARTED); break; @@ -1847,6 +1848,11 @@ void buttonCheckTask(void *e) firstButtonThrownOut = false; requestChangeState(lastSystemState); } + else if (it->newState == STATE_BASE_NOT_STARTED) // User selected Base, clear BaseCast override + { + baseCasterDisableOverride(); + requestChangeState(it->newState); + } else requestChangeState(it->newState); diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index 63769e376..9aeddbf6d 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -232,8 +232,12 @@ bool tcpServerStart() if (settings.debugTcpServer && (!inMainMenu)) systemPrintln("TCP server starting the server"); + uint16_t tcpPort = settings.tcpServerPort; + if(settings.baseCasterOverride == true) + tcpPort = 2101; + // Start the TCP server - tcpServer = new NetworkServer(settings.tcpServerPort, TCP_SERVER_MAX_CLIENTS); + tcpServer = new NetworkServer(tcpPort, TCP_SERVER_MAX_CLIENTS); if (!tcpServer) return false; @@ -243,9 +247,9 @@ bool tcpServerStart() if (settings.enableNtripCaster) systemPrintf("TCP server online, IP address %s:%d, responding as NTRIP Caster\r\n", localIp.toString().c_str(), - settings.tcpServerPort); + tcpPort); else - systemPrintf("TCP server online, IP address %s:%d\r\n", localIp.toString().c_str(), settings.tcpServerPort); + systemPrintf("TCP server online, IP address %s:%d\r\n", localIp.toString().c_str(), tcpPort); return true; } @@ -338,7 +342,7 @@ void tcpServerUpdate() // Shutdown the TCP server when the mode or setting changes DMW_st(tcpServerSetState, tcpServerState); - if (NEQ_RTK_MODE(tcpServerMode) || (!settings.enableTcpServer)) + if (NEQ_RTK_MODE(tcpServerMode) || (!settings.enableTcpServer && !settings.baseCasterOverride)) { if (tcpServerState > TCP_SERVER_STATE_OFF) tcpServerStop(); @@ -373,7 +377,7 @@ void tcpServerUpdate() // Wait until the TCP server is enabled case TCP_SERVER_STATE_OFF: // Determine if the TCP server should be running - if (EQ_RTK_MODE(tcpServerMode) && settings.enableTcpServer) + if (EQ_RTK_MODE(tcpServerMode) && (settings.enableTcpServer || settings.baseCasterOverride)) { if (settings.debugTcpServer && (!inMainMenu)) systemPrintln("TCP server start"); @@ -385,7 +389,7 @@ void tcpServerUpdate() // Wait until the network is connected case TCP_SERVER_STATE_WAIT_FOR_NETWORK: // Determine if the TCP server was turned off - if (NEQ_RTK_MODE(tcpServerMode) || !settings.enableTcpServer) + if (NEQ_RTK_MODE(tcpServerMode) || (!settings.enableTcpServer && !settings.baseCasterOverride)) tcpServerStop(); // Wait until the network is connected to the media @@ -407,7 +411,7 @@ void tcpServerUpdate() // Handle client connections and link failures case TCP_SERVER_STATE_RUNNING: // Determine if the network has failed - if ((!settings.enableTcpServer) || (!networkIsConnected(&tcpServerPriority))) + if ((networkIsConnected(&tcpServerPriority) == false) || (!settings.enableTcpServer && !settings.baseCasterOverride)) { if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu)) { @@ -477,7 +481,7 @@ void tcpServerUpdate() // If we are acting as an NTRIP Caster, intercept the initial communication from the client // and respond accordingly - if (settings.enableNtripCaster) + if (settings.enableNtripCaster || settings.baseCasterOverride) { // Read response from client char response[512]; @@ -520,7 +524,7 @@ void tcpServerUpdate() if (settings.debugTcpServer) systemPrintf("Unknown response: %s\r\n", response); } - } // settings.enableNtripCaster == true + } // settings.enableNtripCaster == true || settings.baseCasterOverride == true // Make client online after any NTRIP injections so ring buffer can start outputting data to it tcpServerClientConnected = tcpServerClientConnected | (1 << index); diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index 6a278d2f4..7b3f87d8b 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -661,18 +661,12 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting SystemState *ptr = (SystemState *)var; knownSetting = true; - // 0 = Rover, 1 = Base, 2 = NTP - if (settingValue == 2) - { - if (productVariant == RTK_EVK) - settings.lastState = STATE_NTPSERVER_NOT_STARTED; - else - knownSetting = false; - } + // 0 = Rover, 1 = Base, 2 = NTP, 3 = Base Caster + settings.lastState = STATE_ROVER_NOT_STARTED; // Default if (settingValue == 1) settings.lastState = STATE_BASE_NOT_STARTED; - else - settings.lastState = STATE_ROVER_NOT_STARTED; // Default + else if (settingValue == 2 && productVariant == RTK_EVK) + settings.lastState = STATE_NTPSERVER_NOT_STARTED; } break; case tPulseEdg: { diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index e201bf7a0..0773c7183 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -158,6 +158,7 @@ void menuSystem() // Support mode switching systemPrintln("B) Switch to Base mode"); + systemPrintln("C) Switch to Base Caster mode"); if (present.ethernet_ws5500 == true) systemPrintln("N) Switch to NTP Server mode"); systemPrintln("R) Switch to Rover mode"); @@ -392,8 +393,14 @@ void menuSystem() else if (incoming == 'B') { forceSystemStateUpdate = true; // Immediately go to this new state + baseCasterDisableOverride(); // Leave Caster mode changeState(STATE_BASE_NOT_STARTED); } + else if (incoming == 'C') + { + forceSystemStateUpdate = true; // Immediately go to this new state + changeState(STATE_BASE_CASTER_NOT_STARTED); + } else if ((incoming == 'N') && (present.ethernet_ws5500 == true)) { forceSystemStateUpdate = true; // Immediately go to this new state diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 109d5f8ed..a5d4dcee7 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -19,12 +19,14 @@ typedef enum STATE_ROVER_FIX, STATE_ROVER_RTK_FLOAT, STATE_ROVER_RTK_FIX, + STATE_BASE_CASTER_NOT_STARTED, //Set override flag STATE_BASE_NOT_STARTED, STATE_BASE_TEMP_SETTLE, // User has indicated base, but current pos accuracy is too low STATE_BASE_TEMP_SURVEY_STARTED, STATE_BASE_TEMP_TRANSMITTING, STATE_BASE_FIXED_NOT_STARTED, STATE_BASE_FIXED_TRANSMITTING, + STATE_DISPLAY_SETUP, STATE_WEB_CONFIG_NOT_STARTED, STATE_WEB_CONFIG_WAIT_FOR_NETWORK, @@ -985,6 +987,7 @@ struct Settings bool debugSettings = false; bool enableNtripCaster = false; //When true, respond as a faux NTRIP Caster to incoming TCP connections + bool baseCasterOverride = false; //When true, user has put device into 'BaseCast' mode. Change settings, but don't save to NVM. // Add new settings to appropriate group above or create new group // Then also add to the same group in rtkSettingsEntries below @@ -1593,6 +1596,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugSettings, "debugSettings", }, { 1, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enableNtripCaster, "enableNtripCaster", }, + { 1, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.baseCasterOverride, "baseCasterOverride", }, // Add new settings to appropriate group above or create new group // Then also add to the same group in settings above From 661fd609f3cb22110e2408a95dbe4c3c79efa3a7 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2025 14:53:39 -0700 Subject: [PATCH 093/276] LG290P: Fix NMEA enable after Rover->Base transition --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index 0a6f4a818..9f17c2529 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -37,7 +37,7 @@ void GNSS_LG290P::baseRtcmLowDataRate() settings.lg290pMessageRatesRTCMBase[x] = 0; settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-1005")] = - 10; // 1005 0.1Hz - Exclude antenna height + 10; // 1005 0.1Hz - Exclude antenna height settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-107X")] = 2; // 1074 0.5Hz settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-108X")] = 2; // 1084 0.5Hz settings.lg290pMessageRatesRTCMBase[getRtcmMessageNumberByName("RTCM3-109X")] = 2; // 1094 0.5Hz @@ -401,6 +401,10 @@ bool GNSS_LG290P::configureBase() softwareReset(); + // When a device is changed from Rover to Base, NMEA messages settings do not survive PQTMSAVEPAR + // Re-enable NMEA post reset + enableNMEA(); // Set NMEA messages + if (settings.debugGnss) systemPrintln("LG290P Base configured"); } @@ -507,6 +511,8 @@ bool GNSS_LG290P::enableNMEA() bool gpggaEnabled = false; bool gpzdaEnabled = false; + Serial.println("\r\n setting nmea"); + for (int messageNumber = 0; messageNumber < MAX_LG290P_NMEA_MSG; messageNumber++) { if (_lg290p->setMessageRate(lgMessagesNMEA[messageNumber].msgTextName, @@ -587,8 +593,8 @@ bool GNSS_LG290P::enableRTCMBase() if (enableMSM == true) { - if(settings.debugGnss) - + if (settings.debugGnss) + systemPrintln("Enabling RTCM MSM output"); // PQTMCFGRTCM fails to respond with OK over UART2 of LG290P, so don't look for it From 097d9a161eda4c820a4242688267acc34e05db27 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2025 15:44:11 -0700 Subject: [PATCH 094/276] Add SIV to Survey In --- Firmware/RTK_Everywhere/Display.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 6657f6644..a93c865f8 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -327,6 +327,7 @@ void displayUpdate() displayFullIPAddress(&iconPropertyList); // Bottom left - 128x64 only setRadioIcons(&iconPropertyList); paintBaseTempSurveyStarted(&iconPropertyList); + displaySivVsOpenShort(&iconPropertyList); // 128x64 only break; case (STATE_BASE_TEMP_TRANSMITTING): paintLogging(&iconPropertyList); From 69924bfb66824919e1625e7eefb58f7f10863292 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2025 15:44:59 -0700 Subject: [PATCH 095/276] Add BaseCast to Web Config. Add shutdownNoChargeTimeout to web config. --- Firmware/RTK_Everywhere/AP-Config/index.html | 44 +++++++++++++++---- Firmware/RTK_Everywhere/AP-Config/src/main.js | 10 +++++ Firmware/RTK_Everywhere/GNSS_LG290P.ino | 2 - Firmware/RTK_Everywhere/menuCommands.ino | 29 +++++++----- Firmware/RTK_Everywhere/menuSystem.ino | 2 +- Firmware/RTK_Everywhere/settings.h | 2 +- 6 files changed, 66 insertions(+), 23 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/index.html b/Firmware/RTK_Everywhere/AP-Config/index.html index d2c62fb32..a329162a0 100644 --- a/Firmware/RTK_Everywhere/AP-Config/index.html +++ b/Firmware/RTK_Everywhere/AP-Config/index.html @@ -242,7 +242,7 @@ @@ -257,7 +257,7 @@
@@ -1770,7 +1770,7 @@
Coordination Frequency (MHz): + title="The base frequency used to control hopping between channels. Radios that need to hear each other must use the same coordination frequency. Default: 910MHz. Limits: 903 to 927MHz.">
@@ -1782,7 +1782,7 @@
Seconds before dedicated listening mode: + title="After this number of seconds, incoming serial over USB is ignored so that LoRa serial can flow between devices. Reset the device to re-enable serial over USB. Default: 30s. Limits: 10 to 600s.">
@@ -1813,7 +1813,7 @@ @@ -2007,9 +2007,10 @@ + + title="Put the system into the selected mode at next Power On or Reset.">
@@ -2030,7 +2031,7 @@ @@ -2041,7 +2042,7 @@
@@ -2199,6 +2200,31 @@
+
+
+ + + + + +
+
+ +
+
+ + +

+
+
+
@@ -2369,7 +2395,7 @@
diff --git a/Firmware/RTK_Everywhere/AP-Config/src/main.js b/Firmware/RTK_Everywhere/AP-Config/src/main.js index ba38d34e0..20be185c8 100644 --- a/Firmware/RTK_Everywhere/AP-Config/src/main.js +++ b/Firmware/RTK_Everywhere/AP-Config/src/main.js @@ -121,6 +121,7 @@ function parseIncoming(msg) { show("useLocalizedDistributionCheckbox"); show("useEnableExtCorrRadio"); show("extCorrRadioSPARTNSourceDropdown"); + hide("shutdownNoChargeTimeoutCheckbox"); } else if ((platformPrefix == "Facet v2") || (platformPrefix == "Facet v2 LBand")) { show("baseConfig"); @@ -1732,6 +1733,15 @@ document.addEventListener("DOMContentLoaded", (event) => { } }); + ge("shutdownNoChargeTimeout").addEventListener("change", function () { + if (ge("shutdownNoChargeTimeout").checked == true) { + show("shutdownNoChargeTimeoutDetails"); + } + else { + hide("shutdownNoChargeTimeoutDetails"); + } + }); + ge("fixedAltitude").addEventListener("change", function () { adjustHAE(); }); diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index 9f17c2529..e96a07bc7 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -511,8 +511,6 @@ bool GNSS_LG290P::enableNMEA() bool gpggaEnabled = false; bool gpzdaEnabled = false; - Serial.println("\r\n setting nmea"); - for (int messageNumber = 0; messageNumber < MAX_LG290P_NMEA_MSG; messageNumber++) { if (_lg290p->setMessageRate(lgMessagesNMEA[messageNumber].msgTextName, diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index 7b3f87d8b..89b076a76 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -667,6 +667,8 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting settings.lastState = STATE_BASE_NOT_STARTED; else if (settingValue == 2 && productVariant == RTK_EVK) settings.lastState = STATE_NTPSERVER_NOT_STARTED; + else if (settingValue == 3) + settings.lastState = STATE_BASE_CASTER_NOT_STARTED; } break; case tPulseEdg: { @@ -1493,6 +1495,7 @@ void createSettingsString(char *newSettings) break; case tSysState: { SystemState *ptr = (SystemState *)rtkSettingsEntries[i].var; + stringRecord(newSettings, rtkSettingsEntries[i].name, (int)*ptr); } break; @@ -1882,20 +1885,24 @@ void createSettingsString(char *newSettings) stringRecord(newSettings, "measurementRateHz", 1.0 / gnss->getRateS(), 2); // 2 = decimals to print - // System state at power on. Convert various system states to either Rover or Base or NTP. - int lastState; // 0 = Rover, 1 = Base, 2 = NTP + // System state at power on. Convert various system states to either Rover, Base, NTP, or BaseCast. + int lastState; // 0 = Rover, 1 = Base, 2 = NTP, 3 = BaseCast if (present.ethernet_ws5500 == true) { lastState = 1; // Default Base - if (settings.lastState >= STATE_ROVER_NOT_STARTED && settings.lastState <= STATE_ROVER_RTK_FIX) + if (settings.baseCasterOverride) + lastState = 3; + else if (settings.lastState >= STATE_ROVER_NOT_STARTED && settings.lastState <= STATE_ROVER_RTK_FIX) lastState = 0; - if (settings.lastState >= STATE_NTPSERVER_NOT_STARTED && settings.lastState <= STATE_NTPSERVER_SYNC) + else if (settings.lastState >= STATE_NTPSERVER_NOT_STARTED && settings.lastState <= STATE_NTPSERVER_SYNC) lastState = 2; } else { lastState = 0; // Default Rover - if (settings.lastState >= STATE_BASE_NOT_STARTED && settings.lastState <= STATE_BASE_FIXED_TRANSMITTING) + if (settings.baseCasterOverride) + lastState = 3; + else if (settings.lastState >= STATE_BASE_NOT_STARTED && settings.lastState <= STATE_BASE_FIXED_TRANSMITTING) lastState = 1; } stringRecord(newSettings, "lastState", lastState); @@ -2317,11 +2324,13 @@ SettingValueResponse getSettingValue(bool inCommands, const char *settingName, c knownSetting = true; } break; - case tSysState: { - SystemState *ptr = (SystemState *)var; - writeToString(settingValueStr, (int)*ptr); - knownSetting = true; - } + // System state at power on. Convert various system states to either Rover, Base, NTP, or BaseCast. + // Manually handled below + // case tSysState: { + // SystemState *ptr = (SystemState *)var; + // writeToString(settingValueStr, (int)*ptr); + // knownSetting = true; + // } break; case tPulseEdg: { pulseEdgeType_e *ptr = (pulseEdgeType_e *)var; diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index 0773c7183..022e933c9 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -162,7 +162,7 @@ void menuSystem() if (present.ethernet_ws5500 == true) systemPrintln("N) Switch to NTP Server mode"); systemPrintln("R) Switch to Rover mode"); - systemPrintln("W) Switch to WiFi Config mode"); + systemPrintln("W) Switch to Web Config mode"); if (present.fastPowerOff == true) systemPrintln("S) Shut down"); diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index a5d4dcee7..14eb91e4a 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -1596,7 +1596,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugSettings, "debugSettings", }, { 1, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enableNtripCaster, "enableNtripCaster", }, - { 1, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.baseCasterOverride, "baseCasterOverride", }, + { 0, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.baseCasterOverride, "baseCasterOverride", }, // Add new settings to appropriate group above or create new group // Then also add to the same group in settings above From 5aacede168fe115242b44551af921b136b20cada Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2025 15:50:53 -0700 Subject: [PATCH 096/276] Add BaseCast display. Align vertical Base text. --- Firmware/RTK_Everywhere/Display.ino | 36 ++++++++++++++++++----------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index a93c865f8..fd6b79bf9 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -327,7 +327,7 @@ void displayUpdate() displayFullIPAddress(&iconPropertyList); // Bottom left - 128x64 only setRadioIcons(&iconPropertyList); paintBaseTempSurveyStarted(&iconPropertyList); - displaySivVsOpenShort(&iconPropertyList); // 128x64 only + displaySivVsOpenShort(&iconPropertyList); // 128x64 only break; case (STATE_BASE_TEMP_TRANSMITTING): paintLogging(&iconPropertyList); @@ -335,7 +335,7 @@ void displayUpdate() displayFullIPAddress(&iconPropertyList); // Bottom left - 128x64 only setRadioIcons(&iconPropertyList); paintRTCM(&iconPropertyList); - displaySivVsOpenShort(&iconPropertyList); // 128x64 only + displaySivVsOpenShort(&iconPropertyList); // 128x64 only break; case (STATE_BASE_FIXED_NOT_STARTED): displayBatteryVsEthernet(&iconPropertyList); // Top right @@ -348,7 +348,7 @@ void displayUpdate() displayFullIPAddress(&iconPropertyList); // Bottom left - 128x64 only setRadioIcons(&iconPropertyList); paintRTCM(&iconPropertyList); - displaySivVsOpenShort(&iconPropertyList); // 128x64 only + displaySivVsOpenShort(&iconPropertyList); // 128x64 only break; case (STATE_NTPSERVER_NOT_STARTED): @@ -410,7 +410,7 @@ void displayUpdate() else { setWiFiIcon(&iconPropertyList); // Blink WiFi in center - displayConfigViaWiFi(); // Display SSID and IP + displayConfigViaWiFi(); // Display SSID and IP } break; case (STATE_TEST): @@ -1659,14 +1659,14 @@ displayCoords paintSIVIcon(std::vector *iconList, const ic icon = &LBandIconProperties; else { - if(inBaseMode() == false) + if (inBaseMode() == false) icon = &SIVIconProperties; - else if(inBaseMode() && present.display_type == DISPLAY_128x64) - icon = &BaseSIVIconProperties; //Move SIV down to avoid collision with 'Xmitting RTCM' text + else if (inBaseMode() && present.display_type == DISPLAY_128x64) + icon = &BaseSIVIconProperties; // Move SIV down to avoid collision with 'Xmitting RTCM' text } // if in base mode, don't blink - if(inBaseMode() == true) + if (inBaseMode() == true) { // override duty - solid satellite dish icon regardless of fix state duty = 0b11111111; @@ -1704,7 +1704,7 @@ void paintSIVText(displayCoords textCoords) if (online.gnss) { - if(inBaseMode() == true) + if (inBaseMode() == true) oled->print(gnss->getSatellitesInView()); else if (gnss->isFixed() == false) oled->print("0"); @@ -2008,9 +2008,13 @@ void displayBaseStart(uint16_t displayTime) oled->erase(); uint8_t fontHeight = 15; // Assume fontsize 1 - uint8_t yPos = oled->getHeight() / 2 - fontHeight; + uint8_t yPos = oled->getHeight() / 2 - fontHeight + 1; + + if (settings.baseCasterOverride == true) + printTextCenter("BaseCast", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted + else + printTextCenter("Base", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted - printTextCenter("Base", yPos, QW_FONT_8X16, 1, false); // text, y, font type, kerning, inverted oled->display(); oled->display(); @@ -2021,12 +2025,18 @@ void displayBaseStart(uint16_t displayTime) void displayBaseSuccess(uint16_t displayTime) { - displayMessage("Base Started", displayTime); + if (settings.baseCasterOverride == true) + displayMessage("BaseCast Started", displayTime); + else + displayMessage("Base Started", displayTime); } void displayBaseFail(uint16_t displayTime) { - displayMessage("Base Failed", displayTime); + if (settings.baseCasterOverride == true) + displayMessage("BaseCast Failed", displayTime); + else + displayMessage("Base Failed", displayTime); } void displayGNSSFail(uint16_t displayTime) From 316483f60fa9dd362139bb4e6f14d898c5714f65 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 6 Jan 2025 16:30:17 -0700 Subject: [PATCH 097/276] Don't stop WiFi STA if events happen while AP is connected --- Firmware/RTK_Everywhere/Network.ino | 2 +- Firmware/RTK_Everywhere/WiFi.ino | 30 +++++++++++++++++------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index a0ca485f7..16f81fc15 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1593,7 +1593,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular // If NTRIP Caster is enabled then add AP mode - // Caster us available over ethernet, WiFi AP, WiFi STA, and cellular + // Caster is available over ethernet, WiFi AP, WiFi STA, and cellular // Caster is available in all mode: Rover, and Base if (settings.enableNtripCaster == true || settings.baseCasterOverride == true) *consumerTypes |= (1 << NETCONSUMER_WIFI_AP); diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 3934cd064..57a29b17c 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -234,10 +234,11 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) if (inWebConfigMode()) strncpy(softApSsid, "RTK Config", sizeof(softApSsid)); - //snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Config"); // TODO use settings.webconfigApName + // snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Config"); // TODO use + // settings.webconfigApName else strncpy(softApSsid, "RTK Caster", sizeof(softApSsid)); - //snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Caster"); + // snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Caster"); if (WiFi.softAP(softApSsid) == false) { @@ -344,11 +345,19 @@ void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) char ssid[sizeof(info.wifi_sta_connected.ssid) + 1]; IPAddress ipAddress; - // Take the network offline if necessary - if (networkIsInterfaceOnline(NETWORK_WIFI) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP) && - (event != ARDUINO_EVENT_WIFI_STA_GOT_IP6)) + // If we are in AP or AP_STA, the network is immediately marked online + // Once AP is online, don't stop WiFi because STA has various events + if (WiFi.getMode() == WIFI_MODE_STA) { - networkStop(NETWORK_WIFI, settings.debugNetworkLayer); // Stop WiFi to allow it to restart + // Take the network offline if necessary + if (networkIsInterfaceOnline(NETWORK_WIFI) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP) && + (event != ARDUINO_EVENT_WIFI_STA_GOT_IP6)) + { + if (settings.debugWifiState) + systemPrintf("Stopping WiFi because of event # %d\r\n", event); + + networkStop(NETWORK_WIFI, settings.debugNetworkLayer); // Stop WiFi to allow it to restart + } } // WiFi State Machine @@ -490,7 +499,6 @@ const char *wifiPrintState(wl_status_t wifiStatus) return ("WiFi Status Unknown"); } - //---------------------------------------- // Starts the WiFi connection state machine (moves from WIFI_STATE_OFF to WIFI_STATE_CONNECTING) // Sets the appropriate protocols (WiFi + ESP-Now) @@ -545,11 +553,7 @@ bool wifiStart() // Start WiFi if (wifiConnect(startWiFiStation, startWiFiAP, settings.wifiConnectTimeoutMs)) - { - wifiResetTimeout(); - if (settings.debugWifiState == true) - systemPrintln("WiFi: Start timeout reset to zero"); - } + wifiResetTimeout(); // If we successfully connected then reset the throttling timeout } // If we are in AP only mode, as long as the AP is started, return true @@ -568,6 +572,8 @@ bool wifiStart() void wifiResetTimeout() { wifiStartTimeout = 0; + if (settings.debugWifiState == true) + systemPrintln("WiFi: Start timeout reset to zero"); } //---------------------------------------- From be11af6d3071b02041fe257f33e52ce9f3009643 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 7 Jan 2025 11:24:21 -0700 Subject: [PATCH 098/276] WebConfig: Hide NAVIC constellation for ZED --- Firmware/RTK_Everywhere/AP-Config/src/main.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Firmware/RTK_Everywhere/AP-Config/src/main.js b/Firmware/RTK_Everywhere/AP-Config/src/main.js index 20be185c8..dc1e84bf1 100644 --- a/Firmware/RTK_Everywhere/AP-Config/src/main.js +++ b/Firmware/RTK_Everywhere/AP-Config/src/main.js @@ -122,6 +122,8 @@ function parseIncoming(msg) { show("useEnableExtCorrRadio"); show("extCorrRadioSPARTNSourceDropdown"); hide("shutdownNoChargeTimeoutCheckbox"); + + hide("constellationNavic"); //Not supported on ZED } else if ((platformPrefix == "Facet v2") || (platformPrefix == "Facet v2 LBand")) { show("baseConfig"); @@ -141,6 +143,8 @@ function parseIncoming(msg) { show("useLocalizedDistributionCheckbox"); show("useEnableExtCorrRadio"); show("extCorrRadioSPARTNSourceDropdown"); + + hide("constellationNavic"); //Not supported on ZED } else if (platformPrefix == "Facet mosaicX5") { show("baseConfig"); From ad06c002d334b5df0f2d174eebe3e1d7fec945f2 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 7 Jan 2025 12:12:11 -0700 Subject: [PATCH 099/276] Display BaseCast during base --- Firmware/RTK_Everywhere/Display.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index fd6b79bf9..15c85d9b0 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -1854,9 +1854,11 @@ void paintRTCM(std::vector *iconList) uint8_t yPos = CrossHairProperties.iconDisplay[present.display_type].yPos; if (present.display_type == DISPLAY_64x48) - yPos = yPos - 1; // Move text up by 1 pixel on 64x48. Note: this is brittle. TODO: find a better solution + yPos = yPos - 1; // Move text up by 1 pixel on 64x48. Note: this is brittle. - if (casting) + if(settings.baseCasterOverride == true) + printTextAt("BaseCast", xPos + 4, yPos, QW_FONT_8X16, 1); // text, y, font type, kerning + else if (casting) printTextAt("Casting", xPos + 4, yPos, QW_FONT_8X16, 1); // text, y, font type, kerning else printTextAt("Xmitting", xPos, yPos, QW_FONT_8X16, 1); // text, y, font type, kerning From a0ce154077ee91d5ef2d739caaae8f98ae6dd737 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 7 Jan 2025 12:12:50 -0700 Subject: [PATCH 100/276] Change AP name when state changes --- Firmware/RTK_Everywhere/States.ino | 33 ++++++++++++++++++++++++++---- Firmware/RTK_Everywhere/WiFi.ino | 4 ++-- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index d43b1cab3..16714afba 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -115,9 +115,9 @@ void stateUpdate() bluetoothStart(); // Turn on Bluetooth with 'Rover' name espnowStart(); // Start internal radio if enabled, otherwise disable - webServerStop(); // Stop the web config server + webServerStop(); // Stop the web config server baseCasterDisableOverride(); // Disable casting overrides - + // Start the UART connected to the GNSS receiver for NMEA and UBX data (enables logging) if (tasksStartGnssUart() == false) displayRoverFail(1000); @@ -210,6 +210,19 @@ void stateUpdate() case (STATE_BASE_CASTER_NOT_STARTED): { baseCasterEnableOverride(); + +#ifdef COMPILE_WIFI + // If the AP is already running, check that the name is correct + if ((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) + { + if (strcmp(WiFi.softAPSSID().c_str(), "RTK Caster") != 0) + { + // The AP name cannot be changed while it is running. WiFi must be restarted. + restartWiFi = true; // Tell network layer to restart WiFi + } + } +#endif // COMPILE_WIFI + changeState(STATE_BASE_NOT_STARTED); } break; @@ -236,7 +249,7 @@ void stateUpdate() settings.updateGNSSSettings = false; // On the next boot, no need to update the GNSS on this profile settings.lastState = STATE_BASE_NOT_STARTED; // Record this state for next POR - recordSystemSettings(); // Record this state for next POR + recordSystemSettings(); // Record this state for next POR displayBaseSuccess(500); // Show 'Base Started' @@ -431,7 +444,19 @@ void stateUpdate() bluetoothStop(); // Bluetooth must be stopped to allow enough RAM for AP+STA (firmware check) espnowStop(); // We don't need ESP-NOW during web config - // The GNSS UART task is left running to allow non-ZED platforms to obtain LLh data for 1Hz page updates + // The GNSS UART task is left running to allow GNSS receivers to obtain LLh data for 1Hz page updates + +#ifdef COMPILE_WIFI + // If the AP is already running, check that the name is correct + if ((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) + { + if (strcmp(WiFi.softAPSSID().c_str(), "RTK Config") != 0) + { + // The AP name cannot be changed while it is running. WiFi must be restarted. + restartWiFi = true; // Tell network layer to restart WiFi + } + } +#endif // COMPILE_WIFI // Stop any running NTRIP Client or Server ntripClientStop(true); // Do not allocate new wifiClient diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 57a29b17c..e8809863f 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -139,8 +139,8 @@ void menuWiFi() } //---------------------------------------- -// Starts WiFi in STA, AP, or STA_AP mode depending on networkGetConsumerTypes() -// Returns true if STA connects, or if AP is started, or if STA_AP is successful +// Starts WiFi in STA, AP, or STA_AP mode depending on bools +// Returns true if STA connects, or if AP is started //---------------------------------------- bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) { From 384b31be84becafb306641e31481b6069bc5372e Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 7 Jan 2025 12:22:54 -0700 Subject: [PATCH 101/276] Correctly throttle WiFi if AP is active. --- Firmware/RTK_Everywhere/WiFi.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index e8809863f..24895acd3 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -145,10 +145,10 @@ void menuWiFi() bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) { // Is a change needed? - if (startWiFiStation && startWiFiAP && WiFi.getMode() == WIFI_AP_STA) + if (startWiFiStation && startWiFiAP && WiFi.getMode() == WIFI_AP_STA && WiFi.status() == WL_CONNECTED) return (true); // There is nothing needing to be changed - if (startWiFiStation && WiFi.getMode() == WIFI_STA) + if (startWiFiStation && WiFi.getMode() == WIFI_STA && WiFi.status() == WL_CONNECTED) return (true); // There is nothing needing to be changed if (startWiFiAP && WiFi.getMode() == WIFI_AP) @@ -287,6 +287,7 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) int wifiStatus = wifiMulti->run(timeout); if (wifiStatus == WL_CONNECTED) { + wifiResetTimeout(); // If we successfully connected then reset the throttling timeout wifiRunning = true; return true; } @@ -552,8 +553,7 @@ bool wifiStart() } // Start WiFi - if (wifiConnect(startWiFiStation, startWiFiAP, settings.wifiConnectTimeoutMs)) - wifiResetTimeout(); // If we successfully connected then reset the throttling timeout + wifiConnect(startWiFiStation, startWiFiAP, settings.wifiConnectTimeoutMs); } // If we are in AP only mode, as long as the AP is started, return true From 4d2f2a6768340db747705214c27cc9ebc34592c3 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Tue, 7 Jan 2025 07:35:32 -1000 Subject: [PATCH 102/276] Network: Move NETWORK_POLL_SEQUENCEs from RAM into flash The network sequences should never change! --- Firmware/RTK_Everywhere/settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 14eb91e4a..c288ec0d6 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -1789,7 +1789,7 @@ enum NetworkTypes typedef void (* NETWORK_POLL_ROUTINE)(NetIndex_t index, uintptr_t parameter, bool debug); // Sequence entry specifying a poll routine call for a network interface -typedef struct _NETWORK_POLL_SEQUENCE +typedef const struct _NETWORK_POLL_SEQUENCE { NETWORK_POLL_ROUTINE routine; // Address of poll routine, nullptr at end of table uintptr_t parameter; // Parameter passed to poll routine From a0779c197d0140f48212c8ae9f87efdd96bd05c9 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 7 Jan 2025 14:50:58 -0700 Subject: [PATCH 103/276] Mark cellular not present/offline if no SIM card present. --- Firmware/RTK_Everywhere/Cellular.ino | 42 ++++++---------------------- Firmware/RTK_Everywhere/LARA.ino | 1 - 2 files changed, 8 insertions(+), 35 deletions(-) diff --git a/Firmware/RTK_Everywhere/Cellular.ino b/Firmware/RTK_Everywhere/Cellular.ino index 79ccff3f6..fa7b12205 100644 --- a/Firmware/RTK_Everywhere/Cellular.ino +++ b/Firmware/RTK_Everywhere/Cellular.ino @@ -23,8 +23,6 @@ //---------------------------------------- -static bool cellularSimCardRemoved = false; -static bool cellularSimCardPresent = false; static int cellularRSSI = 0; static bool cellularIsAttached = false; @@ -148,43 +146,19 @@ void cellularSimCheck(NetIndex_t index, uintptr_t parameter, bool debug) { String simCardID; - if (cellularSimCardPresent) - networkSequenceNextEntry(index, debug); - else + simCardID = CELLULAR.cmd("AT+CCID", 500); + if (simCardID.length()) { - simCardID = CELLULAR.cmd("AT+CCID", 500); - if (simCardID.length()) - { - if (debug) - systemPrintf("SIM card %s installed\r\n", simCardID.c_str()); - cellularSimCardPresent = true; - networkSequenceNextEntry(index, debug); - } - else - { - if (debug) - systemPrintf("SIM card not present\r\n"); - cellularSimCardRemoved = true; - networkSequenceExit(index, debug); - } + if (debug) + systemPrintf("SIM card %s installed\r\n", simCardID.c_str()); + networkSequenceNextEntry(index, debug); } -} - -//---------------------------------------- -// Stop if SIM card not installed -void cellularSimInstalled(NetIndex_t index, uintptr_t parameter, bool debug) -{ - // Determine if the SIM card check has run - if (cellularSimCardRemoved) + else { - if (debug) - systemPrintf("SIM card was not present, leaving cellular off\r\n"); + systemPrintf("SIM card not present. Marking cellular offline.\r\n"); + present.cellular_lara = false; networkSequenceExit(index, debug); } - - // Get the next sequence entry - else - networkSequenceNextEntry(index, debug); } //---------------------------------------- diff --git a/Firmware/RTK_Everywhere/LARA.ino b/Firmware/RTK_Everywhere/LARA.ino index aed99d24d..2972f8093 100644 --- a/Firmware/RTK_Everywhere/LARA.ino +++ b/Firmware/RTK_Everywhere/LARA.ino @@ -138,7 +138,6 @@ NETWORK_POLL_SEQUENCE laraBootSequence[] = // (Remember that LARA_PWR is inverted by the RTK EVK level-shifter) NETWORK_POLL_SEQUENCE laraOnSequence[] = { // State Parameter Description - {cellularSimInstalled, 0, "SIM card validation"}, {laraPowerLow, LARA_ON_TIME, "Notify LARA of power state change"}, {networkDelay, (uintptr_t)&laraTimer, "Tell LARA to power on"}, {laraPowerHigh, LARA_SETTLE_TIME, "Finish power on sequence"}, From 0fbf19cc1a943059b054528a3aab9f6f93505ec0 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 9 Jan 2025 11:39:46 +0000 Subject: [PATCH 104/276] Add soft reset to resolve "Ready for SUF Download" issue on X5 --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 862694af1..15009f258 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -225,8 +225,26 @@ void GNSS_MOSAIC::begin() if (retries == retryLimit) { - systemPrintln("Could not communicate with mosaic-X5!"); - return; + systemPrintln("Could not communicate with mosaic-X5! Attempting a soft reset..."); + + sendWithResponse("erst,soft,none\n\r", "ResetReceiver"); + + retries = 0; + + // Set COM4 to: CMD input (only), SBF output (only) + while (!sendWithResponse("sdio,COM4,CMD,SBF\n\r", "DataInOut")) + { + if (retries == retryLimit) + break; + retries++; + sendWithResponse("SSSSSSSSSSSSSSSSSSSS\n\r", "COM4>"); // Send escape sequence + } + + if (retries == retryLimit) + { + systemPrintln("Could not communicate with mosaic-X5!"); + return; + } } retries = 0; From e224045eaa1fa78c2571d39d7d9a33a2f172f957 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 9 Jan 2025 14:15:44 -0700 Subject: [PATCH 105/276] During base settle, SIV inline with HPA --- Firmware/RTK_Everywhere/Display.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 15c85d9b0..e1c83ab32 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -1661,6 +1661,8 @@ displayCoords paintSIVIcon(std::vector *iconList, const ic { if (inBaseMode() == false) icon = &SIVIconProperties; + else if (systemState == STATE_BASE_TEMP_SETTLE) + icon = &SIVIconProperties; //During base settle, SIV inline with HPA else if (inBaseMode() && present.display_type == DISPLAY_128x64) icon = &BaseSIVIconProperties; // Move SIV down to avoid collision with 'Xmitting RTCM' text } From 942fed05e75b8af150cede97235b92817b52499a Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 9 Jan 2025 14:16:12 -0700 Subject: [PATCH 106/276] Don't start the next network if the previous one is online --- Firmware/RTK_Everywhere/Network.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 16f81fc15..1a7a3d59e 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1453,10 +1453,11 @@ void networkUpdate() if (consumerTypes && (1 << NETCONSUMER_ETHERNET)) networkStart(NETWORK_ETHERNET, settings.debugNetworkLayer); - if ((consumerTypes && (1 << NETCONSUMER_WIFI_STA)) || (consumerTypes && (1 << NETCONSUMER_WIFI_AP))) + if ((networkIsOnline() == false) && (consumerTypes && (1 << NETCONSUMER_WIFI_STA)) || + (consumerTypes && (1 << NETCONSUMER_WIFI_AP))) networkStart(NETWORK_WIFI, settings.debugNetworkLayer); - if (consumerTypes && (1 << NETCONSUMER_CELLULAR)) + if ((networkIsOnline() == false) && (consumerTypes && (1 << NETCONSUMER_CELLULAR))) networkStart(NETWORK_CELLULAR, settings.debugNetworkLayer); } From 49d1a3308c8cdf87989cc2772d2af46946940da7 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 9 Jan 2025 14:16:50 -0700 Subject: [PATCH 107/276] During WebConfig, fall back to AP mode if STA connection failed. --- Firmware/RTK_Everywhere/Network.ino | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 1a7a3d59e..7e431e2ff 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1408,7 +1408,7 @@ void networkUpdate() // Stop WiFi to allow restart with new settings if (restartWiFi == true && networkIsInterfaceOnline(NETWORK_WIFI)) { - if (settings.debugNetworkLayer) + if (settings.debugNetworkLayer) systemPrintln("WiFi settings changed, restarting WiFi"); restartWiFi = false; @@ -1643,6 +1643,15 @@ uint8_t networkConsumers(uint16_t *consumerTypes) if (settings.wifiConfigOverAP == true) *consumerTypes |= (1 << NETCONSUMER_WIFI_AP); // WebConfig requires both AP and STA (for firmware check) + + // A good number of RTK products have only WiFi + // If WiFi STA has failed, fall back to WiFi AP, but allow STA to keep hunting + if (networkIsPresent(NETWORK_ETHERNET) == false && networkIsPresent(NETWORK_CELLULAR) == false && + settings.wifiConfigOverAP == false && wifiGetStartTimeout() > 0) + { + *consumerTypes |= (1 << NETCONSUMER_WIFI_AP); // Re-allow Webconfig over AP + wifiResetTimeout(); // Force immediate switch to AP mode + } } // Debug From 1431f37b860f417e42a4c4d826330100e6f9fc2a Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 9 Jan 2025 14:17:26 -0700 Subject: [PATCH 108/276] Discard everything but RTCM during BaseCast --- Firmware/RTK_Everywhere/Tasks.ino | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index 4e04800ae..46d771056 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -734,6 +734,19 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type) } } + // If BaseCasterOverride is enabled, remove everything but RTCM from the circular buffer + // to avoid saturating the downstream radio link that is consuming over a TCP (NTRIP Caster) connection + // Remove NMEA, etc after passing to the GNSS receiver library so that we still have SIV and other stats available + if (settings.baseCasterOverride == true) + { + if (type != RTK_RTCM_PARSER_INDEX) + { + // Erase buffer + parse->buffer[0] = 0; + parse->length = 0; + } + } + // Determine if this message will fit into the ring buffer bytesToCopy = parse->length; space = availableHandlerSpace; @@ -1848,7 +1861,8 @@ void buttonCheckTask(void *e) firstButtonThrownOut = false; requestChangeState(lastSystemState); } - else if (it->newState == STATE_BASE_NOT_STARTED) // User selected Base, clear BaseCast override + else if (it->newState == + STATE_BASE_NOT_STARTED) // User selected Base, clear BaseCast override { baseCasterDisableOverride(); requestChangeState(it->newState); From de621fd04750cd6ec7adf296b5fdb199b8bc3592 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 9 Jan 2025 14:18:06 -0700 Subject: [PATCH 109/276] Add wifiGetStartTimeout() --- Firmware/RTK_Everywhere/Developer.ino | 1 + Firmware/RTK_Everywhere/WiFi.ino | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index ad5344885..d88965634 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -171,6 +171,7 @@ void menuWiFi() {systemPrintln("**WiFi not compiled**");} bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) {return false;} int wifiNetworkCount() {return 0;} bool wifiIsRunning() {return false;} +uint32_t wifiGetStartTimeout() {return 0;} #define WIFI_STOP() {} #endif // COMPILE_WIFI diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 24895acd3..47e66b2aa 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -576,6 +576,13 @@ void wifiResetTimeout() systemPrintln("WiFi: Start timeout reset to zero"); } +//---------------------------------------- +//---------------------------------------- +uint32_t wifiGetStartTimeout() +{ + return (wifiStartTimeout); +} + //---------------------------------------- // Reset the last WiFi start attempt // Useful when WiFi settings have changed From 4c5317216962288a28e3a1dc2bd44c57039c284b Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 9 Jan 2025 15:15:22 -0700 Subject: [PATCH 110/276] Change to shutdownNoChargeTimeoutMinutes Make work over web config --- Firmware/RTK_Everywhere/AP-Config/index.html | 16 +++++----- Firmware/RTK_Everywhere/AP-Config/src/main.js | 30 +++++++++++++++---- Firmware/RTK_Everywhere/Network.ino | 5 ++-- Firmware/RTK_Everywhere/System.ino | 6 ++-- Firmware/RTK_Everywhere/menuSystem.ino | 8 ++--- Firmware/RTK_Everywhere/settings.h | 4 +-- 6 files changed, 43 insertions(+), 26 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/index.html b/Firmware/RTK_Everywhere/AP-Config/index.html index a329162a0..2054d5535 100644 --- a/Firmware/RTK_Everywhere/AP-Config/index.html +++ b/Firmware/RTK_Everywhere/AP-Config/index.html @@ -2200,10 +2200,10 @@
-
+
- - + + @@ -2211,17 +2211,17 @@
-
+
-
diff --git a/Firmware/RTK_Everywhere/AP-Config/src/main.js b/Firmware/RTK_Everywhere/AP-Config/src/main.js index dc1e84bf1..af2c713d8 100644 --- a/Firmware/RTK_Everywhere/AP-Config/src/main.js +++ b/Firmware/RTK_Everywhere/AP-Config/src/main.js @@ -121,7 +121,7 @@ function parseIncoming(msg) { show("useLocalizedDistributionCheckbox"); show("useEnableExtCorrRadio"); show("extCorrRadioSPARTNSourceDropdown"); - hide("shutdownNoChargeTimeoutCheckbox"); + hide("shutdownNoChargeTimeoutMinutesCheckboxDetail"); hide("constellationNavic"); //Not supported on ZED } @@ -512,6 +512,18 @@ function parseIncoming(msg) { hide("enableAutomaticResetDetails"); } } + else if (id.includes("shutdownNoChargeTimeoutMinutes")) { + if (val > 0) { + ge("shutdownNoChargeTimeoutMinutes").value = val; + ge("shutdownNoChargeTimeoutMinutesCheckbox").checked = true; + show("shutdownNoChargeTimeoutMinutesDetails"); + } + else { + ge("shutdownNoChargeTimeoutMinutes").value = 0; + ge("shutdownNoChargeTimeoutMinutesCheckbox").checked = false; + hide("shutdownNoChargeTimeoutMinutesDetails"); + } + } //Convert incoming mm to local meters else if (id.includes("antennaHeight_mm")) { @@ -960,12 +972,18 @@ function validateFields() { } if (ge("enableAutoReset").checked == true) { - checkElementValue("rebootMinutes", 1, 4294967, "Must be 1 to 4294967", "collapseSystemConfig"); + checkElementValue("rebootMinutes", 0, 4294967, "Must be 0 to 4,294,967", "collapseSystemConfig"); } else { clearElement("rebootMinutes", 0); //0 = disable } + if (ge("shutdownNoChargeTimeoutMinutesCheckbox").checked == true) { + checkElementValue("shutdownNoChargeTimeoutMinutes", 0, 604800, "Must be 0 to 604,800", "collapseSystemConfig"); + } + else { + clearElement("shutdownNoChargeTimeoutMinutes", 0); //0 = disable + } //Ethernet if (platformPrefix == "EVK") { @@ -1737,12 +1755,12 @@ document.addEventListener("DOMContentLoaded", (event) => { } }); - ge("shutdownNoChargeTimeout").addEventListener("change", function () { - if (ge("shutdownNoChargeTimeout").checked == true) { - show("shutdownNoChargeTimeoutDetails"); + ge("shutdownNoChargeTimeoutMinutesCheckbox").addEventListener("change", function () { + if (ge("shutdownNoChargeTimeoutMinutesCheckbox").checked == true) { + show("shutdownNoChargeTimeoutMinutesDetails"); } else { - hide("shutdownNoChargeTimeoutDetails"); + hide("shutdownNoChargeTimeoutMinutesDetails"); } }); diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 7e431e2ff..4c54ee982 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1645,12 +1645,11 @@ uint8_t networkConsumers(uint16_t *consumerTypes) *consumerTypes |= (1 << NETCONSUMER_WIFI_AP); // WebConfig requires both AP and STA (for firmware check) // A good number of RTK products have only WiFi - // If WiFi STA has failed, fall back to WiFi AP, but allow STA to keep hunting + // If WiFi STA has failed or we have no WiFi SSIDs, fall back to WiFi AP, but allow STA to keep hunting if (networkIsPresent(NETWORK_ETHERNET) == false && networkIsPresent(NETWORK_CELLULAR) == false && - settings.wifiConfigOverAP == false && wifiGetStartTimeout() > 0) + settings.wifiConfigOverAP == false && (wifiGetStartTimeout() > 0 || wifiNetworkCount() == 0)) { *consumerTypes |= (1 << NETCONSUMER_WIFI_AP); // Re-allow Webconfig over AP - wifiResetTimeout(); // Force immediate switch to AP mode } } diff --git a/Firmware/RTK_Everywhere/System.ino b/Firmware/RTK_Everywhere/System.ino index 00799cf6a..0677ba460 100644 --- a/Firmware/RTK_Everywhere/System.ino +++ b/Firmware/RTK_Everywhere/System.ino @@ -162,12 +162,12 @@ void updateBattery() } // Check if we need to shutdown due to no charging - if (settings.shutdownNoChargeTimeout_s > 0) + if (settings.shutdownNoChargeTimeoutMinutes > 0) { if (isCharging() == false) { - int secondsSinceLastCharger = (millis() - shutdownNoChargeTimer) / 1000; - if (secondsSinceLastCharger > settings.shutdownNoChargeTimeout_s) + int minutesSinceLastCharge = ((millis() - shutdownNoChargeTimer) / 1000) / 60; + if (minutesSinceLastCharge > settings.shutdownNoChargeTimeoutMinutes) powerDown(true); } else diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index 022e933c9..e04114ea6 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -200,10 +200,10 @@ void menuSystem() if (present.fuelgauge_max17048 || present.fuelgauge_bq40z50 || present.charger_mp2762a) { - if (settings.shutdownNoChargeTimeout_s == 0) + if (settings.shutdownNoChargeTimeoutMinutes == 0) systemPrintln("c) Shutdown if not charging: Disabled"); else - systemPrintf("c) Shutdown if not charging after: %d seconds\r\n", settings.shutdownNoChargeTimeout_s); + systemPrintf("c) Shutdown if not charging after: %d minutes\r\n", settings.shutdownNoChargeTimeoutMinutes); } systemPrintln("d) Debug software"); @@ -299,8 +299,8 @@ void menuSystem() else if ((incoming == 'c') && (present.fuelgauge_max17048 || present.fuelgauge_bq40z50 || present.charger_mp2762a)) { - getNewSetting("Enter time in seconds to shutdown unit if not charging (0 to disable)", 0, 60 * 60 * 24 * 7, - &settings.shutdownNoChargeTimeout_s); // Arbitrary 7 day limit + getNewSetting("Enter time in minutes to shutdown unit if not charging (0 to disable)", 0, 60 * 24 * 7, + &settings.shutdownNoChargeTimeoutMinutes); // Arbitrary 7 day limit } else if (incoming == 'd') menuDebugSoftware(); diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index c288ec0d6..e8325e5f5 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -594,7 +594,7 @@ struct Settings // Battery bool enablePrintBatteryMessages = true; - uint32_t shutdownNoChargeTimeout_s = 0; // If > 0, shut down unit after timeout if not charging + uint32_t shutdownNoChargeTimeoutMinutes = 0; // If > 0, shut down unit after timeout if not charging // Beeper bool enableBeeper = true; // Some platforms have an audible notification @@ -1136,7 +1136,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = // Battery { 0, 0, 0, 0, 1, 1, 1, 1, 1, _bool, 0, & settings.enablePrintBatteryMessages, "enablePrintBatteryMessages", }, - { 1, 1, 0, 0, 1, 1, 1, 1, 1, _uint32_t, 0, & settings.shutdownNoChargeTimeout_s, "shutdownNoChargeTimeout", }, + { 1, 1, 0, 0, 1, 1, 1, 1, 1, _uint32_t, 0, & settings.shutdownNoChargeTimeoutMinutes, "shutdownNoChargeTimeoutMinutes", }, // F // a From d3f4b27456f4d40c3bffb569f81d6930ca8c56c7 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 9 Jan 2025 16:28:27 -0700 Subject: [PATCH 111/276] Add connecttest to webserver --- Firmware/RTK_Everywhere/WebServer.ino | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index 1e2e5f644..c96f69e12 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -334,8 +334,6 @@ bool webServerAssignResources(int httpPort = 80) if (settings.enableCaptivePortal == true) { webServer->addHandler(new CaptiveRequestHandler()); - - // TODO: add a handler for /connecttest.txt } // * index.html (not gz'd) @@ -469,6 +467,11 @@ bool webServerAssignResources(int httpPort = 80) webServer->send_P(200, "text/plain", (const char *)icomoon_woof, sizeof(icomoon_woof)); }); + //https://lemariva.com/blog/2017/11/white-hacking-wemos-captive-portal-using-micropython + webServer->on("/connecttest.txt", HTTP_GET, []() { + webServer->send(200, "text/plain", "Microsoft Connect Test"); + }); + // Handler for the /uploadFile form POST webServer->on( "/uploadFile", HTTP_POST, []() { webServer->send(200, "text/plain", ""); }, @@ -1130,6 +1133,10 @@ void createDynamicDataString(char *settingsCSV) stringRecord(settingsCSV, "batteryIconFileName", batteryIconFileName); + //Limit batteryLevelPercent to sane levels + if (batteryLevelPercent > 100) + batteryLevelPercent = 100; + // Determine battery percent char batteryPercent[sizeof("+100%__")]; if (isCharging()) From c6f00855f41636cafff63b4f9fff6b005d0b3e15 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jan 2025 16:49:57 +0000 Subject: [PATCH 112/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4173 ++++++++++++++++---------------- 1 file changed, 2098 insertions(+), 2075 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index 902b5a2fe..bab182952 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,1010 +26,1021 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xB7, 0x72, 0x78, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, - 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0x1B, 0x39, 0xB2, 0xE8, 0xFF, - 0x79, 0x0A, 0xAD, 0xEF, 0xDE, 0x31, 0x2C, 0xC6, 0xD8, 0xE6, 0x23, 0x21, 0x84, 0xEC, 0x25, 0x40, - 0x12, 0xEE, 0x02, 0xE1, 0x62, 0x32, 0x33, 0x99, 0x6C, 0x0E, 0xA7, 0x71, 0x0B, 0xD3, 0x27, 0x76, - 0xB7, 0xB7, 0xBB, 0x0D, 0x61, 0xF6, 0xF0, 0x4E, 0xE7, 0x19, 0xCE, 0x93, 0xDD, 0x2A, 0x49, 0xDD, - 0x2D, 0xA9, 0xD5, 0x9F, 0xB6, 0x09, 0xB3, 0x27, 0xF9, 0xFD, 0x86, 0x81, 0x96, 0xEA, 0x43, 0xA5, - 0x52, 0xA9, 0x24, 0x95, 0x4A, 0xB7, 0x96, 0x4F, 0x86, 0x56, 0x48, 0xEF, 0xAC, 0x7B, 0xB2, 0x4B, - 0xFE, 0xFD, 0x2E, 0x78, 0xB9, 0xB6, 0xF6, 0xE7, 0x7F, 0xDE, 0x39, 0xAE, 0xED, 0xDD, 0xB5, 0x47, - 0xDE, 0xC0, 0x0A, 0x1D, 0xCF, 0x6D, 0xDF, 0x78, 0x41, 0xE8, 0x5A, 0x63, 0xFA, 0xF0, 0xF2, 0x45, - 0x77, 0xED, 0x2E, 0xF8, 0xF7, 0x9D, 0x67, 0xB7, 0x00, 0x77, 0x47, 0xAF, 0x02, 0x6F, 0xF0, 0x95, - 0x86, 0x3B, 0xCF, 0x9E, 0x09, 0x08, 0xCB, 0xB6, 0x0F, 0x6F, 0xA9, 0x1B, 0x1E, 0x3B, 0x41, 0x48, - 0x5D, 0xEA, 0x2F, 0x35, 0x47, 0x9E, 0x65, 0x37, 0x5B, 0xC4, 0x73, 0x8F, 0xE1, 0x97, 0x65, 0xA8, - 0x79, 0x3D, 0x75, 0x07, 0x88, 0x54, 0x7C, 0x5A, 0xA2, 0x58, 0x7F, 0x99, 0xFC, 0xF3, 0x19, 0x81, - 0x7F, 0x8E, 0xEB, 0x84, 0xBF, 0xD0, 0xAB, 0x3E, 0x43, 0xBB, 0x04, 0xD5, 0x1F, 0x24, 0x00, 0xAD, - 0x50, 0x80, 0xC4, 0x5C, 0x00, 0xFF, 0x2E, 0xBD, 0x23, 0x49, 0x0D, 0xD1, 0x2E, 0xC0, 0xA2, 0xD4, - 0x6B, 0x7B, 0xEE, 0x98, 0x06, 0x81, 0x35, 0xA4, 0x00, 0x11, 0x23, 0x5F, 0x1A, 0x07, 0xC3, 0x08, - 0x25, 0xFE, 0x9B, 0x58, 0x7E, 0x40, 0x8F, 0xDC, 0x81, 0x37, 0x76, 0xDC, 0x21, 0x16, 0xB6, 0x6D, - 0x2B, 0xB4, 0x04, 0xAE, 0x07, 0x95, 0xB1, 0x21, 0x5D, 0xA2, 0x11, 0xAC, 0x4F, 0xC3, 0xA9, 0xEF, - 0x12, 0xDB, 0x1B, 0x4C, 0xC7, 0xD0, 0xB0, 0xF6, 0x90, 0x86, 0x87, 0x23, 0x8A, 0xBF, 0xBE, 0xB9, - 0x3F, 0x82, 0xD6, 0xF2, 0x36, 0xA1, 0xF8, 0xAE, 0x9D, 0x6F, 0xD4, 0x3E, 0xB6, 0x90, 0xEF, 0xCE, - 0x8E, 0xF4, 0xC5, 0x73, 0x87, 0xC9, 0xA7, 0xC9, 0xC8, 0x0A, 0xAF, 0x3D, 0x7F, 0x7C, 0xE6, 0x53, - 0x28, 0x85, 0xEF, 0x8D, 0x06, 0x2F, 0x18, 0x52, 0xCF, 0xA6, 0xA1, 0x33, 0xE0, 0x08, 0x36, 0x3A, - 0xED, 0x4E, 0x57, 0x2B, 0x00, 0xC6, 0x76, 0xC9, 0x6A, 0xB7, 0xB3, 0xD9, 0xEE, 0x6E, 0xAB, 0x45, - 0x7B, 0x23, 0x84, 0xE9, 0x6E, 0x76, 0x3A, 0x6D, 0x01, 0x44, 0x07, 0xF4, 0xFA, 0x57, 0x56, 0xBD, - 0xF7, 0xA2, 0xD3, 0xEB, 0x6C, 0xB5, 0x37, 0xB7, 0x5E, 0x24, 0x25, 0x9F, 0xB0, 0x64, 0xE3, 0x79, - 0x77, 0xEB, 0x45, 0x67, 0xA3, 0xBD, 0xD1, 0x59, 0x4F, 0x4A, 0x7E, 0x63, 0xB4, 0x5F, 0x6C, 0x6D, - 0x6D, 0x6D, 0xB6, 0x37, 0x5E, 0x6C, 0xF0, 0x82, 0x91, 0x15, 0x84, 0x6F, 0x9D, 0x11, 0x3D, 0x05, - 0x8D, 0x91, 0x38, 0xBE, 0xC6, 0x4F, 0xD3, 0xF1, 0x15, 0xF5, 0x93, 0xE6, 0xB9, 0xEC, 0xEF, 0x0F, - 0xD7, 0x58, 0x3D, 0xE8, 0xD3, 0x11, 0x1D, 0x84, 0xD4, 0x4E, 0x8A, 0x03, 0xF1, 0x85, 0x15, 0x4B, - 0xA8, 0x82, 0x1B, 0x0F, 0x14, 0x6E, 0x88, 0x9F, 0x51, 0xD3, 0xB0, 0x1F, 0xAD, 0x51, 0x40, 0x79, - 0xA1, 0x77, 0x15, 0x5A, 0x8E, 0x4B, 0xED, 0x13, 0xDE, 0xC9, 0xA5, 0x2A, 0xBC, 0xB1, 0x02, 0xAA, - 0x56, 0x12, 0x24, 0x44, 0x9D, 0xF3, 0x8B, 0xFD, 0x93, 0x34, 0x22, 0x6C, 0xD1, 0x85, 0x75, 0x05, - 0x3F, 0xE8, 0xB7, 0x50, 0x62, 0x6F, 0xE0, 0xF9, 0x3E, 0x65, 0xAA, 0xA1, 0x15, 0x08, 0xBD, 0xD3, - 0xBE, 0xA2, 0xBC, 0x04, 0x9D, 0x8B, 0xFB, 0x09, 0xCD, 0x2E, 0x11, 0x5C, 0x62, 0x29, 0xE7, 0xD1, - 0xBA, 0x8D, 0x5B, 0x81, 0xC2, 0x46, 0x11, 0x7D, 0xFE, 0xB2, 0x93, 0x2A, 0xFB, 0xD9, 0x1A, 0x4D, - 0xD3, 0x85, 0xFB, 0x37, 0x74, 0xF0, 0xF5, 0xCA, 0xFB, 0x66, 0x84, 0x8C, 0x0A, 0x15, 0x50, 0x56, - 0x0C, 0x2D, 0xF3, 0x7C, 0x3B, 0x38, 0xDC, 0x3F, 0x7C, 0x2B, 0x01, 0x89, 0xAF, 0xEF, 0x84, 0x86, - 0x49, 0x25, 0xD7, 0xD3, 0xD1, 0xE8, 0x0C, 0x98, 0xF8, 0x38, 0x81, 0x01, 0x24, 0x09, 0x59, 0x80, - 0x05, 0x34, 0xBC, 0x70, 0xC6, 0xD4, 0x9B, 0x86, 0x51, 0x97, 0xBB, 0xF6, 0x01, 0x8C, 0x34, 0xE5, - 0xE3, 0x00, 0xB9, 0x39, 0xA5, 0x77, 0x6F, 0x1D, 0x7F, 0x7C, 0x67, 0xF9, 0x54, 0x29, 0x84, 0x11, - 0x66, 0x2A, 0x7A, 0x36, 0xF0, 0x5C, 0xE8, 0x30, 0xD0, 0xB0, 0xFD, 0xB8, 0x3B, 0x82, 0xBE, 0x37, - 0xF5, 0x07, 0xAC, 0x3D, 0x2F, 0xF4, 0xAE, 0x12, 0x65, 0xBA, 0x34, 0x52, 0x15, 0xCE, 0x7C, 0xC7, - 0xF3, 0x9D, 0xD0, 0x49, 0xA4, 0xC2, 0x09, 0xED, 0x7B, 0x20, 0x00, 0xC7, 0x85, 0x36, 0x62, 0x57, - 0x61, 0x21, 0x37, 0x08, 0xFB, 0x1F, 0x3E, 0x9C, 0x1F, 0x1C, 0x9D, 0xEE, 0x5D, 0x1C, 0x5E, 0x1E, - 0x9D, 0x9E, 0x7D, 0xBC, 0xB8, 0xBC, 0xF8, 0x74, 0x76, 0x78, 0x79, 0x70, 0xF0, 0x92, 0x74, 0x5A, - 0x64, 0x6D, 0xED, 0x80, 0x5E, 0x5B, 0x53, 0x18, 0x8F, 0x07, 0x07, 0x6D, 0x3B, 0xFA, 0x97, 0x0B, - 0x77, 0x72, 0xF2, 0x92, 0x74, 0x19, 0x24, 0xFC, 0xDA, 0x1E, 0xE3, 0xBF, 0xDC, 0xFA, 0x97, 0x08, - 0xD0, 0xE3, 0x00, 0xA4, 0x2C, 0xC4, 0xE5, 0xC1, 0x5E, 0xFF, 0xFD, 0x4B, 0xB2, 0xCE, 0xC1, 0x56, - 0x4B, 0x83, 0xF5, 0x3F, 0x9D, 0xBC, 0xF9, 0x70, 0xFC, 0x92, 0x6C, 0x70, 0xC0, 0xFF, 0xFE, 0xAF, - 0x08, 0x72, 0x3C, 0x6E, 0x16, 0xB4, 0xAA, 0xDF, 0x7F, 0x49, 0x36, 0x63, 0x36, 0x49, 0xBF, 0xDF, - 0x0E, 0xD8, 0xBF, 0x62, 0x9A, 0x00, 0xB8, 0x55, 0x0F, 0x50, 0x34, 0xF3, 0x79, 0xDC, 0xCC, 0xD5, - 0x4A, 0xD0, 0x51, 0x6B, 0x5F, 0x24, 0xAD, 0x6D, 0xC6, 0x08, 0x1A, 0x85, 0xED, 0xBD, 0x3C, 0xFD, - 0x70, 0x79, 0x70, 0xB8, 0x7F, 0x74, 0xB2, 0x07, 0x38, 0xB6, 0xA3, 0x2E, 0xED, 0xF7, 0xC9, 0x2A, - 0x39, 0xF5, 0x88, 0x4D, 0x07, 0xCE, 0xD8, 0x1A, 0x95, 0xE1, 0x43, 0xC6, 0xD3, 0xED, 0xC8, 0xA2, - 0xA8, 0x8C, 0x0A, 0x05, 0xA2, 0xE2, 0xEB, 0xCA, 0xC2, 0x29, 0x8B, 0xEF, 0xE8, 0xF4, 0xE7, 0xBD, - 0xE3, 0xA3, 0x83, 0xCB, 0x8F, 0xA7, 0x7F, 0x3B, 0xFD, 0xF0, 0xCB, 0x29, 0xA0, 0xE9, 0xB5, 0xA2, - 0x79, 0x0F, 0x86, 0xCB, 0x2D, 0xF5, 0xC1, 0xAA, 0x27, 0x23, 0x06, 0x2D, 0x7E, 0xBB, 0x13, 0x0D, - 0xB8, 0xE8, 0xEB, 0x91, 0x3B, 0x99, 0x86, 0xC2, 0x22, 0x6A, 0xA3, 0xAB, 0x9D, 0xD5, 0x0C, 0xD9, - 0xC1, 0x48, 0x4D, 0xE1, 0xD1, 0x1C, 0xBD, 0xB6, 0x86, 0x43, 0xD6, 0x1B, 0x51, 0xF0, 0x70, 0x86, - 0x4B, 0x8D, 0xA8, 0x4A, 0x64, 0x9E, 0x5F, 0x92, 0x06, 0x59, 0x21, 0x58, 0x1F, 0xB0, 0x61, 0x7D, - 0x64, 0x0B, 0x67, 0x7F, 0xE0, 0x03, 0x1D, 0x81, 0x60, 0x32, 0x72, 0xC2, 0xA5, 0x66, 0xAB, 0x29, - 0xBC, 0x01, 0x98, 0x9F, 0xC9, 0xD2, 0x08, 0x1C, 0x90, 0x6F, 0x6C, 0xE6, 0x82, 0xFF, 0xBD, 0x62, - 0xD5, 0xDB, 0x23, 0xEA, 0x0E, 0xC3, 0x1B, 0x90, 0x59, 0x17, 0x3F, 0xAE, 0xEC, 0x92, 0x9E, 0xEC, - 0x61, 0x20, 0x56, 0x07, 0x27, 0x3B, 0xAC, 0xFB, 0xF9, 0xDB, 0x97, 0x1D, 0xA5, 0xE4, 0xD6, 0x1A, - 0xC5, 0x45, 0xC0, 0x4D, 0x57, 0x2A, 0xD6, 0xD8, 0x77, 0x6C, 0xCE, 0x30, 0xE0, 0x5A, 0x21, 0x8D, - 0x16, 0x42, 0xF2, 0x0F, 0xF0, 0x4B, 0xD4, 0x02, 0x0E, 0xD6, 0x9F, 0x40, 0xC7, 0x01, 0x5E, 0x68, - 0xEE, 0xD8, 0x72, 0xED, 0x20, 0x2E, 0x72, 0xAE, 0xC9, 0x92, 0x63, 0xB7, 0x1D, 0x77, 0x30, 0x9A, - 0xDA, 0x34, 0x58, 0x6A, 0x04, 0xF6, 0x89, 0x37, 0x75, 0xA1, 0x8F, 0x1A, 0xCB, 0x32, 0xCB, 0x1C, - 0xCD, 0x05, 0x3A, 0x38, 0x9E, 0xBB, 0xE6, 0x5D, 0x5F, 0x93, 0xFE, 0x01, 0x01, 0xA3, 0x6B, 0x29, - 0x35, 0x10, 0x1B, 0x63, 0x1F, 0xA6, 0x2A, 0x66, 0xEC, 0x1B, 0x3A, 0x0E, 0xFC, 0x77, 0xE3, 0xD8, - 0x74, 0xA9, 0x81, 0x53, 0xE8, 0x89, 0xE5, 0x82, 0xD4, 0xFD, 0xC6, 0xF2, 0x8E, 0x52, 0xE9, 0x41, - 0xF9, 0x8B, 0x02, 0x1E, 0x05, 0x73, 0xE8, 0x4F, 0xCD, 0x88, 0x71, 0xE6, 0x2E, 0x89, 0x38, 0xF9, - 0x2D, 0x46, 0x8F, 0x3D, 0x02, 0xD8, 0x55, 0xBF, 0x2B, 0x45, 0x27, 0xE5, 0x96, 0x01, 0x57, 0x2A, - 0x91, 0xD8, 0x01, 0x0C, 0x9D, 0x70, 0xC4, 0x66, 0xED, 0xF3, 0x8B, 0xBF, 0xB1, 0x6E, 0xD1, 0x60, - 0xA1, 0xCF, 0x48, 0x1F, 0x9C, 0xC6, 0x49, 0x43, 0x45, 0x90, 0x9A, 0x37, 0xB1, 0xC1, 0x6A, 0x15, - 0xA3, 0x9F, 0x91, 0xEA, 0x0A, 0x9D, 0x57, 0xA8, 0x76, 0xF8, 0xF3, 0xDF, 0x72, 0x44, 0x77, 0x05, - 0x6E, 0xC6, 0xBE, 0xE7, 0x5E, 0x3B, 0x43, 0x5D, 0x72, 0x49, 0x9D, 0xC9, 0xA4, 0xA8, 0x06, 0x0D, - 0x6F, 0xA8, 0xEF, 0xD2, 0xB0, 0xA8, 0x9E, 0x1B, 0x16, 0xA2, 0x9A, 0x78, 0x7E, 0x18, 0x64, 0x57, - 0xE2, 0x9A, 0x04, 0x12, 0x00, 0x7A, 0xD6, 0xE8, 0x0C, 0x2A, 0x7F, 0x98, 0xB0, 0x09, 0x3B, 0x1B, - 0x23, 0x0C, 0x9C, 0x0B, 0xAF, 0x7F, 0xB0, 0x6F, 0xF9, 0x76, 0x36, 0xC6, 0xA1, 0x35, 0x02, 0x25, - 0xF2, 0xDE, 0x5B, 0xE0, 0x99, 0x86, 0x21, 0x18, 0x88, 0xEC, 0xAA, 0xA1, 0x33, 0x0A, 0x8B, 0x18, - 0xBC, 0xA2, 0x74, 0x42, 0x7D, 0xA8, 0x15, 0xFA, 0xDE, 0x28, 0x9B, 0xB5, 0x69, 0x40, 0xF7, 0x82, - 0x00, 0x7C, 0xCD, 0x53, 0xEF, 0x2E, 0xF2, 0xC2, 0xB2, 0x6B, 0x8F, 0xA9, 0x15, 0x4C, 0x7D, 0xB6, - 0xBE, 0x38, 0x8F, 0x4C, 0x66, 0x36, 0x0B, 0x63, 0x2F, 0xB0, 0x9C, 0xC1, 0xE9, 0xC9, 0xE1, 0x5E, - 0x3F, 0x84, 0x51, 0x3B, 0x3E, 0xF0, 0xBD, 0x09, 0x2C, 0xDB, 0xF2, 0x24, 0x05, 0xD8, 0x6F, 0xE9, - 0xFD, 0x91, 0x2B, 0x44, 0x10, 0xE4, 0x32, 0x7E, 0x0C, 0x0B, 0xC6, 0x91, 0xF3, 0x3B, 0xB5, 0x0F, - 0x80, 0x7F, 0xDF, 0xB9, 0x9A, 0x62, 0x37, 0x14, 0x37, 0x02, 0x20, 0x0F, 0x5D, 0xF4, 0xA3, 0x0F, - 0xBF, 0x85, 0xE8, 0xAC, 0x9D, 0x5B, 0xB6, 0xE3, 0xE5, 0x68, 0x96, 0x54, 0xAB, 0x7F, 0xB6, 0x77, - 0x7E, 0x71, 0xCA, 0x3D, 0xB3, 0xA8, 0x35, 0x25, 0x0D, 0x89, 0x69, 0x60, 0xBC, 0xB5, 0x06, 0x60, - 0xC7, 0x6F, 0x7B, 0x30, 0x3A, 0xFE, 0xF3, 0x3F, 0x49, 0x5E, 0x0D, 0x72, 0xFC, 0x06, 0x4C, 0x68, - 0xDA, 0x3C, 0xCE, 0x6F, 0x18, 0x09, 0xB5, 0x2E, 0x1C, 0x46, 0xBC, 0xDE, 0xEC, 0xC3, 0x28, 0x16, - 0xEE, 0x8F, 0x61, 0xF4, 0x63, 0x18, 0x95, 0x1F, 0x46, 0x99, 0x63, 0x84, 0x4B, 0xE9, 0xD7, 0xCD, - 0xC6, 0x8F, 0x21, 0xF2, 0xD4, 0x86, 0x08, 0xAF, 0x56, 0x76, 0x88, 0x08, 0xA5, 0x2F, 0x39, 0x44, - 0xC4, 0x80, 0xAA, 0x32, 0x44, 0x38, 0x81, 0x32, 0x43, 0x24, 0x66, 0x7C, 0xD1, 0x43, 0x24, 0xF6, - 0x29, 0x0A, 0x87, 0x48, 0x9A, 0x12, 0xDB, 0xB4, 0x02, 0x6F, 0x6C, 0x08, 0x18, 0xEC, 0x7B, 0xD7, - 0x1A, 0x3B, 0x83, 0x13, 0xCF, 0xA6, 0xC6, 0x9E, 0xC0, 0x65, 0x83, 0x4B, 0xEF, 0xB8, 0x1A, 0x89, - 0x1D, 0x4C, 0xFE, 0xC7, 0x52, 0xB3, 0x1F, 0x5A, 0xA1, 0x33, 0x68, 0xB6, 0x48, 0xB3, 0xD3, 0x34, - 0xB5, 0x88, 0xD1, 0xC1, 0x2D, 0xD7, 0xA5, 0x18, 0x43, 0x8B, 0x4C, 0x5D, 0x1B, 0xC6, 0xA1, 0x4B, - 0x6D, 0x03, 0x44, 0x16, 0xA1, 0xFF, 0x37, 0xB5, 0x50, 0x0D, 0x22, 0x6A, 0xDD, 0xC5, 0x52, 0x3B, - 0xA3, 0xB0, 0xC4, 0x80, 0x3E, 0xB3, 0x5C, 0x24, 0xD6, 0x5B, 0x2C, 0xB1, 0xBD, 0x69, 0xE8, 0x8D, - 0xBD, 0xD0, 0xB9, 0xA5, 0x48, 0x6C, 0x7D, 0xB1, 0xC4, 0xCE, 0xC1, 0xEE, 0x11, 0x18, 0xE9, 0x48, - 0x6A, 0x63, 0xB1, 0xA4, 0xDE, 0x53, 0xEB, 0xF6, 0x9E, 0x9C, 0x58, 0x83, 0x1B, 0x00, 0xF4, 0xEF, - 0x91, 0xE2, 0xE6, 0x62, 0x29, 0x7E, 0xDC, 0xFB, 0x19, 0xA9, 0x6C, 0x2D, 0x98, 0x8A, 0x3B, 0x72, - 0xC6, 0x0E, 0x2C, 0x3C, 0x91, 0xD6, 0xF3, 0x7A, 0xB4, 0x52, 0x20, 0x43, 0x66, 0xBE, 0xF8, 0x46, - 0x2E, 0x33, 0x5D, 0xD7, 0x1E, 0x2E, 0x98, 0x1A, 0xCB, 0xED, 0x80, 0x86, 0x7B, 0x21, 0xB7, 0x1F, - 0x74, 0xA9, 0x89, 0xAB, 0xED, 0xD5, 0xAB, 0x60, 0xD5, 0xF3, 0x9D, 0xA1, 0x03, 0x06, 0x7E, 0x95, - 0xAD, 0xDD, 0x90, 0x93, 0x8B, 0x1B, 0x4A, 0xDE, 0x9D, 0xF6, 0xFB, 0x64, 0x60, 0xC1, 0xD2, 0x77, - 0x1A, 0x82, 0xED, 0x23, 0x68, 0xDC, 0x08, 0xF8, 0x80, 0x04, 0x37, 0x87, 0x6F, 0xD7, 0x89, 0x15, - 0x12, 0xDB, 0xB9, 0xBE, 0xA6, 0x3E, 0x58, 0x48, 0xE2, 0x03, 0x9D, 0xA0, 0x4D, 0xDE, 0x7A, 0x3E, - 0xAB, 0xF7, 0x32, 0xB2, 0x0A, 0x16, 0x09, 0x98, 0x3D, 0x64, 0x9B, 0x06, 0x14, 0xBA, 0x2F, 0xDA, - 0x74, 0x68, 0x31, 0x54, 0xC0, 0x0F, 0xFC, 0x9F, 0x38, 0xB0, 0xF4, 0xF6, 0x71, 0xA1, 0x1B, 0xD7, - 0xE2, 0x50, 0x1C, 0x21, 0xA7, 0xF7, 0x32, 0xBB, 0x72, 0x74, 0xBC, 0x31, 0xF4, 0xBD, 0xE9, 0x84, - 0x23, 0xA6, 0xCC, 0xEA, 0x41, 0x5D, 0xDB, 0xB9, 0x75, 0xEC, 0x29, 0xD4, 0x16, 0x95, 0x82, 0xB6, - 0x49, 0xC8, 0x28, 0x31, 0x3F, 0x1C, 0x8C, 0x6B, 0x8A, 0x0B, 0x39, 0x24, 0x4E, 0x00, 0x4B, 0x56, - 0xCB, 0x0D, 0xA0, 0x3B, 0x71, 0x53, 0xFF, 0xEA, 0x9E, 0xC0, 0x3C, 0x4D, 0x70, 0xCA, 0x47, 0x51, - 0x59, 0xC4, 0x16, 0x3B, 0x9F, 0xDE, 0x35, 0xE9, 0xBE, 0xFF, 0x9D, 0x71, 0x1F, 0xF1, 0x44, 0xBA, - 0x9D, 0xCE, 0x66, 0x8B, 0x9C, 0xF4, 0x4F, 0x36, 0x38, 0xFB, 0x9D, 0x76, 0x54, 0xA5, 0xDB, 0x59, - 0x5F, 0x6F, 0x93, 0x8B, 0x1B, 0xC0, 0x8E, 0x7D, 0x71, 0x45, 0xC9, 0xC8, 0xBB, 0x03, 0x99, 0xDB, - 0xAC, 0xD4, 0x47, 0x4B, 0x1D, 0x90, 0x3B, 0x27, 0xBC, 0xC1, 0xEF, 0x40, 0xCD, 0xB5, 0xEF, 0x1C, - 0x1B, 0xFE, 0x82, 0xC2, 0xD0, 0x72, 0x46, 0x1E, 0xD6, 0x0C, 0xBD, 0x98, 0x33, 0xC0, 0x7E, 0xBF, - 0x66, 0x8D, 0x46, 0x4C, 0xA8, 0x89, 0x4C, 0xC8, 0x31, 0x6A, 0x61, 0xF0, 0x12, 0x09, 0x63, 0xF5, - 0xAD, 0x4E, 0x27, 0x53, 0x4E, 0x34, 0x35, 0xA1, 0xD4, 0x90, 0x18, 0x9F, 0x95, 0x48, 0xE4, 0x5A, - 0xF0, 0x86, 0xC8, 0x9B, 0xCF, 0x2F, 0x23, 0x35, 0x83, 0x21, 0xC3, 0x27, 0x57, 0xB2, 0xFF, 0xE1, - 0xA4, 0xD7, 0x26, 0x62, 0x03, 0xF9, 0x25, 0x79, 0x8B, 0x5B, 0x2D, 0xCD, 0xDA, 0x4E, 0xDB, 0x85, - 0xE7, 0x0F, 0x6E, 0xFE, 0x85, 0x7C, 0xB5, 0xDC, 0x5D, 0x81, 0x8C, 0xDA, 0x9A, 0xB3, 0x96, 0x51, - 0x8B, 0xED, 0xF7, 0xD3, 0xD1, 0x88, 0x9D, 0x8D, 0xF6, 0x41, 0x2E, 0x50, 0x97, 0xAC, 0xAD, 0x9D, - 0x7A, 0x21, 0x09, 0xA6, 0x13, 0x64, 0x0B, 0x74, 0x0C, 0xBA, 0xE9, 0xE3, 0xC9, 0xF6, 0x8B, 0x4E, - 0x19, 0x1C, 0xA7, 0xD6, 0xAD, 0x33, 0xC8, 0x45, 0x52, 0x6D, 0x91, 0x83, 0x1B, 0xB6, 0x1E, 0x8C, - 0x22, 0x1C, 0x6F, 0x67, 0x67, 0xC7, 0x04, 0xAA, 0x91, 0x93, 0x77, 0x7B, 0x7F, 0x25, 0x1C, 0xBB, - 0x4F, 0xDB, 0xED, 0x76, 0xC5, 0x85, 0x50, 0xA6, 0x77, 0xEB, 0x5B, 0x49, 0x17, 0x2C, 0xD0, 0x15, - 0x62, 0xBE, 0xE1, 0x23, 0xB8, 0x42, 0x62, 0x96, 0xEB, 0x3E, 0xA6, 0x57, 0xD2, 0x9B, 0xE3, 0x34, - 0xF7, 0xFD, 0x8D, 0x76, 0xB7, 0xF3, 0x7C, 0x03, 0x7F, 0xBE, 0x60, 0x3F, 0xB7, 0xF1, 0x67, 0xB7, - 0xF7, 0xDD, 0xCD, 0x38, 0x56, 0xEE, 0x75, 0xDA, 0x38, 0x02, 0xE8, 0x4B, 0x82, 0xD3, 0xB9, 0xA4, - 0xE9, 0x6C, 0xB6, 0xC6, 0xA6, 0x7B, 0xB7, 0xD4, 0xF7, 0x1D, 0xDB, 0xA6, 0x2E, 0xD6, 0x47, 0x5E, - 0xEF, 0x6E, 0x28, 0xCE, 0xB0, 0x84, 0x1D, 0xBD, 0x8E, 0x41, 0x75, 0xD9, 0x34, 0x50, 0xD3, 0xC4, - 0x9E, 0x79, 0x41, 0x38, 0x60, 0xB6, 0xE5, 0xC7, 0x8A, 0xB8, 0xC8, 0xC8, 0x2E, 0x7A, 0x49, 0xFC, - 0x63, 0xDB, 0x68, 0x81, 0xDB, 0x46, 0x33, 0x4E, 0x9C, 0xC7, 0xEF, 0x7A, 0xDB, 0x9D, 0xB3, 0x0C, - 0xFA, 0xC6, 0x99, 0x33, 0x8B, 0xA2, 0x3C, 0xE7, 0x48, 0x0C, 0x56, 0x20, 0x2A, 0xBA, 0xCE, 0x71, - 0x0F, 0x47, 0xF4, 0x36, 0xD6, 0xB2, 0x3A, 0x08, 0xF6, 0x4F, 0x3F, 0x94, 0x81, 0xFF, 0x03, 0x99, - 0xF5, 0x6E, 0x6C, 0xDC, 0xBB, 0xDD, 0xF5, 0x8D, 0x3F, 0xAE, 0x39, 0xAF, 0x70, 0x38, 0x28, 0x9D, - 0x91, 0x0E, 0xDD, 0x20, 0x88, 0xA2, 0x4E, 0x7E, 0xA6, 0x7E, 0x00, 0xEA, 0x78, 0xE4, 0x86, 0xA6, - 0x03, 0x53, 0x50, 0x3F, 0xE7, 0xFA, 0x1E, 0xD7, 0x6B, 0x6C, 0x10, 0x13, 0x7B, 0x4A, 0x91, 0xA1, - 0x6B, 0x01, 0x4C, 0xD8, 0x92, 0x97, 0xE9, 0x73, 0x90, 0x3A, 0xBD, 0xCB, 0x3E, 0xBE, 0x2B, 0x38, - 0xA0, 0x98, 0xF1, 0x08, 0x63, 0x5E, 0x9E, 0x1B, 0x4E, 0x09, 0x68, 0x5C, 0x1E, 0xC1, 0x77, 0xEB, - 0x73, 0x19, 0x5A, 0x7C, 0x3B, 0xA4, 0xF7, 0x98, 0xBB, 0x58, 0xEB, 0x8F, 0xE9, 0x2F, 0x2E, 0x78, - 0x6B, 0xA9, 0x4F, 0xAD, 0x47, 0xD8, 0x4E, 0xDA, 0x73, 0xFC, 0x2B, 0x0F, 0x7C, 0x14, 0xD2, 0x1D, - 0x3E, 0xC2, 0xB6, 0x52, 0x4C, 0xAD, 0x37, 0x9C, 0x61, 0x63, 0xA9, 0x32, 0xB5, 0x0D, 0x46, 0xED, - 0xC5, 0x62, 0xA9, 0xFD, 0xE2, 0xC3, 0x74, 0x8F, 0x74, 0xB6, 0x17, 0x4B, 0xE7, 0x8D, 0xF3, 0x95, - 0xA9, 0x5F, 0x77, 0x4E, 0xC3, 0x38, 0x0A, 0xE6, 0x78, 0xBD, 0x4B, 0xBA, 0xBD, 0xAE, 0xC9, 0x08, - 0x55, 0x36, 0x44, 0x45, 0xC6, 0xE8, 0x04, 0x27, 0x25, 0xD6, 0x06, 0xE3, 0x02, 0xAF, 0x5E, 0x3B, - 0xF2, 0x64, 0x76, 0xB8, 0xDA, 0x1F, 0x78, 0x30, 0x47, 0x71, 0xA2, 0xBD, 0xF9, 0x11, 0x7D, 0x28, - 0x9C, 0xB4, 0xD6, 0xD6, 0xC0, 0xCB, 0x64, 0xD3, 0xCD, 0x10, 0x23, 0xB1, 0x2D, 0x31, 0xEF, 0x63, - 0x14, 0xCA, 0xD4, 0x75, 0xC2, 0x82, 0xC9, 0x2D, 0xB0, 0xDF, 0xFA, 0x94, 0xF6, 0x27, 0x30, 0x55, - 0x34, 0x96, 0x15, 0x5A, 0x30, 0xA9, 0x68, 0x35, 0xFB, 0xE0, 0x73, 0x16, 0x54, 0xBA, 0x01, 0x67, - 0x1F, 0xA7, 0xBA, 0xA3, 0x83, 0x82, 0x8A, 0x86, 0x49, 0xB5, 0x00, 0xC2, 0xB6, 0xEE, 0x83, 0x73, - 0x3A, 0xB6, 0x1C, 0x97, 0x2D, 0x12, 0x72, 0xEB, 0x4E, 0x7C, 0x0F, 0xE3, 0x82, 0x3A, 0x18, 0xE4, - 0x59, 0xAE, 0x6A, 0xB7, 0x7C, 0xD5, 0x5E, 0xF9, 0xAA, 0xEB, 0xE5, 0xAB, 0x6E, 0x94, 0xAF, 0xBA, - 0x59, 0xBE, 0xEA, 0x56, 0xF9, 0xAA, 0xCF, 0x4B, 0x54, 0x65, 0x0E, 0xDE, 0xC9, 0xDE, 0x7E, 0x51, - 0x57, 0x51, 0xF0, 0xD6, 0xE9, 0x9B, 0x8B, 0x42, 0x2D, 0x80, 0x25, 0x62, 0x14, 0x40, 0x5E, 0x50, - 0xF3, 0xCA, 0x02, 0x87, 0xD6, 0xBF, 0x3F, 0xA3, 0xB0, 0x02, 0x41, 0xE7, 0x2B, 0xAE, 0xAC, 0xDB, - 0x13, 0x30, 0x1F, 0x8E, 0xBD, 0x0C, 0x90, 0x30, 0x16, 0xDE, 0x5F, 0x9C, 0x1C, 0xEB, 0x31, 0x5B, - 0x45, 0xDE, 0x9E, 0x1F, 0x7E, 0x4D, 0xE9, 0xA5, 0x81, 0x86, 0xB1, 0x5E, 0x36, 0xD5, 0x6C, 0xA8, - 0x8F, 0x93, 0x21, 0x48, 0x95, 0x36, 0x66, 0x60, 0x79, 0x80, 0xAB, 0x0D, 0x7F, 0x7C, 0x8E, 0x31, - 0xD6, 0x69, 0x66, 0x59, 0xE8, 0xF5, 0xBE, 0x37, 0x9E, 0x80, 0xC1, 0xA4, 0x4B, 0xCB, 0x95, 0xD1, - 0x62, 0x90, 0xF6, 0x39, 0x1D, 0x50, 0x67, 0x62, 0x40, 0x9E, 0xAE, 0xA3, 0x52, 0x28, 0x20, 0x21, - 0x54, 0x8F, 0xDF, 0x16, 0x30, 0x60, 0x9F, 0xFA, 0x78, 0xC8, 0x72, 0x26, 0xD7, 0x32, 0x49, 0xF6, - 0xCF, 0x4B, 0x0D, 0x07, 0x97, 0xE4, 0x9F, 0xF1, 0xEE, 0xCA, 0xAE, 0x40, 0xCA, 0x16, 0xAE, 0x5F, - 0x3E, 0xDF, 0x62, 0x60, 0xFB, 0x2E, 0xC6, 0xE3, 0x19, 0xB1, 0xAD, 0x90, 0xC6, 0x17, 0x90, 0x3D, - 0xC0, 0x4C, 0x96, 0x9A, 0x2C, 0xFC, 0x9C, 0x1D, 0x49, 0x61, 0x0C, 0x5E, 0x05, 0x51, 0x45, 0x1E, - 0xFE, 0xC7, 0x09, 0x5E, 0x83, 0x89, 0x84, 0x9D, 0x6E, 0x90, 0xB9, 0xDE, 0x52, 0x6D, 0x4A, 0xE8, - 0x09, 0x4F, 0x83, 0x22, 0x3A, 0xBC, 0xD6, 0x12, 0x0F, 0x13, 0x2D, 0xBD, 0xEA, 0x49, 0xEE, 0x9D, - 0x98, 0x06, 0x80, 0x7C, 0x29, 0xC5, 0xA4, 0xE9, 0x33, 0x8D, 0x41, 0xE9, 0x6A, 0x4B, 0x0E, 0x6D, - 0x36, 0x09, 0x2F, 0x8C, 0xF6, 0xDE, 0x28, 0xA7, 0xDD, 0xFC, 0x62, 0xCD, 0xDC, 0x69, 0xB3, 0xDB, - 0x39, 0x69, 0xAA, 0xD1, 0xA5, 0x9D, 0x85, 0xD0, 0xFB, 0x64, 0xA6, 0xF7, 0x69, 0x51, 0xF4, 0x7E, - 0x33, 0xD3, 0xFB, 0x6D, 0x21, 0xF4, 0x82, 0x89, 0xEB, 0xDD, 0x9D, 0x51, 0xDC, 0x10, 0x9C, 0x9A, - 0x96, 0xEC, 0xB1, 0x6B, 0x4A, 0x3A, 0xCB, 0xC6, 0xFD, 0x98, 0x09, 0xC0, 0xC2, 0x7C, 0x17, 0x68, - 0xE6, 0xB9, 0xD1, 0xA8, 0xC3, 0xC4, 0x65, 0x26, 0x03, 0x9F, 0x3B, 0x5F, 0xC8, 0x9F, 0x00, 0x6D, - 0xA7, 0x41, 0x7E, 0xFA, 0x09, 0xDB, 0xF8, 0xB9, 0x1B, 0x7D, 0x30, 0xF9, 0xCB, 0x99, 0x9C, 0xAD, - 0x30, 0x01, 0xA1, 0x51, 0x7B, 0x75, 0xE5, 0xBF, 0x6E, 0xD4, 0xDD, 0xF1, 0x08, 0xF8, 0x02, 0x1B, - 0xAF, 0xFE, 0x98, 0xE6, 0x93, 0xF8, 0x5E, 0x50, 0x7B, 0x32, 0x0D, 0x6E, 0x2A, 0xDA, 0x15, 0x81, - 0x3B, 0xBA, 0x40, 0x94, 0x89, 0x3F, 0xAA, 0x50, 0x87, 0xC6, 0xF5, 0x98, 0x7B, 0x14, 0x3A, 0x6A, - 0xED, 0xC2, 0x5A, 0x25, 0x5D, 0xBA, 0x1E, 0x73, 0xF7, 0x37, 0x6D, 0x6A, 0xE5, 0xBB, 0x61, 0xD0, - 0x01, 0x8D, 0x57, 0xA1, 0x4F, 0xAC, 0x91, 0x33, 0x74, 0x77, 0x9B, 0x23, 0x7A, 0x1D, 0x36, 0xF5, - 0x7E, 0x30, 0x41, 0xD8, 0xAF, 0x71, 0x86, 0x52, 0xF8, 0xC3, 0x4E, 0x5C, 0xC3, 0x82, 0xB2, 0xD0, - 0x51, 0xCF, 0x97, 0x06, 0x7A, 0xC5, 0x26, 0x4D, 0x12, 0xDE, 0x4F, 0xE8, 0x2E, 0x9F, 0xFB, 0xAE, - 0xBC, 0x6F, 0x4D, 0xF0, 0xBB, 0x76, 0x9B, 0x26, 0x6E, 0x9A, 0x84, 0x4D, 0xAF, 0x4D, 0x44, 0x76, - 0x74, 0xD0, 0x24, 0x03, 0xA8, 0x10, 0xC0, 0x9F, 0x9E, 0x3F, 0x5E, 0x65, 0xD0, 0xAB, 0x1C, 0x9F, - 0x14, 0x91, 0xCF, 0x36, 0xA5, 0x9B, 0xAF, 0x4B, 0xB2, 0xB4, 0x16, 0x2A, 0x3A, 0x5B, 0xA2, 0x97, - 0xD9, 0x0E, 0xA9, 0xDE, 0x23, 0x78, 0xB3, 0x0C, 0xF9, 0xAE, 0x32, 0xAD, 0x4E, 0xAF, 0xBE, 0x9D, - 0x24, 0x81, 0x23, 0x0C, 0x27, 0x2C, 0xAC, 0x88, 0xFA, 0xF9, 0x12, 0xB7, 0xF4, 0x2F, 0x0F, 0x2E, - 0x4E, 0xB4, 0xEF, 0xB8, 0xC9, 0x78, 0x89, 0x3B, 0x98, 0x97, 0xB8, 0x85, 0xAA, 0xF0, 0x22, 0x5D, - 0x06, 0x14, 0x4A, 0xE7, 0xD8, 0x3B, 0x59, 0x35, 0xCE, 0x79, 0xFC, 0x7F, 0xCA, 0x0C, 0x6A, 0x48, - 0x8E, 0xAD, 0x2B, 0x3A, 0x32, 0x5D, 0x02, 0x90, 0xEA, 0x1D, 0x88, 0x5B, 0x2C, 0x09, 0x54, 0x74, - 0x9B, 0xE5, 0x52, 0x5F, 0x9B, 0xA2, 0x2C, 0x24, 0xA8, 0xE8, 0x32, 0x0B, 0xAC, 0xD6, 0xD7, 0x4D, - 0xB6, 0x47, 0xBE, 0xDE, 0xC8, 0xAF, 0xEC, 0x48, 0xC0, 0x60, 0xB6, 0x76, 0xF2, 0xE4, 0xB6, 0xCB, - 0x82, 0x64, 0x8C, 0x3B, 0x04, 0xFA, 0xE5, 0xC8, 0x3F, 0xED, 0xCA, 0x64, 0xB2, 0x76, 0x0D, 0xD2, - 0x57, 0x2A, 0x25, 0x20, 0xF3, 0x1A, 0x5C, 0xBE, 0x9B, 0xC9, 0xD4, 0xEE, 0x26, 0x65, 0x29, 0x35, - 0xDF, 0x55, 0x83, 0x94, 0xFB, 0x40, 0x6D, 0x3B, 0x8E, 0x92, 0x4B, 0x76, 0xA7, 0x48, 0xFA, 0xDC, - 0x33, 0x89, 0x44, 0x55, 0x19, 0x40, 0x64, 0x56, 0x9F, 0x9C, 0xFE, 0xD9, 0xDD, 0x25, 0x1B, 0x59, - 0x52, 0xA9, 0xCB, 0xA8, 0xF1, 0xF3, 0xBA, 0xB1, 0x4B, 0x19, 0xBF, 0x1B, 0x9D, 0xE7, 0xBD, 0xCB, - 0x4E, 0xC4, 0x3D, 0xFF, 0xAB, 0x70, 0x07, 0xE3, 0x59, 0x6E, 0x67, 0xD8, 0xCE, 0xAD, 0x62, 0x58, - 0x58, 0x68, 0x13, 0xF1, 0xBD, 0x3B, 0x6E, 0x97, 0xC6, 0xC1, 0x50, 0xE2, 0x2F, 0xB6, 0x4C, 0x7A, - 0x07, 0xA6, 0xD0, 0x8E, 0x98, 0x18, 0x00, 0x23, 0x37, 0x6D, 0x3A, 0x7C, 0x44, 0x72, 0xE0, 0x8D, - 0x56, 0x83, 0xF1, 0xEA, 0x06, 0xC1, 0x5F, 0xB6, 0xD8, 0x4F, 0xC6, 0x05, 0x03, 0x6F, 0xBE, 0xD6, - 0x40, 0xB9, 0x6C, 0x01, 0xFE, 0xE5, 0xAB, 0x35, 0x56, 0xA3, 0x90, 0x0D, 0xA9, 0x75, 0x0A, 0xA9, - 0x8D, 0xA6, 0x6A, 0x8C, 0xF9, 0x75, 0x69, 0xCD, 0xC4, 0xF2, 0x33, 0xCD, 0x66, 0x01, 0x8D, 0xD8, - 0x7C, 0xA7, 0xDA, 0xC8, 0x57, 0x42, 0x72, 0x19, 0x33, 0x38, 0xA5, 0xE4, 0x37, 0xC9, 0x42, 0x7B, - 0xE8, 0xFB, 0x5E, 0xC2, 0xA8, 0xE3, 0x8E, 0x1C, 0x97, 0xF2, 0x6F, 0x60, 0xF5, 0x27, 0x85, 0x78, - 0xD7, 0x40, 0x22, 0xAF, 0xF9, 0xCF, 0x0A, 0x96, 0x7F, 0x2C, 0x9B, 0xEA, 0xD4, 0x56, 0x81, 0x28, - 0x3D, 0x12, 0xE1, 0x72, 0xA8, 0x9B, 0xA6, 0xC3, 0x1A, 0x59, 0x08, 0xCC, 0x40, 0xBD, 0x3B, 0x03, - 0x13, 0x95, 0x53, 0x09, 0x11, 0x9D, 0xE3, 0x51, 0x13, 0x53, 0x7E, 0x18, 0xAB, 0xDD, 0x9C, 0xCA, - 0x01, 0xD6, 0x89, 0x47, 0x79, 0x4E, 0x65, 0x99, 0x4D, 0x09, 0x7B, 0x6F, 0xBD, 0x53, 0x02, 0x20, - 0x21, 0xA0, 0xD7, 0xAF, 0x33, 0xF1, 0xB0, 0x7B, 0x94, 0x6F, 0x61, 0xC5, 0x18, 0x6A, 0xFE, 0x56, - 0xC1, 0x24, 0xA4, 0x57, 0xFB, 0xC7, 0x14, 0xDC, 0x9F, 0x6B, 0x87, 0xAD, 0xD5, 0xF5, 0xF2, 0xAC, - 0xBE, 0xCC, 0xEF, 0x2D, 0xFC, 0xA7, 0x60, 0x8D, 0x83, 0x21, 0x1B, 0x79, 0xD6, 0xA5, 0xDE, 0x84, - 0x58, 0x68, 0x3D, 0x77, 0xFE, 0x05, 0x6D, 0x58, 0x22, 0xDD, 0x1F, 0xF6, 0xEC, 0x7B, 0xD9, 0x33, - 0x1E, 0x2D, 0x82, 0xB6, 0x28, 0xCF, 0x5E, 0x25, 0xB5, 0x2E, 0xDF, 0xBD, 0xDB, 0xAB, 0x3F, 0xE8, - 0x17, 0xE0, 0x4A, 0xCE, 0x65, 0xE4, 0xFC, 0x0B, 0x4C, 0xF3, 0xE2, 0x2C, 0x8B, 0x2F, 0x97, 0x8C, - 0x8C, 0x64, 0x2A, 0xB5, 0x3C, 0x42, 0x6C, 0x11, 0xC8, 0x42, 0xC6, 0x57, 0xAB, 0xBD, 0xE2, 0xC6, - 0x7B, 0xFC, 0x60, 0x4A, 0x0C, 0x8B, 0x4E, 0xF3, 0xF5, 0x87, 0xEB, 0xEB, 0x57, 0x6B, 0xFC, 0x6B, - 0x45, 0xE0, 0x6E, 0xF3, 0x35, 0x57, 0xB3, 0x6E, 0x4D, 0x04, 0xBD, 0x08, 0x41, 0xAF, 0x34, 0x82, - 0x35, 0x2E, 0xB5, 0x72, 0x43, 0x4C, 0xD7, 0x57, 0x18, 0x1E, 0x7D, 0xEB, 0x96, 0xB2, 0x68, 0x17, - 0x14, 0x3B, 0x8B, 0x42, 0x64, 0xBC, 0x10, 0x2B, 0x20, 0x77, 0x14, 0xA3, 0x55, 0x9A, 0x21, 0x8B, - 0xA4, 0xC7, 0x2A, 0xBC, 0xE4, 0x9E, 0x86, 0x6D, 0x05, 0xFF, 0x0D, 0xD4, 0x75, 0xBD, 0x10, 0x0B, - 0xC8, 0x15, 0xA5, 0x2E, 0xB1, 0x6C, 0x9B, 0x07, 0xAC, 0xC4, 0x5B, 0x2C, 0xEA, 0x4A, 0x53, 0xCF, - 0xCB, 0xC2, 0x37, 0x2B, 0xA4, 0x4E, 0xD5, 0x06, 0x48, 0x3A, 0x59, 0x4B, 0x9D, 0xED, 0x0D, 0x81, - 0x9F, 0x07, 0x73, 0xD9, 0x45, 0xFE, 0x8D, 0x54, 0xAD, 0x94, 0x7F, 0x21, 0xD5, 0x9F, 0x93, 0x7B, - 0xF1, 0x54, 0x2D, 0x4D, 0x6A, 0x03, 0x83, 0x8C, 0xC3, 0xD5, 0xF5, 0xB2, 0x56, 0x26, 0xBD, 0xFD, - 0xC1, 0xCD, 0x47, 0xB6, 0xF9, 0x79, 0x2D, 0x82, 0xFF, 0xB3, 0xEC, 0x4B, 0x59, 0xF3, 0xC2, 0x67, - 0xD6, 0x8C, 0xED, 0x97, 0x66, 0xE6, 0x7E, 0x4E, 0x65, 0x6B, 0x3A, 0xEB, 0x48, 0x8B, 0xCF, 0x53, - 0xE6, 0x34, 0xD2, 0x94, 0x44, 0x46, 0xA5, 0x86, 0x9A, 0x9A, 0xDD, 0xA8, 0xCE, 0x58, 0x93, 0x6E, - 0x66, 0x88, 0x84, 0x40, 0xF7, 0xE9, 0xC1, 0xA6, 0xE6, 0x0F, 0xCA, 0x19, 0x10, 0x49, 0xA5, 0x08, - 0x59, 0xE4, 0x76, 0x83, 0xFF, 0x9B, 0xE1, 0x74, 0x27, 0x30, 0x62, 0x7C, 0xA8, 0x94, 0x32, 0x87, - 0x48, 0x9A, 0xA9, 0x68, 0xA4, 0xA8, 0x18, 0xD3, 0x83, 0x05, 0x85, 0x60, 0xCE, 0x97, 0x14, 0x6D, - 0x3E, 0xBC, 0x32, 0xA7, 0x5B, 0x32, 0xB9, 0xED, 0x19, 0x88, 0x58, 0x57, 0x18, 0xD8, 0x33, 0x84, - 0x40, 0xE4, 0x64, 0x66, 0xD2, 0xD1, 0x44, 0x52, 0x2D, 0xBC, 0x1C, 0x63, 0x20, 0x22, 0x65, 0x5A, - 0xB9, 0xF0, 0x3C, 0x32, 0xB6, 0xDC, 0x7B, 0x99, 0x34, 0x09, 0x78, 0x1B, 0x1B, 0x55, 0x94, 0x07, - 0xD5, 0xCF, 0x71, 0x87, 0x52, 0xDA, 0x2A, 0xC3, 0x21, 0x67, 0xBA, 0x52, 0x95, 0x9D, 0x4B, 0x37, - 0x01, 0xCB, 0x3C, 0xAF, 0x4E, 0xD7, 0xA9, 0x7C, 0x18, 0xC8, 0x22, 0x1A, 0x73, 0xDB, 0x91, 0xAE, - 0x53, 0xA5, 0x19, 0x5E, 0x68, 0x45, 0x60, 0x59, 0x87, 0x9A, 0xA9, 0x2A, 0x15, 0x1B, 0x21, 0x42, - 0x08, 0x8E, 0xA0, 0xAB, 0x93, 0xA0, 0x03, 0xD3, 0xD1, 0xBE, 0xB1, 0x62, 0x3B, 0xF0, 0x07, 0xD5, - 0x0F, 0xE6, 0x53, 0x29, 0x8E, 0x4C, 0x47, 0xE8, 0xA6, 0x3C, 0x48, 0xD5, 0xCE, 0x26, 0x44, 0x86, - 0x41, 0xD3, 0xE9, 0x44, 0x9C, 0x7B, 0xB0, 0x06, 0x46, 0x0F, 0x03, 0x6D, 0xCC, 0x28, 0x79, 0xF2, - 0xC2, 0x6A, 0x91, 0x15, 0xF4, 0xCA, 0xF3, 0xC2, 0x13, 0xC7, 0x9D, 0x86, 0x34, 0xC8, 0x3F, 0x8B, - 0xCB, 0x38, 0xF3, 0xD2, 0x30, 0xB4, 0xF9, 0xB4, 0x63, 0xD8, 0x31, 0x57, 0xAF, 0xEC, 0x61, 0x54, - 0xA5, 0x08, 0x8E, 0x68, 0x8B, 0x29, 0xC9, 0x98, 0x66, 0x47, 0x8A, 0x7D, 0x8F, 0xE1, 0xC6, 0x78, - 0x59, 0x9A, 0x01, 0x1F, 0x50, 0x8C, 0x60, 0x0E, 0x4A, 0x64, 0x4B, 0xA8, 0xC6, 0x7C, 0xA7, 0x3A, - 0xEB, 0x22, 0xB3, 0x5E, 0xC6, 0x9D, 0x90, 0x3A, 0xBC, 0x3F, 0xC8, 0xE9, 0xA3, 0xF6, 0x79, 0xE2, - 0x2E, 0x98, 0x8A, 0xA3, 0x7C, 0x59, 0x63, 0x9C, 0x99, 0x31, 0x4B, 0x28, 0x5E, 0x27, 0x85, 0xB1, - 0x11, 0x14, 0x74, 0xB5, 0xE5, 0x86, 0xD4, 0x75, 0xAD, 0xF7, 0xD4, 0x19, 0xDE, 0x84, 0x97, 0xE3, - 0xB1, 0x79, 0x9C, 0x69, 0xB5, 0xD4, 0x0E, 0x25, 0x6B, 0x18, 0x90, 0xCE, 0xB2, 0x85, 0x99, 0x45, - 0x2D, 0x33, 0xCC, 0x9C, 0x37, 0x98, 0xE7, 0x69, 0x00, 0x60, 0xFC, 0x4A, 0xE5, 0xD5, 0x34, 0x0C, - 0xE5, 0x38, 0xEB, 0x72, 0x79, 0xA5, 0x42, 0xFF, 0xDE, 0xDC, 0x7D, 0x78, 0x0E, 0x9D, 0xA7, 0x3B, - 0x0F, 0xE0, 0xF7, 0x84, 0x83, 0x1B, 0xB2, 0x44, 0x71, 0xB3, 0xC0, 0x3C, 0x11, 0x4A, 0x33, 0x4C, - 0x1F, 0xFC, 0x9E, 0x0B, 0x40, 0x42, 0x9C, 0x20, 0x80, 0x9F, 0x2C, 0x62, 0xFE, 0xE8, 0x20, 0xCA, - 0xEF, 0x55, 0x25, 0x54, 0x3D, 0x3F, 0x01, 0x57, 0xC9, 0xF6, 0x18, 0x14, 0xAA, 0x46, 0x83, 0xD8, - 0xC5, 0xD4, 0xCA, 0x2D, 0x92, 0xFA, 0x71, 0x6F, 0x34, 0x22, 0x3E, 0x1D, 0x4E, 0x47, 0x98, 0x31, - 0x8D, 0x39, 0xB9, 0xBC, 0x4F, 0x63, 0x17, 0x53, 0xEB, 0xCE, 0x0A, 0x6D, 0xCD, 0x34, 0x15, 0x15, - 0xDB, 0x79, 0x54, 0xA3, 0xBF, 0x1E, 0x4C, 0xC9, 0xE8, 0xA2, 0x9B, 0x3E, 0x04, 0x23, 0x74, 0x68, - 0x72, 0x43, 0x8A, 0x9D, 0xED, 0xF3, 0x10, 0xA5, 0xFD, 0x1B, 0xCB, 0x1D, 0x52, 0xB1, 0x5C, 0xD4, - 0x22, 0x10, 0x9A, 0xCD, 0x9D, 0x67, 0x89, 0x65, 0x81, 0x21, 0x2E, 0xC2, 0x9A, 0x4E, 0x82, 0xA1, - 0xA1, 0xA6, 0x60, 0xE0, 0xC0, 0x43, 0xD7, 0x7C, 0xCA, 0x13, 0x8D, 0x81, 0xF2, 0xE0, 0xCD, 0x0B, - 0xF0, 0xD8, 0x7D, 0x8C, 0xDC, 0x02, 0x6F, 0x99, 0xDC, 0x81, 0x57, 0x9E, 0x4C, 0x47, 0xD0, 0x05, - 0xD7, 0xDE, 0xB3, 0xC8, 0x34, 0xEB, 0x69, 0xCA, 0xF8, 0x20, 0x90, 0xE5, 0x95, 0x99, 0x00, 0x34, - 0xE9, 0xE0, 0xB7, 0x1E, 0xB8, 0x50, 0xD0, 0x77, 0xFC, 0xFA, 0x06, 0x67, 0x24, 0xE9, 0xD3, 0x61, - 0x3A, 0xFB, 0xC8, 0xFB, 0xDF, 0xA1, 0x35, 0xB6, 0x13, 0x4C, 0xB0, 0x8F, 0x58, 0xC6, 0x61, 0x0C, - 0x9C, 0x25, 0xFB, 0xD3, 0x00, 0xCC, 0x1B, 0xFF, 0x1B, 0x56, 0x19, 0x28, 0xA6, 0xE6, 0xB2, 0xD4, - 0x0B, 0x06, 0x4C, 0x7D, 0x3A, 0xA8, 0x8D, 0x0A, 0xEF, 0xCF, 0xE0, 0xBC, 0xDC, 0x17, 0xB7, 0xB4, - 0x66, 0x46, 0xF4, 0x16, 0xE7, 0xD0, 0xDA, 0x58, 0xD8, 0x0C, 0xFC, 0x86, 0x5D, 0x20, 0x94, 0x93, - 0x25, 0xF2, 0x70, 0x8D, 0xF9, 0xE2, 0x7C, 0x47, 0xBD, 0xDA, 0x28, 0xF9, 0x44, 0x74, 0x1A, 0xFA, - 0xCE, 0xA4, 0x4F, 0x41, 0x70, 0xFE, 0x3C, 0x30, 0xED, 0x8F, 0x1C, 0x16, 0xFF, 0x59, 0x13, 0x13, - 0x5E, 0x9F, 0xC2, 0x9B, 0x2A, 0x38, 0xB4, 0x5C, 0x8C, 0x2D, 0x9F, 0x89, 0xA3, 0x33, 0xCF, 0x71, - 0xC3, 0x33, 0xEA, 0x5F, 0xC3, 0x1A, 0x41, 0x5A, 0x0D, 0xCD, 0x88, 0xF5, 0x30, 0xBA, 0x64, 0x39, - 0x65, 0x16, 0x7D, 0x2E, 0xB8, 0xDE, 0x8B, 0xB8, 0x6C, 0x9E, 0xB4, 0xDB, 0x1B, 0x0E, 0x59, 0x0C, - 0xF5, 0x6C, 0xA8, 0x83, 0xC9, 0xA9, 0x77, 0x37, 0x23, 0x92, 0x63, 0xCF, 0xB7, 0x6A, 0xA3, 0x10, - 0xFE, 0xC3, 0xD9, 0x0D, 0xAA, 0x2D, 0xC5, 0x03, 0x21, 0xE6, 0x6A, 0xCC, 0xC8, 0xD0, 0x3C, 0x64, - 0x23, 0xB0, 0x9C, 0x1F, 0x9D, 0x1E, 0xFE, 0x3A, 0x23, 0xAA, 0xBD, 0xF3, 0xB3, 0xF9, 0xF0, 0x84, - 0x1E, 0xE1, 0xDB, 0x38, 0x2E, 0xD4, 0x66, 0x67, 0xA7, 0x33, 0x23, 0x8C, 0x7C, 0xD3, 0x7A, 0x78, - 0xB2, 0xEE, 0xB2, 0x56, 0x42, 0x18, 0x63, 0xE4, 0xD3, 0x09, 0x5A, 0x41, 0xCC, 0xE0, 0x2D, 0x2F, - 0x3E, 0x79, 0x49, 0x14, 0x51, 0xA6, 0x97, 0x86, 0x03, 0x61, 0x55, 0xDE, 0xA0, 0xB3, 0xA1, 0x95, - 0x70, 0xCB, 0x95, 0x2A, 0x99, 0xDA, 0x93, 0xD4, 0x37, 0xFB, 0x66, 0x30, 0x39, 0x14, 0x17, 0xB2, - 0xD3, 0xD4, 0x61, 0x11, 0x86, 0x8B, 0xA6, 0x74, 0xC1, 0x7E, 0x6A, 0x87, 0xC9, 0x49, 0xF0, 0x3E, - 0x28, 0xF9, 0xE7, 0x99, 0x83, 0x0F, 0xEE, 0x86, 0x98, 0x74, 0x85, 0x6B, 0x13, 0x84, 0xF7, 0xE0, - 0x54, 0xA0, 0xC0, 0x46, 0x2C, 0xB9, 0x7F, 0xC3, 0xF5, 0x5C, 0xDA, 0x50, 0x33, 0xD7, 0xB3, 0x65, - 0x4D, 0x31, 0xE4, 0x15, 0xF8, 0xF8, 0x5F, 0x39, 0x28, 0x78, 0xD5, 0x3E, 0xC5, 0x79, 0x7C, 0xBF, - 0xFF, 0x33, 0x5E, 0x17, 0x45, 0x5F, 0x41, 0x5C, 0x6C, 0x64, 0xD9, 0x6A, 0x25, 0xDC, 0x22, 0x93, - 0x77, 0x9C, 0xA9, 0x9F, 0xA7, 0xF7, 0x66, 0x55, 0x11, 0x58, 0xDA, 0xF4, 0x5D, 0x5B, 0x3B, 0x4A, - 0xDC, 0xBA, 0xB8, 0xEE, 0x60, 0x14, 0x88, 0xD4, 0xF9, 0x98, 0x4D, 0x3B, 0x4E, 0xA8, 0xFA, 0x8F, - 0x29, 0x2C, 0xC2, 0x79, 0xAE, 0x78, 0xCF, 0x07, 0xD7, 0x70, 0xA9, 0xD1, 0x96, 0x0F, 0x0E, 0x5B, - 0xA4, 0xAD, 0x9C, 0x92, 0x34, 0x72, 0xB2, 0xF4, 0x4A, 0x14, 0xC4, 0x16, 0x16, 0x7C, 0x5F, 0x59, - 0x91, 0xBD, 0x17, 0x89, 0xE1, 0x95, 0x5D, 0x19, 0xE0, 0xF3, 0xB7, 0x2F, 0x6D, 0x91, 0x72, 0x97, - 0x45, 0x91, 0xAB, 0x25, 0xDC, 0xAF, 0x64, 0x85, 0x51, 0x8F, 0x3D, 0x4B, 0x2D, 0x4A, 0x5A, 0x86, - 0x35, 0xC9, 0xDA, 0xDA, 0x39, 0x1D, 0x7B, 0xB7, 0x94, 0x05, 0xC2, 0xE1, 0x6E, 0x13, 0xC6, 0xCB, - 0xB1, 0x3F, 0x78, 0x79, 0x55, 0xA1, 0x24, 0x3B, 0xC0, 0x2F, 0x5D, 0x2F, 0x5C, 0x6A, 0xEB, 0x51, - 0x78, 0xCB, 0x91, 0xBC, 0x7C, 0xF9, 0xDA, 0xF7, 0xE3, 0x0A, 0x2B, 0x5A, 0x70, 0xA4, 0xC5, 0x65, - 0xE2, 0x43, 0x0E, 0x34, 0x2D, 0xC5, 0x87, 0x12, 0xB7, 0x0A, 0x44, 0x30, 0xE7, 0x6E, 0xB3, 0xD5, - 0x84, 0x9F, 0x12, 0x2A, 0xE0, 0xA3, 0x1A, 0xFD, 0x38, 0x10, 0xB5, 0x12, 0x0F, 0x71, 0x7C, 0xAB, - 0x89, 0x8F, 0xA8, 0xB0, 0x3C, 0x2F, 0xB9, 0xDB, 0xB1, 0x45, 0x2C, 0x19, 0xF6, 0xB0, 0x59, 0x94, - 0x97, 0x19, 0x29, 0x67, 0x8A, 0xF3, 0x9B, 0xB3, 0xF5, 0x6A, 0xE6, 0x5D, 0x5B, 0xE2, 0xB8, 0xE0, - 0x49, 0x0E, 0xF9, 0x2A, 0x29, 0xE1, 0x29, 0xF5, 0x4E, 0x07, 0x1A, 0x90, 0x25, 0xA5, 0xFC, 0x59, - 0x14, 0xC7, 0x29, 0xBD, 0x10, 0x00, 0xC2, 0x48, 0xDE, 0x10, 0x58, 0x8A, 0x0A, 0x5B, 0xA4, 0xD7, - 0xE9, 0x74, 0x96, 0xD3, 0xD6, 0x8E, 0x1D, 0xDA, 0x83, 0x95, 0x6B, 0x11, 0xB6, 0xB0, 0xC3, 0x53, - 0x07, 0xC5, 0xFA, 0x61, 0x1B, 0xF9, 0xC1, 0xBE, 0xB6, 0x5C, 0xC2, 0xC8, 0x69, 0x56, 0xF0, 0x92, - 0xA0, 0x08, 0x62, 0x68, 0x24, 0x11, 0x53, 0x18, 0x8C, 0xA8, 0xE5, 0x47, 0x24, 0xCA, 0xE1, 0x6D, - 0xA6, 0x79, 0xEC, 0x4F, 0x07, 0x03, 0x58, 0xDD, 0x31, 0x2E, 0xA5, 0xB4, 0xE5, 0x31, 0x1E, 0x51, - 0x6E, 0xE2, 0xB0, 0xC9, 0x33, 0x97, 0xA7, 0x99, 0x4A, 0x70, 0x96, 0x45, 0x67, 0x60, 0x0C, 0x56, - 0x91, 0x11, 0x53, 0x42, 0x7E, 0xD1, 0x72, 0x2E, 0x7E, 0xC0, 0xE5, 0x5A, 0xAC, 0x98, 0x4D, 0x2B, - 0xC1, 0xF4, 0x4A, 0x3C, 0xDA, 0x71, 0xC0, 0x33, 0x2B, 0x9C, 0x7F, 0xDB, 0x3E, 0x33, 0x7E, 0x4B, - 0x22, 0xC2, 0x22, 0xE6, 0x6C, 0x27, 0x1F, 0x0A, 0x2F, 0x4E, 0x2A, 0x41, 0x19, 0xC6, 0xED, 0x5F, - 0xBE, 0xA0, 0xFF, 0xA7, 0xB2, 0xFA, 0xD6, 0xF6, 0x0B, 0x2A, 0x73, 0x98, 0x22, 0x57, 0xC4, 0x9F, - 0xA1, 0x49, 0xF9, 0x1C, 0x1A, 0x2E, 0x3B, 0x64, 0xF6, 0xB4, 0xE8, 0xA3, 0x44, 0xC7, 0x25, 0xED, - 0x91, 0xFB, 0xAF, 0x21, 0x14, 0x59, 0xE4, 0xB9, 0x8F, 0xEF, 0x35, 0xE9, 0x4A, 0x23, 0xF5, 0xB7, - 0xE6, 0x22, 0x18, 0x34, 0x85, 0xBD, 0x09, 0x83, 0x78, 0xD9, 0xA5, 0x0A, 0xBE, 0x83, 0x29, 0xE1, - 0x43, 0x1B, 0x2F, 0x1F, 0x71, 0x7F, 0x7C, 0xF3, 0xAB, 0xA4, 0x8C, 0xAC, 0x58, 0xCC, 0x09, 0xAC, - 0x98, 0xD1, 0xED, 0xC0, 0x30, 0xDE, 0xDC, 0x04, 0x7E, 0x4F, 0xC0, 0xC9, 0xC3, 0xAC, 0x12, 0x57, - 0x34, 0xBC, 0xC3, 0x63, 0xC1, 0x0E, 0xDB, 0xFB, 0x81, 0xB2, 0x46, 0x0B, 0xED, 0xD8, 0x68, 0x64, - 0x4D, 0x02, 0x8A, 0x09, 0xFA, 0x78, 0x86, 0x0D, 0xB6, 0xDB, 0xA1, 0xAA, 0xAF, 0x89, 0x3E, 0xAE, - 0x6B, 0x17, 0xC9, 0x03, 0xE2, 0x2F, 0xE6, 0x03, 0x13, 0x7C, 0x95, 0xE1, 0x62, 0x2B, 0x9B, 0x89, - 0xAD, 0x59, 0xE4, 0x80, 0xF4, 0xCB, 0x4A, 0xA2, 0x1E, 0x0F, 0x46, 0x39, 0x88, 0x8A, 0x7D, 0x3E, - 0x8F, 0x80, 0xE1, 0x1E, 0xF0, 0x5B, 0xCF, 0x03, 0x58, 0x87, 0xC8, 0x26, 0x59, 0x14, 0x98, 0x86, - 0x20, 0xAA, 0x74, 0x34, 0x90, 0xA0, 0x26, 0x87, 0x34, 0x0D, 0x55, 0x98, 0x7E, 0x56, 0x59, 0xE9, - 0x2A, 0x7A, 0x84, 0x15, 0x41, 0xA6, 0x93, 0x3C, 0x00, 0x3E, 0xB4, 0xD3, 0x04, 0xE4, 0xB6, 0x82, - 0x33, 0xE8, 0xA0, 0x4B, 0xFF, 0xD6, 0xA1, 0x23, 0x3B, 0x58, 0x4A, 0x9E, 0xA1, 0xD8, 0x17, 0x42, - 0x10, 0x5E, 0xF4, 0x20, 0x49, 0x01, 0xA2, 0x8B, 0x27, 0x16, 0xAC, 0xD8, 0xCF, 0x13, 0x99, 0x64, - 0x40, 0xE2, 0xD1, 0xA6, 0x20, 0x52, 0x8F, 0xDC, 0xB7, 0x4C, 0xE8, 0xA4, 0x5B, 0x10, 0x14, 0x2F, - 0x5B, 0x57, 0x85, 0x43, 0x95, 0x12, 0xA0, 0xF0, 0x6B, 0x39, 0xE8, 0x37, 0x49, 0x52, 0x2B, 0x00, - 0x65, 0x29, 0xAE, 0xAA, 0x53, 0x65, 0x4A, 0x24, 0xC0, 0x4B, 0x53, 0x3E, 0x3B, 0x93, 0x04, 0x25, - 0xEF, 0xCA, 0x94, 0x83, 0x96, 0x72, 0x5F, 0x31, 0x04, 0xF8, 0x67, 0x29, 0xC8, 0x5F, 0x9C, 0xB7, - 0x4E, 0x02, 0x78, 0xE7, 0x5C, 0x3B, 0xE5, 0xE0, 0x2E, 0xF6, 0xCF, 0x3E, 0x1E, 0x48, 0x3C, 0xC3, - 0x4A, 0xF3, 0xA3, 0x3D, 0x29, 0x07, 0xCB, 0x2E, 0xB6, 0x26, 0xA0, 0xCC, 0x9F, 0x2F, 0x07, 0x99, - 0x5E, 0x6A, 0xDE, 0x27, 0x78, 0x24, 0x5F, 0xAF, 0x1C, 0xB6, 0xFE, 0x7D, 0x10, 0xD2, 0x71, 0x82, - 0x20, 0xE0, 0x7F, 0x97, 0x82, 0x3D, 0x54, 0x13, 0x97, 0x01, 0x74, 0x9C, 0xCA, 0xAC, 0x14, 0xFC, - 0xE9, 0x85, 0x24, 0x3C, 0xCC, 0x6E, 0x56, 0x0A, 0xEA, 0xAD, 0xF4, 0x56, 0x08, 0xC0, 0xC9, 0x4B, - 0xA4, 0x08, 0x9E, 0x3B, 0x0B, 0xFA, 0xEC, 0xC6, 0x47, 0xB1, 0x18, 0x92, 0x84, 0x53, 0x4E, 0x19, - 0x50, 0x9E, 0x86, 0x21, 0xB9, 0xD4, 0x8C, 0xC7, 0xC6, 0x2D, 0x7C, 0xC2, 0x69, 0x63, 0x5B, 0x32, - 0xA6, 0x2C, 0xCD, 0xE8, 0xC6, 0x36, 0x40, 0x5A, 0xBE, 0x35, 0xC0, 0xB3, 0x34, 0xD9, 0x9C, 0xAA, - 0xA3, 0x7E, 0x39, 0x26, 0xCD, 0x72, 0xD2, 0x66, 0xD0, 0xE5, 0x86, 0xDB, 0xB0, 0x73, 0xDE, 0xC2, - 0xC7, 0x76, 0x3A, 0x9D, 0x6E, 0xAF, 0xC5, 0x5E, 0x0B, 0x4A, 0xDB, 0x73, 0x5E, 0xCA, 0xAC, 0x7A, - 0xB7, 0xC3, 0x00, 0x4C, 0x06, 0x24, 0x92, 0x2A, 0x92, 0xDC, 0x97, 0x93, 0x72, 0xB1, 0x5D, 0x8A, - 0x4C, 0x76, 0x78, 0x26, 0xAD, 0x06, 0x9B, 0x4E, 0xB6, 0x3B, 0x99, 0xD3, 0xC9, 0x76, 0xA7, 0x04, - 0xD9, 0x14, 0xEA, 0xFD, 0xD3, 0x0F, 0x33, 0x61, 0x8E, 0x7D, 0xD8, 0xAC, 0xED, 0xE5, 0xF8, 0x6C, - 0x2C, 0xED, 0xDD, 0x9A, 0xFA, 0xDC, 0x4D, 0x80, 0xF7, 0x2D, 0x90, 0x90, 0xFF, 0xDE, 0x0B, 0x42, - 0xD1, 0xFB, 0x9B, 0xA9, 0xDE, 0xDF, 0xCC, 0xE8, 0xFD, 0x74, 0xEB, 0x33, 0x24, 0x90, 0x22, 0x87, - 0x16, 0x8C, 0x93, 0xDB, 0xC6, 0x7F, 0x3A, 0x45, 0xF6, 0xB1, 0x1A, 0x25, 0x43, 0xCB, 0xD8, 0x53, - 0x41, 0x6C, 0xCF, 0x9B, 0x93, 0x5A, 0xEF, 0xE8, 0x74, 0xD6, 0x3B, 0xB5, 0x5B, 0xC6, 0xDB, 0xF1, - 0x31, 0xA0, 0x7E, 0xB6, 0x34, 0xD3, 0x05, 0x58, 0x9F, 0x19, 0xC1, 0xF0, 0x6B, 0x6F, 0xE8, 0xB5, - 0x07, 0xDE, 0x18, 0xFF, 0xC2, 0xAF, 0x64, 0x8C, 0x8C, 0x61, 0x46, 0x54, 0x30, 0x2C, 0x0E, 0x78, - 0xAC, 0x63, 0xCB, 0x19, 0x61, 0x98, 0x99, 0x0F, 0x3E, 0x51, 0x3E, 0x6B, 0xD1, 0x79, 0x1D, 0xE1, - 0xE7, 0x65, 0x18, 0x34, 0x79, 0x07, 0xB6, 0x52, 0x1C, 0xFB, 0x61, 0xE0, 0x9B, 0x48, 0xA3, 0x16, - 0x10, 0xB0, 0x59, 0xB4, 0x4D, 0x38, 0x3D, 0xEB, 0x9E, 0xDC, 0x59, 0x60, 0x32, 0x40, 0x0E, 0xB6, - 0x13, 0xB0, 0x48, 0xBF, 0xD3, 0x8B, 0xF3, 0xA3, 0x33, 0xDC, 0xF6, 0x61, 0xC1, 0x6E, 0x23, 0x8F, - 0x73, 0x43, 0xE8, 0x37, 0xF0, 0x28, 0x70, 0x23, 0x2D, 0xCA, 0x14, 0xD6, 0x8E, 0x28, 0x4A, 0xCB, - 0x14, 0xF8, 0x8B, 0xEF, 0x03, 0xE1, 0x4A, 0x93, 0xCB, 0x28, 0x47, 0x32, 0x92, 0x00, 0x44, 0x2B, - 0xCA, 0xC1, 0x0B, 0xC5, 0xE9, 0x75, 0x3B, 0xDD, 0x92, 0x70, 0x8A, 0x16, 0x34, 0xAE, 0x46, 0xB6, - 0x7F, 0xD9, 0x9F, 0x58, 0xFE, 0xD7, 0xB7, 0x53, 0xB7, 0xDB, 0xA8, 0x8C, 0xE3, 0xEC, 0x97, 0x6A, - 0xFC, 0x46, 0x1D, 0x1E, 0xD2, 0x20, 0xFC, 0x3F, 0xF8, 0xA3, 0x7A, 0x93, 0x11, 0x05, 0x90, 0x05, - 0x24, 0x1A, 0xDC, 0x50, 0x1D, 0x59, 0x17, 0x22, 0x49, 0xDD, 0xBB, 0x77, 0x7B, 0x19, 0x81, 0x23, - 0x00, 0xA7, 0x6D, 0xF7, 0xA1, 0x7F, 0x07, 0x0B, 0x8E, 0x38, 0x33, 0x77, 0xB2, 0xD1, 0xB9, 0xB6, - 0x36, 0x66, 0x8B, 0x3E, 0xAC, 0xE1, 0xD8, 0x01, 0x09, 0x42, 0xCB, 0x67, 0x3A, 0xC0, 0x94, 0x4A, - 0xBB, 0x5D, 0xF7, 0xEC, 0x3B, 0x65, 0x85, 0xC3, 0xA5, 0x5D, 0xC2, 0x4A, 0xFE, 0xC6, 0x63, 0x93, - 0xA7, 0xDC, 0x70, 0xEC, 0x7F, 0xDB, 0xD5, 0xB8, 0xFF, 0x22, 0x2F, 0x7A, 0x4D, 0xBB, 0x59, 0x12, - 0x89, 0xAC, 0x2D, 0x2C, 0x73, 0x90, 0xB1, 0x04, 0xC8, 0x77, 0x1A, 0x77, 0xD2, 0xA1, 0x74, 0xFA, - 0xDA, 0xD3, 0x1C, 0x22, 0x2A, 0xE7, 0x4F, 0x2A, 0xDF, 0x31, 0x2C, 0x20, 0x7A, 0xBE, 0xD2, 0x62, - 0x28, 0x9F, 0x94, 0xC4, 0xD8, 0x1A, 0x31, 0x4F, 0x6A, 0x26, 0x9D, 0xC7, 0xC5, 0xA5, 0x41, 0xEB, - 0xAB, 0x25, 0x22, 0x97, 0xD8, 0x2F, 0x2D, 0x4D, 0xFD, 0x16, 0x5F, 0xA1, 0x28, 0xC7, 0xB5, 0xE4, - 0x38, 0xAE, 0x24, 0x44, 0xB6, 0xD4, 0x2F, 0x52, 0xBC, 0x19, 0x5B, 0x9B, 0x04, 0xF4, 0xFF, 0x8F, - 0x6A, 0x72, 0xB9, 0xF1, 0xF2, 0x58, 0x2D, 0xAE, 0x3A, 0x56, 0xD4, 0x17, 0x93, 0x78, 0xDA, 0xD3, - 0xE8, 0x2A, 0x63, 0xF1, 0x88, 0xC9, 0x79, 0x6F, 0x69, 0x06, 0xC9, 0xA6, 0x6E, 0xA0, 0x7E, 0x2F, - 0xE9, 0x2A, 0x3E, 0xAE, 0x04, 0x8B, 0xEB, 0x18, 0x70, 0x37, 0xF1, 0x6D, 0x06, 0xF3, 0x32, 0xA6, - 0xCB, 0x37, 0xA6, 0xB0, 0x3C, 0x77, 0x7F, 0x6C, 0xAE, 0x0A, 0xA9, 0xDF, 0xC3, 0xFD, 0x97, 0x94, - 0x5A, 0xB4, 0xA3, 0x97, 0xA1, 0xD4, 0x2C, 0xBD, 0xAE, 0xB4, 0x2C, 0x8D, 0x56, 0x54, 0x86, 0x80, - 0xA9, 0x92, 0x0B, 0x2A, 0xB1, 0xC0, 0xF1, 0xAE, 0x02, 0x14, 0x2E, 0xCB, 0x1F, 0x4D, 0x07, 0x9E, - 0x6B, 0xA3, 0xCB, 0xBE, 0xD5, 0x61, 0xCD, 0x31, 0x34, 0x66, 0xAB, 0x23, 0x1E, 0xEF, 0x90, 0x1B, - 0xF2, 0xC6, 0x98, 0x62, 0x3D, 0x9F, 0xD8, 0x99, 0x17, 0x38, 0xF8, 0xFF, 0xBD, 0xC1, 0x60, 0x0A, - 0xCB, 0x98, 0x7B, 0xBE, 0xD0, 0xD9, 0x44, 0x41, 0xA6, 0x88, 0x76, 0xDB, 0x8C, 0xEA, 0x66, 0x3B, - 0x87, 0x6A, 0x42, 0x56, 0xF1, 0x49, 0x59, 0xB4, 0xD5, 0x21, 0xCB, 0xF6, 0xD4, 0x52, 0xDE, 0x62, - 0x97, 0x19, 0x35, 0x43, 0x7C, 0x42, 0x08, 0xE9, 0x8D, 0xF6, 0x62, 0x88, 0xDF, 0x00, 0x42, 0x7A, - 0xBB, 0x3D, 0x1F, 0xE0, 0xD8, 0x0A, 0x59, 0xDE, 0xE9, 0x16, 0x7B, 0x6A, 0x7E, 0xBB, 0xD3, 0xDB, - 0xDE, 0x78, 0xBE, 0x5D, 0x00, 0xE2, 0xB9, 0x43, 0x01, 0xC3, 0x5F, 0xA1, 0x7F, 0xB1, 0xD9, 0xD9, - 0x7C, 0xBE, 0xD5, 0xCD, 0x87, 0xDA, 0x1B, 0x85, 0x4E, 0x38, 0xB5, 0xD9, 0x16, 0xC9, 0xE6, 0x16, - 0xD0, 0x7A, 0xB1, 0xAD, 0x2C, 0xBF, 0xB4, 0x03, 0x1B, 0x15, 0x43, 0x86, 0x7A, 0x64, 0x52, 0xCC, - 0xEF, 0x61, 0xE8, 0x41, 0xB9, 0xAB, 0x22, 0x25, 0xCE, 0x0F, 0xB3, 0xCB, 0xD1, 0xE7, 0x9A, 0xA2, - 0xAD, 0x2F, 0xDE, 0x4A, 0x22, 0x2E, 0xB0, 0x20, 0x9A, 0x6E, 0x3E, 0xEF, 0xB0, 0x7F, 0x2D, 0x12, - 0xFF, 0x12, 0x8F, 0x83, 0xA8, 0x0C, 0x07, 0x81, 0xF8, 0xB5, 0x78, 0xF8, 0x15, 0x11, 0xFD, 0xF4, - 0x3D, 0x88, 0xFE, 0xB6, 0x08, 0xA2, 0x0F, 0x79, 0xB1, 0xCA, 0xD5, 0xCD, 0x41, 0x3D, 0x93, 0x50, - 0xC9, 0x2C, 0xA4, 0xE5, 0x95, 0x04, 0x2D, 0x81, 0xB1, 0xFF, 0x99, 0xFA, 0x98, 0xDD, 0x1C, 0xBE, - 0xAD, 0xB1, 0xEB, 0x1F, 0xC9, 0x05, 0xFF, 0x52, 0x82, 0x96, 0xB4, 0x71, 0xB5, 0xDB, 0xED, 0xAC, - 0x6F, 0xB4, 0xC8, 0x8B, 0x17, 0xCA, 0xD6, 0x28, 0xFF, 0x8C, 0x42, 0xC6, 0x82, 0x12, 0x46, 0x35, - 0x83, 0x9C, 0x7E, 0xAF, 0x00, 0x09, 0x62, 0x66, 0xFB, 0x4D, 0x85, 0xD6, 0x26, 0xCB, 0x15, 0xBF, - 0x59, 0x5B, 0x7B, 0xCC, 0xD1, 0x87, 0x40, 0xAB, 0xC7, 0x67, 0xDC, 0x9E, 0x36, 0xF1, 0xF2, 0xEF, - 0x3C, 0xA1, 0x7D, 0xA7, 0x5D, 0x5A, 0x81, 0x1E, 0x32, 0xF7, 0x2A, 0xE3, 0xA0, 0xDA, 0x3A, 0x7B, - 0x95, 0x1C, 0x38, 0xD9, 0x43, 0xBA, 0xEC, 0x94, 0xDE, 0xAB, 0x96, 0xE1, 0x19, 0xD3, 0x9D, 0x32, - 0xBB, 0x95, 0x32, 0x41, 0xDC, 0x74, 0x8A, 0x08, 0xE6, 0xEF, 0x57, 0x96, 0xA7, 0x95, 0xD9, 0x3A, - 0xDC, 0xEE, 0x61, 0xC4, 0x3A, 0x5A, 0xEB, 0x3A, 0x33, 0xB6, 0x2E, 0x97, 0xE2, 0xD9, 0x2F, 0x8F, - 0x45, 0x33, 0xD9, 0x4B, 0x5B, 0x48, 0x1F, 0xE6, 0x52, 0x7C, 0xBC, 0x56, 0x4A, 0x9A, 0xDA, 0xAD, - 0x4F, 0xB1, 0x5B, 0x4B, 0x53, 0x05, 0x41, 0x5D, 0x53, 0x3B, 0xF9, 0x9A, 0xDA, 0xAD, 0xA7, 0xA9, - 0x8B, 0x68, 0x5D, 0x91, 0xA6, 0x3E, 0x12, 0x4D, 0x49, 0x53, 0x1F, 0x9D, 0xE2, 0xE3, 0xB5, 0x52, - 0xD2, 0xD4, 0x5E, 0x7D, 0x8A, 0xBD, 0x5A, 0x9A, 0xDA, 0xAB, 0xA5, 0xA9, 0xBD, 0x7A, 0x9A, 0xBA, - 0x88, 0xD6, 0x15, 0x69, 0xEA, 0x23, 0xD1, 0x94, 0x34, 0xF5, 0xD1, 0x29, 0x3E, 0x5E, 0x2B, 0x25, - 0x4D, 0x5D, 0xAF, 0x4F, 0x71, 0xBD, 0x96, 0xA6, 0xAE, 0xD7, 0xD2, 0xD4, 0xF5, 0x7A, 0x9A, 0xBA, - 0x88, 0xD6, 0x15, 0x69, 0xEA, 0x23, 0xD1, 0x94, 0x34, 0xF5, 0xD1, 0x29, 0xCE, 0xA9, 0x95, 0x4F, - 0xFD, 0xB8, 0xD5, 0xE8, 0x2A, 0x57, 0x3A, 0x70, 0x35, 0xFA, 0xBE, 0xA5, 0x8E, 0x5C, 0x8D, 0x8E, - 0x6C, 0xD5, 0xC3, 0xCF, 0x0C, 0xDF, 0xB4, 0x51, 0x16, 0x52, 0xF3, 0x30, 0xF9, 0x99, 0xAF, 0x7D, - 0xE7, 0x86, 0x77, 0x6E, 0xAF, 0x3A, 0x8E, 0x88, 0xFA, 0x2F, 0xE7, 0x9B, 0x77, 0xE7, 0xDE, 0xC6, - 0xFB, 0x6A, 0xFC, 0xC7, 0x1E, 0x60, 0xA3, 0x86, 0xD8, 0x99, 0x07, 0x50, 0x5D, 0xE6, 0x35, 0xC8, - 0x49, 0x8E, 0x55, 0x1D, 0x31, 0xD7, 0x84, 0xAB, 0x4A, 0x51, 0x73, 0x55, 0xEA, 0x88, 0xB4, 0x57, - 0x4F, 0xA4, 0xBD, 0xDA, 0x22, 0xED, 0xD5, 0x14, 0x69, 0xAF, 0xB6, 0x48, 0x7B, 0x35, 0x45, 0xBA, - 0x5E, 0x53, 0xA4, 0xEB, 0xF5, 0x44, 0xBA, 0x5E, 0x5B, 0xA4, 0xEB, 0x35, 0x45, 0xBA, 0x5E, 0x5B, - 0xA4, 0x3A, 0x64, 0x7C, 0xA0, 0x20, 0xDF, 0xA8, 0x35, 0x1D, 0x2C, 0x14, 0xDD, 0xBB, 0xCD, 0xD9, - 0x0A, 0x89, 0x32, 0x00, 0xB0, 0x0B, 0xF6, 0x12, 0x82, 0x03, 0xF6, 0x58, 0x8D, 0x08, 0xBC, 0xBB, - 0xF0, 0xBE, 0x52, 0x37, 0x4A, 0x44, 0xB1, 0xF3, 0x4C, 0xCB, 0x4D, 0x32, 0xA5, 0x71, 0x76, 0x6C, - 0xFD, 0xC1, 0x00, 0x63, 0x20, 0x60, 0x3E, 0x95, 0x16, 0x59, 0xDF, 0xE2, 0xFF, 0xC5, 0x53, 0xE7, - 0xFA, 0x56, 0x56, 0x5C, 0xE0, 0x99, 0x29, 0x44, 0x29, 0x77, 0x8F, 0xBC, 0x90, 0x7A, 0xA3, 0xA1, - 0xDF, 0xA7, 0x9D, 0x86, 0xDE, 0xDF, 0xE8, 0xFD, 0x39, 0x75, 0xE9, 0x9D, 0x35, 0xCA, 0x88, 0x79, - 0x91, 0xBA, 0xCA, 0xCF, 0xE9, 0x22, 0xFD, 0x12, 0x73, 0xB5, 0xE3, 0x1F, 0x2A, 0x43, 0xE3, 0x95, - 0x9F, 0x37, 0xFC, 0xCC, 0x85, 0x63, 0x63, 0x9B, 0x1C, 0x5B, 0x9D, 0xD4, 0x36, 0xAD, 0x78, 0xC1, - 0xBD, 0x85, 0x5F, 0xB5, 0x2D, 0xDA, 0x33, 0xF3, 0xEB, 0xB6, 0x45, 0xA4, 0x8F, 0x59, 0x6F, 0xCF, - 0x89, 0x60, 0x2C, 0x39, 0x0C, 0x1A, 0x2E, 0x0A, 0x22, 0xC5, 0x50, 0xE2, 0x53, 0x68, 0xB4, 0xE7, - 0x7F, 0xBD, 0xEC, 0xF4, 0xFB, 0x47, 0x07, 0xA5, 0x1D, 0x2D, 0x43, 0x68, 0xB2, 0x21, 0x94, 0xD2, - 0x48, 0xE7, 0xCC, 0x0A, 0x02, 0xF8, 0xCD, 0x7E, 0x04, 0x5A, 0xDD, 0x47, 0x6A, 0x53, 0xF7, 0x11, - 0xDB, 0xD4, 0x7B, 0xA4, 0x36, 0xF5, 0x1E, 0xB1, 0x4D, 0xEB, 0x8F, 0xD4, 0xA6, 0xF5, 0x39, 0xB5, - 0x49, 0x0C, 0xB1, 0x8B, 0xFD, 0xB3, 0xB5, 0x8F, 0x07, 0x67, 0xD9, 0xF6, 0xE9, 0x62, 0x50, 0x39, - 0xD6, 0x57, 0x18, 0x88, 0xF8, 0xBA, 0x78, 0x12, 0x73, 0xBB, 0xB5, 0xB9, 0xB9, 0x9E, 0x8A, 0xF2, - 0x65, 0x1F, 0x65, 0x46, 0x95, 0x98, 0xFF, 0x82, 0xF5, 0x56, 0x4C, 0x44, 0x8A, 0x23, 0x2E, 0x1F, - 0x45, 0x6E, 0xA2, 0xF4, 0x60, 0x16, 0x42, 0xD5, 0x43, 0x84, 0x44, 0x08, 0x1C, 0x72, 0x1E, 0x42, - 0x30, 0xB1, 0xF6, 0xD1, 0xAE, 0xCB, 0xDA, 0xD4, 0x9E, 0x3B, 0x6B, 0x6B, 0x6B, 0x1F, 0x5C, 0x12, - 0x5D, 0x59, 0x68, 0x11, 0xA8, 0x48, 0x78, 0xEF, 0xB0, 0x08, 0x0A, 0x4E, 0x8D, 0xBD, 0x87, 0x8C, - 0xCB, 0x4E, 0xC0, 0xCF, 0x9B, 0x60, 0xE3, 0x93, 0xCB, 0xB8, 0xFE, 0x0C, 0x30, 0x92, 0x23, 0x84, - 0x59, 0x2C, 0x8A, 0x9A, 0x98, 0x02, 0x12, 0xCF, 0x25, 0xA8, 0xB9, 0x2D, 0xAC, 0x71, 0x2F, 0x1E, - 0x53, 0x6E, 0xB7, 0xA3, 0x95, 0x29, 0x0F, 0xB6, 0x17, 0xD9, 0x2B, 0x4F, 0xA6, 0x21, 0xFD, 0x96, - 0x56, 0x5C, 0xBC, 0x34, 0xA1, 0x75, 0x23, 0x7C, 0xAA, 0xCD, 0x5C, 0x9E, 0x28, 0xA2, 0x1B, 0xEB, - 0xEC, 0x16, 0x7B, 0xE6, 0x98, 0x12, 0xC9, 0x3C, 0xAA, 0x75, 0xD7, 0x08, 0x80, 0xE2, 0x03, 0x76, - 0xF0, 0xE2, 0xDE, 0xFA, 0xF4, 0x1F, 0x53, 0xEA, 0xB2, 0x83, 0xF9, 0xED, 0xCE, 0x3A, 0xFC, 0xE8, - 0x3D, 0x97, 0xBA, 0x0E, 0x3E, 0xB1, 0x2D, 0xA2, 0xDE, 0x73, 0x99, 0x5F, 0xF9, 0x4A, 0x4C, 0xFE, - 0xF4, 0x8E, 0xE4, 0x40, 0x26, 0x8E, 0x35, 0x62, 0xF1, 0x3B, 0x16, 0xF3, 0x1C, 0xC5, 0xA5, 0xE2, - 0x4B, 0x1C, 0x44, 0xDD, 0x54, 0x90, 0x49, 0xD7, 0x14, 0x5C, 0x62, 0xA0, 0x98, 0x84, 0x7A, 0x49, - 0x59, 0x23, 0xF3, 0xEF, 0x6C, 0xA4, 0xEE, 0x57, 0x07, 0xC7, 0xCE, 0x35, 0x15, 0xBD, 0x81, 0x47, - 0x96, 0x3D, 0x99, 0x11, 0x7E, 0x62, 0xD9, 0x53, 0xF8, 0xC8, 0xBE, 0xD2, 0xB3, 0x2C, 0xE5, 0x5C, - 0x08, 0xA0, 0x23, 0x58, 0xCA, 0xA5, 0x7C, 0x76, 0xE6, 0x78, 0x70, 0xFA, 0x98, 0x07, 0xA6, 0xA2, - 0x99, 0xFC, 0x3E, 0x52, 0x9E, 0x7A, 0x46, 0x69, 0x54, 0xAA, 0x69, 0xE8, 0xD8, 0xFA, 0x06, 0xA0, - 0x17, 0x4E, 0x74, 0x9D, 0xA7, 0xDB, 0xD9, 0x84, 0x4E, 0x48, 0xF9, 0x81, 0xDD, 0x16, 0x7C, 0x6F, - 0xF5, 0x54, 0x35, 0x51, 0xEE, 0x48, 0xE5, 0x6B, 0x26, 0x27, 0x23, 0x7B, 0x9C, 0xB3, 0x12, 0x2A, - 0xB1, 0x48, 0x50, 0xDA, 0xB6, 0xD5, 0x21, 0x7F, 0x21, 0xBD, 0xEC, 0x00, 0x21, 0x8D, 0x43, 0xB5, - 0xBA, 0xF1, 0x9C, 0x5A, 0x49, 0x5E, 0x53, 0x4D, 0xEA, 0x09, 0x68, 0x14, 0x68, 0x17, 0xBB, 0xE1, - 0x69, 0x0F, 0x7C, 0x1E, 0xA2, 0x30, 0x13, 0xEC, 0xE4, 0x36, 0xCF, 0x94, 0x52, 0xA7, 0x5A, 0x33, - 0x2D, 0x09, 0x05, 0xB3, 0xF7, 0x51, 0x82, 0xC8, 0xE4, 0x70, 0xDC, 0x7C, 0x3A, 0xBE, 0x3D, 0x87, - 0x26, 0xE7, 0x10, 0x2F, 0x6C, 0x77, 0x2A, 0x2B, 0x65, 0xA9, 0xE6, 0xAA, 0x49, 0x30, 0xB9, 0x5F, - 0xD3, 0xDB, 0xDE, 0xD8, 0xDE, 0x7A, 0x9E, 0x72, 0x6E, 0xF8, 0xE7, 0x39, 0xB4, 0x52, 0xA7, 0xD9, - 0x61, 0xD1, 0x2C, 0xF8, 0x6C, 0x91, 0xD8, 0x37, 0x8E, 0x1A, 0x2A, 0xEC, 0x48, 0x34, 0xD1, 0xC7, - 0x0D, 0xCF, 0xBC, 0x83, 0x61, 0x6E, 0xEA, 0xD1, 0xD9, 0x1E, 0xBF, 0x65, 0xB4, 0x14, 0x5F, 0x6A, - 0x3C, 0x3A, 0x6B, 0x48, 0xED, 0x73, 0x5D, 0xB7, 0x2D, 0xFD, 0x27, 0x37, 0x51, 0xBB, 0x17, 0x99, - 0x61, 0x31, 0x0C, 0x14, 0x0E, 0x4E, 0xFB, 0x8B, 0x26, 0xF1, 0x0E, 0xF4, 0xFB, 0xCE, 0xBA, 0x5F, - 0x34, 0x99, 0xFE, 0xF4, 0x0A, 0x7E, 0xCE, 0x95, 0x4A, 0xB4, 0xB4, 0x17, 0x95, 0x4F, 0xC3, 0x89, - 0xF0, 0x0D, 0x3B, 0x69, 0xDF, 0xB0, 0x63, 0xF4, 0x0D, 0xCD, 0x74, 0xE2, 0x19, 0xFF, 0xF4, 0xE2, - 0xAC, 0xAE, 0xB6, 0xC4, 0xA7, 0x64, 0xC0, 0xD3, 0x68, 0x74, 0xF8, 0x6D, 0xE2, 0xB9, 0xDC, 0xB9, - 0x03, 0xD7, 0xA7, 0x2B, 0x8F, 0x0A, 0xE6, 0xF7, 0x74, 0x95, 0x01, 0x91, 0xDC, 0x82, 0x2D, 0x3A, - 0x82, 0x9B, 0x00, 0x37, 0x03, 0x87, 0x65, 0x87, 0x86, 0x09, 0x17, 0x2F, 0xEE, 0x29, 0x33, 0xED, - 0x3A, 0x6B, 0x75, 0xA7, 0x26, 0xEE, 0x73, 0x18, 0x5E, 0x07, 0x74, 0xC4, 0x54, 0xA3, 0xD3, 0x62, - 0x69, 0x5B, 0xB5, 0x8D, 0x12, 0x86, 0xBE, 0x6B, 0xDC, 0x28, 0xA9, 0x4A, 0xC7, 0x09, 0x26, 0x22, - 0xCD, 0xF5, 0x22, 0x88, 0x25, 0xE7, 0x5D, 0x93, 0x73, 0x7A, 0x4D, 0x7D, 0x70, 0x44, 0xE9, 0x91, - 0x2D, 0x0C, 0x55, 0xCA, 0x44, 0xB1, 0xE5, 0x57, 0x90, 0x4B, 0xE0, 0x21, 0xCA, 0x98, 0x91, 0xF1, - 0x96, 0xB1, 0x96, 0x3B, 0x03, 0xB3, 0x9A, 0x89, 0x2A, 0x52, 0x3A, 0x2D, 0x35, 0xAB, 0x80, 0x74, - 0x7B, 0x55, 0xBE, 0xA8, 0xBC, 0x4B, 0xBA, 0x4A, 0x0E, 0xA0, 0x38, 0x07, 0x4E, 0x13, 0x53, 0xE1, - 0xBF, 0x09, 0xDD, 0x26, 0xF0, 0x79, 0x06, 0x96, 0x11, 0x4C, 0x25, 0x33, 0x90, 0x2C, 0x2B, 0x88, - 0x84, 0x61, 0x05, 0x3E, 0xB0, 0x3F, 0x1B, 0xBA, 0x07, 0x10, 0xE5, 0x94, 0x89, 0x31, 0x49, 0x15, - 0x16, 0xFA, 0xF6, 0xF2, 0x83, 0x7A, 0x25, 0x42, 0x62, 0xF6, 0xF5, 0xDC, 0x5A, 0x1B, 0x3C, 0xC9, - 0xE6, 0xFE, 0x53, 0xD9, 0x99, 0x2D, 0x93, 0x10, 0xF6, 0xD8, 0xB3, 0x30, 0xDB, 0x52, 0x9B, 0x88, - 0x56, 0xDF, 0x59, 0x4E, 0x08, 0x0B, 0xCA, 0xA6, 0x1C, 0x84, 0x6E, 0xD6, 0x41, 0xF3, 0xAD, 0x87, - 0xE8, 0xCA, 0x43, 0xBA, 0xA1, 0x2F, 0x23, 0xE6, 0xE3, 0x7D, 0xF2, 0x67, 0xF2, 0xDB, 0x9B, 0x3C, - 0x17, 0x9C, 0xEE, 0x44, 0xAA, 0x9D, 0x23, 0x15, 0xCB, 0x89, 0x90, 0xE4, 0xCE, 0xEB, 0x5B, 0xB7, - 0xD8, 0x9C, 0x76, 0x5B, 0x09, 0xF9, 0xD4, 0xB2, 0x46, 0x35, 0x92, 0xCC, 0xB7, 0xAD, 0x3C, 0xC1, - 0xB7, 0x14, 0x24, 0x43, 0x9A, 0x95, 0x67, 0x23, 0x95, 0xF1, 0x43, 0x4E, 0x3D, 0x32, 0x4B, 0xC6, - 0x8D, 0xD9, 0xB3, 0x6E, 0xCC, 0x92, 0x79, 0x63, 0x3E, 0xD9, 0x37, 0x66, 0xCF, 0xC0, 0x31, 0x5B, - 0x16, 0x8E, 0x59, 0x32, 0x71, 0xCC, 0x9A, 0x8D, 0x63, 0xB6, 0x8C, 0x1C, 0xF3, 0xCF, 0xCA, 0x91, - 0x8B, 0x31, 0x59, 0xF0, 0x27, 0x88, 0x9C, 0xE4, 0x5B, 0x69, 0x3C, 0x05, 0x19, 0x3E, 0x8A, 0x11, - 0x94, 0x4C, 0xF3, 0x51, 0x3F, 0xD5, 0xC7, 0xAC, 0xE9, 0x3E, 0xD2, 0x39, 0x36, 0xD1, 0x02, 0x71, - 0x7A, 0x7F, 0x80, 0x09, 0xF8, 0x69, 0xCD, 0x8F, 0xC6, 0xE9, 0x6B, 0x51, 0x33, 0x82, 0xF0, 0xBF, - 0x53, 0x29, 0xAF, 0xF4, 0x0C, 0x25, 0x52, 0xBE, 0xBA, 0x25, 0x6E, 0xF7, 0xA5, 0xF2, 0xCB, 0x77, - 0x67, 0x7D, 0x75, 0x0D, 0xCB, 0x93, 0xDC, 0xC5, 0xAC, 0xFC, 0xF4, 0x13, 0x31, 0x41, 0x81, 0x42, - 0x8C, 0x58, 0x66, 0xEC, 0xAA, 0x90, 0x6F, 0xA8, 0x73, 0xE0, 0x4D, 0xEB, 0x90, 0x3C, 0xFE, 0x70, - 0xBA, 0xD7, 0x37, 0x32, 0xBB, 0xAC, 0x39, 0x0B, 0xA6, 0xC4, 0x16, 0x45, 0xD3, 0x9A, 0xA4, 0x1F, - 0x6C, 0xEA, 0x52, 0x84, 0x28, 0xAB, 0xCA, 0x8D, 0x87, 0x51, 0x55, 0xB0, 0x46, 0x21, 0x0A, 0x7F, - 0xB2, 0x8E, 0x24, 0x4A, 0xB4, 0xB2, 0xA2, 0x2B, 0x86, 0x49, 0x05, 0x1A, 0x69, 0x8A, 0xC6, 0x64, - 0x66, 0x6F, 0x9C, 0xF0, 0xC4, 0x9A, 0x24, 0x69, 0xCA, 0xC6, 0x8E, 0x0B, 0x3F, 0xAC, 0x6F, 0x2D, - 0x72, 0xC5, 0x4A, 0xA4, 0x4C, 0x8F, 0xAD, 0xD8, 0x28, 0x1C, 0x1D, 0x48, 0xA3, 0x38, 0x3A, 0xFF, - 0x8F, 0x1F, 0x04, 0xE0, 0xEC, 0x8D, 0xAD, 0xE0, 0x2B, 0x2F, 0xE0, 0x88, 0x94, 0x42, 0xA6, 0x38, - 0x1C, 0xF6, 0x15, 0x92, 0xE4, 0x79, 0x15, 0xF8, 0x87, 0xD7, 0x48, 0x9E, 0x7F, 0x58, 0x62, 0x48, - 0xA0, 0xEB, 0xBA, 0xE4, 0xD5, 0x2B, 0x4E, 0x0B, 0x3A, 0x06, 0xFA, 0xA8, 0xA3, 0xF7, 0x4F, 0x4E, - 0x8A, 0x48, 0x73, 0xDA, 0x49, 0x09, 0x56, 0x6A, 0x55, 0x51, 0x8F, 0xE6, 0xF5, 0x42, 0x6A, 0xAB, - 0x24, 0x4A, 0x64, 0x29, 0x19, 0xC4, 0xE8, 0xC6, 0x32, 0xB4, 0xDF, 0x70, 0xE3, 0x27, 0x20, 0x60, - 0x41, 0x89, 0x0D, 0x6B, 0xCA, 0x09, 0xD8, 0x73, 0xB6, 0x89, 0xA2, 0x76, 0x56, 0x7C, 0x73, 0x48, - 0xCA, 0x09, 0xEC, 0x60, 0x24, 0x81, 0x7A, 0x17, 0x6E, 0x27, 0x49, 0x02, 0x1C, 0x37, 0x8D, 0xEC, - 0x1A, 0x37, 0x7A, 0x93, 0xF7, 0x0E, 0x6C, 0x1A, 0x82, 0xA9, 0xA7, 0xF6, 0x5B, 0x58, 0x65, 0x0B, - 0x3C, 0xC9, 0x03, 0x0F, 0x71, 0xAE, 0xE1, 0xDB, 0xE8, 0x11, 0x09, 0xBC, 0xB4, 0xC7, 0x9F, 0xC0, - 0x71, 0x6C, 0x98, 0xFE, 0x9C, 0xEB, 0xFB, 0xF8, 0xA1, 0x9D, 0x25, 0x59, 0x19, 0x96, 0xE3, 0xFE, - 0x56, 0xC1, 0x76, 0x89, 0x7A, 0x01, 0x30, 0x68, 0xEF, 0x7F, 0xF8, 0x70, 0x7E, 0x70, 0x74, 0xBA, - 0x77, 0x71, 0x78, 0x79, 0x74, 0x7A, 0xF6, 0xF1, 0xE2, 0xF2, 0xE2, 0xD3, 0x19, 0xFE, 0xFA, 0xF3, - 0xDE, 0xF1, 0xD1, 0xC1, 0xE5, 0xC7, 0xD3, 0xBF, 0x9D, 0x7E, 0xF8, 0xE5, 0x54, 0xBF, 0x9D, 0x1D, - 0xF7, 0x28, 0x32, 0x99, 0x60, 0xC4, 0xAB, 0xC2, 0xD0, 0x0A, 0x32, 0x75, 0xBF, 0xBA, 0x98, 0xC5, - 0x78, 0xE7, 0xA9, 0xE9, 0x0A, 0x1B, 0x00, 0x03, 0xFE, 0x24, 0x0C, 0xB5, 0x25, 0xC6, 0x5F, 0x91, - 0xD5, 0xEE, 0x8B, 0x0E, 0x57, 0x7F, 0x53, 0x39, 0x4C, 0x41, 0x2F, 0x3A, 0xCB, 0xB9, 0x62, 0x48, - 0x0E, 0x15, 0x5E, 0xF0, 0x55, 0xFB, 0x8B, 0xCE, 0x93, 0x13, 0x40, 0xE6, 0x50, 0xE1, 0xEA, 0x22, - 0xE9, 0x74, 0x74, 0x51, 0x73, 0xC7, 0xA0, 0x7F, 0xFC, 0xBD, 0xA4, 0xEA, 0x0A, 0xC8, 0xE0, 0x7E, - 0x68, 0xE0, 0x0F, 0x0D, 0xCC, 0xD6, 0xC0, 0x94, 0xBE, 0xFC, 0x69, 0x57, 0x31, 0x7C, 0xB9, 0xED, - 0xE7, 0x36, 0x34, 0xE0, 0xD9, 0xB2, 0x58, 0x22, 0x9C, 0x27, 0xD2, 0xFC, 0x5C, 0x63, 0x2F, 0xF3, - 0x31, 0xF1, 0x61, 0xB1, 0x89, 0x33, 0x50, 0x32, 0xA8, 0xEA, 0x8D, 0x96, 0x4C, 0xB1, 0xD7, 0x65, - 0x43, 0xE9, 0x04, 0x91, 0x54, 0x1F, 0x27, 0x34, 0x1B, 0x0F, 0xFF, 0xF1, 0xEC, 0xDD, 0xF0, 0xF4, - 0x5B, 0x2B, 0x1A, 0x8D, 0x58, 0x0E, 0xDE, 0xD0, 0xDA, 0x08, 0x7B, 0x34, 0xC4, 0xDE, 0xE2, 0x59, - 0x75, 0xE2, 0x69, 0x56, 0x7B, 0x56, 0x20, 0x49, 0xA4, 0xAA, 0xCE, 0xB0, 0xC9, 0xCC, 0x28, 0x46, - 0x08, 0x23, 0xB5, 0x14, 0xD5, 0x69, 0x99, 0x98, 0x48, 0xD2, 0xA0, 0x6A, 0x96, 0x2D, 0x17, 0x19, - 0x54, 0xCA, 0xC3, 0x96, 0xBE, 0x50, 0xCC, 0x8F, 0xCC, 0x02, 0x11, 0xE2, 0xCF, 0xE5, 0x2B, 0x9A, - 0x9F, 0xF6, 0xFE, 0x52, 0x59, 0x6A, 0x13, 0xF7, 0xAF, 0xA6, 0xDB, 0x57, 0xD2, 0xB3, 0x13, 0x08, - 0xD0, 0xB3, 0xF8, 0x4E, 0xAE, 0x1C, 0x7F, 0x8F, 0x33, 0x71, 0x8F, 0x76, 0x33, 0x53, 0x9C, 0x18, - 0x1E, 0x59, 0xAB, 0xB3, 0x1A, 0x78, 0xA8, 0x4C, 0x9A, 0xE7, 0x09, 0xC9, 0x21, 0x2F, 0x9F, 0xD8, - 0x97, 0x27, 0x5F, 0xCB, 0x2A, 0x66, 0xA9, 0x8E, 0xD8, 0xDB, 0x9F, 0xB3, 0xEE, 0x24, 0x4F, 0xA2, - 0xAA, 0x2A, 0x94, 0x44, 0x0A, 0xA3, 0x26, 0xCD, 0x4B, 0x71, 0x0C, 0xFD, 0x61, 0xBA, 0x56, 0x3B, - 0xA7, 0x8E, 0x50, 0x92, 0xE2, 0xC9, 0x24, 0x66, 0x00, 0xED, 0x54, 0xEA, 0xFF, 0x68, 0xFA, 0x2F, - 0x6A, 0x73, 0xF7, 0x49, 0xB7, 0xB9, 0xBB, 0x90, 0x36, 0xF7, 0x9E, 0x74, 0x9B, 0x7B, 0x0B, 0x69, - 0xF3, 0xFA, 0x93, 0x6E, 0xF3, 0x7A, 0xD5, 0x36, 0xEB, 0x28, 0x17, 0xED, 0x30, 0x66, 0x99, 0xC6, - 0xE4, 0x18, 0x5E, 0x79, 0x30, 0xA3, 0x9A, 0x4D, 0x44, 0xDF, 0xD2, 0xE6, 0x4F, 0x54, 0x73, 0x0B, - 0x28, 0x5E, 0xA6, 0x6E, 0x47, 0x6C, 0x33, 0xA3, 0x89, 0x35, 0x22, 0xDB, 0x08, 0x8E, 0xEA, 0x46, - 0xB2, 0xF1, 0xC5, 0xB6, 0x51, 0xB0, 0xF8, 0x73, 0xE7, 0x8B, 0x98, 0x6F, 0xD9, 0x37, 0x27, 0x38, - 0xB5, 0x4E, 0x97, 0xF8, 0x59, 0x4E, 0x54, 0xBE, 0xBC, 0xCC, 0xCB, 0xA2, 0xEA, 0xAF, 0x48, 0x47, - 0xFD, 0xF0, 0x1A, 0x13, 0xF6, 0x2F, 0x9B, 0x90, 0x77, 0x0B, 0x90, 0x77, 0x55, 0xE4, 0x5D, 0x1D, - 0x79, 0x37, 0x0F, 0x79, 0xAF, 0x00, 0x79, 0x4F, 0x45, 0xDE, 0xD3, 0x91, 0xF7, 0xF2, 0x90, 0xAF, - 0x17, 0x20, 0x5F, 0x57, 0x91, 0xAF, 0xEB, 0xC8, 0xD7, 0x63, 0xE4, 0x4F, 0x6F, 0x4B, 0xAA, 0xB2, - 0xCA, 0x4A, 0xF9, 0x82, 0x6F, 0xBC, 0x00, 0x54, 0x75, 0x0A, 0xBF, 0xC2, 0x4F, 0x7F, 0x54, 0xA0, - 0xC0, 0x22, 0x94, 0x09, 0x81, 0x84, 0xFA, 0xB6, 0x43, 0xEF, 0xD8, 0xBB, 0x63, 0x97, 0xA2, 0xE8, - 0xD2, 0x72, 0xF2, 0x8C, 0x2D, 0xE0, 0x5A, 0xCE, 0xB8, 0x41, 0x84, 0xC4, 0x8C, 0xB7, 0x84, 0x74, - 0xA7, 0xA0, 0x6B, 0x74, 0x09, 0x36, 0xB6, 0x4D, 0x0F, 0xE2, 0x22, 0xD2, 0x9A, 0x1D, 0x51, 0xBD, - 0x33, 0xB2, 0x57, 0x5D, 0x39, 0x26, 0x4A, 0xEA, 0x1C, 0x26, 0x81, 0x32, 0xBD, 0x28, 0x2A, 0xA6, - 0x37, 0xEA, 0x95, 0xE8, 0x66, 0xC7, 0xEE, 0xB6, 0x88, 0x63, 0xF7, 0x4A, 0x74, 0x1E, 0xDF, 0x33, - 0xE9, 0x1A, 0x42, 0xCF, 0xC4, 0xD6, 0x39, 0xA0, 0x49, 0x17, 0xA6, 0x54, 0xBE, 0x5B, 0x5F, 0xE7, - 0x81, 0xC0, 0x93, 0xDD, 0xC3, 0xED, 0x9A, 0xCF, 0x59, 0x50, 0x26, 0xA6, 0xE3, 0x2E, 0x25, 0x54, - 0x0E, 0x8D, 0x3F, 0xDF, 0x89, 0x52, 0x1F, 0x81, 0x91, 0x1E, 0xCF, 0x8D, 0xF4, 0x3D, 0x6F, 0x98, - 0xB2, 0xF7, 0x68, 0x2F, 0xBC, 0xB7, 0x16, 0x86, 0x11, 0xDC, 0x1F, 0x88, 0xCB, 0xDB, 0xEA, 0x12, - 0x55, 0x2D, 0x4B, 0xBF, 0x5A, 0xDB, 0x88, 0x8A, 0xC8, 0xDE, 0x04, 0xA6, 0x11, 0x6A, 0x2B, 0x71, - 0x0D, 0x2C, 0xBF, 0xA2, 0xCD, 0x2E, 0xB5, 0x71, 0x6A, 0x78, 0x28, 0x64, 0x7C, 0x56, 0x4A, 0xA3, - 0xC4, 0xA2, 0x16, 0x5B, 0xDD, 0x56, 0xC3, 0xCC, 0xB2, 0xE1, 0x28, 0x36, 0xC5, 0x7E, 0xA9, 0xE7, - 0xB9, 0x92, 0x77, 0xB2, 0xB2, 0xB2, 0x3D, 0x16, 0x3C, 0xAD, 0xB5, 0x4B, 0xBE, 0x29, 0x31, 0x66, - 0x05, 0x6F, 0x05, 0xCA, 0x6D, 0xF9, 0x9D, 0xFA, 0x5E, 0x94, 0xF3, 0x57, 0x7A, 0x83, 0x44, 0xCA, - 0x72, 0xCC, 0xB6, 0xF1, 0x0B, 0x93, 0x50, 0x93, 0x25, 0xBC, 0x31, 0x60, 0xC8, 0x56, 0xBC, 0xFC, - 0x6C, 0x01, 0xB9, 0xA2, 0x6B, 0x66, 0x3D, 0xAE, 0x94, 0xF1, 0x78, 0xA8, 0xE6, 0x6A, 0xD5, 0x9F, - 0x60, 0x7F, 0x50, 0x24, 0xA5, 0x27, 0x16, 0x7E, 0x36, 0xF7, 0x0C, 0xC5, 0x75, 0x92, 0x84, 0x96, - 0x4F, 0x10, 0x9A, 0xD9, 0xD8, 0x76, 0xA7, 0xA8, 0xBD, 0x49, 0x6A, 0x61, 0x7E, 0x3E, 0x36, 0xD7, - 0x24, 0xC5, 0x4F, 0xAB, 0xD5, 0xFC, 0x41, 0x1E, 0x6C, 0x86, 0x61, 0x40, 0x08, 0x4C, 0xFD, 0xD0, - 0xA7, 0xD6, 0x38, 0x51, 0x82, 0x72, 0xF2, 0xE0, 0x58, 0x65, 0x81, 0x48, 0x78, 0xBE, 0xB7, 0x34, - 0x72, 0x14, 0x20, 0x95, 0x0E, 0x78, 0x26, 0x25, 0x48, 0x63, 0xFB, 0xCE, 0x4D, 0xEF, 0xB6, 0xF3, - 0x1A, 0x7F, 0xC8, 0x2F, 0x47, 0xCD, 0xA7, 0xED, 0x29, 0x64, 0xDF, 0xA9, 0xE9, 0xC9, 0x35, 0x6E, - 0xF1, 0x22, 0x7B, 0xDA, 0x0D, 0xC0, 0x39, 0x03, 0x6D, 0x7B, 0xFE, 0xBC, 0x51, 0x26, 0x3B, 0xBE, - 0x69, 0xD6, 0x98, 0xE7, 0x8C, 0xA1, 0xE6, 0xFF, 0x7E, 0xCA, 0xB3, 0x46, 0x9C, 0xAD, 0x7C, 0x1E, - 0x33, 0x47, 0x3A, 0xF5, 0xF9, 0x93, 0x9C, 0x3D, 0xF4, 0xA4, 0xD8, 0x73, 0xB3, 0x1D, 0x4F, 0xA1, - 0xED, 0xA5, 0x4D, 0xC7, 0xCC, 0x2D, 0xD7, 0x71, 0x3D, 0x5D, 0xC3, 0x21, 0x1C, 0x67, 0x9E, 0xE8, - 0x1B, 0xEC, 0x42, 0xCA, 0x5D, 0x56, 0xBD, 0xD1, 0x9D, 0xEF, 0xF5, 0xB2, 0x09, 0x7B, 0x6E, 0x5C, - 0x35, 0x4A, 0x6C, 0x22, 0xE6, 0x8F, 0xBB, 0xC4, 0x3D, 0xBC, 0x53, 0x0C, 0xD0, 0xAF, 0x0C, 0x70, - 0x51, 0x15, 0xE0, 0x67, 0x09, 0x60, 0xA3, 0x18, 0xE0, 0xFC, 0x64, 0x3F, 0x4D, 0xE1, 0xA1, 0xC6, - 0xFB, 0x1B, 0x43, 0xF6, 0x8C, 0x98, 0xEA, 0xAD, 0xBE, 0x3B, 0x53, 0x45, 0xD4, 0x69, 0x6F, 0xEE, - 0x14, 0x01, 0xF4, 0x2B, 0x03, 0x5C, 0x54, 0x05, 0x90, 0x45, 0x14, 0x8F, 0xCB, 0x6C, 0x00, 0x55, - 0x44, 0x31, 0x85, 0x87, 0x59, 0x9E, 0x5C, 0x40, 0x4A, 0x01, 0x73, 0xE9, 0x22, 0x43, 0xC5, 0x88, - 0x75, 0x24, 0x42, 0x5B, 0x78, 0xCC, 0x39, 0x0E, 0xE8, 0x60, 0xB3, 0xD3, 0x29, 0x82, 0xEB, 0x4A, - 0x70, 0xCF, 0x11, 0x0E, 0xC0, 0xBA, 0xA6, 0x66, 0x49, 0x6E, 0x64, 0xAE, 0xF6, 0x1A, 0xAA, 0xF7, - 0x2B, 0x56, 0xBF, 0xA8, 0x56, 0x5D, 0xEE, 0x94, 0x5E, 0x51, 0xF5, 0x94, 0xD6, 0x9A, 0xEA, 0xA7, - 0xDD, 0x47, 0xFC, 0xAD, 0xDB, 0x59, 0x5F, 0x97, 0x61, 0x3B, 0x89, 0x61, 0x7E, 0x48, 0x99, 0x26, - 0x71, 0xA9, 0xF3, 0x87, 0x61, 0x7A, 0x02, 0x86, 0x29, 0x0F, 0xE2, 0xFC, 0xD7, 0x93, 0xCB, 0xF3, - 0xBD, 0x5F, 0x7E, 0x2D, 0xCD, 0x13, 0x02, 0xF4, 0xDF, 0x9E, 0xBF, 0xF9, 0xF5, 0x87, 0xF1, 0xAB, - 0x6C, 0xFC, 0xB2, 0x20, 0xF4, 0x71, 0xD6, 0xDD, 0x2E, 0x49, 0x4A, 0x07, 0xEC, 0x75, 0x6A, 0x02, - 0x6E, 0xF4, 0xEA, 0x02, 0x6E, 0x35, 0x32, 0x5D, 0xB5, 0x1F, 0x16, 0xFE, 0x5F, 0xC1, 0xC2, 0x9B, - 0xC0, 0x53, 0x6B, 0x6C, 0x49, 0x6F, 0x4D, 0xE9, 0xCB, 0xCA, 0x81, 0x33, 0xED, 0xAD, 0x0F, 0xCE, - 0x74, 0x78, 0x06, 0xF0, 0xAD, 0xCC, 0xDC, 0x6B, 0x06, 0xD7, 0x1B, 0x61, 0x8C, 0x93, 0x9B, 0xBA, - 0x9E, 0x7F, 0x42, 0x13, 0x1C, 0x5B, 0xD2, 0x20, 0xDB, 0x97, 0xDD, 0x4E, 0x67, 0xB3, 0xAC, 0xBD, - 0x97, 0xA1, 0x9E, 0x6F, 0xD4, 0x82, 0x7A, 0xDE, 0x48, 0xAD, 0xDE, 0x8B, 0xA1, 0x5E, 0xD4, 0xA2, - 0xF5, 0x42, 0xA3, 0x55, 0x12, 0x6C, 0xBB, 0x16, 0xB1, 0xED, 0x3A, 0x0D, 0xEB, 0xF6, 0xEA, 0xD0, - 0xEA, 0xF6, 0xEA, 0xD0, 0xEA, 0xAD, 0x2B, 0xD3, 0x41, 0x59, 0x79, 0x6C, 0x74, 0x9E, 0xF7, 0x14, - 0x6B, 0x5B, 0x92, 0x1E, 0x83, 0xEB, 0x36, 0x32, 0xB6, 0x6A, 0x66, 0x72, 0x0B, 0xE2, 0x25, 0x39, - 0x1F, 0xAA, 0xAA, 0xFA, 0x16, 0xCC, 0x56, 0x12, 0x5C, 0x86, 0xFF, 0x5A, 0x0C, 0xA8, 0x6A, 0x7E, - 0x79, 0xB8, 0x17, 0x35, 0xE1, 0xB6, 0xEB, 0xC1, 0x69, 0xCA, 0x35, 0xB7, 0xD9, 0x38, 0x6B, 0x67, - 0xA8, 0xEE, 0x9C, 0xA1, 0x77, 0x65, 0x35, 0xA3, 0xAD, 0x93, 0xAE, 0x01, 0x7D, 0xD2, 0x3F, 0xD9, - 0xA8, 0x6A, 0xED, 0x8F, 0xBD, 0x3B, 0x34, 0xB3, 0x77, 0x8E, 0x1D, 0xDE, 0xFC, 0xD1, 0x2D, 0x7E, - 0xA7, 0x96, 0xC9, 0xEF, 0x3D, 0xA2, 0xC9, 0xEF, 0x3D, 0xA6, 0xC9, 0xEF, 0x3D, 0xA2, 0xC9, 0xEF, - 0xFD, 0x30, 0xF9, 0x33, 0x9B, 0xFC, 0xDE, 0x63, 0x9B, 0xFC, 0x5E, 0x4D, 0x93, 0xDF, 0xAB, 0x69, - 0xF2, 0x7B, 0x35, 0x4D, 0x7E, 0xEF, 0x91, 0x4C, 0x7E, 0x67, 0xF3, 0x3F, 0xB7, 0xCA, 0xC8, 0xB5, - 0xFC, 0x8C, 0x51, 0x06, 0x58, 0x58, 0x6D, 0xA5, 0xB1, 0xFF, 0x32, 0x33, 0xCD, 0x34, 0x60, 0x6F, - 0x1C, 0x26, 0x97, 0x68, 0x82, 0xF4, 0xED, 0x12, 0xFE, 0x58, 0x5D, 0x22, 0x01, 0x8A, 0x7F, 0xEF, - 0xA4, 0xEB, 0x7C, 0xD2, 0xEA, 0x7C, 0x32, 0xD4, 0xF9, 0x4D, 0xAB, 0xF3, 0xDB, 0x8E, 0xBC, 0x8B, - 0x07, 0xDC, 0xBC, 0xA3, 0x9E, 0x4D, 0x43, 0x67, 0x90, 0xCB, 0x51, 0xFA, 0xBE, 0xCB, 0x50, 0x80, - 0x41, 0x49, 0xF1, 0x7D, 0x96, 0xB8, 0xB2, 0xE7, 0x6A, 0x95, 0xDF, 0xEF, 0x1D, 0xEE, 0x9D, 0xED, - 0x1B, 0xAA, 0xEE, 0x8D, 0x42, 0xD1, 0xEB, 0x6A, 0x52, 0x98, 0xB1, 0xE5, 0x7F, 0x55, 0x32, 0xC2, - 0x74, 0x0B, 0xD2, 0xBE, 0x14, 0x80, 0xF7, 0x4C, 0xE0, 0xFC, 0xEA, 0xB7, 0xA0, 0x6F, 0xD9, 0xFF, - 0x31, 0x0D, 0x42, 0x60, 0x54, 0x0F, 0x05, 0x62, 0xA7, 0xB5, 0xA7, 0xF4, 0xEE, 0xD8, 0x4B, 0x6E, - 0x08, 0xA5, 0x32, 0xA8, 0x24, 0x75, 0x0C, 0x81, 0x51, 0xF4, 0x9B, 0x13, 0x6A, 0xE9, 0x10, 0x6E, - 0x1C, 0x9B, 0xA5, 0x2B, 0x74, 0xDC, 0x33, 0x96, 0x86, 0x86, 0x37, 0x02, 0x63, 0xD7, 0x30, 0xD7, - 0x1A, 0x78, 0x29, 0x47, 0xEE, 0x99, 0xEF, 0xE1, 0xED, 0xFD, 0x38, 0x49, 0x84, 0x4E, 0x13, 0xB1, - 0xEE, 0xB9, 0xB6, 0x1C, 0x8D, 0x85, 0xD5, 0xB8, 0x8F, 0xC3, 0x93, 0x71, 0x82, 0xA0, 0x93, 0x3F, - 0x96, 0x12, 0x36, 0x58, 0x9E, 0xC8, 0x8E, 0x29, 0x7C, 0x6B, 0xDF, 0x1B, 0x4F, 0x46, 0x34, 0x4C, - 0x12, 0x27, 0xB1, 0x18, 0xB5, 0x08, 0x83, 0x8C, 0x5B, 0x90, 0x33, 0x37, 0x84, 0x7F, 0x4D, 0x37, - 0x44, 0x6B, 0x64, 0x44, 0xAD, 0x11, 0xDD, 0xEC, 0xDA, 0xB7, 0x46, 0x98, 0x56, 0xF5, 0xEE, 0x86, - 0xF2, 0xCB, 0x5D, 0x87, 0xFD, 0xB3, 0xF5, 0x1E, 0xB9, 0xB1, 0x02, 0xBC, 0x2B, 0x75, 0xED, 0xF8, - 0x63, 0x28, 0xF4, 0x41, 0xBF, 0x9D, 0x49, 0x48, 0xBC, 0x6B, 0x1E, 0x29, 0x8D, 0x8B, 0xFE, 0x44, - 0x38, 0xE4, 0xDA, 0xF7, 0xC6, 0x64, 0xEF, 0x8C, 0x03, 0x0C, 0xC9, 0x04, 0xB8, 0x92, 0x22, 0xF5, - 0x38, 0x16, 0xCC, 0xA5, 0x70, 0xCE, 0xD1, 0x48, 0x87, 0xF4, 0x07, 0xC0, 0x89, 0x3F, 0x76, 0x5C, - 0x0A, 0xF4, 0x9D, 0xC1, 0x0D, 0x49, 0x34, 0x00, 0xB3, 0x7E, 0x22, 0x3B, 0x9E, 0xEF, 0x0C, 0x61, - 0xEC, 0x8C, 0x18, 0xE1, 0xD8, 0x33, 0x8C, 0xB2, 0x33, 0x44, 0x42, 0xFF, 0xD3, 0x2E, 0x71, 0xA7, - 0xA3, 0xD1, 0xB2, 0x1E, 0x5D, 0x18, 0x49, 0x51, 0xAB, 0x5F, 0x26, 0x69, 0x03, 0xFF, 0xF6, 0x92, - 0xEC, 0x8D, 0x46, 0xA4, 0x0F, 0xDF, 0xED, 0xFC, 0xD4, 0x7D, 0x9E, 0x1B, 0x78, 0x23, 0xDA, 0x1E, - 0x81, 0xC6, 0x36, 0x3E, 0xF2, 0x1B, 0xA9, 0x04, 0xFE, 0x03, 0x39, 0x81, 0xD0, 0xD2, 0x32, 0x30, - 0x27, 0xF1, 0xB8, 0x8E, 0x93, 0x32, 0x8E, 0x3C, 0xCB, 0xFE, 0xC5, 0x72, 0x42, 0xE5, 0x22, 0x3A, - 0x66, 0x02, 0x11, 0x2F, 0x01, 0x04, 0xD3, 0xAB, 0xB1, 0x13, 0x46, 0x49, 0x10, 0x31, 0x63, 0x08, - 0x0C, 0x36, 0x2C, 0x0F, 0x3E, 0x77, 0xBE, 0x24, 0x71, 0xED, 0x38, 0x65, 0x89, 0xD8, 0x76, 0x97, - 0xDE, 0x11, 0xBC, 0x05, 0x28, 0x27, 0xB5, 0x88, 0x8A, 0xDB, 0xD6, 0x64, 0xC2, 0x07, 0x55, 0x1A, - 0x6D, 0x8B, 0x91, 0x5D, 0x4E, 0x70, 0x5A, 0xFF, 0x61, 0x7D, 0x13, 0xF8, 0x7E, 0x3D, 0x39, 0x7E, - 0x1F, 0x62, 0xCA, 0xB1, 0x7F, 0x4C, 0x69, 0x10, 0x46, 0x58, 0xB1, 0x42, 0xDB, 0x03, 0x84, 0x4B, - 0x8D, 0xB3, 0x0F, 0xFD, 0x0B, 0xCC, 0x61, 0xB2, 0x36, 0x65, 0x2D, 0x8A, 0x10, 0x37, 0xE4, 0x9A, - 0x6C, 0x68, 0x45, 0x9C, 0x44, 0x23, 0x8F, 0x9B, 0x31, 0x59, 0x1A, 0x86, 0x58, 0xCB, 0x57, 0x57, - 0xFE, 0x6B, 0x5E, 0xE8, 0xE0, 0x1D, 0xBE, 0x89, 0x92, 0x40, 0xAA, 0xB1, 0x93, 0x23, 0xDA, 0x7E, - 0x68, 0x85, 0xD3, 0x00, 0xC3, 0x9B, 0x55, 0x83, 0x9C, 0x4F, 0x10, 0xAA, 0xE7, 0x21, 0x4D, 0x0D, - 0x64, 0x3E, 0xEC, 0xCC, 0x95, 0x1A, 0x99, 0x83, 0x59, 0x21, 0xE0, 0xF9, 0x43, 0x1A, 0x9E, 0x59, - 0x8E, 0x0F, 0x33, 0x22, 0x1A, 0x57, 0x75, 0x06, 0xB9, 0x0A, 0xDD, 0xB7, 0xAC, 0x06, 0x2F, 0x33, - 0x88, 0x08, 0xB5, 0x97, 0xE5, 0xF5, 0x09, 0x18, 0x2E, 0x2F, 0x0C, 0xA9, 0xDB, 0x96, 0x72, 0x12, - 0x4C, 0x28, 0xF5, 0x4F, 0xF6, 0xF6, 0x03, 0x1D, 0xEE, 0xD4, 0x73, 0x69, 0x56, 0x64, 0x2A, 0xA3, - 0x78, 0x18, 0x4C, 0x4E, 0xBD, 0xBB, 0x33, 0x00, 0x0F, 0x0C, 0xE6, 0x17, 0x18, 0x63, 0x46, 0x52, - 0xCF, 0x09, 0x37, 0x8C, 0x4C, 0x94, 0x28, 0x30, 0x70, 0xCC, 0xE0, 0x58, 0xA8, 0x8E, 0x48, 0xDE, - 0x95, 0x15, 0x21, 0x2B, 0xE3, 0x49, 0x58, 0x88, 0xC3, 0x15, 0x2C, 0xDB, 0x3E, 0xBC, 0x85, 0x5F, - 0x30, 0x4C, 0x99, 0x02, 0xFE, 0xA5, 0xC6, 0xC1, 0x87, 0x13, 0xB0, 0xC5, 0x21, 0x7E, 0x83, 0x8E, - 0xA0, 0x98, 0x1E, 0x6F, 0x89, 0x62, 0x95, 0x65, 0xB2, 0xFB, 0x1A, 0x18, 0x8C, 0x35, 0x5C, 0x08, - 0xAC, 0x44, 0xEC, 0x43, 0x3A, 0xC9, 0x98, 0x12, 0xF1, 0xC0, 0xEE, 0xD2, 0xA3, 0x53, 0xCF, 0x6E, - 0xED, 0xC1, 0x2F, 0x1C, 0x73, 0x1C, 0xF1, 0xE0, 0x60, 0x18, 0x84, 0xF5, 0x0D, 0x7E, 0x51, 0x43, - 0x1F, 0x78, 0xB5, 0xCF, 0xCE, 0x97, 0xB6, 0xE7, 0x0E, 0x46, 0xCE, 0x00, 0xD3, 0x7C, 0xC4, 0xB2, - 0x5D, 0x4A, 0xBD, 0xD9, 0xAC, 0xA6, 0xDF, 0xCB, 0x78, 0x89, 0x95, 0xBB, 0x58, 0x56, 0x30, 0xF5, - 0x59, 0xD0, 0x34, 0x3A, 0xC2, 0xEF, 0x7F, 0x07, 0xE1, 0xA7, 0xE5, 0xC4, 0xF1, 0xE1, 0xC0, 0x37, - 0x92, 0x34, 0x20, 0xEA, 0xD3, 0x81, 0xBA, 0x6D, 0x42, 0xD6, 0x32, 0xE9, 0x49, 0xC1, 0xD8, 0x0F, - 0xF2, 0x68, 0x37, 0xA2, 0x9C, 0x07, 0x73, 0x09, 0xD5, 0x3C, 0xDE, 0xA4, 0x26, 0x18, 0x98, 0x33, - 0x3C, 0x0C, 0x5F, 0x99, 0xB5, 0x7A, 0x8F, 0xCC, 0x27, 0x76, 0x24, 0x10, 0xF5, 0xCD, 0x2F, 0xFD, - 0x72, 0x3B, 0xC2, 0x3C, 0xBF, 0xCC, 0x27, 0x79, 0x4D, 0x2D, 0x7A, 0x8B, 0x10, 0xF3, 0x68, 0x4E, - 0x84, 0xA8, 0x54, 0x5B, 0x32, 0xF8, 0x4C, 0x1A, 0x92, 0xDD, 0x58, 0x43, 0x5B, 0xF2, 0x5F, 0x3C, - 0xAF, 0xDD, 0xB2, 0x99, 0x1E, 0x52, 0xE7, 0xED, 0xC4, 0x75, 0x41, 0x5E, 0x33, 0x87, 0xF1, 0x12, - 0xA1, 0x7E, 0x33, 0xDF, 0xB1, 0x8C, 0x4E, 0xF3, 0x6E, 0xE5, 0x3B, 0x3D, 0x4F, 0x94, 0xA9, 0x91, - 0xBC, 0x11, 0xD9, 0x8D, 0xE4, 0x42, 0x48, 0x37, 0x52, 0xA9, 0x94, 0xB5, 0xD3, 0x97, 0x5A, 0x5F, - 0xD7, 0xD8, 0xD2, 0x53, 0x9E, 0x09, 0x32, 0xE6, 0x71, 0x97, 0x8E, 0x44, 0x5F, 0xB4, 0x37, 0xF1, - 0x74, 0x73, 0x0F, 0x9C, 0x5B, 0x98, 0x8A, 0xD1, 0x6F, 0x3B, 0xEE, 0xAE, 0x1D, 0xF7, 0x14, 0x64, - 0x0F, 0xEA, 0x45, 0xA4, 0xC2, 0xED, 0x81, 0xDB, 0xF4, 0x6D, 0xD7, 0xD2, 0xFC, 0x6C, 0xB7, 0xB7, - 0xE6, 0xC8, 0x4F, 0x7A, 0xBF, 0xA8, 0x0A, 0x33, 0xDD, 0xEE, 0xD6, 0x5C, 0xA5, 0xA3, 0xA7, 0x16, - 0xAE, 0xC2, 0xCB, 0x06, 0xEE, 0x5B, 0xD4, 0x60, 0xA5, 0x1E, 0x35, 0x65, 0x73, 0x45, 0xC5, 0x6C, - 0x18, 0xA3, 0xA6, 0x77, 0xCE, 0x6B, 0x0F, 0xCD, 0x8A, 0x8F, 0xA6, 0x27, 0x23, 0xCE, 0x70, 0x39, - 0x38, 0xF3, 0xFA, 0xB2, 0x69, 0x44, 0x97, 0x80, 0xCF, 0x6A, 0x75, 0xFC, 0x3A, 0xCD, 0x3C, 0x5A, - 0x5D, 0xE6, 0xA9, 0x1B, 0xAD, 0xD5, 0x1C, 0xA4, 0x7E, 0xAB, 0xF3, 0xE1, 0x0D, 0xAD, 0xD6, 0xAE, - 0x8B, 0xCD, 0xDE, 0xF2, 0x34, 0xC2, 0x82, 0xD6, 0x1B, 0x2E, 0xA6, 0x01, 0x90, 0x48, 0x12, 0xAF, - 0x45, 0xC1, 0x16, 0x8A, 0xA2, 0x10, 0x99, 0xBA, 0x71, 0x67, 0x10, 0x0B, 0x2E, 0xE3, 0x30, 0x27, - 0x2A, 0x66, 0xFD, 0x75, 0xE9, 0x68, 0x16, 0x81, 0xA4, 0x51, 0xC5, 0x59, 0x4D, 0x3A, 0x66, 0x1D, - 0x88, 0x20, 0xDE, 0x58, 0x53, 0xFB, 0xC0, 0xF7, 0x26, 0x36, 0x66, 0x86, 0x32, 0x4E, 0xBD, 0xCA, - 0x83, 0x69, 0x85, 0xFA, 0x52, 0x82, 0xA3, 0xAE, 0x79, 0x76, 0x2C, 0xC3, 0x91, 0x70, 0x16, 0x2A, - 0x71, 0x54, 0x97, 0x56, 0x85, 0xD6, 0x1B, 0xB4, 0x3D, 0xFB, 0x09, 0xC3, 0x19, 0xB5, 0xBE, 0xF0, - 0x6D, 0x44, 0x73, 0x7F, 0x4F, 0xC0, 0x4C, 0xF1, 0xC7, 0x71, 0x6B, 0x09, 0xAC, 0x18, 0x5C, 0x91, - 0xC1, 0x34, 0xA0, 0xC7, 0xDE, 0xC0, 0x1A, 0x39, 0xBF, 0x53, 0xFB, 0x00, 0xDA, 0xE9, 0x3B, 0x57, - 0x53, 0x9E, 0x46, 0xB2, 0x7E, 0xF3, 0x73, 0x70, 0xE6, 0xB6, 0x7C, 0x64, 0x02, 0xBA, 0x80, 0x15, - 0xE0, 0x31, 0xAC, 0x69, 0x47, 0xA6, 0xDE, 0x2F, 0x21, 0x8F, 0xBA, 0x48, 0x0D, 0x9A, 0xA2, 0xBF, - 0xA4, 0x38, 0xA3, 0x7E, 0x54, 0x78, 0x98, 0x31, 0x77, 0x44, 0x1D, 0xD0, 0xD0, 0x72, 0x46, 0x41, - 0x45, 0xB9, 0x54, 0x41, 0x94, 0x23, 0x8B, 0xF7, 0x96, 0x6F, 0xE3, 0x56, 0x10, 0x17, 0x44, 0xFC, - 0xC2, 0xCC, 0x9C, 0x44, 0x93, 0x81, 0xBD, 0x92, 0xA4, 0x64, 0xD8, 0xD9, 0x44, 0x55, 0x0A, 0x93, - 0x49, 0x56, 0x6C, 0x63, 0x69, 0x0E, 0x52, 0x89, 0xF0, 0x94, 0x6A, 0x3F, 0xDB, 0x71, 0xA9, 0xD7, - 0xE0, 0x7C, 0x50, 0x93, 0xC7, 0x20, 0x6D, 0xD9, 0xCD, 0xC1, 0x5D, 0x50, 0xB1, 0x65, 0xD8, 0x0C, - 0xC3, 0x6E, 0xE1, 0x6C, 0x3E, 0x42, 0x2E, 0xB2, 0x42, 0x1F, 0x41, 0x79, 0x78, 0x6D, 0x46, 0x01, - 0x14, 0x3F, 0xDF, 0x26, 0x1B, 0x4D, 0xDF, 0xAA, 0xD7, 0xCB, 0xB9, 0x90, 0xC6, 0xB6, 0xD5, 0x1E, - 0xDD, 0xC8, 0xEA, 0x7B, 0x20, 0xAA, 0x0E, 0x9E, 0x68, 0x63, 0x2F, 0x9B, 0xD6, 0xF9, 0xD1, 0xE9, - 0xE1, 0xAF, 0xF3, 0x90, 0xA7, 0x82, 0xAD, 0x9C, 0xF9, 0x48, 0x41, 0xD6, 0x34, 0x1E, 0xE5, 0xF1, - 0x18, 0xE4, 0xA0, 0x3C, 0xDB, 0x35, 0xA3, 0x14, 0xCA, 0x3E, 0x01, 0xA6, 0xCB, 0x20, 0x81, 0x9B, - 0x45, 0x02, 0x25, 0xB0, 0x98, 0xDA, 0x6F, 0x7A, 0xD7, 0x6B, 0x56, 0x39, 0x54, 0x7C, 0x2B, 0x2C, - 0x25, 0x0F, 0x80, 0x1F, 0x5B, 0xA1, 0x33, 0x50, 0x91, 0xCC, 0x24, 0x9C, 0x8A, 0x28, 0x33, 0x24, - 0x15, 0xBD, 0x04, 0x36, 0x07, 0x01, 0x95, 0x78, 0x54, 0x2C, 0x53, 0x2E, 0x0C, 0x76, 0x2E, 0xE2, - 0xC8, 0xC7, 0x94, 0xDE, 0x4A, 0xDC, 0x1B, 0x85, 0x4E, 0x38, 0xB5, 0x6B, 0x29, 0x89, 0x72, 0x74, - 0x9F, 0x42, 0xAF, 0x3F, 0xC8, 0xB8, 0x28, 0x02, 0xA9, 0x4D, 0x9B, 0x39, 0x93, 0x51, 0x03, 0x29, - 0xE6, 0x88, 0x3C, 0xBE, 0x0F, 0x7B, 0xCF, 0xEF, 0xC3, 0xDE, 0x93, 0x57, 0xC4, 0x9D, 0x8E, 0xF7, - 0x53, 0xEF, 0x6A, 0x42, 0x51, 0xFA, 0x56, 0x2C, 0xB8, 0xE5, 0xA1, 0xE7, 0x8A, 0x4B, 0xB1, 0xEC, - 0xA9, 0x0D, 0xCC, 0xAA, 0xF2, 0x86, 0x7D, 0xC5, 0xE7, 0x10, 0xEE, 0x95, 0xC0, 0x9A, 0xA4, 0xB6, - 0xB1, 0x09, 0x78, 0xBC, 0x94, 0xD9, 0x82, 0x28, 0xE3, 0x4B, 0x82, 0x7F, 0x1F, 0xEB, 0x2F, 0xDD, - 0xCB, 0xEA, 0x25, 0xBD, 0x6A, 0xB0, 0x2C, 0x07, 0x71, 0x64, 0x4C, 0x63, 0x52, 0x4A, 0xA4, 0x6A, - 0x51, 0x55, 0x05, 0xCF, 0x62, 0x96, 0x98, 0x99, 0x04, 0x0F, 0x27, 0x0C, 0xFB, 0x2C, 0x53, 0x53, - 0x01, 0x22, 0x63, 0x88, 0xC0, 0xDC, 0xD8, 0x9F, 0x03, 0xE3, 0x26, 0x96, 0x95, 0x58, 0xAA, 0xBC, - 0xB4, 0x3D, 0x39, 0x09, 0x85, 0x32, 0x74, 0x58, 0xBB, 0xD9, 0x5D, 0x5F, 0xFB, 0x93, 0x5C, 0xA2, - 0xD9, 0x59, 0x88, 0xEE, 0x59, 0xBA, 0xB9, 0x6F, 0xA6, 0xDD, 0xE5, 0x32, 0x83, 0xE7, 0xDB, 0x8E, - 0x69, 0x9B, 0x58, 0x1E, 0x44, 0x98, 0xD5, 0x58, 0x1C, 0x24, 0xB3, 0x8C, 0xC2, 0x1A, 0x2B, 0x58, - 0x09, 0xB9, 0x28, 0xD8, 0x35, 0x56, 0xD3, 0x59, 0x19, 0xC6, 0x18, 0x7E, 0xE3, 0x7F, 0x27, 0xF1, - 0x32, 0xE4, 0xC8, 0x1D, 0xF8, 0x2C, 0xCA, 0x61, 0x22, 0xF2, 0x3C, 0x91, 0x55, 0x12, 0xDC, 0x59, - 0x13, 0xFE, 0x26, 0x32, 0x3B, 0xA0, 0x86, 0xF9, 0x27, 0xE1, 0x89, 0x04, 0x8C, 0x27, 0x9E, 0xF6, - 0x02, 0xEB, 0xB8, 0x98, 0x92, 0xF9, 0x06, 0xEC, 0x32, 0x0D, 0x92, 0x97, 0x22, 0x13, 0x52, 0xE4, - 0xB5, 0xBA, 0xB3, 0xC6, 0x2E, 0xE1, 0x5B, 0x5F, 0xE9, 0x09, 0x7D, 0x8F, 0x30, 0xFE, 0x8E, 0xA1, - 0x84, 0x25, 0xA1, 0xDB, 0x49, 0xF7, 0x6E, 0x65, 0xBD, 0x28, 0xD3, 0xBB, 0xDF, 0x58, 0xEF, 0xA6, - 0x65, 0x23, 0xFF, 0x93, 0x19, 0x4E, 0x32, 0x52, 0x99, 0x4F, 0x06, 0xCA, 0xD1, 0x93, 0x25, 0xB4, - 0x4A, 0xBA, 0xCB, 0xD9, 0x54, 0x99, 0x30, 0xF2, 0x88, 0x3E, 0xCC, 0x51, 0x50, 0xCC, 0x64, 0xCA, - 0xAD, 0x35, 0xF1, 0x55, 0xD0, 0xBA, 0x55, 0xBC, 0x44, 0x23, 0xAB, 0x56, 0x81, 0xB0, 0x24, 0x9A, - 0xAC, 0xAD, 0x26, 0x92, 0x80, 0xED, 0xD4, 0x0B, 0xE9, 0x4B, 0xD2, 0x28, 0x20, 0xBE, 0x02, 0xC4, - 0x1B, 0xC4, 0x73, 0x47, 0xF7, 0xE4, 0xCE, 0xF3, 0xBF, 0x06, 0x11, 0xB3, 0xF0, 0xB7, 0x73, 0x6D, - 0x42, 0x9B, 0x83, 0x8F, 0x3D, 0xED, 0xE1, 0xB8, 0x61, 0x8B, 0xBD, 0x18, 0x1E, 0xB0, 0xAC, 0xC9, - 0x6D, 0xF2, 0x11, 0xC7, 0x8A, 0xE5, 0xE3, 0xE3, 0x52, 0x21, 0x8E, 0x15, 0x4A, 0x89, 0x75, 0xE5, - 0xDD, 0xD2, 0xAA, 0x62, 0x5A, 0x89, 0xC4, 0x74, 0x40, 0x73, 0xC5, 0xF4, 0xA0, 0x64, 0xDA, 0x20, - 0x47, 0xD7, 0xC4, 0x1A, 0x41, 0x7D, 0xFB, 0x9E, 0x8D, 0x3E, 0x31, 0xF0, 0xE2, 0xD1, 0xDB, 0x62, - 0x92, 0x24, 0x4E, 0x48, 0x46, 0x20, 0x4B, 0x31, 0x22, 0x35, 0x4B, 0xCE, 0x82, 0x48, 0xF6, 0xC6, - 0xEF, 0x39, 0xE8, 0xE3, 0x8E, 0x33, 0xB4, 0x05, 0xD8, 0x8C, 0x0E, 0x71, 0x02, 0xF2, 0x5E, 0xB2, - 0x1A, 0x0A, 0xAA, 0x98, 0xB9, 0xB4, 0xDE, 0xE3, 0xBF, 0x2B, 0x68, 0xFF, 0xD7, 0xC7, 0x19, 0x0E, - 0xF8, 0x84, 0x40, 0xCC, 0xCD, 0x82, 0x07, 0x43, 0xC6, 0x99, 0x62, 0x61, 0x82, 0x3C, 0x63, 0x9B, - 0xD0, 0xAA, 0x30, 0xC2, 0xC7, 0x89, 0x1E, 0x64, 0x2B, 0x57, 0xD5, 0xD4, 0x7A, 0xE8, 0xF6, 0xED, - 0x1F, 0xBE, 0x8D, 0xA7, 0x6E, 0xF9, 0xF9, 0xAF, 0xF8, 0xCA, 0x87, 0x0B, 0x93, 0x0E, 0xC6, 0x33, - 0x61, 0xCD, 0xF8, 0xF4, 0xD3, 0xA7, 0x63, 0x18, 0x2C, 0x6F, 0x2C, 0x7B, 0x1F, 0x9F, 0x0C, 0x5D, - 0x4A, 0xD7, 0x89, 0x3C, 0x5A, 0xE3, 0x6B, 0xA4, 0x52, 0x6D, 0xF1, 0x16, 0x69, 0xEA, 0x51, 0xE8, - 0x8D, 0x6D, 0xF6, 0x1A, 0xA9, 0x05, 0xF3, 0x96, 0xFA, 0x24, 0x69, 0xA9, 0xB7, 0xD9, 0xA5, 0xA0, - 0xEE, 0x16, 0x59, 0x7D, 0x1E, 0xBD, 0xA9, 0xFA, 0x3C, 0xF5, 0xB8, 0x6A, 0x54, 0x86, 0x24, 0xC5, - 0xAF, 0xF5, 0x89, 0x7D, 0x7A, 0x4C, 0x62, 0xBF, 0xCD, 0x93, 0x58, 0xC6, 0x03, 0x70, 0xCA, 0x94, - 0x1F, 0xBD, 0xA0, 0x84, 0x3D, 0x47, 0xAC, 0xA1, 0x85, 0x2F, 0xF0, 0xF1, 0x67, 0x1D, 0x1C, 0x49, - 0x31, 0xF9, 0x33, 0x31, 0x36, 0xFD, 0xA6, 0xDE, 0x75, 0x61, 0x83, 0x78, 0x47, 0x94, 0xBC, 0xC2, - 0xC0, 0x61, 0xCF, 0xB7, 0x03, 0xA6, 0x2E, 0x51, 0xD0, 0xDB, 0xCA, 0x0A, 0x2B, 0xD5, 0x47, 0x27, - 0x22, 0x04, 0x43, 0x1D, 0x06, 0x4C, 0xEB, 0x62, 0xB0, 0xCF, 0xAC, 0xF2, 0x97, 0x28, 0x29, 0x33, - 0xD1, 0x73, 0xC1, 0x46, 0x5E, 0xB5, 0xA2, 0x6B, 0xD2, 0xA9, 0x1C, 0x43, 0x89, 0x99, 0x97, 0x0D, - 0x43, 0x35, 0x4D, 0x06, 0x87, 0x67, 0x7A, 0x18, 0xAC, 0x90, 0x26, 0x4B, 0x8C, 0x9A, 0x68, 0x5B, - 0x56, 0xC1, 0xA7, 0xAC, 0x82, 0xDF, 0xF4, 0xA4, 0xBB, 0x15, 0x8D, 0x23, 0x7F, 0x2D, 0x85, 0x89, - 0x7B, 0xD7, 0x20, 0xD5, 0xE5, 0x67, 0x19, 0xED, 0x6A, 0x4F, 0xA6, 0xC1, 0xCD, 0xD2, 0x42, 0xDB, - 0xB4, 0x6C, 0x48, 0xF8, 0x89, 0x84, 0x70, 0x8D, 0xA9, 0x1B, 0x22, 0x9B, 0x62, 0xEC, 0x6B, 0x6C, - 0x8B, 0xE2, 0x88, 0x4B, 0x40, 0x24, 0x02, 0x9B, 0x31, 0x32, 0x17, 0x6A, 0x4A, 0x77, 0x26, 0xE4, - 0x1E, 0x4D, 0xEE, 0x06, 0x22, 0xC4, 0x6B, 0x96, 0x54, 0x5A, 0x9D, 0x29, 0x4D, 0x2A, 0x04, 0x75, - 0xCD, 0x0A, 0x84, 0x00, 0x28, 0x1B, 0xB1, 0x1A, 0x88, 0x74, 0x45, 0x0A, 0x50, 0xE2, 0xD3, 0x24, - 0x8B, 0xDE, 0x5E, 0x6A, 0x1C, 0x30, 0xEE, 0x09, 0x1E, 0x92, 0xB1, 0xD6, 0xE0, 0x72, 0x21, 0x06, - 0x5F, 0x21, 0x8D, 0xBF, 0x36, 0x96, 0xB3, 0xB6, 0x7E, 0xE4, 0x2E, 0x41, 0x4E, 0x06, 0x14, 0x5B, - 0x00, 0x36, 0x31, 0x63, 0xED, 0x98, 0x2F, 0x46, 0x0C, 0x24, 0x56, 0x0C, 0xFA, 0x77, 0x94, 0x61, - 0xE6, 0xDD, 0x1A, 0x2E, 0xCD, 0xEE, 0x97, 0x8C, 0xAA, 0x9F, 0x52, 0x55, 0x7B, 0x59, 0x55, 0x7F, - 0x4B, 0x55, 0x5D, 0xD7, 0xAA, 0x9A, 0x47, 0xBF, 0xD4, 0xA1, 0xA6, 0xF7, 0xFB, 0x64, 0xAE, 0x0B, - 0x6A, 0x7C, 0x2A, 0xAC, 0xF1, 0x5B, 0x56, 0x0D, 0x95, 0x35, 0xE5, 0xA5, 0xBA, 0xF8, 0x51, 0x1D, - 0x49, 0xD0, 0xE0, 0xC5, 0xFA, 0x16, 0xF8, 0x85, 0x5C, 0x01, 0x88, 0xE5, 0xDA, 0x64, 0xEC, 0xB9, - 0x5E, 0x30, 0xB1, 0x60, 0x15, 0xC7, 0x62, 0xA4, 0x99, 0x19, 0xD6, 0x56, 0xEA, 0x89, 0xA2, 0x48, - 0x81, 0xD6, 0x99, 0x6A, 0x20, 0xF2, 0x79, 0x27, 0x53, 0x3F, 0x2A, 0x43, 0xDA, 0xA8, 0xA4, 0x66, - 0x06, 0xBE, 0x9F, 0x90, 0x85, 0x36, 0x69, 0xBE, 0xDC, 0x64, 0xBC, 0xAF, 0xA4, 0x87, 0x96, 0x4B, - 0xAF, 0xED, 0x60, 0x66, 0x46, 0xCF, 0xA7, 0x76, 0x23, 0xEF, 0x29, 0x4E, 0xB6, 0x13, 0x32, 0x33, - 0x59, 0x51, 0xFA, 0x92, 0xFC, 0xBA, 0xF6, 0x69, 0xED, 0xB7, 0x86, 0x9A, 0xFF, 0xDC, 0xD0, 0xFA, - 0x57, 0x64, 0x73, 0x39, 0x75, 0xEC, 0x95, 0x29, 0xD3, 0xC0, 0xF9, 0x9D, 0x12, 0x93, 0x69, 0x56, - 0xAC, 0x63, 0xEC, 0xE3, 0x26, 0x53, 0x67, 0xD5, 0xB9, 0x12, 0x07, 0xA8, 0x37, 0x61, 0x7D, 0x2F, - 0x05, 0xA8, 0xA3, 0xB7, 0x0A, 0x6A, 0x20, 0x12, 0x62, 0x37, 0x79, 0x05, 0x79, 0x98, 0xF2, 0x2F, - 0x6C, 0xEF, 0xC2, 0x38, 0xC1, 0xA6, 0x6A, 0x46, 0x63, 0x88, 0x15, 0xAB, 0xA3, 0x2D, 0x53, 0x08, - 0x98, 0x0D, 0x9C, 0x83, 0xAB, 0x93, 0xC2, 0x9F, 0x97, 0x1A, 0xFF, 0xCB, 0x0C, 0x24, 0xA8, 0x01, - 0x2C, 0xB5, 0x06, 0x37, 0x4B, 0xE6, 0x5D, 0x48, 0xD9, 0x26, 0xFD, 0x79, 0x29, 0xBC, 0x71, 0x02, - 0xBE, 0x09, 0xB3, 0xB4, 0x9C, 0x6B, 0xD5, 0x5D, 0xD5, 0xAA, 0xB7, 0x83, 0xE9, 0x15, 0x5F, 0x15, - 0x2E, 0x81, 0xFF, 0xD4, 0xDD, 0x54, 0x5E, 0x47, 0x97, 0x90, 0xC6, 0xA0, 0x30, 0xE1, 0xF1, 0x84, - 0xE8, 0x91, 0x25, 0x8B, 0xA7, 0xC0, 0xC8, 0x5E, 0x69, 0x1F, 0xD6, 0xBF, 0x70, 0x14, 0xC9, 0x66, - 0xAF, 0xE6, 0x84, 0x47, 0x37, 0x02, 0xCB, 0x39, 0xE2, 0x51, 0xED, 0x22, 0x67, 0x5C, 0xAD, 0x57, - 0xC6, 0x21, 0x8F, 0x20, 0xE6, 0xE5, 0x94, 0x27, 0xCF, 0x63, 0xE5, 0xBA, 0xB3, 0xF1, 0x81, 0x03, - 0x78, 0xB4, 0xDD, 0x6E, 0x67, 0x7D, 0xA3, 0x45, 0x5E, 0xBC, 0x50, 0xA8, 0xF3, 0xCF, 0xC8, 0x02, - 0x16, 0x54, 0x76, 0x9A, 0xF5, 0x73, 0x07, 0xA4, 0xB3, 0x89, 0x7D, 0xAD, 0x90, 0xD8, 0x64, 0x0F, - 0xE6, 0x6D, 0xD6, 0xC5, 0xAE, 0x1D, 0x3A, 0x00, 0x8D, 0x5E, 0xA7, 0xD3, 0xEE, 0xB0, 0x0B, 0x7E, - 0x6D, 0xC5, 0x33, 0x67, 0x1F, 0x90, 0x18, 0xFB, 0xE5, 0xC9, 0x79, 0xE5, 0xB1, 0xDE, 0x54, 0xF7, - 0xCC, 0x23, 0xD0, 0xAA, 0xDE, 0x79, 0xAC, 0x78, 0xD5, 0x3C, 0x74, 0x8D, 0x9C, 0xE4, 0xA5, 0x6B, - 0x63, 0x44, 0xF1, 0x51, 0xC5, 0xD5, 0x5A, 0x63, 0x91, 0xB8, 0x49, 0x6B, 0x2A, 0x8B, 0xB4, 0x54, - 0x2B, 0xD3, 0x74, 0xCB, 0x5C, 0xAA, 0xEA, 0xC6, 0x02, 0x7C, 0x7E, 0xAD, 0xCF, 0x8C, 0x7E, 0x7F, - 0x5C, 0x47, 0xF1, 0xFD, 0xFF, 0x00, 0x92, 0x32, 0xAD, 0x24, 0x22, 0xB6, 0xB3, 0x57, 0x13, 0x29, - 0xA3, 0x5A, 0xE4, 0x0C, 0xEB, 0x4A, 0x58, 0xD9, 0x21, 0x8E, 0xD5, 0xF1, 0xE9, 0x2C, 0x2C, 0xE2, - 0xDE, 0x2D, 0xBF, 0xB8, 0xC8, 0x93, 0xAC, 0x74, 0x72, 0x29, 0x2F, 0xD3, 0x6E, 0x2C, 0x7A, 0x42, - 0xC3, 0x1B, 0xCF, 0xCE, 0xBC, 0x1B, 0xA7, 0x5C, 0x8C, 0x4B, 0xAE, 0x84, 0xBF, 0x8C, 0x6E, 0x80, - 0xA7, 0x5E, 0x5E, 0x02, 0x94, 0x89, 0xFC, 0x25, 0xFC, 0x5A, 0x3C, 0x6D, 0xFA, 0x34, 0x36, 0x3B, - 0x76, 0xC9, 0x74, 0xC0, 0x9D, 0x19, 0x9C, 0x04, 0x24, 0xE1, 0x9B, 0x78, 0x8E, 0x28, 0xE3, 0xF2, - 0xFC, 0x32, 0x59, 0x25, 0x4B, 0x52, 0x95, 0xF4, 0xF1, 0xB6, 0xA8, 0xB6, 0x42, 0xD2, 0xB5, 0xCC, - 0x17, 0x0B, 0x96, 0xC9, 0x1A, 0xE9, 0xF2, 0x0B, 0xE1, 0x79, 0x6C, 0x47, 0x33, 0x3F, 0x70, 0xD9, - 0xC6, 0x38, 0x0C, 0x28, 0x5D, 0x5A, 0xCF, 0xBB, 0x87, 0x9C, 0x2B, 0xA7, 0x74, 0xCE, 0x85, 0x1C, - 0x31, 0x69, 0x42, 0x35, 0xCB, 0x49, 0x67, 0x15, 0x45, 0xF0, 0x88, 0x92, 0x4A, 0xE5, 0x38, 0x30, - 0xCB, 0x49, 0x5F, 0x3A, 0x3F, 0x59, 0x8B, 0x31, 0x1D, 0x9F, 0x09, 0x38, 0x06, 0xAF, 0xAC, 0x20, - 0x22, 0x8A, 0x71, 0xA5, 0xD7, 0xBB, 0x64, 0xCB, 0x34, 0x55, 0x8F, 0xAC, 0x30, 0xC2, 0x92, 0x54, - 0x5E, 0x25, 0x1B, 0x28, 0xC8, 0x9E, 0xE1, 0x35, 0xB8, 0xCC, 0xA9, 0xD9, 0xB0, 0x7C, 0x2E, 0x48, - 0x5D, 0x91, 0x5E, 0xF2, 0x47, 0x5C, 0xC7, 0x4C, 0xBD, 0x4E, 0xC7, 0xC9, 0x2B, 0x0B, 0xA3, 0x31, - 0xAC, 0x06, 0x23, 0xF6, 0xBB, 0x3B, 0xD2, 0x9F, 0xAF, 0xE2, 0x86, 0x49, 0x5F, 0xD3, 0xE7, 0x00, - 0x85, 0x5C, 0xAE, 0xEC, 0x2A, 0x3E, 0x7B, 0x42, 0x60, 0x85, 0xE8, 0x8C, 0xA7, 0xF7, 0xFC, 0x1F, - 0x32, 0x24, 0x91, 0x4E, 0xCC, 0x21, 0x44, 0x01, 0x58, 0x23, 0xB6, 0x9F, 0x96, 0x54, 0x74, 0x8E, - 0xF3, 0xC4, 0x92, 0xDD, 0x88, 0xD2, 0x12, 0x32, 0xD8, 0x34, 0x4E, 0x48, 0xD2, 0xD0, 0x75, 0x83, - 0xA2, 0x65, 0x18, 0x10, 0x13, 0x78, 0x2F, 0x1B, 0x3C, 0xF3, 0x72, 0x57, 0x0A, 0x49, 0xF7, 0x8B, - 0x76, 0x3B, 0xB1, 0x4E, 0x8E, 0x94, 0x28, 0xC9, 0x49, 0x05, 0x3C, 0xBD, 0x9C, 0x5C, 0x2B, 0x0A, - 0x1E, 0x25, 0xA6, 0x28, 0xEB, 0x91, 0x33, 0xC3, 0xA0, 0xDE, 0xC9, 0xAC, 0xAB, 0x8E, 0x92, 0xA2, - 0x7A, 0xB1, 0xDE, 0x14, 0x54, 0x4C, 0x3A, 0x3C, 0xBB, 0x62, 0xAA, 0x73, 0x0B, 0xAB, 0xEA, 0x1D, - 0x59, 0x32, 0x10, 0x46, 0xC9, 0xCE, 0x11, 0x70, 0xF3, 0x1E, 0x89, 0x86, 0x30, 0x6B, 0xCC, 0x57, - 0xE2, 0x19, 0x61, 0x31, 0xE9, 0x9D, 0xBA, 0x18, 0xB8, 0xD6, 0x6E, 0x9D, 0xEA, 0x79, 0xE5, 0xEE, - 0xD8, 0x49, 0x56, 0x39, 0x6F, 0xD7, 0x4E, 0x5B, 0x16, 0x94, 0xDE, 0xB9, 0x33, 0xE9, 0x87, 0xAE, - 0x3B, 0x0B, 0xDC, 0xC1, 0xAB, 0x49, 0x3E, 0xDE, 0xC9, 0x03, 0xAD, 0x5D, 0x43, 0x8D, 0x5C, 0x03, - 0x6D, 0x33, 0x6F, 0xE8, 0xE9, 0x82, 0x29, 0xB9, 0xA9, 0x27, 0x89, 0x5D, 0xDD, 0xD8, 0xD3, 0xD7, - 0xCC, 0x15, 0x37, 0xF7, 0xCA, 0x2C, 0xB9, 0xE7, 0xB9, 0xC1, 0xA7, 0x2D, 0x9C, 0x67, 0xDB, 0xE4, - 0x93, 0x84, 0x52, 0x6D, 0xA3, 0x2F, 0x1E, 0x2D, 0xDF, 0x75, 0xB3, 0x4F, 0x51, 0x0F, 0xD9, 0xBF, - 0x42, 0x4F, 0xEA, 0xB9, 0x3E, 0x63, 0xCE, 0x6D, 0x4B, 0x30, 0x35, 0x5F, 0xAA, 0x15, 0x36, 0x74, - 0x88, 0x4D, 0xFD, 0xC3, 0x56, 0x11, 0x8A, 0xE7, 0xCA, 0xB6, 0x63, 0xA1, 0x31, 0x5C, 0xC8, 0x66, - 0xA7, 0xA4, 0x03, 0x0F, 0xA9, 0x24, 0x57, 0xCA, 0xAE, 0xA5, 0x94, 0x73, 0x87, 0xBB, 0xDC, 0xF0, - 0x53, 0xEA, 0xD9, 0xF6, 0x7F, 0x78, 0x8E, 0xBB, 0xD4, 0x6C, 0xC6, 0x09, 0x87, 0xB4, 0x2A, 0xAD, - 0xE2, 0x2A, 0x7F, 0xFF, 0x7B, 0xAA, 0x8E, 0x4F, 0xC3, 0xA9, 0xEF, 0x32, 0x77, 0x5D, 0xE3, 0x6E, - 0x48, 0x43, 0x4C, 0x73, 0xA4, 0x98, 0x62, 0x96, 0x61, 0x0A, 0x4C, 0x16, 0x68, 0x4F, 0x54, 0x86, - 0x16, 0x95, 0x4F, 0xEB, 0x9A, 0x59, 0x53, 0xEA, 0x88, 0x15, 0x96, 0xB4, 0x69, 0x77, 0x74, 0xCD, - 0x36, 0xE9, 0x42, 0xEB, 0x8A, 0xDC, 0x59, 0x01, 0xC1, 0xB9, 0x9B, 0x60, 0x6A, 0x24, 0x6A, 0xB7, - 0x08, 0x1F, 0xD2, 0x58, 0x36, 0xA2, 0x3C, 0x87, 0x56, 0x30, 0xF0, 0xF1, 0x69, 0x1E, 0x6D, 0xA1, - 0x33, 0xA2, 0x27, 0x96, 0x6B, 0x0D, 0xA9, 0x7F, 0x81, 0x35, 0x53, 0x49, 0x90, 0x18, 0xFC, 0xEB, - 0x57, 0xA1, 0x4F, 0xAC, 0x91, 0x33, 0x74, 0x77, 0x9B, 0x23, 0x7A, 0x1D, 0x36, 0xE1, 0xC3, 0xCD, - 0x6B, 0xDC, 0x3F, 0x78, 0xB5, 0x06, 0xBF, 0xE0, 0x1F, 0x7D, 0x30, 0x64, 0xE2, 0x0F, 0xFB, 0xF5, - 0x2B, 0xFE, 0x98, 0x62, 0x78, 0x3F, 0xA1, 0xBB, 0xDC, 0xE3, 0xB8, 0xF2, 0xBE, 0x35, 0x89, 0x63, - 0xEF, 0x36, 0x91, 0x20, 0x5F, 0xCE, 0xEF, 0x8D, 0x46, 0x4D, 0xC2, 0xDE, 0xFA, 0x84, 0xAF, 0x9E, - 0x3F, 0x5E, 0x65, 0x15, 0x57, 0x39, 0xA8, 0xC4, 0x17, 0xDB, 0x99, 0x6C, 0x12, 0x11, 0xB8, 0xC8, - 0x31, 0x44, 0x2C, 0x7B, 0xC3, 0x21, 0x26, 0xA5, 0x01, 0x7E, 0xD6, 0x90, 0xEC, 0x5A, 0xE8, 0xC7, - 0x3F, 0x18, 0xDF, 0x92, 0xD9, 0x46, 0x30, 0xD6, 0xC4, 0x0B, 0x6E, 0xC3, 0x1A, 0x0D, 0x49, 0x94, - 0xDF, 0xC6, 0xA3, 0x9B, 0x30, 0x9C, 0xE4, 0x26, 0x9E, 0x92, 0xEA, 0x89, 0xFC, 0x53, 0xEF, 0x0E, - 0x79, 0xFA, 0x29, 0x9C, 0x85, 0x59, 0x76, 0xAC, 0x46, 0xDA, 0x3B, 0x8B, 0x20, 0x58, 0x56, 0x21, - 0xD9, 0x4E, 0x88, 0xB0, 0xB1, 0x81, 0x37, 0x46, 0x33, 0x12, 0x55, 0xF3, 0x69, 0x30, 0x01, 0x77, - 0x82, 0x31, 0xB9, 0x8C, 0x21, 0x3B, 0x22, 0xD7, 0x1A, 0xD9, 0xEF, 0xFF, 0xCC, 0xB3, 0xA3, 0x39, - 0x6E, 0xE8, 0xB1, 0xC9, 0xFF, 0x59, 0xF9, 0x8E, 0x04, 0xF7, 0x5B, 0x69, 0x7E, 0xC1, 0x64, 0xAA, - 0x6A, 0x5D, 0xE6, 0x2B, 0x47, 0xA0, 0xDC, 0x22, 0xEB, 0x68, 0x4A, 0xBF, 0xBD, 0xAB, 0xD0, 0x72, - 0x40, 0x0D, 0xA5, 0x72, 0xA3, 0x8E, 0x1B, 0xEB, 0xE9, 0x7A, 0x2E, 0xA5, 0x6F, 0xC4, 0x0A, 0xBA, - 0x8A, 0x4A, 0x7D, 0x2C, 0x6A, 0x49, 0x3D, 0x1C, 0x37, 0x0B, 0x73, 0xAC, 0x9D, 0x24, 0xCF, 0x38, - 0xA1, 0xFD, 0xFF, 0xFC, 0xC5, 0x5C, 0xCE, 0x36, 0xE4, 0x8D, 0x15, 0xA2, 0xD7, 0x79, 0x33, 0x31, - 0x44, 0x15, 0x14, 0x14, 0x73, 0xD4, 0xB2, 0x28, 0x8F, 0xF1, 0x77, 0x54, 0xB4, 0xAC, 0x9E, 0x58, - 0xD9, 0x95, 0xC5, 0xAF, 0x98, 0x29, 0x72, 0x4E, 0x27, 0x02, 0xBB, 0xE5, 0xDE, 0x73, 0x49, 0x45, - 0x95, 0xD9, 0x91, 0x43, 0xC0, 0x7C, 0xDB, 0x5B, 0x2E, 0xB4, 0x55, 0xE2, 0xB4, 0x69, 0x9B, 0x19, - 0x36, 0xF1, 0x05, 0x5D, 0x1F, 0xFC, 0x13, 0xDF, 0x4F, 0x20, 0xFC, 0x09, 0x09, 0x62, 0x8B, 0xDB, - 0xC2, 0x41, 0x6E, 0x84, 0x5F, 0xAA, 0xDB, 0xB3, 0x9E, 0x03, 0x13, 0xAD, 0x4B, 0xD5, 0xFF, 0xFC, - 0xED, 0x4B, 0xB2, 0x9E, 0x4B, 0x2B, 0xC9, 0x67, 0xD9, 0xEB, 0x79, 0x28, 0x6C, 0x73, 0x64, 0x0A, - 0xAB, 0x34, 0x1A, 0x53, 0x95, 0x12, 0x1E, 0x65, 0x9F, 0x20, 0xA0, 0x25, 0x9A, 0xAD, 0x28, 0x6B, - 0x5E, 0xBB, 0xD9, 0x84, 0x94, 0xD6, 0x5E, 0x11, 0xA4, 0xD9, 0xC0, 0xD1, 0x98, 0x95, 0x4D, 0x25, - 0x4D, 0x88, 0x09, 0x2C, 0x2B, 0x11, 0x6B, 0x4E, 0x16, 0x97, 0x1C, 0x06, 0x98, 0xA6, 0xD7, 0xE6, - 0x40, 0xDB, 0x69, 0xAC, 0x10, 0x69, 0x29, 0xAD, 0xEA, 0x54, 0x53, 0x47, 0x8E, 0x82, 0x60, 0x2A, - 0xA2, 0xDE, 0x8F, 0x0E, 0x5E, 0xB2, 0x0D, 0x75, 0x33, 0x1F, 0x55, 0xA2, 0xF4, 0x55, 0x1A, 0x6F, - 0xD8, 0xB3, 0xEB, 0xF9, 0x26, 0x15, 0xEB, 0x94, 0x35, 0xAB, 0xBC, 0x6E, 0x81, 0x69, 0xC5, 0x4A, - 0xF5, 0xCD, 0xEB, 0x93, 0xB1, 0x8E, 0xAC, 0x19, 0x4F, 0xC2, 0x42, 0xA6, 0x04, 0x5A, 0xD5, 0x4A, - 0xFE, 0xB0, 0x18, 0xFF, 0x12, 0x16, 0x83, 0x8D, 0x3E, 0x67, 0x11, 0x56, 0x43, 0xF2, 0xFB, 0x0E, - 0x60, 0x3A, 0xC4, 0x03, 0x88, 0x24, 0x43, 0xA8, 0xB8, 0xB1, 0x83, 0xCE, 0x5C, 0xF9, 0x84, 0x93, - 0x88, 0xF1, 0xE8, 0x40, 0x3A, 0x54, 0xE3, 0xEC, 0xB8, 0xEC, 0x44, 0xE5, 0xC3, 0x35, 0x43, 0xD6, - 0x8F, 0xEE, 0x02, 0xD5, 0x46, 0xAA, 0x6C, 0x71, 0x60, 0x29, 0x3F, 0xB1, 0x49, 0x22, 0x0B, 0x70, - 0x94, 0xBE, 0xE5, 0x29, 0x27, 0x61, 0x70, 0xF4, 0x31, 0x1F, 0x33, 0x66, 0x44, 0x05, 0xEB, 0x8B, - 0x25, 0x6A, 0x42, 0xE7, 0xB8, 0xAA, 0x64, 0x2F, 0x65, 0x9C, 0xBB, 0x66, 0xEE, 0x97, 0xC5, 0xCA, - 0x2D, 0x39, 0x2F, 0x9C, 0xFA, 0xA3, 0x10, 0x93, 0x94, 0xE0, 0x9A, 0xAF, 0xB1, 0x86, 0x28, 0xFE, - 0xCA, 0xD8, 0x67, 0x7D, 0x25, 0x4B, 0xF3, 0x73, 0x82, 0x1E, 0x5F, 0x0B, 0xC5, 0x63, 0xD4, 0x9F, - 0x2C, 0xC6, 0xCD, 0xAE, 0x2D, 0xBA, 0x41, 0x98, 0x47, 0x59, 0x2B, 0x62, 0xF4, 0x42, 0xA6, 0xE0, - 0x69, 0x43, 0xED, 0x76, 0x74, 0x32, 0xDB, 0xBE, 0xF1, 0xE9, 0x35, 0x3E, 0xBB, 0x1B, 0x55, 0x8B, - 0xEE, 0x73, 0xC6, 0xB4, 0x56, 0x56, 0x76, 0xB2, 0x7A, 0x3F, 0x5A, 0x0B, 0x49, 0x87, 0x4E, 0xC9, - 0xD8, 0xAF, 0xDA, 0x4F, 0x59, 0x79, 0x46, 0x71, 0xD3, 0x28, 0xC1, 0xAA, 0x64, 0x1A, 0x75, 0x53, - 0x79, 0x46, 0x93, 0x8A, 0x98, 0x6B, 0x34, 0x19, 0x5F, 0xD1, 0x72, 0x25, 0x5E, 0x06, 0x26, 0xD7, - 0x14, 0x77, 0x0A, 0x34, 0x9C, 0xAA, 0x19, 0x70, 0xE7, 0xA5, 0xDF, 0xCF, 0xB2, 0xCE, 0xCC, 0x53, - 0xFD, 0x1E, 0x6D, 0xEA, 0x40, 0x7F, 0x33, 0xC6, 0x02, 0x71, 0x78, 0x9E, 0x9A, 0x82, 0x65, 0xCD, - 0xD2, 0x77, 0xF0, 0x64, 0xBB, 0x6B, 0x40, 0x6E, 0x7C, 0xAB, 0xB6, 0xBC, 0x66, 0x7E, 0x4B, 0x29, - 0x24, 0x6B, 0x4B, 0x63, 0xA7, 0xF4, 0x4C, 0x9B, 0x3B, 0xD5, 0xC6, 0x8C, 0x14, 0x4F, 0xB0, 0x52, - 0xDB, 0xD7, 0xD6, 0xCE, 0xE9, 0x35, 0xCC, 0xA8, 0x37, 0x3C, 0xCD, 0x74, 0x1C, 0x56, 0x94, 0xBB, - 0xDC, 0x54, 0x76, 0x4F, 0x76, 0xB4, 0x2B, 0xA4, 0x3C, 0xE3, 0xB3, 0xA6, 0xF1, 0x52, 0x0E, 0x6B, - 0xFC, 0xB5, 0x3B, 0x97, 0xB4, 0xD5, 0x1C, 0x53, 0xCD, 0x4C, 0xD5, 0x9C, 0x51, 0xC3, 0xD5, 0x68, - 0x98, 0xEB, 0x87, 0x3E, 0x66, 0x51, 0x6F, 0x91, 0xE8, 0xD7, 0xF7, 0x30, 0xBD, 0x8F, 0xA8, 0xAF, - 0x0A, 0x96, 0x61, 0x49, 0x83, 0x33, 0x0B, 0xD3, 0x02, 0xEB, 0xC2, 0x13, 0x3E, 0x57, 0x01, 0xE5, - 0x87, 0x11, 0x2D, 0x7E, 0x28, 0x51, 0x05, 0xD0, 0xBA, 0xF2, 0xFC, 0x10, 0x00, 0xD9, 0xFF, 0xB3, - 0x01, 0x33, 0x92, 0x73, 0x8F, 0xF2, 0x13, 0x73, 0x4B, 0xAF, 0x1B, 0x68, 0xF2, 0x88, 0xD2, 0x28, - 0x27, 0xDD, 0x3C, 0xA1, 0xFE, 0x80, 0xDF, 0x8F, 0xE5, 0x65, 0xED, 0x11, 0x4B, 0xB9, 0x4C, 0xD6, - 0x08, 0xFF, 0x33, 0xF4, 0x42, 0xDC, 0x07, 0xFC, 0x0B, 0x1E, 0xED, 0x4B, 0xD9, 0xA8, 0x05, 0xDA, - 0x37, 0x96, 0x2F, 0x1D, 0xD2, 0x9D, 0x58, 0xE1, 0x4D, 0xDB, 0xF7, 0xA6, 0xC0, 0x8D, 0x40, 0xBB, - 0x9C, 0x80, 0x4C, 0xA5, 0x7C, 0xDE, 0x9A, 0x63, 0x6C, 0x80, 0xC3, 0x41, 0xF7, 0xBF, 0x85, 0x6A, - 0x52, 0x9B, 0x67, 0x09, 0x8F, 0xB7, 0x84, 0x05, 0xCB, 0xAF, 0xF1, 0x45, 0x8D, 0x4E, 0xEA, 0x61, - 0xA0, 0x6C, 0x3A, 0x8D, 0xB3, 0x24, 0xF1, 0x78, 0x8B, 0xDC, 0xE1, 0x15, 0x2C, 0x77, 0xC8, 0x15, - 0x1D, 0xBC, 0x4F, 0xA6, 0xDD, 0xF7, 0xD0, 0x41, 0xE3, 0x86, 0xE1, 0xB1, 0x57, 0x4D, 0x3B, 0x54, - 0x41, 0x16, 0xD1, 0xE5, 0x19, 0xC5, 0x49, 0x9C, 0x52, 0xBC, 0x48, 0x90, 0xD1, 0xC1, 0xD1, 0x3C, - 0x86, 0x3A, 0xFB, 0x16, 0x9B, 0x73, 0x4C, 0x08, 0xCE, 0x8F, 0x26, 0xDE, 0xDC, 0x1F, 0xD9, 0x55, - 0xB9, 0x96, 0xE4, 0x21, 0x6B, 0x7C, 0x2D, 0x61, 0xBC, 0xB5, 0x80, 0x49, 0x5B, 0x45, 0x2A, 0x8F, - 0x86, 0x5A, 0x48, 0xF7, 0x10, 0x81, 0xC0, 0x9A, 0xA0, 0x0D, 0x07, 0x22, 0x5B, 0xE4, 0x1B, 0x9C, - 0x41, 0x15, 0xD7, 0x26, 0xB9, 0xE7, 0x7F, 0x31, 0x28, 0x95, 0xC5, 0x92, 0x9F, 0x90, 0xC5, 0x18, - 0xD5, 0x58, 0x54, 0xE3, 0x36, 0x20, 0x3F, 0xD2, 0xCB, 0x80, 0x88, 0xDA, 0x16, 0x17, 0x63, 0x56, - 0x40, 0xF9, 0xE5, 0x97, 0xED, 0x8D, 0x17, 0xA6, 0x99, 0x1C, 0xEA, 0xF3, 0xB4, 0x9F, 0x05, 0x4D, - 0x2A, 0x93, 0x8E, 0x34, 0x6E, 0x92, 0x29, 0x91, 0x68, 0x7E, 0x93, 0xB2, 0x52, 0x8F, 0x0E, 0xE5, - 0xE2, 0x92, 0x4D, 0x9A, 0xDA, 0x93, 0xBC, 0xC6, 0x7C, 0xB4, 0x2B, 0x34, 0x66, 0x6A, 0x67, 0xE4, - 0x0B, 0xCC, 0x69, 0x4E, 0x26, 0x4C, 0xAC, 0x7F, 0xB6, 0xB9, 0x41, 0xDD, 0x4E, 0xB7, 0xDB, 0x31, - 0xB5, 0xC8, 0xBE, 0x19, 0x4C, 0x0E, 0x61, 0x19, 0xE9, 0xBB, 0x34, 0x4C, 0xB7, 0x4A, 0x14, 0x1C, - 0xBC, 0xDF, 0x3F, 0xCB, 0x6F, 0x92, 0x94, 0x31, 0xFC, 0xE8, 0x4C, 0x65, 0x31, 0xC2, 0x9E, 0xDB, - 0x3C, 0x29, 0x93, 0x77, 0x31, 0xBC, 0xCC, 0x3F, 0x14, 0xE0, 0x65, 0x6F, 0x16, 0xE7, 0xAC, 0x7A, - 0xC3, 0x5A, 0x20, 0x3C, 0x7E, 0xBB, 0x73, 0xAE, 0x9D, 0x53, 0x0E, 0x50, 0xCA, 0x81, 0x74, 0xEC, - 0x7F, 0xDB, 0x95, 0x60, 0xBE, 0x34, 0xC9, 0x4F, 0x3F, 0x91, 0xB8, 0xEC, 0xCF, 0xBB, 0xFD, 0xBE, - 0xEE, 0x3C, 0x6B, 0xFE, 0x9E, 0x4C, 0x30, 0xCB, 0xDD, 0x43, 0x61, 0xCB, 0xF5, 0xD0, 0xA3, 0x63, - 0xDD, 0x16, 0x9F, 0x28, 0x92, 0xCE, 0xB2, 0x16, 0x81, 0x00, 0x4D, 0xC3, 0xB5, 0x81, 0xE4, 0x71, - 0x45, 0x87, 0x52, 0xAC, 0x4C, 0xF3, 0x9E, 0x58, 0xBF, 0x9D, 0xD2, 0xBB, 0x28, 0xC5, 0x91, 0xD2, - 0xCF, 0x7A, 0xDE, 0x94, 0x3F, 0xC5, 0x09, 0x95, 0xA1, 0xAD, 0x4B, 0x9A, 0x78, 0x59, 0x28, 0x80, - 0xAE, 0xCA, 0x27, 0xC1, 0x90, 0x07, 0x56, 0x34, 0xA3, 0xD7, 0x29, 0xF6, 0x05, 0x41, 0x28, 0xC1, - 0xE7, 0x4F, 0x7E, 0x71, 0xDE, 0x3A, 0x6C, 0x62, 0xC0, 0x8B, 0xDF, 0x74, 0x3C, 0x09, 0xEF, 0x65, - 0xB5, 0x35, 0xB8, 0xCE, 0x22, 0x27, 0xDC, 0xBE, 0xC6, 0x77, 0x56, 0x00, 0xA2, 0x60, 0x22, 0x93, - 0x3E, 0xE8, 0x91, 0x8B, 0xD7, 0x9A, 0x61, 0x22, 0x85, 0x39, 0x54, 0x34, 0xA9, 0xA1, 0xBD, 0x1F, - 0x84, 0xFA, 0x21, 0x1E, 0x8B, 0xC0, 0x1D, 0x1F, 0xE9, 0xC4, 0x08, 0x96, 0xA3, 0xE0, 0xBC, 0x90, - 0xC1, 0xD4, 0xF7, 0x71, 0x4A, 0x67, 0xAD, 0xC1, 0x9E, 0x67, 0xDB, 0x33, 0x67, 0xBF, 0x04, 0x89, - 0xCA, 0x8D, 0x02, 0x31, 0x71, 0xD5, 0xD3, 0xAE, 0x1C, 0x45, 0x92, 0x50, 0x67, 0xE9, 0x91, 0xC4, - 0xFC, 0xCA, 0xAE, 0x0C, 0x90, 0x2C, 0x11, 0x5A, 0xB8, 0x7C, 0xD0, 0x4A, 0xA2, 0x80, 0x6A, 0x28, - 0x54, 0xFA, 0x40, 0xB5, 0x6C, 0xE7, 0xFB, 0x52, 0x27, 0xE8, 0x76, 0x20, 0x83, 0x85, 0x14, 0x68, - 0x0B, 0x6B, 0x47, 0x64, 0xD0, 0x00, 0x94, 0x06, 0x64, 0x3D, 0xD5, 0x8A, 0x3A, 0x44, 0xAB, 0xAD, - 0xAB, 0x37, 0xBE, 0xDF, 0x11, 0xDD, 0x5B, 0x91, 0xF7, 0x68, 0xA2, 0x72, 0xB6, 0x81, 0x00, 0xF0, - 0x62, 0x4F, 0x26, 0x46, 0xB6, 0x6C, 0x7C, 0x1A, 0x44, 0x29, 0x4F, 0x6E, 0x73, 0x48, 0xF4, 0x8C, - 0x8F, 0x35, 0xA5, 0x98, 0x32, 0x3D, 0xD9, 0xC4, 0x2A, 0x01, 0x72, 0xD3, 0xD8, 0x54, 0x9E, 0x1C, - 0xCA, 0x20, 0xB9, 0x9C, 0xDE, 0x73, 0x68, 0xEC, 0x23, 0x1C, 0x53, 0x75, 0xC1, 0x16, 0xAA, 0x53, - 0x06, 0x7C, 0x7C, 0x5F, 0xA4, 0x70, 0x04, 0x09, 0x46, 0xE3, 0x47, 0x6A, 0x08, 0x4C, 0x31, 0x01, - 0x0B, 0xBF, 0xD8, 0xD1, 0xCC, 0x71, 0x4C, 0xE3, 0x67, 0x5E, 0x63, 0xE9, 0x5A, 0xFD, 0x5B, 0x69, - 0x5F, 0x26, 0x4D, 0xE9, 0xE1, 0x4E, 0x0D, 0x9E, 0x67, 0x7C, 0x3F, 0x3F, 0xFF, 0x70, 0xDE, 0xA8, - 0x6C, 0x88, 0xC4, 0x48, 0x23, 0x20, 0x11, 0x3E, 0x4B, 0xB2, 0xEC, 0x1E, 0xD6, 0x2D, 0xB8, 0x79, - 0xFC, 0x10, 0x75, 0x47, 0x9B, 0xD0, 0x6C, 0xE7, 0xF6, 0x1D, 0x0D, 0x15, 0x13, 0xA4, 0xCE, 0xB7, - 0x85, 0x56, 0x4A, 0xDB, 0x5D, 0x54, 0x8D, 0x9D, 0xB2, 0xC1, 0x69, 0x6A, 0xE7, 0xFE, 0xC7, 0xF3, - 0xF3, 0xC3, 0xD3, 0x0B, 0x53, 0x4B, 0x33, 0x1B, 0x19, 0xAB, 0x39, 0x18, 0xDB, 0xE9, 0x04, 0x2D, - 0x1E, 0x4F, 0xB4, 0xF7, 0xC8, 0x6D, 0x93, 0x0D, 0xB9, 0x4E, 0x47, 0xF7, 0x8B, 0x59, 0xBC, 0x1B, - 0x30, 0x7A, 0xDB, 0x60, 0xB7, 0x41, 0x14, 0x39, 0xEC, 0xE4, 0x22, 0x32, 0x73, 0xA3, 0xBE, 0xBF, - 0x84, 0xD8, 0xCF, 0xB2, 0xD6, 0x30, 0x66, 0x55, 0x54, 0x81, 0x24, 0x85, 0x14, 0x89, 0xC1, 0x4D, - 0xA2, 0xD3, 0x0E, 0x77, 0xF4, 0x31, 0xFD, 0x74, 0x26, 0xDC, 0xEF, 0xDF, 0xFD, 0xC6, 0x59, 0xBC, - 0x94, 0x41, 0x48, 0x29, 0x7F, 0xBA, 0xA7, 0xA0, 0xFD, 0xEF, 0xC4, 0xA3, 0x4F, 0xB8, 0x59, 0x73, - 0x2D, 0x35, 0xEF, 0xC7, 0x44, 0xAF, 0x4E, 0xF4, 0x86, 0xC9, 0x54, 0xD5, 0xDC, 0x45, 0x4F, 0xA5, - 0x2A, 0x35, 0xE3, 0x44, 0xAA, 0x31, 0x64, 0x9A, 0x46, 0x87, 0x1C, 0xAF, 0x3C, 0xE2, 0xA4, 0xC0, - 0xB0, 0xE8, 0x66, 0x05, 0xDA, 0xD3, 0x6E, 0x23, 0xF3, 0x55, 0x3F, 0x23, 0x2B, 0xCB, 0x46, 0x4B, - 0x1D, 0x61, 0x4B, 0xCF, 0x42, 0x0B, 0x1A, 0x5A, 0x45, 0x26, 0x9F, 0x59, 0x83, 0x48, 0x0C, 0xAA, - 0xD6, 0x2B, 0x8F, 0x6C, 0xAA, 0x4B, 0x27, 0x2F, 0xB4, 0x22, 0xEA, 0xE2, 0x09, 0x3B, 0xB1, 0x6B, - 0x15, 0xED, 0xA6, 0x18, 0x5D, 0x91, 0x2C, 0x39, 0x95, 0x1F, 0x9E, 0x1A, 0x15, 0xBE, 0x8D, 0xA6, - 0x3F, 0x65, 0x57, 0xD6, 0x84, 0x6B, 0xC8, 0xA4, 0xCD, 0x7D, 0x9D, 0xCC, 0x6E, 0x6A, 0x2B, 0x4E, - 0x7B, 0x31, 0x53, 0x49, 0xA7, 0xF0, 0xCE, 0xB9, 0xA5, 0x2E, 0xB1, 0xF0, 0xE9, 0x55, 0xBF, 0x19, - 0x88, 0x0C, 0x60, 0x28, 0xCC, 0x7B, 0x9C, 0xA8, 0xA0, 0x9B, 0xDD, 0xD0, 0xB9, 0xE6, 0x79, 0xB8, - 0x30, 0xEE, 0x8D, 0x99, 0x08, 0xB1, 0x06, 0xC3, 0x6F, 0x49, 0x48, 0x33, 0x71, 0x5C, 0x72, 0x70, - 0xD0, 0xB6, 0xA3, 0x7F, 0x6C, 0xC3, 0xD9, 0x92, 0xC2, 0xB8, 0x23, 0x5C, 0x47, 0x68, 0x2B, 0xF0, - 0xB5, 0xA4, 0x25, 0xA4, 0x79, 0xE8, 0x02, 0x29, 0x75, 0x3D, 0x1B, 0x61, 0x8C, 0x2B, 0x42, 0xF3, - 0xD5, 0x77, 0x96, 0x82, 0xF6, 0xFE, 0x87, 0x0F, 0xE7, 0x07, 0x47, 0xA7, 0x7B, 0x17, 0x87, 0x97, - 0x47, 0xA7, 0x67, 0x1F, 0x2F, 0x2E, 0x2F, 0x3E, 0x9D, 0xE1, 0xAF, 0x3F, 0xEF, 0x1D, 0x1F, 0x1D, - 0x5C, 0x7E, 0x3C, 0xFD, 0xDB, 0xE9, 0x87, 0x5F, 0x4E, 0x93, 0x4D, 0x6D, 0xDB, 0x0A, 0x6E, 0xA4, - 0x1B, 0xE3, 0xB1, 0x79, 0xC4, 0x90, 0x73, 0xC3, 0x77, 0x9B, 0x0E, 0x9C, 0xB1, 0x35, 0x32, 0x94, - 0x70, 0x53, 0xF5, 0xE1, 0xFA, 0x98, 0xB2, 0xF7, 0x13, 0xF5, 0xD3, 0x3D, 0x30, 0x1E, 0xE0, 0x6D, - 0x85, 0xF8, 0x4C, 0x57, 0x2C, 0x17, 0xFE, 0x1A, 0x0E, 0xDE, 0x45, 0x46, 0xF5, 0x22, 0x77, 0x37, - 0x16, 0x9B, 0xAE, 0x86, 0x4C, 0xF0, 0x20, 0xE3, 0x69, 0x10, 0x5B, 0xE5, 0x81, 0xE5, 0x12, 0x8A, - 0x02, 0x61, 0x26, 0xD3, 0x71, 0xA1, 0xF3, 0x1D, 0x9B, 0xDD, 0x2A, 0x0F, 0x44, 0x95, 0x3D, 0xC2, - 0xBF, 0xF1, 0x5A, 0xF8, 0xE0, 0x28, 0xCB, 0x03, 0xC7, 0xCF, 0x01, 0x83, 0x16, 0x59, 0x6D, 0x61, - 0xBC, 0x69, 0x8B, 0x75, 0x53, 0x5B, 0x3D, 0xEB, 0x92, 0x8C, 0x6F, 0x2C, 0x78, 0xDD, 0xF4, 0xAA, - 0xD7, 0x68, 0x03, 0xDB, 0x19, 0x3A, 0x61, 0xD2, 0x4D, 0x78, 0x88, 0x9B, 0x75, 0xA5, 0x12, 0x01, - 0x54, 0xB1, 0xB1, 0x68, 0x7A, 0xA3, 0xBC, 0x56, 0x56, 0xF2, 0x5E, 0x0C, 0x91, 0xC9, 0x21, 0x96, - 0xE6, 0x6A, 0x73, 0x39, 0xE9, 0xC0, 0x95, 0x15, 0xF6, 0x8A, 0xD1, 0x68, 0x44, 0x86, 0x9E, 0x67, - 0x97, 0x80, 0x26, 0x00, 0x9D, 0xF4, 0x73, 0x65, 0xF0, 0x36, 0x12, 0x97, 0xDA, 0x95, 0x87, 0x20, - 0xDA, 0x9B, 0xA8, 0xA5, 0xAC, 0xE2, 0x3C, 0x98, 0x2D, 0x69, 0x40, 0x8D, 0x30, 0xD2, 0x25, 0x50, - 0x54, 0x80, 0x25, 0x16, 0x50, 0x0F, 0x9F, 0xC0, 0xBB, 0x47, 0x25, 0x9A, 0x78, 0x41, 0xE0, 0x60, - 0x3C, 0x2C, 0xD7, 0x0A, 0x1C, 0xA7, 0x91, 0xBE, 0x24, 0x43, 0x32, 0xF9, 0x70, 0x72, 0xD2, 0x1E, - 0xF3, 0x7F, 0xC9, 0x37, 0x62, 0xFA, 0xB8, 0x6A, 0xFA, 0x78, 0x72, 0xD2, 0xEF, 0xB7, 0x03, 0xF6, - 0x4F, 0x01, 0x27, 0x86, 0xCF, 0x80, 0x60, 0x35, 0xF9, 0xFC, 0xCC, 0xA8, 0x27, 0xEC, 0x16, 0xD7, - 0xEC, 0x92, 0xFB, 0xBF, 0x18, 0x24, 0xEC, 0x7A, 0x6D, 0xB2, 0x01, 0xA3, 0x6D, 0xBB, 0xB3, 0xBE, - 0xBE, 0xF1, 0x9C, 0xE5, 0xDF, 0x63, 0xF2, 0x6B, 0x27, 0x11, 0xCA, 0xC9, 0x88, 0x7F, 0x4D, 0x7A, - 0xF3, 0x20, 0xFC, 0x01, 0xC7, 0x5F, 0x87, 0xE5, 0x84, 0x80, 0x91, 0xD6, 0x23, 0xD6, 0x08, 0xB3, - 0x12, 0xDA, 0xC8, 0x08, 0xE9, 0x6C, 0x92, 0xDE, 0x66, 0xBB, 0xD7, 0xD9, 0xD8, 0x36, 0xB0, 0x92, - 0xD8, 0xA4, 0xD7, 0x64, 0x7D, 0xCE, 0x9C, 0xF4, 0x18, 0x33, 0xEB, 0x09, 0x33, 0xAB, 0xDD, 0xCE, - 0xE6, 0x6A, 0xB7, 0xBB, 0xDA, 0xD9, 0x6C, 0x77, 0xB7, 0x7A, 0x26, 0x76, 0xCC, 0x96, 0xED, 0x35, - 0x06, 0xF9, 0xCF, 0x89, 0xB5, 0xE7, 0xC8, 0xD3, 0x35, 0xBD, 0xA3, 0x3E, 0xE7, 0xA7, 0xDB, 0x45, - 0x6E, 0x5E, 0xBC, 0xD8, 0xDE, 0xEE, 0x91, 0xA5, 0x03, 0xAE, 0x59, 0x58, 0x85, 0xFF, 0xB6, 0x1C, - 0xF3, 0x98, 0xB8, 0xB3, 0x2E, 0x1D, 0x5A, 0x21, 0xD8, 0xCD, 0xBE, 0x33, 0x74, 0x55, 0xEF, 0x41, - 0x1D, 0xBB, 0x9D, 0xC4, 0x70, 0x24, 0x56, 0x2A, 0x2E, 0xE6, 0x7E, 0x17, 0x06, 0xD6, 0xEF, 0x49, - 0xC6, 0xAD, 0x85, 0xA2, 0xC3, 0xD8, 0x77, 0x76, 0xD2, 0x83, 0xD1, 0xF7, 0x60, 0xBC, 0x98, 0x28, - 0xB8, 0xF9, 0x48, 0xEE, 0xDA, 0xA8, 0x4C, 0xA8, 0x81, 0x3D, 0x71, 0xA7, 0xAE, 0xAE, 0x22, 0x22, - 0x4C, 0xA4, 0x99, 0xF4, 0x33, 0x58, 0x6B, 0x9C, 0x33, 0x1D, 0x97, 0x3F, 0xF6, 0xC1, 0x4A, 0x28, - 0xB7, 0xE0, 0x3C, 0xFF, 0x26, 0x4B, 0x4D, 0x21, 0x88, 0x46, 0x64, 0x48, 0x00, 0x74, 0xF4, 0x0D, - 0x2B, 0x59, 0x8F, 0xB9, 0xA1, 0xC5, 0x35, 0x95, 0x34, 0xCB, 0xC5, 0xDF, 0x32, 0xFA, 0x75, 0x97, - 0xDD, 0xDE, 0xC0, 0xC7, 0x01, 0x33, 0xCB, 0xB7, 0x96, 0x61, 0x41, 0xB6, 0xB6, 0x96, 0x1E, 0xF1, - 0xF2, 0x03, 0xCE, 0xF5, 0xE7, 0x6A, 0x8E, 0x57, 0x3A, 0x95, 0xE7, 0x69, 0x38, 0xD8, 0xA1, 0x0B, - 0xBF, 0xC6, 0xC3, 0x8E, 0x22, 0x41, 0xBC, 0xEE, 0x20, 0xBA, 0x1D, 0x9D, 0x38, 0x0C, 0xAC, 0x9B, - 0xC0, 0xF9, 0x24, 0x42, 0x6F, 0x14, 0x2C, 0xC2, 0xBE, 0xA8, 0x28, 0x24, 0xD4, 0xFC, 0x6E, 0x74, - 0x47, 0xC6, 0x91, 0x4C, 0x7C, 0x49, 0xB5, 0xD5, 0xDD, 0xD8, 0x54, 0xF1, 0x33, 0x57, 0xE5, 0x3E, - 0x35, 0x4B, 0xE5, 0xEB, 0xB8, 0xD3, 0x90, 0xC5, 0x68, 0xE4, 0x10, 0x8A, 0xC9, 0x9C, 0x9C, 0xC8, - 0x71, 0x71, 0x6F, 0x1D, 0x98, 0xA2, 0x61, 0x7A, 0x51, 0xA6, 0xDC, 0x64, 0x62, 0x66, 0x97, 0x8B, - 0x3E, 0x5C, 0x2F, 0xB1, 0x09, 0x08, 0x7A, 0x63, 0xB5, 0xAB, 0xEF, 0x8D, 0xCF, 0x2A, 0xFA, 0xCB, - 0xD3, 0x0F, 0x97, 0x07, 0x87, 0xFB, 0x47, 0x27, 0x7B, 0xC7, 0x5A, 0x2F, 0x04, 0x14, 0x26, 0x20, - 0x1B, 0x9B, 0x15, 0xF3, 0xA3, 0x89, 0x5B, 0x56, 0x07, 0xBE, 0xB8, 0xE2, 0x10, 0x46, 0x91, 0x25, - 0x03, 0x4A, 0x16, 0xB4, 0x0C, 0x12, 0xC9, 0xF1, 0x2F, 0xB1, 0xBC, 0x04, 0x00, 0x88, 0x4C, 0x0A, - 0x43, 0x33, 0xB8, 0x56, 0x11, 0xB1, 0x95, 0x04, 0xC9, 0x1A, 0xD9, 0x82, 0x29, 0x80, 0x5D, 0xAA, - 0x8F, 0x68, 0xAC, 0x91, 0xF5, 0x2D, 0xCC, 0x26, 0xB3, 0xAC, 0xDD, 0x0A, 0x57, 0x46, 0xB2, 0xD9, - 0xAF, 0x31, 0x91, 0xFD, 0x0B, 0x76, 0x87, 0xFC, 0xC2, 0xE1, 0x83, 0x69, 0xF5, 0xA4, 0x0D, 0x51, - 0x1C, 0x8D, 0xEA, 0x00, 0x65, 0xE3, 0x33, 0x73, 0xF8, 0x6D, 0xE2, 0xE8, 0xCC, 0x2C, 0xDD, 0x88, - 0xC7, 0xA6, 0x32, 0x43, 0xCF, 0x6F, 0x68, 0x96, 0x1C, 0x98, 0xC9, 0x88, 0x54, 0x34, 0x24, 0x63, - 0x38, 0xEA, 0x43, 0xA3, 0xEA, 0x00, 0xCC, 0x1C, 0x7E, 0x66, 0x3D, 0x55, 0x44, 0xC3, 0x22, 0x7D, - 0x05, 0x80, 0x01, 0xB1, 0x59, 0x49, 0xAB, 0x2A, 0xDD, 0x82, 0xF5, 0x4B, 0x55, 0x30, 0x45, 0x9B, - 0xBA, 0x5C, 0x1F, 0x56, 0x17, 0xA4, 0x10, 0x97, 0x27, 0x27, 0x97, 0x07, 0x7B, 0xFD, 0xF7, 0x9A, - 0x5A, 0x88, 0x78, 0xA3, 0xC4, 0x6C, 0x89, 0xDB, 0x64, 0xAB, 0xFA, 0x6D, 0xC3, 0x44, 0x07, 0x84, - 0x29, 0x47, 0x48, 0xCC, 0x5F, 0x94, 0x74, 0x58, 0x46, 0xD7, 0xCA, 0xF5, 0xBB, 0x5F, 0x24, 0x63, - 0x9A, 0xEA, 0xDD, 0x27, 0xD6, 0x59, 0xD9, 0x7D, 0xD5, 0x8B, 0xFB, 0x2A, 0xF2, 0x8E, 0xE7, 0xDE, - 0x57, 0x60, 0xDE, 0x9F, 0x58, 0x77, 0x3D, 0x99, 0xB9, 0x4F, 0x12, 0x4F, 0x99, 0x29, 0x50, 0x6E, - 0x50, 0x2F, 0x69, 0x50, 0x7A, 0x0E, 0xFC, 0xA3, 0x4F, 0x50, 0x5C, 0x29, 0x93, 0x0D, 0x9C, 0xB9, - 0xEA, 0xE4, 0x4E, 0x81, 0x98, 0x12, 0x03, 0xFE, 0xDD, 0x04, 0x20, 0x2C, 0x28, 0x59, 0x9C, 0x05, - 0x2D, 0x39, 0x1A, 0xC9, 0x0F, 0xE3, 0x99, 0xD7, 0x4F, 0xBD, 0xB8, 0x9F, 0xC8, 0x62, 0xD6, 0x25, - 0xDC, 0x40, 0x3C, 0xA1, 0xCE, 0x7A, 0x6A, 0xA6, 0xF3, 0x7F, 0x9A, 0xD5, 0x14, 0x1B, 0x5A, 0xCA, - 0xC9, 0x90, 0x01, 0x01, 0x3F, 0x1C, 0x32, 0x14, 0xC4, 0xD9, 0xB5, 0xB6, 0x97, 0xB5, 0xAB, 0xF5, - 0x86, 0xEE, 0xE0, 0x67, 0x3E, 0xC9, 0xC6, 0xBC, 0xB4, 0xC3, 0x8E, 0x9B, 0xBA, 0xC9, 0x15, 0xF4, - 0x16, 0xF1, 0xA6, 0x21, 0xFE, 0x61, 0x89, 0x5D, 0x7B, 0x00, 0xEA, 0x7B, 0xEA, 0x1E, 0x3C, 0x6E, - 0x28, 0x5F, 0x81, 0xB4, 0xC6, 0x94, 0x34, 0xB5, 0x21, 0xD3, 0x6C, 0x11, 0x1A, 0x0E, 0xE4, 0xA0, - 0x5A, 0xC6, 0x37, 0xE3, 0x43, 0xE2, 0xAB, 0x65, 0x52, 0x19, 0xF3, 0x7E, 0xBD, 0xD8, 0xBC, 0x94, - 0x0E, 0x1A, 0xF9, 0xDD, 0x03, 0x83, 0xC6, 0x95, 0x57, 0xB9, 0x65, 0xE3, 0xB0, 0x4E, 0x34, 0x2C, - 0xF9, 0xB6, 0x2C, 0x89, 0x59, 0x3F, 0xAD, 0x95, 0xD9, 0x30, 0x9F, 0x75, 0xCD, 0xC8, 0xE6, 0xA5, - 0xB4, 0xE6, 0x81, 0x75, 0xDB, 0x8C, 0xD8, 0xE6, 0x8A, 0x2C, 0x72, 0xDD, 0xE7, 0x8C, 0xB2, 0xFF, - 0xE9, 0xE4, 0xCD, 0x87, 0x63, 0x86, 0x54, 0xBF, 0xD4, 0x31, 0xF2, 0xDC, 0x21, 0xCB, 0x63, 0x74, - 0x40, 0x87, 0x3E, 0xD5, 0xF7, 0x47, 0x52, 0x3D, 0xA1, 0x75, 0x2D, 0x2C, 0xCE, 0x74, 0x04, 0xC6, - 0x7A, 0x30, 0x5C, 0xB7, 0x3A, 0x3B, 0x5A, 0x6E, 0xC8, 0xB8, 0xF4, 0x15, 0xC9, 0xB4, 0x7C, 0x7C, - 0xA0, 0x4B, 0xA6, 0x4B, 0xD1, 0xAB, 0x41, 0x7A, 0xD8, 0x3E, 0x5F, 0x4E, 0xE5, 0xA0, 0x9C, 0xB1, - 0x7B, 0xB3, 0x58, 0x8B, 0x87, 0x50, 0x4A, 0x84, 0x2B, 0x30, 0xAA, 0x98, 0x75, 0x89, 0xAA, 0xEE, - 0xA4, 0x0F, 0x2F, 0xE6, 0xA4, 0x28, 0xB5, 0x98, 0x5B, 0x7D, 0x0C, 0xEE, 0xB8, 0xCE, 0xD5, 0xE2, - 0xEF, 0xBF, 0xFF, 0x4B, 0x65, 0x10, 0xBF, 0x35, 0x1B, 0x2A, 0x9B, 0x75, 0xF0, 0x12, 0x53, 0xBB, - 0x35, 0xDB, 0x32, 0x97, 0xA6, 0xF7, 0x97, 0xE5, 0x01, 0x3C, 0xBB, 0x0A, 0xCE, 0x19, 0xA1, 0xB4, - 0xAA, 0x5A, 0x04, 0x5E, 0xBD, 0xE7, 0xE7, 0x24, 0x02, 0xC9, 0x95, 0x59, 0x04, 0xD7, 0x8B, 0xC5, - 0xAE, 0xAD, 0x60, 0x97, 0xFF, 0xE8, 0x66, 0x58, 0xE1, 0xF9, 0xC4, 0xB4, 0xB5, 0x5E, 0x85, 0x67, - 0x81, 0x20, 0x8F, 0xE7, 0xD2, 0x13, 0xC0, 0xD6, 0xDC, 0x27, 0x00, 0x79, 0xF4, 0x55, 0x9C, 0x02, - 0x52, 0x22, 0x7A, 0xA4, 0xA9, 0x21, 0x35, 0xBA, 0xAB, 0xCE, 0x0E, 0x26, 0xC6, 0x57, 0x1F, 0x89, - 0xF3, 0x99, 0x67, 0x0E, 0x13, 0xF3, 0xCD, 0xF4, 0x94, 0xF2, 0xF7, 0x46, 0x63, 0x51, 0x6D, 0x58, - 0xAE, 0x3D, 0x3D, 0x99, 0x78, 0x27, 0x8B, 0x16, 0x7C, 0xA6, 0x79, 0x9D, 0x93, 0xBA, 0x4B, 0x17, - 0x15, 0x8D, 0x66, 0x61, 0xCE, 0x0A, 0x34, 0x63, 0x4B, 0xF2, 0xFB, 0xE1, 0x91, 0xDB, 0xA2, 0x4F, - 0x1C, 0xF3, 0x1F, 0xD1, 0x79, 0x0D, 0x4A, 0x5D, 0xE4, 0x51, 0xE9, 0x69, 0x31, 0x8F, 0x51, 0x10, - 0xD2, 0x00, 0x1F, 0x55, 0x14, 0x30, 0x6B, 0x7F, 0xB7, 0xD7, 0xDA, 0x21, 0x5E, 0x49, 0x1E, 0x2C, - 0xEF, 0x10, 0x35, 0x65, 0x42, 0x74, 0xAE, 0x0F, 0x4B, 0xE2, 0x16, 0xCF, 0xD0, 0x08, 0x2B, 0xD8, - 0x1B, 0x5F, 0x0E, 0x92, 0xE4, 0xE9, 0x25, 0x5F, 0xE3, 0xAA, 0x39, 0xBA, 0x7A, 0xB4, 0x2A, 0x05, - 0xA1, 0xC0, 0x67, 0x65, 0x91, 0x8E, 0xD5, 0x94, 0xC4, 0x88, 0x22, 0xF9, 0xE4, 0x0A, 0xE2, 0xC5, - 0x68, 0x50, 0xA5, 0x9C, 0x23, 0x5F, 0x61, 0x69, 0xE4, 0xE5, 0x75, 0xBC, 0xAB, 0xAC, 0xDC, 0x05, - 0x6A, 0x0B, 0xDF, 0xB4, 0x74, 0x79, 0x2E, 0x3B, 0xB1, 0x86, 0x97, 0x6E, 0x0B, 0x8B, 0x92, 0x24, - 0x5E, 0x2E, 0x67, 0x25, 0x1E, 0xDC, 0x39, 0xE1, 0xE0, 0x86, 0xE4, 0x55, 0x61, 0xE1, 0x09, 0xF4, - 0xDA, 0x9A, 0x8E, 0xC2, 0x97, 0x5A, 0x36, 0x7C, 0xDE, 0x13, 0x8D, 0x8F, 0xEE, 0x57, 0xD7, 0xBB, - 0x73, 0xF5, 0x94, 0xB2, 0xDA, 0xCB, 0x0B, 0x03, 0xBC, 0xB6, 0xBB, 0x54, 0x7A, 0xFD, 0x9E, 0x41, - 0x4B, 0xDE, 0xA6, 0x98, 0x2B, 0x41, 0x58, 0x5C, 0x65, 0x92, 0x4C, 0xF6, 0x3D, 0xE7, 0x4A, 0xF2, - 0x32, 0x8F, 0x26, 0x59, 0x1C, 0x51, 0x3E, 0x1F, 0x67, 0x52, 0x5E, 0x5D, 0x10, 0x65, 0xE6, 0xBD, - 0xE4, 0xC8, 0x38, 0xDE, 0x62, 0x9A, 0x7B, 0x7B, 0xF3, 0xE8, 0x2A, 0x9B, 0x5B, 0x0B, 0xA0, 0x5C, - 0x2C, 0xEC, 0xD5, 0xC5, 0x90, 0xD7, 0x27, 0xD2, 0x5C, 0xC9, 0x2F, 0xA2, 0xE1, 0x65, 0x68, 0x73, - 0xE9, 0x2F, 0x4A, 0xEC, 0xA5, 0x58, 0xE0, 0x3D, 0x90, 0xC3, 0xC2, 0xC3, 0xB3, 0x2C, 0x6B, 0xF7, - 0xF0, 0xFF, 0x01, 0x0F, 0xF8, 0x5F, 0x58, 0x32, 0x95, 0x00 + 0x1F, 0x8B, 0x08, 0x08, 0x35, 0x44, 0x85, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, + 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, + 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, + 0x6D, 0xF7, 0xD8, 0x6E, 0x08, 0x33, 0xCB, 0x3B, 0xED, 0x33, 0xEC, 0x93, 0xDD, 0x2A, 0x49, 0xB6, + 0x25, 0x59, 0xFE, 0xEC, 0x86, 0x30, 0xB3, 0xC9, 0xEF, 0x77, 0x38, 0x60, 0xA9, 0x3E, 0x54, 0x2A, + 0x95, 0x4A, 0x52, 0xA9, 0x74, 0x6B, 0x07, 0x64, 0x68, 0x47, 0xF4, 0xCE, 0xBE, 0x27, 0xBB, 0xE4, + 0xDF, 0xEF, 0xC2, 0x57, 0xAB, 0xAB, 0x7F, 0xFC, 0xFB, 0x9D, 0xEB, 0x39, 0xFE, 0x5D, 0x67, 0xE4, + 0x0F, 0xEC, 0xC8, 0xF5, 0xBD, 0xCE, 0x8D, 0x1F, 0x46, 0x9E, 0x3D, 0xA6, 0x0F, 0xAF, 0xB6, 0xBA, + 0xAB, 0x77, 0xE1, 0xBF, 0xEF, 0xBC, 0xB8, 0x05, 0xB8, 0x3B, 0x7A, 0x15, 0xFA, 0x83, 0x6F, 0x34, + 0xDA, 0x79, 0xF1, 0x42, 0x40, 0xD8, 0x8E, 0x73, 0x78, 0x4B, 0xBD, 0xE8, 0xD8, 0x0D, 0x23, 0xEA, + 0xD1, 0x60, 0x71, 0x61, 0xE4, 0xDB, 0xCE, 0x42, 0x9B, 0xF8, 0xDE, 0x31, 0xFC, 0xB2, 0x04, 0x35, + 0xAF, 0xA7, 0xDE, 0x00, 0x91, 0x8A, 0x4F, 0x8B, 0x14, 0xEB, 0x2F, 0x91, 0xBF, 0xBF, 0x20, 0xF0, + 0xCF, 0xF5, 0xDC, 0xE8, 0x57, 0x7A, 0xD5, 0x67, 0x68, 0x17, 0xA1, 0xFA, 0x83, 0x04, 0xA0, 0x15, + 0x0A, 0x90, 0x84, 0x0B, 0xE0, 0xDF, 0xA3, 0x77, 0x24, 0xAD, 0x21, 0xDA, 0x05, 0x58, 0x94, 0x7A, + 0x1D, 0xDF, 0x1B, 0xD3, 0x30, 0xB4, 0x87, 0x14, 0x20, 0x12, 0xE4, 0x8B, 0xE3, 0x70, 0x18, 0xA3, + 0xC4, 0x7F, 0x13, 0x3B, 0x08, 0xE9, 0x91, 0x37, 0xF0, 0xC7, 0xAE, 0x37, 0xC4, 0xC2, 0x8E, 0x63, + 0x47, 0xB6, 0xC0, 0xF5, 0xA0, 0x32, 0x36, 0xA4, 0x8B, 0x34, 0x86, 0x0D, 0x68, 0x34, 0x0D, 0x3C, + 0xE2, 0xF8, 0x83, 0xE9, 0x18, 0x1A, 0xD6, 0x19, 0xD2, 0xE8, 0x70, 0x44, 0xF1, 0xD7, 0xB7, 0xF7, + 0x47, 0xD0, 0x5A, 0xDE, 0x26, 0x14, 0xDF, 0xB5, 0xFB, 0x9D, 0x3A, 0xC7, 0x36, 0xF2, 0x6D, 0xED, + 0x48, 0x5F, 0x7C, 0x6F, 0x98, 0x7E, 0x9A, 0x8C, 0xEC, 0xE8, 0xDA, 0x0F, 0xC6, 0x67, 0x01, 0x85, + 0x52, 0xF8, 0xDE, 0x6A, 0xF1, 0x82, 0x21, 0xF5, 0x1D, 0x1A, 0xB9, 0x03, 0x8E, 0x60, 0xDD, 0xEA, + 0x58, 0x5D, 0xAD, 0x00, 0x18, 0xDB, 0x25, 0x2B, 0x5D, 0x6B, 0xA3, 0xD3, 0xDD, 0x56, 0x8B, 0xF6, + 0x46, 0x08, 0xD3, 0xDD, 0xB0, 0xAC, 0x8E, 0x00, 0xA2, 0x03, 0x7A, 0xFD, 0x1B, 0xAB, 0xDE, 0xDB, + 0xB2, 0x7A, 0xD6, 0x66, 0x67, 0x63, 0x73, 0x2B, 0x2D, 0xF9, 0x8C, 0x25, 0xEB, 0x2F, 0xBB, 0x9B, + 0x5B, 0xD6, 0x7A, 0x67, 0xDD, 0x5A, 0x4B, 0x4B, 0x7E, 0x67, 0xB4, 0xB7, 0x36, 0x37, 0x37, 0x37, + 0x3A, 0xEB, 0x5B, 0xEB, 0xBC, 0x60, 0x64, 0x87, 0xD1, 0x3B, 0x77, 0x44, 0x4F, 0x41, 0x63, 0x24, + 0x8E, 0xAF, 0xF1, 0xD3, 0x74, 0x7C, 0x45, 0x83, 0xB4, 0x79, 0x1E, 0xFB, 0xFB, 0xE3, 0x35, 0x56, + 0x0F, 0xFB, 0x74, 0x44, 0x07, 0x11, 0x75, 0xD2, 0xE2, 0x50, 0x7C, 0x61, 0xC5, 0x12, 0xAA, 0xF0, + 0xC6, 0x07, 0x85, 0x1B, 0xE2, 0x67, 0xD4, 0x34, 0xEC, 0x47, 0x7B, 0x14, 0x52, 0x5E, 0xE8, 0x5F, + 0x45, 0xB6, 0xEB, 0x51, 0xE7, 0x84, 0x77, 0x72, 0xA5, 0x0A, 0x6F, 0xED, 0x90, 0xAA, 0x95, 0x04, + 0x09, 0x51, 0xE7, 0xFC, 0x62, 0xFF, 0x24, 0x8B, 0x08, 0x5B, 0x74, 0x61, 0x5F, 0xC1, 0x0F, 0xFA, + 0x3D, 0x92, 0xD8, 0x1B, 0xF8, 0x41, 0x40, 0x99, 0x6A, 0x68, 0x05, 0x42, 0xEF, 0xB4, 0xAF, 0x28, + 0x2F, 0x41, 0xE7, 0xE2, 0x7E, 0x42, 0xF3, 0x4B, 0x04, 0x97, 0x58, 0xCA, 0x79, 0xB4, 0x6F, 0x93, + 0x56, 0xA0, 0xB0, 0x51, 0x44, 0x5F, 0xBE, 0xEE, 0x64, 0xCA, 0x7E, 0xB1, 0x47, 0xD3, 0x6C, 0xE1, + 0xFE, 0x0D, 0x1D, 0x7C, 0xBB, 0xF2, 0xBF, 0x1B, 0x21, 0xE3, 0x42, 0x05, 0x94, 0x15, 0x43, 0xCB, + 0xFC, 0xC0, 0x09, 0x0F, 0xF7, 0x0F, 0xDF, 0x49, 0x40, 0xE2, 0xEB, 0x7B, 0xA1, 0x61, 0x52, 0xC9, + 0xF5, 0x74, 0x34, 0x3A, 0x03, 0x26, 0x3E, 0x4D, 0x60, 0x00, 0x49, 0x42, 0x16, 0x60, 0x21, 0x8D, + 0x2E, 0xDC, 0x31, 0xF5, 0xA7, 0x51, 0xDC, 0xE5, 0x9E, 0x73, 0x00, 0x23, 0x4D, 0xF9, 0x38, 0x40, + 0x6E, 0x4E, 0xE9, 0xDD, 0x3B, 0x37, 0x18, 0xDF, 0xD9, 0x01, 0x55, 0x0A, 0x61, 0x84, 0x99, 0x8A, + 0x5E, 0x0C, 0x7C, 0x0F, 0x3A, 0x0C, 0x34, 0x6C, 0x3F, 0xE9, 0x8E, 0xB0, 0xEF, 0x4F, 0x83, 0x01, + 0x6B, 0xCF, 0x96, 0xDE, 0x55, 0xA2, 0x4C, 0x97, 0x46, 0xA6, 0xC2, 0x59, 0xE0, 0xFA, 0x81, 0x1B, + 0xB9, 0xA9, 0x54, 0x38, 0xA1, 0x7D, 0x1F, 0x04, 0xE0, 0x7A, 0xD0, 0x46, 0xEC, 0x2A, 0x2C, 0xE4, + 0x06, 0x61, 0xFF, 0xE3, 0xC7, 0xF3, 0x83, 0xA3, 0xD3, 0xBD, 0x8B, 0xC3, 0xCB, 0xA3, 0xD3, 0xB3, + 0x4F, 0x17, 0x97, 0x17, 0x9F, 0xCF, 0x0E, 0x2F, 0x0F, 0x0E, 0x5E, 0x11, 0xAB, 0x4D, 0x56, 0x57, + 0x0F, 0xE8, 0xB5, 0x3D, 0x85, 0xF1, 0x78, 0x70, 0xD0, 0x71, 0xE2, 0x7F, 0x85, 0x70, 0x27, 0x27, + 0xAF, 0x48, 0x97, 0x41, 0xC2, 0xAF, 0x9D, 0x31, 0xFE, 0x2B, 0xAC, 0x7F, 0x89, 0x00, 0x3D, 0x0E, + 0x40, 0xAA, 0x42, 0x5C, 0x1E, 0xEC, 0xF5, 0x3F, 0xBC, 0x22, 0x6B, 0x1C, 0x6C, 0xA5, 0x32, 0x58, + 0xFF, 0xF3, 0xC9, 0xDB, 0x8F, 0xC7, 0xAF, 0xC8, 0x3A, 0x07, 0xFC, 0xEF, 0xFF, 0x8A, 0x21, 0xC7, + 0xE3, 0x85, 0x92, 0x56, 0xF5, 0xFB, 0xAF, 0xC8, 0x46, 0xC2, 0x26, 0xE9, 0xF7, 0x3B, 0x21, 0xFB, + 0x57, 0x4E, 0x13, 0x00, 0x37, 0x9B, 0x01, 0x8A, 0x66, 0xBE, 0x4C, 0x9A, 0xB9, 0x52, 0x0B, 0x3A, + 0x6E, 0xED, 0x56, 0xDA, 0xDA, 0x85, 0x04, 0x41, 0xAB, 0xB4, 0xBD, 0x97, 0xA7, 0x1F, 0x2F, 0x0F, + 0x0E, 0xF7, 0x8F, 0x4E, 0xF6, 0x00, 0xC7, 0x76, 0xDC, 0xA5, 0xFD, 0x3E, 0x59, 0x21, 0xA7, 0x3E, + 0x71, 0xE8, 0xC0, 0x1D, 0xDB, 0xA3, 0x2A, 0x7C, 0xC8, 0x78, 0xBA, 0x96, 0x2C, 0x8A, 0xDA, 0xA8, + 0x50, 0x20, 0x2A, 0xBE, 0xAE, 0x2C, 0x9C, 0xAA, 0xF8, 0x8E, 0x4E, 0x7F, 0xD9, 0x3B, 0x3E, 0x3A, + 0xB8, 0xFC, 0x74, 0xFA, 0x97, 0xD3, 0x8F, 0xBF, 0x9E, 0x02, 0x9A, 0x5E, 0x3B, 0x9E, 0xF7, 0x60, + 0xB8, 0xDC, 0xD2, 0x00, 0xAC, 0x7A, 0x3A, 0x62, 0xD0, 0xE2, 0x77, 0xAC, 0x78, 0xC0, 0xC5, 0x5F, + 0x8F, 0xBC, 0xC9, 0x34, 0x12, 0x16, 0x51, 0x1B, 0x5D, 0x9D, 0xBC, 0x66, 0xC8, 0x0E, 0x46, 0x66, + 0x0A, 0x8F, 0xE7, 0xE8, 0xD5, 0x55, 0x1C, 0xB2, 0xFE, 0x88, 0x82, 0x87, 0x33, 0x5C, 0x6C, 0xC5, + 0x55, 0x62, 0xF3, 0xFC, 0x8A, 0xB4, 0xC8, 0x32, 0xC1, 0xFA, 0x80, 0x0D, 0xEB, 0x23, 0x5B, 0x38, + 0xFB, 0x03, 0x1F, 0xE8, 0x08, 0x84, 0x93, 0x91, 0x1B, 0x2D, 0x2E, 0xB4, 0x17, 0x84, 0x37, 0x00, + 0xF3, 0x33, 0x59, 0x1C, 0x81, 0x03, 0xF2, 0x9D, 0xCD, 0x5C, 0xF0, 0xBF, 0xD7, 0xAC, 0x7A, 0x67, + 0x44, 0xBD, 0x61, 0x74, 0x03, 0x32, 0xEB, 0xE2, 0xC7, 0xE5, 0x5D, 0xD2, 0x93, 0x3D, 0x0C, 0xC4, + 0xEA, 0xE2, 0x64, 0x87, 0x75, 0xBF, 0x7C, 0xFF, 0xBA, 0xA3, 0x94, 0xDC, 0xDA, 0xA3, 0xA4, 0x08, + 0xB8, 0xE9, 0x4A, 0xC5, 0x1A, 0xFB, 0xAE, 0xC3, 0x19, 0x06, 0x5C, 0xCB, 0xA4, 0xD5, 0x46, 0x48, + 0xFE, 0x01, 0x7E, 0x89, 0x5B, 0xC0, 0xC1, 0xFA, 0x13, 0xE8, 0x38, 0xC0, 0x0B, 0xCD, 0x1D, 0xDB, + 0x9E, 0x13, 0x26, 0x45, 0xEE, 0x35, 0x59, 0x74, 0x9D, 0x8E, 0xEB, 0x0D, 0x46, 0x53, 0x87, 0x86, + 0x8B, 0xAD, 0xD0, 0x39, 0xF1, 0xA7, 0x1E, 0xF4, 0x51, 0x6B, 0x49, 0x66, 0x99, 0xA3, 0xB9, 0x40, + 0x07, 0xC7, 0xF7, 0x56, 0xFD, 0xEB, 0x6B, 0xD2, 0x3F, 0x20, 0x60, 0x74, 0x6D, 0xA5, 0x06, 0x62, + 0x63, 0xEC, 0xC3, 0x54, 0xC5, 0x8C, 0x7D, 0x4B, 0xC7, 0x81, 0xFF, 0x6E, 0x5C, 0x87, 0x2E, 0xB6, + 0x70, 0x0A, 0x3D, 0xB1, 0x3D, 0x90, 0x7A, 0xD0, 0x5A, 0xDA, 0x51, 0x2A, 0x3D, 0x28, 0x7F, 0x51, + 0xC0, 0xA3, 0x60, 0x8E, 0x82, 0xA9, 0x19, 0x31, 0xCE, 0xDC, 0x15, 0x11, 0xA7, 0xBF, 0x25, 0xE8, + 0xB1, 0x47, 0x00, 0xBB, 0xEA, 0x77, 0x65, 0xE8, 0x64, 0xDC, 0x32, 0xE0, 0x4A, 0x25, 0x92, 0x38, + 0x80, 0x91, 0x1B, 0x8D, 0xD8, 0xAC, 0x7D, 0x7E, 0xF1, 0x17, 0xD6, 0x2D, 0x1A, 0x2C, 0xF4, 0x19, + 0xE9, 0x83, 0xD3, 0x38, 0x69, 0xA9, 0x08, 0x32, 0xF3, 0x26, 0x36, 0x58, 0xAD, 0x62, 0xF4, 0x33, + 0x32, 0x5D, 0xA1, 0xF3, 0x0A, 0xD5, 0x0E, 0x7F, 0xF9, 0x4B, 0x81, 0xE8, 0xAE, 0xC0, 0xCD, 0xD8, + 0xF7, 0xBD, 0x6B, 0x77, 0xA8, 0x4B, 0x2E, 0xAD, 0x33, 0x99, 0x94, 0xD5, 0xA0, 0xD1, 0x0D, 0x0D, + 0x3C, 0x1A, 0x95, 0xD5, 0xF3, 0xA2, 0x52, 0x54, 0x13, 0x3F, 0x88, 0xC2, 0xFC, 0x4A, 0x5C, 0x93, + 0x40, 0x02, 0x40, 0xCF, 0x1E, 0x9D, 0x41, 0xE5, 0x8F, 0x13, 0x36, 0x61, 0xE7, 0x63, 0x84, 0x81, + 0x73, 0xE1, 0xF7, 0x0F, 0xF6, 0xED, 0xC0, 0xC9, 0xC7, 0x38, 0xB4, 0x47, 0xA0, 0x44, 0xFE, 0x07, + 0x1B, 0x3C, 0xD3, 0x28, 0x02, 0x03, 0x91, 0x5F, 0x35, 0x72, 0x47, 0x51, 0x19, 0x83, 0x57, 0x94, + 0x4E, 0x68, 0x00, 0xB5, 0xA2, 0xC0, 0x1F, 0xE5, 0xB3, 0x36, 0x0D, 0xE9, 0x5E, 0x18, 0x82, 0xAF, + 0x79, 0xEA, 0xDF, 0xC5, 0x5E, 0x58, 0x7E, 0xED, 0x31, 0xB5, 0xC3, 0x69, 0xC0, 0xD6, 0x17, 0xE7, + 0xB1, 0xC9, 0xCC, 0x67, 0x61, 0xEC, 0x87, 0xB6, 0x3B, 0x38, 0x3D, 0x39, 0xDC, 0xEB, 0x47, 0x30, + 0x6A, 0xC7, 0x07, 0x81, 0x3F, 0x81, 0x65, 0x5B, 0x91, 0xA4, 0x00, 0xFB, 0x2D, 0xBD, 0x3F, 0xF2, + 0x84, 0x08, 0xC2, 0x42, 0xC6, 0x8F, 0x61, 0xC1, 0x38, 0x72, 0xFF, 0x46, 0x9D, 0x03, 0xE0, 0x3F, + 0x70, 0xAF, 0xA6, 0xD8, 0x0D, 0xE5, 0x8D, 0x00, 0xC8, 0x43, 0x0F, 0xFD, 0xE8, 0xC3, 0xEF, 0x11, + 0x3A, 0x6B, 0xE7, 0xB6, 0xE3, 0xFA, 0x05, 0x9A, 0x25, 0xD5, 0xEA, 0x9F, 0xED, 0x9D, 0x5F, 0x9C, + 0x72, 0xCF, 0x2C, 0x6E, 0x4D, 0x7E, 0xFB, 0xC3, 0x9B, 0x69, 0x84, 0x35, 0x4E, 0xFD, 0xFD, 0x1B, + 0x3B, 0x18, 0xC6, 0xCE, 0xE2, 0x89, 0xEB, 0x4D, 0x23, 0x1A, 0xC6, 0x8C, 0x1E, 0x50, 0x58, 0x1F, + 0xB0, 0x1E, 0xCA, 0x41, 0xC3, 0x1C, 0x3E, 0x3A, 0x1A, 0xB1, 0xC5, 0xF1, 0xA9, 0x7D, 0xEB, 0x0E, + 0xA0, 0x32, 0x18, 0xC6, 0x53, 0x3F, 0x22, 0xE1, 0x74, 0x82, 0xEA, 0x0A, 0xAB, 0x18, 0x98, 0x81, + 0x7E, 0x3F, 0x3C, 0xA8, 0x62, 0xD2, 0x4C, 0x43, 0xF4, 0x9D, 0x3D, 0x80, 0x19, 0xE5, 0xB6, 0x07, + 0xE3, 0xF4, 0x3F, 0xFF, 0x93, 0x14, 0xD5, 0x20, 0xC7, 0x6F, 0xC1, 0x98, 0x67, 0x0D, 0xF5, 0xFC, + 0x06, 0xB4, 0x18, 0x60, 0xA5, 0x03, 0x9A, 0xD7, 0x9B, 0x7D, 0x40, 0x27, 0xDD, 0xFC, 0x73, 0x40, + 0xFF, 0x1C, 0xD0, 0x62, 0x40, 0x3F, 0xD1, 0x50, 0xCC, 0x1D, 0x67, 0x5C, 0xD2, 0xBF, 0x6D, 0xB4, + 0x7E, 0x0E, 0xB3, 0xE7, 0x36, 0xCC, 0x78, 0xB5, 0xAA, 0xC3, 0x4C, 0x0C, 0x9C, 0x8A, 0xC3, 0x4C, + 0x0C, 0xCA, 0x3A, 0xC3, 0x4C, 0x4C, 0x35, 0x15, 0x86, 0x59, 0xC2, 0xF8, 0x63, 0x0F, 0xB3, 0xC4, + 0x43, 0xAA, 0x3F, 0xCC, 0xF8, 0x16, 0x1C, 0xF8, 0x96, 0x43, 0xC0, 0xE0, 0xDC, 0x7B, 0xF6, 0xD8, + 0x1D, 0x9C, 0xF8, 0x0E, 0x35, 0xF6, 0x04, 0x2E, 0x82, 0x3C, 0x7A, 0xC7, 0xD5, 0x48, 0xEC, 0xC7, + 0xF2, 0x3F, 0x16, 0x17, 0xFA, 0x11, 0x8C, 0xD1, 0xC1, 0x42, 0x9B, 0x2C, 0x58, 0x0B, 0xA6, 0x16, + 0x31, 0x3A, 0xB8, 0x81, 0xBC, 0x98, 0x60, 0x68, 0x93, 0xA9, 0xE7, 0xC0, 0x38, 0xF4, 0xA8, 0x63, + 0x80, 0xC8, 0x23, 0xF4, 0xFF, 0xA6, 0x36, 0xAA, 0x41, 0x4C, 0xAD, 0xFB, 0xB8, 0xD4, 0xCE, 0x28, + 0x2C, 0x98, 0xA0, 0xCF, 0x6C, 0x0F, 0x89, 0xF5, 0x1E, 0x97, 0xD8, 0xDE, 0x34, 0xF2, 0xC7, 0x7E, + 0xE4, 0xDE, 0x52, 0x24, 0xB6, 0xF6, 0xB8, 0xC4, 0xCE, 0xC1, 0xEE, 0x11, 0x18, 0xE9, 0x48, 0x6A, + 0xFD, 0x71, 0x49, 0x7D, 0xA0, 0xF6, 0xED, 0x3D, 0x39, 0xB1, 0x07, 0x37, 0x00, 0x18, 0xDC, 0x23, + 0xC5, 0x8D, 0xC7, 0xA5, 0xF8, 0x69, 0xEF, 0x17, 0xA4, 0xB2, 0xF9, 0xC8, 0x54, 0xBC, 0x91, 0x3B, + 0x76, 0x61, 0x06, 0x42, 0x5A, 0x2F, 0x9B, 0xD1, 0xCA, 0x80, 0x0C, 0x99, 0xF9, 0xE2, 0xDB, 0xD2, + 0xCC, 0x74, 0x5D, 0xFB, 0xB8, 0xFC, 0x6B, 0x2D, 0x75, 0x42, 0x1A, 0xED, 0x45, 0xDC, 0x7E, 0xD0, + 0xC5, 0x05, 0xDC, 0x3B, 0x58, 0xB9, 0x0A, 0x57, 0xFC, 0xC0, 0x1D, 0xBA, 0x60, 0xE0, 0x57, 0xD8, + 0x4A, 0x14, 0x39, 0xB9, 0xB8, 0xA1, 0xE4, 0xFD, 0x69, 0xBF, 0x4F, 0x06, 0x36, 0x2C, 0xE4, 0xA7, + 0x11, 0xD8, 0x3E, 0x82, 0xC6, 0x8D, 0x80, 0x1F, 0x49, 0x70, 0xAB, 0xFB, 0x76, 0x8D, 0xD8, 0x11, + 0x71, 0xDC, 0xEB, 0x6B, 0x1A, 0x80, 0x85, 0x24, 0x01, 0xD0, 0x09, 0x3B, 0xE4, 0x9D, 0x1F, 0xB0, + 0x7A, 0xAF, 0x62, 0xAB, 0x60, 0x93, 0x90, 0xD9, 0x43, 0xB6, 0x05, 0x42, 0xA1, 0xFB, 0xE2, 0x2D, + 0x94, 0x36, 0x43, 0x05, 0xFC, 0xC0, 0xFF, 0x89, 0xEB, 0xC1, 0x0C, 0x83, 0xCB, 0xF6, 0xA4, 0x16, + 0x87, 0xE2, 0x08, 0x39, 0xBD, 0x57, 0xF9, 0x95, 0xE3, 0xC3, 0x9A, 0x61, 0xE0, 0x4F, 0x27, 0x1C, + 0x31, 0x65, 0x56, 0x0F, 0xEA, 0x3A, 0xEE, 0xAD, 0xEB, 0x4C, 0xA1, 0xB6, 0xA8, 0x14, 0x76, 0x4C, + 0x42, 0x46, 0x89, 0x05, 0xD1, 0x60, 0xDC, 0x50, 0x5C, 0xC8, 0x21, 0x71, 0x43, 0x58, 0x80, 0xDB, + 0x5E, 0x08, 0xDD, 0x89, 0x1E, 0xC5, 0xD5, 0x3D, 0x81, 0x79, 0x9A, 0xE0, 0x94, 0x8F, 0xA2, 0xB2, + 0x89, 0x23, 0xF6, 0x71, 0xFD, 0x6B, 0xD2, 0xFD, 0xF0, 0x37, 0xC6, 0x7D, 0xCC, 0x13, 0xE9, 0x5A, + 0xD6, 0x46, 0x9B, 0x9C, 0xF4, 0x4F, 0xD6, 0x39, 0xFB, 0x56, 0x27, 0xAE, 0xD2, 0xB5, 0xD6, 0xD6, + 0x3A, 0xE4, 0xE2, 0x06, 0xB0, 0x63, 0x5F, 0x5C, 0x51, 0x32, 0xF2, 0xEF, 0x40, 0xE6, 0x0E, 0x2B, + 0x0D, 0xD0, 0x52, 0x87, 0xE4, 0xCE, 0x8D, 0x6E, 0xF0, 0x3B, 0x50, 0xF3, 0x9C, 0x3B, 0xD7, 0x81, + 0xBF, 0xA0, 0x10, 0xD7, 0x28, 0x3E, 0xD6, 0x8C, 0xFC, 0x84, 0x33, 0xC0, 0x7E, 0xBF, 0x6A, 0x8F, + 0x46, 0x4C, 0xA8, 0xA9, 0x4C, 0xC8, 0x31, 0x6A, 0x61, 0xF8, 0x0A, 0x09, 0x63, 0xF5, 0x4D, 0xCB, + 0xCA, 0x95, 0x13, 0xCD, 0x4C, 0x28, 0x0D, 0x24, 0xC6, 0x67, 0x25, 0x12, 0xBB, 0x16, 0xBC, 0x21, + 0xF2, 0x56, 0xFA, 0xAB, 0x58, 0xCD, 0x60, 0xC8, 0xF0, 0xC9, 0x95, 0xEC, 0x7F, 0x3C, 0xE9, 0x75, + 0x88, 0xD8, 0x0E, 0x7F, 0x45, 0xDE, 0xE1, 0xC6, 0xD1, 0x42, 0xB5, 0x2D, 0x21, 0x83, 0xD3, 0x76, + 0xE1, 0x07, 0x83, 0x9B, 0x7F, 0x22, 0x5F, 0xAD, 0x70, 0x8F, 0x23, 0xA7, 0xB6, 0xE6, 0xAC, 0x55, + 0xF1, 0xA0, 0xFB, 0x20, 0x97, 0x1C, 0x07, 0xFA, 0xD3, 0xC9, 0xF6, 0x96, 0x35, 0xAB, 0x17, 0xCE, + 0x91, 0xD4, 0x5B, 0x28, 0xE1, 0xF6, 0xB3, 0x0F, 0xA3, 0x08, 0xC7, 0xDB, 0xD9, 0xD9, 0x31, 0x81, + 0x6A, 0xE4, 0xE4, 0xFD, 0xDE, 0xBF, 0x10, 0x8E, 0x3D, 0xA0, 0x9D, 0x4E, 0xA7, 0xE6, 0x62, 0x2A, + 0xD7, 0xBB, 0x0D, 0xEC, 0xB4, 0x0B, 0x1E, 0xD1, 0x15, 0x62, 0xBE, 0xE1, 0x13, 0xB8, 0x42, 0x62, + 0x96, 0xEB, 0x3E, 0xA5, 0x57, 0xD2, 0x9B, 0xE3, 0x34, 0xF7, 0xE3, 0x8D, 0x76, 0xD7, 0x7A, 0xB9, + 0x8E, 0x3F, 0xB7, 0xD8, 0xCF, 0x6D, 0xFC, 0xD9, 0xED, 0xFD, 0x70, 0x33, 0x8E, 0x95, 0x7B, 0x56, + 0x07, 0x47, 0x00, 0x7D, 0x45, 0x70, 0x3A, 0x97, 0x34, 0x9D, 0xCD, 0xD6, 0xD8, 0x74, 0xFF, 0x96, + 0x06, 0x81, 0xEB, 0x38, 0xD4, 0xC3, 0xFA, 0xC8, 0xEB, 0xDD, 0x0D, 0xC5, 0x19, 0x96, 0xB0, 0x83, + 0xE4, 0x31, 0xA8, 0x2E, 0x9B, 0x06, 0x1A, 0x9A, 0xD8, 0x33, 0x3F, 0x8C, 0x06, 0xCC, 0xB6, 0xFC, + 0x5C, 0x11, 0x97, 0x19, 0xD9, 0xC7, 0x5E, 0x12, 0xFF, 0xDC, 0x7A, 0xFA, 0xC1, 0x5B, 0x4F, 0x05, + 0x13, 0xE7, 0xF1, 0xFB, 0xDE, 0xB6, 0x75, 0x96, 0x43, 0xDF, 0x38, 0x73, 0xE6, 0x51, 0x94, 0xE7, + 0x1C, 0x89, 0xC1, 0x1A, 0x44, 0x45, 0xD7, 0xB9, 0xDE, 0xE1, 0x88, 0xDE, 0x26, 0x5A, 0xD6, 0x04, + 0xC1, 0xFE, 0xE9, 0xC7, 0x2A, 0xF0, 0xFF, 0x40, 0x66, 0xBD, 0x9B, 0x18, 0xF7, 0x6E, 0x77, 0x6D, + 0xFD, 0x1F, 0xD7, 0x9C, 0xD7, 0x38, 0xEA, 0x94, 0x4E, 0x7C, 0x87, 0x5E, 0x18, 0xC6, 0x31, 0x34, + 0xBF, 0xD0, 0x20, 0x04, 0x75, 0x3C, 0xF2, 0x22, 0xD3, 0xF1, 0x2F, 0xA8, 0x9F, 0x7B, 0x7D, 0x8F, + 0xEB, 0x35, 0x36, 0x88, 0x89, 0x33, 0xA5, 0xC8, 0xD0, 0xB5, 0x00, 0x26, 0x6C, 0xC9, 0xCB, 0xF4, + 0x39, 0xCC, 0x9C, 0x45, 0xE6, 0x1F, 0x46, 0x96, 0x1C, 0x72, 0xCC, 0x78, 0x0C, 0x32, 0x2F, 0xCF, + 0x0D, 0xA7, 0x04, 0x34, 0x2E, 0x4F, 0xE0, 0xBB, 0xF5, 0xB9, 0x0C, 0x6D, 0xBE, 0x1D, 0xD2, 0x7B, + 0xCA, 0x5D, 0xAC, 0xB5, 0xA7, 0xF4, 0x17, 0x1F, 0x79, 0x6B, 0xA9, 0x4F, 0xED, 0x27, 0xD8, 0x4E, + 0xDA, 0x73, 0x83, 0x2B, 0x1F, 0x7C, 0x14, 0xD2, 0x1D, 0x3E, 0xC1, 0xB6, 0x52, 0x42, 0xAD, 0x37, + 0x9C, 0x61, 0x63, 0xA9, 0x36, 0xB5, 0x75, 0x46, 0x6D, 0xEB, 0x71, 0xA9, 0xFD, 0x1A, 0xC0, 0x74, + 0x8F, 0x74, 0xB6, 0x1F, 0x97, 0xCE, 0x5B, 0xF7, 0x1B, 0x53, 0xBF, 0xEE, 0x9C, 0x86, 0x71, 0x1C, + 0x9A, 0xF2, 0x66, 0x97, 0x74, 0x7B, 0x5D, 0x93, 0x11, 0xAA, 0x6D, 0x88, 0xCA, 0x8C, 0xD1, 0x09, + 0x4E, 0x4A, 0xAC, 0x0D, 0xC6, 0x05, 0x5E, 0xB3, 0x76, 0x14, 0xC9, 0xEC, 0x70, 0xA5, 0x3F, 0xF0, + 0x61, 0x8E, 0xE2, 0x44, 0x7B, 0xF3, 0x23, 0xFA, 0x50, 0x3A, 0x69, 0xAD, 0xAE, 0x82, 0x97, 0xC9, + 0xA6, 0x9B, 0x21, 0xC6, 0x95, 0xDB, 0x62, 0xDE, 0xC7, 0x98, 0x9A, 0xA9, 0xE7, 0x46, 0x25, 0x93, + 0x5B, 0xE8, 0xBC, 0x0B, 0x28, 0xED, 0x4F, 0x60, 0xAA, 0x68, 0x2D, 0x29, 0xB4, 0x60, 0x52, 0xD1, + 0x6A, 0xF6, 0xC1, 0xE7, 0x2C, 0xA9, 0x74, 0x03, 0xCE, 0x3E, 0x4E, 0x75, 0x47, 0x07, 0x25, 0x15, + 0x0D, 0x93, 0x6A, 0x09, 0x84, 0x63, 0xDF, 0x87, 0xE7, 0x74, 0x6C, 0xBB, 0x1E, 0x5B, 0x24, 0x14, + 0xD6, 0x9D, 0x04, 0x3E, 0x46, 0x39, 0x59, 0x18, 0xB2, 0x5A, 0xAD, 0x6A, 0xB7, 0x7A, 0xD5, 0x5E, + 0xF5, 0xAA, 0x6B, 0xD5, 0xAB, 0xAE, 0x57, 0xAF, 0xBA, 0x51, 0xBD, 0xEA, 0x66, 0xF5, 0xAA, 0x2F, + 0x2B, 0x54, 0x65, 0x0E, 0xDE, 0xC9, 0xDE, 0x7E, 0x59, 0x57, 0x51, 0xF0, 0xD6, 0xE9, 0xDB, 0x8B, + 0x52, 0x2D, 0x80, 0x25, 0x62, 0x1C, 0x0E, 0x5F, 0x52, 0xF3, 0xCA, 0x06, 0x87, 0x36, 0xB8, 0x3F, + 0xA3, 0xB0, 0x02, 0x41, 0xE7, 0x2B, 0xA9, 0xAC, 0xDB, 0x13, 0x30, 0x1F, 0xAE, 0xB3, 0x04, 0x90, + 0x30, 0x16, 0x3E, 0x5C, 0x9C, 0x1C, 0xEB, 0x11, 0x68, 0x65, 0xDE, 0x5E, 0x10, 0x7D, 0xCB, 0xE8, + 0xA5, 0x81, 0x86, 0xB1, 0x5E, 0x3E, 0xD5, 0x7C, 0xA8, 0x4F, 0x93, 0x21, 0x48, 0x95, 0xB6, 0x66, + 0x60, 0x79, 0x80, 0xAB, 0x8D, 0x60, 0x7C, 0x8E, 0x11, 0xE3, 0x59, 0x66, 0x59, 0x20, 0xF9, 0xBE, + 0x3F, 0x9E, 0x80, 0xC1, 0xA4, 0x8B, 0x4B, 0xB5, 0xD1, 0x62, 0xC8, 0xF9, 0x39, 0x1D, 0x50, 0x77, + 0x62, 0x40, 0x9E, 0xAD, 0xA3, 0x52, 0x28, 0x21, 0x21, 0x54, 0x8F, 0xDF, 0x7D, 0x30, 0x60, 0x9F, + 0x06, 0x78, 0xC8, 0x72, 0x26, 0xD7, 0x32, 0x49, 0xF6, 0x8F, 0x8B, 0x2D, 0x17, 0x97, 0xE4, 0x5F, + 0xF0, 0x26, 0xCE, 0xAE, 0x40, 0xCA, 0x16, 0xAE, 0x5F, 0xBF, 0xDC, 0x62, 0x98, 0xFE, 0x2E, 0x46, + 0x17, 0x1A, 0xB1, 0x2D, 0x93, 0xD6, 0x57, 0x90, 0x3D, 0xC0, 0x4C, 0x16, 0x17, 0x58, 0x30, 0x3D, + 0x3B, 0x92, 0xC2, 0x88, 0xC2, 0x1A, 0xA2, 0x8A, 0x3D, 0xFC, 0x4F, 0x13, 0xBC, 0xD4, 0x13, 0x0B, + 0x3B, 0xDB, 0x20, 0x73, 0xBD, 0xC5, 0xC6, 0x94, 0xD0, 0x13, 0x9E, 0x86, 0x65, 0x74, 0x78, 0xAD, + 0x45, 0x1E, 0xF4, 0x5A, 0x79, 0xD5, 0x93, 0xDE, 0xA2, 0x31, 0x0D, 0x00, 0xF9, 0x8A, 0x8D, 0x49, + 0xD3, 0x67, 0x1A, 0x83, 0xD2, 0x45, 0x9D, 0x02, 0xDA, 0x6C, 0x12, 0x7E, 0x34, 0xDA, 0x7B, 0xA3, + 0x82, 0x76, 0xF3, 0x6B, 0x42, 0x73, 0xA7, 0xCD, 0xEE, 0x1A, 0x65, 0xA9, 0xC6, 0x57, 0x90, 0x1E, + 0x85, 0xDE, 0x67, 0x33, 0xBD, 0xCF, 0x8F, 0x45, 0xEF, 0x77, 0x33, 0xBD, 0xDF, 0x1F, 0x85, 0x5E, + 0x38, 0xF1, 0xFC, 0xBB, 0x33, 0x8A, 0x1B, 0x82, 0x53, 0xD3, 0x92, 0x3D, 0x71, 0x4D, 0x89, 0xB5, + 0x64, 0xDC, 0x8F, 0x99, 0x00, 0x2C, 0xCC, 0x77, 0xA1, 0x66, 0x9E, 0x5B, 0xAD, 0x26, 0x4C, 0x5C, + 0xE6, 0x32, 0xF0, 0xC5, 0xFA, 0x4A, 0xFE, 0x00, 0x68, 0xAD, 0x16, 0xF9, 0xD3, 0x9F, 0xB0, 0x8D, + 0x5F, 0xBA, 0xF1, 0x07, 0x93, 0xBF, 0x9C, 0xCB, 0xD9, 0x32, 0x13, 0x10, 0x1A, 0xB5, 0xD7, 0x57, + 0xC1, 0x9B, 0x56, 0xD3, 0x1D, 0x8F, 0x90, 0x2F, 0xB0, 0xF1, 0x22, 0x93, 0x69, 0x3E, 0x49, 0x6E, + 0x39, 0x75, 0x26, 0xD3, 0xF0, 0xA6, 0xA6, 0x5D, 0x11, 0xB8, 0xE3, 0xEB, 0x50, 0xB9, 0xF8, 0xE3, + 0x0A, 0x4D, 0x68, 0x5C, 0x8F, 0xB9, 0x47, 0xA1, 0xA3, 0xD6, 0xAE, 0xDF, 0xD5, 0xD2, 0xA5, 0xEB, + 0x31, 0x77, 0x7F, 0xB3, 0xA6, 0x56, 0xBE, 0xE9, 0x06, 0x1D, 0xD0, 0x7A, 0x1D, 0x05, 0xC4, 0x1E, + 0xB9, 0x43, 0x6F, 0x77, 0x61, 0x44, 0xAF, 0xA3, 0x05, 0xBD, 0x1F, 0x4C, 0x10, 0xCE, 0x1B, 0x9C, + 0xA1, 0x14, 0xFE, 0xB0, 0x13, 0x57, 0xB1, 0xA0, 0x2A, 0x74, 0xDC, 0xF3, 0x95, 0x81, 0x5E, 0xB3, + 0x49, 0x93, 0x44, 0xF7, 0x13, 0xBA, 0xCB, 0xE7, 0xBE, 0x2B, 0xFF, 0xFB, 0x02, 0xF8, 0x5D, 0xBB, + 0x0B, 0x26, 0x6E, 0x16, 0x08, 0x9B, 0x5E, 0x17, 0x10, 0xD9, 0xD1, 0xC1, 0x02, 0x19, 0x40, 0x85, + 0x10, 0xFE, 0xF4, 0x83, 0xF1, 0x0A, 0x83, 0x5E, 0xE1, 0xF8, 0xA4, 0xFB, 0x05, 0x6C, 0x53, 0x7A, + 0xE1, 0x4D, 0x45, 0x96, 0x56, 0x23, 0x45, 0x67, 0x2B, 0xF4, 0x32, 0xDB, 0x21, 0xD5, 0x7B, 0x04, + 0xEF, 0xC9, 0x21, 0xDF, 0x75, 0xA6, 0xD5, 0xE9, 0xD5, 0xF7, 0x93, 0x34, 0x70, 0x84, 0xE1, 0x84, + 0x85, 0x15, 0x51, 0x3F, 0x5F, 0xE2, 0x96, 0xFE, 0xE5, 0xC1, 0xC5, 0x89, 0xF6, 0x1D, 0x37, 0x19, + 0x2F, 0x71, 0x07, 0xF3, 0x12, 0xB7, 0x50, 0x15, 0x5E, 0xA4, 0xAB, 0x8D, 0x42, 0xE9, 0x5C, 0x67, + 0x27, 0xAF, 0xC6, 0x39, 0xBF, 0xCD, 0x90, 0x31, 0x83, 0x1A, 0x92, 0x63, 0xFB, 0x8A, 0x8E, 0x4C, + 0x57, 0x1A, 0xA4, 0x7A, 0x07, 0xE2, 0x4E, 0x4E, 0x0A, 0x15, 0xDF, 0xCD, 0xB9, 0xD4, 0xD7, 0xA6, + 0x28, 0x0B, 0x09, 0x2A, 0xBE, 0x9A, 0x03, 0xAB, 0xF5, 0x35, 0x93, 0xED, 0x91, 0x2F, 0x6B, 0xF2, + 0x0B, 0x48, 0x12, 0x30, 0x98, 0xAD, 0x9D, 0x22, 0xB9, 0xED, 0xB2, 0x20, 0x19, 0xE3, 0x0E, 0x81, + 0x7E, 0xD5, 0xF3, 0x0F, 0xBB, 0x32, 0x99, 0xBC, 0x5D, 0x83, 0xEC, 0x05, 0x51, 0x09, 0xC8, 0xBC, + 0x06, 0x97, 0x6F, 0x9A, 0x32, 0xB5, 0xBB, 0xC9, 0x58, 0x4A, 0xCD, 0x77, 0xD5, 0x20, 0xE5, 0x3E, + 0x50, 0xDB, 0x8E, 0xA3, 0xE4, 0x92, 0xDD, 0x90, 0x92, 0x3E, 0xF7, 0x4C, 0x22, 0x51, 0x55, 0x06, + 0x10, 0x99, 0xD5, 0xA7, 0xA0, 0x7F, 0x76, 0x77, 0xC9, 0x7A, 0x9E, 0x54, 0x9A, 0x32, 0x6A, 0xFC, + 0xBC, 0x66, 0xEC, 0x52, 0xC6, 0xEF, 0xBA, 0xF5, 0xB2, 0x77, 0x69, 0xC5, 0xDC, 0xF3, 0xBF, 0x4A, + 0x77, 0x30, 0x5E, 0x14, 0x76, 0x86, 0xE3, 0xDE, 0x2A, 0x86, 0x85, 0x85, 0x36, 0x91, 0xC0, 0xBF, + 0xE3, 0x76, 0x69, 0x1C, 0x0E, 0x25, 0xFE, 0x12, 0xCB, 0xA4, 0x77, 0x60, 0x06, 0xED, 0x88, 0x89, + 0x01, 0x30, 0x72, 0xD3, 0xA6, 0xC3, 0xC7, 0x24, 0x07, 0xFE, 0x68, 0x25, 0x1C, 0xAF, 0xAC, 0x13, + 0xFC, 0x65, 0x93, 0xFD, 0x64, 0x5C, 0x30, 0xF0, 0x85, 0x37, 0x1A, 0x28, 0x97, 0x2D, 0xC0, 0xBF, + 0x7A, 0xBD, 0xCA, 0x6A, 0x94, 0xB2, 0x21, 0xB5, 0x4E, 0x21, 0xB5, 0xBE, 0xA0, 0x1A, 0x63, 0x7E, + 0xF9, 0x5B, 0x33, 0xB1, 0xFC, 0x4C, 0x73, 0xA1, 0x84, 0x46, 0x62, 0xBE, 0x33, 0x6D, 0xE4, 0x2B, + 0x21, 0xB9, 0x8C, 0x19, 0x9C, 0x4A, 0xF2, 0x9B, 0xE4, 0xA1, 0x3D, 0x0C, 0x02, 0x3F, 0x65, 0xD4, + 0xF5, 0x46, 0xAE, 0x47, 0xF9, 0x37, 0xB0, 0xFA, 0x93, 0x52, 0xBC, 0xAB, 0x20, 0x91, 0x37, 0xFC, + 0x67, 0x0D, 0xCB, 0x3F, 0x96, 0x4D, 0x75, 0x66, 0xAB, 0x40, 0x94, 0x1E, 0x89, 0x70, 0x39, 0xD4, + 0x4D, 0xD3, 0x61, 0x8D, 0x2C, 0x04, 0x66, 0xA0, 0xDE, 0x9F, 0x81, 0x89, 0x2A, 0xA8, 0x84, 0x88, + 0xCE, 0xF1, 0xA8, 0x89, 0x29, 0x3F, 0x8C, 0xD5, 0x6E, 0x41, 0xE5, 0x10, 0xEB, 0x24, 0xA3, 0xBC, + 0xA0, 0xB2, 0xCC, 0xA6, 0x84, 0xBD, 0xB7, 0x66, 0x55, 0x00, 0x48, 0x09, 0xE8, 0xF5, 0x9B, 0x4C, + 0x3C, 0xEC, 0x56, 0xE8, 0x3B, 0x58, 0x31, 0x46, 0x9A, 0xBF, 0x55, 0x32, 0x09, 0xE9, 0xD5, 0xFE, + 0x3A, 0x05, 0xF7, 0xE7, 0xDA, 0x65, 0x6B, 0x75, 0xBD, 0x3C, 0xAF, 0x2F, 0x8B, 0x7B, 0x0B, 0xFF, + 0x29, 0x58, 0x93, 0x60, 0xC8, 0x56, 0x91, 0x75, 0x69, 0x36, 0x21, 0x96, 0x5A, 0xCF, 0x9D, 0x7F, + 0x42, 0x1B, 0x96, 0x4A, 0xF7, 0xA7, 0x3D, 0xFB, 0x51, 0xF6, 0x8C, 0x47, 0x8B, 0xA0, 0x2D, 0x2A, + 0xB2, 0x57, 0x69, 0xAD, 0xCB, 0xF7, 0xEF, 0xF7, 0x9A, 0x0F, 0xFA, 0x47, 0x70, 0x25, 0xE7, 0x32, + 0x72, 0xFE, 0x09, 0xA6, 0x79, 0x71, 0x96, 0xC5, 0x97, 0x4B, 0x46, 0x46, 0x72, 0x95, 0x5A, 0x1E, + 0x21, 0x8E, 0x08, 0x64, 0x21, 0xE3, 0xAB, 0x95, 0x5E, 0x79, 0xE3, 0x7D, 0x7E, 0x30, 0x25, 0x86, + 0x85, 0xB5, 0xF0, 0xE6, 0xE3, 0xF5, 0xF5, 0xEB, 0x55, 0xFE, 0xB5, 0x26, 0x70, 0x77, 0xE1, 0x0D, + 0x57, 0xB3, 0x6E, 0x43, 0x04, 0xBD, 0x18, 0x41, 0xAF, 0x32, 0x82, 0x55, 0x2E, 0xB5, 0x6A, 0x43, + 0x4C, 0xD7, 0x57, 0x18, 0x1E, 0x7D, 0xFB, 0x96, 0xB2, 0x68, 0x17, 0x14, 0x3B, 0x8B, 0x42, 0x64, + 0xBC, 0x10, 0x3B, 0x24, 0x77, 0x14, 0xA3, 0x55, 0x16, 0x22, 0x16, 0x49, 0x8F, 0x55, 0x78, 0xC9, + 0x3D, 0x8D, 0x3A, 0x0A, 0xFE, 0x1B, 0xA8, 0xEB, 0xF9, 0x11, 0x16, 0x90, 0x2B, 0x4A, 0x3D, 0x62, + 0x3B, 0x0E, 0x0F, 0x58, 0x49, 0xB6, 0x58, 0xD4, 0x95, 0xA6, 0x9E, 0x65, 0x86, 0x6F, 0x56, 0x48, + 0x9D, 0xAA, 0x0D, 0x90, 0x6C, 0xEA, 0x99, 0x26, 0xDB, 0x1B, 0x02, 0x3F, 0x0F, 0xE6, 0x72, 0xCA, + 0xFC, 0x1B, 0xA9, 0x5A, 0x25, 0xFF, 0x42, 0xAA, 0x3F, 0x27, 0xF7, 0xE2, 0xB9, 0x5A, 0x9A, 0xCC, + 0x06, 0x06, 0x19, 0x47, 0x2B, 0x6B, 0x55, 0xAD, 0x4C, 0x76, 0xFB, 0x83, 0x9B, 0x8F, 0x7C, 0xF3, + 0xF3, 0x46, 0x04, 0xFF, 0xE7, 0xD9, 0x97, 0xAA, 0xE6, 0x85, 0xCF, 0xAC, 0x39, 0xDB, 0x2F, 0x0B, + 0xB9, 0xFB, 0x39, 0xB5, 0xAD, 0xE9, 0xAC, 0x23, 0x2D, 0x39, 0x4F, 0x99, 0xD3, 0x48, 0x53, 0xD2, + 0x32, 0x55, 0x1A, 0x6A, 0x6A, 0xAE, 0xA6, 0x26, 0x63, 0x4D, 0xBA, 0x99, 0x21, 0xD2, 0x1B, 0xDD, + 0x67, 0x07, 0x9B, 0x9A, 0x0D, 0xA9, 0x60, 0x40, 0xA4, 0x95, 0x62, 0x64, 0xB1, 0xDB, 0x0D, 0xFE, + 0x6F, 0x8E, 0xD3, 0x9D, 0xC2, 0x88, 0xF1, 0xA1, 0x52, 0xCA, 0x1D, 0x22, 0x59, 0xA6, 0xE2, 0x91, + 0xA2, 0x62, 0xCC, 0x0E, 0x16, 0x14, 0x82, 0x39, 0xFB, 0x53, 0xBC, 0xF9, 0xF0, 0xDA, 0x9C, 0x3C, + 0xCA, 0xE4, 0xB6, 0xE7, 0x20, 0x62, 0x5D, 0x61, 0x60, 0xCF, 0x10, 0x02, 0x51, 0x90, 0x67, 0x4A, + 0x47, 0x13, 0x4B, 0xB5, 0xF4, 0x72, 0x8C, 0x81, 0x88, 0x94, 0x37, 0xE6, 0xC2, 0xF7, 0xC9, 0xD8, + 0xF6, 0xEE, 0x65, 0xD2, 0x24, 0xE4, 0x6D, 0x6C, 0xD5, 0x51, 0x1E, 0x54, 0x3F, 0xD7, 0x1B, 0x4A, + 0x49, 0xB8, 0x0C, 0x87, 0x9C, 0xD9, 0x4A, 0x75, 0x76, 0x2E, 0xBD, 0x14, 0x2C, 0xF7, 0xBC, 0x3A, + 0x5B, 0xA7, 0xF6, 0x61, 0x20, 0x8B, 0x68, 0x2C, 0x6C, 0x47, 0xB6, 0x4E, 0x9D, 0x66, 0xF8, 0x91, + 0x1D, 0x83, 0xE5, 0x1D, 0x6A, 0x66, 0xAA, 0xD4, 0x6C, 0x84, 0x08, 0x21, 0x38, 0x82, 0xAE, 0x4E, + 0x83, 0x0E, 0x4C, 0x47, 0xFB, 0xC6, 0x8A, 0x9D, 0x30, 0x18, 0xD4, 0x3F, 0x98, 0xCF, 0x24, 0x6C, + 0x32, 0x1D, 0xA1, 0x9B, 0xB2, 0x3A, 0xD5, 0x3B, 0x9B, 0x10, 0xF9, 0x12, 0x4D, 0xA7, 0x13, 0x49, + 0x26, 0xC5, 0x06, 0x18, 0x7D, 0x0C, 0xB4, 0x31, 0xA3, 0xE4, 0xA9, 0x18, 0xEB, 0x45, 0x56, 0xD0, + 0x2B, 0xDF, 0x8F, 0x33, 0x8A, 0x14, 0x9F, 0xC5, 0xE5, 0x9C, 0x79, 0x69, 0x18, 0x3A, 0x7C, 0xDA, + 0x31, 0xEC, 0x98, 0xAB, 0x57, 0xF6, 0x30, 0xAA, 0x52, 0x04, 0x47, 0x74, 0xC4, 0x94, 0x64, 0x4C, + 0x1A, 0x24, 0xC5, 0xBE, 0x27, 0x70, 0x63, 0xBC, 0x2C, 0xCD, 0x80, 0x79, 0xEE, 0x93, 0xB0, 0x42, + 0x2E, 0xA6, 0x7A, 0xCC, 0x5B, 0xF5, 0x59, 0x17, 0x79, 0x02, 0x73, 0xEE, 0x84, 0x34, 0xE1, 0xBD, + 0xF4, 0xD4, 0xAE, 0x30, 0x3D, 0x4C, 0xA3, 0xCE, 0x2C, 0x43, 0x59, 0xDE, 0xBB, 0xD5, 0x72, 0xD6, + 0x54, 0xEE, 0xF4, 0x62, 0x74, 0xB3, 0x76, 0x7F, 0xE5, 0xE6, 0x5A, 0x73, 0x6B, 0x6C, 0xA1, 0x9A, + 0xCC, 0xD8, 0xDA, 0x07, 0x39, 0x7B, 0xDA, 0x3E, 0xCF, 0x5B, 0x07, 0xBE, 0x5B, 0x9C, 0x2E, 0x6E, + 0x8C, 0xAE, 0x1C, 0x26, 0xC9, 0xC5, 0xFB, 0xC7, 0x60, 0x4C, 0xC3, 0x12, 0xFD, 0xB2, 0xBD, 0x88, + 0x7A, 0x9E, 0xFD, 0x81, 0xBA, 0xC3, 0x9B, 0xE8, 0x72, 0x3C, 0x36, 0x1B, 0x66, 0xAD, 0x96, 0xAA, + 0x23, 0x64, 0x15, 0x6F, 0x30, 0xB0, 0x64, 0x79, 0xE6, 0xCE, 0x91, 0x19, 0x66, 0xDE, 0x3E, 0xC8, + 0x8B, 0x86, 0x00, 0xC6, 0xEF, 0xE0, 0x5E, 0x4D, 0xA3, 0x48, 0x0E, 0xCC, 0xAF, 0x96, 0x56, 0x2D, + 0x0A, 0xEE, 0xCD, 0x1D, 0x8E, 0x81, 0x0B, 0x45, 0x7A, 0xF7, 0x00, 0x8E, 0x72, 0x34, 0xB8, 0x21, + 0x8B, 0x14, 0x77, 0x97, 0xCC, 0x9E, 0x93, 0xE4, 0x92, 0xF4, 0xC1, 0x51, 0xBE, 0x00, 0x24, 0xC4, + 0x0D, 0x43, 0xF8, 0xC9, 0xAE, 0x58, 0x1C, 0x1D, 0xC4, 0xE9, 0xED, 0xEA, 0x8C, 0xEB, 0xE2, 0xFC, + 0x73, 0x15, 0xDB, 0x63, 0x50, 0xAD, 0x06, 0x0D, 0x62, 0x37, 0x99, 0x6B, 0xB7, 0x48, 0xEA, 0xC7, + 0xBD, 0xD1, 0x88, 0x04, 0x74, 0x38, 0x1D, 0x61, 0xC2, 0x40, 0xB6, 0x2A, 0xE2, 0x7D, 0x9A, 0xAC, + 0x49, 0xB4, 0xEE, 0xAC, 0xD1, 0xD6, 0x5C, 0xEB, 0x53, 0xB3, 0x9D, 0x47, 0x0D, 0xFA, 0xEB, 0xC1, + 0x94, 0x8B, 0x31, 0xBE, 0x1A, 0x46, 0x30, 0xA4, 0x8B, 0xA6, 0x57, 0xEA, 0x58, 0x30, 0x08, 0x8F, + 0x69, 0x83, 0x91, 0xEC, 0x0D, 0xA9, 0xD8, 0x5F, 0xD0, 0x42, 0x56, 0x16, 0x16, 0x76, 0x5E, 0xA4, + 0x53, 0x11, 0xCC, 0x09, 0x22, 0x0E, 0xEE, 0x24, 0x1C, 0x1A, 0x6A, 0x0A, 0x06, 0x0E, 0x7C, 0x5C, + 0xCB, 0x4D, 0x79, 0x9E, 0x3D, 0x50, 0x1E, 0xBC, 0xAA, 0x03, 0x4B, 0xBC, 0x00, 0x43, 0xFD, 0x60, + 0x79, 0x45, 0xEE, 0x60, 0x19, 0x97, 0xFA, 0x2F, 0xD0, 0x05, 0xD7, 0xFE, 0x8B, 0xD8, 0xFC, 0xEB, + 0x59, 0xFA, 0xF8, 0x20, 0x90, 0xE5, 0x95, 0x9B, 0xFF, 0x36, 0xED, 0xE0, 0x77, 0x3E, 0xF8, 0xDC, + 0xD0, 0x77, 0xFC, 0xBE, 0x0F, 0x67, 0x24, 0xED, 0xD3, 0x61, 0x36, 0x5D, 0xCD, 0x87, 0xBF, 0x41, + 0x6B, 0x1C, 0x37, 0x9C, 0x60, 0x1F, 0xB1, 0x84, 0xDB, 0x18, 0x69, 0x4D, 0xF6, 0xA7, 0x21, 0xCC, + 0x87, 0xFC, 0x6F, 0x58, 0x96, 0xA2, 0x98, 0x16, 0x96, 0xA4, 0x5E, 0x30, 0x60, 0xEA, 0xD3, 0x41, + 0x63, 0x54, 0x78, 0xE1, 0x0A, 0x1D, 0xB9, 0xBE, 0xB8, 0xD6, 0x37, 0x33, 0xA2, 0x77, 0xE8, 0x74, + 0x35, 0xC6, 0xC2, 0x5C, 0xB6, 0xB7, 0xEC, 0xC6, 0xA9, 0x9C, 0x2B, 0x94, 0xC7, 0xF7, 0xCC, 0x17, + 0xE7, 0x7B, 0xEA, 0x37, 0x46, 0xC9, 0x3D, 0x97, 0xD3, 0x28, 0x70, 0x27, 0x7D, 0x0A, 0x82, 0x0B, + 0xE6, 0x81, 0x69, 0x7F, 0xE4, 0xB2, 0x80, 0xE1, 0x86, 0x98, 0xF0, 0xBE, 0x1D, 0x5E, 0x6D, 0xC2, + 0xA1, 0xE5, 0xE1, 0x65, 0x84, 0x99, 0x38, 0x3A, 0xF3, 0x5D, 0x2F, 0x3A, 0xA3, 0xC1, 0x35, 0x2C, + 0x2A, 0xA5, 0xE5, 0xF3, 0x8C, 0x58, 0x0F, 0xE3, 0x5B, 0xB9, 0x53, 0x66, 0xD1, 0xE7, 0x82, 0xEB, + 0x83, 0x08, 0xE4, 0xE7, 0x39, 0xEB, 0xFD, 0xE1, 0x90, 0x05, 0xDD, 0xCF, 0x86, 0x3A, 0x9C, 0x9C, + 0xFA, 0x77, 0x33, 0x22, 0x39, 0xF6, 0x03, 0xBB, 0x31, 0x0A, 0xE1, 0x3F, 0x9C, 0xDD, 0xA0, 0xDA, + 0x52, 0x3C, 0x41, 0x64, 0xAE, 0xC6, 0x8C, 0x0C, 0xCD, 0x43, 0x36, 0x02, 0xCB, 0xF9, 0xD1, 0xE9, + 0xE1, 0x6F, 0x33, 0xA2, 0xDA, 0x3B, 0x3F, 0x9B, 0x0F, 0x4F, 0xB8, 0x84, 0x78, 0x97, 0x04, 0x12, + 0x3B, 0xEC, 0xB0, 0x7D, 0x66, 0x84, 0xF1, 0x62, 0xA6, 0x19, 0x9E, 0xBC, 0xCB, 0xCF, 0xB5, 0x10, + 0x26, 0x18, 0xF9, 0x74, 0x82, 0x56, 0x10, 0x13, 0xD8, 0xCB, 0xBB, 0x15, 0xBC, 0x24, 0x0E, 0x41, + 0xD4, 0x4B, 0xA3, 0x81, 0xB0, 0x2A, 0x6F, 0xD1, 0xD9, 0xD0, 0x4A, 0xB8, 0xE5, 0xCA, 0x94, 0x4C, + 0x9D, 0x49, 0xE6, 0x9B, 0x73, 0x33, 0x98, 0x1C, 0x8A, 0x1B, 0xFC, 0x59, 0xEA, 0xB0, 0x6A, 0xC7, + 0x55, 0x76, 0xB6, 0x60, 0x3F, 0xB3, 0x25, 0xE9, 0xA6, 0x78, 0x1F, 0x94, 0xE7, 0x17, 0x98, 0xAB, + 0x0F, 0xEE, 0x86, 0x98, 0x74, 0x85, 0x6B, 0x13, 0x46, 0xF7, 0xE0, 0x54, 0xA0, 0xC0, 0x46, 0xEC, + 0x6D, 0x8B, 0x96, 0xE7, 0x7B, 0xB4, 0xA5, 0x3E, 0xDC, 0xC0, 0x96, 0x44, 0xE5, 0x90, 0x57, 0xE0, + 0xE3, 0x7F, 0xE3, 0xA0, 0xE0, 0x55, 0x07, 0x14, 0xE7, 0xF1, 0xFD, 0xFE, 0x2F, 0x78, 0xBF, 0x18, + 0x7D, 0x05, 0x71, 0x13, 0x96, 0x25, 0x6B, 0x96, 0x70, 0x8B, 0x44, 0xF6, 0xC9, 0x43, 0x15, 0x3C, + 0xBB, 0x3D, 0xAB, 0x8A, 0xC0, 0xD2, 0x29, 0xC1, 0xEA, 0xEA, 0x51, 0xEA, 0xD6, 0x25, 0x75, 0x07, + 0xA3, 0x50, 0xBC, 0x1C, 0x81, 0xC9, 0xE4, 0x93, 0x7C, 0xC2, 0x7F, 0x9D, 0xD2, 0xE0, 0x9E, 0x3F, + 0x95, 0xE0, 0x07, 0xE0, 0x1A, 0x2E, 0xB6, 0x3A, 0xF2, 0x49, 0x73, 0x9B, 0x74, 0x94, 0x63, 0xB5, + 0x56, 0x41, 0x92, 0x6A, 0x89, 0x82, 0xD8, 0xF3, 0x84, 0xEF, 0xCB, 0xCB, 0xB2, 0xF7, 0x22, 0x31, + 0xBC, 0xBC, 0x2B, 0x03, 0x7C, 0xF9, 0xFE, 0xB5, 0x23, 0x32, 0x4E, 0xB3, 0x6B, 0x07, 0x6A, 0x09, + 0xF7, 0x2B, 0x59, 0x61, 0xDC, 0x63, 0x2F, 0x32, 0x8B, 0x92, 0xB6, 0x61, 0x4D, 0xB2, 0xBA, 0x7A, + 0x4E, 0xC7, 0xFE, 0x2D, 0x65, 0x91, 0x93, 0xB8, 0x3D, 0x89, 0x01, 0x96, 0xEC, 0x0F, 0x5E, 0x5E, + 0x57, 0x28, 0xE9, 0x91, 0xC1, 0x2B, 0xCF, 0x8F, 0x16, 0x3B, 0x7A, 0xD8, 0xE6, 0x52, 0x2C, 0xAF, + 0x40, 0xCE, 0x13, 0xF0, 0xB4, 0xC2, 0x8A, 0x17, 0x1C, 0x59, 0x71, 0x99, 0xF8, 0x90, 0x23, 0x93, + 0x2B, 0xF1, 0xA1, 0x04, 0x3A, 0x03, 0x11, 0x4C, 0x39, 0xBD, 0xD0, 0x5E, 0x80, 0x9F, 0x12, 0x2A, + 0xE0, 0xA3, 0x1E, 0xFD, 0x24, 0x72, 0xB9, 0x16, 0x0F, 0x49, 0x40, 0xB4, 0x89, 0x8F, 0xB8, 0xB0, + 0x3A, 0x2F, 0x85, 0xFB, 0xF7, 0x65, 0x2C, 0x19, 0x0E, 0x3D, 0x58, 0x58, 0xA0, 0x19, 0x29, 0x67, + 0x8A, 0xF3, 0x5B, 0xB0, 0x57, 0x6F, 0xE6, 0x5D, 0x5B, 0xE2, 0x78, 0xE0, 0x49, 0x0E, 0xF9, 0x2A, + 0x29, 0xE5, 0x29, 0xF3, 0x4C, 0x0D, 0x1A, 0x90, 0x45, 0xA5, 0xFC, 0x45, 0x1C, 0xF8, 0x2B, 0x3D, + 0x90, 0x01, 0xC2, 0x48, 0x9F, 0xD0, 0x58, 0x8C, 0x0B, 0xDB, 0xA4, 0x67, 0x59, 0xD6, 0x52, 0xD6, + 0xDA, 0xB1, 0x28, 0x0F, 0xB0, 0x72, 0x6D, 0xC2, 0x16, 0x76, 0x78, 0x4C, 0xA5, 0x58, 0x3F, 0x6C, + 0x23, 0x8F, 0x04, 0xD1, 0x96, 0x4B, 0x18, 0x6A, 0xCF, 0x0A, 0x5E, 0x11, 0x14, 0x41, 0x02, 0x8D, + 0x24, 0x12, 0x0A, 0x83, 0x11, 0xB5, 0x83, 0x98, 0x44, 0x35, 0xBC, 0x0B, 0x59, 0x1E, 0xFB, 0xD3, + 0xC1, 0x00, 0x56, 0x77, 0x8C, 0x4B, 0x29, 0x6B, 0x7F, 0x82, 0x47, 0x94, 0x9B, 0x38, 0x5C, 0xE0, + 0x89, 0xFB, 0xB3, 0x4C, 0xA5, 0x38, 0xAB, 0xA2, 0x33, 0x30, 0x06, 0xAB, 0xC8, 0x98, 0x29, 0x21, + 0xBF, 0x78, 0x39, 0x97, 0xBC, 0x5F, 0x74, 0x2D, 0x56, 0xCC, 0xA6, 0x95, 0x60, 0x76, 0x25, 0x1E, + 0xEF, 0x38, 0xE0, 0x21, 0x27, 0xCE, 0xBF, 0x9D, 0x80, 0x19, 0xBF, 0x45, 0x11, 0x92, 0x93, 0x70, + 0xB6, 0x53, 0x0C, 0x85, 0x37, 0x6D, 0x95, 0x28, 0x1E, 0xE3, 0x79, 0x01, 0x5F, 0xD0, 0xFF, 0x5D, + 0x59, 0x7D, 0x6B, 0xFB, 0x05, 0xB5, 0x39, 0xCC, 0x90, 0x2B, 0xE3, 0xCF, 0xD0, 0xA4, 0x62, 0x0E, + 0x0D, 0xB7, 0x63, 0x72, 0x7B, 0x5A, 0xF4, 0x51, 0xAA, 0xE3, 0x92, 0xF6, 0xC8, 0xFD, 0xD7, 0x12, + 0x8A, 0x2C, 0x9E, 0x79, 0x48, 0x2E, 0xC2, 0xE9, 0x4A, 0x23, 0xF5, 0xB7, 0xE6, 0x22, 0x18, 0x34, + 0x85, 0x3D, 0x89, 0x84, 0x78, 0xD9, 0x2D, 0x1C, 0xBE, 0xC5, 0x29, 0xE1, 0x43, 0x1B, 0x2F, 0xC7, + 0x44, 0x7C, 0x7A, 0xFB, 0x9B, 0xA4, 0x8C, 0xAC, 0x58, 0xCC, 0x09, 0xAC, 0x98, 0xD1, 0xB5, 0x60, + 0x18, 0x6F, 0x6C, 0x00, 0xBF, 0x27, 0xE0, 0xE4, 0x61, 0x1A, 0x92, 0x2B, 0x1A, 0xDD, 0xE1, 0x39, + 0xB2, 0xC5, 0xF6, 0x7E, 0xA0, 0xAC, 0xD5, 0x46, 0x3B, 0x36, 0x1A, 0xD9, 0x93, 0x90, 0x62, 0x46, + 0x47, 0x9E, 0x92, 0x85, 0xED, 0x76, 0xA8, 0xEA, 0x6B, 0xA2, 0x8F, 0xEB, 0xDA, 0xC7, 0xE4, 0x01, + 0xF1, 0x97, 0xF3, 0x81, 0x19, 0xE1, 0xAA, 0x70, 0xB1, 0x99, 0xCF, 0xC4, 0xE6, 0x2C, 0x72, 0x40, + 0xFA, 0x55, 0x25, 0xD1, 0x8C, 0x07, 0xA3, 0x1C, 0x44, 0xC5, 0x3E, 0x9F, 0x47, 0xC0, 0x70, 0x0F, + 0xF8, 0x35, 0xF9, 0x01, 0xAC, 0x43, 0x64, 0x93, 0x2C, 0x0A, 0x4C, 0x43, 0x10, 0x55, 0x3A, 0x1E, + 0x48, 0x50, 0x93, 0x43, 0x9A, 0x86, 0x2A, 0x4C, 0x3F, 0x2B, 0xAC, 0x74, 0x05, 0x3D, 0xC2, 0x9A, + 0x20, 0xD3, 0x49, 0x11, 0x00, 0x1F, 0xDA, 0x59, 0x02, 0x72, 0x5B, 0xC1, 0x19, 0x74, 0xD1, 0xA5, + 0x7F, 0xE7, 0xD2, 0x91, 0x13, 0x2E, 0xA6, 0xAF, 0xB0, 0xEC, 0x0B, 0x21, 0x08, 0x2F, 0x7A, 0x90, + 0xE6, 0x8C, 0xD1, 0xC5, 0x93, 0x08, 0x56, 0xEC, 0xE7, 0x89, 0xD4, 0x43, 0x20, 0xF1, 0x78, 0x53, + 0x10, 0xA9, 0xC7, 0xEE, 0x5B, 0x2E, 0x74, 0xDA, 0x2D, 0x08, 0x8A, 0xB7, 0xF3, 0xEB, 0xC2, 0xA1, + 0x4A, 0x09, 0x50, 0xF8, 0xB5, 0x1A, 0xF4, 0xDB, 0x34, 0x0B, 0x1A, 0x80, 0xB2, 0x9C, 0x68, 0xF5, + 0xA9, 0x32, 0x25, 0x12, 0xE0, 0x95, 0x29, 0x9F, 0x9D, 0x49, 0x82, 0x92, 0x77, 0x65, 0xAA, 0x41, + 0x4B, 0xC9, 0xD2, 0x18, 0x02, 0xFC, 0xB3, 0x12, 0xE4, 0xAF, 0xEE, 0x3B, 0x37, 0x05, 0xBC, 0x73, + 0xAF, 0xDD, 0x6A, 0x70, 0x17, 0xFB, 0x67, 0x9F, 0x0E, 0x24, 0x9E, 0x61, 0xA5, 0xF9, 0xC9, 0x99, + 0x54, 0x83, 0x65, 0x37, 0xA1, 0x53, 0x50, 0xE6, 0xCF, 0x57, 0x83, 0xCC, 0x2E, 0x35, 0xEF, 0x53, + 0x3C, 0x92, 0xAF, 0x57, 0x0D, 0x5B, 0xFF, 0x3E, 0x8C, 0xE8, 0x38, 0x45, 0x10, 0xF2, 0xBF, 0x2B, + 0xC1, 0x1E, 0xAA, 0x99, 0xEE, 0x00, 0x3A, 0xC9, 0x7D, 0x57, 0x09, 0xFE, 0xF4, 0x42, 0x12, 0x1E, + 0xA6, 0xC3, 0xAB, 0x04, 0xF5, 0x4E, 0x7A, 0x2A, 0x07, 0xE0, 0xE4, 0x25, 0x52, 0x0C, 0xCF, 0x9D, + 0x05, 0x7D, 0x76, 0xE3, 0xA3, 0x58, 0x0C, 0x49, 0xC2, 0x29, 0x67, 0x0C, 0x28, 0xCF, 0xDB, 0x91, + 0xDE, 0x82, 0xC7, 0x38, 0x83, 0x36, 0xBE, 0x60, 0xB6, 0xBE, 0x2D, 0x19, 0x53, 0x96, 0x97, 0x76, + 0x7D, 0x1B, 0x20, 0xED, 0xC0, 0x1E, 0xE0, 0x59, 0x9A, 0x6C, 0x4E, 0xD5, 0x51, 0xBF, 0x94, 0x90, + 0x66, 0x49, 0x8C, 0x73, 0xE8, 0x72, 0xC3, 0x6D, 0xD8, 0x39, 0x6F, 0xE3, 0x5B, 0x53, 0x96, 0xD5, + 0xED, 0xB5, 0xD9, 0x63, 0x59, 0x59, 0x7B, 0xCE, 0x4B, 0x99, 0x55, 0xEF, 0x5A, 0x0C, 0xC0, 0x64, + 0x40, 0x62, 0xA9, 0x22, 0xC9, 0x7D, 0x39, 0x8B, 0x1B, 0xDB, 0xA5, 0xC8, 0x65, 0x87, 0xA7, 0x5E, + 0x6B, 0xB1, 0xE9, 0x64, 0xDB, 0xCA, 0x9D, 0x4E, 0xB6, 0xAD, 0x0A, 0x64, 0x33, 0xA8, 0xF7, 0x4F, + 0x3F, 0xCE, 0x84, 0x39, 0xF1, 0x61, 0xF3, 0xB6, 0x97, 0x93, 0xB3, 0xB1, 0xAC, 0x77, 0x6B, 0xEA, + 0x73, 0x2F, 0x05, 0xDE, 0xB7, 0x41, 0x42, 0xC1, 0x07, 0x3F, 0x8C, 0x44, 0xEF, 0x6F, 0x64, 0x7A, + 0x7F, 0x23, 0xA7, 0xF7, 0xB3, 0xAD, 0xCF, 0x91, 0x40, 0x86, 0x1C, 0x5A, 0x30, 0x4E, 0x6E, 0x1B, + 0xFF, 0xE9, 0x14, 0xD9, 0xC7, 0x7A, 0x94, 0x0C, 0x2D, 0x63, 0x2F, 0x65, 0xB1, 0x3D, 0x6F, 0x4E, + 0x6A, 0xCD, 0xD2, 0xE9, 0xAC, 0x59, 0x8D, 0x5B, 0xC6, 0xDB, 0xF1, 0x29, 0xA4, 0x41, 0xBE, 0x34, + 0xB3, 0x05, 0x58, 0x9F, 0x19, 0xC1, 0xE8, 0x5B, 0x6F, 0xE8, 0x77, 0x06, 0xFE, 0x18, 0xFF, 0xC2, + 0xAF, 0x64, 0x8C, 0x8C, 0x61, 0x0A, 0x5D, 0x30, 0x2C, 0x2E, 0x78, 0xAC, 0x63, 0xDB, 0x1D, 0x61, + 0x5C, 0x62, 0x00, 0x3E, 0x51, 0x31, 0x6B, 0xF1, 0x79, 0x1D, 0xE1, 0xE7, 0x65, 0x18, 0x65, 0x7B, + 0x07, 0xB6, 0x52, 0x1C, 0xFB, 0x61, 0xA4, 0xA4, 0xC8, 0xBB, 0x17, 0x12, 0xB0, 0x59, 0xB4, 0x43, + 0x38, 0x3D, 0xFB, 0x9E, 0xDC, 0xD9, 0x60, 0x32, 0x40, 0x0E, 0x8E, 0x1B, 0xB2, 0xD0, 0xD0, 0xD3, + 0x8B, 0xF3, 0xA3, 0x33, 0xDC, 0xF6, 0x61, 0xD1, 0x91, 0x23, 0x9F, 0x73, 0x43, 0xE8, 0x77, 0xF0, + 0x28, 0x70, 0x23, 0x2D, 0x4E, 0x2D, 0xD7, 0x89, 0x29, 0x4A, 0xCB, 0x14, 0xF8, 0x8B, 0xEF, 0x03, + 0xE1, 0x4A, 0x93, 0xCB, 0xA8, 0x40, 0x32, 0x92, 0x00, 0x44, 0x2B, 0xAA, 0xC1, 0x0B, 0xC5, 0xE9, + 0x75, 0xAD, 0x6E, 0x45, 0x38, 0x45, 0x0B, 0x5A, 0x57, 0x23, 0x27, 0xB8, 0xEC, 0x4F, 0xEC, 0xE0, + 0xDB, 0xBB, 0xA9, 0xD7, 0x6D, 0xD5, 0xC6, 0x71, 0xF6, 0x6B, 0x3D, 0x7E, 0xE3, 0x0E, 0x8F, 0x68, + 0x18, 0xFD, 0x1F, 0xFC, 0x51, 0xBF, 0xC9, 0x88, 0x02, 0xC8, 0x02, 0x12, 0x0D, 0x6E, 0xA8, 0x8E, + 0xAC, 0x0B, 0x91, 0xD5, 0xF0, 0xFD, 0xFB, 0xBD, 0x9C, 0xA0, 0x13, 0x80, 0xD3, 0xB6, 0xFB, 0xD0, + 0xBF, 0x83, 0x05, 0x47, 0x92, 0xCA, 0x3D, 0xDD, 0xE8, 0x5C, 0x5D, 0x1D, 0xB3, 0x45, 0x1F, 0xD6, + 0x70, 0x9D, 0x90, 0x84, 0x91, 0x1D, 0x30, 0x1D, 0x60, 0x4A, 0xA5, 0x5D, 0xC7, 0x7C, 0xF1, 0x83, + 0xD2, 0x08, 0xE2, 0xD2, 0x2E, 0x65, 0xA5, 0x78, 0xE3, 0x71, 0x81, 0xE7, 0x68, 0x71, 0x9D, 0x7F, + 0xDB, 0xD5, 0xB8, 0xFF, 0x2A, 0x2F, 0x7A, 0x4D, 0xBB, 0x59, 0x12, 0x89, 0xBC, 0x2D, 0x2C, 0x73, + 0x54, 0xBA, 0x04, 0xC8, 0x77, 0x1A, 0x77, 0xB2, 0xB1, 0x97, 0xFA, 0xDA, 0xD3, 0x1C, 0x53, 0x2C, + 0x27, 0xDC, 0xAA, 0xDE, 0x31, 0x2C, 0x82, 0x7E, 0xBE, 0xD2, 0x62, 0x28, 0x9F, 0x95, 0xC4, 0xD8, + 0x1A, 0xB1, 0x48, 0x6A, 0x26, 0x9D, 0xC7, 0xC5, 0xA5, 0x41, 0xEB, 0xEB, 0x65, 0xAE, 0x97, 0xD8, + 0xAF, 0x2C, 0x4D, 0xFD, 0xDA, 0x67, 0xA9, 0x28, 0xC7, 0x8D, 0xE4, 0x38, 0xAE, 0x25, 0x44, 0xB6, + 0xD4, 0x2F, 0x53, 0xBC, 0x19, 0x5B, 0x9B, 0xDE, 0x00, 0xF9, 0x1F, 0xD5, 0xE4, 0x6A, 0xE3, 0xE5, + 0xA9, 0x5A, 0x5C, 0x77, 0xAC, 0xA8, 0x4F, 0x6C, 0xF1, 0x3C, 0xB9, 0xF1, 0xDD, 0xD7, 0xF2, 0x11, + 0x53, 0xF0, 0x40, 0xD7, 0x0C, 0x92, 0xCD, 0x5C, 0x59, 0xFE, 0x51, 0xD2, 0x55, 0x7C, 0x5C, 0x09, + 0x16, 0xD7, 0x31, 0xE0, 0x6E, 0xE2, 0x63, 0x1E, 0xE6, 0x65, 0x4C, 0x97, 0x6F, 0x4C, 0x61, 0x79, + 0xE1, 0xFE, 0xD8, 0x5C, 0x15, 0x52, 0xBF, 0xB8, 0xFD, 0x4F, 0x29, 0xB5, 0x78, 0x47, 0x2F, 0x47, + 0xA9, 0x59, 0x3E, 0x66, 0x69, 0x59, 0x1A, 0xAF, 0xA8, 0x0C, 0x01, 0x53, 0x15, 0x17, 0x54, 0x62, + 0x81, 0xE3, 0x5F, 0x85, 0x28, 0x5C, 0x96, 0x70, 0x9C, 0x0E, 0x7C, 0xCF, 0x41, 0x97, 0x7D, 0xD3, + 0x62, 0xCD, 0x31, 0x34, 0x66, 0xD3, 0x12, 0xAF, 0xBD, 0xC8, 0x0D, 0x79, 0x6B, 0xCC, 0xC9, 0x5F, + 0x4C, 0xEC, 0xCC, 0x0F, 0x5D, 0xFC, 0xFF, 0xDE, 0x60, 0x30, 0x85, 0x65, 0xCC, 0x3D, 0x5F, 0xE8, + 0x6C, 0xA0, 0x20, 0x33, 0x44, 0xBB, 0x1D, 0x46, 0x75, 0xA3, 0x53, 0x40, 0x35, 0x25, 0xAB, 0xF8, + 0xA4, 0x2C, 0xDA, 0xEA, 0x90, 0xA5, 0x07, 0x6B, 0x93, 0x95, 0x6E, 0x6F, 0xCB, 0xEA, 0x59, 0x9B, + 0x9D, 0x8D, 0xCD, 0x2D, 0x99, 0x51, 0x33, 0xC4, 0x67, 0x84, 0x58, 0x7F, 0xD9, 0xDD, 0xDC, 0xB2, + 0xD6, 0x3B, 0xEB, 0xD6, 0x5A, 0x39, 0xC4, 0xEF, 0x00, 0xB1, 0x6E, 0x6D, 0x6D, 0x6E, 0x6E, 0x6E, + 0x74, 0xD6, 0xB7, 0xD6, 0x8B, 0x01, 0x8E, 0xED, 0x88, 0x25, 0x2A, 0x47, 0x90, 0x8E, 0xB5, 0x6D, + 0xF5, 0xB6, 0xD7, 0x5F, 0x6E, 0x97, 0x80, 0xF8, 0xDE, 0x50, 0xC0, 0xAC, 0x74, 0x2D, 0x90, 0xD5, + 0xD6, 0x86, 0xB5, 0xF1, 0x72, 0xB3, 0x5B, 0x0C, 0xB5, 0x37, 0x8A, 0xDC, 0x68, 0xEA, 0xB0, 0x2D, + 0x92, 0x8D, 0x4D, 0xA0, 0xB5, 0xB5, 0xAD, 0x2C, 0xBF, 0xB4, 0x03, 0x1B, 0x15, 0x43, 0x8E, 0x7A, + 0xE4, 0x52, 0x2C, 0xEE, 0x61, 0xE8, 0x41, 0xB9, 0xAB, 0x62, 0x25, 0x2E, 0x0E, 0xB3, 0x2B, 0xD0, + 0xE7, 0x86, 0xA2, 0x6D, 0x2E, 0xDE, 0x5A, 0x22, 0x2E, 0xB1, 0x20, 0x9A, 0x6E, 0xBE, 0xB4, 0xD8, + 0xBF, 0x36, 0x49, 0x7E, 0x49, 0xC6, 0x41, 0x5C, 0x86, 0x83, 0x40, 0xFC, 0x5A, 0x3E, 0xFC, 0xCA, + 0x88, 0x7E, 0xFE, 0x11, 0x44, 0x7F, 0x7F, 0x0C, 0xA2, 0x0F, 0x45, 0xB1, 0xCA, 0xF5, 0xCD, 0x41, + 0x33, 0x93, 0x50, 0xCB, 0x2C, 0x64, 0xE5, 0x95, 0x06, 0x2D, 0x81, 0xB1, 0xFF, 0x85, 0x06, 0x98, + 0x0E, 0x1F, 0xBE, 0xAD, 0xB2, 0xFB, 0x42, 0x69, 0x46, 0x88, 0x4A, 0x82, 0x96, 0xB4, 0x71, 0xA5, + 0xDB, 0xB5, 0xD6, 0xD6, 0xDB, 0x64, 0x6B, 0x4B, 0xD9, 0x1A, 0xE5, 0x9F, 0x51, 0xC8, 0x58, 0x50, + 0xC1, 0xA8, 0xE6, 0x90, 0xD3, 0xEF, 0x15, 0x20, 0x41, 0x7C, 0x0A, 0x61, 0x43, 0xA1, 0xB5, 0xC1, + 0x1E, 0x17, 0xD8, 0x68, 0xAC, 0x3D, 0xE6, 0xE8, 0x43, 0xA0, 0xD5, 0xE3, 0x33, 0x6E, 0x4F, 0x9B, + 0x78, 0xF9, 0x77, 0xFE, 0x02, 0x82, 0xD5, 0xA9, 0xAC, 0x40, 0x0F, 0xB9, 0x7B, 0x95, 0x49, 0x50, + 0x6D, 0x93, 0xBD, 0x4A, 0x0E, 0x9C, 0xEE, 0x21, 0x5D, 0x5A, 0x95, 0xF7, 0xAA, 0x65, 0x78, 0xC6, + 0xB4, 0x55, 0x65, 0xB7, 0x52, 0x26, 0x88, 0x9B, 0x4E, 0x31, 0xC1, 0xE2, 0xFD, 0xCA, 0xEA, 0xB4, + 0x72, 0x5B, 0x87, 0xDB, 0x3D, 0x8C, 0x98, 0xA5, 0xB5, 0xCE, 0x9A, 0xB1, 0x75, 0x85, 0x14, 0xCF, + 0x7E, 0x7D, 0x2A, 0x9A, 0xE9, 0x5E, 0xDA, 0xA3, 0xF4, 0x61, 0x21, 0xC5, 0xA7, 0x6B, 0xA5, 0xA4, + 0xA9, 0xDD, 0xE6, 0x14, 0xBB, 0x8D, 0x34, 0x55, 0x10, 0xD4, 0x35, 0xD5, 0x2A, 0xD6, 0xD4, 0x6E, + 0x33, 0x4D, 0x7D, 0x8C, 0xD6, 0x95, 0x69, 0xEA, 0x13, 0xD1, 0x94, 0x34, 0xF5, 0xC9, 0x29, 0x3E, + 0x5D, 0x2B, 0x25, 0x4D, 0xED, 0x35, 0xA7, 0xD8, 0x6B, 0xA4, 0xA9, 0xBD, 0x46, 0x9A, 0xDA, 0x6B, + 0xA6, 0xA9, 0x8F, 0xD1, 0xBA, 0x32, 0x4D, 0x7D, 0x22, 0x9A, 0x92, 0xA6, 0x3E, 0x39, 0xC5, 0xA7, + 0x6B, 0xA5, 0xA4, 0xA9, 0x6B, 0xCD, 0x29, 0xAE, 0x35, 0xD2, 0xD4, 0xB5, 0x46, 0x9A, 0xBA, 0xD6, + 0x4C, 0x53, 0x1F, 0xA3, 0x75, 0x65, 0x9A, 0xFA, 0x44, 0x34, 0x25, 0x4D, 0x7D, 0x72, 0x8A, 0x73, + 0x6A, 0xE5, 0x73, 0x3F, 0x6E, 0x35, 0xBA, 0xCA, 0xB5, 0x0E, 0x5C, 0x8D, 0xBE, 0x6F, 0xA5, 0x23, + 0x57, 0xA3, 0x23, 0x5B, 0xF7, 0xF0, 0x33, 0xC7, 0x37, 0x6D, 0x55, 0x85, 0xD4, 0x3C, 0x4C, 0x7E, + 0xE6, 0xEB, 0xDC, 0x79, 0xD1, 0x9D, 0xD7, 0xAB, 0x8F, 0x23, 0xA6, 0xFE, 0xEB, 0xF9, 0xC6, 0xDD, + 0xB9, 0xBF, 0xFE, 0xA1, 0x1E, 0xFF, 0x89, 0x07, 0xD8, 0x6A, 0x20, 0x76, 0xE6, 0x01, 0xD4, 0x97, + 0x79, 0x03, 0x72, 0x92, 0x63, 0xD5, 0x44, 0xCC, 0x0D, 0xE1, 0xEA, 0x52, 0xD4, 0x5C, 0x95, 0x26, + 0x22, 0xED, 0x35, 0x13, 0x69, 0xAF, 0xB1, 0x48, 0x7B, 0x0D, 0x45, 0xDA, 0x6B, 0x2C, 0xD2, 0x5E, + 0x43, 0x91, 0xAE, 0x35, 0x14, 0xE9, 0x5A, 0x33, 0x91, 0xAE, 0x35, 0x16, 0xE9, 0x5A, 0x43, 0x91, + 0xAE, 0x35, 0x16, 0xA9, 0x0E, 0x99, 0x1C, 0x28, 0xC8, 0x37, 0x6A, 0x4D, 0x07, 0x0B, 0x65, 0xF7, + 0x6E, 0x0B, 0xB6, 0x42, 0xE2, 0x0C, 0x00, 0xEC, 0x82, 0xBD, 0x84, 0xE0, 0x80, 0xBD, 0x6E, 0x24, + 0x02, 0xEF, 0x2E, 0xFC, 0x6F, 0xD4, 0x8B, 0x13, 0x51, 0xEC, 0xBC, 0xD0, 0xF2, 0x9F, 0x4C, 0x69, + 0x92, 0x4E, 0x5D, 0x7F, 0x61, 0xC2, 0x18, 0x08, 0x58, 0x4C, 0xA5, 0x4D, 0xD6, 0x36, 0xF9, 0x7F, + 0xC9, 0xD4, 0xB9, 0xB6, 0x99, 0x17, 0x17, 0x78, 0x66, 0x0A, 0x51, 0x2A, 0xDC, 0x23, 0x2F, 0xA5, + 0xDE, 0x6A, 0xE9, 0xF7, 0x69, 0xA7, 0x91, 0xFF, 0x17, 0x7A, 0x7F, 0x4E, 0x3D, 0x7A, 0x67, 0x8F, + 0x72, 0x62, 0x5E, 0xA4, 0xAE, 0x0A, 0x0A, 0xBA, 0x48, 0xBF, 0xC4, 0x5C, 0xEF, 0xF8, 0x87, 0xCA, + 0xD0, 0x78, 0xE5, 0xE7, 0x2D, 0x3F, 0x73, 0xE1, 0xD8, 0xD8, 0x26, 0xC7, 0xA6, 0x95, 0xD9, 0xA6, + 0xED, 0xF2, 0x43, 0xA0, 0x36, 0x7E, 0xD5, 0xB6, 0x68, 0xCF, 0xCC, 0xCF, 0x21, 0x97, 0x91, 0x3E, + 0x66, 0xBD, 0x3D, 0x27, 0x82, 0x89, 0xE4, 0x30, 0x68, 0xB8, 0x2C, 0x88, 0x14, 0x43, 0x89, 0x4F, + 0xA1, 0xD1, 0x7E, 0xF0, 0xED, 0xD2, 0xEA, 0xF7, 0x8F, 0x0E, 0x2A, 0x3B, 0x5A, 0x86, 0xD0, 0x64, + 0x43, 0x28, 0xA5, 0x91, 0xCE, 0x99, 0x1D, 0x86, 0xF0, 0x9B, 0xF3, 0x04, 0xB4, 0xBA, 0x4F, 0xD4, + 0xA6, 0xEE, 0x13, 0xB6, 0xA9, 0xF7, 0x44, 0x6D, 0xEA, 0x3D, 0x61, 0x9B, 0xD6, 0x9E, 0xA8, 0x4D, + 0x6B, 0x73, 0x6A, 0x93, 0x18, 0x62, 0x17, 0xFB, 0x67, 0xAB, 0x9F, 0x0E, 0xCE, 0xF2, 0xED, 0xD3, + 0xC5, 0xA0, 0x76, 0xAC, 0xAF, 0x30, 0x10, 0xC9, 0x75, 0xF1, 0x34, 0xE6, 0x76, 0x73, 0x63, 0x63, + 0x2D, 0x13, 0xE5, 0xCB, 0x3E, 0xCA, 0x8C, 0x2A, 0x31, 0xFF, 0x25, 0xEB, 0xAD, 0x84, 0x88, 0x14, + 0x47, 0x5C, 0x3D, 0x8A, 0xDC, 0x44, 0xE9, 0xC1, 0x2C, 0x84, 0xBA, 0x87, 0x08, 0xA9, 0x10, 0x38, + 0xE4, 0x3C, 0x84, 0x60, 0x62, 0xED, 0x93, 0xD3, 0x94, 0xB5, 0xA9, 0x33, 0x77, 0xD6, 0x56, 0x57, + 0x3F, 0x7A, 0x24, 0xBE, 0xB2, 0xD0, 0x26, 0x50, 0x91, 0xF0, 0xDE, 0x61, 0x11, 0x14, 0x9C, 0x1A, + 0x7B, 0x40, 0x1B, 0x97, 0x9D, 0x80, 0x9F, 0x37, 0xC1, 0xC1, 0x37, 0xBA, 0x71, 0xFD, 0x19, 0x62, + 0x24, 0x47, 0x04, 0xB3, 0x58, 0x1C, 0x35, 0x31, 0x05, 0x24, 0xBE, 0x47, 0x50, 0x73, 0xDB, 0x58, + 0xE3, 0x5E, 0xBC, 0xBE, 0xDD, 0xE9, 0xC4, 0x2B, 0x53, 0x1E, 0x6C, 0x2F, 0xB2, 0x80, 0x9D, 0x4C, + 0x23, 0xFA, 0x3D, 0xAB, 0xB8, 0x78, 0x69, 0x42, 0xEB, 0x46, 0xF8, 0xD4, 0x98, 0xB9, 0x22, 0x51, + 0xC4, 0x37, 0xD6, 0xD9, 0x2D, 0xF6, 0xDC, 0x31, 0x25, 0x92, 0x79, 0xD4, 0xEB, 0xAE, 0x11, 0x00, + 0x25, 0x07, 0xEC, 0xE0, 0xC5, 0xBD, 0x0B, 0xE8, 0x5F, 0xA7, 0xD4, 0x63, 0x07, 0xF3, 0xDB, 0xD6, + 0x1A, 0xFC, 0xE8, 0xBD, 0x94, 0xBA, 0x0E, 0x3E, 0xB1, 0x2D, 0xA2, 0xDE, 0x4B, 0x99, 0x5F, 0xF9, + 0x4A, 0x4C, 0xF1, 0xF4, 0x8E, 0xE4, 0x40, 0x26, 0xAE, 0x3D, 0x62, 0xF1, 0x3B, 0x36, 0xF3, 0x1C, + 0xC5, 0xA5, 0xE2, 0x4B, 0x1C, 0x44, 0xDD, 0x4C, 0x90, 0x49, 0xD7, 0x14, 0x5C, 0x62, 0xA0, 0x98, + 0x86, 0x7A, 0x49, 0x69, 0x46, 0x8B, 0xEF, 0x6C, 0x64, 0xEE, 0x57, 0x87, 0xC7, 0xEE, 0x35, 0x15, + 0xBD, 0x81, 0x47, 0x96, 0x3D, 0x99, 0x11, 0x7E, 0x62, 0xD9, 0x53, 0xF8, 0xC8, 0xBF, 0xD2, 0xB3, + 0x24, 0xE5, 0x5C, 0x08, 0xA1, 0x23, 0x58, 0xCA, 0xA5, 0x62, 0x76, 0xE6, 0x78, 0x70, 0xFA, 0x94, + 0x07, 0xA6, 0xA2, 0x99, 0xFC, 0x3E, 0x52, 0x91, 0x7A, 0xC6, 0x69, 0x54, 0xEA, 0x69, 0xE8, 0xD8, + 0xFE, 0x0E, 0xA0, 0x17, 0x6E, 0x7C, 0x9D, 0xA7, 0x6B, 0x6D, 0x40, 0x27, 0x64, 0xFC, 0xC0, 0x6E, + 0x1B, 0xBE, 0xB7, 0x7B, 0xAA, 0x9A, 0x28, 0x77, 0xA4, 0x8A, 0x35, 0x93, 0x93, 0x91, 0x3D, 0xCE, + 0x59, 0x09, 0x55, 0x58, 0x24, 0x28, 0x6D, 0xDB, 0xB4, 0xC8, 0x9F, 0x49, 0x2F, 0x3F, 0x40, 0x48, + 0xE3, 0x50, 0xAD, 0x6E, 0x3C, 0xA7, 0x56, 0x92, 0xD7, 0xD4, 0x93, 0x7A, 0x0A, 0x1A, 0x07, 0xDA, + 0x25, 0x6E, 0x78, 0xD6, 0x03, 0x9F, 0x87, 0x28, 0xCC, 0x04, 0xAD, 0xC2, 0xE6, 0x99, 0x52, 0xEA, + 0xD4, 0x6B, 0xA6, 0x2D, 0xA1, 0x60, 0xF6, 0x3E, 0xCE, 0x20, 0x99, 0x1E, 0x8E, 0x9B, 0x4F, 0xC7, + 0xB7, 0xE7, 0xD0, 0xE4, 0x02, 0xE2, 0xA5, 0xED, 0xCE, 0xA4, 0x31, 0xAD, 0xD4, 0x5C, 0x35, 0x6B, + 0x2A, 0x77, 0xF5, 0x7A, 0xDB, 0xEB, 0xDB, 0x9B, 0x2F, 0x33, 0xFE, 0x5E, 0x1B, 0xBE, 0xB7, 0xA1, + 0x60, 0x0E, 0xED, 0xCC, 0x50, 0x65, 0xF1, 0x2C, 0xF8, 0xD2, 0x95, 0xD8, 0x39, 0x36, 0x35, 0xB5, + 0x7E, 0x86, 0xCE, 0x4A, 0x12, 0x28, 0x49, 0x1C, 0xCA, 0x6F, 0x5F, 0x5B, 0xEB, 0x5B, 0x8A, 0x9A, + 0x8B, 0x19, 0x68, 0xBD, 0xBD, 0x35, 0x17, 0x55, 0x2F, 0xE7, 0xA1, 0x48, 0x40, 0xAB, 0xAB, 0xB1, + 0x2B, 0x94, 0xC8, 0x2B, 0xF7, 0x96, 0x8A, 0x59, 0x14, 0x47, 0x67, 0x7B, 0xFC, 0x1E, 0xD6, 0x62, + 0x72, 0xED, 0xF3, 0xE8, 0xAC, 0x25, 0xB5, 0xD7, 0xF3, 0xBC, 0x8E, 0xF4, 0x9F, 0xDC, 0x64, 0xED, + 0xE6, 0x68, 0x8E, 0x4D, 0x35, 0x50, 0x38, 0x38, 0xED, 0x3F, 0x36, 0x89, 0xF7, 0x60, 0x01, 0xEE, + 0xEC, 0xFB, 0xC7, 0x26, 0xD3, 0x9F, 0x5E, 0xC1, 0xCF, 0xB9, 0x52, 0x89, 0x37, 0x3F, 0x44, 0xE5, + 0xD3, 0x68, 0x22, 0xBC, 0x67, 0x2B, 0xEB, 0x3D, 0x5B, 0x46, 0xEF, 0xD9, 0x4C, 0x27, 0x51, 0x99, + 0xD3, 0x8B, 0xB3, 0xA6, 0xDA, 0x92, 0x9C, 0x23, 0x02, 0x4F, 0xA3, 0xD1, 0xE1, 0xF7, 0x89, 0xEF, + 0x71, 0xF7, 0x17, 0x9C, 0xC3, 0xAE, 0x6C, 0x37, 0x98, 0x67, 0xD8, 0x55, 0x0C, 0x46, 0x7A, 0x4F, + 0xB8, 0xEC, 0x90, 0x72, 0x02, 0xDC, 0x0C, 0x5C, 0x96, 0x70, 0x1D, 0x5C, 0x12, 0xBC, 0xDA, 0xA8, + 0xF8, 0x22, 0x6B, 0xAC, 0xD5, 0x56, 0x43, 0xDC, 0xE7, 0x60, 0x7E, 0x0E, 0xE8, 0x88, 0xA9, 0x86, + 0xD5, 0x66, 0x89, 0x6D, 0xB5, 0xAD, 0x24, 0x86, 0xBE, 0x6B, 0xDC, 0x4A, 0xAA, 0x4B, 0xC7, 0x0D, + 0x27, 0x22, 0x73, 0xFC, 0x63, 0x10, 0x4B, 0x4F, 0x04, 0x27, 0xE7, 0xF4, 0x9A, 0x06, 0xE0, 0xAA, + 0xD3, 0x23, 0x47, 0x2C, 0x51, 0x33, 0x2B, 0x54, 0xB6, 0x40, 0x0D, 0x0B, 0x09, 0x3C, 0xC4, 0x39, + 0x45, 0x72, 0x9E, 0x07, 0xD7, 0xB2, 0x8B, 0x60, 0xDE, 0x37, 0x51, 0x45, 0x4A, 0x38, 0xA6, 0xE6, + 0x5D, 0x90, 0xEE, 0xF7, 0xCA, 0x57, 0xB9, 0x77, 0x49, 0x57, 0xC9, 0x92, 0x94, 0x64, 0x09, 0x5A, + 0xC0, 0xD7, 0x25, 0xDE, 0x46, 0xDE, 0x02, 0xF0, 0x79, 0x06, 0x96, 0x12, 0x4C, 0x27, 0x33, 0x98, + 0x2C, 0x6F, 0x8A, 0x84, 0x61, 0x19, 0x3E, 0xB0, 0x3F, 0x5B, 0xBA, 0x8F, 0x14, 0x67, 0xDD, 0x49, + 0x30, 0x49, 0x15, 0x1E, 0xF5, 0x39, 0xF3, 0x07, 0xF5, 0xD2, 0x88, 0xC4, 0xEC, 0x9B, 0xB9, 0xB5, + 0x36, 0x7C, 0x96, 0xCD, 0xFD, 0xBB, 0xB2, 0x77, 0x5D, 0x25, 0x65, 0xEE, 0xB1, 0x6F, 0x63, 0x3E, + 0xAA, 0x0E, 0x11, 0xAD, 0xBE, 0xB3, 0xDD, 0x08, 0x96, 0xDC, 0x0B, 0x72, 0x98, 0xBE, 0x59, 0x07, + 0xCD, 0xF7, 0x42, 0xE2, 0x4B, 0x21, 0xD9, 0x86, 0xBE, 0x8A, 0x99, 0x4F, 0x4E, 0x12, 0x5E, 0xC8, + 0xCF, 0xD9, 0xF2, 0x6C, 0x79, 0xBA, 0x9B, 0xAD, 0x76, 0x8E, 0x54, 0x2C, 0xA7, 0x8A, 0x92, 0x3B, + 0xAF, 0x6F, 0xDF, 0x62, 0x73, 0x3A, 0x1D, 0x25, 0x28, 0x56, 0xCB, 0xAB, 0xD5, 0x4A, 0x73, 0x03, + 0xB7, 0x8B, 0x04, 0xDF, 0x56, 0x90, 0x0C, 0x69, 0x5E, 0x26, 0x92, 0x4C, 0x4E, 0x14, 0x39, 0x39, + 0xCB, 0x2C, 0x39, 0x49, 0x66, 0xCF, 0x4B, 0x32, 0x4B, 0x6E, 0x92, 0xF9, 0xE4, 0x27, 0x99, 0x3D, + 0x47, 0xC9, 0x6C, 0x79, 0x4A, 0x66, 0xC9, 0x55, 0x32, 0x6B, 0xBE, 0x92, 0xD9, 0x72, 0x96, 0xCC, + 0x3F, 0x6F, 0x49, 0x21, 0xC6, 0x74, 0x4B, 0x24, 0x45, 0xE4, 0xA6, 0xDF, 0x2A, 0xE3, 0x29, 0xC9, + 0x81, 0x52, 0x8E, 0xA0, 0x62, 0x22, 0x94, 0xE6, 0xC9, 0x50, 0x66, 0x4D, 0x88, 0x92, 0xCD, 0x42, + 0x8A, 0x16, 0x88, 0xD3, 0xFB, 0x07, 0x98, 0x80, 0x9F, 0xD7, 0xFC, 0x68, 0x9C, 0xBE, 0x1E, 0x6B, + 0x46, 0x10, 0xFE, 0x77, 0x26, 0x29, 0x98, 0x9E, 0xC3, 0x45, 0xCA, 0xE8, 0xB7, 0xC8, 0xED, 0xBE, + 0x54, 0x7E, 0xF9, 0xFE, 0xAC, 0xAF, 0xAE, 0x71, 0x79, 0x1A, 0xC0, 0x84, 0x95, 0x3F, 0xFD, 0x89, + 0x98, 0xA0, 0x40, 0x21, 0x46, 0x2C, 0x77, 0x78, 0x5D, 0xC8, 0xB7, 0xD4, 0x3D, 0xF0, 0xA7, 0x4D, + 0x48, 0x1E, 0x7F, 0x3C, 0xDD, 0xEB, 0x1B, 0x99, 0x5D, 0xD2, 0x9C, 0x05, 0x53, 0xEA, 0x8F, 0xB2, + 0x69, 0x4D, 0xD2, 0x0F, 0x36, 0x75, 0x29, 0x42, 0x94, 0x55, 0xE5, 0xC6, 0xC7, 0xB8, 0x33, 0x58, + 0xA3, 0x10, 0x85, 0x3F, 0x59, 0x47, 0x52, 0x25, 0x5A, 0x5E, 0xD6, 0x15, 0xC3, 0xA4, 0x02, 0xAD, + 0x2C, 0x45, 0x63, 0xBA, 0xB7, 0xB7, 0x6E, 0x74, 0x62, 0x4F, 0xD2, 0x44, 0x6E, 0x63, 0xD7, 0x83, + 0x1F, 0xF6, 0xF7, 0x36, 0xB9, 0x62, 0x25, 0x52, 0x2E, 0xCC, 0x76, 0x62, 0x14, 0x8E, 0x0E, 0xA4, + 0x51, 0x1C, 0x47, 0x48, 0x24, 0x4F, 0x26, 0x70, 0xF6, 0xC6, 0x76, 0xF8, 0x8D, 0x17, 0x70, 0x44, + 0x4A, 0x21, 0x53, 0x1C, 0x0E, 0xFB, 0x1A, 0x49, 0xF2, 0xCC, 0x13, 0xFC, 0xC3, 0x1B, 0x24, 0xCF, + 0x3F, 0x2C, 0x32, 0x24, 0xD0, 0x75, 0x5D, 0xF2, 0xFA, 0x35, 0xA7, 0x05, 0x1D, 0x03, 0x7D, 0x64, + 0xE9, 0xFD, 0x53, 0x90, 0x44, 0xD3, 0x9C, 0x98, 0x53, 0x82, 0x95, 0x5A, 0x55, 0xD6, 0xA3, 0x45, + 0xBD, 0x90, 0xD9, 0x3A, 0x89, 0x53, 0x7D, 0x4A, 0x06, 0x31, 0xBE, 0xD3, 0x0D, 0xED, 0x37, 0xDC, + 0x89, 0x0A, 0x09, 0x58, 0x50, 0xE2, 0xC0, 0x9A, 0x72, 0x02, 0xF6, 0x9C, 0xED, 0xA1, 0xA8, 0x9D, + 0x95, 0xDC, 0xAD, 0x92, 0xB2, 0x26, 0xBB, 0x18, 0x6B, 0xA1, 0xDE, 0x16, 0xDC, 0x49, 0xD3, 0x24, + 0x27, 0x4D, 0x23, 0xBB, 0xC6, 0xAD, 0xF0, 0xF4, 0x45, 0x08, 0x87, 0x46, 0x60, 0xEA, 0xA9, 0xF3, + 0x0E, 0x56, 0xD9, 0x02, 0x4F, 0xFA, 0x04, 0x46, 0x92, 0x8D, 0xF9, 0x36, 0x7E, 0x66, 0x03, 0xAF, + 0x35, 0xF2, 0x57, 0xA5, 0x5C, 0x07, 0xA6, 0x3F, 0xF7, 0xFA, 0x3E, 0x79, 0xBB, 0x6A, 0x51, 0x56, + 0x86, 0xA5, 0xA4, 0xBF, 0x55, 0xB0, 0x5D, 0xA2, 0x5E, 0x91, 0x0C, 0x3B, 0xFB, 0x1F, 0x3F, 0x9E, + 0x1F, 0x1C, 0x9D, 0xEE, 0x5D, 0x1C, 0x5E, 0x1E, 0x9D, 0x9E, 0x7D, 0xBA, 0xB8, 0xBC, 0xF8, 0x7C, + 0x86, 0xBF, 0xFE, 0xB2, 0x77, 0x7C, 0x74, 0x70, 0xF9, 0xE9, 0xF4, 0x2F, 0xA7, 0x1F, 0x7F, 0x3D, + 0xD5, 0xEF, 0xAF, 0x27, 0x3D, 0x8A, 0x4C, 0xA6, 0x18, 0xF1, 0x32, 0x35, 0xB4, 0x82, 0x4C, 0xBD, + 0x6F, 0x1E, 0xE6, 0x79, 0xDE, 0x79, 0x6E, 0xBA, 0xC2, 0x06, 0xC0, 0x80, 0x3F, 0x9A, 0x43, 0x1D, + 0x89, 0xF1, 0xD7, 0x64, 0xA5, 0xBB, 0x65, 0x71, 0xF5, 0x37, 0x95, 0xC3, 0x14, 0xB4, 0x65, 0x2D, + 0x15, 0x8A, 0x21, 0x3D, 0x76, 0xD9, 0xE2, 0xAB, 0xF6, 0x2D, 0xEB, 0xD9, 0x09, 0x20, 0x77, 0xA8, + 0x70, 0x75, 0x91, 0x74, 0x3A, 0xBE, 0xCA, 0xBA, 0x63, 0xD0, 0x3F, 0xFE, 0x04, 0x59, 0x7D, 0x05, + 0x64, 0x70, 0x3F, 0x35, 0xF0, 0xA7, 0x06, 0xE6, 0x6B, 0x60, 0x46, 0x5F, 0xFE, 0xB0, 0xAB, 0x18, + 0xBE, 0xC2, 0xF6, 0x73, 0x1B, 0x1A, 0xF2, 0x7C, 0x62, 0x2C, 0x55, 0xD0, 0x33, 0x69, 0x7E, 0xA1, + 0xB1, 0x97, 0xF9, 0x98, 0x04, 0xB0, 0xD8, 0xC4, 0x19, 0x28, 0x1D, 0x54, 0xCD, 0x46, 0x4B, 0xAE, + 0xD8, 0x9B, 0xB2, 0xA1, 0x74, 0x82, 0x78, 0x76, 0x00, 0x27, 0x34, 0x07, 0xC3, 0x23, 0x30, 0x3A, + 0xC1, 0xF0, 0x9A, 0x62, 0x3B, 0x1E, 0x8D, 0x58, 0x0E, 0xDE, 0xD0, 0xEA, 0x08, 0x7B, 0x34, 0xC2, + 0xDE, 0xE2, 0x79, 0x87, 0x92, 0x69, 0x56, 0x7B, 0x78, 0x21, 0x4D, 0x35, 0xAB, 0xCE, 0xB0, 0xE9, + 0xCC, 0x28, 0x46, 0x08, 0x23, 0xB5, 0x18, 0xD7, 0x69, 0x9B, 0x98, 0x48, 0x13, 0xC5, 0x6A, 0x96, + 0xAD, 0x10, 0x19, 0x54, 0x2A, 0xC2, 0x96, 0xBD, 0x72, 0xCD, 0x0F, 0x15, 0x43, 0x71, 0x09, 0x82, + 0xCB, 0x57, 0x34, 0x3F, 0xEB, 0xFD, 0x65, 0xF2, 0xF8, 0xA6, 0xEE, 0x5F, 0x43, 0xB7, 0xAF, 0xA2, + 0x67, 0x27, 0x10, 0xA0, 0x67, 0xF1, 0x83, 0x5C, 0x39, 0xFE, 0xC4, 0x6D, 0xEA, 0x1E, 0xED, 0xE6, + 0x26, 0x81, 0x31, 0x3C, 0x43, 0xD7, 0x64, 0x35, 0xF0, 0x50, 0x9B, 0x34, 0xCF, 0xA4, 0x52, 0x40, + 0x5E, 0x8E, 0x69, 0xA8, 0x4E, 0xBE, 0x91, 0x55, 0xCC, 0x53, 0x1D, 0xB1, 0xB7, 0x3F, 0x67, 0xDD, + 0x49, 0x5F, 0x19, 0x56, 0x55, 0x28, 0x8D, 0xA5, 0x46, 0x4D, 0x9A, 0x97, 0xE2, 0x18, 0xFA, 0xC3, + 0x74, 0xF1, 0x78, 0x4E, 0x1D, 0xA1, 0xA4, 0x0D, 0x94, 0x49, 0xCC, 0x00, 0x6A, 0xD5, 0xEA, 0xFF, + 0x78, 0xFA, 0x2F, 0x6B, 0x73, 0xF7, 0x59, 0xB7, 0xB9, 0xFB, 0x28, 0x6D, 0xEE, 0x3D, 0xEB, 0x36, + 0xF7, 0x1E, 0xA5, 0xCD, 0x6B, 0xCF, 0xBA, 0xCD, 0x6B, 0x75, 0xDB, 0xAC, 0xA3, 0x7C, 0x6C, 0x87, + 0x31, 0xCF, 0x34, 0xA6, 0xC7, 0xF0, 0xCA, 0x93, 0x22, 0xF5, 0x6C, 0x22, 0xFA, 0x96, 0x0E, 0x7F, + 0xF5, 0x9D, 0x5B, 0x40, 0xF1, 0xD8, 0x7B, 0x27, 0x66, 0x9B, 0x19, 0x4D, 0xAC, 0x11, 0xDB, 0x46, + 0x70, 0x54, 0xD7, 0xD3, 0x8D, 0x2F, 0xB6, 0x8D, 0x82, 0xC5, 0x5F, 0xAC, 0xAF, 0x62, 0xBE, 0x65, + 0xDF, 0xDC, 0xF0, 0xD4, 0x3E, 0x5D, 0xE4, 0x67, 0x39, 0x71, 0xF9, 0xD2, 0x12, 0x2F, 0x8B, 0xAB, + 0xBF, 0x26, 0x96, 0xFA, 0xE1, 0x0D, 0x3E, 0x69, 0xB0, 0x64, 0x42, 0xDE, 0x2D, 0x41, 0xDE, 0x55, + 0x91, 0x77, 0x75, 0xE4, 0xDD, 0x22, 0xE4, 0xBD, 0x12, 0xE4, 0x3D, 0x15, 0x79, 0x4F, 0x47, 0xDE, + 0x2B, 0x42, 0xBE, 0x56, 0x82, 0x7C, 0x4D, 0x45, 0xBE, 0xA6, 0x23, 0x5F, 0x4B, 0x90, 0x3F, 0xBF, + 0x2D, 0xA9, 0xDA, 0x2A, 0x2B, 0x65, 0x54, 0xBE, 0xF1, 0x43, 0x50, 0xD5, 0x29, 0xFC, 0x0A, 0x3F, + 0x83, 0x51, 0x89, 0x02, 0x8B, 0x08, 0x28, 0x04, 0x12, 0xEA, 0xDB, 0x89, 0xFC, 0x63, 0xFF, 0x8E, + 0x5D, 0x1B, 0xA3, 0x8B, 0x4B, 0xE9, 0x43, 0xBF, 0x80, 0x6B, 0x29, 0xE7, 0x8E, 0x15, 0x12, 0x33, + 0xDE, 0xA3, 0xD2, 0x9D, 0x82, 0xAE, 0xD1, 0x25, 0x58, 0xDF, 0x36, 0x3D, 0x19, 0x8C, 0x48, 0x1B, + 0x76, 0x44, 0xFD, 0xCE, 0xC8, 0x5F, 0x75, 0x15, 0x98, 0x28, 0xA9, 0x73, 0x98, 0x04, 0xAA, 0xF4, + 0xA2, 0xA8, 0x98, 0xDD, 0xA8, 0x57, 0xE2, 0xBF, 0x5D, 0xA7, 0xDB, 0x26, 0xAE, 0xD3, 0xAB, 0xD0, + 0x79, 0x7C, 0xCF, 0xA4, 0x6B, 0x08, 0x4D, 0x13, 0x5B, 0xE7, 0x80, 0x26, 0x5B, 0x98, 0x51, 0xF9, + 0x6E, 0x73, 0x9D, 0x07, 0x02, 0xCF, 0x76, 0x0F, 0xB7, 0x6B, 0x3E, 0x67, 0x41, 0x99, 0x98, 0x8E, + 0xBB, 0x94, 0xD0, 0x39, 0x34, 0xFE, 0x7C, 0x27, 0x4A, 0x7D, 0x26, 0x47, 0x7A, 0x5E, 0x38, 0xD6, + 0xF7, 0xA2, 0x61, 0xCA, 0x5E, 0xEC, 0xBD, 0xF0, 0xDF, 0xD9, 0x18, 0x46, 0x70, 0x7F, 0x20, 0xAE, + 0xB7, 0xAB, 0x4B, 0x54, 0xB5, 0x2C, 0xFB, 0xAE, 0x6F, 0x2B, 0x2E, 0x22, 0x7B, 0x13, 0x98, 0x46, + 0xA8, 0xA3, 0xC4, 0x35, 0xB0, 0x0C, 0x94, 0x0E, 0xBB, 0xF6, 0xC7, 0xA9, 0xE1, 0xA1, 0x90, 0xF1, + 0xE1, 0x2D, 0x8D, 0x12, 0x8B, 0xEB, 0x6C, 0x77, 0xDB, 0x2D, 0x33, 0xCB, 0x86, 0xA3, 0xD8, 0x0C, + 0xFB, 0x95, 0x1E, 0x30, 0x4B, 0x5F, 0x12, 0xCB, 0xCB, 0x87, 0x59, 0xF2, 0xF8, 0xD8, 0x2E, 0xF9, + 0xAE, 0xC4, 0x98, 0x95, 0xBC, 0xA6, 0x28, 0xB7, 0xE5, 0x6F, 0x34, 0xF0, 0xE3, 0xAC, 0xC8, 0xD2, + 0x2B, 0x2D, 0x52, 0x1E, 0x68, 0xB6, 0x8D, 0x5F, 0x9A, 0xA6, 0x9B, 0x2C, 0xE2, 0x9D, 0x0A, 0x43, + 0x3E, 0xE7, 0xA5, 0x17, 0x8F, 0x90, 0x4D, 0xBB, 0x61, 0x5E, 0xE8, 0x5A, 0x39, 0xA1, 0x87, 0x6A, + 0x36, 0x5B, 0xFD, 0x15, 0xFB, 0x07, 0x45, 0x52, 0x7A, 0xEA, 0xE5, 0x17, 0x73, 0xCF, 0xE1, 0xDC, + 0x24, 0x8D, 0x6A, 0xF5, 0x14, 0xAA, 0xB9, 0x8D, 0xED, 0x58, 0x65, 0xED, 0x4D, 0x93, 0x2F, 0xF3, + 0xF3, 0xB1, 0xB9, 0xA6, 0x71, 0x7E, 0x5E, 0xAD, 0xE6, 0x4F, 0x16, 0x61, 0x33, 0x0C, 0x03, 0x42, + 0x60, 0xEA, 0x47, 0x01, 0xB5, 0xC7, 0xA9, 0x12, 0x54, 0x93, 0x07, 0xC7, 0x2A, 0x0B, 0x44, 0xC2, + 0xF3, 0xA3, 0xA5, 0x51, 0xA0, 0x00, 0x99, 0x84, 0xC9, 0x33, 0x29, 0x41, 0x16, 0xDB, 0x0F, 0x6E, + 0x7A, 0xB7, 0x53, 0xD4, 0xF8, 0x43, 0x7E, 0x7D, 0x6C, 0x3E, 0x6D, 0xCF, 0x20, 0xFB, 0x41, 0x4D, + 0x4F, 0x2F, 0xBA, 0x8B, 0x37, 0xEB, 0xB3, 0x6E, 0x00, 0xCE, 0x19, 0x68, 0xDB, 0x8B, 0xE7, 0x8D, + 0x2A, 0xEF, 0x07, 0x98, 0x66, 0x8D, 0x79, 0xCE, 0x18, 0x6A, 0x86, 0xF4, 0xE7, 0x3C, 0x6B, 0x24, + 0xF9, 0xDC, 0xE7, 0x31, 0x73, 0x64, 0x93, 0xC3, 0x3F, 0xCB, 0xD9, 0x43, 0x4F, 0x1B, 0x3E, 0x37, + 0xDB, 0xF1, 0x1C, 0xDA, 0x5E, 0xD9, 0x74, 0xCC, 0xDC, 0x72, 0x1D, 0xD7, 0xF3, 0x35, 0x1C, 0xC2, + 0x71, 0xE6, 0xA9, 0xD0, 0xC1, 0x2E, 0x64, 0xDC, 0x65, 0xD5, 0x1B, 0xDD, 0xF9, 0x51, 0x6F, 0xBF, + 0xB0, 0x07, 0xD9, 0x55, 0xA3, 0xC4, 0x26, 0x62, 0xFE, 0xFC, 0x4D, 0xD2, 0xC3, 0x3B, 0xE5, 0x00, + 0xFD, 0xDA, 0x00, 0x17, 0x75, 0x01, 0x7E, 0x91, 0x00, 0xD6, 0xCB, 0x01, 0xCE, 0x4F, 0xF6, 0xB3, + 0x14, 0x1E, 0x1A, 0xBC, 0x50, 0x32, 0x64, 0x0F, 0xAD, 0xA9, 0xDE, 0xEA, 0xFB, 0x33, 0x55, 0x44, + 0x56, 0x67, 0x63, 0xA7, 0x0C, 0xA0, 0x5F, 0x1B, 0xE0, 0xA2, 0x2E, 0x80, 0x2C, 0xA2, 0x64, 0x5C, + 0xE6, 0x03, 0xA8, 0x22, 0x4A, 0x28, 0x3C, 0xCC, 0xF2, 0x28, 0x05, 0xBB, 0x46, 0xC7, 0x5C, 0xBA, + 0xD8, 0x50, 0x31, 0x62, 0x96, 0x44, 0x68, 0x13, 0x8F, 0x39, 0xC7, 0x21, 0x1D, 0x6C, 0x58, 0x56, + 0x19, 0x5C, 0x57, 0x82, 0x7B, 0x89, 0x70, 0x00, 0xD6, 0x35, 0x35, 0x4B, 0x72, 0x23, 0x0B, 0xB5, + 0xD7, 0x50, 0xBD, 0x5F, 0xB3, 0xFA, 0x45, 0xBD, 0xEA, 0x72, 0xA7, 0xF4, 0xCA, 0xAA, 0x67, 0xB4, + 0xD6, 0x54, 0x3F, 0xEB, 0x3E, 0xE2, 0x6F, 0x5D, 0x6B, 0x6D, 0x4D, 0x86, 0xB5, 0x52, 0xC3, 0xFC, + 0x90, 0x31, 0x4D, 0xE2, 0xDA, 0xEB, 0x4F, 0xC3, 0xF4, 0x0C, 0x0C, 0x53, 0x11, 0xC4, 0xF9, 0x6F, + 0x27, 0x97, 0xE7, 0x7B, 0xBF, 0xFE, 0x56, 0x99, 0x27, 0x04, 0xE8, 0xBF, 0x3B, 0x7F, 0xFB, 0xDB, + 0x4F, 0xE3, 0x57, 0xDB, 0xF8, 0xE5, 0x41, 0xE8, 0xE3, 0xAC, 0xBB, 0x5D, 0x91, 0x94, 0x0E, 0xD8, + 0xB3, 0x1A, 0x02, 0xAE, 0xF7, 0x9A, 0x02, 0x6E, 0xB6, 0x72, 0x5D, 0xB5, 0x9F, 0x16, 0xFE, 0x9F, + 0xC1, 0xC2, 0x9B, 0xC0, 0x33, 0x6B, 0x6C, 0x49, 0x6F, 0x4D, 0x09, 0xDE, 0xAA, 0x81, 0x33, 0xED, + 0x6D, 0x0E, 0xCE, 0x74, 0x78, 0x06, 0xF0, 0xCD, 0xDC, 0xEC, 0x74, 0x06, 0xD7, 0x1B, 0x61, 0x8C, + 0x93, 0x9B, 0xBA, 0x9E, 0x7F, 0x46, 0x13, 0x1C, 0x5B, 0xD2, 0x20, 0xDB, 0x97, 0x5D, 0xCB, 0xDA, + 0xA8, 0x6A, 0xEF, 0x65, 0xA8, 0x97, 0xEB, 0x8D, 0xA0, 0x5E, 0xB6, 0x32, 0xAB, 0xF7, 0x72, 0xA8, + 0xAD, 0x46, 0xB4, 0xB6, 0x34, 0x5A, 0x15, 0xC1, 0xB6, 0x1B, 0x11, 0xDB, 0x6E, 0xD2, 0xB0, 0x6E, + 0xAF, 0x09, 0xAD, 0x6E, 0xAF, 0x09, 0xAD, 0xDE, 0x9A, 0x32, 0x1D, 0x54, 0x95, 0xC7, 0xBA, 0xF5, + 0xB2, 0xA7, 0x58, 0xDB, 0x8A, 0xF4, 0x18, 0x5C, 0xB7, 0x95, 0xB3, 0x55, 0x33, 0x93, 0x5B, 0x90, + 0x2C, 0xC9, 0xF9, 0x50, 0x55, 0xD5, 0xB7, 0x64, 0xB6, 0x92, 0xE0, 0x72, 0xFC, 0xD7, 0x72, 0x40, + 0x55, 0xF3, 0xAB, 0xC3, 0x6D, 0x35, 0x84, 0xDB, 0x6E, 0x06, 0xA7, 0x29, 0xD7, 0xDC, 0x66, 0xE3, + 0xBC, 0x9D, 0xA1, 0xA6, 0x73, 0x86, 0xDE, 0x95, 0xF5, 0x8C, 0xB6, 0x4E, 0xBA, 0x01, 0xF4, 0x49, + 0xFF, 0x64, 0xBD, 0xAE, 0xB5, 0x3F, 0xF6, 0xEF, 0xD0, 0xCC, 0xDE, 0xB9, 0x4E, 0x74, 0xF3, 0x8F, + 0x6E, 0xF1, 0xAD, 0x46, 0x26, 0xBF, 0xF7, 0x84, 0x26, 0xBF, 0xF7, 0x94, 0x26, 0xBF, 0xF7, 0x84, + 0x26, 0xBF, 0xF7, 0xD3, 0xE4, 0xCF, 0x6C, 0xF2, 0x7B, 0x4F, 0x6D, 0xF2, 0x7B, 0x0D, 0x4D, 0x7E, + 0xAF, 0xA1, 0xC9, 0xEF, 0x35, 0x34, 0xF9, 0xBD, 0x27, 0x32, 0xF9, 0xD6, 0xC6, 0x7F, 0x6E, 0x56, + 0x91, 0x6B, 0xF5, 0x19, 0xA3, 0x0A, 0xB0, 0xB0, 0xDA, 0x4A, 0x63, 0xFF, 0x69, 0x66, 0x9A, 0x69, + 0xC8, 0x5E, 0x81, 0x4C, 0x2F, 0xD1, 0x84, 0xD9, 0xDB, 0x25, 0xFC, 0x39, 0xBF, 0x54, 0x02, 0x14, + 0xFF, 0xDE, 0xC9, 0xD6, 0xF9, 0xAC, 0xD5, 0xF9, 0x6C, 0xA8, 0xF3, 0xBB, 0x56, 0xE7, 0xF7, 0x1D, + 0x79, 0x17, 0x0F, 0xB8, 0x79, 0x4F, 0x7D, 0x87, 0x46, 0xEE, 0xA0, 0x90, 0xA3, 0xEC, 0x7D, 0x97, + 0xA1, 0x00, 0x83, 0x92, 0xF2, 0xFB, 0x2C, 0x49, 0x65, 0xDF, 0xD3, 0x2A, 0x7F, 0xD8, 0x3B, 0xDC, + 0x3B, 0xDB, 0x37, 0x54, 0xDD, 0x1B, 0x45, 0xA2, 0xD7, 0xD5, 0xA4, 0x30, 0x63, 0x3B, 0xF8, 0xA6, + 0x64, 0x84, 0xE9, 0x96, 0xA4, 0x7D, 0x29, 0x01, 0xEF, 0x99, 0xC0, 0xF9, 0xD5, 0x6F, 0x41, 0xDF, + 0x76, 0xFE, 0x63, 0x1A, 0x46, 0xC0, 0xA8, 0x1E, 0x0A, 0xC4, 0x4E, 0x6B, 0x4F, 0xE9, 0xDD, 0xB1, + 0x9F, 0xDE, 0x10, 0xCA, 0x64, 0x50, 0x49, 0xEB, 0x18, 0x02, 0xA3, 0xE8, 0x77, 0x37, 0xD2, 0xD2, + 0x21, 0xDC, 0xB8, 0x0E, 0x4B, 0xE8, 0xE8, 0x7A, 0x67, 0x2C, 0x0D, 0x0D, 0x6F, 0x04, 0xC6, 0xAE, + 0x61, 0x2E, 0x3A, 0xF0, 0x52, 0x8E, 0xBC, 0xB3, 0xC0, 0xC7, 0xDB, 0xFB, 0x49, 0x92, 0x08, 0x9D, + 0x26, 0x62, 0xDD, 0xF3, 0x1C, 0x39, 0x1A, 0x0B, 0xAB, 0x71, 0x1F, 0x87, 0xA7, 0x6B, 0x03, 0x41, + 0xA7, 0x7F, 0x2C, 0xA6, 0x6C, 0xB0, 0x4C, 0x9A, 0x96, 0x29, 0x7C, 0x6B, 0xDF, 0x1F, 0x4F, 0x46, + 0x34, 0x4A, 0x13, 0x27, 0xB1, 0x18, 0xB5, 0x18, 0x83, 0x8C, 0x5B, 0x90, 0x33, 0x37, 0x84, 0x7F, + 0xCD, 0x36, 0x44, 0x6B, 0x64, 0x4C, 0xAD, 0x15, 0xDF, 0xEC, 0xDA, 0xB7, 0x47, 0x98, 0x78, 0xF6, + 0xEE, 0x86, 0xF2, 0xCB, 0x5D, 0x87, 0xFD, 0xB3, 0xB5, 0x1E, 0xB9, 0xB1, 0x43, 0xBC, 0x2B, 0x75, + 0xED, 0x06, 0x63, 0x28, 0x0C, 0x40, 0xBF, 0xDD, 0x49, 0x44, 0xFC, 0x6B, 0x1E, 0x29, 0x8D, 0x8B, + 0xFE, 0x54, 0x38, 0xE4, 0x3A, 0xF0, 0xC7, 0x64, 0xEF, 0x8C, 0x03, 0x0C, 0xC9, 0x04, 0xB8, 0x92, + 0x22, 0xF5, 0x38, 0x16, 0xCC, 0xA5, 0x70, 0xCE, 0xD1, 0x48, 0x87, 0xF4, 0x07, 0xC0, 0x49, 0x30, + 0x76, 0x3D, 0x0A, 0xF4, 0xDD, 0xC1, 0x0D, 0x49, 0x35, 0x00, 0xF3, 0xA2, 0x22, 0x3B, 0x7E, 0xE0, + 0x0E, 0x61, 0xEC, 0x8C, 0x18, 0xE1, 0xC4, 0x33, 0x8C, 0xB3, 0x33, 0xC4, 0x42, 0xFF, 0xC3, 0x2E, + 0xF1, 0xA6, 0xA3, 0xD1, 0x92, 0x1E, 0x5D, 0x18, 0x4B, 0x51, 0xAB, 0x5F, 0x25, 0x69, 0x03, 0xFF, + 0xF6, 0x8A, 0xEC, 0x8D, 0x46, 0xA4, 0x0F, 0xDF, 0x9D, 0xE2, 0x54, 0x7E, 0xBE, 0x17, 0xFA, 0x23, + 0xDA, 0x19, 0x81, 0xC6, 0xB6, 0x3E, 0xF1, 0x1B, 0xA9, 0x04, 0xFE, 0x03, 0x39, 0x81, 0xD0, 0xB2, + 0x32, 0x30, 0x27, 0xF1, 0xB8, 0x4E, 0xD2, 0x56, 0x8E, 0x7C, 0xDB, 0xF9, 0xD5, 0x76, 0x23, 0xE5, + 0x22, 0x3A, 0x66, 0x02, 0x11, 0x6F, 0x25, 0x84, 0xD3, 0xAB, 0xB1, 0x1B, 0xC5, 0x69, 0x22, 0x31, + 0x63, 0x08, 0x0C, 0x36, 0x2C, 0x0F, 0xBF, 0x58, 0x5F, 0xD3, 0xB8, 0x76, 0x9C, 0xB2, 0x44, 0x6C, + 0xBB, 0x47, 0xEF, 0x08, 0xDE, 0x02, 0x94, 0x93, 0x5A, 0xC4, 0xC5, 0x1D, 0x7B, 0x32, 0xE1, 0x83, + 0x2A, 0x8B, 0xB6, 0xCD, 0xC8, 0x2E, 0xA5, 0x38, 0xED, 0xFF, 0xB0, 0xBF, 0x0B, 0x7C, 0xBF, 0x9D, + 0x1C, 0x7F, 0x88, 0x30, 0xE5, 0xD8, 0x5F, 0xA7, 0x34, 0x8C, 0x62, 0xAC, 0x58, 0xA1, 0xE3, 0x03, + 0xC2, 0xC5, 0xD6, 0xD9, 0xC7, 0xFE, 0x05, 0xE6, 0x30, 0x59, 0x9D, 0xB2, 0x16, 0xC5, 0x88, 0x5B, + 0x72, 0x4D, 0x36, 0xB4, 0x62, 0x4E, 0xE2, 0x91, 0xC7, 0xCD, 0x98, 0x2C, 0x0D, 0x43, 0xAC, 0xE5, + 0xEB, 0xAB, 0xE0, 0x0D, 0x2F, 0x74, 0xF1, 0x0E, 0xDF, 0x44, 0x49, 0x20, 0xD5, 0xDA, 0x29, 0x10, + 0x6D, 0x3F, 0xB2, 0xA3, 0x69, 0x88, 0xE1, 0xCD, 0xAA, 0x41, 0x2E, 0x26, 0x08, 0xD5, 0x8B, 0x90, + 0x66, 0x06, 0x32, 0x1F, 0x76, 0xE6, 0x4A, 0xAD, 0xDC, 0xC1, 0xAC, 0x10, 0xF0, 0x83, 0x21, 0x8D, + 0xCE, 0x6C, 0x37, 0x80, 0x19, 0x11, 0x8D, 0xAB, 0x3A, 0x83, 0x5C, 0x45, 0xDE, 0x3B, 0x56, 0x83, + 0x97, 0x19, 0x44, 0x84, 0xDA, 0xCB, 0xF2, 0xFA, 0x84, 0x0C, 0x97, 0x1F, 0x45, 0xD4, 0xEB, 0x48, + 0x39, 0x09, 0x26, 0x94, 0x06, 0x27, 0x7B, 0xFB, 0xA1, 0x0E, 0x77, 0xEA, 0x7B, 0x34, 0x2F, 0x32, + 0x95, 0x51, 0x3C, 0x0C, 0x27, 0xA7, 0xFE, 0xDD, 0x19, 0x80, 0x87, 0x06, 0xF3, 0x0B, 0x8C, 0x31, + 0x23, 0xA9, 0xE7, 0x84, 0x1B, 0xC6, 0x26, 0x4A, 0x14, 0x18, 0x38, 0x66, 0x70, 0x2C, 0x54, 0x47, + 0x24, 0xEF, 0xCA, 0x8B, 0x90, 0x95, 0xF1, 0xA4, 0x2C, 0x24, 0xE1, 0x0A, 0xB6, 0xE3, 0x1C, 0xDE, + 0xC2, 0x2F, 0x18, 0xA6, 0x4C, 0x01, 0xFF, 0x62, 0xEB, 0xE0, 0xE3, 0x09, 0xD8, 0xE2, 0x08, 0xBF, + 0x41, 0x47, 0x50, 0x4C, 0x8F, 0xB7, 0x48, 0xB1, 0xCA, 0x12, 0xD9, 0x7D, 0x03, 0x0C, 0x26, 0x1A, + 0x2E, 0x04, 0x56, 0x21, 0xF6, 0x21, 0x9B, 0x64, 0x4C, 0x89, 0x78, 0x60, 0x77, 0xE9, 0xD1, 0xA9, + 0x67, 0xB7, 0xF6, 0xE0, 0x17, 0x8E, 0x39, 0x89, 0x78, 0x70, 0x31, 0x0C, 0xC2, 0xFE, 0x0E, 0xBF, + 0xA8, 0xA1, 0x0F, 0xBC, 0xDA, 0x17, 0xF7, 0x6B, 0xC7, 0xF7, 0x06, 0x23, 0x77, 0x80, 0x69, 0x3E, + 0x12, 0xD9, 0x2E, 0x66, 0x5E, 0xB5, 0x56, 0xD3, 0xEF, 0xE5, 0xBC, 0x55, 0xCB, 0x5D, 0x2C, 0x3B, + 0x9C, 0x06, 0x2C, 0x68, 0x1A, 0x1D, 0xE1, 0x0F, 0x7F, 0x03, 0xE1, 0x67, 0xE5, 0xC4, 0xF1, 0xE1, + 0xC0, 0x37, 0x92, 0x34, 0x20, 0xEA, 0xD3, 0x81, 0xBA, 0x6D, 0x42, 0x56, 0x73, 0xE9, 0x49, 0xC1, + 0xD8, 0x0F, 0xF2, 0x68, 0x37, 0xA2, 0x9C, 0x07, 0x73, 0x29, 0xD5, 0x22, 0xDE, 0xA4, 0x26, 0x18, + 0x98, 0xC3, 0xB4, 0x62, 0x78, 0x27, 0x98, 0xC7, 0x8B, 0x1C, 0x79, 0x4D, 0x58, 0x8B, 0x53, 0xD8, + 0x1A, 0x70, 0x95, 0x3C, 0x5B, 0xCE, 0xED, 0x48, 0x28, 0xEA, 0x9B, 0xDF, 0x42, 0xE6, 0x76, 0x84, + 0x79, 0x7E, 0xB9, 0x8F, 0x16, 0x9B, 0x5A, 0xF4, 0x0E, 0x21, 0xE6, 0xD1, 0x9C, 0x18, 0x51, 0xA5, + 0xB6, 0xE4, 0xF0, 0x99, 0x36, 0x24, 0xBF, 0xB1, 0x86, 0xB6, 0x14, 0xBF, 0x09, 0xDF, 0xB8, 0x65, + 0x33, 0x3D, 0x35, 0xCF, 0xDB, 0x89, 0xEB, 0x82, 0xA2, 0x66, 0x0E, 0x93, 0x25, 0x42, 0xF3, 0x66, + 0xBE, 0x67, 0x19, 0x9D, 0xE6, 0xDD, 0xCA, 0xF7, 0x7A, 0x9E, 0x28, 0x53, 0x23, 0x79, 0x23, 0xF2, + 0x1B, 0xC9, 0x85, 0x90, 0x6D, 0xA4, 0x52, 0x29, 0x6F, 0xA7, 0x2F, 0xB3, 0xBE, 0x6E, 0xB0, 0xA5, + 0xA7, 0x3C, 0xA4, 0x64, 0xCC, 0x74, 0x2F, 0x1D, 0x89, 0x6E, 0x75, 0x36, 0xF0, 0x74, 0x73, 0x0F, + 0x9C, 0x5B, 0x98, 0x8A, 0xD1, 0x6F, 0x3B, 0xEE, 0xAE, 0x1E, 0xF7, 0x14, 0x64, 0x0F, 0xEA, 0x45, + 0xA4, 0xD2, 0xED, 0x81, 0xDB, 0xEC, 0x6D, 0xD7, 0xCA, 0xFC, 0x6C, 0x77, 0x36, 0xE7, 0xC8, 0x4F, + 0x76, 0xBF, 0xA8, 0x0E, 0x33, 0xDD, 0xEE, 0xE6, 0x5C, 0xA5, 0xA3, 0xA7, 0x16, 0xAE, 0xC3, 0xCB, + 0x3A, 0xEE, 0x5B, 0x34, 0x60, 0xA5, 0x19, 0x35, 0x65, 0x73, 0x45, 0xC5, 0x6C, 0x18, 0xA3, 0xA6, + 0x97, 0xE0, 0x1B, 0x0F, 0xCD, 0x9A, 0xCF, 0xCA, 0xA7, 0x23, 0xCE, 0x70, 0x39, 0x38, 0xF7, 0xFA, + 0xB2, 0x69, 0x44, 0x57, 0x80, 0xCF, 0x6B, 0x75, 0xF2, 0x7E, 0xCF, 0x3C, 0x5A, 0x5D, 0xE5, 0x31, + 0x20, 0xAD, 0xD5, 0x1C, 0xA4, 0x79, 0xAB, 0x8B, 0xE1, 0x0D, 0xAD, 0xD6, 0xAE, 0x8B, 0xCD, 0xDE, + 0xF2, 0x2C, 0xC2, 0x92, 0xD6, 0x1B, 0x2E, 0xA6, 0x01, 0x90, 0xC8, 0x11, 0xAF, 0x45, 0xC1, 0x96, + 0x8A, 0xA2, 0x14, 0x99, 0xBA, 0x71, 0x67, 0x10, 0x0B, 0x2E, 0xE3, 0x30, 0x27, 0x2A, 0x66, 0xFD, + 0xF5, 0xE8, 0x68, 0x16, 0x81, 0x64, 0x51, 0x25, 0x59, 0x4D, 0x2C, 0xB3, 0x0E, 0xC4, 0x10, 0x6F, + 0xED, 0xA9, 0x73, 0x10, 0xF8, 0x13, 0x4C, 0xA8, 0x6F, 0x9E, 0x7A, 0x95, 0x27, 0xE5, 0x4A, 0xF5, + 0xA5, 0x02, 0x47, 0x5D, 0xF3, 0xEC, 0x58, 0x85, 0x23, 0xE1, 0x2C, 0xD4, 0xE2, 0xA8, 0x29, 0xAD, + 0x1A, 0xAD, 0x37, 0x68, 0x7B, 0xFE, 0x23, 0x8F, 0x33, 0x6A, 0x7D, 0xE9, 0xEB, 0x91, 0xE6, 0xFE, + 0x9E, 0x80, 0x99, 0xE2, 0xCF, 0x07, 0x37, 0x12, 0x58, 0x39, 0xB8, 0x22, 0x83, 0x69, 0x48, 0x8F, + 0xFD, 0x81, 0x3D, 0x72, 0xFF, 0x46, 0x9D, 0x03, 0x68, 0x67, 0xE0, 0x5E, 0x4D, 0x79, 0x1A, 0xC9, + 0xE6, 0xCD, 0x2F, 0xC0, 0x59, 0xD8, 0xF2, 0x91, 0x09, 0xE8, 0x02, 0x56, 0x80, 0xC7, 0xB0, 0xA6, + 0x1D, 0x99, 0x7A, 0xBF, 0x82, 0x3C, 0x9A, 0x22, 0x35, 0x68, 0x8A, 0xFE, 0xD6, 0xE4, 0x8C, 0xFA, + 0x51, 0xE3, 0xE9, 0xCA, 0xC2, 0x11, 0x75, 0x40, 0x23, 0xDB, 0x1D, 0x85, 0x35, 0xE5, 0x52, 0x07, + 0x51, 0x81, 0x2C, 0x3E, 0xD8, 0x81, 0x83, 0x5B, 0x41, 0x5C, 0x10, 0xC9, 0x1B, 0x3C, 0x73, 0x12, + 0x4D, 0x0E, 0xF6, 0x5A, 0x92, 0x92, 0x61, 0x67, 0x13, 0x55, 0x25, 0x4C, 0x26, 0x59, 0xB1, 0x8D, + 0xA5, 0x39, 0x48, 0x25, 0xC6, 0x53, 0xA9, 0xFD, 0x6C, 0xC7, 0xA5, 0x59, 0x83, 0x8B, 0x41, 0x4D, + 0x1E, 0x83, 0xB4, 0x65, 0x37, 0x07, 0x77, 0x41, 0xC5, 0x96, 0x63, 0x33, 0x0C, 0xBB, 0x85, 0xB3, + 0xF9, 0x08, 0x85, 0xC8, 0x4A, 0x7D, 0x04, 0xE5, 0x69, 0xBA, 0x19, 0x05, 0x50, 0xFE, 0xC0, 0x9D, + 0x6C, 0x34, 0x03, 0xBB, 0x59, 0x2F, 0x17, 0x42, 0x1A, 0xDB, 0xD6, 0x78, 0x74, 0x23, 0xAB, 0x1F, + 0x80, 0xA8, 0x3A, 0x78, 0xE2, 0x8D, 0xBD, 0x7C, 0x5A, 0xE7, 0x47, 0xA7, 0x87, 0xBF, 0xCD, 0x43, + 0x9E, 0x0A, 0xB6, 0x6A, 0xE6, 0x23, 0x03, 0xD9, 0xD0, 0x78, 0x54, 0xC7, 0x63, 0x90, 0x83, 0xF2, + 0xB0, 0xD9, 0x8C, 0x52, 0xA8, 0xFA, 0x48, 0x9A, 0x2E, 0x83, 0x14, 0x6E, 0x16, 0x09, 0x54, 0xC0, + 0x62, 0x6A, 0xBF, 0xE9, 0xE5, 0xB3, 0x59, 0xE5, 0x50, 0xF3, 0x35, 0xB5, 0x8C, 0x3C, 0x00, 0x7E, + 0x6C, 0x47, 0xEE, 0x40, 0x45, 0x32, 0x93, 0x70, 0x6A, 0xA2, 0xCC, 0x91, 0x54, 0xFC, 0x56, 0xDA, + 0x1C, 0x04, 0x54, 0xE1, 0xD9, 0xB5, 0x5C, 0xB9, 0x30, 0xD8, 0xB9, 0x88, 0xA3, 0x18, 0x93, 0x22, + 0x85, 0xCA, 0xCF, 0xA8, 0x35, 0x16, 0xCE, 0x3C, 0x1E, 0x6A, 0x93, 0xF6, 0xBE, 0x0B, 0xB1, 0x35, + 0x93, 0x5E, 0x43, 0x9C, 0xD9, 0x2D, 0xD9, 0xBD, 0x51, 0xE4, 0x46, 0x53, 0xA7, 0xD1, 0x60, 0x53, + 0x42, 0x20, 0x32, 0xE8, 0xF5, 0xA7, 0x3F, 0x1F, 0x8B, 0x40, 0x66, 0xF3, 0x6B, 0xCE, 0x64, 0xD4, + 0x80, 0x94, 0x39, 0x22, 0x4F, 0xEE, 0x15, 0xDF, 0xF3, 0x7B, 0xC5, 0xF7, 0xE4, 0x35, 0xF1, 0xA6, + 0xE3, 0xFD, 0xCC, 0x0B, 0xAE, 0x50, 0x94, 0xBD, 0x5D, 0x0C, 0xCB, 0x9B, 0xC8, 0xF7, 0xC4, 0xE5, + 0x62, 0xF6, 0x64, 0x09, 0x66, 0xA7, 0x79, 0xCB, 0xBE, 0xE2, 0xB3, 0x12, 0xF7, 0x4A, 0x80, 0x52, + 0x5A, 0xDB, 0xD8, 0x04, 0x3C, 0xA6, 0xCB, 0x6D, 0x41, 0x9C, 0x39, 0x27, 0xC5, 0xBF, 0x8F, 0xF5, + 0x17, 0xEF, 0x65, 0xF5, 0x92, 0x5E, 0x87, 0x58, 0x92, 0x83, 0x61, 0x72, 0xDC, 0x01, 0x29, 0xB5, + 0x54, 0xBD, 0xE8, 0xB4, 0x92, 0x07, 0x58, 0x2B, 0xCC, 0xF0, 0x82, 0x87, 0x13, 0x86, 0x7D, 0x96, + 0x29, 0xBE, 0x04, 0x91, 0x31, 0xD4, 0x62, 0x6E, 0xEC, 0xCF, 0x81, 0x71, 0x13, 0xCB, 0x4A, 0x4C, + 0x5A, 0x51, 0xFA, 0xA3, 0x82, 0xC4, 0x4C, 0x39, 0x3A, 0xAC, 0xDD, 0x90, 0x6F, 0xAE, 0xFD, 0x69, + 0x4E, 0xD6, 0xFC, 0x6C, 0x4E, 0xF7, 0x2C, 0x6D, 0xDF, 0x77, 0xD3, 0x2E, 0x7D, 0x95, 0xC1, 0xF3, + 0x7D, 0xC7, 0xB4, 0xDD, 0x2E, 0x0F, 0x22, 0xCC, 0x0E, 0x2D, 0x0E, 0xE4, 0x59, 0x66, 0x66, 0x8D, + 0x15, 0xAC, 0x84, 0x5C, 0x94, 0xEC, 0xBE, 0xAB, 0x69, 0xC1, 0x0C, 0x63, 0x0C, 0xBF, 0xF1, 0xBF, + 0xD3, 0xB8, 0x23, 0x72, 0xE4, 0x0D, 0x02, 0x16, 0x2D, 0x32, 0x11, 0xF9, 0xB2, 0xC8, 0x0A, 0x09, + 0xEF, 0xEC, 0x09, 0x7F, 0x7D, 0x9B, 0x1D, 0xF4, 0xC3, 0x9C, 0x94, 0xF2, 0x44, 0x42, 0xC6, 0x13, + 0x4F, 0x1F, 0x82, 0x75, 0x3C, 0x4C, 0x6D, 0x7D, 0x03, 0x76, 0x99, 0x86, 0xE9, 0x8B, 0x9B, 0x29, + 0x29, 0xF2, 0x46, 0xDD, 0xA1, 0x64, 0xC9, 0x0C, 0xEC, 0x6F, 0xF4, 0x84, 0x7E, 0x40, 0x98, 0x60, + 0xC7, 0x50, 0xC2, 0x92, 0xF9, 0xED, 0x64, 0x7B, 0xB7, 0xB6, 0x5E, 0x54, 0xE9, 0xDD, 0xEF, 0xAC, + 0x77, 0xB3, 0xB2, 0x91, 0xFF, 0xC9, 0x0C, 0xA7, 0x99, 0xBD, 0xCC, 0x27, 0x2C, 0xD5, 0xE8, 0xC9, + 0x12, 0x5A, 0x21, 0xDD, 0xA5, 0x7C, 0xAA, 0x4C, 0x18, 0x45, 0x44, 0x1F, 0xE6, 0x28, 0x28, 0x66, + 0x32, 0xE5, 0xD6, 0x9A, 0xF8, 0x2A, 0x69, 0xDD, 0x0A, 0x5E, 0x46, 0x92, 0x55, 0xAB, 0x44, 0x58, + 0x12, 0x4D, 0xD6, 0x56, 0x13, 0x49, 0xC0, 0x76, 0xEA, 0x47, 0xF4, 0x15, 0x69, 0x95, 0x10, 0x5F, + 0x06, 0xE2, 0x2D, 0xE2, 0x7B, 0xA3, 0x7B, 0x72, 0xE7, 0x07, 0xDF, 0xC2, 0x98, 0x59, 0xF8, 0xDB, + 0xBD, 0x36, 0xA1, 0x2D, 0xC0, 0xC7, 0x9E, 0x48, 0x71, 0xBD, 0xA8, 0xCD, 0xDE, 0xA6, 0x0F, 0x59, + 0xF6, 0xE9, 0x0E, 0xF9, 0x84, 0x63, 0xC5, 0x0E, 0xF0, 0x91, 0xAE, 0x08, 0xC7, 0x0A, 0xA5, 0xC4, + 0xBE, 0xF2, 0x6F, 0x69, 0x5D, 0x31, 0x2D, 0xC7, 0x62, 0x3A, 0xA0, 0x85, 0x62, 0x7A, 0x50, 0x32, + 0x96, 0x90, 0xA3, 0x6B, 0x62, 0x8F, 0xA0, 0xBE, 0x73, 0xCF, 0x46, 0x9F, 0x18, 0x78, 0xC9, 0xE8, + 0x6D, 0x33, 0x49, 0x12, 0x37, 0x22, 0x23, 0x90, 0xA5, 0x18, 0x91, 0x9A, 0x25, 0x67, 0xC1, 0x38, + 0x7B, 0xE3, 0x0F, 0x1C, 0xF4, 0x69, 0xC7, 0x19, 0xDA, 0x02, 0x6C, 0x86, 0x45, 0xDC, 0x90, 0x7C, + 0x90, 0xAC, 0x86, 0x82, 0x2A, 0x61, 0x2E, 0xAB, 0xF7, 0xF8, 0xEF, 0x0A, 0xDA, 0xFF, 0xED, 0x69, + 0x86, 0x03, 0x3E, 0xC5, 0x90, 0x70, 0xF3, 0xC8, 0x83, 0x21, 0xE7, 0x6C, 0xB6, 0x34, 0xD1, 0xA0, + 0xB1, 0x4D, 0x68, 0x55, 0x18, 0xE1, 0xE3, 0x54, 0x0F, 0xF2, 0x95, 0xAB, 0x6E, 0x8A, 0x42, 0x74, + 0xFB, 0xF6, 0x0F, 0xDF, 0x25, 0x53, 0xB7, 0xFC, 0x8C, 0x5A, 0x72, 0x75, 0xC6, 0x83, 0x49, 0x07, + 0xE3, 0xC2, 0xB0, 0x66, 0x72, 0x8A, 0x1C, 0xD0, 0x31, 0x0C, 0x96, 0xB7, 0xB6, 0x83, 0x6B, 0x8D, + 0x70, 0x31, 0x5B, 0x27, 0xF6, 0x68, 0x8D, 0xAF, 0xBA, 0x4A, 0xB5, 0xC5, 0x9B, 0xAE, 0x99, 0xE7, + 0xC7, 0xD7, 0xB7, 0xD9, 0xAB, 0xAE, 0x36, 0xCC, 0x5B, 0xEA, 0xD3, 0xAE, 0x72, 0x72, 0xE9, 0x9D, + 0x17, 0x39, 0xAF, 0xD4, 0x4A, 0xC1, 0xF1, 0x6D, 0xB2, 0xF2, 0x32, 0x7E, 0x9B, 0xF6, 0x65, 0xE6, + 0x91, 0xDA, 0xB8, 0x0C, 0x49, 0x8A, 0x5F, 0x9B, 0x13, 0xFB, 0xFC, 0x94, 0xC4, 0x7E, 0x9F, 0x27, + 0xB1, 0x9C, 0x87, 0xF4, 0x94, 0x29, 0x3F, 0x7E, 0x89, 0x0A, 0x7B, 0x8E, 0xD8, 0x43, 0x1B, 0x5F, + 0x32, 0xE4, 0xCF, 0x63, 0xB8, 0x92, 0x62, 0xF2, 0xE7, 0x76, 0x1C, 0xFA, 0x5D, 0xBD, 0x33, 0xC4, + 0x06, 0xF1, 0x8E, 0x28, 0x79, 0x8D, 0x01, 0xD8, 0x7E, 0xE0, 0x84, 0x4C, 0x5D, 0xE2, 0xE0, 0xC1, + 0xE5, 0x65, 0x56, 0xAA, 0x8F, 0x4E, 0x44, 0x08, 0x86, 0x3A, 0x0A, 0x99, 0xD6, 0x25, 0x60, 0x5F, + 0x58, 0xE5, 0xAF, 0x71, 0x72, 0x6B, 0xA2, 0xE7, 0xD4, 0x8D, 0xBD, 0x6A, 0x45, 0xD7, 0xA4, 0xD3, + 0x4D, 0x86, 0x12, 0x33, 0x58, 0x1B, 0x86, 0x6A, 0x96, 0x0C, 0x0E, 0xCF, 0xEC, 0x30, 0x58, 0x26, + 0x0B, 0x2C, 0xC1, 0x6C, 0xAA, 0x6D, 0x79, 0x05, 0x9F, 0xF3, 0x0A, 0x7E, 0xD7, 0x93, 0x17, 0xD7, + 0x34, 0x8E, 0xFC, 0xD5, 0x19, 0x26, 0xEE, 0x5D, 0x83, 0x54, 0x97, 0x5E, 0xE4, 0xB4, 0xAB, 0x33, + 0x99, 0x86, 0x37, 0x8B, 0x8F, 0xDA, 0xA6, 0x25, 0x43, 0xE2, 0x54, 0x24, 0x84, 0x6B, 0x4C, 0xDD, + 0x10, 0x39, 0x14, 0x63, 0x88, 0x13, 0x5B, 0x94, 0x44, 0xAE, 0x02, 0x22, 0x11, 0x20, 0x8E, 0x11, + 0xCE, 0x50, 0x53, 0xBA, 0x7B, 0x22, 0xF7, 0x68, 0x7A, 0xC7, 0x12, 0x21, 0xDE, 0xB0, 0xE4, 0xDC, + 0xEA, 0x4C, 0x69, 0x52, 0x21, 0xA8, 0x6B, 0x56, 0x20, 0x04, 0x40, 0xD9, 0x88, 0xD5, 0x40, 0xAC, + 0x2B, 0x52, 0xA0, 0x17, 0x9F, 0x26, 0x59, 0x14, 0xFC, 0x62, 0xEB, 0x80, 0x71, 0x4F, 0xF0, 0xB0, + 0x91, 0xB5, 0x06, 0x97, 0x0B, 0x09, 0xF8, 0x32, 0x69, 0xFD, 0x4B, 0x6B, 0x29, 0x6F, 0x3B, 0x48, + 0xEE, 0x12, 0xE4, 0x64, 0x40, 0xB1, 0x05, 0x60, 0x13, 0x73, 0xD6, 0x8E, 0xC5, 0x62, 0xC4, 0x80, + 0x6C, 0xC5, 0xA0, 0xFF, 0x40, 0x19, 0xE6, 0xDE, 0x51, 0xE2, 0xD2, 0xEC, 0x7E, 0xCD, 0xA9, 0xFA, + 0x39, 0x53, 0xB5, 0x97, 0x57, 0xF5, 0xF7, 0x4C, 0xD5, 0x35, 0xAD, 0xAA, 0x79, 0xF4, 0x4B, 0x1D, + 0x6A, 0x7A, 0x07, 0x51, 0xE6, 0xBA, 0xA4, 0xC6, 0xE7, 0xD2, 0x1A, 0xBF, 0xE7, 0xD5, 0x50, 0x59, + 0x53, 0x5E, 0xFC, 0x4B, 0x1E, 0x27, 0x92, 0x04, 0x0D, 0x5E, 0x6C, 0x60, 0x83, 0x5F, 0xC8, 0x15, + 0x80, 0xD8, 0x9E, 0x43, 0xC6, 0xBE, 0xE7, 0x87, 0x13, 0x1B, 0x56, 0x71, 0x2C, 0xD6, 0x9C, 0x99, + 0x61, 0x6D, 0xA5, 0x9E, 0x2A, 0x8A, 0x14, 0xB0, 0x9E, 0xAB, 0x06, 0x22, 0x2F, 0x7A, 0x3A, 0xF5, + 0xA3, 0x32, 0x64, 0x8D, 0x4A, 0x66, 0x66, 0xE0, 0xFB, 0x09, 0x79, 0x68, 0xD3, 0xE6, 0xCB, 0x4D, + 0xC6, 0x7B, 0x5F, 0x7A, 0x88, 0xBE, 0xF4, 0x6A, 0x11, 0x66, 0xB8, 0xF4, 0x03, 0xEA, 0xB4, 0x8A, + 0x9E, 0x34, 0x65, 0x3B, 0x21, 0x33, 0x93, 0x15, 0xA5, 0xAF, 0xC8, 0x6F, 0xAB, 0x9F, 0x57, 0x7F, + 0x6F, 0xA9, 0x79, 0xE4, 0x0D, 0xAD, 0x7F, 0x4D, 0x36, 0x96, 0x32, 0xC7, 0x87, 0xB9, 0x32, 0x0D, + 0xDD, 0xBF, 0x51, 0x62, 0x32, 0xCD, 0x8A, 0x75, 0x4C, 0x7C, 0xDC, 0x74, 0xEA, 0xAC, 0x3B, 0x57, + 0xE2, 0x00, 0xF5, 0x27, 0xAC, 0xEF, 0xA5, 0x40, 0x7F, 0xF4, 0x56, 0x41, 0x0D, 0x44, 0x62, 0xF1, + 0x05, 0x5E, 0x41, 0x1E, 0xA6, 0xFC, 0x0B, 0xDB, 0xBB, 0x30, 0x4E, 0xB0, 0x99, 0x9A, 0xF1, 0x18, + 0x62, 0xC5, 0xEA, 0x68, 0xCB, 0x15, 0x02, 0x66, 0x55, 0xE7, 0xE0, 0xEA, 0xA4, 0xF0, 0xC7, 0xC5, + 0xD6, 0xFF, 0x32, 0x03, 0x09, 0x6A, 0x00, 0x4B, 0xED, 0xC1, 0xCD, 0xA2, 0x79, 0x17, 0x52, 0xB6, + 0x49, 0x7F, 0x5C, 0x8C, 0x6E, 0xDC, 0x90, 0x6F, 0xC2, 0x2C, 0x2E, 0x15, 0x5A, 0x75, 0x4F, 0xB5, + 0xEA, 0x9D, 0x70, 0x7A, 0xC5, 0x57, 0x85, 0x8B, 0xE0, 0x3F, 0x75, 0x37, 0x94, 0x57, 0xE6, 0x25, + 0xA4, 0x09, 0x28, 0x4C, 0x78, 0x3C, 0xB1, 0x7C, 0x6C, 0xC9, 0x92, 0x29, 0x30, 0xB6, 0x57, 0xDA, + 0x87, 0xB5, 0xAF, 0x1C, 0x45, 0xBA, 0xD9, 0xAB, 0x39, 0xE1, 0xF1, 0xCD, 0xCA, 0x6A, 0x8E, 0x78, + 0x5C, 0xBB, 0xCC, 0x19, 0x57, 0xEB, 0x55, 0x71, 0xC8, 0x63, 0x88, 0x79, 0x39, 0xE5, 0xE9, 0x33, + 0x63, 0x85, 0xEE, 0x6C, 0x72, 0xE0, 0x00, 0x1E, 0x6D, 0xB7, 0x6B, 0xAD, 0xAD, 0xB7, 0xC9, 0xD6, + 0x96, 0x42, 0x9D, 0x7F, 0x46, 0x16, 0xB0, 0xA0, 0xB6, 0xD3, 0xAC, 0x9F, 0x3B, 0x20, 0x9D, 0x0D, + 0xEC, 0x6B, 0x85, 0xC4, 0x06, 0x7B, 0x78, 0x70, 0xA3, 0x29, 0x76, 0xED, 0xD0, 0x01, 0x68, 0xF4, + 0x2C, 0xAB, 0x63, 0xB1, 0x8B, 0x92, 0x1D, 0xC5, 0x33, 0x67, 0x1F, 0x90, 0x18, 0xFB, 0xE5, 0xD9, + 0x79, 0xE5, 0x89, 0xDE, 0xD4, 0xF7, 0xCC, 0x63, 0xD0, 0xBA, 0xDE, 0x79, 0xA2, 0x78, 0xF5, 0x3C, + 0x74, 0x8D, 0x9C, 0xE4, 0xA5, 0x6B, 0x63, 0x44, 0xF1, 0x51, 0xC5, 0x15, 0x65, 0x63, 0x91, 0xB8, + 0x91, 0x6C, 0x2A, 0x8B, 0xB5, 0x54, 0x2B, 0xD3, 0x74, 0xCB, 0x5C, 0xAA, 0xEA, 0xC6, 0x23, 0xF8, + 0xFC, 0x5A, 0x9F, 0x19, 0xFD, 0xFE, 0xA4, 0x8E, 0xE2, 0xFB, 0xFF, 0x03, 0x48, 0xCA, 0xB4, 0x92, + 0x88, 0xD9, 0xCE, 0x5F, 0x4D, 0x64, 0x8C, 0x6A, 0x99, 0x33, 0xAC, 0x2B, 0x61, 0x6D, 0x87, 0x38, + 0x51, 0xC7, 0xE7, 0xB3, 0xB0, 0x48, 0x7A, 0xB7, 0xFA, 0xE2, 0xA2, 0x48, 0xB2, 0xD2, 0xC9, 0xA5, + 0xBC, 0x4C, 0xBB, 0xB1, 0xE9, 0x09, 0x8D, 0x6E, 0x7C, 0x27, 0xF7, 0x8E, 0xA1, 0x72, 0xC1, 0x30, + 0xBD, 0x5A, 0xFF, 0x2A, 0xBE, 0x49, 0x9F, 0x79, 0xC1, 0x0A, 0x50, 0xA6, 0xF2, 0x97, 0xF0, 0x6B, + 0x71, 0xC9, 0xD9, 0xD3, 0xD8, 0xFC, 0x18, 0x30, 0xD3, 0x01, 0x77, 0x6E, 0x90, 0x17, 0x90, 0x84, + 0x6F, 0xE2, 0x59, 0xA7, 0x9C, 0x24, 0x04, 0x4B, 0x64, 0x85, 0x2C, 0x4A, 0x55, 0xB2, 0xC7, 0xDB, + 0xA2, 0xDA, 0x32, 0xC9, 0xD6, 0x32, 0x5F, 0xD0, 0x58, 0x22, 0xAB, 0xA4, 0xCB, 0x2F, 0xD6, 0x17, + 0xB1, 0x1D, 0xCF, 0xFC, 0xC0, 0x65, 0x07, 0xE3, 0x59, 0xA0, 0x74, 0x71, 0xAD, 0xE8, 0x3E, 0x77, + 0xA1, 0x9C, 0xB2, 0xB9, 0x2B, 0x0A, 0xC4, 0xA4, 0x09, 0xD5, 0x2C, 0x27, 0x9D, 0x55, 0x14, 0xC1, + 0x13, 0x4A, 0x2A, 0x93, 0x2B, 0xC2, 0x2C, 0x27, 0x7D, 0xE9, 0xFC, 0x6C, 0x2D, 0xC6, 0x74, 0x7C, + 0x26, 0xE0, 0x18, 0xBC, 0xB2, 0x82, 0x88, 0x29, 0x26, 0x95, 0xDE, 0xEC, 0x92, 0x4D, 0xD3, 0x54, + 0x3D, 0xB2, 0xA3, 0x18, 0x4B, 0x5A, 0x79, 0x85, 0xAC, 0xA3, 0x20, 0x7B, 0x86, 0x57, 0xF5, 0x72, + 0xA7, 0x66, 0xC3, 0xF2, 0xB9, 0x24, 0x05, 0x48, 0x76, 0xC9, 0x1F, 0x73, 0x9D, 0x30, 0xF5, 0x26, + 0x7B, 0xDF, 0x40, 0x59, 0x18, 0x8D, 0x61, 0x35, 0x18, 0xB3, 0xDF, 0xDD, 0x91, 0xFE, 0x7C, 0x9D, + 0x34, 0x4C, 0xFA, 0x9A, 0x3D, 0x07, 0x28, 0xE5, 0x72, 0x79, 0x57, 0xF1, 0xD9, 0x53, 0x02, 0xCB, + 0x44, 0x67, 0x3C, 0xBB, 0xE7, 0xFF, 0x90, 0x23, 0x89, 0x6C, 0x82, 0x13, 0x21, 0x0A, 0xC0, 0x1A, + 0xB3, 0xFD, 0xBC, 0xA4, 0xA2, 0x73, 0x5C, 0x24, 0x96, 0xFC, 0x46, 0x54, 0x96, 0x90, 0xC1, 0xA6, + 0x71, 0x42, 0x92, 0x86, 0xAE, 0x19, 0x14, 0x2D, 0xC7, 0x80, 0x98, 0xC0, 0x7B, 0xF9, 0xE0, 0xB9, + 0x97, 0xE4, 0x32, 0x48, 0xBA, 0x5F, 0xB5, 0x5B, 0x9E, 0x4D, 0x72, 0xCD, 0xC4, 0xC9, 0x62, 0x6A, + 0xE0, 0xE9, 0x15, 0xE4, 0xAC, 0x51, 0xF0, 0x28, 0x31, 0x45, 0x79, 0x8F, 0xC5, 0x19, 0x06, 0xF5, + 0x4E, 0x6E, 0x5D, 0x75, 0x94, 0x94, 0xD5, 0x4B, 0xF4, 0xA6, 0xA4, 0x62, 0xDA, 0xE1, 0xF9, 0x15, + 0x33, 0x9D, 0x5B, 0x5A, 0x55, 0xEF, 0xC8, 0x8A, 0x81, 0x30, 0x4A, 0x96, 0x93, 0x90, 0x9B, 0xF7, + 0x58, 0x34, 0x84, 0x59, 0x63, 0xBE, 0x12, 0xCF, 0x09, 0x8B, 0xC9, 0xEE, 0xD4, 0x25, 0xC0, 0x8D, + 0x76, 0xEB, 0x54, 0xCF, 0xAB, 0x70, 0xC7, 0x4E, 0xB2, 0xCA, 0x45, 0xBB, 0x76, 0xDA, 0xB2, 0xA0, + 0xF2, 0xCE, 0x9D, 0x49, 0x3F, 0x74, 0xDD, 0x79, 0xC4, 0x1D, 0xBC, 0x86, 0xE4, 0x93, 0x9D, 0x3C, + 0xD0, 0xDA, 0x55, 0xD4, 0xC8, 0x55, 0xD0, 0x36, 0xF3, 0x86, 0x9E, 0x2E, 0x98, 0x8A, 0x9B, 0x7A, + 0x92, 0xD8, 0xD5, 0x8D, 0x3D, 0x7D, 0xCD, 0x5C, 0x73, 0x73, 0xAF, 0xCA, 0x92, 0x7B, 0x9E, 0x1B, + 0x7C, 0xDA, 0xC2, 0x79, 0xB6, 0x4D, 0x3E, 0x49, 0x28, 0xF5, 0x36, 0xFA, 0x92, 0xD1, 0xF2, 0x43, + 0x37, 0xFB, 0x14, 0xF5, 0x90, 0xFD, 0x2B, 0xF4, 0xA4, 0x5E, 0xEA, 0x33, 0xE6, 0xDC, 0xB6, 0x04, + 0x33, 0xF3, 0xA5, 0x5A, 0x61, 0x5D, 0x87, 0xD8, 0xD0, 0x3F, 0x6C, 0x96, 0xA1, 0x78, 0xA9, 0x6C, + 0x3B, 0x96, 0x1A, 0xC3, 0x47, 0xD9, 0xEC, 0x94, 0x74, 0xE0, 0x21, 0x93, 0x2C, 0x4C, 0xD9, 0xB5, + 0x94, 0x72, 0x17, 0x71, 0x97, 0x1B, 0x7E, 0x4A, 0x3D, 0xDB, 0xF9, 0x0F, 0xDF, 0xF5, 0x16, 0x17, + 0x16, 0x92, 0xC4, 0x4D, 0x5A, 0x95, 0x76, 0x79, 0x95, 0x7F, 0xFD, 0xD7, 0x4C, 0x9D, 0x80, 0x46, + 0xD3, 0xC0, 0x63, 0xEE, 0xBA, 0xC6, 0xDD, 0x90, 0x46, 0x98, 0x2E, 0x4A, 0x31, 0xC5, 0x2C, 0x53, + 0x17, 0x98, 0x2C, 0xD0, 0x9E, 0xB8, 0x0C, 0x2D, 0x2A, 0x9F, 0xD6, 0x35, 0xB3, 0xA6, 0xD4, 0x11, + 0x2B, 0x2C, 0x69, 0xD3, 0xEE, 0xE8, 0x9A, 0x6D, 0xD2, 0x45, 0xF6, 0x15, 0xB9, 0xB3, 0x43, 0x82, + 0x73, 0x37, 0xC1, 0x14, 0x53, 0xD4, 0x69, 0x13, 0x3E, 0xA4, 0xB1, 0x6C, 0x44, 0x79, 0x2E, 0xB2, + 0x70, 0x10, 0xE0, 0x13, 0x47, 0xDA, 0x42, 0x67, 0x44, 0x4F, 0x6C, 0xCF, 0x1E, 0xD2, 0xE0, 0x02, + 0x6B, 0x66, 0x92, 0x49, 0x31, 0xF8, 0x37, 0xAF, 0xA3, 0x80, 0xD8, 0x23, 0x77, 0xE8, 0xED, 0x2E, + 0x8C, 0xE8, 0x75, 0xB4, 0x00, 0x1F, 0x6E, 0xDE, 0xE0, 0xFE, 0xC1, 0xEB, 0x55, 0xF8, 0x05, 0xFF, + 0xE8, 0x83, 0x21, 0x13, 0x7F, 0x38, 0x6F, 0x5E, 0xF3, 0x47, 0x29, 0xA3, 0xFB, 0x09, 0xDD, 0xE5, + 0x1E, 0xC7, 0x95, 0xFF, 0x7D, 0x81, 0xB8, 0xCE, 0xEE, 0x02, 0x12, 0xE4, 0xCB, 0xF9, 0xBD, 0xD1, + 0x68, 0x81, 0xB0, 0x37, 0x53, 0xE1, 0xAB, 0x1F, 0x8C, 0x57, 0x58, 0xC5, 0x15, 0x0E, 0x2A, 0xF1, + 0xC5, 0x76, 0x26, 0x17, 0x88, 0x08, 0x5C, 0xE4, 0x18, 0x62, 0x96, 0xFD, 0xE1, 0x10, 0x93, 0xFB, + 0x00, 0x3F, 0xAB, 0x48, 0x76, 0x35, 0x0A, 0x92, 0x1F, 0x8C, 0x6F, 0xC9, 0x6C, 0x23, 0x18, 0x6B, + 0xE2, 0x05, 0xB7, 0x61, 0xAD, 0x96, 0x24, 0xCA, 0xEF, 0xE3, 0xD1, 0x4D, 0x14, 0x4D, 0x0A, 0x13, + 0x78, 0x49, 0xF5, 0x44, 0x1E, 0xAF, 0xF7, 0x87, 0x3C, 0x8D, 0x17, 0xCE, 0xC2, 0x2C, 0xCB, 0x58, + 0x2B, 0xEB, 0x9D, 0xC5, 0x10, 0x2C, 0x3B, 0x93, 0x6C, 0x27, 0x44, 0xD8, 0xD8, 0xC0, 0x1F, 0xA3, + 0x19, 0x89, 0xAB, 0x05, 0x34, 0x9C, 0x80, 0x3B, 0xC1, 0x98, 0x5C, 0xC2, 0x90, 0x1D, 0x91, 0xB3, + 0x8E, 0xEC, 0xF7, 0x7F, 0xE1, 0x59, 0xE6, 0x5C, 0x2F, 0xF2, 0xD9, 0xE4, 0xFF, 0xA2, 0x7A, 0x47, + 0x82, 0xFB, 0xAD, 0x34, 0xBF, 0x64, 0x32, 0x55, 0xB5, 0x2E, 0xF7, 0xB5, 0x28, 0x50, 0x6E, 0x91, + 0xBD, 0x35, 0xA3, 0xDF, 0xFE, 0x55, 0x64, 0xBB, 0xA0, 0x86, 0x52, 0xB9, 0x51, 0xC7, 0x8D, 0xF5, + 0x74, 0x3D, 0x97, 0xD2, 0x60, 0x62, 0x05, 0x5D, 0x45, 0xA5, 0x3E, 0x16, 0xB5, 0xA4, 0x1E, 0x4E, + 0x9A, 0x85, 0xB9, 0xEA, 0x4E, 0xD2, 0xE7, 0xB0, 0xD0, 0xFE, 0x7F, 0xF9, 0x6A, 0x2E, 0x67, 0x1B, + 0xF2, 0xC6, 0x0A, 0xF1, 0x05, 0x8D, 0x5C, 0x0C, 0x71, 0x05, 0x05, 0xC5, 0x1C, 0xB5, 0x2C, 0xCE, + 0x07, 0xFD, 0x03, 0x15, 0x2D, 0xAF, 0x27, 0x96, 0x77, 0x65, 0xF1, 0x2B, 0x66, 0x8A, 0x9C, 0xD3, + 0x89, 0xC0, 0x6E, 0x7B, 0xF7, 0x5C, 0x52, 0x71, 0x65, 0x76, 0xE4, 0x10, 0x32, 0xDF, 0xF6, 0x96, + 0x0B, 0x6D, 0x85, 0xB8, 0x1D, 0xDA, 0x61, 0x86, 0x4D, 0x7C, 0x41, 0xD7, 0x07, 0xFF, 0xC4, 0x77, + 0x28, 0x08, 0x7F, 0x8A, 0x83, 0x38, 0xE2, 0xD6, 0x75, 0x58, 0x18, 0xE1, 0x97, 0xE9, 0xF6, 0xBC, + 0x67, 0xD5, 0x44, 0xEB, 0x32, 0xF5, 0xBF, 0x7C, 0xFF, 0x9A, 0xAE, 0xE7, 0xB2, 0x4A, 0xF2, 0x45, + 0xF6, 0x7A, 0x1E, 0x4A, 0xDB, 0x1C, 0x9B, 0xC2, 0x3A, 0x8D, 0xC6, 0x94, 0xAF, 0x84, 0x47, 0xD9, + 0xA7, 0x08, 0x68, 0x85, 0x66, 0x2B, 0xCA, 0x5A, 0xD4, 0x6E, 0x36, 0x21, 0x65, 0xB5, 0x57, 0x04, + 0x69, 0xB6, 0x70, 0x34, 0xE6, 0x65, 0xA5, 0xC9, 0x12, 0x62, 0x02, 0xCB, 0x4B, 0x68, 0x5B, 0x90, + 0x0D, 0xA7, 0x80, 0x01, 0xA6, 0xE9, 0x8D, 0x39, 0xD0, 0x76, 0x1A, 0x6B, 0x44, 0x5A, 0x4A, 0xAB, + 0x3A, 0xD5, 0xD4, 0x91, 0xA3, 0x30, 0x9C, 0x8A, 0xA8, 0xF7, 0xA3, 0x83, 0x57, 0x6C, 0x43, 0xDD, + 0xCC, 0x47, 0x9D, 0x28, 0x7D, 0x95, 0xC6, 0x5B, 0xF6, 0x7C, 0x7D, 0xB1, 0x49, 0xC5, 0x3A, 0x55, + 0xCD, 0x2A, 0xAF, 0x5B, 0x62, 0x5A, 0xB1, 0x52, 0x73, 0xF3, 0xFA, 0x6C, 0xAC, 0x23, 0x6B, 0xC6, + 0xB3, 0xB0, 0x90, 0x19, 0x81, 0xD6, 0xB5, 0x92, 0x3F, 0x2D, 0xC6, 0x3F, 0x85, 0xC5, 0x60, 0xA3, + 0xCF, 0x7D, 0x0C, 0xAB, 0x21, 0xF9, 0x7D, 0x07, 0x30, 0x1D, 0xE2, 0x01, 0x44, 0x9A, 0x69, 0x55, + 0xDC, 0xD8, 0x41, 0x67, 0xAE, 0x7A, 0xE2, 0x4E, 0xC4, 0x78, 0x74, 0x20, 0x1D, 0xAA, 0x71, 0x76, + 0x3C, 0x76, 0xA2, 0xF2, 0xF1, 0x9A, 0x21, 0xEB, 0xC7, 0x77, 0x81, 0x1A, 0x23, 0x55, 0xB6, 0x38, + 0xB0, 0x94, 0x9F, 0xD8, 0xA4, 0x91, 0x05, 0x38, 0x4A, 0xDF, 0xF1, 0xD4, 0x9D, 0x30, 0x38, 0xFA, + 0x98, 0xD7, 0x1A, 0x33, 0xCB, 0x82, 0xF5, 0xC5, 0x12, 0x35, 0x31, 0x76, 0x52, 0x55, 0xB2, 0x97, + 0x32, 0xCE, 0x5D, 0x33, 0xF7, 0x4B, 0x62, 0xE5, 0x96, 0x9E, 0x17, 0x4E, 0x83, 0x51, 0x84, 0xC9, + 0x5E, 0x70, 0xCD, 0xD7, 0x5A, 0x45, 0x14, 0xFF, 0xC2, 0xD8, 0x67, 0x7D, 0x25, 0x4B, 0xF3, 0x4B, + 0x8A, 0x1E, 0x5F, 0x5D, 0xC5, 0x63, 0xD4, 0x3F, 0xD9, 0x8C, 0x9B, 0x5D, 0x47, 0x74, 0x83, 0x30, + 0x8F, 0xB2, 0x56, 0x24, 0xE8, 0x85, 0x4C, 0xC1, 0xD3, 0x86, 0xDA, 0x9D, 0xF8, 0x64, 0xB6, 0x73, + 0x13, 0xD0, 0x6B, 0x7C, 0xBE, 0x38, 0xAE, 0x16, 0xDF, 0xE7, 0x4C, 0x68, 0x2D, 0x2F, 0xEF, 0xE4, + 0xF5, 0x7E, 0xBC, 0x16, 0x92, 0x0E, 0x9D, 0xD2, 0xB1, 0x5F, 0xB7, 0x9F, 0xF2, 0xF2, 0xB5, 0xE2, + 0xA6, 0x51, 0x8A, 0x55, 0xC9, 0xD8, 0xEA, 0x65, 0xF2, 0xB5, 0xA6, 0x15, 0x31, 0x67, 0x6B, 0x3A, + 0xBE, 0xE2, 0xE5, 0x4A, 0xB2, 0x0C, 0x4C, 0xAF, 0x29, 0xEE, 0x94, 0x68, 0x38, 0x55, 0x33, 0x09, + 0xCF, 0x4B, 0xBF, 0x5F, 0xE4, 0x9D, 0x99, 0x67, 0xFA, 0x3D, 0xDE, 0xD4, 0x81, 0xFE, 0x66, 0x8C, + 0x85, 0xE2, 0xF0, 0x3C, 0x33, 0x05, 0xCB, 0x9A, 0xA5, 0xEF, 0xE0, 0xC9, 0x76, 0xD7, 0x80, 0xDC, + 0xF8, 0xE6, 0x6F, 0x75, 0xCD, 0xFC, 0x9E, 0x51, 0x48, 0xD6, 0x96, 0xD6, 0x4E, 0xE5, 0x99, 0xB6, + 0x70, 0xAA, 0x4D, 0x18, 0x29, 0x9F, 0x60, 0xA5, 0xB6, 0xAF, 0xAE, 0x9E, 0xD3, 0x6B, 0x98, 0x51, + 0x6F, 0x78, 0xBA, 0xEE, 0x24, 0xAC, 0xA8, 0x70, 0xB9, 0xA9, 0xEC, 0x9E, 0xEC, 0x68, 0x57, 0x48, + 0x79, 0xE6, 0x6C, 0x4D, 0xE3, 0xA5, 0x5C, 0xE0, 0xF8, 0x6B, 0x77, 0x2E, 0xE9, 0xBF, 0x39, 0xA6, + 0x86, 0x19, 0xBF, 0x39, 0xA3, 0x86, 0xAB, 0xD1, 0x30, 0xD7, 0x0F, 0x03, 0xCC, 0x46, 0xDF, 0x26, + 0xF1, 0xAF, 0x1F, 0x60, 0x7A, 0x1F, 0xD1, 0x40, 0x15, 0x2C, 0xC3, 0x92, 0x05, 0x67, 0x16, 0xA6, + 0x0D, 0xD6, 0x85, 0x27, 0xCE, 0xAE, 0x03, 0xCA, 0x0F, 0x23, 0xDA, 0xFC, 0x50, 0xA2, 0x0E, 0xA0, + 0x7D, 0xE5, 0x07, 0x11, 0x00, 0xB2, 0xFF, 0xE7, 0x03, 0xE6, 0x24, 0x39, 0x1F, 0x15, 0x27, 0x38, + 0x97, 0x5E, 0x89, 0xD0, 0xE4, 0x11, 0xA7, 0xA3, 0x4E, 0xBB, 0x79, 0x42, 0x83, 0x01, 0xBF, 0x1F, + 0xCB, 0xCB, 0x3A, 0x23, 0x96, 0xBA, 0x9A, 0xAC, 0x12, 0xFE, 0x67, 0xE4, 0x47, 0xB8, 0x0F, 0xF8, + 0x67, 0x3C, 0xDA, 0x97, 0xB2, 0x7A, 0x0B, 0xB4, 0x6F, 0xED, 0x40, 0x3A, 0xA4, 0x3B, 0xB1, 0xA3, + 0x9B, 0x4E, 0xE0, 0x4F, 0x81, 0x1B, 0x81, 0x76, 0x29, 0x05, 0x99, 0x4A, 0x79, 0xD1, 0x35, 0xC7, + 0xD8, 0x00, 0x87, 0x83, 0xEE, 0x7F, 0x0B, 0xD5, 0xA4, 0x0E, 0xCF, 0xB6, 0x9E, 0x6C, 0x09, 0x0B, + 0x96, 0xDF, 0xE0, 0xCB, 0x24, 0x56, 0xE6, 0x81, 0xA5, 0x7C, 0x3A, 0xAD, 0xB3, 0x34, 0x81, 0x7B, + 0x9B, 0xDC, 0xE1, 0x15, 0x2C, 0x6F, 0xC8, 0x15, 0x1D, 0xBC, 0x4F, 0xA6, 0xDD, 0xF7, 0xD0, 0x41, + 0xE3, 0x96, 0xE1, 0xD1, 0x5C, 0x4D, 0x3B, 0x54, 0x41, 0x96, 0xD1, 0xE5, 0x99, 0xD9, 0x49, 0x92, + 0x9A, 0xBD, 0x4C, 0x90, 0xF1, 0xC1, 0xD1, 0x3C, 0x86, 0x3A, 0xFB, 0x96, 0x98, 0x73, 0x4C, 0xAC, + 0xCE, 0x8F, 0x26, 0xDE, 0xDE, 0x1F, 0x39, 0x75, 0xB9, 0x96, 0xE4, 0x21, 0x6B, 0x7C, 0x23, 0x61, + 0xBC, 0xB3, 0x81, 0x49, 0x47, 0x45, 0x2A, 0x8F, 0x86, 0x46, 0x48, 0xF7, 0x10, 0x81, 0xC0, 0x9A, + 0xA2, 0x8D, 0x06, 0x22, 0xEB, 0xE6, 0x5B, 0x9C, 0x41, 0x15, 0xD7, 0x26, 0xBD, 0xE7, 0x7F, 0x31, + 0xA8, 0x94, 0x0D, 0x94, 0x9F, 0x90, 0x25, 0x18, 0xD5, 0x58, 0x54, 0xE3, 0x36, 0x20, 0x3F, 0xD2, + 0xCB, 0x81, 0x88, 0xDB, 0x96, 0x14, 0x63, 0x76, 0x45, 0xF9, 0x05, 0x9D, 0xED, 0xF5, 0x2D, 0xD3, + 0x4C, 0x0E, 0xF5, 0x79, 0xFA, 0xD4, 0x92, 0x26, 0x55, 0x49, 0xEB, 0x9A, 0x34, 0xC9, 0x94, 0x90, + 0xB5, 0xB8, 0x49, 0x79, 0x29, 0x5C, 0x87, 0x72, 0x71, 0xC5, 0x26, 0x4D, 0x9D, 0x49, 0x51, 0x63, + 0x3E, 0x39, 0x35, 0x1A, 0x33, 0x75, 0x72, 0xF2, 0x2E, 0x16, 0x34, 0x27, 0x17, 0x26, 0xD1, 0x3F, + 0xC7, 0xDC, 0xA0, 0xAE, 0xD5, 0xED, 0x5A, 0xA6, 0x16, 0x39, 0x37, 0x83, 0xC9, 0x21, 0x2C, 0x23, + 0x03, 0x8F, 0x46, 0xD9, 0x56, 0x89, 0x82, 0x83, 0x0F, 0xFB, 0x67, 0xC5, 0x4D, 0x92, 0x32, 0xAF, + 0x1F, 0x9D, 0xA9, 0x2C, 0xC6, 0xD8, 0x0B, 0x9B, 0x27, 0x65, 0x44, 0x2F, 0x87, 0x97, 0xF9, 0x87, + 0x02, 0xBC, 0xEC, 0xCD, 0xE2, 0x9C, 0x55, 0x6F, 0x58, 0x0B, 0x84, 0xC7, 0x6F, 0x77, 0xEE, 0xB5, + 0x7B, 0xCA, 0x01, 0x2A, 0x39, 0x90, 0xAE, 0xF3, 0x6F, 0xBB, 0x12, 0xCC, 0xD7, 0x05, 0xF2, 0xA7, + 0x3F, 0x91, 0xA4, 0xEC, 0x8F, 0xBB, 0xFD, 0xBE, 0xEE, 0x3C, 0x6B, 0xFE, 0x9E, 0x4C, 0x30, 0xCF, + 0xDD, 0x43, 0x61, 0xCB, 0xF5, 0xD0, 0xA3, 0x63, 0xDD, 0x96, 0x9C, 0x28, 0x12, 0x6B, 0x49, 0x8B, + 0x40, 0x80, 0xA6, 0xE1, 0xDA, 0x40, 0xF2, 0xB8, 0xE2, 0x43, 0x29, 0x56, 0xA6, 0x79, 0x4F, 0xAC, + 0xDF, 0x4E, 0xE9, 0x5D, 0x9C, 0x2A, 0x4A, 0xE9, 0x67, 0x3D, 0x6F, 0xCA, 0x1F, 0x92, 0xC4, 0xD4, + 0xD0, 0xD6, 0x45, 0x4D, 0xBC, 0x2C, 0x14, 0x40, 0x57, 0xE5, 0x93, 0x70, 0xC8, 0x03, 0x2B, 0x16, + 0xE2, 0x57, 0x3E, 0xF6, 0x05, 0x41, 0x28, 0xC1, 0x67, 0x64, 0x7E, 0x75, 0xDF, 0xB9, 0x6C, 0x62, + 0xC0, 0x8B, 0xDF, 0x74, 0x3C, 0x89, 0xEE, 0x65, 0xB5, 0x35, 0xB8, 0xCE, 0x22, 0xB7, 0xDE, 0xBE, + 0xC6, 0x77, 0x5E, 0x00, 0xA2, 0x60, 0x22, 0x97, 0x3E, 0xE8, 0x91, 0x87, 0xD7, 0x9A, 0x61, 0x22, + 0x85, 0x39, 0x54, 0x34, 0xA9, 0xA5, 0xBD, 0xC3, 0x84, 0xFA, 0x21, 0x1E, 0xDD, 0xC0, 0x1D, 0x1F, + 0xE9, 0xC4, 0x08, 0x96, 0xA3, 0xE0, 0xBC, 0x90, 0xC1, 0x34, 0x08, 0x70, 0x4A, 0x67, 0xAD, 0xC1, + 0x9E, 0x67, 0xDB, 0x33, 0x67, 0xBF, 0x86, 0xA9, 0xCA, 0x8D, 0x42, 0x31, 0x71, 0x35, 0xD3, 0xAE, + 0x02, 0x45, 0x92, 0x50, 0xE7, 0xE9, 0x91, 0xC4, 0xFC, 0xF2, 0xAE, 0x0C, 0x90, 0x2E, 0x11, 0xDA, + 0xB8, 0x7C, 0xD0, 0x4A, 0xE2, 0x80, 0x6A, 0x28, 0x54, 0xFA, 0x40, 0xB5, 0x6C, 0xE7, 0xFB, 0x52, + 0x27, 0xE8, 0x76, 0x20, 0x87, 0x85, 0x0C, 0x68, 0x1B, 0x6B, 0xC7, 0x64, 0xD0, 0x00, 0x54, 0x06, + 0x64, 0x3D, 0xD5, 0x8E, 0x3B, 0x44, 0xAB, 0xAD, 0xAB, 0x37, 0xBE, 0x83, 0x12, 0xDF, 0x5B, 0x91, + 0xF7, 0x68, 0xE2, 0x72, 0xB6, 0x81, 0x00, 0xF0, 0x62, 0x4F, 0x26, 0x41, 0xB6, 0x64, 0x7C, 0x62, + 0x45, 0x29, 0x4F, 0x6F, 0x73, 0x48, 0xF4, 0x8C, 0x8F, 0x5E, 0x65, 0x98, 0x32, 0x3D, 0x7D, 0xC5, + 0x2A, 0x01, 0x72, 0xD3, 0xD8, 0x54, 0x9E, 0x6E, 0xCA, 0x21, 0xB9, 0x94, 0xDD, 0x73, 0x68, 0xED, + 0x23, 0x1C, 0x53, 0x75, 0xC1, 0x16, 0xAA, 0x53, 0x0E, 0x7C, 0x72, 0x5F, 0xA4, 0x74, 0x04, 0x09, + 0x46, 0x93, 0xC7, 0x7E, 0x08, 0x4C, 0x31, 0x21, 0x0B, 0xBF, 0xD8, 0xD1, 0xCC, 0x71, 0x42, 0xE3, + 0x17, 0x5E, 0x63, 0xF1, 0x5A, 0xFD, 0x5B, 0x69, 0x5F, 0x2E, 0x4D, 0xE9, 0x01, 0x54, 0x0D, 0x9E, + 0x67, 0xCE, 0x3F, 0x3F, 0xFF, 0x78, 0xDE, 0xAA, 0x6D, 0x88, 0xC4, 0x48, 0x23, 0x20, 0x11, 0x3E, + 0x4B, 0xB2, 0xEC, 0x1E, 0xF6, 0x2D, 0xB8, 0x79, 0xFC, 0x10, 0x75, 0x47, 0x9B, 0xD0, 0x1C, 0xF7, + 0xF6, 0x3D, 0x8D, 0x14, 0x13, 0xA4, 0xCE, 0xB7, 0xA5, 0x56, 0x4A, 0xDB, 0x5D, 0x54, 0x8D, 0x9D, + 0xB2, 0xC1, 0x69, 0x6A, 0xE7, 0xFE, 0xA7, 0xF3, 0xF3, 0xC3, 0xD3, 0x0B, 0x53, 0x4B, 0x73, 0x1B, + 0x99, 0xA8, 0x39, 0x18, 0xDB, 0xE9, 0x04, 0x2D, 0x1E, 0x4F, 0x58, 0xF8, 0xC4, 0x6D, 0x93, 0x0D, + 0xB9, 0x4E, 0x47, 0xF7, 0x8B, 0x59, 0xBC, 0x1B, 0x30, 0x7A, 0xDB, 0x62, 0xB7, 0x41, 0x14, 0x39, + 0xEC, 0x14, 0x22, 0x32, 0x73, 0xA3, 0xBE, 0x63, 0x85, 0xD8, 0xCF, 0xF2, 0xD6, 0x30, 0x66, 0x55, + 0x54, 0x81, 0x24, 0x85, 0x14, 0x09, 0xD6, 0x4D, 0xA2, 0xD3, 0x0E, 0x77, 0xF4, 0x31, 0xFD, 0x7C, + 0x26, 0xDC, 0x1F, 0xDF, 0xFD, 0xC6, 0x59, 0xBC, 0x92, 0x41, 0xC8, 0x28, 0x7F, 0xB6, 0xA7, 0xA0, + 0xFD, 0xEF, 0xC5, 0xE3, 0x59, 0xB8, 0x59, 0x73, 0x2D, 0x35, 0xEF, 0xE7, 0x44, 0xAF, 0x4E, 0xF4, + 0x86, 0xC9, 0x54, 0xD5, 0xDC, 0xC7, 0x9E, 0x4A, 0x55, 0x6A, 0xC6, 0x89, 0x54, 0x63, 0xC8, 0x34, + 0x8D, 0x0E, 0x39, 0x5E, 0x79, 0xC4, 0x49, 0x81, 0x61, 0xF1, 0xCD, 0x0A, 0xB4, 0xA7, 0xDD, 0x56, + 0xEE, 0xEB, 0x88, 0x46, 0x56, 0x96, 0x8C, 0x96, 0x3A, 0xC6, 0x96, 0x9D, 0x85, 0x1E, 0x69, 0x68, + 0x95, 0x99, 0x7C, 0x66, 0x0D, 0x62, 0x31, 0xA8, 0x5A, 0xAF, 0x3C, 0x56, 0xAA, 0x2E, 0x9D, 0xFC, + 0xC8, 0x8E, 0xA9, 0x8B, 0xA7, 0x00, 0xC5, 0xAE, 0x55, 0xBC, 0x9B, 0x62, 0x74, 0x45, 0xF2, 0xE4, + 0x54, 0x7D, 0x78, 0x6A, 0x54, 0xF8, 0x36, 0x9A, 0xFE, 0x24, 0x60, 0x55, 0x13, 0xAE, 0x21, 0x93, + 0x36, 0xF7, 0x75, 0x32, 0xBB, 0x99, 0xAD, 0x38, 0xED, 0xE5, 0x51, 0x25, 0x9D, 0xC2, 0x7B, 0xF7, + 0x96, 0x7A, 0xC4, 0xC6, 0x27, 0x6C, 0x83, 0x85, 0x50, 0x64, 0x00, 0x43, 0x61, 0xDE, 0xE3, 0x44, + 0x05, 0xDD, 0xEC, 0x45, 0xEE, 0x35, 0xCF, 0xC3, 0x85, 0x71, 0x6F, 0xCC, 0x44, 0x88, 0x35, 0x18, + 0x7E, 0x4B, 0x43, 0x9A, 0x89, 0xEB, 0x91, 0x83, 0x83, 0x8E, 0x13, 0xFF, 0x63, 0x1B, 0xCE, 0xB6, + 0x14, 0xC6, 0x1D, 0xE3, 0x3A, 0x42, 0x5B, 0x81, 0xAF, 0x4E, 0x2D, 0x22, 0xCD, 0x43, 0x0F, 0x48, + 0xA9, 0xEB, 0xD9, 0x18, 0x63, 0x52, 0x11, 0x9A, 0xAF, 0xBE, 0x57, 0x15, 0x76, 0xF6, 0x3F, 0x7E, + 0x3C, 0x3F, 0x38, 0x3A, 0xDD, 0xBB, 0x38, 0xBC, 0x3C, 0x3A, 0x3D, 0xFB, 0x74, 0x71, 0x79, 0xF1, + 0xF9, 0x0C, 0x7F, 0xFD, 0x65, 0xEF, 0xF8, 0xE8, 0xE0, 0xF2, 0xD3, 0xE9, 0x5F, 0x4E, 0x3F, 0xFE, + 0x7A, 0x9A, 0x6E, 0x6A, 0x3B, 0x76, 0x78, 0x23, 0xDD, 0x18, 0x4F, 0xCC, 0x23, 0x86, 0x9C, 0x1B, + 0xBE, 0x3B, 0x74, 0xE0, 0x8E, 0xED, 0x91, 0xA1, 0x84, 0x9B, 0xAA, 0x8F, 0xD7, 0xC7, 0x94, 0xBD, + 0x43, 0xA9, 0x9F, 0xEE, 0x81, 0xF1, 0x00, 0x6F, 0x2B, 0xC2, 0xE7, 0xCE, 0x12, 0xB9, 0xF0, 0x57, + 0x85, 0xF0, 0x2E, 0x32, 0xAA, 0x17, 0xB9, 0xBB, 0xB1, 0xD9, 0x74, 0x35, 0x64, 0x82, 0x07, 0x19, + 0x4F, 0xC3, 0xC4, 0x2A, 0x0F, 0x6C, 0x8F, 0x50, 0x14, 0x08, 0x33, 0x99, 0xAE, 0x07, 0x9D, 0xEF, + 0x3A, 0xEC, 0x56, 0x79, 0x28, 0xAA, 0xEC, 0x11, 0xFE, 0x8D, 0xD7, 0xC2, 0x87, 0x5B, 0x59, 0x1E, + 0x38, 0x7E, 0x0E, 0x18, 0xB6, 0xC9, 0x4A, 0x1B, 0xE3, 0x4D, 0xDB, 0xAC, 0x9B, 0x3A, 0xEA, 0x59, + 0x97, 0x64, 0x7C, 0x13, 0xC1, 0xEB, 0xA6, 0x57, 0xBD, 0x46, 0x1B, 0x3A, 0xEE, 0xD0, 0x8D, 0xD2, + 0x6E, 0xC2, 0x43, 0xDC, 0xBC, 0x2B, 0x95, 0x08, 0xA0, 0x8A, 0x8D, 0x45, 0xD3, 0x1B, 0xE5, 0xB5, + 0xBC, 0x5C, 0xF4, 0xF2, 0x8A, 0x4C, 0x0E, 0xB1, 0x2C, 0xAC, 0x2C, 0x2C, 0xA5, 0x1D, 0xB8, 0xBC, + 0xCC, 0x5E, 0x83, 0x1A, 0x8D, 0xC8, 0xD0, 0xF7, 0x9D, 0x0A, 0xD0, 0x04, 0xA0, 0xD3, 0x7E, 0xAE, + 0x0D, 0xDE, 0x41, 0xE2, 0x52, 0xBB, 0x8A, 0x10, 0xC4, 0x7B, 0x13, 0x8D, 0x94, 0x55, 0x9C, 0x07, + 0xB3, 0x25, 0x0D, 0xA8, 0x11, 0x46, 0xBA, 0x84, 0x8A, 0x0A, 0xB0, 0xC4, 0x02, 0xEA, 0xE1, 0x13, + 0x78, 0xF7, 0xA8, 0x44, 0x13, 0x3F, 0x0C, 0x5D, 0x8C, 0x87, 0xE5, 0x5A, 0x81, 0xE3, 0x34, 0xD6, + 0x97, 0x74, 0x48, 0xA6, 0x1F, 0x4E, 0x4E, 0x3A, 0x63, 0xFE, 0x2F, 0xFD, 0x46, 0x4C, 0x1F, 0x57, + 0x4C, 0x1F, 0x4F, 0x4E, 0xFA, 0xFD, 0x4E, 0xC8, 0xFE, 0x29, 0xE0, 0xC4, 0xF0, 0x19, 0x10, 0xAC, + 0xA4, 0x9F, 0x5F, 0x18, 0xF5, 0x84, 0xDD, 0xE2, 0x9A, 0x5D, 0x72, 0xFF, 0x17, 0x83, 0x84, 0x3D, + 0xBF, 0x43, 0xD6, 0x61, 0xB4, 0x6D, 0x5B, 0x6B, 0x6B, 0xEB, 0x2F, 0x59, 0xFE, 0x3D, 0x26, 0xBF, + 0x4E, 0x1A, 0xA1, 0x9C, 0x8E, 0xF8, 0x37, 0xA4, 0x37, 0x0F, 0xC2, 0x1F, 0x71, 0xFC, 0x59, 0x2C, + 0x27, 0x04, 0x8C, 0xB4, 0x1E, 0xB1, 0x47, 0x98, 0x95, 0xD0, 0x41, 0x46, 0x88, 0xB5, 0x41, 0x7A, + 0x1B, 0x9D, 0x9E, 0xB5, 0xBE, 0x6D, 0x60, 0x25, 0xB5, 0x49, 0x6F, 0xC8, 0xDA, 0x9C, 0x39, 0xE9, + 0x31, 0x66, 0xD6, 0x52, 0x66, 0x56, 0xBA, 0xD6, 0xC6, 0x4A, 0xB7, 0xBB, 0x62, 0x6D, 0x74, 0xBA, + 0x9B, 0x3D, 0x13, 0x3B, 0x66, 0xCB, 0xF6, 0x06, 0x83, 0xFC, 0xE7, 0xC4, 0xDA, 0x4B, 0xE4, 0xE9, + 0x9A, 0xDE, 0xD1, 0x80, 0xF3, 0xD3, 0xED, 0x22, 0x37, 0x5B, 0x5B, 0xDB, 0xDB, 0x3D, 0xB2, 0x78, + 0xC0, 0x35, 0x0B, 0xAB, 0xF0, 0xDF, 0x96, 0x12, 0x1E, 0x53, 0x77, 0xD6, 0xA3, 0x43, 0x3B, 0x02, + 0xBB, 0xD9, 0x77, 0x87, 0x9E, 0xEA, 0x3D, 0xA8, 0x63, 0xD7, 0x4A, 0x0D, 0x47, 0x6A, 0xA5, 0x92, + 0x62, 0xEE, 0x77, 0x61, 0x60, 0xFD, 0x9E, 0x64, 0xDC, 0xDA, 0x28, 0x3A, 0x8C, 0x7D, 0x67, 0x27, + 0x3D, 0x18, 0x7D, 0x0F, 0xC6, 0x8B, 0x89, 0x82, 0x9B, 0x8F, 0xF4, 0xAE, 0x8D, 0xCA, 0x84, 0x1A, + 0xD8, 0x93, 0x74, 0xEA, 0xCA, 0x0A, 0x22, 0xC2, 0x44, 0x9A, 0x69, 0x3F, 0x83, 0xB5, 0xC6, 0x39, + 0xD3, 0xF5, 0xF8, 0xA3, 0x29, 0xAC, 0x84, 0x72, 0x0B, 0xCE, 0xF3, 0x6F, 0xB2, 0xD4, 0x14, 0x82, + 0x68, 0x4C, 0x86, 0x84, 0x40, 0x47, 0xDF, 0xB0, 0x92, 0xF5, 0x98, 0x1B, 0x5A, 0x5C, 0x53, 0x49, + 0xB3, 0x5C, 0xF2, 0x2D, 0xA7, 0x5F, 0x77, 0xD9, 0xED, 0x0D, 0x7C, 0x64, 0x31, 0xB7, 0x7C, 0x73, + 0x09, 0x16, 0x64, 0xAB, 0xAB, 0xD9, 0x11, 0x2F, 0x3F, 0x84, 0xDD, 0x7C, 0xAE, 0xE6, 0x78, 0xA5, + 0x53, 0x79, 0x9E, 0x86, 0x83, 0x1D, 0xBA, 0xF0, 0x6B, 0x3C, 0xEC, 0x28, 0x12, 0xC4, 0xEB, 0x0D, + 0xE2, 0xDB, 0xD1, 0xA9, 0xC3, 0xC0, 0xBA, 0x09, 0x9C, 0x4F, 0x22, 0xF4, 0x46, 0xC1, 0x22, 0xEC, + 0x8B, 0x8A, 0x42, 0x42, 0xCD, 0xEF, 0x46, 0x5B, 0x32, 0x8E, 0x74, 0xE2, 0x4B, 0xAB, 0xAD, 0xEC, + 0x26, 0xA6, 0x8A, 0x9F, 0xB9, 0x2A, 0xF7, 0xA9, 0x59, 0x2A, 0x5F, 0x9E, 0x3E, 0xBE, 0x98, 0x50, + 0x42, 0xE6, 0xE4, 0x44, 0x8E, 0x8B, 0x7B, 0xE7, 0xC2, 0x14, 0x0D, 0xD3, 0x8B, 0x32, 0xE5, 0xA6, + 0x13, 0x33, 0xBB, 0x5C, 0xF4, 0xF1, 0x7A, 0x91, 0x4D, 0x40, 0xD0, 0x1B, 0x2B, 0x5D, 0x7D, 0x6F, + 0x7C, 0x56, 0xD1, 0x5F, 0x9E, 0x7E, 0xBC, 0x3C, 0x38, 0xDC, 0x3F, 0x3A, 0xD9, 0x3B, 0xD6, 0x7A, + 0x21, 0xA4, 0x30, 0x01, 0x39, 0xD8, 0xAC, 0x84, 0x1F, 0x4D, 0xDC, 0xB2, 0x3A, 0xF0, 0xC5, 0x15, + 0x87, 0x30, 0x8A, 0x2C, 0x1D, 0x50, 0xB2, 0xA0, 0x65, 0x90, 0x58, 0x8E, 0x7F, 0x4E, 0xE4, 0x25, + 0x00, 0x40, 0x64, 0x52, 0x18, 0x9A, 0xC1, 0xB5, 0x8A, 0x89, 0x2D, 0xA7, 0x48, 0x56, 0xC9, 0x26, + 0x4C, 0x01, 0xEC, 0x52, 0x7D, 0x4C, 0x63, 0x95, 0xAC, 0x6D, 0x62, 0x36, 0x99, 0x25, 0xED, 0x56, + 0xB8, 0x32, 0x92, 0xCD, 0x7E, 0x8D, 0x89, 0xEC, 0x9F, 0xB1, 0x3B, 0xE4, 0x97, 0x22, 0x1F, 0x4C, + 0xAB, 0x27, 0x6D, 0x88, 0xE2, 0x68, 0x54, 0x07, 0x28, 0x1B, 0x9F, 0xB9, 0xC3, 0x6F, 0x03, 0x47, + 0x67, 0x6E, 0xE9, 0x7A, 0x32, 0x36, 0x95, 0x19, 0x7A, 0x7E, 0x43, 0xB3, 0xE2, 0xC0, 0x4C, 0x47, + 0xA4, 0xA2, 0x21, 0x39, 0xC3, 0x51, 0x1F, 0x1A, 0x75, 0x07, 0x60, 0xEE, 0xF0, 0x33, 0xEB, 0xA9, + 0x22, 0x1A, 0x16, 0xE9, 0x2B, 0x00, 0x0C, 0x88, 0xCD, 0x4A, 0x5A, 0x57, 0xE9, 0x1E, 0x59, 0xBF, + 0x54, 0x05, 0x53, 0xB4, 0xA9, 0xCB, 0xF5, 0x61, 0xE5, 0x91, 0x14, 0xE2, 0xF2, 0xE4, 0xE4, 0xF2, + 0x60, 0xAF, 0xFF, 0x41, 0x53, 0x0B, 0x11, 0x6F, 0x94, 0x9A, 0x2D, 0x71, 0x9B, 0x6C, 0x45, 0xBF, + 0x6D, 0x98, 0xEA, 0x80, 0x30, 0xE5, 0x08, 0x89, 0xF9, 0x8B, 0xD2, 0x0E, 0xCB, 0xE9, 0x5A, 0xB9, + 0x7E, 0xF7, 0xAB, 0x64, 0x4C, 0x33, 0xBD, 0xFB, 0xCC, 0x3A, 0x2B, 0xBF, 0xAF, 0x7A, 0x49, 0x5F, + 0xC5, 0xDE, 0xF1, 0xDC, 0xFB, 0x0A, 0xCC, 0xFB, 0x33, 0xEB, 0xAE, 0x67, 0x33, 0xF7, 0x49, 0xE2, + 0xA9, 0x32, 0x05, 0xCA, 0x0D, 0xEA, 0xA5, 0x0D, 0xCA, 0xCE, 0x81, 0xFF, 0xE8, 0x13, 0x14, 0x57, + 0xCA, 0x74, 0x03, 0x67, 0xAE, 0x3A, 0xB9, 0x53, 0x22, 0xA6, 0xD4, 0x80, 0xFF, 0x30, 0x01, 0x08, + 0x0B, 0x4A, 0x1E, 0xCF, 0x82, 0x56, 0x1C, 0x8D, 0xE4, 0xA7, 0xF1, 0x2C, 0xEA, 0xA7, 0x5E, 0xD2, + 0x4F, 0xE4, 0x71, 0xD6, 0x25, 0xDC, 0x40, 0x3C, 0xA3, 0xCE, 0x7A, 0x6E, 0xA6, 0xF3, 0x7F, 0x9A, + 0xD5, 0x14, 0x1B, 0x5A, 0xCA, 0xC9, 0x90, 0x01, 0x01, 0x3F, 0x1C, 0x32, 0x14, 0x24, 0xD9, 0xB5, + 0xB6, 0x97, 0xB4, 0xAB, 0xF5, 0x86, 0xEE, 0xE0, 0x67, 0x3E, 0xE9, 0xC6, 0xBC, 0xB4, 0xC3, 0x8E, + 0x9B, 0xBA, 0xE9, 0x15, 0xF4, 0x36, 0xF1, 0xA7, 0x11, 0xFE, 0x61, 0x8B, 0x5D, 0x7B, 0x00, 0xEA, + 0xFB, 0xEA, 0x1E, 0x3C, 0x6E, 0x28, 0x5F, 0x81, 0xB4, 0xC6, 0x94, 0x2C, 0x68, 0x43, 0x66, 0xA1, + 0x4D, 0x68, 0x34, 0x90, 0x83, 0x6A, 0x19, 0xDF, 0x8C, 0x0F, 0x89, 0xAF, 0xB6, 0x49, 0x65, 0xCC, + 0xFB, 0xF5, 0x62, 0xF3, 0x52, 0x3A, 0x68, 0xE4, 0x77, 0x0F, 0x0C, 0x1A, 0x57, 0x5D, 0xE5, 0x96, + 0x8C, 0xC3, 0x3A, 0xD5, 0xB0, 0xF4, 0xDB, 0x92, 0x24, 0x66, 0xFD, 0xB4, 0x56, 0x66, 0xC3, 0x7C, + 0xD6, 0x35, 0x23, 0x9B, 0x97, 0xD2, 0x9A, 0x07, 0xD6, 0x6D, 0x33, 0x62, 0x9B, 0x2B, 0xB2, 0xD8, + 0x75, 0x9F, 0x33, 0xCA, 0xFE, 0xE7, 0x93, 0xB7, 0x1F, 0x8F, 0x19, 0x52, 0xFD, 0x52, 0xC7, 0xC8, + 0xF7, 0x86, 0x2C, 0x8F, 0xD1, 0x01, 0x1D, 0x06, 0x54, 0xDF, 0x1F, 0xC9, 0xF4, 0x84, 0xD6, 0xB5, + 0xB0, 0x38, 0xD3, 0x11, 0x18, 0xEB, 0xC1, 0x70, 0xDD, 0xB4, 0x76, 0xB4, 0xDC, 0x90, 0x49, 0xE9, + 0x6B, 0x92, 0x6B, 0xF9, 0xF8, 0x40, 0x97, 0x4C, 0x97, 0xA2, 0x57, 0x83, 0xEC, 0xB0, 0x7D, 0xB9, + 0x94, 0xC9, 0x41, 0x39, 0x63, 0xF7, 0xE6, 0xB1, 0x96, 0x0C, 0xA1, 0x8C, 0x08, 0x97, 0x61, 0x54, + 0x31, 0xEB, 0x12, 0x57, 0xDD, 0xC9, 0x1E, 0x5E, 0xCC, 0x49, 0x51, 0x1A, 0x31, 0xB7, 0xF2, 0x14, + 0xDC, 0x71, 0x9D, 0x6B, 0xC4, 0xDF, 0x7F, 0xFF, 0x97, 0xCA, 0x20, 0x7E, 0x5B, 0x68, 0xA9, 0x6C, + 0x36, 0xC1, 0x4B, 0x4C, 0xED, 0xD6, 0x6C, 0xCB, 0x5C, 0x9A, 0xDE, 0x5F, 0x92, 0x07, 0xF0, 0xEC, + 0x2A, 0x38, 0x67, 0x84, 0xD2, 0xAA, 0xEA, 0x31, 0xF0, 0xEA, 0x3D, 0x3F, 0x27, 0x11, 0x48, 0xAE, + 0xCC, 0x63, 0x70, 0xFD, 0xB8, 0xD8, 0xB5, 0x15, 0xEC, 0xD2, 0x3F, 0xBA, 0x19, 0x56, 0x78, 0x3E, + 0x31, 0x6D, 0xAD, 0xD7, 0xE1, 0x59, 0x20, 0x28, 0xE2, 0xB9, 0xF2, 0x04, 0xB0, 0x39, 0xF7, 0x09, + 0x40, 0x1E, 0x7D, 0x35, 0xA7, 0x80, 0x8C, 0x88, 0x9E, 0x68, 0x6A, 0xC8, 0x8C, 0xEE, 0xBA, 0xB3, + 0x83, 0x89, 0xF1, 0x95, 0x27, 0xE2, 0x7C, 0xE6, 0x99, 0xC3, 0xC4, 0xFC, 0x42, 0x76, 0x4A, 0xF9, + 0xD7, 0x56, 0xEB, 0xB1, 0xDA, 0xB0, 0xD4, 0x78, 0x7A, 0x32, 0xF1, 0x4E, 0x1E, 0x5B, 0xF0, 0xB9, + 0xE6, 0x75, 0x4E, 0xEA, 0x2E, 0x5D, 0x54, 0x34, 0x9A, 0x85, 0x39, 0x2B, 0xD0, 0x8C, 0x2D, 0x29, + 0xEE, 0x87, 0x27, 0x6E, 0x8B, 0x3E, 0x71, 0xCC, 0x7F, 0x44, 0x17, 0x35, 0x28, 0x73, 0x91, 0x47, + 0xA5, 0xA7, 0xC5, 0x3C, 0xC6, 0x41, 0x48, 0x03, 0x7C, 0x54, 0x51, 0xC0, 0xAC, 0xFE, 0xAB, 0xB3, + 0xDA, 0x89, 0xF0, 0x4A, 0xF2, 0x60, 0x69, 0x87, 0xA8, 0x29, 0x13, 0xE2, 0x73, 0x7D, 0x58, 0x12, + 0xB7, 0x79, 0x86, 0x46, 0x58, 0xC1, 0xDE, 0x04, 0x72, 0x90, 0x24, 0x4F, 0x2F, 0xF9, 0x06, 0x57, + 0xCD, 0xF1, 0xD5, 0xA3, 0x15, 0x29, 0x08, 0x05, 0x3E, 0x2B, 0x8B, 0x74, 0xAC, 0xA6, 0x24, 0x46, + 0x14, 0xC9, 0x27, 0x97, 0x11, 0x2F, 0x46, 0x83, 0x2A, 0xE5, 0x1C, 0xF9, 0x32, 0x4B, 0x23, 0x2F, + 0xAF, 0xE3, 0x3D, 0x65, 0xE5, 0x2E, 0x50, 0xDB, 0xF8, 0xA6, 0xA5, 0xC7, 0x73, 0xD9, 0x89, 0x35, + 0xBC, 0x74, 0x5B, 0x58, 0x94, 0xA4, 0xF1, 0x72, 0x05, 0x2B, 0xF1, 0xF0, 0xCE, 0x8D, 0x06, 0x37, + 0xA4, 0xA8, 0x0A, 0x0B, 0x4F, 0xA0, 0xD7, 0xF6, 0x74, 0x14, 0xBD, 0xD2, 0xB2, 0xE1, 0xF3, 0x9E, + 0x68, 0x7D, 0xF2, 0xBE, 0x79, 0xFE, 0x9D, 0xA7, 0xA7, 0x94, 0xD5, 0x5E, 0x5E, 0x18, 0xE0, 0xB5, + 0xDD, 0xC5, 0xCA, 0xEB, 0xF7, 0x1C, 0x5A, 0xF2, 0x36, 0xC5, 0x5C, 0x09, 0xC2, 0xE2, 0x2A, 0x97, + 0x64, 0xBA, 0xEF, 0x39, 0x57, 0x92, 0x97, 0x45, 0x34, 0xC9, 0xE3, 0x11, 0xE5, 0xF3, 0x71, 0x2E, + 0xE5, 0x95, 0x47, 0xA2, 0xCC, 0xBC, 0x97, 0x02, 0x19, 0x27, 0x5B, 0x4C, 0x73, 0x6F, 0x6F, 0x11, + 0x5D, 0x65, 0x73, 0xEB, 0x11, 0x28, 0x97, 0x0B, 0x7B, 0xE5, 0x71, 0xC8, 0xEB, 0x13, 0x69, 0xA1, + 0xE4, 0x1F, 0xA3, 0xE1, 0x55, 0x68, 0x73, 0xE9, 0x3F, 0x96, 0xD8, 0x2B, 0xB1, 0xC0, 0x7B, 0xA0, + 0x80, 0x85, 0x87, 0x17, 0x79, 0xD6, 0xEE, 0xE1, 0xFF, 0x03, 0xDF, 0x1B, 0x82, 0xF1, 0x9B, 0x9A, + 0x00 }; ///main_js //To convert AP-Config\index.html to index_html[], run the Python index_html_zipper.py script in the Tools folder: @@ -1037,1078 +1048,1090 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xB7, 0x72, 0x78, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0x35, 0x44, 0x85, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, - 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x07, 0x49, 0x96, 0xF5, - 0x6C, 0x9D, 0x43, 0x4D, 0xB6, 0xFA, 0x49, 0x36, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, - 0x01, 0x49, 0x12, 0x4F, 0x20, 0x80, 0x8B, 0x41, 0xB2, 0x6E, 0x9D, 0xAA, 0x53, 0xCB, 0xE8, 0x5E, - 0x48, 0x6F, 0xA0, 0x97, 0x52, 0x2B, 0xE9, 0x88, 0xC8, 0x04, 0x08, 0x80, 0x00, 0x01, 0x90, 0x20, - 0x45, 0xCA, 0xF4, 0x7B, 0x57, 0x12, 0x41, 0xE4, 0x14, 0x19, 0x11, 0x19, 0x11, 0x19, 0xC3, 0x87, - 0x7F, 0x38, 0xFF, 0x7A, 0x76, 0xF7, 0x6B, 0xEF, 0x82, 0x8D, 0xBC, 0xB1, 0x71, 0xF2, 0xD3, 0x07, - 0xFC, 0xC5, 0x0C, 0xC5, 0x1C, 0x7E, 0xAC, 0x71, 0xB3, 0x76, 0xF2, 0x13, 0x3C, 0xE1, 0x8A, 0x76, - 0xF2, 0x13, 0x83, 0x7F, 0x1F, 0xC6, 0xDC, 0x53, 0x98, 0x3A, 0x52, 0x1C, 0x97, 0x7B, 0x1F, 0x6B, - 0xBE, 0x37, 0xA8, 0x1F, 0xD5, 0xD8, 0x5E, 0xF4, 0xCB, 0x91, 0xE7, 0xD9, 0x75, 0xFE, 0x87, 0xAF, - 0x3F, 0x7E, 0xAC, 0xFD, 0x52, 0xFF, 0xD6, 0xAD, 0x9F, 0x59, 0x63, 0x5B, 0xF1, 0xF4, 0x7B, 0x83, - 0xD7, 0x98, 0x6A, 0x99, 0x1E, 0x37, 0xA1, 0xE5, 0xD5, 0xC5, 0x47, 0xAE, 0x0D, 0xF9, 0xAE, 0x3A, - 0x72, 0xAC, 0x31, 0xFF, 0xD8, 0x9A, 0x74, 0xE2, 0xE9, 0x9E, 0xC1, 0x4F, 0xFA, 0xB6, 0xE2, 0x3C, - 0x5C, 0xFA, 0x26, 0xBB, 0xBD, 0xFB, 0x2B, 0xEB, 0x73, 0xCF, 0xB7, 0x3F, 0xEC, 0x89, 0x6F, 0x22, - 0x43, 0x99, 0x0A, 0x34, 0xAD, 0x3D, 0xEA, 0xFC, 0xC9, 0xB6, 0x1C, 0xAF, 0x46, 0xDF, 0xE0, 0xBF, - 0x70, 0x94, 0x27, 0x5D, 0xF3, 0x46, 0x1F, 0x35, 0xFE, 0xA8, 0xAB, 0xBC, 0x4E, 0x1F, 0x76, 0x99, - 0x6E, 0xEA, 0x9E, 0xAE, 0x18, 0x75, 0x57, 0x55, 0x0C, 0x18, 0x78, 0x97, 0x8D, 0x95, 0xEF, 0xFA, - 0xD8, 0x1F, 0x4F, 0x1E, 0xF8, 0x2E, 0x77, 0xE8, 0x93, 0x02, 0x73, 0xFE, 0xD8, 0xDC, 0x65, 0xEE, - 0xC8, 0xD1, 0xCD, 0x87, 0xBA, 0x67, 0xD5, 0x07, 0xBA, 0xF7, 0xF1, 0x99, 0xBB, 0x93, 0xD9, 0x1A, - 0xF0, 0x05, 0x73, 0xB8, 0xF1, 0xB1, 0xE6, 0x7A, 0xCF, 0x06, 0x77, 0x47, 0x9C, 0x7B, 0x35, 0x36, - 0x72, 0xF8, 0x00, 0x9E, 0x38, 0xEA, 0xDE, 0xBD, 0x65, 0x79, 0xAE, 0xE7, 0x28, 0x76, 0x63, 0xAC, - 0x9B, 0x0D, 0xD5, 0x75, 0x6B, 0x05, 0x1B, 0xD2, 0xD3, 0x68, 0x03, 0x57, 0x75, 0x74, 0xDB, 0x63, - 0xF0, 0x9D, 0x78, 0xE1, 0xEF, 0x7F, 0xF8, 0xDC, 0x79, 0xAE, 0x77, 0x1A, 0x87, 0x8D, 0x26, 0x75, - 0xFE, 0x77, 0x78, 0xF5, 0xC3, 0x9E, 0x78, 0x2D, 0xA3, 0x4D, 0x7C, 0x36, 0xA5, 0x1A, 0xDC, 0xFB, - 0xA6, 0x06, 0x13, 0x9A, 0x6E, 0x17, 0x6D, 0x78, 0x12, 0x6E, 0xC1, 0x7F, 0xD9, 0xD1, 0x2C, 0xD5, - 0x1F, 0xC3, 0x2E, 0xBC, 0x6D, 0x58, 0xE6, 0xCE, 0x1B, 0xD5, 0xD0, 0xD5, 0x87, 0x37, 0xBB, 0xEC, - 0x4D, 0xC3, 0xB3, 0x86, 0x43, 0x83, 0xD7, 0xEF, 0x3D, 0x13, 0x3E, 0x0E, 0x7C, 0x53, 0xF5, 0x74, - 0xCB, 0x64, 0x3B, 0xFC, 0x2D, 0xFB, 0xD7, 0xB0, 0xB5, 0xE8, 0x01, 0x96, 0xEF, 0x3B, 0x0E, 0x74, - 0x71, 0xA7, 0x38, 0x43, 0xEE, 0x35, 0xD4, 0x91, 0x6E, 0x68, 0xF0, 0xF9, 0x7F, 0x34, 0xFF, 0xE7, - 0x5B, 0xD9, 0xCD, 0x99, 0xA1, 0xB8, 0xEE, 0xCE, 0x1B, 0x1D, 0x76, 0xBC, 0xAE, 0x2A, 0x0E, 0xF7, - 0xEA, 0x9A, 0xF5, 0x64, 0xB2, 0xC8, 0x67, 0xDF, 0x7E, 0xF3, 0xF6, 0x2F, 0x61, 0xC7, 0xFF, 0xF6, - 0x56, 0x4C, 0x37, 0x39, 0x7B, 0x04, 0xF6, 0x64, 0xF2, 0x0D, 0xD7, 0x03, 0x84, 0x55, 0xEB, 0x43, - 0xC7, 0xF2, 0xED, 0xC4, 0xB4, 0x46, 0x5C, 0x1F, 0x8E, 0xBC, 0x63, 0xD6, 0xFC, 0x4B, 0xEC, 0xB1, - 0xF5, 0xC8, 0x9D, 0x81, 0x61, 0x3D, 0x1D, 0xB3, 0x91, 0xAE, 0x69, 0xDC, 0x8C, 0x7F, 0x0B, 0x10, - 0x34, 0x5D, 0x1D, 0x17, 0x7A, 0x2C, 0x3B, 0x60, 0xCD, 0xC6, 0xBE, 0xCB, 0xB8, 0xE2, 0xF2, 0xF8, - 0x9B, 0xF7, 0x96, 0xA3, 0x01, 0xF6, 0xDD, 0x5B, 0x9E, 0x67, 0x8D, 0x8F, 0x99, 0x6B, 0x19, 0xBA, - 0xC6, 0x5A, 0xF6, 0x77, 0xF6, 0x8F, 0x6A, 0x13, 0xFF, 0x17, 0x59, 0xCA, 0x4F, 0x93, 0xF9, 0x1A, - 0xBA, 0xEB, 0xAD, 0xF7, 0x6C, 0xF1, 0x9F, 0xAD, 0x68, 0x9A, 0x6E, 0x0E, 0xEB, 0x8E, 0x98, 0xD3, - 0x41, 0xD3, 0xFE, 0x9E, 0xBE, 0x1C, 0xD1, 0x2D, 0x10, 0x85, 0xCB, 0x3C, 0x6D, 0x37, 0xFD, 0xF9, - 0x28, 0xB1, 0x52, 0xF1, 0xDD, 0x31, 0x33, 0x2D, 0x33, 0x31, 0xC9, 0x31, 0x60, 0x8F, 0x6E, 0xD6, - 0x0D, 0x3E, 0x40, 0x40, 0x64, 0x8C, 0x79, 0xEF, 0xC3, 0x12, 0xCC, 0xE3, 0x01, 0x20, 0xAD, 0x9B, - 0xE8, 0xD9, 0xF2, 0x3D, 0x20, 0x56, 0x1E, 0x03, 0x62, 0x74, 0xB6, 0xBA, 0x89, 0x5F, 0x5F, 0x38, - 0x8E, 0xE5, 0x24, 0x5A, 0x6A, 0xBA, 0x6B, 0x1B, 0xCA, 0xF3, 0x31, 0x13, 0xAF, 0xC4, 0xA7, 0xA5, - 0x5A, 0x86, 0x05, 0xF3, 0x75, 0xB8, 0x16, 0x7F, 0x3E, 0x00, 0xE6, 0x55, 0x77, 0xF5, 0x3F, 0x61, - 0x40, 0x77, 0xAC, 0x18, 0x06, 0x77, 0x66, 0x0D, 0xDB, 0xF7, 0x55, 0x15, 0xE1, 0x51, 0x7E, 0xE0, - 0xA1, 0xC3, 0x93, 0x1B, 0x3F, 0x6B, 0xE8, 0xF0, 0xFB, 0x27, 0x89, 0x52, 0xF7, 0x96, 0xA1, 0x65, - 0x6D, 0xDF, 0xF7, 0x3A, 0xB5, 0x4F, 0xCC, 0x2A, 0x7B, 0x23, 0xF0, 0x1F, 0xB1, 0xE7, 0x63, 0xD6, - 0x69, 0xFE, 0xD7, 0xEC, 0x5E, 0x45, 0x0F, 0xED, 0xE6, 0xAC, 0x8E, 0xDB, 0x33, 0xD0, 0x2A, 0xE8, - 0x61, 0x7F, 0x66, 0x0F, 0xFB, 0xD9, 0x3D, 0x28, 0x9E, 0x07, 0x4C, 0x37, 0xD1, 0xD8, 0xB6, 0x02, - 0x6A, 0x51, 0xEE, 0x81, 0x04, 0x7C, 0x2F, 0x01, 0xF0, 0x3F, 0xEB, 0xBA, 0xA9, 0xF1, 0xEF, 0xC7, - 0xAC, 0xD5, 0x6C, 0x26, 0x48, 0x42, 0x92, 0x42, 0x6B, 0x0A, 0x1A, 0x70, 0x28, 0xD5, 0x25, 0x44, - 0x0E, 0x9B, 0x29, 0xDF, 0xD2, 0x74, 0x3D, 0xCB, 0x06, 0x32, 0x8A, 0x4F, 0x56, 0xB2, 0x37, 0xC1, - 0xD0, 0x3E, 0xEC, 0x89, 0xA3, 0xFB, 0xA7, 0x0F, 0xF7, 0x96, 0xF6, 0x2C, 0x79, 0xBC, 0xA6, 0x3F, - 0x32, 0x15, 0xF9, 0xE6, 0xC7, 0x1A, 0x1E, 0x94, 0x0A, 0x20, 0x88, 0x53, 0x63, 0xBA, 0xF6, 0xB1, - 0x26, 0x97, 0x77, 0x05, 0x8F, 0x6B, 0x13, 0x6E, 0x48, 0x0D, 0x14, 0x43, 0x1F, 0x9A, 0x1F, 0x6B, - 0x34, 0xDF, 0x5A, 0xD0, 0x5C, 0xBE, 0x1F, 0x79, 0x97, 0xDE, 0xD7, 0xC7, 0xC3, 0x64, 0x77, 0x97, - 0xBA, 0xC1, 0xBF, 0xC0, 0x69, 0x5D, 0x9B, 0x1C, 0x2D, 0xA7, 0xE2, 0xDB, 0x53, 0x90, 0x34, 0x1E, - 0x1A, 0xB6, 0x39, 0xAC, 0xC1, 0x18, 0x70, 0x64, 0xCB, 0xC7, 0xCC, 0xE0, 0x8F, 0xDC, 0xA8, 0x9D, - 0x00, 0x6F, 0xB6, 0x15, 0x33, 0xDA, 0x5D, 0x8F, 0x3B, 0x2A, 0x9C, 0x09, 0xB5, 0xD8, 0x98, 0x84, - 0xD7, 0x62, 0x52, 0x84, 0x79, 0x30, 0x0E, 0x42, 0xE0, 0x63, 0x2D, 0xA0, 0x04, 0x49, 0x08, 0x74, - 0x70, 0x41, 0x87, 0x91, 0xD5, 0xED, 0xC1, 0xF2, 0x24, 0x64, 0xC4, 0x9F, 0xB3, 0xA0, 0x94, 0xE8, - 0x95, 0x98, 0x4D, 0x74, 0x37, 0x08, 0xF9, 0x26, 0x7B, 0x27, 0xB6, 0x4E, 0x00, 0xD7, 0xE1, 0x20, - 0x32, 0x5D, 0x99, 0x3D, 0xC7, 0x42, 0x82, 0x8D, 0xC2, 0xF7, 0xFE, 0xE4, 0x16, 0xBF, 0xF3, 0x80, - 0x37, 0x7E, 0xD8, 0xBB, 0x3F, 0xF9, 0x70, 0xEF, 0xD0, 0x7F, 0x28, 0xF9, 0x08, 0xD1, 0x85, 0xE9, - 0x2E, 0xF0, 0x09, 0x3C, 0x8B, 0xE1, 0x95, 0x06, 0xEB, 0x19, 0xC8, 0x89, 0xD9, 0x93, 0xA2, 0x7B, - 0x8D, 0x46, 0x63, 0x55, 0x53, 0x47, 0x31, 0xCE, 0xE0, 0x1E, 0x4F, 0x99, 0x39, 0x3B, 0x87, 0xCE, - 0x32, 0xA6, 0x3E, 0x52, 0x5C, 0xE0, 0xC9, 0x4F, 0x8C, 0xFA, 0x58, 0xC5, 0x64, 0x07, 0xBA, 0x33, - 0x7E, 0x82, 0xA3, 0xFF, 0x9B, 0x6D, 0x58, 0x8A, 0x96, 0x3E, 0xEB, 0xE4, 0x7C, 0x2F, 0x65, 0x1B, - 0xE6, 0xDB, 0x9A, 0xE2, 0x71, 0x60, 0x91, 0xA2, 0x55, 0x83, 0xC5, 0x37, 0x41, 0x2C, 0x24, 0xD8, - 0x88, 0x82, 0x8B, 0x39, 0xF9, 0x29, 0x95, 0x94, 0x10, 0x89, 0x71, 0xA9, 0xE1, 0xFB, 0x20, 0x92, - 0x8E, 0xEB, 0xAD, 0x36, 0xA0, 0x28, 0x12, 0x50, 0x48, 0x27, 0x8E, 0xF7, 0x50, 0x77, 0x51, 0x00, - 0x8E, 0x10, 0x49, 0x4C, 0x3A, 0xFE, 0x59, 0xBF, 0xD4, 0x85, 0x88, 0x8C, 0xD8, 0x1D, 0x99, 0x4D, - 0x61, 0x30, 0x47, 0x00, 0xDB, 0xCA, 0x06, 0xEC, 0x18, 0x1A, 0xF5, 0x94, 0x21, 0x2F, 0xB8, 0x20, - 0xC7, 0x7A, 0x9A, 0xDA, 0xC7, 0x7B, 0xC3, 0x52, 0x1F, 0xFE, 0x12, 0xED, 0x20, 0xA7, 0x13, 0x71, - 0x8C, 0x20, 0x5B, 0x4E, 0x30, 0x19, 0xFC, 0x87, 0x8B, 0xBF, 0x00, 0x49, 0xE6, 0xF9, 0x69, 0xC4, - 0x61, 0xEF, 0x82, 0x4D, 0x3C, 0x8E, 0xF0, 0x0C, 0x00, 0x5E, 0xF0, 0xF8, 0x6F, 0xDC, 0x71, 0x81, - 0x49, 0x67, 0x73, 0x86, 0xC7, 0x66, 0xA3, 0x29, 0xB9, 0x03, 0xE2, 0xC4, 0xD4, 0x70, 0x93, 0x5E, - 0x87, 0xA6, 0xEB, 0x16, 0xEE, 0xF6, 0xD3, 0x97, 0x7E, 0x3F, 0x32, 0xB7, 0xC8, 0x28, 0x2C, 0x67, - 0x18, 0x81, 0x77, 0xA7, 0x77, 0x57, 0xE7, 0xD9, 0xBD, 0x9F, 0x0B, 0xDC, 0x3C, 0x35, 0x7C, 0xEE, - 0x01, 0x5A, 0x8E, 0xD8, 0xD5, 0x39, 0x9C, 0xAD, 0xF0, 0xAF, 0xE0, 0x18, 0xAA, 0x05, 0x72, 0x93, - 0x6E, 0x02, 0xD2, 0xBB, 0xD7, 0xD7, 0x9F, 0xB3, 0xC7, 0xB9, 0xBE, 0x1E, 0x1D, 0x4F, 0x75, 0x93, - 0x80, 0x0A, 0xB7, 0x34, 0x0E, 0x62, 0xF3, 0xB5, 0xE2, 0x65, 0xF7, 0xB3, 0x0F, 0xCB, 0x7F, 0xDF, - 0x6C, 0xBF, 0xDF, 0x7F, 0xF7, 0x5E, 0xCE, 0x70, 0xB7, 0x68, 0xB7, 0xB3, 0x80, 0x5C, 0x6F, 0x35, - 0x0F, 0x1A, 0xAD, 0xA3, 0x83, 0xE6, 0xC1, 0xBB, 0xC3, 0x56, 0xC9, 0x8E, 0xBB, 0xC6, 0x8C, 0xF9, - 0xB6, 0x0E, 0x0E, 0x61, 0xC6, 0x47, 0xC1, 0x64, 0xD9, 0x4E, 0xB7, 0x77, 0xF6, 0x76, 0x1A, 0x9E, - 0x85, 0xD0, 0x26, 0x02, 0xEB, 0x8B, 0xB3, 0x8B, 0xCB, 0xEC, 0x41, 0xF1, 0xDB, 0x3C, 0x68, 0x73, - 0x95, 0x0F, 0x7E, 0x99, 0x05, 0x90, 0xF6, 0x51, 0xB3, 0xDD, 0x3C, 0x6C, 0x1C, 0x1C, 0x1E, 0x15, - 0x84, 0x07, 0xF6, 0xF8, 0xEB, 0x8C, 0x1E, 0xF7, 0xDF, 0xB5, 0x0E, 0x8F, 0x9A, 0xFB, 0x8D, 0xFD, - 0x66, 0xA7, 0x44, 0x8F, 0xBF, 0xCD, 0xC2, 0x85, 0xA3, 0xC3, 0xC3, 0xC3, 0x83, 0xC6, 0xFE, 0xD1, - 0x7E, 0xF2, 0x54, 0xCE, 0x03, 0x6C, 0x94, 0xB7, 0xA5, 0x7E, 0x1E, 0x39, 0x01, 0x0B, 0x19, 0x7B, - 0xF5, 0x66, 0x52, 0x9A, 0x99, 0xE6, 0x7B, 0x74, 0xA0, 0x4C, 0x31, 0xA6, 0x7F, 0xA8, 0xD7, 0x59, - 0x3D, 0xF8, 0xC7, 0xE0, 0xE8, 0x1E, 0x80, 0x1C, 0xC3, 0xCE, 0x2C, 0x73, 0xA0, 0x0F, 0x23, 0x5F, - 0xD4, 0xEB, 0x27, 0xD3, 0x0C, 0x4D, 0x0E, 0xAF, 0x81, 0x5E, 0x06, 0x4A, 0xD1, 0x50, 0xB1, 0xEB, - 0xED, 0x14, 0x1E, 0xF6, 0x41, 0x28, 0x1E, 0xA1, 0x44, 0xE5, 0x99, 0x0C, 0xFE, 0xAB, 0xDB, 0x8E, - 0x0E, 0x93, 0x7B, 0x66, 0x13, 0x65, 0x59, 0xF0, 0x60, 0x5B, 0x4C, 0x41, 0xCC, 0xA0, 0xC6, 0xBC, - 0x67, 0x1B, 0x96, 0x21, 0xBA, 0xA8, 0x31, 0x38, 0xBA, 0x94, 0xBA, 0x68, 0x41, 0xE7, 0x89, 0xA1, - 0xD8, 0x2E, 0xAF, 0xA5, 0xEE, 0x91, 0x78, 0x95, 0xD4, 0xEA, 0x8F, 0xB5, 0x7F, 0x0C, 0xDE, 0xED, - 0xC5, 0x7B, 0x57, 0x1C, 0x5D, 0xA9, 0xF3, 0xEF, 0xB0, 0x01, 0x1A, 0xC7, 0x83, 0x55, 0x31, 0xA0, - 0x3B, 0xF1, 0x14, 0xCF, 0x10, 0xC7, 0x32, 0xDC, 0xC9, 0x38, 0xF1, 0xB6, 0x27, 0xA9, 0xA3, 0xC6, - 0x01, 0xE8, 0x3B, 0x0A, 0xA9, 0xFE, 0x1F, 0xF4, 0xD8, 0xD2, 0x50, 0x6B, 0x9F, 0x9C, 0x8A, 0xA4, - 0xC3, 0xA3, 0x3A, 0xCF, 0xEE, 0x75, 0x96, 0x50, 0xF3, 0xF1, 0xB8, 0xD3, 0xD3, 0x70, 0x46, 0x00, - 0x24, 0x15, 0x63, 0xB2, 0xB6, 0x29, 0x58, 0x06, 0x1B, 0xDF, 0xC3, 0x3E, 0x49, 0x72, 0x2D, 0xB6, - 0x32, 0xC2, 0x92, 0xD4, 0xBE, 0xDC, 0x11, 0xC8, 0x0B, 0xB9, 0x1D, 0x4E, 0xA1, 0xCF, 0xD4, 0xDC, - 0x14, 0x47, 0x63, 0xF8, 0xA3, 0x8E, 0x52, 0x7C, 0x12, 0x49, 0xD3, 0x5A, 0x0C, 0x2C, 0x67, 0x2C, - 0xED, 0x01, 0x80, 0xFE, 0xED, 0x8C, 0xED, 0x88, 0x6C, 0xC9, 0x71, 0xE6, 0x0B, 0x82, 0x9A, 0x65, - 0xBF, 0x9E, 0x27, 0xB1, 0xEC, 0xDE, 0xAD, 0x03, 0x2D, 0xAB, 0x7C, 0x4C, 0x66, 0x36, 0xA1, 0x15, - 0x64, 0x76, 0x41, 0x36, 0x05, 0xB4, 0xDD, 0x81, 0xE0, 0xC2, 0x0D, 0xAE, 0x7A, 0x4C, 0x61, 0x72, - 0xB7, 0x19, 0xE0, 0x16, 0xE8, 0xF2, 0xDC, 0x64, 0xD0, 0x3F, 0x08, 0x00, 0x4C, 0xCA, 0xC1, 0xA0, - 0xE0, 0x5B, 0xF0, 0x5C, 0xF1, 0x82, 0x17, 0x1B, 0xAC, 0xEB, 0x09, 0x19, 0x72, 0x37, 0x2A, 0x93, - 0x3D, 0xE9, 0x20, 0x1E, 0xF8, 0x08, 0x6A, 0xEA, 0x98, 0x6B, 0x93, 0xF7, 0x03, 0x64, 0x53, 0x47, - 0x8A, 0x39, 0xE4, 0x2E, 0x43, 0xF1, 0xCE, 0x55, 0x1E, 0xE1, 0x95, 0x27, 0x1A, 0x0F, 0x94, 0xE4, - 0xC1, 0x80, 0xA3, 0x79, 0x29, 0x9C, 0x0C, 0x48, 0x78, 0x61, 0x3F, 0xA0, 0xCC, 0xD3, 0x7B, 0x6F, - 0xFA, 0xD0, 0x26, 0x8E, 0xB1, 0x6F, 0xF0, 0x45, 0x1B, 0x26, 0xE3, 0x72, 0xAD, 0x31, 0x03, 0xB6, - 0x53, 0xE0, 0x23, 0xFC, 0xD5, 0xCD, 0x81, 0x55, 0x57, 0x75, 0x47, 0x85, 0x01, 0x3D, 0xFE, 0xDD, - 0x0B, 0x69, 0x7D, 0xEC, 0xE2, 0x4E, 0x65, 0x71, 0xC2, 0x04, 0x47, 0x4C, 0x47, 0x81, 0x04, 0x17, - 0x2C, 0x80, 0x1E, 0x28, 0xA5, 0x9D, 0xE4, 0x6C, 0x7E, 0x3A, 0xFF, 0x8E, 0xE9, 0xCC, 0x01, 0xFB, - 0x9C, 0x09, 0x0A, 0xDD, 0xB4, 0x7D, 0x4F, 0xF2, 0x2C, 0x47, 0xD1, 0x74, 0xAB, 0x26, 0x2D, 0xB8, - 0x12, 0xFE, 0xB7, 0xE2, 0xD9, 0xA3, 0x02, 0xC2, 0xCC, 0xC7, 0x5A, 0x33, 0xAF, 0x3B, 0x43, 0xB9, - 0xE7, 0x46, 0x94, 0x75, 0x34, 0x49, 0xC3, 0x3C, 0x91, 0x1B, 0x0F, 0x62, 0x00, 0xBD, 0xB1, 0x10, - 0x28, 0x5F, 0x05, 0x24, 0x5B, 0xA5, 0x21, 0xD9, 0x12, 0x90, 0x6C, 0xB5, 0x3B, 0xFB, 0x07, 0x87, - 0xEF, 0x8E, 0xDE, 0x37, 0x27, 0x7F, 0x6D, 0xA1, 0x2A, 0xA1, 0xDA, 0x2E, 0x0D, 0xD5, 0xB6, 0x80, - 0xEA, 0x16, 0x82, 0x12, 0x82, 0x9D, 0xD2, 0x10, 0xEC, 0x6C, 0x21, 0x18, 0x83, 0xE0, 0x7E, 0x69, - 0x08, 0xEE, 0x6F, 0x21, 0x18, 0x83, 0xE0, 0x41, 0x69, 0x08, 0x1E, 0x6C, 0x21, 0x18, 0x83, 0xE0, - 0x61, 0x69, 0x08, 0x1E, 0x6E, 0x21, 0x18, 0x83, 0xE0, 0xBB, 0xD2, 0x10, 0x7C, 0x57, 0x1D, 0x04, - 0x2B, 0x04, 0xA1, 0x98, 0x26, 0xBC, 0x1F, 0xCE, 0x53, 0x98, 0xFC, 0x03, 0xDD, 0x36, 0x7A, 0x81, - 0x23, 0xCD, 0x9D, 0x1D, 0xFA, 0x63, 0x9F, 0x7E, 0xD2, 0x40, 0xD4, 0x47, 0x28, 0xC3, 0xCD, 0x04, - 0x0B, 0x76, 0x7E, 0x9C, 0x0F, 0x82, 0xB8, 0x62, 0x86, 0x83, 0x1E, 0xD1, 0x70, 0xEF, 0xCA, 0x6C, - 0x22, 0x0A, 0xEA, 0xB5, 0x18, 0x44, 0xA4, 0x06, 0x1C, 0x53, 0xCB, 0xC5, 0xAE, 0xCC, 0xEE, 0xD5, - 0x4E, 0x36, 0xA0, 0x8B, 0xC3, 0xB0, 0xEF, 0xC8, 0x65, 0x22, 0xEE, 0xAF, 0x3D, 0x6B, 0x6F, 0x33, - 0x29, 0x60, 0x7A, 0xA0, 0x33, 0x52, 0x82, 0x6E, 0x40, 0x65, 0x41, 0x03, 0x6E, 0x7C, 0x30, 0x79, - 0x85, 0x38, 0x63, 0xB8, 0xEA, 0x51, 0x65, 0xDA, 0x08, 0x23, 0xEF, 0x90, 0x0F, 0x0A, 0x50, 0x97, - 0x34, 0x99, 0xC4, 0x8D, 0x1F, 0x74, 0x43, 0xE4, 0x99, 0x74, 0x1F, 0x21, 0xB1, 0xA7, 0x96, 0x65, - 0x55, 0x49, 0xC5, 0xC4, 0xD9, 0xFA, 0x2B, 0x5D, 0x04, 0x9B, 0x67, 0xE8, 0xC5, 0x30, 0x35, 0xCE, - 0xCE, 0xDB, 0x9A, 0xBC, 0x07, 0x91, 0x0F, 0xD2, 0x2D, 0x10, 0x4B, 0xD2, 0xAC, 0x23, 0xDA, 0xB5, - 0x98, 0x44, 0x52, 0x15, 0x46, 0x55, 0x7A, 0xA0, 0xA8, 0x9E, 0x05, 0x2B, 0xD7, 0xF8, 0x40, 0xF1, - 0x0D, 0xCF, 0xCD, 0x53, 0x5B, 0x97, 0xA2, 0xBA, 0xE6, 0x71, 0xA4, 0xE2, 0x58, 0xED, 0x44, 0xA0, - 0x7F, 0xE3, 0x0E, 0x2B, 0x43, 0xE8, 0x34, 0x23, 0x51, 0xCA, 0xAB, 0x09, 0xBB, 0x20, 0x59, 0xF8, - 0x57, 0x68, 0x14, 0x1C, 0x7B, 0xC0, 0x37, 0xA3, 0x96, 0xC1, 0x8A, 0xCD, 0x80, 0xB8, 0x9E, 0xB9, - 0x6C, 0x80, 0x91, 0x86, 0xE9, 0x70, 0x8F, 0x40, 0x2A, 0x61, 0xFD, 0xC3, 0x2B, 0x95, 0x17, 0x36, - 0xFD, 0xC5, 0x8D, 0x74, 0x33, 0xD7, 0x92, 0x6D, 0x9D, 0x63, 0xB6, 0x57, 0x6F, 0xCD, 0x34, 0xD1, - 0xD1, 0x55, 0x1A, 0x57, 0x5C, 0xDF, 0x21, 0x1A, 0xBF, 0x55, 0x3C, 0x7E, 0x85, 0x27, 0xCD, 0x0C, - 0x8A, 0xBC, 0x99, 0xBC, 0xCE, 0xF0, 0xFD, 0xE3, 0x42, 0xA7, 0xDD, 0x6C, 0x16, 0x9C, 0x71, 0x36, - 0xB6, 0x89, 0x1F, 0xB6, 0xDA, 0x48, 0xD2, 0x1D, 0x36, 0x61, 0xE8, 0x45, 0xF8, 0x45, 0xE4, 0xFC, - 0x4F, 0x2C, 0xF0, 0xF3, 0x9F, 0xB1, 0x7B, 0xCE, 0xE8, 0x49, 0x7F, 0x65, 0xE6, 0x76, 0x8C, 0xFF, - 0x3E, 0xFF, 0x79, 0x5C, 0xE8, 0xBD, 0x0A, 0x99, 0x6A, 0x82, 0xB9, 0xDE, 0x8D, 0x38, 0x33, 0xFD, - 0xF1, 0x3D, 0x77, 0x98, 0x35, 0x60, 0xE4, 0xE7, 0x01, 0xF8, 0xEB, 0xA2, 0xA1, 0xD0, 0xB0, 0x54, - 0x81, 0xCC, 0xFF, 0xF9, 0x1F, 0xFF, 0x7B, 0xA0, 0x7F, 0xE7, 0xEE, 0x7F, 0xFE, 0xC7, 0xFF, 0x61, - 0x36, 0xBC, 0xE8, 0x72, 0x40, 0x5B, 0xAD, 0xC1, 0xBA, 0xE6, 0xB3, 0x37, 0xD2, 0xCD, 0x21, 0x53, - 0xEE, 0xAD, 0x47, 0xCE, 0xF6, 0x3F, 0xFF, 0x09, 0x32, 0xE5, 0x33, 0x60, 0x0D, 0x9A, 0x2E, 0x27, - 0x77, 0x77, 0xF0, 0xF2, 0x90, 0xBB, 0xD4, 0x13, 0xD0, 0xDB, 0x1E, 0xF5, 0x3C, 0x1C, 0x62, 0x3B, - 0x90, 0x48, 0x55, 0x87, 0xC3, 0xD2, 0x54, 0x9D, 0xBB, 0x0D, 0xF6, 0xC5, 0x02, 0x24, 0x60, 0x38, - 0xA3, 0x08, 0xA0, 0x99, 0x83, 0x57, 0xD7, 0xBA, 0x4B, 0xDE, 0x5D, 0x0E, 0xF9, 0x75, 0x21, 0xEB, - 0x6F, 0xC1, 0x60, 0x64, 0xC9, 0xD4, 0x4D, 0x76, 0x8A, 0x7E, 0x03, 0x63, 0x4B, 0xE3, 0x0D, 0x76, - 0x2E, 0x4E, 0x82, 0x63, 0x9C, 0x4C, 0x83, 0x5D, 0xEB, 0x63, 0x1D, 0x9D, 0x72, 0x1A, 0xCD, 0x66, - 0xB3, 0xD5, 0x6E, 0x53, 0xBB, 0x26, 0x7C, 0x51, 0x60, 0xDB, 0x97, 0x7A, 0x5C, 0x14, 0x3D, 0x36, - 0x26, 0xEF, 0xE5, 0x88, 0x83, 0x05, 0xCE, 0x98, 0x0C, 0xCA, 0x10, 0x42, 0xEA, 0xC1, 0x3C, 0x84, - 0x11, 0x95, 0x24, 0x05, 0x0A, 0xA5, 0xCA, 0x92, 0x91, 0xAB, 0x82, 0x69, 0xFA, 0x29, 0x30, 0x8C, - 0x9D, 0xDE, 0x74, 0x5E, 0x01, 0x33, 0x4F, 0xF2, 0x8B, 0x8C, 0x1B, 0xBB, 0xAD, 0x27, 0x00, 0xE1, - 0xAD, 0x1B, 0xAE, 0xA7, 0x09, 0x83, 0xF0, 0xF1, 0x89, 0xE5, 0x7C, 0xD8, 0x83, 0x5F, 0x34, 0xDE, - 0x7A, 0xB0, 0xA4, 0x3E, 0x57, 0x6B, 0x27, 0x7D, 0xA2, 0x4F, 0x97, 0xDD, 0x73, 0xEF, 0x89, 0x03, - 0x89, 0x44, 0xDE, 0x71, 0xD7, 0x8C, 0xDF, 0xCC, 0x98, 0x69, 0x03, 0x38, 0x01, 0x90, 0xBD, 0xC0, - 0x32, 0x1D, 0x7D, 0x23, 0x81, 0x0D, 0x98, 0xC0, 0x04, 0x80, 0xD8, 0xA1, 0xA9, 0x97, 0xC6, 0x26, - 0xF0, 0xDE, 0x05, 0x5E, 0x05, 0xFE, 0x33, 0xF0, 0x0D, 0xC1, 0x1F, 0x3C, 0xE5, 0x81, 0x58, 0x54, - 0xEC, 0x65, 0x8E, 0xFE, 0x15, 0x6C, 0xC0, 0x9F, 0xC2, 0x19, 0x28, 0xAA, 0x63, 0xB9, 0xF0, 0x0B, - 0x78, 0x13, 0xBC, 0x0D, 0x2F, 0x3E, 0xF2, 0x67, 0xB6, 0xD3, 0xDE, 0xFF, 0x6F, 0x6C, 0x64, 0xF9, - 0x8E, 0xFB, 0xB6, 0x0A, 0xEE, 0x14, 0xB2, 0xA3, 0x16, 0xBE, 0x73, 0xD4, 0x7A, 0x7F, 0x18, 0x0C, - 0x0F, 0x1C, 0x89, 0x40, 0x5E, 0x18, 0x9A, 0x11, 0xCF, 0xB0, 0x2D, 0x53, 0xAA, 0x94, 0x29, 0x11, - 0x05, 0xCD, 0xC9, 0x95, 0xA0, 0x6D, 0x05, 0x6C, 0x69, 0x8E, 0xAF, 0xE7, 0x54, 0x65, 0x85, 0x3F, - 0xCE, 0xB3, 0xA9, 0x8C, 0x75, 0xF5, 0x06, 0x30, 0xD4, 0x38, 0x77, 0x2C, 0x5B, 0x08, 0xA2, 0x85, - 0xEC, 0x21, 0xD1, 0xA6, 0xB5, 0xD4, 0x3D, 0x3C, 0x9C, 0xB2, 0x81, 0x9C, 0x8B, 0x36, 0x8C, 0x1A, - 0x1D, 0xAF, 0x58, 0x95, 0xEC, 0x6A, 0x7F, 0xF7, 0x5D, 0x2F, 0xE0, 0x25, 0x1E, 0x77, 0x4C, 0xC5, - 0x60, 0x8A, 0x31, 0xB4, 0x1C, 0xDD, 0x1B, 0x8D, 0x91, 0x2A, 0xC7, 0x8A, 0xA7, 0x8E, 0xE8, 0x7B, - 0x50, 0x0F, 0x84, 0xC2, 0xA9, 0xD8, 0x36, 0x28, 0xC8, 0x42, 0x14, 0xE2, 0xE6, 0xA3, 0xEE, 0x58, - 0x26, 0x8E, 0x2D, 0xF9, 0x93, 0xBC, 0xDA, 0x65, 0xFA, 0x18, 0x14, 0xD3, 0x47, 0x2E, 0xFA, 0x76, - 0xB8, 0xCA, 0x75, 0xE0, 0x08, 0x6F, 0x5C, 0x31, 0x8C, 0x0D, 0x12, 0xBE, 0xE8, 0x00, 0x38, 0x57, - 0x94, 0xC9, 0xC9, 0x9B, 0x62, 0x1F, 0x6F, 0x5E, 0xAD, 0x47, 0x5D, 0xC3, 0x1B, 0x5D, 0x60, 0x16, - 0x0E, 0xB0, 0x32, 0x55, 0xF5, 0x89, 0xB9, 0x04, 0x7E, 0xB8, 0xE8, 0xB1, 0x0D, 0xB8, 0xDD, 0x40, - 0xA7, 0x38, 0x1A, 0x31, 0x3A, 0x10, 0x4E, 0x1D, 0x60, 0xE5, 0x9B, 0xAE, 0xAF, 0x7B, 0x18, 0xE0, - 0xC1, 0x00, 0x46, 0x1E, 0xC2, 0x9D, 0x58, 0x0F, 0xED, 0x17, 0x35, 0x18, 0xC2, 0xDB, 0x66, 0xD6, - 0x92, 0x90, 0x91, 0x19, 0xFA, 0x03, 0x37, 0xD0, 0x45, 0x03, 0xEF, 0xA5, 0x41, 0x94, 0x42, 0x16, - 0x86, 0x5C, 0x11, 0x98, 0x23, 0xCC, 0x3D, 0x1C, 0x0F, 0xE4, 0x40, 0xEC, 0x1D, 0x44, 0x37, 0xC1, - 0x75, 0xC3, 0x59, 0x8A, 0x79, 0xAB, 0xCF, 0xEB, 0xAB, 0x8A, 0x97, 0x37, 0xAD, 0x49, 0x5C, 0xCE, - 0xBD, 0x14, 0x17, 0x6E, 0x00, 0xC2, 0x26, 0x1A, 0xA7, 0x8D, 0x24, 0xA1, 0xC5, 0x99, 0x92, 0x26, - 0xC9, 0x4E, 0x70, 0xA5, 0xDC, 0xF5, 0xD1, 0x30, 0x2B, 0xE7, 0x13, 0x63, 0xDD, 0xBC, 0x30, 0xF8, - 0xE3, 0x4C, 0x4D, 0x78, 0x6E, 0xD3, 0xD9, 0x94, 0x58, 0x23, 0x06, 0x2B, 0xCA, 0x54, 0x6E, 0x00, - 0x49, 0xFB, 0x7F, 0x63, 0xD8, 0x84, 0x90, 0xFA, 0xF8, 0xA7, 0x15, 0x4B, 0x38, 0x92, 0xBF, 0xC0, - 0x3C, 0x30, 0xE8, 0x8A, 0xF1, 0x60, 0x22, 0x48, 0x3D, 0x1A, 0xC7, 0xA0, 0x04, 0x97, 0x48, 0x50, - 0x11, 0xC6, 0x02, 0x17, 0x08, 0xDB, 0x30, 0x74, 0x8F, 0xAC, 0x58, 0xF7, 0x1C, 0x05, 0x16, 0x4D, - 0x10, 0x1A, 0x28, 0x5A, 0x45, 0xD5, 0x93, 0xA5, 0xA9, 0x26, 0xC5, 0xC8, 0xAC, 0xC8, 0xE9, 0x3F, - 0x2F, 0x29, 0x95, 0x39, 0xCA, 0x63, 0xD8, 0x59, 0xE2, 0xE8, 0x16, 0x0D, 0x36, 0xEF, 0xBC, 0x86, - 0x89, 0x9F, 0x7D, 0xF9, 0xBA, 0x32, 0x32, 0x84, 0xB1, 0xCA, 0x50, 0xE1, 0xD9, 0xDE, 0x97, 0xE6, - 0x4B, 0x53, 0xDF, 0x84, 0xBA, 0xD0, 0xF9, 0x4A, 0x31, 0x44, 0xD4, 0x45, 0x2A, 0xA9, 0x4D, 0x0C, - 0x06, 0x87, 0xDA, 0x29, 0x08, 0xED, 0x48, 0xA3, 0xBF, 0x5D, 0x9C, 0xD7, 0x2F, 0xDF, 0xF7, 0xE8, - 0x58, 0x6B, 0x35, 0xC3, 0xC7, 0xDF, 0x6E, 0xDE, 0x1F, 0x35, 0xB7, 0xB4, 0x39, 0x1F, 0x6D, 0x22, - 0x16, 0x95, 0x21, 0x4D, 0x78, 0x7F, 0x63, 0x28, 0x13, 0x0D, 0xD7, 0x81, 0x95, 0xD5, 0x74, 0x11, - 0xF5, 0x88, 0xF5, 0x9F, 0x8D, 0xB8, 0xFA, 0x70, 0x6A, 0x7D, 0xE7, 0x6E, 0x41, 0x69, 0x9A, 0x8C, - 0xC5, 0xD1, 0x1E, 0xA0, 0x61, 0xFC, 0x73, 0x81, 0x7B, 0xC1, 0x4A, 0xFD, 0x1A, 0xEF, 0xA2, 0x12, - 0x26, 0xC8, 0x86, 0xAA, 0x62, 0x93, 0x6C, 0x09, 0x82, 0x20, 0x2C, 0x55, 0x86, 0xB1, 0x82, 0xB0, - 0x28, 0xDE, 0x41, 0x99, 0x54, 0x10, 0x1C, 0x9C, 0x75, 0x8E, 0x05, 0x92, 0x27, 0x10, 0x96, 0x6E, - 0x1B, 0x7C, 0x42, 0x90, 0xA1, 0x9E, 0x1D, 0x7E, 0x15, 0x03, 0x19, 0xE8, 0xFC, 0x7D, 0x6B, 0xCC, - 0xA3, 0xE2, 0xA9, 0xCB, 0x34, 0x5D, 0xF5, 0x50, 0x0E, 0x46, 0xE9, 0xD5, 0xE4, 0x40, 0xBC, 0xE8, - 0x43, 0xE9, 0x3B, 0x28, 0x4A, 0xC3, 0x34, 0xB8, 0x83, 0x51, 0x1F, 0xF1, 0x6E, 0x68, 0x3E, 0x36, - 0xFE, 0x85, 0xF4, 0x2D, 0xC4, 0x25, 0x61, 0x03, 0x10, 0xD2, 0x6F, 0xFC, 0x65, 0x72, 0xB6, 0x14, - 0x36, 0xCB, 0xA4, 0x44, 0x0D, 0x8B, 0x41, 0x51, 0xDC, 0x1B, 0x59, 0x2E, 0x0F, 0x97, 0x06, 0xB2, - 0x3C, 0x74, 0x12, 0x48, 0xE0, 0x63, 0xB1, 0xD4, 0x7B, 0x8E, 0x9F, 0x89, 0xB7, 0x68, 0xBE, 0x83, - 0x7F, 0x87, 0x02, 0xB1, 0xAA, 0x18, 0xAA, 0x1F, 0xAE, 0x2F, 0xE4, 0x37, 0x5D, 0x18, 0x95, 0x9B, - 0x08, 0xCE, 0xF5, 0xF2, 0xB6, 0x8C, 0x59, 0xF4, 0x63, 0x90, 0x3A, 0xE5, 0xFA, 0xB9, 0xE5, 0x27, - 0xE8, 0x1C, 0x91, 0x5C, 0x5C, 0xDD, 0x44, 0xAF, 0x1F, 0x8B, 0x1D, 0x31, 0x53, 0x1D, 0xC9, 0x83, - 0x44, 0x90, 0x43, 0x6C, 0xEC, 0xDF, 0xE5, 0xE0, 0x27, 0xE2, 0x77, 0x31, 0x0E, 0x27, 0x98, 0xD4, - 0xF4, 0x28, 0xF4, 0x3C, 0xB8, 0x5F, 0xA2, 0x47, 0x30, 0xF7, 0xD0, 0x6F, 0x21, 0x85, 0x94, 0xC3, - 0xD1, 0xE7, 0xBE, 0xE0, 0x4B, 0x05, 0xE8, 0x27, 0xC5, 0xD0, 0x0D, 0x6E, 0xBD, 0x10, 0x44, 0x83, - 0xD1, 0x4F, 0xE4, 0x1F, 0xAB, 0x86, 0x69, 0x38, 0x7E, 0xC5, 0x40, 0x35, 0x2C, 0x13, 0x26, 0xF7, - 0x52, 0x40, 0xBD, 0xFE, 0xFA, 0xA5, 0xDB, 0xEF, 0x03, 0x50, 0xC5, 0x1F, 0x2B, 0x07, 0x6A, 0x30, - 0x7E, 0xC5, 0x40, 0xB5, 0x5F, 0x0C, 0xA0, 0x3D, 0x04, 0x66, 0x6F, 0xF5, 0x80, 0xEC, 0x55, 0x0E, - 0xC4, 0x2F, 0xCA, 0xA3, 0xAE, 0xBE, 0x10, 0x18, 0x61, 0xEC, 0xAB, 0xB3, 0xDA, 0xC9, 0x97, 0xEE, - 0xDF, 0xAE, 0xCE, 0x56, 0x0D, 0x4A, 0x39, 0x76, 0xB5, 0xC0, 0xFC, 0x97, 0x3F, 0x5F, 0x8C, 0xC6, - 0xFF, 0xE5, 0x37, 0x24, 0x30, 0xFC, 0xB9, 0x6A, 0x48, 0x8A, 0x91, 0xAB, 0x05, 0x64, 0xFF, 0x5E, - 0x79, 0x29, 0x40, 0xF6, 0x4F, 0xBB, 0xB0, 0x1C, 0xFC, 0xB9, 0x6A, 0x40, 0x8A, 0x91, 0x17, 0x02, - 0xE4, 0x5C, 0xAA, 0xB5, 0x3D, 0xF1, 0x0A, 0x89, 0xC9, 0xBD, 0x4B, 0xF0, 0x96, 0xCB, 0x55, 0x64, - 0x68, 0x26, 0xE2, 0x0C, 0xFE, 0xAC, 0xB8, 0xD2, 0xA8, 0x5C, 0xC6, 0xA0, 0x30, 0xC1, 0x93, 0x2A, - 0x50, 0x43, 0xC8, 0xC2, 0x9F, 0xC2, 0x09, 0xD5, 0x4E, 0x2E, 0xE8, 0x09, 0x93, 0x8F, 0xD8, 0xE7, - 0x6E, 0x7F, 0xEF, 0xE2, 0x30, 0x57, 0x87, 0x3C, 0xB3, 0x40, 0x2B, 0xA1, 0xEC, 0x3B, 0xEE, 0xF2, - 0xB1, 0x6A, 0x7A, 0xD2, 0x2B, 0xBE, 0xD0, 0xF8, 0x06, 0x8A, 0xC9, 0x67, 0x68, 0xC1, 0xBA, 0xD2, - 0xEC, 0xCE, 0xFA, 0xDC, 0xA1, 0x18, 0x32, 0x75, 0x02, 0x87, 0xE0, 0x6E, 0x41, 0xA3, 0x5B, 0x4A, - 0xD2, 0x72, 0x02, 0xA0, 0xC6, 0xC8, 0x22, 0xA2, 0x9D, 0x5C, 0x14, 0xD3, 0x4C, 0xD6, 0xD1, 0xA1, - 0xAE, 0x94, 0x06, 0x5F, 0x08, 0x87, 0x4B, 0xE0, 0xEF, 0x17, 0xCF, 0xD1, 0xED, 0x33, 0x43, 0xC7, - 0x54, 0x1E, 0x01, 0x02, 0x7F, 0xB9, 0xBB, 0xBD, 0xEA, 0x31, 0xF1, 0x30, 0x5F, 0x81, 0x5F, 0x1C, - 0x1D, 0x63, 0x73, 0x58, 0x91, 0xA5, 0xE0, 0x1B, 0x69, 0xCF, 0xBA, 0x2B, 0x17, 0xAB, 0xD2, 0xE8, - 0xA8, 0x42, 0xE3, 0xB5, 0x06, 0x66, 0xAC, 0x88, 0xE0, 0x23, 0x8D, 0x24, 0xD4, 0x66, 0x05, 0xB4, - 0x63, 0x97, 0x54, 0x69, 0x57, 0xA0, 0x6D, 0x83, 0xFD, 0x6A, 0xF9, 0x4E, 0x10, 0x07, 0x39, 0xF6, - 0x5D, 0x0F, 0x6D, 0x76, 0x4F, 0x3A, 0xFA, 0x19, 0x89, 0x94, 0x10, 0x0E, 0xBA, 0xFC, 0x32, 0xC5, - 0x63, 0xE8, 0x94, 0xE1, 0xE9, 0x63, 0x1E, 0x55, 0xAA, 0xCF, 0x75, 0x77, 0xFD, 0x34, 0xEA, 0x42, - 0x9C, 0xD8, 0x9C, 0x6C, 0x5A, 0xE0, 0xA4, 0x98, 0x1A, 0xC3, 0xBB, 0x64, 0x83, 0x6F, 0x74, 0x1A, - 0xB0, 0x33, 0xDC, 0xF9, 0x6C, 0xB9, 0x5E, 0x01, 0x5F, 0xF7, 0x83, 0x29, 0x63, 0xB0, 0x68, 0x9E, - 0xCB, 0x3D, 0xB0, 0xFF, 0xE3, 0x79, 0x0D, 0x96, 0x47, 0xF3, 0x19, 0x2C, 0x73, 0xDC, 0xDE, 0xD3, - 0x61, 0x50, 0xD8, 0x7A, 0x99, 0xDA, 0x7C, 0xF9, 0xC6, 0xCC, 0x15, 0xE3, 0x45, 0x0F, 0x53, 0x13, - 0x2E, 0x11, 0x2F, 0xB0, 0xFF, 0x55, 0xE3, 0x45, 0xAE, 0x21, 0x3B, 0x1D, 0x0A, 0xF3, 0x63, 0x06, - 0x36, 0x7F, 0x75, 0x98, 0x01, 0x47, 0x81, 0xB3, 0x4C, 0xCC, 0xC0, 0xFE, 0xD7, 0x9D, 0x63, 0x10, - 0x0C, 0xE6, 0xC7, 0x0B, 0x6C, 0xFE, 0x2A, 0xF1, 0xA2, 0xF7, 0x73, 0xBE, 0x64, 0x3B, 0x03, 0x73, - 0xB2, 0x2E, 0x1E, 0x4B, 0x60, 0x0E, 0xEB, 0xFD, 0x3C, 0x37, 0xF2, 0xBC, 0x13, 0x88, 0xBB, 0x0A, - 0xE4, 0x01, 0x40, 0x2D, 0x86, 0x3E, 0xBD, 0x9F, 0x5F, 0x11, 0x02, 0xDD, 0x58, 0xBE, 0xE9, 0xF5, - 0x2C, 0xDD, 0x9C, 0xEF, 0xC8, 0xA1, 0xE6, 0x05, 0x4E, 0x1C, 0xE8, 0x7F, 0x7D, 0x19, 0x4B, 0x04, - 0x06, 0xF3, 0x60, 0xC6, 0xA4, 0xF9, 0xAB, 0xC4, 0x8B, 0x25, 0x31, 0x96, 0x12, 0x98, 0x93, 0xFF, - 0xD6, 0x1A, 0x33, 0x9E, 0x18, 0x20, 0x17, 0x43, 0xAF, 0xF5, 0x62, 0x3C, 0xA1, 0x7E, 0xDF, 0xAA, - 0xDC, 0x96, 0x19, 0x59, 0xFD, 0x1D, 0xA6, 0x16, 0x1E, 0xEB, 0xDE, 0xA7, 0x4F, 0xDD, 0xDA, 0x49, - 0xF0, 0x81, 0xC1, 0x27, 0xD4, 0x80, 0x05, 0x4F, 0x5E, 0xBE, 0x2D, 0x2A, 0x63, 0x3E, 0xB9, 0x9B, - 0xE9, 0x9B, 0xD4, 0x21, 0xD7, 0x56, 0x6D, 0xBB, 0xA2, 0xAB, 0x7E, 0x95, 0xA0, 0x83, 0x89, 0x40, - 0xFF, 0xF0, 0x75, 0x74, 0x7B, 0x85, 0xBF, 0x86, 0xBE, 0xA1, 0x38, 0x93, 0x0B, 0x74, 0x99, 0xBD, - 0x92, 0x0C, 0x06, 0x74, 0x43, 0x4F, 0x56, 0xAC, 0x1D, 0x04, 0xEF, 0x58, 0x84, 0xFE, 0xBE, 0x65, - 0xAE, 0xCC, 0xAB, 0x84, 0xDF, 0x8B, 0x2E, 0xE1, 0x97, 0xC9, 0x14, 0xDF, 0xB3, 0xC6, 0x98, 0xF4, - 0x5A, 0x31, 0x8C, 0x67, 0x19, 0x42, 0x2A, 0x1D, 0x09, 0x14, 0x87, 0xBB, 0x1E, 0x53, 0x1E, 0x15, - 0x9D, 0x12, 0xA2, 0x27, 0xED, 0x13, 0x29, 0x46, 0x85, 0xD7, 0x68, 0x0B, 0x13, 0x4E, 0xEC, 0x04, - 0x44, 0x74, 0x60, 0x3F, 0x15, 0xC1, 0x96, 0x33, 0xC6, 0x92, 0x31, 0x9C, 0x61, 0xD0, 0xF0, 0x90, - 0x7B, 0x32, 0xFE, 0xFA, 0x5A, 0x77, 0xBD, 0x9D, 0xB7, 0x53, 0xD1, 0xC9, 0x63, 0x8D, 0x7E, 0xC9, - 0x74, 0xD3, 0x99, 0xD1, 0x9E, 0xB3, 0x8D, 0x4C, 0x05, 0x22, 0x41, 0x73, 0xA3, 0x3E, 0x31, 0xA2, - 0x76, 0xE6, 0x28, 0x73, 0x06, 0x85, 0x62, 0xBF, 0xB3, 0x37, 0x50, 0x02, 0x88, 0x82, 0x1C, 0xDD, - 0x68, 0x68, 0x28, 0x34, 0x5D, 0x3C, 0x3A, 0x74, 0xB2, 0xD7, 0x79, 0xE1, 0xD9, 0xC5, 0x49, 0x38, - 0x89, 0x17, 0x57, 0x80, 0xC5, 0x77, 0x78, 0x9A, 0x14, 0xB1, 0x05, 0x7E, 0xB9, 0xB9, 0xE8, 0x92, - 0xF3, 0xDC, 0x6D, 0xF7, 0xE7, 0x5F, 0x28, 0x41, 0x19, 0x52, 0x9C, 0xF7, 0x64, 0xB1, 0xB1, 0x05, - 0x24, 0xA7, 0x5A, 0xE3, 0xB1, 0x65, 0x92, 0xD7, 0x10, 0xD6, 0x37, 0x40, 0x87, 0x1E, 0xD8, 0x5E, - 0x57, 0x78, 0xC6, 0x0B, 0x40, 0xDD, 0xFB, 0x5E, 0xDC, 0x17, 0xC7, 0xF5, 0x6D, 0x7C, 0xD7, 0x15, - 0xAE, 0xF1, 0x40, 0xE9, 0x26, 0x7B, 0xD7, 0x8C, 0xA4, 0x3A, 0x93, 0x0D, 0xDD, 0x06, 0xBB, 0x50, - 0xD4, 0x51, 0xD8, 0x8F, 0x08, 0xCE, 0x11, 0x3C, 0x55, 0xEE, 0x20, 0x7B, 0x1A, 0xE9, 0x93, 0x37, - 0x44, 0xFE, 0x34, 0x4D, 0x12, 0x38, 0xDB, 0x69, 0xBE, 0xA5, 0x89, 0x63, 0x82, 0x3B, 0x6B, 0xE0, - 0x61, 0x2C, 0x0F, 0x85, 0xFB, 0x88, 0xDE, 0x28, 0x5D, 0xB1, 0x9C, 0xF2, 0x4E, 0x8B, 0x7D, 0x04, - 0x22, 0x98, 0x7C, 0x19, 0x7E, 0x83, 0x01, 0x92, 0x2D, 0xF4, 0x2D, 0xDC, 0x65, 0x07, 0xF2, 0x1D, - 0xF1, 0x9D, 0x0C, 0x3A, 0x3A, 0x60, 0x14, 0x4B, 0xF9, 0x36, 0xC2, 0x60, 0x08, 0x60, 0xC0, 0xCE, - 0x76, 0xD9, 0xA7, 0x3E, 0xFD, 0xB8, 0xC3, 0x1F, 0x7F, 0xDB, 0x15, 0x40, 0xBC, 0x39, 0x93, 0x81, - 0x8C, 0xEE, 0x31, 0x6B, 0xE2, 0x81, 0xD2, 0x6E, 0x6E, 0x64, 0x7A, 0xB6, 0xBC, 0x80, 0xE4, 0xD9, - 0x74, 0x34, 0x23, 0x73, 0x60, 0x4A, 0xDE, 0xCB, 0x83, 0x94, 0xB4, 0x97, 0xA9, 0x3D, 0xCE, 0x9B, - 0xAD, 0x21, 0xCA, 0x0B, 0xA7, 0x33, 0x36, 0x98, 0x63, 0xAE, 0xC8, 0xDD, 0x75, 0xB3, 0xD2, 0x35, - 0x14, 0xF3, 0x6C, 0x0D, 0xF9, 0x2C, 0xE5, 0x06, 0xB8, 0xB3, 0xFA, 0x14, 0x98, 0xA6, 0x9B, 0xC3, - 0xA0, 0xFB, 0x49, 0x96, 0x06, 0xC0, 0x8C, 0xF0, 0xDB, 0x00, 0xB7, 0xDC, 0x82, 0x39, 0x1B, 0x0A, - 0x46, 0x69, 0x2D, 0x07, 0x5A, 0x32, 0x1A, 0x78, 0x39, 0x00, 0xBB, 0x8E, 0x77, 0x1E, 0x03, 0x97, - 0xFC, 0x6E, 0x09, 0xC0, 0x4A, 0xCB, 0x98, 0x9B, 0x7E, 0xF6, 0x5A, 0xAE, 0xA2, 0xAB, 0xC8, 0x00, - 0xFA, 0x9E, 0xC3, 0x95, 0x71, 0x10, 0x80, 0xE5, 0x16, 0x81, 0x68, 0x56, 0x27, 0xAD, 0x02, 0x61, - 0x5C, 0x59, 0xDA, 0x95, 0x4B, 0x3D, 0x5C, 0x61, 0xD0, 0x12, 0x48, 0x97, 0xD8, 0xE7, 0xEF, 0x20, - 0x2D, 0x13, 0x87, 0x92, 0x9D, 0x8B, 0x88, 0x26, 0xF8, 0xF2, 0xB8, 0x98, 0xA3, 0xF1, 0x84, 0x29, - 0x45, 0xC3, 0x63, 0x52, 0xC7, 0xA1, 0xD5, 0xA4, 0x7E, 0x53, 0x38, 0x30, 0x72, 0xDE, 0xB0, 0x9A, - 0xD8, 0x4C, 0x2D, 0x72, 0x1E, 0x8D, 0xA4, 0x6C, 0x6C, 0x35, 0xC7, 0x80, 0x1D, 0xE2, 0xF1, 0xDC, - 0xFD, 0xB4, 0x6A, 0x27, 0xED, 0x2A, 0xFA, 0x69, 0x63, 0x8E, 0xE1, 0x0A, 0xFA, 0xE9, 0xD4, 0x4E, - 0x0E, 0xAA, 0xE8, 0x67, 0x1F, 0xE1, 0x53, 0x45, 0x47, 0x07, 0x08, 0xA0, 0x2A, 0x3A, 0x3A, 0xC4, - 0x95, 0x55, 0xD1, 0xD1, 0x3B, 0x58, 0xDA, 0xE2, 0xBD, 0x1C, 0xC1, 0xBA, 0x16, 0xEF, 0xE5, 0x3D, - 0x2C, 0xAA, 0x02, 0x24, 0x24, 0x6C, 0xAE, 0xA0, 0x9F, 0x16, 0x66, 0x11, 0xAF, 0xA0, 0x1F, 0xC0, - 0xE6, 0x4E, 0x15, 0xF3, 0x01, 0x6C, 0x3E, 0xAC, 0xA2, 0x1F, 0xC0, 0xE6, 0xF6, 0x58, 0x37, 0x17, - 0xEF, 0x08, 0xB0, 0xF9, 0xA0, 0x92, 0x8E, 0x0E, 0x89, 0xFF, 0x54, 0xD1, 0x13, 0xA2, 0x73, 0x35, - 0x73, 0x3A, 0xC2, 0x5D, 0xAB, 0xA4, 0xA7, 0xF7, 0xB8, 0x6F, 0xA5, 0x7B, 0xCA, 0x8F, 0x82, 0x5C, - 0x92, 0xED, 0x22, 0x69, 0xC3, 0x98, 0x98, 0x14, 0x82, 0x63, 0x91, 0x82, 0x85, 0xA2, 0x07, 0xE6, - 0xA6, 0x65, 0x1B, 0x29, 0x24, 0xC1, 0x14, 0x94, 0x84, 0x66, 0xCA, 0x29, 0xED, 0x6A, 0xE5, 0x94, - 0x56, 0x4C, 0x4E, 0x69, 0x2F, 0x4D, 0x4E, 0x69, 0x65, 0xCA, 0x29, 0xAD, 0xAD, 0x9C, 0xB2, 0x95, - 0x53, 0xB6, 0x72, 0xCA, 0x56, 0x4E, 0xD9, 0xCA, 0x29, 0x5B, 0x39, 0x65, 0xD3, 0xE4, 0x94, 0xF6, - 0xE6, 0x65, 0x45, 0xCB, 0x37, 0xC4, 0x14, 0x34, 0x6C, 0x45, 0xCC, 0xDD, 0x78, 0x8D, 0x81, 0xA6, - 0xC3, 0xE5, 0xC6, 0x17, 0x17, 0x78, 0x1C, 0xD8, 0x55, 0x67, 0xE5, 0xE8, 0xA4, 0xDC, 0x52, 0x2F, - 0x99, 0xA3, 0x53, 0x54, 0x30, 0x74, 0x97, 0x55, 0xBA, 0xE7, 0x34, 0xD2, 0x75, 0xA9, 0xEB, 0x99, - 0x48, 0xC3, 0x8C, 0x7D, 0x40, 0x40, 0xA6, 0xD4, 0xE3, 0xCB, 0x28, 0x5C, 0x83, 0xFF, 0x22, 0xC0, - 0x4E, 0xA4, 0xF9, 0x24, 0x08, 0xAC, 0x53, 0x9A, 0xCF, 0x99, 0xCB, 0x9F, 0xB3, 0x08, 0x0F, 0xC9, - 0xBC, 0x64, 0x60, 0xBE, 0x32, 0x45, 0xA6, 0xEF, 0x5C, 0x2F, 0xF6, 0x58, 0xAA, 0xF0, 0x00, 0x50, - 0x77, 0xF0, 0xB0, 0x2F, 0xFB, 0x09, 0x12, 0x88, 0x07, 0xCF, 0xE3, 0xDE, 0x0A, 0xB2, 0x61, 0xEE, - 0xF5, 0x74, 0x54, 0x2F, 0x98, 0x1A, 0xE1, 0x44, 0xFC, 0x55, 0xBF, 0x32, 0x57, 0x1C, 0x3C, 0x7F, - 0x25, 0x72, 0xD4, 0xD9, 0x0E, 0x57, 0x75, 0x40, 0x9C, 0x30, 0x9B, 0xA6, 0x35, 0x60, 0x0A, 0xC3, - 0x69, 0x32, 0x57, 0xE6, 0x84, 0xA2, 0x12, 0x8C, 0x1E, 0x7B, 0x30, 0xA9, 0xC8, 0xB3, 0x47, 0x49, - 0x34, 0xEF, 0x39, 0xB3, 0xEE, 0xA9, 0xA0, 0xA1, 0xC6, 0xEE, 0x9F, 0x31, 0x05, 0xA7, 0x1B, 0x18, - 0xF7, 0x31, 0x0D, 0x27, 0xF6, 0x1C, 0xF4, 0xD8, 0xA0, 0xA4, 0x74, 0xD4, 0x23, 0xF4, 0x84, 0xB7, - 0x4B, 0x94, 0xE0, 0x02, 0x6F, 0x9E, 0x68, 0xE2, 0x22, 0xC7, 0x94, 0xF2, 0x80, 0xB7, 0x5D, 0xB6, - 0xED, 0x58, 0xDF, 0x81, 0x96, 0x3D, 0xCC, 0xF1, 0x74, 0xD8, 0x0C, 0xD3, 0xDF, 0x3D, 0x59, 0x8E, - 0x37, 0x12, 0x09, 0x9E, 0x14, 0x2D, 0xA8, 0x54, 0x24, 0x26, 0x80, 0xB3, 0xC5, 0xAB, 0xF2, 0x01, - 0xCC, 0x2C, 0x5C, 0x04, 0x8E, 0xA6, 0x31, 0xCB, 0x4C, 0xA6, 0xE1, 0x0B, 0xB2, 0xF6, 0x8D, 0xB9, - 0x37, 0xB2, 0x34, 0xA6, 0xA8, 0x23, 0x9D, 0x63, 0x52, 0xAC, 0x7F, 0xEF, 0x34, 0xD5, 0x71, 0x4A, - 0x4E, 0x2B, 0xBC, 0xE9, 0xC3, 0x8B, 0xFA, 0x47, 0xE0, 0x2E, 0x0D, 0x76, 0x65, 0xAA, 0x30, 0xBE, - 0x1B, 0x24, 0xB7, 0x0A, 0xF2, 0x79, 0x7C, 0xBD, 0xC7, 0xE8, 0x00, 0x31, 0xF0, 0x9D, 0x3E, 0xE6, - 0x41, 0x1A, 0xD1, 0x5B, 0xE1, 0x33, 0xA0, 0x61, 0x26, 0x59, 0x93, 0x61, 0xCD, 0xC0, 0x48, 0x44, - 0xBF, 0x2E, 0xFA, 0xE2, 0x61, 0x42, 0x2A, 0x1A, 0x8B, 0x2E, 0x1E, 0x31, 0x57, 0x16, 0x4C, 0x41, - 0xC7, 0x1C, 0x5E, 0xA7, 0x1C, 0xCB, 0xAF, 0x4E, 0x5E, 0xD2, 0xDD, 0x60, 0xD2, 0x1A, 0x85, 0x1D, - 0x50, 0x3E, 0xC0, 0x3A, 0xBC, 0x32, 0x0E, 0xB3, 0x96, 0xCA, 0x74, 0x57, 0x54, 0x60, 0x09, 0x33, - 0x32, 0x53, 0xF5, 0xD2, 0x49, 0x1E, 0x91, 0xA6, 0x48, 0xEA, 0x75, 0xD0, 0x68, 0x8E, 0x27, 0x17, - 0x77, 0x87, 0x74, 0x73, 0x77, 0xD8, 0x6C, 0xBA, 0xBB, 0xAC, 0xD5, 0xA0, 0x0F, 0xF4, 0xC2, 0xC6, - 0xC5, 0x29, 0x04, 0x1C, 0x40, 0xC6, 0x8B, 0xB9, 0xB5, 0x02, 0xF1, 0x86, 0x41, 0x9B, 0x39, 0x03, - 0x1B, 0x16, 0xF2, 0x1C, 0x4B, 0xF2, 0x07, 0x6B, 0x82, 0x4B, 0x32, 0x4D, 0xE6, 0x4C, 0x97, 0xC2, - 0x56, 0x3B, 0x2D, 0xCB, 0x0D, 0x62, 0x65, 0xB1, 0xDB, 0xA8, 0x08, 0xE6, 0x62, 0xAC, 0x0A, 0xDB, - 0x71, 0xDF, 0x1E, 0x17, 0xB6, 0x46, 0xE4, 0x65, 0x46, 0x2C, 0x61, 0x2E, 0x28, 0xE7, 0xE7, 0x9E, - 0x02, 0xA4, 0x82, 0xC3, 0xD8, 0x19, 0xED, 0x17, 0xF1, 0x09, 0x2B, 0x27, 0xEB, 0xAD, 0x1C, 0x8D, - 0x7A, 0x92, 0x97, 0x05, 0x11, 0x78, 0xC5, 0x64, 0xF3, 0x72, 0x38, 0x17, 0x70, 0xBA, 0x42, 0x5D, - 0x13, 0x37, 0xEC, 0x9C, 0x83, 0x58, 0x0F, 0x7C, 0x08, 0xCF, 0xF7, 0x90, 0x33, 0x16, 0x6A, 0xBE, - 0x33, 0x5E, 0x14, 0x45, 0x09, 0x39, 0x25, 0x9E, 0xDE, 0xE7, 0x46, 0x87, 0x2E, 0x8C, 0xA2, 0x53, - 0x1B, 0x30, 0x2F, 0xAE, 0x26, 0x3B, 0x5A, 0x1D, 0xD2, 0x2E, 0xCB, 0xB5, 0x8B, 0x84, 0x81, 0x45, - 0x85, 0xB5, 0x4B, 0xEC, 0x64, 0x5A, 0x52, 0x0B, 0xAD, 0x85, 0x29, 0x32, 0x5B, 0x39, 0x59, 0x4D, - 0x0C, 0x70, 0x42, 0xBF, 0x62, 0x27, 0x9E, 0x28, 0x7A, 0x7E, 0xC2, 0x76, 0xCE, 0x46, 0x16, 0xA6, - 0xE0, 0xC1, 0x0A, 0xB2, 0xCC, 0xCA, 0x77, 0xF4, 0xFF, 0x24, 0x6B, 0xE0, 0xBE, 0x0D, 0x0A, 0xAD, - 0xBE, 0x88, 0xE4, 0x17, 0x95, 0xF8, 0xBC, 0x88, 0x84, 0x16, 0xCA, 0x79, 0x28, 0xF8, 0x80, 0x9C, - 0x47, 0xB5, 0xA1, 0x85, 0xCC, 0xC6, 0x41, 0xE2, 0x00, 0x69, 0x44, 0xAE, 0x33, 0x5C, 0x07, 0x8B, - 0xD4, 0xD8, 0x45, 0x29, 0x49, 0x84, 0x5A, 0x62, 0x62, 0xCF, 0xB8, 0x9B, 0x94, 0x10, 0x7C, 0xC6, - 0x63, 0xAE, 0xE9, 0x42, 0xC2, 0xBB, 0xE7, 0x43, 0x3D, 0x48, 0x1C, 0x4A, 0x61, 0x96, 0xB7, 0x77, - 0x67, 0x37, 0xD3, 0xAE, 0x8E, 0x5D, 0x29, 0x35, 0x86, 0x62, 0x99, 0xEE, 0x0A, 0x99, 0x2F, 0x14, - 0x41, 0x49, 0x14, 0xEA, 0xF5, 0x7A, 0x6C, 0xC7, 0x16, 0x65, 0xDA, 0x5D, 0x0E, 0x02, 0xAA, 0xEF, - 0x30, 0xCF, 0xF7, 0x2C, 0x50, 0xC1, 0x8C, 0xB7, 0x54, 0x5A, 0x12, 0xDF, 0x4A, 0x88, 0x46, 0x4C, - 0x19, 0x42, 0x17, 0xE8, 0x6A, 0x09, 0xF3, 0x24, 0x77, 0x2D, 0x35, 0x94, 0x7C, 0x23, 0x62, 0x53, - 0x50, 0xFB, 0xFB, 0x8D, 0x3B, 0x81, 0x1B, 0x26, 0x4F, 0xB6, 0x7C, 0x43, 0xE3, 0xCE, 0x2E, 0xE8, - 0x5D, 0x86, 0x05, 0xB8, 0x65, 0x6D, 0x9E, 0xC4, 0x44, 0xA0, 0xAD, 0x20, 0xA6, 0xB3, 0x48, 0xA0, - 0x7D, 0x06, 0x25, 0xD3, 0x14, 0x84, 0x4E, 0x18, 0xE0, 0x11, 0xD2, 0x9D, 0x28, 0xD7, 0x2C, 0x4B, - 0x38, 0xC9, 0xAD, 0x8F, 0xD1, 0x76, 0xB3, 0xB0, 0x53, 0xFD, 0x84, 0xF6, 0xE7, 0xF0, 0xB3, 0x26, - 0x66, 0x30, 0x6B, 0x8E, 0x54, 0x3A, 0x9A, 0x4D, 0xBE, 0x08, 0x23, 0xFB, 0x67, 0x5E, 0x53, 0x15, - 0x72, 0x16, 0x0F, 0x0A, 0x3A, 0xE7, 0x6C, 0xD0, 0x12, 0xA5, 0x8A, 0x48, 0xE3, 0x09, 0xE8, 0xF6, - 0x43, 0x69, 0x40, 0x04, 0x96, 0x1C, 0x4D, 0x89, 0x04, 0x05, 0xAF, 0xF1, 0xB2, 0x9C, 0xAE, 0x7C, - 0x97, 0x40, 0x1B, 0x81, 0x69, 0xA1, 0xBA, 0x42, 0xC5, 0x0D, 0x8F, 0xA1, 0x23, 0xD6, 0xF4, 0x48, - 0xE8, 0x84, 0x75, 0x8D, 0x31, 0xE1, 0xB4, 0xAD, 0x97, 0xE8, 0xD7, 0x8D, 0x6E, 0x80, 0xC5, 0xDC, - 0xAF, 0x96, 0x6F, 0x2B, 0xED, 0xF9, 0x32, 0x43, 0xB4, 0x4C, 0x70, 0x27, 0xA6, 0x19, 0x61, 0xC1, - 0x68, 0x42, 0xB5, 0xE8, 0x0D, 0xC1, 0x36, 0x7F, 0xD9, 0xFB, 0x75, 0xEF, 0x37, 0x04, 0x13, 0x77, - 0x1B, 0xAF, 0xD7, 0x88, 0xBA, 0x1A, 0x12, 0x88, 0x55, 0x47, 0xE8, 0xCC, 0x71, 0x31, 0x4C, 0x5B, - 0x72, 0x21, 0xCA, 0xC8, 0x67, 0x91, 0x55, 0x94, 0x8E, 0x7E, 0x29, 0x21, 0xEC, 0x96, 0xB8, 0xEF, - 0x4E, 0x53, 0xDB, 0x8E, 0x96, 0x22, 0x09, 0x47, 0x16, 0x5C, 0x4A, 0xF0, 0x9D, 0xB4, 0x7B, 0x15, - 0xCA, 0xD9, 0x52, 0x70, 0xE8, 0xD7, 0x62, 0x38, 0xF4, 0xEB, 0xAB, 0xC1, 0xA1, 0x5F, 0xE7, 0xC4, - 0xA1, 0x5F, 0xB7, 0x38, 0x94, 0x85, 0x43, 0xBF, 0x15, 0xC3, 0xA1, 0xDF, 0x5E, 0x0D, 0x0E, 0xFD, - 0x36, 0x27, 0x0E, 0xFD, 0xB6, 0xC5, 0xA1, 0x04, 0x0E, 0x99, 0x20, 0x40, 0xA1, 0x78, 0x2E, 0x04, - 0xF5, 0x22, 0x58, 0x54, 0xAC, 0x7A, 0xE8, 0x8B, 0x22, 0x52, 0x5E, 0x54, 0x6A, 0x74, 0xCD, 0xA5, - 0x10, 0x29, 0xDA, 0xF2, 0xF5, 0xD8, 0x1B, 0x4F, 0xCE, 0x82, 0x78, 0xA9, 0x6F, 0x78, 0xE5, 0x12, - 0x11, 0xA3, 0x5F, 0xBC, 0x92, 0x13, 0x55, 0x0B, 0x41, 0x2B, 0xC1, 0x20, 0x26, 0x1D, 0x4B, 0xB3, - 0x06, 0x25, 0x43, 0x06, 0x39, 0xF9, 0x0F, 0x1F, 0xF6, 0x05, 0xA6, 0xAF, 0x5A, 0xF6, 0xF3, 0x9E, - 0x8D, 0xB1, 0x99, 0xD2, 0x02, 0x32, 0x25, 0x51, 0x6F, 0xB6, 0x1C, 0x5D, 0xBC, 0x1A, 0xD2, 0x72, - 0xB9, 0x4F, 0x19, 0xF5, 0x29, 0x49, 0x36, 0x14, 0xE3, 0x97, 0x51, 0x2F, 0x1A, 0x98, 0x8B, 0x7C, - 0xF3, 0x58, 0xEC, 0x94, 0x04, 0x4D, 0x31, 0x5F, 0x51, 0x31, 0x66, 0xD4, 0xB3, 0xB2, 0x2F, 0x6C, - 0x40, 0x11, 0x84, 0x16, 0x6C, 0x0E, 0xE7, 0x94, 0xF5, 0x9D, 0xAB, 0xFF, 0x49, 0xFE, 0x77, 0x85, - 0x71, 0x23, 0x8C, 0x58, 0xFA, 0x5E, 0x7F, 0xD2, 0x35, 0x6F, 0x74, 0xDC, 0x39, 0x68, 0x16, 0x8B, - 0x57, 0xCA, 0xF2, 0x03, 0x42, 0xD5, 0x55, 0xD8, 0xA7, 0xBA, 0xAC, 0xDE, 0x6A, 0x1F, 0x35, 0xDB, - 0xCD, 0xC3, 0xC6, 0xC1, 0xE1, 0x11, 0xAB, 0xEF, 0xBF, 0x6B, 0x1D, 0x1E, 0x35, 0xF7, 0x1B, 0xFB, - 0xCD, 0x0E, 0xDB, 0x6F, 0x1E, 0x1D, 0x1E, 0x1E, 0x1E, 0x34, 0xF6, 0x8F, 0xF6, 0xAB, 0xF0, 0xA3, - 0x0C, 0x86, 0x3C, 0x5D, 0xD1, 0x90, 0x1D, 0x1A, 0xF2, 0x6C, 0x45, 0xA3, 0xED, 0xD7, 0x4E, 0xBA, - 0x78, 0x70, 0xDD, 0x8D, 0x14, 0xEF, 0xCA, 0xBD, 0xB3, 0xAC, 0x6B, 0xCB, 0x1C, 0xDE, 0x59, 0xA7, - 0xFC, 0x5C, 0x60, 0x20, 0xF0, 0x91, 0xCC, 0x89, 0x94, 0xAA, 0x98, 0x36, 0xF7, 0xA4, 0x8B, 0xBB, - 0x71, 0xAD, 0x9B, 0x0C, 0x32, 0x75, 0xC1, 0x54, 0xA1, 0x0D, 0x49, 0xD1, 0xB4, 0xB8, 0x64, 0x52, - 0xAD, 0xE1, 0x48, 0x76, 0x8F, 0xD6, 0xA2, 0xAE, 0xA6, 0x95, 0xB4, 0x0E, 0xCD, 0x88, 0x36, 0x54, - 0x96, 0x3A, 0xEB, 0xA0, 0xFF, 0xC0, 0xC8, 0x55, 0xD5, 0xBC, 0x35, 0x40, 0x40, 0x8F, 0x2F, 0x73, - 0xE6, 0x93, 0x11, 0x70, 0xEE, 0xE7, 0xF4, 0x69, 0x5D, 0x6C, 0x72, 0x80, 0x00, 0x20, 0x4B, 0xEC, - 0x8A, 0xB2, 0xB4, 0x8A, 0x46, 0xC9, 0x20, 0x76, 0xC9, 0x04, 0x17, 0xD6, 0x05, 0x77, 0xB8, 0x0A, - 0xA7, 0x45, 0x44, 0x92, 0xA0, 0xB7, 0xC5, 0xA2, 0x98, 0xEE, 0x35, 0x7E, 0x3C, 0xF7, 0xC6, 0x32, - 0xD9, 0x52, 0xAA, 0xBF, 0x5D, 0xF8, 0x84, 0x95, 0x0D, 0x66, 0x5C, 0x2E, 0xB4, 0x5E, 0xFE, 0x72, - 0xE1, 0x13, 0x95, 0x3F, 0x90, 0x97, 0x6C, 0xD5, 0xDE, 0x29, 0x0C, 0x65, 0xAF, 0x2F, 0xE6, 0xF3, - 0xF2, 0x62, 0xD7, 0x0A, 0x9F, 0xC2, 0x95, 0x4F, 0xAE, 0x16, 0xCA, 0x86, 0xC5, 0xCC, 0xE4, 0x6C, - 0xB1, 0xAB, 0x85, 0x94, 0xD1, 0xC2, 0xEB, 0x85, 0xEB, 0xEB, 0x51, 0xE1, 0x81, 0xD7, 0xFF, 0x16, - 0x02, 0x56, 0x93, 0xBC, 0x78, 0xC0, 0x47, 0xDB, 0x6B, 0x87, 0x2A, 0xFC, 0x79, 0x08, 0x9E, 0xD7, - 0x8A, 0x97, 0x9F, 0xE4, 0x24, 0xD3, 0x81, 0x67, 0x3F, 0x91, 0x87, 0x6E, 0x7F, 0x8A, 0xB6, 0xA0, - 0x7F, 0xDD, 0xF3, 0x35, 0x5E, 0x81, 0x07, 0xD8, 0xE1, 0x12, 0x2C, 0x2F, 0x31, 0x18, 0x94, 0x37, - 0xE1, 0xC9, 0x96, 0xAF, 0xCD, 0xD3, 0x4B, 0xAC, 0x0D, 0x15, 0x92, 0xA5, 0xA2, 0x06, 0x0C, 0xB0, - 0xFE, 0xB8, 0x11, 0x40, 0x61, 0x0E, 0xE4, 0x90, 0x4D, 0x5F, 0x8D, 0x89, 0x57, 0x88, 0xE4, 0x1E, - 0x89, 0x9E, 0x97, 0x58, 0x08, 0xD7, 0x4B, 0x35, 0xD0, 0x96, 0x33, 0xFA, 0x66, 0x25, 0x9C, 0x03, - 0x61, 0x5C, 0x8C, 0xC4, 0xC4, 0x50, 0xC7, 0x25, 0x03, 0x5A, 0x03, 0x53, 0x4F, 0x7C, 0xC2, 0xB3, - 0x8D, 0x3D, 0x9B, 0x7A, 0x81, 0x5C, 0xBA, 0x71, 0x2A, 0xC1, 0x77, 0x0D, 0xC1, 0xAA, 0x6B, 0xF9, - 0xC4, 0x3C, 0x9D, 0x35, 0xF2, 0x73, 0xF7, 0xA2, 0xF0, 0x69, 0x7C, 0xA3, 0x38, 0x0F, 0x7B, 0x30, - 0x1A, 0x7A, 0x5D, 0xCE, 0x77, 0x84, 0x57, 0x23, 0x75, 0x44, 0x24, 0x8F, 0xCF, 0x1C, 0x9B, 0xB2, - 0xEE, 0xBD, 0xF5, 0xC8, 0xD9, 0x85, 0x61, 0xE8, 0xB6, 0x6B, 0xE9, 0x5A, 0xE0, 0xC5, 0x06, 0x40, - 0x78, 0x90, 0x4E, 0xFE, 0xBA, 0x14, 0x50, 0x42, 0xD1, 0x0B, 0x15, 0x2E, 0x45, 0x42, 0x2E, 0xFA, - 0x3E, 0x3E, 0x1F, 0x5B, 0xA6, 0x4F, 0x35, 0xA6, 0x65, 0xD0, 0x00, 0x6E, 0x91, 0xA9, 0x95, 0x11, - 0x5C, 0x96, 0x2E, 0xBC, 0x94, 0x11, 0x60, 0x0A, 0xDB, 0x7C, 0x73, 0xD9, 0xF5, 0x7E, 0x19, 0xD9, - 0xAD, 0xFC, 0x8D, 0x5C, 0x88, 0xC9, 0x45, 0xD7, 0x54, 0xEC, 0x4A, 0xA8, 0xE0, 0x6B, 0xF6, 0xF4, - 0x44, 0x2A, 0x48, 0x0F, 0xBA, 0x44, 0x4E, 0x42, 0xF8, 0x95, 0xCE, 0x13, 0x99, 0xCC, 0x7B, 0x65, - 0xF0, 0x81, 0x77, 0xBC, 0x5F, 0xC2, 0x8C, 0x9C, 0xA6, 0x38, 0x0B, 0xC5, 0x18, 0x89, 0x43, 0xB8, - 0xE7, 0x46, 0xDC, 0x69, 0x23, 0x06, 0x30, 0xAC, 0x56, 0x0F, 0xDC, 0x04, 0x35, 0x9A, 0x32, 0x7C, - 0x8C, 0x42, 0xC1, 0x14, 0x43, 0x85, 0xA6, 0xC8, 0x5F, 0x30, 0x41, 0xB6, 0xA8, 0x41, 0xC9, 0x19, - 0x3C, 0x22, 0x9E, 0x33, 0xC7, 0x09, 0xB2, 0x0C, 0x2D, 0xE7, 0x6A, 0x10, 0x14, 0xC1, 0xDC, 0x0D, - 0xA7, 0x26, 0x2A, 0x8D, 0xCA, 0x09, 0x53, 0xF4, 0xD3, 0x3F, 0xBB, 0xFE, 0xBD, 0xE7, 0x28, 0x54, - 0xC5, 0xF3, 0x9F, 0x89, 0x7B, 0x04, 0x3E, 0xB3, 0x5D, 0xF8, 0x6D, 0x9A, 0x0A, 0x93, 0x3C, 0x0B, - 0x03, 0x6F, 0xBA, 0xB7, 0xBD, 0x49, 0xAE, 0xD0, 0x90, 0x1B, 0x85, 0xF9, 0xF9, 0xA0, 0x3B, 0x2A, - 0x80, 0x83, 0x65, 0xB8, 0x03, 0xC7, 0xD9, 0x09, 0x3F, 0x1B, 0x41, 0x0F, 0xCF, 0xEC, 0x69, 0xC4, - 0x4D, 0x19, 0xD5, 0x24, 0xEA, 0x86, 0x12, 0x13, 0x23, 0xEF, 0x56, 0x45, 0x5E, 0x5E, 0xD9, 0x16, - 0xF0, 0x9B, 0x51, 0x6C, 0xD4, 0x5D, 0x8A, 0x30, 0xF2, 0x4D, 0xF1, 0x02, 0x35, 0x09, 0xEB, 0x80, - 0x37, 0xD8, 0x17, 0xCB, 0xE3, 0xC7, 0x14, 0xA9, 0x15, 0xAE, 0x93, 0xB6, 0x9C, 0x22, 0x8E, 0x8C, - 0x27, 0xE5, 0xD9, 0x95, 0x16, 0x2C, 0x59, 0xE1, 0x74, 0x84, 0xB1, 0x86, 0x19, 0x37, 0x7F, 0xCC, - 0x43, 0x90, 0x6D, 0xA0, 0xD2, 0x57, 0x24, 0xD9, 0x69, 0xB1, 0x88, 0xDD, 0x8D, 0x25, 0xF0, 0x76, - 0x06, 0x81, 0xB3, 0x42, 0x59, 0x78, 0xD3, 0x09, 0xDD, 0x80, 0x2E, 0xBA, 0xBD, 0xB3, 0x24, 0x9D, - 0xC3, 0xA3, 0x35, 0x25, 0x73, 0x98, 0x59, 0x0A, 0x95, 0x2B, 0x9A, 0x56, 0x94, 0xC0, 0x25, 0x85, - 0x14, 0x25, 0xEF, 0x2D, 0xF1, 0x95, 0x21, 0xBE, 0x15, 0x2A, 0xD6, 0x12, 0x71, 0xF3, 0xA5, 0xEC, - 0x83, 0x34, 0x29, 0x1B, 0xF1, 0xA8, 0xB0, 0xE0, 0xBC, 0x3C, 0xEC, 0x9E, 0x2D, 0x30, 0x07, 0x18, - 0xDC, 0x1B, 0x51, 0xFC, 0x38, 0x21, 0x76, 0x5C, 0x80, 0x76, 0xFD, 0x71, 0xF0, 0xB2, 0x22, 0x5F, - 0x16, 0x27, 0xCB, 0x2E, 0xB3, 0xA9, 0x91, 0x4A, 0x8D, 0x44, 0x3E, 0x58, 0x3A, 0x57, 0xC4, 0xD7, - 0x84, 0xD7, 0xE8, 0x67, 0xE1, 0x30, 0xAE, 0xE9, 0x84, 0x96, 0xBB, 0xCC, 0x1D, 0xE1, 0xE9, 0x83, - 0xB9, 0x1D, 0x10, 0xC9, 0x50, 0xCF, 0xA3, 0x10, 0x14, 0xC0, 0xE4, 0xD7, 0xE9, 0x53, 0x31, 0x53, - 0xB6, 0x3E, 0x58, 0x9E, 0xA7, 0x5B, 0x80, 0xB9, 0x41, 0xF2, 0xE0, 0xF2, 0x36, 0x11, 0xD1, 0xC3, - 0xCA, 0x2C, 0x22, 0x74, 0xAF, 0xB1, 0x1A, 0xD2, 0x0E, 0x5C, 0x4A, 0x02, 0xE3, 0x7C, 0x6D, 0x1E, - 0x93, 0x18, 0xB9, 0xB2, 0xBD, 0x30, 0x65, 0x7F, 0x82, 0xE3, 0x43, 0x04, 0x5B, 0x51, 0xB8, 0x38, - 0x48, 0x7F, 0xC1, 0xD2, 0xD8, 0x3D, 0x1F, 0x60, 0x2E, 0x6A, 0x71, 0x66, 0x61, 0x34, 0x97, 0x3C, - 0x37, 0xC2, 0xF4, 0xD6, 0xE4, 0xFF, 0x14, 0xF5, 0x71, 0x42, 0x5F, 0xA9, 0x1F, 0x90, 0x06, 0x0F, - 0x97, 0xE8, 0x24, 0x18, 0x22, 0xD8, 0x5C, 0x8E, 0x82, 0x41, 0xEB, 0xAD, 0xB3, 0xE0, 0xD2, 0x09, - 0xA9, 0x7A, 0x67, 0xC1, 0x6B, 0xC5, 0xDB, 0x43, 0xAB, 0x32, 0x1A, 0xCF, 0xB6, 0x3E, 0x83, 0x2F, - 0xE4, 0x33, 0x18, 0x50, 0x50, 0x41, 0xBF, 0xC1, 0xC2, 0xDB, 0x13, 0xDD, 0xDC, 0xCA, 0xDD, 0x0C, - 0x27, 0xA7, 0x52, 0xBA, 0xAB, 0xE1, 0xE4, 0xFB, 0x35, 0x73, 0x37, 0xDC, 0x6F, 0x36, 0x9A, 0xEF, - 0x9B, 0xED, 0xF7, 0xFB, 0xEF, 0xDE, 0xB3, 0x7A, 0xAB, 0x79, 0xD0, 0x68, 0x1D, 0x1D, 0x34, 0x0F, - 0xDE, 0x1D, 0xB6, 0x58, 0xEB, 0xE0, 0x10, 0xBE, 0x3B, 0x7A, 0x5F, 0xAD, 0xAF, 0xE1, 0x0A, 0xC6, - 0x0B, 0x1C, 0x0D, 0x57, 0x30, 0x54, 0x01, 0x2F, 0xC3, 0xCC, 0x59, 0x94, 0xB2, 0x51, 0xCF, 0x37, - 0xE3, 0xAD, 0x8B, 0x61, 0x86, 0x8B, 0xE1, 0xB4, 0x10, 0x59, 0xB9, 0x9B, 0x61, 0x30, 0xC4, 0x12, - 0x5C, 0x0D, 0x97, 0x3D, 0xFB, 0xE8, 0x18, 0xCB, 0x71, 0x39, 0x5C, 0xF6, 0x0A, 0xE2, 0xA3, 0x6C, - 0xBC, 0xEB, 0x61, 0xF4, 0xE8, 0xFA, 0x61, 0x3C, 0x10, 0x37, 0xB3, 0x4E, 0x7B, 0x9F, 0x3B, 0x8F, - 0x58, 0xA7, 0x35, 0x56, 0xA7, 0x5D, 0x3C, 0x5C, 0x59, 0x9D, 0xF6, 0x60, 0x0E, 0x2F, 0x53, 0xA7, - 0xDD, 0xA5, 0xD1, 0x51, 0xF0, 0xF6, 0x6D, 0x42, 0xEE, 0x20, 0x4F, 0xC9, 0x1B, 0x77, 0xAA, 0x60, - 0x3B, 0x65, 0x4D, 0x9B, 0x2A, 0xD7, 0xFE, 0x95, 0x12, 0x96, 0x88, 0x7A, 0xED, 0x42, 0x9A, 0xF7, - 0xF0, 0xF2, 0x44, 0x51, 0x31, 0xFD, 0x87, 0x54, 0x88, 0xE3, 0xFD, 0xF8, 0x22, 0x2B, 0x88, 0x19, - 0x2B, 0x15, 0xFF, 0x7A, 0x6A, 0xB8, 0x8B, 0x0D, 0x9D, 0x37, 0x9D, 0xC4, 0x87, 0x02, 0xB5, 0x65, - 0x52, 0x33, 0x74, 0x16, 0x2C, 0xB3, 0x16, 0xE7, 0xF2, 0xB9, 0x1C, 0xA0, 0x50, 0xA9, 0xB5, 0xA9, - 0x65, 0x37, 0x33, 0x92, 0x75, 0xE6, 0x0E, 0x97, 0x48, 0xE6, 0x99, 0xD2, 0x71, 0x3E, 0xD3, 0x8A, - 0x52, 0x31, 0x6B, 0x61, 0x86, 0xCE, 0x0A, 0x6A, 0xAB, 0x09, 0x14, 0xC8, 0xAD, 0xAF, 0x56, 0xC2, - 0xDF, 0x3A, 0x9E, 0xB7, 0xB3, 0xF4, 0x4A, 0xAB, 0x2F, 0x87, 0x55, 0xB9, 0x1F, 0x4D, 0x74, 0x4D, - 0x54, 0x91, 0xF1, 0xB3, 0xE5, 0x7A, 0x73, 0x94, 0xF2, 0x59, 0x42, 0x09, 0xF1, 0xE0, 0x1F, 0xCE, - 0xE8, 0x78, 0x51, 0x2F, 0x8E, 0xA3, 0x52, 0x56, 0xAE, 0xD2, 0x96, 0xAE, 0x0C, 0x28, 0x96, 0x18, - 0xCD, 0x9E, 0xD5, 0xD1, 0xA2, 0xB6, 0xAF, 0xF2, 0x3E, 0x23, 0x2F, 0x8C, 0x85, 0x3D, 0xCB, 0x59, - 0x33, 0x2C, 0xC4, 0x19, 0xBD, 0x34, 0x16, 0xE6, 0xDE, 0x79, 0x64, 0xC1, 0x71, 0x71, 0x3C, 0x14, - 0x1D, 0xFD, 0x70, 0x78, 0x88, 0x45, 0xDA, 0xD7, 0x0B, 0x0F, 0x71, 0x46, 0x9B, 0xC6, 0x0D, 0x25, - 0x14, 0x17, 0xC7, 0x42, 0xD1, 0xD1, 0x0F, 0x89, 0x85, 0xBD, 0x9F, 0x2B, 0xC2, 0xC3, 0xAC, 0x2A, - 0xEA, 0x73, 0xE0, 0x61, 0xE1, 0x6A, 0xE9, 0x33, 0x50, 0xF1, 0x5D, 0xA9, 0x2B, 0xE0, 0x4A, 0x50, - 0x91, 0x40, 0x59, 0x0D, 0x32, 0x62, 0x57, 0x3F, 0x10, 0x3A, 0x4E, 0x0A, 0xC8, 0x2F, 0x99, 0x29, - 0xD2, 0x40, 0x25, 0xCE, 0x66, 0x98, 0xD1, 0xE6, 0x30, 0xC5, 0x18, 0x14, 0x17, 0xC1, 0xC3, 0x68, - 0x47, 0x3F, 0x24, 0x16, 0x2E, 0x9D, 0x29, 0xCE, 0x81, 0x87, 0x1B, 0xC5, 0x14, 0x13, 0xA0, 0xAC, - 0x06, 0x19, 0x5F, 0x86, 0x29, 0x2E, 0xF0, 0x4A, 0x11, 0x93, 0xC0, 0xC6, 0xDB, 0x7B, 0x5A, 0xCB, - 0xB2, 0xF7, 0xB4, 0xCA, 0xDA, 0x7B, 0xDA, 0x9B, 0x6A, 0xEF, 0x69, 0xBD, 0x56, 0x7B, 0x4F, 0x6B, - 0x6B, 0xEF, 0xA9, 0xC0, 0xDE, 0xD3, 0xAA, 0xCA, 0xDE, 0xD3, 0xFA, 0x31, 0xED, 0x3D, 0xAD, 0xAD, - 0xBD, 0xA7, 0x12, 0x7B, 0x4F, 0xAB, 0x2A, 0x7B, 0x4F, 0xEB, 0xC7, 0xB4, 0xF7, 0xB4, 0xB6, 0xF6, - 0x9E, 0x0A, 0xEC, 0x3D, 0xAD, 0xAA, 0xEC, 0x3D, 0xAD, 0x1F, 0xD5, 0xDE, 0xD3, 0xDA, 0xDA, 0x7B, - 0xAA, 0xB2, 0xF7, 0xB4, 0xAA, 0xB3, 0xF7, 0xB4, 0x7E, 0x4C, 0x7B, 0x4F, 0x6B, 0x6B, 0xEF, 0xA9, - 0xC0, 0xDE, 0xD3, 0xAA, 0xCA, 0xDE, 0xD3, 0xFA, 0x51, 0xED, 0x3D, 0xAD, 0xAD, 0xBD, 0xA7, 0x2A, - 0x7B, 0x4F, 0xAB, 0x3A, 0x7B, 0x4F, 0x6B, 0x6B, 0xEF, 0x59, 0x37, 0x7B, 0x4F, 0x7B, 0x59, 0xF6, - 0x9E, 0x76, 0x59, 0x7B, 0x4F, 0x67, 0x53, 0xED, 0x3D, 0xED, 0xD7, 0x6A, 0xEF, 0x69, 0x6F, 0xED, - 0x3D, 0x15, 0xD8, 0x7B, 0xDA, 0x55, 0xD9, 0x7B, 0xDA, 0x3F, 0xA6, 0xBD, 0xA7, 0xBD, 0xB5, 0xF7, - 0x54, 0x62, 0xEF, 0x69, 0x57, 0x65, 0xEF, 0x69, 0xFF, 0x98, 0xF6, 0x9E, 0xF6, 0xD6, 0xDE, 0x53, - 0x81, 0xBD, 0xA7, 0x5D, 0x95, 0xBD, 0xA7, 0xFD, 0xA3, 0xDA, 0x7B, 0xDA, 0x5B, 0x7B, 0x4F, 0x55, - 0xF6, 0x9E, 0x76, 0x75, 0xF6, 0x9E, 0xF6, 0x8F, 0x69, 0xEF, 0x69, 0x6F, 0xED, 0x3D, 0x15, 0xD8, - 0x7B, 0xDA, 0x55, 0xD9, 0x7B, 0xDA, 0x3F, 0xAA, 0xBD, 0xA7, 0xBD, 0xB5, 0xF7, 0x54, 0x65, 0xEF, - 0x69, 0x57, 0x67, 0xEF, 0x69, 0x6F, 0xED, 0x3D, 0xEB, 0x66, 0xEF, 0xE9, 0x2C, 0xCB, 0xDE, 0xD3, - 0x29, 0x6B, 0xEF, 0xD9, 0xDF, 0x54, 0x7B, 0x4F, 0xE7, 0xB5, 0xDA, 0x7B, 0x3A, 0x5B, 0x7B, 0x4F, - 0x05, 0xF6, 0x9E, 0x4E, 0x55, 0xF6, 0x9E, 0xCE, 0x8F, 0x69, 0xEF, 0xE9, 0x6C, 0xED, 0x3D, 0x95, - 0xD8, 0x7B, 0x3A, 0x55, 0xD9, 0x7B, 0x3A, 0x3F, 0xA6, 0xBD, 0xA7, 0xB3, 0xB5, 0xF7, 0x54, 0x60, - 0xEF, 0xE9, 0x54, 0x65, 0xEF, 0xE9, 0xFC, 0xA8, 0xF6, 0x9E, 0xCE, 0xD6, 0xDE, 0x53, 0x95, 0xBD, - 0xA7, 0x53, 0x9D, 0xBD, 0xA7, 0xF3, 0x63, 0xDA, 0x7B, 0x3A, 0x5B, 0x7B, 0x4F, 0x05, 0xF6, 0x9E, - 0x4E, 0x55, 0xF6, 0x9E, 0xCE, 0x8F, 0x6A, 0xEF, 0xE9, 0x6C, 0xED, 0x3D, 0x55, 0xD9, 0x7B, 0x3A, - 0xD5, 0xD9, 0x7B, 0x3A, 0xAF, 0xC6, 0xDE, 0x93, 0x97, 0x23, 0x68, 0x46, 0xAF, 0xD2, 0x06, 0x14, - 0xE6, 0x44, 0x1B, 0x72, 0xEF, 0x86, 0xBB, 0xAE, 0x32, 0xE4, 0xD7, 0xBA, 0xEB, 0x61, 0xE1, 0x4A, - 0xAA, 0x10, 0x30, 0x97, 0x89, 0x68, 0x76, 0x5A, 0xA8, 0x58, 0xD2, 0xB7, 0x42, 0xE6, 0xA1, 0xE0, - 0x39, 0xA6, 0xD8, 0x17, 0xC6, 0x8D, 0x1B, 0x77, 0x88, 0x53, 0x9C, 0x3D, 0x52, 0xAA, 0x05, 0x29, - 0x69, 0x21, 0xCA, 0xEE, 0x7B, 0xF6, 0xAE, 0xDD, 0xDE, 0x9D, 0xDD, 0xB0, 0x5B, 0x4A, 0x0E, 0xFB, - 0x41, 0x27, 0x74, 0xC3, 0x24, 0x56, 0xD0, 0xF6, 0x0C, 0x2D, 0x42, 0xB5, 0x2A, 0x4C, 0x46, 0x05, - 0xCC, 0x45, 0x85, 0x33, 0x75, 0xD1, 0x0C, 0x1D, 0x4F, 0x1D, 0xE3, 0x94, 0xAF, 0xCC, 0x81, 0x95, - 0x5F, 0x5B, 0x4E, 0xE6, 0xEF, 0xA2, 0x85, 0x62, 0xDA, 0x78, 0x47, 0x31, 0xDD, 0xB1, 0xEE, 0x45, - 0x4A, 0x1E, 0xE0, 0x8A, 0x99, 0x82, 0x39, 0xAA, 0x35, 0x91, 0x4A, 0x0B, 0x53, 0xED, 0xB6, 0x3E, - 0xFF, 0x49, 0xB9, 0xE0, 0xC7, 0x02, 0x9B, 0x5C, 0xD6, 0x6A, 0x36, 0x0F, 0x76, 0xE1, 0xE7, 0xBB, - 0x7D, 0xFC, 0x79, 0x44, 0x3F, 0xDF, 0xE3, 0xCF, 0x56, 0x7B, 0x5F, 0x24, 0x98, 0x6F, 0x36, 0x82, - 0x46, 0xAD, 0x76, 0xA7, 0x29, 0x33, 0xD5, 0xCB, 0x34, 0xBD, 0x86, 0xF5, 0x44, 0x55, 0x19, 0xF0, - 0x5B, 0xAA, 0x73, 0xE1, 0x8A, 0xAA, 0x28, 0xF0, 0x1C, 0xC6, 0x37, 0x35, 0x4A, 0x7A, 0x8A, 0x49, - 0xEF, 0x3C, 0x45, 0x37, 0x2C, 0x47, 0x56, 0x53, 0x90, 0x73, 0x85, 0xDE, 0x9F, 0xF7, 0x14, 0xC3, - 0x10, 0xBB, 0x15, 0xCC, 0xA8, 0xC1, 0xAE, 0x75, 0xF8, 0xD2, 0x3D, 0x66, 0x4D, 0x7C, 0xB9, 0xDD, - 0x8C, 0x56, 0x6B, 0x10, 0x35, 0x58, 0x08, 0x76, 0x30, 0x9E, 0x47, 0xF5, 0x1A, 0x2C, 0xE0, 0x20, - 0x8E, 0xAE, 0x69, 0xDC, 0xC4, 0xF7, 0x71, 0xAE, 0x54, 0xAE, 0x45, 0x37, 0x19, 0x22, 0x0A, 0x1B, - 0x5B, 0x1A, 0xDF, 0xAC, 0xD4, 0x61, 0xA9, 0x16, 0xC4, 0x79, 0x28, 0xA1, 0x7A, 0x23, 0x22, 0xF5, - 0x18, 0x6F, 0x7A, 0x6F, 0x01, 0x15, 0x8C, 0x83, 0xD6, 0xB9, 0x1C, 0x37, 0x35, 0xB9, 0x64, 0x7A, - 0x22, 0xC9, 0x48, 0x61, 0x14, 0x87, 0xBB, 0xDC, 0xBB, 0xB3, 0x10, 0x51, 0x64, 0x5E, 0x38, 0xAA, - 0xEA, 0x7A, 0x8B, 0x8F, 0x61, 0xD7, 0x0B, 0x9D, 0x09, 0x41, 0xC3, 0x62, 0x79, 0x24, 0x8B, 0xD6, - 0x9D, 0x79, 0x59, 0x60, 0x5C, 0x5B, 0x4F, 0xA7, 0x01, 0x99, 0x85, 0x00, 0x29, 0x04, 0x0D, 0xCC, - 0x4C, 0x09, 0x44, 0x1A, 0xB6, 0x06, 0xAA, 0x33, 0x1F, 0x4A, 0x81, 0x26, 0x1F, 0x36, 0x88, 0xB7, - 0xE3, 0xF8, 0xB1, 0x55, 0x5B, 0x76, 0xFA, 0xC8, 0x02, 0x8F, 0xD3, 0x06, 0xF9, 0xF0, 0x0F, 0xF5, - 0x3A, 0xAB, 0x07, 0xFF, 0x02, 0x71, 0x8C, 0x3B, 0x03, 0x4C, 0x1C, 0x2D, 0xE8, 0x2D, 0xF2, 0x75, - 0xBD, 0x9E, 0xE8, 0x31, 0x42, 0x68, 0x1A, 0xC8, 0xAA, 0xBA, 0xC6, 0x86, 0x8A, 0x9D, 0x5A, 0xD0, - 0x39, 0xE3, 0x7A, 0x27, 0xF3, 0x3E, 0x07, 0x61, 0x68, 0xDB, 0x41, 0xFA, 0xC0, 0x22, 0xC7, 0xF3, - 0x4F, 0xD9, 0x17, 0x3D, 0xC9, 0x23, 0xBB, 0xD7, 0x0B, 0x3A, 0x2E, 0x75, 0x1A, 0x87, 0xCD, 0x52, - 0x87, 0x8A, 0x67, 0xFD, 0xCE, 0xD8, 0x70, 0x21, 0xED, 0xC5, 0xE0, 0xEB, 0x3B, 0xA2, 0x34, 0x89, - 0x3C, 0xB0, 0xED, 0xC8, 0x1B, 0x8B, 0x9F, 0xDA, 0xE9, 0x98, 0x9D, 0x86, 0x1C, 0xB9, 0x1C, 0x38, - 0x5C, 0x7D, 0xCA, 0x28, 0xD9, 0x0C, 0x77, 0x2E, 0x39, 0xF0, 0x9C, 0xD2, 0x68, 0xB2, 0xAB, 0xF3, - 0xE3, 0x40, 0x6A, 0x1E, 0x41, 0x87, 0x4F, 0xB0, 0xD8, 0xAB, 0xF3, 0x19, 0xE9, 0xD5, 0xF7, 0xBA, - 0x28, 0x28, 0xCF, 0xCC, 0x8F, 0x7E, 0x8E, 0x25, 0x8E, 0x40, 0xEA, 0xD6, 0x0D, 0xF6, 0xC0, 0xE1, - 0x4F, 0xD8, 0x7A, 0xDD, 0xE1, 0xE1, 0x30, 0x1A, 0x7C, 0x7D, 0xCB, 0xC7, 0x8A, 0x6E, 0xEA, 0xE6, - 0x70, 0xC6, 0x48, 0x16, 0xFB, 0x2B, 0xB4, 0xCE, 0x14, 0xCB, 0x5F, 0x34, 0xA5, 0x6B, 0x14, 0xC5, - 0xCE, 0xC2, 0x9C, 0xA3, 0x6E, 0x98, 0xDE, 0x35, 0xFA, 0xFD, 0x4C, 0xA6, 0x14, 0x69, 0xCC, 0x56, - 0x91, 0x07, 0x36, 0x73, 0xE2, 0x2B, 0xCC, 0x09, 0x7B, 0x5D, 0xC7, 0x93, 0x81, 0xED, 0xB1, 0xAB, - 0x5E, 0x9C, 0x56, 0xD5, 0x08, 0x30, 0x48, 0xCE, 0x52, 0x1E, 0x41, 0xB4, 0xA3, 0x0A, 0x58, 0xD3, - 0x29, 0x5B, 0x37, 0x2E, 0x63, 0xEB, 0x90, 0x5B, 0x43, 0x47, 0xB1, 0x47, 0xBA, 0x7A, 0xCB, 0x87, - 0xB0, 0xC6, 0x73, 0xC7, 0xB2, 0x05, 0x57, 0xC9, 0xC3, 0x48, 0x42, 0xBC, 0x64, 0xF3, 0xDA, 0xC9, - 0xA7, 0xF0, 0x09, 0x13, 0x8F, 0xF2, 0x15, 0xFC, 0x78, 0xB9, 0x82, 0xA9, 0x2E, 0x53, 0xE7, 0x19, - 0x57, 0xD9, 0x35, 0x39, 0xEB, 0x20, 0xBB, 0xEC, 0xCC, 0x3D, 0x88, 0x27, 0xC5, 0x6F, 0xD6, 0x4E, - 0xBE, 0xF5, 0x8B, 0x25, 0xAA, 0x9F, 0xAE, 0x4C, 0x70, 0xF1, 0x6D, 0xAE, 0x96, 0x30, 0xC5, 0xEE, - 0x7C, 0x2D, 0x81, 0x53, 0xFC, 0xF5, 0x76, 0xAE, 0x96, 0xFB, 0xB5, 0x93, 0xFF, 0xAE, 0x00, 0xAE, - 0xE4, 0x37, 0xCE, 0xCF, 0xC3, 0x5F, 0x2D, 0xF5, 0xF5, 0xC5, 0xEE, 0x3F, 0x5B, 0xBE, 0xC3, 0x26, - 0xDB, 0xCC, 0x1C, 0xDA, 0x67, 0xA9, 0x7D, 0x81, 0x42, 0x07, 0x0C, 0x58, 0xA4, 0x53, 0x96, 0x94, - 0x3A, 0x70, 0xF8, 0x1F, 0x3E, 0x37, 0xD5, 0x67, 0xD2, 0xD9, 0x04, 0x56, 0x28, 0x46, 0x84, 0x77, - 0x81, 0x54, 0x61, 0xEB, 0x6A, 0x84, 0x48, 0xBF, 0xF5, 0xD7, 0x89, 0x3C, 0x85, 0x6C, 0xE4, 0x2C, - 0x40, 0xBB, 0xB6, 0xDD, 0xE7, 0x1E, 0x26, 0xA3, 0x76, 0x33, 0xCF, 0xE7, 0xC5, 0xCE, 0x9E, 0xC2, - 0xE7, 0x8F, 0xE2, 0x7B, 0x16, 0x9C, 0x8B, 0xB7, 0xDC, 0xE4, 0x4F, 0x8A, 0x01, 0xD8, 0x0D, 0x9F, - 0xF1, 0xA0, 0x64, 0xF2, 0x49, 0xC1, 0x42, 0x2F, 0x8B, 0x9C, 0x24, 0xC9, 0x29, 0x14, 0xDF, 0xE8, - 0xC5, 0x72, 0xE5, 0x4B, 0x24, 0xFE, 0x19, 0x4F, 0x06, 0x12, 0x2C, 0x90, 0x17, 0x31, 0x58, 0x2B, - 0xE8, 0x1A, 0xED, 0x23, 0x86, 0x72, 0x05, 0xAA, 0x1E, 0x24, 0x6E, 0x3C, 0xEF, 0x32, 0x9C, 0x26, - 0x56, 0xA4, 0xC3, 0x9A, 0x95, 0x80, 0xB9, 0x9E, 0xC7, 0xC7, 0x36, 0x55, 0xCE, 0x02, 0x6C, 0x33, - 0x91, 0x0C, 0xE0, 0xCF, 0x37, 0x9F, 0xAD, 0x31, 0x7F, 0xC3, 0x4C, 0xEE, 0x3D, 0x59, 0xCE, 0xC3, - 0x2E, 0xE8, 0x41, 0x20, 0x12, 0x29, 0xD8, 0xD5, 0x2E, 0x7E, 0xED, 0xE0, 0x12, 0x69, 0xAC, 0x08, - 0x6E, 0x8B, 0x23, 0x5E, 0x2B, 0x5C, 0xFF, 0xB3, 0xE2, 0xC4, 0xFA, 0xF9, 0x84, 0x50, 0xDC, 0x91, - 0xA8, 0x94, 0xF9, 0x3B, 0x7A, 0x18, 0x45, 0x05, 0x68, 0x21, 0x48, 0xF6, 0x1C, 0x6B, 0xA0, 0x1B, - 0xFC, 0xCE, 0x7A, 0xE0, 0x05, 0x7C, 0xC3, 0x72, 0xEF, 0x5E, 0xA6, 0x4B, 0xB4, 0x49, 0x79, 0x55, - 0x8E, 0xC3, 0x68, 0xA0, 0xE3, 0x72, 0x5B, 0xB0, 0x78, 0xA9, 0x86, 0x49, 0x89, 0x51, 0xE2, 0xA1, - 0x96, 0x33, 0x54, 0x4C, 0xFD, 0x4F, 0xA1, 0x5B, 0x8C, 0x14, 0x17, 0x93, 0xD6, 0x5B, 0x8E, 0x6D, - 0x91, 0xF9, 0x08, 0xB8, 0xA9, 0x39, 0xEC, 0x7B, 0x0E, 0x57, 0xC6, 0xC4, 0x37, 0x63, 0xA2, 0x8E, - 0xA2, 0xAA, 0x68, 0x98, 0xDE, 0x15, 0x09, 0xF2, 0x75, 0x92, 0x77, 0x1C, 0x8E, 0xBD, 0x32, 0x24, - 0x4C, 0xEA, 0x5D, 0xF5, 0x5D, 0xC0, 0x60, 0x99, 0xEF, 0x9E, 0xD9, 0x72, 0xE1, 0x1E, 0x2E, 0x3C, - 0x8A, 0x8E, 0x80, 0xD5, 0xCF, 0xAC, 0xCE, 0x44, 0xB6, 0x7D, 0xCE, 0xFA, 0xB6, 0xE2, 0x3C, 0x5C, - 0xFA, 0xA6, 0x80, 0x50, 0x6D, 0x8E, 0x8A, 0x16, 0x55, 0x96, 0x80, 0x28, 0x86, 0xD1, 0x45, 0x38, - 0x56, 0xD6, 0xCD, 0xD8, 0xBB, 0x22, 0x84, 0x58, 0xE2, 0x1A, 0x22, 0x07, 0xB5, 0x0B, 0xD7, 0x21, - 0x9F, 0xDD, 0x4F, 0x05, 0x85, 0xC9, 0x2B, 0x63, 0x00, 0xD5, 0x1E, 0x50, 0x24, 0x2B, 0xB8, 0x1E, - 0x1C, 0x10, 0xDF, 0x6C, 0x20, 0x36, 0x8E, 0x86, 0x23, 0x7A, 0x42, 0xA7, 0x94, 0x78, 0xB6, 0x82, - 0x43, 0x6A, 0x7A, 0x1A, 0x2F, 0x71, 0x4C, 0xC9, 0x3A, 0xCB, 0xA2, 0x84, 0x4B, 0x8C, 0x01, 0xD0, - 0x01, 0xF6, 0xA4, 0x1B, 0x06, 0x9A, 0xBA, 0xE5, 0x64, 0xB9, 0x46, 0x8C, 0xC2, 0xA7, 0x09, 0x6B, - 0x68, 0x5F, 0xC7, 0x66, 0x26, 0xE0, 0x2B, 0xB3, 0x6C, 0xAC, 0x39, 0xEC, 0x9B, 0xBA, 0xF7, 0x5C, - 0x5E, 0x17, 0x5A, 0xEF, 0xB3, 0x08, 0x77, 0xCB, 0x77, 0x79, 0xD7, 0x75, 0x75, 0xD7, 0xFB, 0x62, - 0x3D, 0x9D, 0x05, 0x1B, 0x5A, 0xB2, 0x32, 0x77, 0x61, 0x34, 0x2E, 0x8C, 0xCA, 0xD1, 0x59, 0x81, - 0xA4, 0x15, 0xFC, 0x59, 0xA2, 0x4E, 0xE5, 0x22, 0x18, 0x1C, 0x1F, 0xFD, 0x85, 0x4E, 0x3A, 0xC2, - 0xE2, 0xB0, 0x9C, 0xF6, 0x04, 0x04, 0x37, 0x9F, 0xBA, 0xA2, 0xC2, 0xCA, 0x34, 0x0A, 0x83, 0xDC, - 0xA4, 0x8F, 0xE1, 0xB4, 0x7A, 0x94, 0x95, 0xB1, 0x15, 0xF5, 0x0F, 0x5F, 0x77, 0x75, 0x3A, 0x23, - 0x6D, 0xC0, 0x7E, 0xAC, 0x13, 0x6C, 0xAA, 0x7C, 0x3E, 0x34, 0x5E, 0x83, 0xC3, 0x6A, 0x71, 0xE6, - 0x2B, 0x77, 0x17, 0x8B, 0xDF, 0x19, 0xFA, 0x9F, 0x5C, 0x83, 0xF5, 0x7B, 0x8E, 0x7E, 0xEF, 0x53, - 0x6D, 0xC0, 0x75, 0xC2, 0xFE, 0xD4, 0x19, 0x8A, 0xAA, 0x7D, 0xF4, 0x98, 0x45, 0x9F, 0x57, 0x58, - 0xDE, 0x75, 0x41, 0xB2, 0xC9, 0x98, 0xF6, 0x5A, 0x90, 0x90, 0x11, 0xC2, 0x2E, 0x6A, 0xED, 0xC2, - 0x3B, 0x4E, 0x92, 0xF9, 0x0C, 0x59, 0x10, 0x31, 0xA4, 0x2B, 0x2A, 0x56, 0xAA, 0x9B, 0x40, 0x59, - 0x4A, 0x58, 0xE5, 0x1B, 0xE5, 0x15, 0x90, 0x17, 0x4C, 0x0F, 0xD4, 0xBD, 0x48, 0x2F, 0x9B, 0x4D, - 0x51, 0xC5, 0xAE, 0x7C, 0x8C, 0xB4, 0xAD, 0xBD, 0x03, 0xA9, 0xEA, 0x9A, 0x3F, 0x72, 0xA3, 0x80, - 0x49, 0x2D, 0x4D, 0x9B, 0x99, 0xDD, 0x69, 0x16, 0xBE, 0x33, 0x7C, 0x83, 0xD1, 0x2B, 0xC5, 0x3D, - 0x6B, 0xE2, 0x06, 0xB8, 0x9C, 0x81, 0x0B, 0xAC, 0xB8, 0x18, 0x26, 0xCE, 0x6B, 0xC0, 0xCB, 0x36, - 0xE4, 0xB5, 0x9A, 0xCD, 0x26, 0xFB, 0x8E, 0x37, 0xFC, 0xCD, 0x87, 0x31, 0xE9, 0x1C, 0x2E, 0x2F, - 0x59, 0x83, 0x72, 0xCA, 0xC4, 0x77, 0x40, 0x5D, 0x1E, 0x54, 0xD5, 0x23, 0x2C, 0xAE, 0x7D, 0x80, - 0x3D, 0xC2, 0xCF, 0x6A, 0x7A, 0xEC, 0x24, 0xD7, 0xFD, 0x19, 0x98, 0x01, 0x10, 0x9D, 0x09, 0xA7, - 0xDB, 0xF3, 0x42, 0x3D, 0xEF, 0xC7, 0x57, 0x5F, 0x59, 0xBF, 0x07, 0x71, 0x18, 0xCC, 0xD7, 0x6F, - 0x89, 0x6A, 0xA1, 0x4B, 0x61, 0xA0, 0xD2, 0x6A, 0x89, 0x9C, 0x6F, 0xC2, 0x3D, 0xB5, 0x28, 0x25, - 0x7A, 0x48, 0x89, 0x06, 0xD2, 0x43, 0x23, 0xB6, 0x46, 0x54, 0xAC, 0xB1, 0x5E, 0xE2, 0x18, 0x86, - 0xD6, 0xB8, 0xD6, 0x90, 0x48, 0xC0, 0xC6, 0xCA, 0x33, 0xF2, 0x56, 0x8D, 0xDB, 0xF0, 0x2D, 0xCA, - 0xDA, 0x11, 0xD6, 0x99, 0x05, 0xAF, 0x4D, 0x60, 0xA5, 0x33, 0x0D, 0x9D, 0x25, 0x25, 0x98, 0x55, - 0x5C, 0x84, 0x3B, 0x9E, 0xFB, 0xF2, 0x17, 0xE0, 0x38, 0x8B, 0x65, 0xDD, 0x81, 0x47, 0xFB, 0x2E, - 0x77, 0x0D, 0x1E, 0x69, 0x99, 0x75, 0xCB, 0x3D, 0x81, 0xDE, 0xD4, 0xF5, 0x36, 0x36, 0x5E, 0xAB, - 0x7B, 0xED, 0x99, 0xCB, 0x99, 0xEF, 0x6A, 0x3B, 0xC5, 0x88, 0x09, 0x1B, 0x3C, 0xBB, 0xE2, 0x21, - 0x22, 0xE0, 0xA5, 0x15, 0xD4, 0x90, 0x14, 0xFE, 0x64, 0x40, 0xAE, 0x40, 0x95, 0xDC, 0xC1, 0x2B, - 0x8D, 0xF3, 0xEE, 0x5D, 0x97, 0x21, 0xF8, 0x76, 0x99, 0x3B, 0x02, 0x35, 0x67, 0xE0, 0x83, 0x14, - 0x26, 0x59, 0x2A, 0xBA, 0x03, 0x25, 0x71, 0x33, 0x55, 0x46, 0x09, 0x7A, 0xC3, 0x45, 0x7F, 0xB5, - 0xF3, 0xEE, 0x57, 0x63, 0x4D, 0xC9, 0xCF, 0x0D, 0xDB, 0x9D, 0x8D, 0x14, 0xD3, 0x8C, 0x08, 0x34, - 0xC1, 0x62, 0x0B, 0x1E, 0xDA, 0x51, 0xE9, 0x26, 0xEC, 0xF3, 0x54, 0xF1, 0x41, 0x20, 0xBC, 0xC5, - 0x8F, 0x84, 0x3D, 0x0C, 0x1F, 0x90, 0x27, 0xE3, 0x31, 0x9B, 0x53, 0x80, 0x89, 0xF7, 0x1D, 0x5F, - 0x82, 0x78, 0x94, 0x26, 0x7A, 0xCC, 0x27, 0x75, 0xEC, 0x1F, 0x35, 0x41, 0xF0, 0xC0, 0x9F, 0x0B, - 0x1D, 0x89, 0xEF, 0x0F, 0xB1, 0x1B, 0xFC, 0xB9, 0x98, 0xBC, 0xF2, 0xBE, 0x8D, 0xFD, 0xD0, 0xAF, - 0xC5, 0x84, 0x8A, 0xA3, 0x7D, 0xEC, 0x88, 0x7E, 0x2D, 0x76, 0xD6, 0xBF, 0xA3, 0x95, 0xD1, 0xAF, - 0xC5, 0x96, 0xD6, 0x3A, 0x10, 0x6B, 0xA3, 0xDF, 0x8B, 0xC9, 0x60, 0x9D, 0x26, 0xAD, 0x4E, 0xFC, - 0x5E, 0x4C, 0x44, 0x3A, 0x6C, 0x0A, 0x04, 0xA0, 0xDF, 0x8B, 0xA1, 0x40, 0xBB, 0x25, 0x90, 0x80, - 0x7E, 0x6F, 0x8E, 0x20, 0x74, 0x47, 0x9E, 0xB7, 0x40, 0xB3, 0x74, 0xBF, 0x80, 0x3A, 0x23, 0xCA, - 0x44, 0xB7, 0xDD, 0xF3, 0xAB, 0xAF, 0xC4, 0xB4, 0x02, 0xCF, 0x59, 0x15, 0x98, 0xC7, 0x50, 0x58, - 0x62, 0xC6, 0x8A, 0xA7, 0x02, 0x8B, 0x43, 0x35, 0xD2, 0xC1, 0x3A, 0xBB, 0x23, 0x0B, 0xF9, 0x1E, - 0xE8, 0x91, 0x44, 0xA6, 0x11, 0xB1, 0x87, 0xD0, 0xE6, 0xDE, 0x76, 0x5F, 0x9B, 0x98, 0x53, 0x8C, - 0xEF, 0xE2, 0xF6, 0x54, 0xCC, 0x76, 0x13, 0x5D, 0xD6, 0x4E, 0x6E, 0xFC, 0xEF, 0x4C, 0x7E, 0x98, - 0x9B, 0xDF, 0x26, 0x3B, 0x4D, 0x9B, 0x7C, 0x95, 0x3C, 0x17, 0x88, 0xE4, 0xCB, 0xCD, 0x45, 0x77, - 0x51, 0xCD, 0xAE, 0xD7, 0xEB, 0xEF, 0x5D, 0x3C, 0xA2, 0x63, 0xF5, 0x1D, 0x60, 0xFD, 0x10, 0x4B, - 0x5E, 0x2F, 0xA4, 0xD8, 0x09, 0xEF, 0x4F, 0xFF, 0xBB, 0x5C, 0x31, 0x6C, 0xCD, 0x55, 0xFB, 0x6C, - 0x51, 0xD5, 0xAE, 0x7B, 0x7E, 0xB6, 0x77, 0xDE, 0x3D, 0xDB, 0x2C, 0x76, 0x10, 0x0A, 0x2C, 0x21, - 0xED, 0x4B, 0x81, 0x50, 0x3A, 0xCE, 0x6B, 0xFA, 0x60, 0xC0, 0x1D, 0x84, 0xBC, 0x62, 0xDB, 0x86, - 0x2E, 0x8C, 0x4B, 0x6E, 0x83, 0xE1, 0xAE, 0xA2, 0x76, 0x44, 0xE6, 0x25, 0x7C, 0x11, 0xF8, 0x83, - 0x0E, 0x02, 0xD0, 0xDD, 0x2F, 0x7B, 0xB7, 0xBF, 0x20, 0x7F, 0x08, 0x0D, 0x51, 0x48, 0xD7, 0xCE, - 0x98, 0xFE, 0x6E, 0x30, 0xDC, 0x48, 0xB9, 0x85, 0xB1, 0xD6, 0xB6, 0x0F, 0xC2, 0x2C, 0x5A, 0x77, - 0xA1, 0x1F, 0x98, 0x81, 0xC6, 0x2C, 0xDF, 0x43, 0x13, 0x1E, 0x5E, 0x67, 0x1C, 0x98, 0x2E, 0x5E, - 0x77, 0xFA, 0xC4, 0xB4, 0xBC, 0xA0, 0x31, 0x5A, 0xF2, 0x60, 0x1E, 0xB0, 0x6F, 0x61, 0x47, 0x78, - 0x7F, 0x6A, 0x32, 0x45, 0xD3, 0xC8, 0x56, 0x0C, 0x93, 0xE9, 0x9F, 0x77, 0xF7, 0xFA, 0x67, 0xD7, - 0xC2, 0xD0, 0xAC, 0x8A, 0xBD, 0x6E, 0xB0, 0x9F, 0x47, 0x9C, 0x1B, 0x7B, 0xE7, 0xBA, 0xC3, 0xEE, - 0x74, 0xF5, 0x21, 0x36, 0x0D, 0xBA, 0xF2, 0xB7, 0x3C, 0xFD, 0x91, 0xC3, 0x00, 0x20, 0x84, 0x0D, - 0x14, 0x55, 0x37, 0x87, 0x0D, 0x26, 0xB7, 0x36, 0xF6, 0xAE, 0xBC, 0x5D, 0x1D, 0xE8, 0xCE, 0x18, - 0x9D, 0x1E, 0x13, 0xF0, 0x09, 0xF9, 0x22, 0x02, 0xEA, 0xD5, 0x59, 0xD1, 0x02, 0x8E, 0x81, 0x22, - 0x5A, 0x95, 0xBC, 0x4E, 0x48, 0x98, 0xE7, 0xB8, 0x5D, 0x15, 0x09, 0x98, 0xB1, 0x9E, 0xA7, 0xE6, - 0xBE, 0x15, 0x2F, 0xB7, 0xE2, 0xE5, 0x56, 0xBC, 0xAC, 0xCC, 0xAB, 0xC5, 0x14, 0xC7, 0x02, 0x46, - 0x35, 0xED, 0xCA, 0x30, 0xAF, 0xA4, 0xB0, 0x39, 0x7D, 0xDE, 0x64, 0xCA, 0x9A, 0x11, 0x86, 0x1A, - 0xE1, 0xA7, 0x02, 0xBE, 0x1B, 0x22, 0x68, 0x96, 0x62, 0xAA, 0xA1, 0xDA, 0x8F, 0x67, 0x61, 0x60, - 0xF4, 0x49, 0x58, 0x45, 0x8A, 0x1A, 0xDD, 0x17, 0xBB, 0xDE, 0x2B, 0x7C, 0xC5, 0x27, 0x6E, 0xA5, - 0x2E, 0xA2, 0x13, 0x0F, 0x5D, 0xD8, 0x83, 0xA7, 0xC5, 0xC3, 0x8C, 0xB1, 0x79, 0xB9, 0x10, 0xE3, - 0xC5, 0xFD, 0xD9, 0x13, 0x73, 0x2F, 0x8F, 0x52, 0x8B, 0x53, 0x4F, 0x84, 0x82, 0x3E, 0x71, 0x93, - 0x13, 0xB9, 0x28, 0x02, 0x1A, 0x18, 0xE5, 0xC3, 0xFA, 0x52, 0x22, 0x02, 0xF1, 0x04, 0xDE, 0x1B, - 0xCB, 0xE0, 0xC9, 0xB1, 0x0F, 0xB4, 0x32, 0xA0, 0x8C, 0x0D, 0xBB, 0xC2, 0x0E, 0x05, 0xF8, 0x83, - 0xD1, 0x87, 0x52, 0x56, 0x52, 0x9F, 0x1B, 0x0C, 0x1D, 0x67, 0x74, 0x87, 0xBB, 0xE2, 0x1E, 0xDD, - 0xE1, 0x2A, 0xB7, 0x13, 0xD4, 0x24, 0x7D, 0x11, 0x45, 0x07, 0xAD, 0x66, 0x73, 0xB7, 0xD9, 0x6C, - 0xFA, 0xAE, 0x14, 0xC7, 0x0C, 0x6E, 0x0E, 0xC9, 0xBE, 0xA5, 0xB1, 0xF7, 0xE1, 0x57, 0x62, 0x06, - 0xDC, 0x7B, 0xE2, 0xDC, 0x14, 0xEF, 0xB9, 0x8D, 0x32, 0x01, 0xD6, 0xCB, 0x22, 0xC7, 0x52, 0xBA, - 0x5F, 0x99, 0x48, 0xFF, 0x0C, 0xD2, 0x3C, 0xE7, 0x18, 0x36, 0xEA, 0xCE, 0x4D, 0xA1, 0x0B, 0xB9, - 0x52, 0x66, 0xC9, 0x51, 0xB1, 0x79, 0xDE, 0xC1, 0x4E, 0x9D, 0x8A, 0x8D, 0x12, 0xD8, 0x5D, 0xB8, - 0xCB, 0x39, 0x3D, 0x2C, 0xEF, 0xA6, 0x51, 0x83, 0xED, 0xFC, 0xBF, 0xFF, 0xEB, 0xBE, 0x3D, 0x2E, - 0xBE, 0x98, 0x32, 0xE4, 0xBF, 0xB0, 0x5B, 0x5F, 0xA6, 0x8B, 0xDF, 0xAC, 0x8C, 0x54, 0xA5, 0x7A, - 0xC5, 0x7F, 0x53, 0x08, 0x34, 0xB5, 0x31, 0x25, 0x67, 0x6A, 0xE7, 0x77, 0x59, 0x45, 0x9E, 0x82, - 0x02, 0x77, 0x3D, 0xF3, 0x10, 0xD5, 0xF2, 0x11, 0xFF, 0x9A, 0xF8, 0xD6, 0xD2, 0xD1, 0xBD, 0x17, - 0x61, 0x92, 0xA5, 0xC6, 0x12, 0x34, 0xB1, 0x01, 0xA8, 0x3E, 0x8D, 0x67, 0x12, 0xB4, 0x8B, 0x23, - 0xAC, 0xE8, 0x68, 0x13, 0xD0, 0x94, 0x2E, 0xC4, 0x88, 0xA6, 0xB4, 0x21, 0x9F, 0x57, 0xD9, 0xCD, - 0xC5, 0xD9, 0x9E, 0x65, 0x28, 0x0E, 0xDE, 0x12, 0xAF, 0x06, 0x6B, 0x83, 0xE1, 0x8E, 0xE7, 0xE0, - 0xB8, 0x31, 0xFD, 0x3A, 0x7D, 0x11, 0xD3, 0xFB, 0xBD, 0xD0, 0xFA, 0xE6, 0xD1, 0xCE, 0xB3, 0x0D, - 0x92, 0xB7, 0xBA, 0xAB, 0x9B, 0x43, 0x86, 0xDB, 0x59, 0x4E, 0x4D, 0xCB, 0xB6, 0x4F, 0x5E, 0x2A, - 0x86, 0x31, 0x7F, 0x9F, 0xC5, 0xF5, 0xB6, 0x25, 0x4A, 0xA0, 0x09, 0xBB, 0xA0, 0x90, 0x00, 0x5D, - 0x7D, 0x88, 0x76, 0xB4, 0xC0, 0x97, 0x6C, 0x84, 0xEE, 0x0C, 0x22, 0xB0, 0x52, 0x25, 0x23, 0xD9, - 0x8E, 0x23, 0x60, 0xC9, 0x61, 0xDD, 0x6F, 0x51, 0x42, 0xC5, 0x50, 0x9A, 0xD8, 0x0B, 0x03, 0x09, - 0x19, 0x7A, 0x23, 0x22, 0x78, 0x46, 0x36, 0xA1, 0xEC, 0x86, 0x2E, 0x53, 0x82, 0x2C, 0x23, 0x45, - 0x96, 0x60, 0x3C, 0x73, 0xA7, 0x96, 0x5A, 0x85, 0xDA, 0xF6, 0x59, 0x86, 0x6D, 0x93, 0x81, 0xFD, - 0xDA, 0x1A, 0x0E, 0x31, 0xAC, 0x5A, 0x6A, 0x71, 0x85, 0x81, 0x56, 0x5A, 0xDB, 0x13, 0xE6, 0x7C, - 0x39, 0xDC, 0x4A, 0xB4, 0xBE, 0xC2, 0x53, 0x9B, 0xD6, 0x0E, 0xD3, 0x41, 0xF4, 0xC2, 0xCA, 0x22, - 0xCC, 0x63, 0xE2, 0x78, 0x10, 0x88, 0xDB, 0x1C, 0x67, 0xE8, 0xBE, 0x15, 0x0A, 0x5D, 0xA7, 0x19, - 0x9A, 0xCE, 0xD5, 0x67, 0x76, 0x7B, 0xD3, 0x6F, 0x60, 0x94, 0xCF, 0xC0, 0x37, 0xA4, 0x39, 0x06, - 0xE3, 0x11, 0x99, 0xA1, 0x3F, 0x80, 0xCE, 0xE8, 0xE3, 0xA5, 0xBE, 0xE7, 0xE8, 0x8A, 0x39, 0xF4, - 0x0D, 0x69, 0x73, 0xE9, 0x73, 0x11, 0x11, 0x84, 0xC2, 0x25, 0xD0, 0xD3, 0x03, 0xDA, 0xE6, 0x89, - 0xF1, 0x49, 0x37, 0xD2, 0xDF, 0x2E, 0xCE, 0xEB, 0x97, 0xEF, 0x7B, 0xEC, 0xCA, 0xF4, 0xF8, 0x50, - 0x7A, 0x90, 0xDC, 0x28, 0xA6, 0xAF, 0x88, 0xFE, 0xC7, 0x96, 0xC3, 0xE3, 0xD6, 0xFF, 0x7C, 0x7D, - 0xB4, 0xA4, 0xDF, 0xE9, 0xE6, 0x6B, 0x94, 0x51, 0x8C, 0xAA, 0x4C, 0xA5, 0xA4, 0x01, 0xB0, 0xE3, - 0x65, 0x89, 0x2C, 0x34, 0xEB, 0x95, 0x89, 0x2C, 0x82, 0x55, 0x54, 0x2E, 0xB2, 0xC4, 0x17, 0x31, - 0xBD, 0x2B, 0x6B, 0x24, 0xB2, 0x60, 0x36, 0x1C, 0xCF, 0x22, 0x77, 0xC2, 0xAA, 0x44, 0x16, 0x72, - 0x4D, 0x14, 0x89, 0x76, 0x5E, 0x87, 0xC4, 0x12, 0xB2, 0x42, 0xC2, 0xFC, 0x50, 0x66, 0x31, 0x80, - 0xB6, 0xB8, 0xC6, 0xD0, 0xC9, 0x73, 0x14, 0xE4, 0x22, 0xD3, 0x13, 0x5C, 0x27, 0x02, 0xDE, 0xAD, - 0x30, 0x52, 0xDE, 0x70, 0xED, 0x83, 0x6E, 0x14, 0x1C, 0x97, 0x18, 0xD3, 0x4F, 0x1E, 0x62, 0x6B, - 0x68, 0xA4, 0x8E, 0xCC, 0x2D, 0x61, 0xA3, 0x66, 0xF4, 0xB8, 0xF0, 0xA6, 0x44, 0x12, 0x9F, 0xBC, - 0x80, 0xBD, 0xBA, 0x0C, 0x88, 0xCB, 0x91, 0x5E, 0xC6, 0x38, 0xC5, 0x92, 0xFE, 0xA5, 0x90, 0xA5, - 0x84, 0x72, 0x48, 0x99, 0xE4, 0x33, 0x14, 0x8D, 0x38, 0x39, 0xA6, 0xF4, 0x7A, 0x7B, 0xDF, 0x4E, - 0x7F, 0xD9, 0xEB, 0xF7, 0xBA, 0xB7, 0x77, 0x5F, 0x90, 0x4E, 0x03, 0xB1, 0xE2, 0x1B, 0x3C, 0x68, - 0x47, 0xA8, 0xF4, 0x52, 0x29, 0x67, 0x2B, 0xDB, 0x58, 0xC1, 0x20, 0x04, 0xBC, 0x80, 0x49, 0xDF, - 0xF2, 0x1D, 0x35, 0xE5, 0x18, 0x2F, 0x4D, 0x26, 0xC1, 0x11, 0x9E, 0xDA, 0x3F, 0xD0, 0x44, 0xB0, - 0x4D, 0x72, 0x2B, 0xC4, 0xF3, 0x92, 0xC7, 0xED, 0xD4, 0x51, 0x9B, 0x3A, 0xD8, 0x1D, 0x20, 0x7A, - 0x6D, 0xE6, 0x72, 0x4B, 0xA7, 0xBF, 0x9D, 0xF7, 0xC0, 0x9D, 0x3E, 0x19, 0x45, 0xD2, 0x92, 0x39, - 0x0E, 0xC5, 0xA9, 0x63, 0xFB, 0xAA, 0x57, 0xF2, 0x1E, 0xB8, 0xD4, 0xB1, 0xBA, 0x3C, 0xCD, 0x82, - 0x22, 0xCE, 0x24, 0x16, 0x44, 0xA3, 0xCC, 0xD0, 0xCD, 0x05, 0x03, 0x33, 0x75, 0x4D, 0x9C, 0xA8, - 0x44, 0xA1, 0x32, 0x05, 0x41, 0x34, 0xED, 0x8B, 0x4B, 0x5B, 0xD8, 0x20, 0x4F, 0xE9, 0x2F, 0x17, - 0x5F, 0xEB, 0xE7, 0xEF, 0xCF, 0x8E, 0x99, 0x44, 0x0C, 0x01, 0xDD, 0x08, 0x59, 0x5F, 0xF5, 0x36, - 0xF5, 0xFE, 0x68, 0x81, 0x57, 0x72, 0xC3, 0x3C, 0xD1, 0xD1, 0xBC, 0x6B, 0x3C, 0x61, 0x4A, 0x12, - 0x72, 0x24, 0x97, 0xAC, 0x94, 0x14, 0x27, 0xE9, 0x1B, 0x85, 0xB9, 0x45, 0xD9, 0xB7, 0xFE, 0x69, - 0xBE, 0x53, 0xF9, 0xF2, 0x82, 0xF5, 0xC5, 0x61, 0xF1, 0xC9, 0x74, 0xDD, 0x3B, 0xEB, 0x9B, 0x7B, - 0xDF, 0x27, 0x27, 0xB0, 0xF0, 0x78, 0x4D, 0xCE, 0x36, 0x17, 0xB0, 0xB0, 0x9A, 0xE5, 0x47, 0xF6, - 0x67, 0xCC, 0x79, 0xC5, 0xE1, 0xFD, 0x5F, 0x05, 0x58, 0x08, 0x44, 0xD2, 0x77, 0x8E, 0xDC, 0xD4, - 0x76, 0x74, 0xBE, 0x2B, 0xDC, 0x28, 0x28, 0x57, 0x12, 0x1C, 0x8F, 0x6F, 0xC5, 0x4E, 0x23, 0x61, - 0xE1, 0x6E, 0x93, 0xF3, 0x44, 0x24, 0xA0, 0xD3, 0xF5, 0x14, 0xCF, 0x77, 0x23, 0x29, 0x6A, 0x4B, - 0x1F, 0x98, 0x2F, 0x19, 0xDA, 0x5F, 0xE2, 0xAB, 0xEC, 0x20, 0xA1, 0x2C, 0xAA, 0x4A, 0xC4, 0x0B, - 0xFD, 0xAC, 0x5F, 0xEA, 0xB3, 0xC3, 0x85, 0x0A, 0x86, 0x0A, 0x95, 0x0D, 0x13, 0x9A, 0x2B, 0x2A, - 0x28, 0x3D, 0x22, 0x08, 0xD7, 0x30, 0x57, 0x40, 0x50, 0xA4, 0xE1, 0x34, 0x68, 0x23, 0x90, 0x49, - 0x84, 0x02, 0x3D, 0xE9, 0x03, 0x7D, 0xB1, 0x48, 0xA0, 0xE9, 0x28, 0xA0, 0xE4, 0xAE, 0xE5, 0x46, - 0xFF, 0x64, 0xCE, 0xBD, 0x5C, 0xE0, 0xCF, 0xEC, 0xA0, 0x9F, 0x34, 0x4C, 0xFC, 0x22, 0xF2, 0x3A, - 0xB9, 0xE9, 0x17, 0xD8, 0x15, 0x30, 0x85, 0x50, 0x50, 0x06, 0xD1, 0x8B, 0xA9, 0x0E, 0xD7, 0xA0, - 0x11, 0xB0, 0x02, 0x11, 0xD0, 0x0D, 0x73, 0x03, 0xAD, 0x74, 0x5F, 0xEC, 0x8E, 0x4C, 0x31, 0x05, - 0xF4, 0xDD, 0x05, 0xC5, 0x36, 0xF8, 0x14, 0xAA, 0xB9, 0x9E, 0xA3, 0xCB, 0xEC, 0x1F, 0xE4, 0x77, - 0x85, 0xE9, 0x52, 0xE4, 0x3B, 0x93, 0x24, 0x88, 0xB1, 0x98, 0xF0, 0x46, 0xD1, 0x94, 0x8D, 0x8B, - 0x32, 0x84, 0xAC, 0xEF, 0xB2, 0x8E, 0xC0, 0xD2, 0x77, 0xC3, 0x51, 0xE9, 0x16, 0xD1, 0x55, 0x6E, - 0xDA, 0xEF, 0xCD, 0x7E, 0x1F, 0x33, 0x91, 0x46, 0x6E, 0x4C, 0x3B, 0x53, 0xA6, 0x25, 0x7C, 0x85, - 0xB5, 0x66, 0xDF, 0xC5, 0xCE, 0x75, 0xEF, 0x5A, 0x26, 0x63, 0x50, 0xCA, 0xA4, 0xE5, 0x81, 0xE5, - 0xC1, 0x3E, 0xCE, 0x1A, 0xC4, 0x4E, 0x6F, 0x3F, 0xCF, 0xB5, 0xEA, 0x6C, 0xA6, 0xBB, 0xC4, 0x5D, - 0xEA, 0x41, 0x1F, 0xF0, 0x97, 0x96, 0xB3, 0x53, 0xBD, 0x9F, 0x33, 0xC1, 0xB0, 0x56, 0xFB, 0x17, - 0x2E, 0xA7, 0xDC, 0xB6, 0x05, 0xCD, 0x36, 0x69, 0xEB, 0x5A, 0x45, 0x09, 0xAC, 0xBD, 0x46, 0x1B, - 0x24, 0x26, 0x5D, 0x6A, 0x73, 0x5A, 0x9B, 0x46, 0x53, 0xAD, 0xC5, 0x69, 0x6A, 0xAD, 0xB6, 0x6C, - 0x3E, 0x9A, 0x6A, 0x6D, 0x22, 0x4D, 0xB5, 0x8B, 0xD2, 0x54, 0x67, 0x8D, 0x36, 0xA8, 0x5D, 0x9E, - 0xA6, 0xDA, 0x9B, 0x46, 0x53, 0xED, 0xC5, 0x69, 0x6A, 0xAD, 0xB6, 0x6C, 0x3E, 0x9A, 0x6A, 0x6F, - 0x22, 0x4D, 0x75, 0x8A, 0xD2, 0xD4, 0xFE, 0x1A, 0x6D, 0x50, 0xA7, 0x3C, 0x4D, 0x75, 0x36, 0x8D, - 0xA6, 0x3A, 0x8B, 0xD3, 0xD4, 0x5A, 0x6D, 0xD9, 0x7C, 0x34, 0xD5, 0x59, 0x35, 0x4D, 0x85, 0x7A, - 0x3D, 0xA9, 0xD4, 0x68, 0x8B, 0x2F, 0x73, 0xB9, 0x90, 0xDC, 0x4C, 0xD1, 0xCB, 0xD7, 0x47, 0xEE, - 0x74, 0x7B, 0xB5, 0x93, 0xC0, 0x88, 0xC0, 0xD9, 0x8D, 0xA5, 0xE5, 0x5D, 0x1E, 0xC4, 0x2F, 0x0B, - 0xE2, 0x53, 0xAA, 0x25, 0xA6, 0x29, 0x07, 0x28, 0x6B, 0xEE, 0x9F, 0x36, 0xEF, 0x77, 0x0B, 0x18, - 0xE5, 0xA7, 0x4D, 0xF9, 0xA8, 0x83, 0xCF, 0x6E, 0x37, 0xDB, 0x78, 0x5F, 0x9D, 0xAD, 0xE0, 0xCA, - 0x64, 0xDD, 0x5E, 0x24, 0xC6, 0x2A, 0x4C, 0x45, 0x82, 0xBA, 0xBD, 0x63, 0x29, 0x9A, 0xAA, 0x80, - 0xF2, 0x2F, 0x63, 0x61, 0x55, 0x95, 0xBB, 0x2E, 0xA3, 0x54, 0xB2, 0x0C, 0xF3, 0x58, 0x73, 0x34, - 0x29, 0xFE, 0xB5, 0x2E, 0x40, 0xDA, 0x60, 0xD0, 0x17, 0x19, 0x17, 0xD2, 0x7B, 0x8B, 0xE4, 0xB9, - 0xA6, 0xBC, 0x49, 0xE2, 0x5D, 0xB4, 0x31, 0x44, 0xE2, 0x84, 0xC9, 0xB0, 0x40, 0xB7, 0xEB, 0x9C, - 0xC9, 0x1A, 0x1C, 0x30, 0xC8, 0x55, 0x0F, 0xE3, 0x70, 0x1D, 0x18, 0x7C, 0x2D, 0xED, 0x0C, 0xE5, - 0xEC, 0x86, 0x77, 0x67, 0x3D, 0xB6, 0xC7, 0xBE, 0x9D, 0xF7, 0x36, 0xDD, 0x78, 0x08, 0x0B, 0x81, - 0x55, 0xCC, 0x65, 0x3E, 0x8C, 0x35, 0x9D, 0x06, 0x72, 0x12, 0x44, 0x09, 0x2B, 0xA2, 0xA7, 0xDA, - 0xDF, 0x34, 0xFB, 0xC5, 0xED, 0x88, 0x33, 0x16, 0xB1, 0xA0, 0x25, 0x31, 0xF7, 0x56, 0xA5, 0xC4, - 0x6D, 0xCA, 0x9D, 0x6A, 0x9F, 0x19, 0x3A, 0x70, 0x84, 0xDA, 0x09, 0x82, 0x55, 0xFC, 0x3D, 0x9B, - 0x8F, 0x2E, 0x7E, 0x1D, 0x32, 0x19, 0x34, 0x93, 0x5A, 0xC3, 0x1A, 0x5F, 0x5E, 0xF0, 0xEE, 0xA9, - 0xF5, 0x9D, 0x53, 0xAD, 0xB3, 0x65, 0xB3, 0xBC, 0xC1, 0x24, 0xFF, 0x65, 0x06, 0x83, 0x0A, 0x59, - 0x93, 0xED, 0xBB, 0x23, 0x71, 0x7F, 0x82, 0xD5, 0xFC, 0x80, 0x29, 0x0D, 0xF5, 0x47, 0x6E, 0x12, - 0x82, 0xBA, 0x54, 0xD0, 0x73, 0x72, 0x9B, 0x22, 0xBE, 0xC1, 0xFB, 0x94, 0x75, 0x61, 0x52, 0x99, - 0xC7, 0x75, 0x08, 0xF2, 0x99, 0x29, 0xBD, 0xE6, 0x0A, 0xAB, 0x89, 0x9E, 0xE7, 0xE1, 0x30, 0x18, - 0x20, 0x5F, 0x9B, 0x2B, 0xBC, 0x00, 0x1A, 0x1E, 0x57, 0x74, 0x95, 0x16, 0x7A, 0x77, 0xC1, 0xDE, - 0xD1, 0xAD, 0x17, 0xEC, 0xA8, 0xEF, 0x46, 0x13, 0xFF, 0xB6, 0xDF, 0xEF, 0x1F, 0xAD, 0xEF, 0x05, - 0x57, 0x5E, 0x2D, 0x9D, 0x79, 0xE3, 0x79, 0xCA, 0xC8, 0xA7, 0xF1, 0x1D, 0xCD, 0xE9, 0xD7, 0x9E, - 0x6E, 0x32, 0x6F, 0x84, 0x4E, 0xF9, 0xEB, 0xBD, 0x6A, 0x11, 0xF8, 0xB3, 0xE5, 0xCE, 0x87, 0xC0, - 0xD8, 0x10, 0xFB, 0x9A, 0x09, 0xA9, 0x09, 0x5F, 0x3E, 0x5E, 0xF1, 0xB5, 0x31, 0x7A, 0x3A, 0xA2, - 0xB8, 0x4C, 0xE1, 0xC0, 0x42, 0xC2, 0x0A, 0xDC, 0xB1, 0x47, 0x38, 0xF3, 0xA7, 0x91, 0xAE, 0x8E, - 0x84, 0xD7, 0x36, 0xCC, 0x51, 0xA5, 0x39, 0xC6, 0x13, 0x6D, 0x23, 0x83, 0xA4, 0x78, 0xFB, 0xC6, - 0x96, 0x72, 0x0A, 0x51, 0x8E, 0x40, 0xA5, 0x62, 0x37, 0x32, 0x69, 0x64, 0x84, 0xED, 0x57, 0x47, - 0x46, 0xB3, 0x4E, 0x92, 0x52, 0x3A, 0xBB, 0x9D, 0x26, 0x1D, 0x94, 0x5D, 0x47, 0x61, 0x13, 0x42, - 0xC5, 0x02, 0x94, 0xA8, 0xDD, 0x2D, 0x04, 0x28, 0xF1, 0xF7, 0x0A, 0x04, 0x28, 0x39, 0x68, 0x21, - 0x01, 0x4A, 0xBC, 0xFB, 0xD2, 0x02, 0x14, 0x68, 0x84, 0xD6, 0x13, 0xD3, 0xCD, 0x7B, 0xCB, 0x07, - 0xD1, 0x89, 0x38, 0x86, 0x10, 0xA9, 0x84, 0xBB, 0x57, 0x4C, 0x9C, 0x4A, 0x11, 0x9B, 0x64, 0xA8, - 0x57, 0xC0, 0x66, 0xB0, 0xF4, 0xB2, 0x68, 0xBE, 0x3E, 0xD7, 0xCB, 0xB3, 0x24, 0x2A, 0xB1, 0x07, - 0x4B, 0x97, 0xA8, 0xC4, 0x30, 0x5B, 0x89, 0xEA, 0xF5, 0x9C, 0x0B, 0x91, 0x1D, 0x2D, 0x7A, 0x14, - 0x4C, 0x9A, 0x2C, 0xEF, 0x28, 0xA8, 0xB2, 0x94, 0x69, 0x14, 0x20, 0x33, 0xF9, 0xDE, 0x17, 0xCF, - 0xD1, 0x41, 0xB3, 0xC7, 0x3C, 0x24, 0xB5, 0xD2, 0x1C, 0x6E, 0xCA, 0x39, 0x79, 0xAA, 0xCB, 0x93, - 0x2F, 0x77, 0xB7, 0x57, 0x20, 0x6C, 0xD1, 0xA7, 0x02, 0xE5, 0x29, 0xAB, 0xAC, 0x76, 0x98, 0xC5, - 0x35, 0xF9, 0x18, 0x43, 0xE4, 0x38, 0x1A, 0xD8, 0xC4, 0xEC, 0x54, 0x99, 0x86, 0x85, 0xD8, 0x29, - 0x86, 0xB5, 0x06, 0x1C, 0x55, 0x4E, 0x9E, 0xD8, 0xA3, 0x1B, 0x2D, 0x1D, 0x87, 0xAC, 0x75, 0xC8, - 0x3D, 0x51, 0x5D, 0xBE, 0xA4, 0x42, 0xBA, 0x14, 0xFA, 0x2B, 0x50, 0x9D, 0x74, 0x55, 0x92, 0x86, - 0x40, 0x9C, 0x8D, 0x90, 0x34, 0xBE, 0x69, 0xA1, 0xA4, 0x81, 0xB6, 0xAF, 0xD5, 0x48, 0x1A, 0x93, - 0x41, 0x27, 0xF4, 0xE6, 0x6B, 0xF6, 0x4B, 0xCB, 0x12, 0x13, 0xDB, 0x33, 0x89, 0x0B, 0x2E, 0x74, - 0xC9, 0x4D, 0x95, 0xBB, 0xD2, 0x4F, 0xF9, 0xBC, 0xB7, 0xEE, 0x12, 0x81, 0xAF, 0x15, 0x2B, 0xD2, - 0xB9, 0xB0, 0x4C, 0xE0, 0x6B, 0xEB, 0x28, 0x13, 0x20, 0x02, 0xA7, 0xCB, 0x04, 0xAD, 0x66, 0xAB, - 0xD5, 0xDC, 0x0A, 0x05, 0xB3, 0x84, 0x82, 0xF8, 0x96, 0x16, 0x12, 0x0A, 0x62, 0x4D, 0x36, 0x5C, - 0x3F, 0x0C, 0x59, 0x52, 0x15, 0x5C, 0xBB, 0xDC, 0xE5, 0x8C, 0x48, 0x47, 0xBF, 0xE1, 0x17, 0x33, - 0xB4, 0x88, 0xB9, 0xEE, 0x65, 0xA2, 0x2D, 0xA7, 0xC1, 0x1B, 0x05, 0x4E, 0xE2, 0x4A, 0x86, 0x62, - 0xF1, 0x5E, 0xFC, 0x46, 0x26, 0x7B, 0xFA, 0x6B, 0x74, 0x21, 0x73, 0xE1, 0xDA, 0x54, 0x42, 0xEF, - 0xA2, 0xDF, 0xAB, 0x7F, 0xF9, 0xFA, 0xF3, 0xB2, 0xCF, 0xF7, 0x60, 0xB8, 0x25, 0x9F, 0xE3, 0x68, - 0x49, 0xA4, 0x24, 0xC7, 0x18, 0xF2, 0x07, 0x4B, 0xEB, 0xB4, 0x83, 0x94, 0x9C, 0x61, 0x32, 0x65, - 0x71, 0x71, 0x0C, 0x58, 0x5D, 0xA7, 0x3F, 0x76, 0xD1, 0xE8, 0x18, 0x3E, 0x02, 0x21, 0xD8, 0xD3, - 0xC5, 0xCD, 0xB2, 0x88, 0xEB, 0x44, 0x97, 0x75, 0x92, 0x67, 0x29, 0xC6, 0x7A, 0xAC, 0xBB, 0x6E, - 0x3C, 0xCA, 0xFA, 0xEB, 0x60, 0xB0, 0xD6, 0x3E, 0xE7, 0x21, 0x55, 0xCC, 0x93, 0x87, 0x21, 0x1D, - 0x01, 0x67, 0xAC, 0x57, 0x90, 0xE6, 0x4D, 0xF7, 0xEC, 0x38, 0x60, 0xA5, 0x34, 0x36, 0x3C, 0xA8, - 0x31, 0xD7, 0x7B, 0xC6, 0x1D, 0x92, 0xD7, 0xE9, 0xC7, 0x82, 0x8D, 0xFE, 0xA5, 0x76, 0xD2, 0xED, - 0x1E, 0x9F, 0x9E, 0x1E, 0x9F, 0x9D, 0x1D, 0x9F, 0x9F, 0x1F, 0x5F, 0x5C, 0x1C, 0x5F, 0x5E, 0x96, - 0x75, 0x0B, 0x99, 0x6B, 0xA6, 0x3D, 0x45, 0xC7, 0x6C, 0xE0, 0x34, 0x61, 0xF7, 0xB8, 0x64, 0xA4, - 0x59, 0xB1, 0xB3, 0xD0, 0xE6, 0xDC, 0x81, 0x95, 0xBB, 0xD9, 0x4B, 0xFF, 0x62, 0x99, 0x7C, 0x25, - 0xEA, 0x71, 0x21, 0x61, 0x0E, 0x1B, 0xC9, 0x99, 0x0A, 0x91, 0x0D, 0x18, 0x13, 0x70, 0xC2, 0xF1, - 0xF1, 0x81, 0xFD, 0xFD, 0x2F, 0x79, 0x4B, 0x96, 0xC7, 0x4C, 0xFC, 0xF8, 0x40, 0x28, 0xC0, 0xA9, - 0x82, 0xB0, 0x16, 0x80, 0xAE, 0x65, 0x9D, 0x43, 0xA9, 0x72, 0x62, 0xFE, 0xFD, 0x41, 0xA8, 0x2A, - 0xD8, 0xE1, 0x10, 0xA0, 0x2C, 0xA0, 0xCB, 0x06, 0xC9, 0xF2, 0xC0, 0x4C, 0x1C, 0x9F, 0x83, 0x64, - 0x09, 0xDF, 0xCA, 0xAD, 0x4E, 0x2F, 0xDF, 0xB3, 0x82, 0x2B, 0x8E, 0x48, 0x85, 0xF5, 0x27, 0x4B, - 0xEA, 0x18, 0xEE, 0x2E, 0xE3, 0xDF, 0x75, 0x0F, 0x5D, 0x5F, 0xE4, 0x59, 0x2F, 0x7C, 0x56, 0xC8, - 0x46, 0x49, 0xB7, 0x20, 0x2E, 0xF7, 0x60, 0xE3, 0x24, 0x70, 0x7D, 0xD3, 0xD3, 0x0D, 0xF6, 0x06, - 0x57, 0xF3, 0x06, 0xED, 0x92, 0x2E, 0xC7, 0x9A, 0xD7, 0xDF, 0x4C, 0xDD, 0x93, 0x21, 0x33, 0xEE, - 0x93, 0x62, 0x23, 0xF5, 0x05, 0x97, 0x28, 0xDC, 0x95, 0x8E, 0x2D, 0x00, 0x57, 0x86, 0x05, 0xBF, - 0x7C, 0x93, 0x72, 0x0F, 0x83, 0x32, 0xAF, 0x78, 0xA2, 0x84, 0xAE, 0x6D, 0x3D, 0xE1, 0xED, 0xB1, - 0xD9, 0xD8, 0xDC, 0x90, 0xBA, 0x6A, 0x18, 0xC2, 0x4A, 0x62, 0x4A, 0x2F, 0x2D, 0x94, 0x91, 0x24, - 0x2D, 0x04, 0x01, 0xA5, 0xE2, 0x21, 0x46, 0x40, 0xE5, 0xEE, 0x40, 0x80, 0xC3, 0xAB, 0x89, 0x26, - 0x8D, 0xCD, 0x16, 0xB0, 0x4F, 0xD6, 0x6D, 0x7E, 0x01, 0xD2, 0x01, 0x62, 0xA0, 0xFC, 0x27, 0x8A, - 0xAA, 0xEA, 0x9A, 0x28, 0xF1, 0xA9, 0x71, 0x83, 0x07, 0x79, 0x9B, 0x6C, 0xC1, 0xCC, 0xE9, 0xAC, - 0x11, 0xC1, 0xDA, 0xC1, 0xBA, 0xD8, 0xD8, 0xC7, 0x9B, 0x4F, 0xDD, 0x81, 0x9F, 0xF7, 0x3C, 0xA8, - 0x3C, 0x0D, 0x7F, 0x0E, 0x30, 0x8F, 0x13, 0x45, 0x95, 0x09, 0xDA, 0x02, 0x72, 0x22, 0x8A, 0x9B, - 0x6D, 0xE4, 0x5F, 0x57, 0x4A, 0x98, 0xFF, 0xA8, 0x9A, 0xC5, 0xB7, 0xE3, 0xFB, 0x9F, 0xCE, 0xB9, - 0x4B, 0xF0, 0xE8, 0x01, 0x75, 0x27, 0x0E, 0xDE, 0x69, 0x5E, 0x7D, 0x32, 0x21, 0x83, 0x72, 0xAC, - 0xDA, 0x4E, 0x9B, 0xEE, 0x8D, 0x3B, 0x4C, 0x28, 0x6C, 0x7D, 0x9F, 0xDC, 0x06, 0x97, 0xA5, 0x7A, - 0x66, 0x4B, 0x5F, 0x86, 0xE5, 0x28, 0x33, 0x13, 0x9F, 0x27, 0xC5, 0x03, 0x13, 0xA4, 0x82, 0x52, - 0x02, 0x59, 0xAE, 0xDD, 0xBB, 0x38, 0x83, 0xBA, 0x86, 0xC9, 0x62, 0x66, 0xA6, 0x5B, 0x25, 0xDF, - 0x04, 0xB1, 0x38, 0x83, 0x11, 0xA3, 0xAD, 0xC8, 0xF0, 0x1D, 0x53, 0x0D, 0x70, 0x85, 0x52, 0x5A, - 0x7D, 0x49, 0xFD, 0xE0, 0xA5, 0xAC, 0xDE, 0xD9, 0xC8, 0x15, 0x60, 0xEC, 0xBC, 0x69, 0xDB, 0xE6, - 0xE2, 0x42, 0x67, 0x96, 0xE5, 0x68, 0xBA, 0x29, 0x54, 0xF9, 0x4B, 0x2A, 0x9A, 0x6E, 0xAA, 0xCF, - 0x6C, 0xE7, 0xE6, 0xF3, 0x9F, 0x6F, 0x5F, 0xC2, 0x17, 0x85, 0x72, 0xD1, 0x0F, 0xC2, 0x79, 0x10, - 0x6A, 0x88, 0x7B, 0x0E, 0x34, 0x54, 0xB0, 0x91, 0x65, 0xDB, 0x28, 0x43, 0x05, 0x59, 0xC1, 0x65, - 0x11, 0x1E, 0xB7, 0x21, 0x19, 0x17, 0x9C, 0x2B, 0x24, 0x5E, 0x89, 0x56, 0x23, 0xAE, 0x38, 0x8C, - 0x2B, 0xEA, 0x88, 0x59, 0x70, 0xDE, 0x38, 0xE2, 0x44, 0x82, 0x2E, 0x45, 0x52, 0x11, 0xF4, 0x7A, - 0x51, 0xA3, 0xCB, 0x0F, 0x87, 0x8D, 0x20, 0xD1, 0xFB, 0x56, 0x13, 0x40, 0xD1, 0x60, 0xD7, 0xFA, - 0x58, 0xC7, 0x8F, 0x4D, 0xB4, 0xD9, 0xB0, 0xF7, 0xED, 0x77, 0xF8, 0xF4, 0x15, 0x1C, 0x57, 0x52, - 0xE0, 0x17, 0x26, 0xE1, 0x03, 0x9C, 0x43, 0x87, 0x4D, 0xF4, 0x96, 0x32, 0x16, 0xCD, 0x19, 0x89, - 0x9F, 0x25, 0xB3, 0x9D, 0xB0, 0xE4, 0x09, 0xD0, 0x43, 0x94, 0x2B, 0xA6, 0xD8, 0x65, 0x36, 0x5F, - 0xD0, 0xE0, 0x59, 0x2D, 0x51, 0x89, 0x0A, 0x0B, 0x6E, 0x20, 0xEB, 0x68, 0x5C, 0xD3, 0xA9, 0xAA, - 0x2F, 0x33, 0x74, 0xD7, 0xE3, 0x26, 0x22, 0x30, 0x6A, 0x1B, 0xAB, 0xA6, 0xAF, 0xEE, 0xC0, 0xA3, - 0x8B, 0x41, 0x10, 0xB8, 0xC4, 0x66, 0x51, 0xBA, 0x0F, 0x31, 0xD7, 0x5D, 0x60, 0xD0, 0xA0, 0xA6, - 0xE0, 0xD4, 0x64, 0xF6, 0x90, 0x30, 0x1D, 0x0C, 0xBC, 0xAE, 0x0F, 0x4D, 0x0B, 0xC5, 0x3C, 0xD7, - 0x12, 0x04, 0x46, 0x3C, 0x5C, 0xBE, 0x87, 0x4C, 0x7C, 0x80, 0x6E, 0x1F, 0x01, 0x4D, 0x4A, 0x05, - 0x0B, 0xD3, 0x73, 0x62, 0x89, 0xD2, 0x48, 0x14, 0x00, 0x50, 0x8E, 0xC3, 0xEB, 0xE2, 0x00, 0x4A, - 0x0E, 0x13, 0xA1, 0xB9, 0x4E, 0xD3, 0x0D, 0x09, 0xAE, 0xD5, 0xC4, 0x56, 0x87, 0xCD, 0xA6, 0xBB, - 0xA5, 0xB6, 0xF9, 0xA8, 0x4D, 0xE4, 0xA3, 0xC1, 0x9C, 0xAA, 0x8E, 0xA2, 0x8A, 0x5A, 0xED, 0x63, - 0x6E, 0xF9, 0xDE, 0xEF, 0x6E, 0x71, 0x92, 0xCB, 0xEE, 0x63, 0x19, 0x74, 0x57, 0x42, 0xDC, 0x2B, - 0x67, 0xDB, 0x8F, 0xE4, 0xD9, 0x63, 0x3D, 0x47, 0xB7, 0x30, 0x1B, 0xE7, 0xA6, 0x9B, 0xFA, 0x23, - 0x6B, 0x0A, 0x96, 0x34, 0xD3, 0xF0, 0x3F, 0xD5, 0x6D, 0xC6, 0x45, 0x40, 0x76, 0xBF, 0xD3, 0x3B, - 0x13, 0x85, 0x6B, 0xEA, 0xE5, 0x40, 0x24, 0xE9, 0xD7, 0x92, 0xAE, 0x08, 0x4A, 0xDC, 0x11, 0x14, - 0x5D, 0x59, 0x25, 0xC9, 0x60, 0x8A, 0x05, 0x31, 0x46, 0xE0, 0x23, 0xD2, 0xD5, 0xB9, 0xD7, 0xFA, - 0x80, 0x63, 0x69, 0x9C, 0x6C, 0xE6, 0x3E, 0x75, 0xCD, 0xBB, 0x1F, 0x9A, 0xEF, 0x0E, 0xE9, 0x8F, - 0xC3, 0xA9, 0x6B, 0xDE, 0xE8, 0x3E, 0x89, 0x71, 0x58, 0x30, 0xCE, 0xF1, 0x8A, 0x54, 0x81, 0x6E, - 0x24, 0x01, 0x9C, 0xCC, 0xEB, 0xC6, 0x00, 0x45, 0x29, 0x8B, 0xB3, 0x3E, 0x60, 0xA6, 0x25, 0x9C, - 0x8B, 0xE1, 0xCC, 0xC1, 0x74, 0xCE, 0xFA, 0xA3, 0x2C, 0x8E, 0x48, 0x87, 0xD6, 0x58, 0x31, 0x9F, - 0x83, 0xF3, 0xAA, 0x31, 0x21, 0xE0, 0xC0, 0x11, 0x59, 0x78, 0xBB, 0xC8, 0x28, 0x0D, 0xB2, 0xB0, - 0x61, 0x7E, 0x79, 0xCC, 0x5C, 0x13, 0xE4, 0x8F, 0x93, 0x67, 0xCA, 0x01, 0xBE, 0xD4, 0x6A, 0x37, - 0xC3, 0xBE, 0xD6, 0x4B, 0x4D, 0x28, 0x16, 0x7E, 0xFA, 0x26, 0x76, 0x96, 0xEC, 0xBF, 0x29, 0xE6, - 0x7B, 0xF5, 0x46, 0x9C, 0x1B, 0x6F, 0x82, 0x4E, 0xA2, 0xE7, 0xC6, 0x9B, 0x24, 0xA9, 0x26, 0x51, - 0xB1, 0xFC, 0xD5, 0x80, 0x9D, 0xD3, 0xE5, 0xD2, 0x9C, 0x72, 0x72, 0x33, 0x31, 0x4D, 0x93, 0xC2, - 0xE4, 0x48, 0x58, 0x76, 0x76, 0xA6, 0xAE, 0x8B, 0x75, 0x10, 0x08, 0x4D, 0xED, 0x00, 0x89, 0x41, - 0x12, 0x23, 0x45, 0x25, 0x9A, 0x1E, 0x31, 0x40, 0x5B, 0x32, 0xE2, 0x60, 0x4C, 0xA4, 0x12, 0x50, - 0x0C, 0xE0, 0x2F, 0x88, 0x6B, 0x0E, 0x47, 0x65, 0x09, 0x4D, 0xD0, 0x41, 0x37, 0xC1, 0xBB, 0xE4, - 0xBE, 0x2F, 0x91, 0x9F, 0x0A, 0xE1, 0x3D, 0xE0, 0x7B, 0xF4, 0x18, 0x24, 0x35, 0x78, 0xDA, 0xA0, - 0xCA, 0xBF, 0x43, 0x2E, 0x72, 0x30, 0xBA, 0x0A, 0xD2, 0x19, 0x39, 0xDF, 0xBE, 0xE9, 0xC3, 0xDF, - 0x71, 0x26, 0xFE, 0xA6, 0xA0, 0x85, 0x6E, 0x6D, 0xB2, 0x3C, 0x45, 0x0F, 0x6A, 0xC9, 0x09, 0xC7, - 0xDF, 0xEB, 0x58, 0x8B, 0x55, 0x60, 0x44, 0x12, 0x29, 0x83, 0x7D, 0xBF, 0xD6, 0x33, 0x7D, 0xF1, - 0xD3, 0x8D, 0x75, 0x19, 0x76, 0xB9, 0xB0, 0x7F, 0xEC, 0xF8, 0x94, 0xDE, 0x6D, 0xD6, 0x4E, 0x9A, - 0xB3, 0x8D, 0x6A, 0x8B, 0x8E, 0xD0, 0xAA, 0x9D, 0xB4, 0x96, 0x3B, 0x02, 0xEC, 0x58, 0x7B, 0xB9, - 0x23, 0x74, 0x6A, 0x27, 0x9D, 0xE5, 0x8E, 0xB0, 0x5F, 0x3B, 0xD9, 0x5F, 0xEE, 0x08, 0x07, 0xB5, - 0x93, 0x83, 0xE5, 0x8E, 0x70, 0x58, 0x3B, 0x39, 0x5C, 0xEE, 0x08, 0xEF, 0x6A, 0x27, 0xEF, 0xF2, - 0x46, 0x70, 0xCA, 0x0C, 0x9D, 0x41, 0x70, 0x52, 0xE3, 0x9B, 0xC3, 0xC2, 0x1D, 0x5A, 0xB6, 0x1D, - 0xD4, 0x31, 0xEF, 0xAC, 0xB3, 0xEC, 0xCE, 0xD1, 0x85, 0x51, 0x6A, 0xA2, 0x56, 0xA0, 0x63, 0xCE, - 0x30, 0x70, 0x2F, 0x9C, 0x15, 0xF2, 0xCA, 0x74, 0x3D, 0xC7, 0xC7, 0xF3, 0xE0, 0x45, 0x54, 0x0B, - 0x04, 0xB5, 0x1E, 0x4E, 0x21, 0x50, 0x05, 0x2A, 0x54, 0x38, 0xAE, 0xA6, 0x3A, 0x2F, 0xE5, 0x60, - 0x34, 0xD5, 0x7C, 0x7A, 0x0B, 0xA6, 0x20, 0x98, 0xD0, 0x26, 0x22, 0xCB, 0x7B, 0x69, 0x7F, 0xA3, - 0x9C, 0xD5, 0xCC, 0xA1, 0x42, 0x90, 0x7F, 0xBF, 0x6E, 0x94, 0x0C, 0xCC, 0xAD, 0xFA, 0x32, 0xE2, - 0x8E, 0x66, 0x30, 0xB6, 0xB9, 0xE9, 0x12, 0xE8, 0xC3, 0x1B, 0x53, 0xFC, 0x22, 0xC7, 0xA0, 0x3C, - 0x69, 0xB5, 0x8A, 0x8B, 0x8C, 0xE9, 0x99, 0xAE, 0x4A, 0x93, 0xA1, 0x58, 0x27, 0xDC, 0x2A, 0xBC, - 0xDF, 0x0F, 0xC7, 0x27, 0xCB, 0x1E, 0xB2, 0x1A, 0xD0, 0x48, 0xD0, 0x65, 0xD9, 0xE1, 0xDA, 0x74, - 0x7D, 0xD4, 0xC6, 0x46, 0x5D, 0x4C, 0x2C, 0x07, 0xD1, 0x44, 0x1E, 0xE7, 0x3B, 0xDD, 0xEE, 0x1A, - 0x00, 0x51, 0x5F, 0x03, 0xFD, 0x42, 0xE6, 0x30, 0x86, 0x67, 0x2C, 0x78, 0xB8, 0x5C, 0x14, 0x4A, - 0x99, 0xC3, 0x8A, 0xB0, 0x47, 0x2E, 0xD5, 0xB6, 0x70, 0x3F, 0x61, 0xBD, 0x8A, 0x9C, 0x40, 0x34, - 0x13, 0xB3, 0x82, 0x1E, 0xEF, 0xA6, 0x12, 0x7E, 0x97, 0x52, 0xD7, 0x68, 0x83, 0xE2, 0x3A, 0xB2, - 0xD9, 0x9D, 0x5C, 0x67, 0x6F, 0x04, 0xEA, 0xCC, 0x19, 0xD1, 0xCC, 0xEF, 0xE3, 0xF1, 0x72, 0x5D, - 0xE6, 0x53, 0x87, 0xAC, 0xA5, 0x9A, 0x69, 0xA7, 0xCD, 0x28, 0x5D, 0xB9, 0x2F, 0xD4, 0x7A, 0x36, - 0x33, 0xA4, 0xAE, 0xD9, 0xCE, 0x78, 0xBC, 0xF2, 0xCB, 0xB4, 0x6E, 0xEF, 0x0C, 0xF5, 0x36, 0x99, - 0x46, 0xC7, 0x53, 0x4C, 0x15, 0xEF, 0xD5, 0xAC, 0xB1, 0xAC, 0xA3, 0x0E, 0x8A, 0xA3, 0x0C, 0xF3, - 0x0E, 0xB0, 0x4C, 0x1A, 0x4E, 0x82, 0x8F, 0x36, 0x2E, 0x8E, 0xA9, 0xB4, 0x80, 0x06, 0xBB, 0x43, - 0xFB, 0x0B, 0xFC, 0xDF, 0x77, 0x7D, 0xC5, 0x30, 0x9E, 0x51, 0xE1, 0x34, 0xBD, 0xA0, 0x0C, 0x0E, - 0xD6, 0xF5, 0xD3, 0xA6, 0xFA, 0x43, 0xF7, 0x27, 0x8C, 0xE0, 0x54, 0x0C, 0x95, 0xC2, 0x9B, 0x34, - 0xA6, 0xF9, 0x0E, 0xF9, 0x3F, 0xC9, 0x17, 0xE0, 0x1B, 0xFD, 0xDE, 0x91, 0xA5, 0xBC, 0xBA, 0x63, - 0xCB, 0x17, 0x21, 0x9F, 0x8A, 0xA6, 0x89, 0xDB, 0xBB, 0xCF, 0xDD, 0x8B, 0xE0, 0x06, 0x05, 0xE6, - 0xEF, 0x90, 0xEF, 0xD4, 0x40, 0xFF, 0x8E, 0x3E, 0x24, 0x0A, 0xC6, 0x13, 0x00, 0xD7, 0x1F, 0x5B, - 0x98, 0xBC, 0xE8, 0xCC, 0x3D, 0x66, 0x77, 0x96, 0xA3, 0x8E, 0x76, 0x5A, 0xAD, 0x77, 0x00, 0x6A, - 0x76, 0xF1, 0xB7, 0xBF, 0xEE, 0xEC, 0xB7, 0xF1, 0xAF, 0x4B, 0x80, 0x9E, 0x07, 0x2C, 0xD9, 0x55, - 0x74, 0x75, 0xE7, 0xF0, 0xFD, 0xE4, 0x91, 0x28, 0x1B, 0xC0, 0x1E, 0xDB, 0xB1, 0xA7, 0xF0, 0xF1, - 0x5D, 0x13, 0x3E, 0xBE, 0xA6, 0xE0, 0x04, 0x89, 0xC5, 0x15, 0x5D, 0x2E, 0xD4, 0xB2, 0x29, 0xB6, - 0xD8, 0x75, 0x42, 0x6A, 0xD3, 0x95, 0x87, 0x2B, 0xE4, 0x32, 0xA3, 0xCF, 0x1C, 0xA9, 0xED, 0xF7, - 0xD5, 0xB0, 0xA1, 0x60, 0xB0, 0xB2, 0x0C, 0x48, 0xB4, 0x63, 0x3B, 0x4A, 0xE3, 0xA1, 0xA1, 0x34, - 0x66, 0x42, 0xBF, 0x87, 0x07, 0x8D, 0x28, 0x92, 0xFB, 0x16, 0xF8, 0xD1, 0x0B, 0xDC, 0xED, 0x0B, - 0x06, 0x42, 0x26, 0x28, 0x51, 0x07, 0x5E, 0xF2, 0x0B, 0xA0, 0x12, 0x77, 0x2C, 0x0E, 0x42, 0xA4, - 0x48, 0xB4, 0xF1, 0xEA, 0xA6, 0x6A, 0xF8, 0xC8, 0x05, 0xB0, 0xD2, 0x8F, 0x89, 0x6E, 0x1D, 0x6E, - 0x83, 0x7D, 0xB1, 0x90, 0x35, 0x50, 0xA9, 0x2D, 0xC5, 0x60, 0xDD, 0xDB, 0x1E, 0x16, 0xB2, 0xF0, - 0x0D, 0x4A, 0x1E, 0x16, 0x34, 0x88, 0x06, 0x19, 0x35, 0x8E, 0xC6, 0x5B, 0x32, 0x2E, 0x44, 0xC6, - 0x21, 0xFA, 0x95, 0x21, 0xE0, 0xA0, 0xD1, 0xCB, 0x92, 0x6E, 0x86, 0x6A, 0x9E, 0xA5, 0x9B, 0xF7, - 0x9F, 0x41, 0xB8, 0x1A, 0x6F, 0xFA, 0x95, 0x9F, 0x58, 0xC5, 0x5C, 0xDA, 0x77, 0xAC, 0xE9, 0x34, - 0x88, 0x63, 0xF0, 0x49, 0x68, 0xDD, 0xAE, 0x68, 0xFA, 0xE2, 0xD7, 0x77, 0x33, 0x96, 0x30, 0xA7, - 0xBA, 0xED, 0xDB, 0x86, 0xA5, 0x68, 0x5F, 0xF8, 0xD3, 0xA5, 0xEE, 0x8C, 0xB1, 0x2C, 0xEB, 0xB9, - 0xFE, 0x58, 0xA4, 0xBA, 0x65, 0x21, 0x35, 0x67, 0xAA, 0xF3, 0xDA, 0x89, 0x84, 0x72, 0xF0, 0x20, - 0x27, 0xE3, 0x28, 0x31, 0x28, 0x8A, 0xE7, 0xF0, 0x1E, 0x82, 0x26, 0x7F, 0xE3, 0x0E, 0x72, 0xC5, - 0x6F, 0xF6, 0xD0, 0x51, 0x40, 0x69, 0xC9, 0x8C, 0x72, 0x78, 0x6C, 0x36, 0x9A, 0xF3, 0x58, 0xD2, - 0xB3, 0x8F, 0xBB, 0x19, 0x04, 0x3D, 0xCB, 0x9F, 0xF5, 0x0C, 0xE1, 0x12, 0x05, 0xC2, 0x5C, 0x3E, - 0xAD, 0xA1, 0xD5, 0x4F, 0x4D, 0x74, 0x87, 0x36, 0x3E, 0x1A, 0x82, 0x2E, 0x0B, 0xE1, 0x8B, 0x10, - 0xB8, 0x13, 0x8C, 0x5B, 0x91, 0x62, 0x27, 0xA6, 0xD1, 0xB7, 0x15, 0xE7, 0xE1, 0xD2, 0xA7, 0xEB, - 0x48, 0x97, 0x73, 0xBA, 0xDA, 0x84, 0x59, 0x0D, 0xE4, 0xAC, 0x48, 0xCE, 0x0D, 0xCB, 0x68, 0x84, - 0x17, 0x9C, 0xC2, 0x4D, 0x66, 0xAD, 0x74, 0xBA, 0x08, 0xE3, 0x0F, 0x26, 0x1F, 0xEC, 0x25, 0x3A, - 0xFA, 0x0A, 0x1E, 0xFF, 0xB2, 0x9E, 0xFD, 0xB7, 0x67, 0x13, 0xD2, 0x12, 0x46, 0x99, 0x53, 0xEE, - 0x29, 0x11, 0x0C, 0x58, 0x8D, 0xCB, 0x7E, 0x74, 0x1A, 0x2B, 0x16, 0xAE, 0x68, 0xBD, 0x21, 0x6E, - 0x21, 0xD7, 0x57, 0x74, 0xD3, 0x95, 0xF7, 0xE0, 0x78, 0xDD, 0xC7, 0x06, 0x5C, 0xF1, 0x7C, 0xBC, - 0x63, 0x07, 0x6A, 0x60, 0x63, 0xE5, 0x99, 0x99, 0x16, 0x79, 0xE5, 0x83, 0x62, 0x05, 0x53, 0x47, - 0xE1, 0xCA, 0xC3, 0x0B, 0x77, 0xD0, 0xA8, 0x38, 0x1E, 0x23, 0x84, 0x92, 0x03, 0x9D, 0x83, 0x74, - 0x85, 0x29, 0x85, 0xD7, 0xDD, 0xF5, 0xEA, 0x65, 0xF1, 0xAF, 0xEB, 0x7B, 0x56, 0xB0, 0xF5, 0xDF, - 0x6C, 0xD8, 0x4C, 0x1E, 0x5A, 0x4B, 0xF1, 0x2B, 0x2C, 0x56, 0xAD, 0x86, 0xD8, 0x98, 0x5F, 0xB2, - 0x8C, 0x7A, 0x58, 0x59, 0xA0, 0x49, 0xDA, 0xE4, 0x57, 0x8C, 0xBD, 0x59, 0x09, 0x20, 0x6C, 0xEE, - 0xE8, 0x16, 0x7A, 0x4E, 0xA2, 0xC1, 0x41, 0x0D, 0xB9, 0x7B, 0x94, 0x8F, 0x36, 0x18, 0x34, 0x56, - 0xE8, 0x91, 0xED, 0x58, 0x9A, 0x2F, 0xDC, 0x4A, 0x1E, 0xC5, 0xE9, 0x98, 0xCE, 0x6D, 0x77, 0xF1, - 0x22, 0x3C, 0x70, 0x19, 0x41, 0x63, 0x9B, 0xC8, 0x62, 0xAC, 0x04, 0x3B, 0x85, 0xA3, 0x6D, 0x36, - 0xBE, 0xC7, 0x37, 0x97, 0x16, 0x15, 0xDF, 0xE1, 0x45, 0xEA, 0x82, 0xCF, 0xA5, 0xF2, 0xA6, 0xAA, - 0xBE, 0x11, 0xC4, 0xA3, 0x13, 0xE5, 0x46, 0x37, 0x7D, 0x40, 0xFC, 0x62, 0xC5, 0x25, 0x67, 0x38, - 0x3F, 0x89, 0x1C, 0x17, 0xEF, 0xA6, 0x94, 0x66, 0xD9, 0x7F, 0xC4, 0x75, 0x1C, 0x06, 0x75, 0x8F, - 0x5F, 0xB8, 0x34, 0x26, 0xE2, 0x6F, 0xC8, 0x24, 0x42, 0x84, 0xF5, 0x69, 0x9F, 0x10, 0x6F, 0x43, - 0xCA, 0x98, 0x4A, 0xA6, 0x9D, 0x4A, 0x10, 0x4C, 0x99, 0xF8, 0xF8, 0x92, 0xBB, 0xD4, 0x58, 0xAE, - 0x7A, 0x84, 0x6E, 0x1D, 0x9C, 0xB6, 0x39, 0xA6, 0x25, 0xEF, 0x03, 0xE0, 0x76, 0x5A, 0xB0, 0x9E, - 0xE7, 0xB7, 0x9B, 0x57, 0x35, 0xB3, 0x60, 0x1D, 0xD9, 0xC2, 0x8E, 0xB3, 0x88, 0x4E, 0xEE, 0x18, - 0x38, 0x80, 0x54, 0x8F, 0xB3, 0x50, 0xB4, 0xC0, 0x90, 0xF6, 0xCC, 0x1E, 0xE6, 0x55, 0x9A, 0x8B, - 0xB8, 0x1B, 0x97, 0x77, 0xAC, 0x0D, 0x2F, 0xF4, 0xB3, 0x8D, 0x5C, 0x8A, 0xA1, 0x0F, 0x4D, 0xE0, - 0x14, 0x64, 0xB0, 0x13, 0xD0, 0x81, 0xC7, 0x9F, 0xB8, 0x17, 0x93, 0xE9, 0x8B, 0x47, 0x53, 0xE5, - 0x2A, 0x0C, 0xC9, 0xAE, 0x0B, 0x04, 0x2F, 0x17, 0xD4, 0x1D, 0x86, 0xB1, 0x9E, 0x51, 0x73, 0x10, - 0x5C, 0x11, 0x45, 0xF5, 0xC7, 0x4E, 0xA3, 0xB5, 0xDF, 0x68, 0x1D, 0x14, 0xD1, 0x1A, 0x04, 0x2C, - 0x4E, 0x3E, 0xC0, 0xC1, 0x33, 0xA4, 0x80, 0xE1, 0xA8, 0x8C, 0x2C, 0xBA, 0xEC, 0xC9, 0xAF, 0x4E, - 0x15, 0x27, 0x3C, 0x7C, 0x5B, 0xED, 0x1A, 0x50, 0xE6, 0x77, 0xF8, 0xA3, 0xD9, 0xCC, 0xE7, 0x16, - 0x12, 0xA2, 0x4F, 0xBA, 0xE6, 0x8D, 0x8E, 0x3B, 0xCD, 0x26, 0x85, 0x83, 0x03, 0x8A, 0xC8, 0x8E, - 0x0B, 0x19, 0x6C, 0xD2, 0xE7, 0x34, 0x23, 0x4C, 0xAF, 0xF3, 0xEE, 0xBF, 0xE6, 0x98, 0x6E, 0xE4, - 0xDA, 0xAB, 0x32, 0xBC, 0x16, 0x51, 0xAF, 0x93, 0x8A, 0x62, 0xC1, 0x5C, 0x73, 0x03, 0xDD, 0x00, - 0xEC, 0x11, 0x05, 0x21, 0xEE, 0x81, 0x49, 0xD1, 0x47, 0x32, 0x67, 0xF8, 0xF7, 0x63, 0xDD, 0x0B, - 0xD0, 0xE0, 0x92, 0x9E, 0x5B, 0xA6, 0x4A, 0x5E, 0x71, 0x51, 0x98, 0xA1, 0xF6, 0xFE, 0xB3, 0xA2, - 0x7B, 0x18, 0x30, 0xB9, 0x97, 0x3D, 0xA8, 0x78, 0x91, 0x9D, 0x5E, 0x7D, 0x99, 0xC3, 0xAB, 0xB3, - 0x32, 0xCF, 0xC2, 0x00, 0x93, 0xE1, 0xAC, 0xF0, 0x4D, 0xDD, 0x7B, 0xE3, 0x4E, 0x0E, 0x86, 0xFB, - 0x67, 0x26, 0x4C, 0x11, 0x74, 0x05, 0xC3, 0x00, 0x16, 0x48, 0x3F, 0x08, 0x8F, 0xC9, 0xB5, 0x50, - 0x98, 0x6D, 0x93, 0xD9, 0x23, 0xA0, 0x5D, 0x0C, 0xBF, 0xEB, 0x9D, 0xAD, 0xDA, 0xE5, 0x2F, 0xDB, - 0xB5, 0x28, 0x89, 0xCE, 0xB8, 0x9A, 0xB2, 0xD1, 0xA6, 0x59, 0xD8, 0x99, 0xCA, 0xFE, 0x26, 0x61, - 0x79, 0x8A, 0xEB, 0xF5, 0x3D, 0x14, 0x9D, 0xA6, 0x0A, 0x9B, 0xE4, 0x9A, 0x87, 0x48, 0xDA, 0x09, - 0x3B, 0x08, 0xAD, 0x3F, 0x57, 0xB0, 0x3F, 0x18, 0xFF, 0x42, 0x4F, 0x4B, 0xD5, 0x35, 0x99, 0xF4, - 0x15, 0x9F, 0xDB, 0xA2, 0xB5, 0x4C, 0x9A, 0xB5, 0x93, 0x5B, 0x8B, 0xF2, 0xCD, 0x95, 0x2C, 0x67, - 0xD2, 0xAA, 0x9D, 0x9C, 0x2A, 0x2E, 0x2F, 0xDD, 0xAE, 0x8D, 0xD9, 0x18, 0x7B, 0xEB, 0x51, 0x05, - 0xA5, 0xE7, 0x0B, 0xF7, 0x58, 0x61, 0xE5, 0xC4, 0x68, 0x55, 0x0B, 0x84, 0xDA, 0x47, 0xCC, 0xC2, - 0x28, 0x2E, 0x4B, 0x1D, 0x06, 0x73, 0x15, 0xCE, 0x1D, 0x41, 0x02, 0x87, 0x1E, 0x25, 0x70, 0xF8, - 0x6A, 0xE2, 0x97, 0xE4, 0x61, 0xD6, 0x58, 0xFB, 0x7C, 0x34, 0x86, 0x35, 0xBC, 0xB3, 0xFA, 0xE7, - 0x67, 0x4A, 0x66, 0x51, 0xA1, 0x15, 0xC4, 0x39, 0x0F, 0xE1, 0xB8, 0x1E, 0x62, 0xA8, 0xF3, 0x10, - 0xCF, 0xDC, 0xFE, 0x39, 0xC3, 0xE9, 0xAC, 0x26, 0xE8, 0x59, 0x0E, 0xBD, 0xBA, 0x84, 0x9F, 0x0A, - 0x48, 0xE0, 0xAA, 0x03, 0x20, 0x27, 0x5B, 0x34, 0x23, 0x23, 0x9F, 0x47, 0x3C, 0x96, 0xD2, 0x7B, - 0x86, 0x65, 0xB6, 0x43, 0x95, 0x14, 0x76, 0x68, 0x98, 0xE6, 0x32, 0xB4, 0x71, 0xA1, 0xCC, 0x31, - 0x90, 0xE7, 0xA9, 0x9C, 0xC5, 0x2D, 0x38, 0x45, 0xF5, 0xCD, 0x28, 0xF7, 0x05, 0x79, 0x0B, 0xE6, - 0x81, 0x31, 0x6B, 0xB5, 0xB9, 0x34, 0x47, 0xE5, 0x3B, 0x93, 0xEB, 0xC8, 0x15, 0xD8, 0x70, 0x10, - 0xB6, 0x03, 0x5A, 0xD7, 0xDB, 0xE3, 0x72, 0x26, 0x84, 0xC5, 0xB5, 0xCA, 0xC0, 0xB3, 0x08, 0x3D, - 0x3D, 0x90, 0x95, 0xC1, 0xAA, 0x11, 0x9B, 0x18, 0x06, 0x5A, 0x90, 0x09, 0x44, 0x1D, 0xE9, 0xFC, - 0x11, 0x11, 0xCF, 0x10, 0x8B, 0x91, 0x8A, 0x24, 0x27, 0x6F, 0x8A, 0x89, 0x87, 0x07, 0x1F, 0xF8, - 0x04, 0x37, 0x66, 0x60, 0xB8, 0x0C, 0xBE, 0x67, 0x58, 0xF0, 0x03, 0x04, 0xBE, 0xF1, 0x2E, 0x85, - 0x6B, 0x9A, 0x38, 0xA7, 0x5D, 0x2A, 0x14, 0x0F, 0x4A, 0xAB, 0xEB, 0x3B, 0x8F, 0xFC, 0x99, 0xB2, - 0xD1, 0x2A, 0xD0, 0x99, 0x83, 0xB6, 0xC7, 0xE8, 0x15, 0x2F, 0x8C, 0x9E, 0x54, 0x38, 0xA5, 0x52, - 0x3A, 0x09, 0xF2, 0xC4, 0xC6, 0xED, 0xA3, 0xA3, 0xC9, 0x37, 0x05, 0x75, 0xD1, 0xA5, 0xE9, 0xA1, - 0xC5, 0x8C, 0x35, 0xC5, 0x4D, 0x74, 0xA5, 0x75, 0xCF, 0x08, 0xCA, 0x16, 0x12, 0xF2, 0x27, 0xEF, - 0xAF, 0x2C, 0x12, 0x7A, 0x7E, 0x4A, 0x14, 0x7E, 0x08, 0x8B, 0xD0, 0x62, 0xEE, 0x06, 0xA2, 0x40, - 0x2F, 0xFD, 0x1D, 0x24, 0x39, 0x2E, 0x95, 0xDA, 0x80, 0x70, 0xE2, 0x28, 0x1F, 0x27, 0x38, 0x61, - 0xA2, 0x44, 0x62, 0x0C, 0xD8, 0x3C, 0x06, 0xEF, 0x60, 0x5A, 0xFB, 0x34, 0xBA, 0xA3, 0xEF, 0x28, - 0x48, 0x9C, 0x52, 0x5E, 0x18, 0x74, 0x28, 0xC8, 0xBC, 0xB7, 0x8A, 0x20, 0x46, 0x41, 0x74, 0xAF, - 0x9C, 0xAE, 0x96, 0x48, 0x58, 0x12, 0x03, 0x4B, 0x90, 0x96, 0x68, 0xB1, 0x54, 0xE2, 0x92, 0x02, - 0x9A, 0xD0, 0x45, 0xE5, 0x10, 0x05, 0xC8, 0x2B, 0x42, 0x97, 0x05, 0x0C, 0xB8, 0x53, 0x9A, 0x49, - 0x62, 0xC0, 0x08, 0x69, 0xC7, 0x8C, 0x2B, 0x24, 0xAE, 0x91, 0xBA, 0x88, 0x5A, 0xC8, 0xB1, 0x40, - 0x91, 0xC2, 0x06, 0xC3, 0xC8, 0xD2, 0xBE, 0x28, 0xE3, 0x19, 0x37, 0xD6, 0xFD, 0xCB, 0x8B, 0xDF, - 0x61, 0xA4, 0x86, 0x7F, 0xFF, 0xBD, 0x52, 0x3B, 0xE0, 0x02, 0x56, 0xB3, 0xC5, 0x98, 0xDF, 0x22, - 0xA9, 0xFD, 0x66, 0x5B, 0xC9, 0xC8, 0x29, 0xF2, 0x0B, 0x7F, 0x02, 0x70, 0x55, 0x60, 0x1F, 0x9B, - 0xB2, 0x93, 0x45, 0xBA, 0x47, 0x23, 0x59, 0x1F, 0x3F, 0xD2, 0xD5, 0x3A, 0x3C, 0x28, 0x96, 0x1F, - 0x6A, 0x79, 0x32, 0xCE, 0x99, 0x61, 0x61, 0x86, 0x3D, 0xB2, 0x59, 0xF8, 0x8E, 0x83, 0x91, 0x22, - 0xC8, 0x5C, 0xD1, 0x7F, 0x8C, 0xA6, 0xED, 0x4A, 0x8E, 0x6B, 0x99, 0x7C, 0x43, 0x58, 0x5E, 0xB5, - 0xD8, 0x19, 0xEA, 0x6C, 0xAD, 0x04, 0x11, 0x57, 0x76, 0xE7, 0x79, 0xDB, 0x0B, 0x95, 0xA9, 0xE0, - 0xAE, 0xF3, 0xB6, 0x17, 0x48, 0xC9, 0x2B, 0xBB, 0xBC, 0x9C, 0xCC, 0xE2, 0xE5, 0x72, 0xE4, 0x45, - 0xAF, 0x2F, 0x11, 0x21, 0x03, 0xE7, 0xCC, 0x5B, 0x3E, 0xE0, 0x0E, 0x66, 0xAC, 0x67, 0x3D, 0xCB, - 0xD5, 0x65, 0x82, 0x21, 0x6B, 0x2C, 0x52, 0x56, 0xB5, 0x9A, 0xCD, 0x83, 0x3D, 0xF8, 0x71, 0x18, - 0x0A, 0x04, 0xA1, 0xDB, 0xB3, 0x08, 0xD2, 0x1D, 0xBE, 0x9A, 0x3B, 0xC8, 0x70, 0x8F, 0xD6, 0xE2, - 0xDA, 0x71, 0x32, 0x1D, 0xCA, 0x66, 0x02, 0x48, 0x35, 0x97, 0x18, 0x0A, 0xDD, 0x14, 0xE2, 0x2A, - 0x72, 0x2C, 0x16, 0x0C, 0xC6, 0x76, 0xDC, 0xB7, 0x6B, 0x70, 0xE5, 0x88, 0xB4, 0x1A, 0x28, 0x81, - 0xC9, 0x4B, 0xC6, 0x19, 0xF8, 0x1B, 0xB7, 0x51, 0xA0, 0x1D, 0x4C, 0x97, 0xEB, 0x92, 0x45, 0xE3, - 0x92, 0x49, 0x1A, 0xB6, 0x57, 0x8A, 0x09, 0xE9, 0x33, 0x05, 0xFD, 0x0A, 0x5F, 0x26, 0x4E, 0xB7, - 0x5D, 0xFE, 0x35, 0x62, 0xA5, 0xD6, 0x9F, 0x1B, 0x0A, 0xC3, 0xA8, 0xC0, 0x06, 0x24, 0x8F, 0x37, - 0x68, 0x26, 0xFC, 0x6C, 0x97, 0x73, 0xC6, 0xC9, 0xC9, 0xDF, 0x5E, 0x7D, 0xB9, 0xF8, 0x25, 0x3C, - 0xE5, 0xE8, 0xD3, 0xAA, 0xCF, 0xB9, 0xD8, 0x4C, 0xD6, 0xE3, 0xA4, 0x13, 0x70, 0x88, 0x15, 0x82, - 0x94, 0x5C, 0x41, 0x98, 0x74, 0x9F, 0x74, 0x6F, 0x24, 0xD3, 0xC1, 0x82, 0xA8, 0x66, 0x86, 0x8C, - 0x82, 0x64, 0x34, 0x52, 0x23, 0x34, 0xE9, 0x5F, 0xFC, 0x5A, 0x0E, 0xBA, 0xE8, 0x26, 0x2D, 0x7C, - 0xD4, 0x91, 0xBF, 0x2F, 0x50, 0xF3, 0x77, 0xD4, 0x98, 0xCE, 0x25, 0xA4, 0x52, 0x2F, 0x9F, 0x8A, - 0x38, 0xB3, 0x25, 0x0F, 0x41, 0x9A, 0x63, 0xB4, 0xE7, 0xB9, 0x8A, 0xC6, 0x50, 0x2F, 0x85, 0xD8, - 0x6F, 0x6C, 0xBF, 0x8F, 0x4B, 0x70, 0xD9, 0xD8, 0xBD, 0x57, 0xCA, 0xAC, 0x11, 0x4C, 0xD9, 0x8B, - 0x29, 0x7A, 0x0F, 0x36, 0xFB, 0x4E, 0xAC, 0xC5, 0x3E, 0x5B, 0x7E, 0x81, 0x4B, 0xB1, 0xD9, 0x17, - 0x64, 0x87, 0xD4, 0x8B, 0xBB, 0x50, 0x37, 0x98, 0x80, 0x63, 0xBF, 0x82, 0x7E, 0x00, 0x5D, 0x5A, - 0x07, 0x4C, 0xBA, 0xA2, 0x14, 0xEF, 0x69, 0xF6, 0x55, 0xDC, 0xF2, 0x95, 0xBE, 0x6C, 0x96, 0x13, - 0xCF, 0x10, 0x15, 0xB8, 0x3C, 0xED, 0xB1, 0x11, 0x82, 0x2A, 0x88, 0x21, 0x54, 0xA4, 0xA3, 0x94, - 0x41, 0xB6, 0x39, 0xCB, 0xE6, 0x66, 0xEC, 0x9A, 0x25, 0x80, 0xEC, 0x26, 0xE9, 0x8B, 0x25, 0xF8, - 0xC8, 0xD7, 0x7B, 0xAC, 0x56, 0x4E, 0xF4, 0x11, 0x48, 0x0F, 0xD5, 0xB2, 0x13, 0x18, 0x60, 0x86, - 0x44, 0x5D, 0x25, 0x37, 0xB1, 0x26, 0x4B, 0x09, 0x8F, 0x95, 0xC5, 0x98, 0x4A, 0x6C, 0xEE, 0x21, - 0x4F, 0x49, 0x5B, 0x51, 0x45, 0x2C, 0xC5, 0x5D, 0x94, 0x9D, 0xB4, 0x17, 0xE6, 0x24, 0x07, 0x8B, - 0xF3, 0x90, 0xE6, 0x62, 0x5D, 0xEC, 0x23, 0x1B, 0x5A, 0xAC, 0x8B, 0x83, 0xDA, 0x49, 0x67, 0xC1, - 0x59, 0x60, 0x36, 0x9D, 0xE6, 0xAB, 0xE0, 0x82, 0xFC, 0x91, 0x03, 0xB3, 0x49, 0xC9, 0x94, 0x17, - 0x4B, 0xAC, 0xFA, 0x7A, 0xCC, 0x61, 0x15, 0x39, 0x9F, 0x09, 0x8F, 0x43, 0xC0, 0x05, 0xCF, 0xB2, - 0xBC, 0x11, 0xA5, 0x91, 0xBE, 0x03, 0x91, 0xBC, 0x34, 0x77, 0x8C, 0x72, 0xC4, 0xE9, 0xEE, 0x6A, - 0x27, 0xA7, 0xC1, 0x33, 0xD6, 0x73, 0x2C, 0xCF, 0x02, 0xFE, 0x57, 0xCA, 0xEB, 0x27, 0xA5, 0xCB, - 0x8C, 0x99, 0x57, 0xE0, 0x07, 0xD4, 0xEF, 0xF5, 0xE6, 0xF2, 0x02, 0xBA, 0xBE, 0x98, 0xC7, 0x09, - 0x08, 0x46, 0x63, 0xFF, 0xC4, 0xE6, 0x69, 0x0C, 0x7B, 0xF1, 0x75, 0x30, 0x58, 0x0F, 0x0F, 0xA2, - 0xB3, 0xB0, 0xC8, 0x0B, 0x66, 0xB4, 0x47, 0xCB, 0xCA, 0x19, 0xF6, 0xAA, 0xAB, 0x6C, 0xB2, 0xF3, - 0x22, 0x8F, 0x2E, 0xC3, 0x0A, 0x7D, 0x88, 0x05, 0x24, 0x8C, 0xEC, 0xC0, 0xF2, 0xDF, 0xEE, 0x46, - 0x5E, 0xBA, 0xB6, 0x9E, 0xEA, 0x17, 0x26, 0x77, 0x86, 0xCF, 0x6C, 0x07, 0x80, 0xF2, 0x96, 0xD2, - 0xE0, 0x7B, 0xBE, 0x63, 0x46, 0xDE, 0xB1, 0x06, 0x83, 0x08, 0x5D, 0x87, 0x00, 0x5C, 0x7F, 0x07, - 0xA4, 0x7B, 0xCE, 0x6D, 0xAA, 0x91, 0x2D, 0xA2, 0x90, 0x97, 0x55, 0x62, 0xED, 0x94, 0x86, 0x89, - 0xC4, 0xE1, 0x68, 0x3A, 0xFE, 0x16, 0x8F, 0x97, 0x5D, 0x70, 0x2D, 0x18, 0x7C, 0xD9, 0x69, 0x24, - 0x65, 0xB1, 0x75, 0x59, 0x57, 0xE1, 0xDE, 0xFF, 0xF3, 0x4F, 0x74, 0xFD, 0xB7, 0x28, 0x11, 0x2A, - 0x53, 0x7C, 0xAA, 0x91, 0xC0, 0xB9, 0x76, 0xAF, 0x60, 0x46, 0x48, 0x61, 0x58, 0xF6, 0x5D, 0xCC, - 0xE6, 0x51, 0xC2, 0xB7, 0x68, 0x3D, 0xB0, 0x66, 0xCC, 0x15, 0xD7, 0x77, 0x08, 0x3A, 0x7D, 0x55, - 0x31, 0x16, 0x63, 0xCE, 0xC9, 0xCE, 0x6A, 0x27, 0x37, 0x93, 0x27, 0x8C, 0x1E, 0x95, 0xE2, 0xCC, - 0x53, 0xFD, 0xA5, 0x4E, 0xB9, 0x02, 0xAE, 0x7C, 0xC3, 0x61, 0xAB, 0xDD, 0x79, 0x18, 0xF3, 0x25, - 0xE7, 0xDE, 0xDE, 0x15, 0xDA, 0x8D, 0xDC, 0xF5, 0x60, 0x96, 0xE7, 0xE2, 0xDE, 0x57, 0x96, 0xDB, - 0xC2, 0x9A, 0x1E, 0x3E, 0xD5, 0xD2, 0xD2, 0x4D, 0x36, 0xA6, 0x55, 0x22, 0xCF, 0x03, 0xE4, 0xF5, - 0xA4, 0x83, 0x84, 0x66, 0x81, 0x42, 0x87, 0x31, 0x8B, 0xCA, 0x60, 0x80, 0x90, 0xA7, 0x92, 0xC0, - 0x22, 0x7B, 0x13, 0xB0, 0x47, 0xD3, 0x78, 0x9E, 0xD0, 0x81, 0x0C, 0x92, 0xA1, 0x5E, 0x45, 0x11, - 0x2E, 0x79, 0xC9, 0x1C, 0x95, 0x84, 0x04, 0x28, 0x37, 0x21, 0x99, 0x69, 0xE5, 0xAC, 0x11, 0x83, - 0xC2, 0xC8, 0x5B, 0x35, 0x25, 0x4A, 0xF1, 0x5C, 0xC0, 0x0E, 0xBE, 0xC6, 0x5B, 0xD4, 0x65, 0xF3, - 0xC9, 0xC8, 0x4C, 0x5E, 0xA8, 0xC6, 0x74, 0x2C, 0xC4, 0xD0, 0x11, 0xAB, 0x9E, 0xB8, 0xE4, 0x8C, - 0xB8, 0x61, 0xA3, 0x4F, 0x0E, 0x25, 0xC6, 0xD5, 0xB8, 0x6D, 0x58, 0xCF, 0xC2, 0x79, 0x5E, 0x76, - 0xA1, 0x63, 0x46, 0x5E, 0x20, 0x71, 0xCB, 0x43, 0x19, 0x5C, 0x95, 0x99, 0x8C, 0xA6, 0x72, 0x74, - 0xAD, 0x3D, 0x77, 0x4D, 0x04, 0x0B, 0xD2, 0x96, 0x54, 0x52, 0xB3, 0xB2, 0x6C, 0x3A, 0x1C, 0x87, - 0xDF, 0x83, 0x74, 0x13, 0x44, 0x59, 0x55, 0x10, 0xE4, 0x37, 0x53, 0xCB, 0x90, 0xFB, 0xED, 0x1E, - 0xAF, 0xDE, 0x8C, 0x3E, 0x09, 0xF9, 0x93, 0x93, 0x98, 0x19, 0xEA, 0x47, 0x39, 0x4E, 0x0B, 0x45, - 0xF6, 0x6D, 0x6E, 0xC2, 0x9B, 0x39, 0xEF, 0xD3, 0xE2, 0x18, 0x93, 0x9B, 0xC2, 0x20, 0xF6, 0xFA, - 0x3C, 0xB7, 0x67, 0x39, 0xFA, 0xE5, 0x6A, 0x39, 0xF9, 0xA5, 0xA2, 0x7A, 0x96, 0x33, 0xC9, 0xA2, - 0x1B, 0x56, 0x35, 0x14, 0xCF, 0x23, 0xC9, 0x6E, 0x97, 0xCB, 0xC7, 0x93, 0xF3, 0xC8, 0xBB, 0xA1, - 0xAA, 0x8E, 0xAF, 0x27, 0x57, 0x2A, 0xE8, 0x85, 0x3B, 0x18, 0xB1, 0x81, 0x34, 0x82, 0xE2, 0x2E, - 0x16, 0xF2, 0x44, 0x6F, 0x4A, 0x21, 0x0B, 0x38, 0x61, 0x4D, 0x9A, 0x50, 0x60, 0x90, 0x85, 0x06, - 0x48, 0x74, 0x76, 0x41, 0x31, 0x7F, 0x08, 0x5B, 0x34, 0x58, 0x17, 0x3A, 0x11, 0xCE, 0x97, 0x26, - 0xDE, 0x6A, 0x61, 0x20, 0xD5, 0x58, 0xD1, 0x29, 0xBF, 0x02, 0x39, 0x6F, 0xA6, 0xD6, 0x47, 0x9C, - 0x8C, 0xB1, 0xA4, 0x5A, 0x88, 0xAB, 0x3C, 0x36, 0x8A, 0x61, 0x74, 0xAD, 0x6C, 0x36, 0xE8, 0x41, - 0x12, 0x67, 0x16, 0xCD, 0x00, 0x9D, 0x40, 0xC2, 0x58, 0x7D, 0xC3, 0x30, 0xFD, 0xF3, 0x34, 0x65, - 0xCC, 0x4C, 0x72, 0x6D, 0xA7, 0x4D, 0xB5, 0x82, 0x88, 0xB3, 0x72, 0x09, 0xA5, 0x2F, 0xB0, 0x76, - 0x99, 0xC9, 0x5F, 0x2E, 0x9D, 0x34, 0x97, 0x13, 0x58, 0x42, 0x32, 0xE9, 0x8B, 0x44, 0xD7, 0xA5, - 0x92, 0x59, 0x25, 0x1A, 0x4F, 0x0D, 0x59, 0x2C, 0x1C, 0x39, 0x01, 0xDE, 0x44, 0xD6, 0xAB, 0x70, - 0xED, 0x2F, 0x9D, 0x69, 0x3A, 0xB1, 0xD8, 0x75, 0x2C, 0x6E, 0x2F, 0x67, 0x78, 0xFE, 0xF9, 0xAC, - 0x07, 0x67, 0x51, 0x00, 0x56, 0x1F, 0x3D, 0x35, 0xF1, 0xD9, 0x12, 0x8F, 0xA1, 0xE8, 0xC8, 0x13, - 0xCE, 0xA0, 0x8D, 0x54, 0x3B, 0x98, 0x06, 0xF0, 0x83, 0xEC, 0x4A, 0x3A, 0xAB, 0x39, 0xAC, 0xA2, - 0x4A, 0x48, 0x08, 0x1D, 0x3A, 0xB0, 0xB0, 0x24, 0x21, 0xCE, 0xBD, 0x11, 0xE8, 0x0C, 0xC8, 0xAB, - 0xF0, 0xA1, 0x22, 0x13, 0x9E, 0x5E, 0xF5, 0x58, 0x57, 0xD4, 0x95, 0xDE, 0x65, 0xE7, 0x5F, 0xFA, - 0xBB, 0xEC, 0x93, 0xE2, 0xF1, 0x27, 0xA9, 0x3F, 0xF7, 0xFD, 0x7B, 0xEC, 0xE9, 0x46, 0x71, 0x1F, - 0x36, 0xC8, 0xB4, 0x33, 0x3B, 0xE0, 0x96, 0x96, 0x7D, 0xD5, 0xEB, 0xCB, 0x83, 0x58, 0x20, 0x7D, - 0x00, 0xB4, 0x65, 0xA9, 0x1F, 0x01, 0x1A, 0x5D, 0xF5, 0x62, 0x89, 0x38, 0x0F, 0xA6, 0xB4, 0x8C, - 0xCB, 0xC4, 0xA6, 0xBC, 0x80, 0x06, 0x81, 0xE8, 0x42, 0xD1, 0x84, 0xF2, 0x8C, 0x4B, 0x43, 0x29, - 0xD2, 0x15, 0x92, 0x08, 0xF4, 0x9A, 0x72, 0x62, 0x1E, 0x94, 0xC9, 0x86, 0x89, 0xF3, 0x9E, 0x91, - 0x0B, 0x33, 0xB2, 0xF9, 0x85, 0xA2, 0x42, 0x26, 0xEF, 0xAF, 0x2E, 0x03, 0x66, 0xA5, 0x58, 0x0E, - 0x7C, 0x24, 0x07, 0xCD, 0xE1, 0x8D, 0x75, 0xC6, 0x6C, 0x5C, 0xC0, 0x16, 0x99, 0x67, 0x22, 0x73, - 0x3E, 0x88, 0x12, 0xD8, 0x0C, 0x0D, 0x36, 0x14, 0x9D, 0xE5, 0x89, 0x98, 0x83, 0xD2, 0xF2, 0xAD, - 0x75, 0x46, 0xEB, 0x60, 0x21, 0x5B, 0xD4, 0x9E, 0x89, 0xDA, 0xC5, 0xC0, 0x94, 0x40, 0x6F, 0xD9, - 0x68, 0x43, 0x51, 0x5C, 0x08, 0x7A, 0x39, 0x18, 0x1E, 0x91, 0x06, 0xD7, 0x19, 0xCB, 0x5D, 0x31, - 0xCD, 0x31, 0x4C, 0x73, 0x8B, 0xE9, 0xB3, 0x31, 0x5D, 0x6E, 0x7B, 0x29, 0x44, 0x17, 0x6D, 0xD6, - 0x20, 0xAD, 0x7E, 0xB6, 0x98, 0x3F, 0x6F, 0xAD, 0xD4, 0x60, 0x89, 0x5F, 0x3C, 0x1B, 0xFD, 0x28, - 0x72, 0xC8, 0x21, 0x44, 0x3F, 0xCC, 0xDE, 0x82, 0xEF, 0x57, 0x51, 0xE8, 0x34, 0x40, 0xF8, 0xA9, - 0xCE, 0x43, 0xFD, 0x0B, 0x69, 0xA0, 0xD5, 0xEE, 0x6C, 0x62, 0x61, 0xD1, 0x22, 0xA8, 0x5C, 0x2E, - 0xCD, 0x7C, 0x72, 0xC7, 0x72, 0xCD, 0xF4, 0x89, 0x06, 0x4B, 0x30, 0xD4, 0xCF, 0x6F, 0x8D, 0xC3, - 0xAD, 0x7E, 0x29, 0x43, 0x9C, 0xE9, 0xD9, 0x4B, 0xB0, 0xC1, 0xC1, 0x8A, 0xE6, 0x32, 0xBF, 0x4D, - 0xDA, 0xCD, 0x69, 0x79, 0x9B, 0x80, 0x52, 0x1A, 0xDD, 0xA4, 0xCD, 0x0D, 0x97, 0xF9, 0xD2, 0xE6, - 0xB6, 0xC9, 0xE2, 0x5E, 0xAC, 0x28, 0xB4, 0x89, 0xD8, 0x6F, 0x18, 0x17, 0xDF, 0x6D, 0x00, 0x9F, - 0x99, 0xC7, 0xE8, 0xF0, 0x55, 0x16, 0xBC, 0xBB, 0xAA, 0x6A, 0xCE, 0xE2, 0xA6, 0xDC, 0xD4, 0xC8, - 0xEB, 0xCD, 0x0D, 0xB2, 0xCE, 0xE8, 0x63, 0x7F, 0x3C, 0x09, 0xF8, 0x09, 0xF2, 0xAD, 0xBA, 0xC2, - 0x4A, 0x8E, 0xBE, 0x49, 0x41, 0xD2, 0xA3, 0x06, 0xBB, 0x68, 0x0C, 0x1B, 0xF2, 0xBE, 0x53, 0xF0, - 0x4D, 0xB2, 0xEB, 0x61, 0x30, 0xE1, 0x21, 0xDE, 0xC2, 0xB8, 0x93, 0x9B, 0x1A, 0xEC, 0x0A, 0xB3, - 0x59, 0xFC, 0xAF, 0x43, 0xF6, 0x91, 0x1D, 0xEE, 0xBB, 0x5B, 0xD6, 0x2A, 0x49, 0x25, 0x86, 0x23, - 0xB9, 0xAC, 0x35, 0xD1, 0xA0, 0x7A, 0xD6, 0x5A, 0x39, 0x09, 0x38, 0x5C, 0xD5, 0xDD, 0x68, 0x58, - 0x4F, 0x06, 0xFE, 0x07, 0xEF, 0xBD, 0x20, 0xEE, 0xDB, 0xC1, 0x1C, 0x82, 0xDA, 0x36, 0x32, 0x9B, - 0x9C, 0x6A, 0x58, 0xEA, 0xC3, 0x2C, 0x64, 0xAF, 0x53, 0x31, 0x72, 0x2F, 0xD9, 0x0B, 0xE1, 0x3B, - 0x7E, 0xF7, 0x91, 0xFD, 0x7B, 0xCB, 0xDF, 0xA2, 0x7C, 0x88, 0xC1, 0x21, 0x4E, 0x14, 0xC2, 0xF7, - 0xE0, 0xED, 0xF5, 0x47, 0xF6, 0x5B, 0xCB, 0xF2, 0xCE, 0xB9, 0x91, 0x6B, 0xC6, 0xC0, 0xF7, 0x18, - 0xBD, 0xF8, 0x82, 0xD8, 0xEE, 0x59, 0x74, 0xD9, 0x6D, 0xF9, 0xA6, 0x56, 0xF7, 0x1C, 0xDD, 0x06, - 0xB4, 0x46, 0x97, 0x3E, 0xE9, 0x69, 0xEA, 0x84, 0xE1, 0xE3, 0x84, 0xFD, 0xE8, 0x2C, 0xE5, 0x47, - 0x3D, 0xF0, 0x9A, 0x5B, 0x6C, 0x96, 0xF8, 0x39, 0xD9, 0xF4, 0x22, 0xD8, 0x1C, 0xBE, 0xBD, 0x21, - 0xD8, 0x0C, 0x22, 0xA0, 0x48, 0xC7, 0x5F, 0x08, 0xA5, 0xC3, 0xB7, 0xD7, 0x40, 0x82, 0xE1, 0x08, - 0x4C, 0xC0, 0x63, 0x03, 0x64, 0xD3, 0x47, 0x5E, 0x14, 0xAF, 0x5B, 0xCD, 0xE6, 0x16, 0xB5, 0x63, - 0xC8, 0x3A, 0xC1, 0x80, 0xC2, 0xF8, 0x1D, 0x36, 0xD9, 0x00, 0x24, 0x0F, 0xF0, 0xE1, 0x4A, 0xCB, - 0xC3, 0xF0, 0x10, 0x73, 0xAE, 0xCE, 0x57, 0x8A, 0xDE, 0x2A, 0x26, 0xAD, 0x25, 0xE7, 0x24, 0x7D, - 0xA0, 0x4B, 0x24, 0x4F, 0xA0, 0x71, 0x04, 0x81, 0x3F, 0xF5, 0xFA, 0x93, 0x04, 0x72, 0x18, 0xA8, - 0x39, 0x52, 0x1C, 0x45, 0xCD, 0x71, 0x97, 0x7E, 0x3D, 0x68, 0x9D, 0x63, 0x94, 0x4B, 0xEC, 0x78, - 0x21, 0x8C, 0x9E, 0xBC, 0xBF, 0x56, 0x96, 0x0C, 0x4A, 0x91, 0x78, 0xA3, 0x98, 0xA0, 0x89, 0x39, - 0xD5, 0xD8, 0x32, 0x2C, 0x53, 0x0D, 0x73, 0xEC, 0x63, 0xEF, 0xD7, 0xBA, 0x4B, 0x79, 0xD3, 0xC5, - 0x8D, 0xBE, 0xC1, 0xE5, 0x60, 0xB5, 0xF9, 0x8A, 0xE6, 0x65, 0x98, 0x33, 0x92, 0x56, 0x8F, 0x0C, - 0x2B, 0xC7, 0x65, 0x74, 0xFC, 0x54, 0x3B, 0xC7, 0x54, 0xFF, 0x19, 0x76, 0x8F, 0x58, 0x4F, 0xC5, - 0x2C, 0x1D, 0x31, 0x50, 0x4B, 0x2B, 0x47, 0x04, 0x20, 0x2F, 0x6E, 0xED, 0x88, 0x2E, 0x69, 0x61, - 0x7B, 0x47, 0xBC, 0x56, 0x44, 0x3A, 0x52, 0xF7, 0xCF, 0x59, 0x5F, 0xFF, 0x13, 0xE3, 0x6C, 0x04, - 0x99, 0xB8, 0x1A, 0x7E, 0xCC, 0x4E, 0x0B, 0xD8, 0x64, 0x37, 0xA7, 0x48, 0x21, 0x6C, 0x8F, 0x5D, - 0x3A, 0x3C, 0xDA, 0x0E, 0x3F, 0xF6, 0x6D, 0x60, 0x8D, 0xD9, 0xFC, 0x30, 0xAF, 0xD3, 0xE2, 0xD6, - 0x6C, 0xAA, 0x96, 0x95, 0xDC, 0xBD, 0x3B, 0x7C, 0x98, 0x75, 0x58, 0x78, 0x8E, 0x84, 0xC7, 0x1B, - 0x83, 0x0F, 0xBC, 0x37, 0x33, 0xF8, 0x85, 0x37, 0x3A, 0xC1, 0xD4, 0x88, 0x1F, 0xF6, 0xE0, 0x8F, - 0x99, 0x6F, 0x21, 0xA4, 0xF2, 0xDE, 0xD2, 0x4E, 0x62, 0x4C, 0x6D, 0xE2, 0x37, 0x15, 0xCC, 0xBD, - 0x4F, 0x61, 0x3E, 0x5D, 0x23, 0x2D, 0x06, 0x4F, 0xFA, 0x5C, 0xE5, 0xDE, 0xCA, 0x84, 0x8E, 0x56, - 0x51, 0x60, 0x10, 0x39, 0x62, 0xC2, 0x40, 0x98, 0x62, 0x96, 0x4B, 0xD5, 0x9E, 0xE7, 0x2C, 0x0E, - 0x2E, 0x8D, 0x72, 0x45, 0x5E, 0x7C, 0x27, 0x7F, 0xD9, 0xDF, 0x03, 0x4F, 0xA1, 0xDF, 0x9B, 0x0D, - 0xEF, 0xBB, 0x97, 0x3D, 0x76, 0xD0, 0xF6, 0x80, 0xF6, 0x3E, 0xEF, 0xAD, 0x0C, 0x20, 0x8A, 0xB8, - 0x2F, 0x5C, 0xF5, 0xD5, 0xB9, 0x00, 0x69, 0xF6, 0x54, 0xF2, 0xC1, 0x98, 0x01, 0x7F, 0x16, 0x65, - 0x10, 0x33, 0x7C, 0x6C, 0x25, 0x44, 0x57, 0x08, 0xEB, 0x76, 0xBB, 0xD5, 0xEC, 0xB4, 0x7E, 0x6F, - 0xB6, 0x9B, 0xAD, 0xE6, 0xA1, 0xC8, 0xD4, 0x99, 0x07, 0x48, 0x68, 0xC2, 0xFE, 0xBA, 0x2C, 0x80, - 0x4F, 0xCD, 0xE7, 0x55, 0xC3, 0xBC, 0xDD, 0x7C, 0x5F, 0x0C, 0xE6, 0xFB, 0xCD, 0xA3, 0x55, 0xC0, - 0x5C, 0xCE, 0x67, 0x2D, 0x61, 0x0E, 0x4F, 0x91, 0x39, 0x9F, 0x64, 0x70, 0xF2, 0xDC, 0x4D, 0x12, - 0x67, 0x58, 0xCE, 0x36, 0xCD, 0xBE, 0xC9, 0xA9, 0x4D, 0xA4, 0xA2, 0xC8, 0x42, 0x41, 0x83, 0xE7, - 0x1E, 0xB1, 0x49, 0xF1, 0x57, 0x7E, 0x42, 0xD5, 0x02, 0xFB, 0x58, 0xC5, 0x1B, 0xF3, 0xAC, 0x05, - 0xC4, 0x12, 0x2C, 0xC5, 0x42, 0xAB, 0x91, 0x7F, 0x2F, 0xB2, 0x9E, 0x9C, 0xAD, 0x4C, 0xBF, 0x63, - 0x9E, 0xED, 0xB1, 0x5C, 0xAC, 0x78, 0x50, 0x66, 0xE1, 0x20, 0xFC, 0xBB, 0x35, 0x39, 0x3B, 0x5B, - 0xD1, 0x4A, 0x41, 0xA2, 0xA8, 0x0E, 0x0A, 0x50, 0x33, 0x2A, 0x04, 0x89, 0x5A, 0x35, 0x3F, 0x15, - 0x56, 0x62, 0xD2, 0x8B, 0x4B, 0xD9, 0x29, 0xE5, 0xA4, 0x9A, 0x91, 0x6A, 0x52, 0xB9, 0xD5, 0xA2, - 0xB2, 0x0B, 0x37, 0x49, 0x71, 0x4A, 0x2C, 0x06, 0xAB, 0xC9, 0xF8, 0x6E, 0x5A, 0x6D, 0xD7, 0x92, - 0x81, 0x0B, 0xA6, 0x96, 0xD0, 0x2B, 0x26, 0x6F, 0x8E, 0x9C, 0x74, 0xF9, 0x74, 0x5A, 0xEF, 0x4E, - 0xAB, 0x3F, 0x96, 0xD0, 0xED, 0x30, 0x1D, 0x82, 0x0B, 0x02, 0x32, 0xFC, 0xDD, 0x22, 0xB5, 0xBB, - 0xD5, 0x0E, 0x1E, 0x35, 0xB3, 0x02, 0x16, 0x67, 0xE4, 0x55, 0x56, 0x1E, 0xF9, 0xA9, 0x67, 0x4E, - 0x69, 0x29, 0x22, 0x9F, 0x4A, 0x9C, 0x0C, 0xF0, 0x5D, 0x71, 0x4F, 0x48, 0x39, 0x92, 0xE1, 0x53, - 0xEA, 0xFE, 0x27, 0x42, 0x0B, 0xA6, 0x14, 0x65, 0xEC, 0x06, 0x95, 0xE2, 0x56, 0xA8, 0x14, 0x67, - 0x13, 0x50, 0x20, 0xF9, 0x8A, 0x59, 0x96, 0xD5, 0x28, 0xE3, 0xAD, 0x83, 0xC8, 0x95, 0xA2, 0xF1, - 0x2C, 0x69, 0xB1, 0x2C, 0x05, 0xB6, 0x47, 0x6C, 0x49, 0xA9, 0x4D, 0xE0, 0xDF, 0x75, 0x2F, 0x6D, - 0x13, 0x2C, 0xDF, 0xC3, 0x29, 0xA6, 0x6E, 0x06, 0xB6, 0x99, 0x6C, 0xC6, 0x05, 0x7C, 0x42, 0xFF, - 0xF8, 0xD4, 0x0D, 0xA1, 0x88, 0xA0, 0xE9, 0x7D, 0xC0, 0x60, 0xDE, 0x47, 0x69, 0xAB, 0x08, 0x47, - 0x28, 0xB9, 0x31, 0x72, 0xE6, 0x69, 0x1B, 0x93, 0x13, 0x28, 0x64, 0x9F, 0xFC, 0x93, 0x79, 0xEF, - 0xDA, 0x7F, 0xC9, 0x03, 0x7B, 0xE4, 0x63, 0xF4, 0x4F, 0x57, 0x75, 0x74, 0xDB, 0x63, 0xAE, 0xA3, - 0xC2, 0xFE, 0x3A, 0xEA, 0x1E, 0x06, 0xAA, 0x35, 0xFE, 0x4E, 0xA3, 0x89, 0xAF, 0xB2, 0x9A, 0x4C, - 0x7A, 0x86, 0x15, 0xBB, 0x18, 0x28, 0x65, 0x61, 0xDD, 0x01, 0x97, 0x7D, 0x64, 0x9A, 0xA5, 0xFA, - 0x68, 0x73, 0x6A, 0xFC, 0xE1, 0x73, 0xE7, 0x59, 0x28, 0x0D, 0x96, 0x03, 0x6A, 0xC3, 0xCE, 0x9B, - 0x86, 0xE7, 0xBD, 0x79, 0x1B, 0xB6, 0x0C, 0xDA, 0x34, 0xE0, 0x78, 0xBF, 0x50, 0xD4, 0xD1, 0x8E, - 0xC7, 0x3E, 0x9E, 0xB0, 0x7F, 0x8D, 0x2D, 0x03, 0xF3, 0xAF, 0x61, 0xFC, 0xA5, 0xEB, 0x39, 0x8A, - 0xDD, 0xB8, 0x13, 0x2D, 0x76, 0xBC, 0x49, 0x27, 0xFF, 0xF6, 0x56, 0xCE, 0x30, 0x98, 0x17, 0x00, - 0x1B, 0x34, 0x4D, 0xE0, 0x1B, 0x1F, 0xF6, 0x46, 0xDE, 0xD8, 0x38, 0xF9, 0xFF, 0x52, 0x31, 0x57, - 0x1C, 0xD9, 0x50, 0x00 + 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, + 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, + 0x01, 0x49, 0x12, 0xCF, 0x20, 0x80, 0x8B, 0x41, 0xB2, 0x6E, 0x9D, 0xAA, 0x53, 0xCB, 0xE8, 0x5E, + 0x48, 0x6F, 0xA0, 0x97, 0x52, 0x2B, 0xE9, 0x88, 0xC8, 0x04, 0x08, 0x90, 0x18, 0x49, 0x90, 0x22, + 0x65, 0xF9, 0xBD, 0x2B, 0x89, 0x20, 0x72, 0x8A, 0x8C, 0x88, 0x8C, 0x88, 0x8C, 0xE1, 0xC3, 0x3F, + 0x9C, 0x7D, 0x39, 0xBD, 0xFB, 0xB5, 0x77, 0xCE, 0x46, 0xFE, 0xD8, 0x3C, 0xFA, 0xE9, 0x03, 0xFE, + 0x62, 0xA6, 0x6A, 0x0D, 0x3F, 0x36, 0xB8, 0xD5, 0x38, 0xFA, 0x09, 0x9E, 0x70, 0x55, 0x3F, 0xFA, + 0x89, 0xC1, 0xBF, 0x0F, 0x63, 0xEE, 0xAB, 0x4C, 0x1B, 0xA9, 0xAE, 0xC7, 0xFD, 0x8F, 0x8D, 0xC0, + 0x1F, 0x34, 0x0F, 0x1A, 0x6C, 0x27, 0xFE, 0xE5, 0xC8, 0xF7, 0x9D, 0x26, 0xFF, 0x23, 0x30, 0x1E, + 0x3E, 0x36, 0x7E, 0x69, 0x7E, 0x3D, 0x6E, 0x9E, 0xDA, 0x63, 0x47, 0xF5, 0x8D, 0x7B, 0x93, 0x37, + 0x98, 0x66, 0x5B, 0x3E, 0xB7, 0xA0, 0xE5, 0xE5, 0xF9, 0x47, 0xAE, 0x0F, 0xF9, 0xB6, 0x36, 0x72, + 0xED, 0x31, 0xFF, 0xD8, 0x9E, 0x74, 0xE2, 0x1B, 0xBE, 0xC9, 0x8F, 0xFA, 0x8E, 0xEA, 0x7E, 0xBB, + 0x08, 0x2C, 0x76, 0x7B, 0xF7, 0x57, 0xD6, 0xE7, 0x7E, 0xE0, 0x7C, 0xD8, 0x11, 0xDF, 0xC4, 0x86, + 0xB2, 0x54, 0x68, 0xDA, 0x78, 0x30, 0xF8, 0xA3, 0x63, 0xBB, 0x7E, 0x83, 0xBE, 0xC1, 0x7F, 0xD1, + 0x28, 0x8F, 0x86, 0xEE, 0x8F, 0x3E, 0xEA, 0xFC, 0xC1, 0xD0, 0x78, 0x93, 0x3E, 0x6C, 0x33, 0xC3, + 0x32, 0x7C, 0x43, 0x35, 0x9B, 0x9E, 0xA6, 0x9A, 0x30, 0xF0, 0x36, 0x1B, 0xAB, 0xDF, 0x8D, 0x71, + 0x30, 0x9E, 0x3C, 0x08, 0x3C, 0xEE, 0xD2, 0x27, 0x15, 0xE6, 0xFC, 0x51, 0xD9, 0x66, 0xDE, 0xC8, + 0x35, 0xAC, 0x6F, 0x4D, 0xDF, 0x6E, 0x0E, 0x0C, 0xFF, 0xE3, 0x13, 0xF7, 0x26, 0xB3, 0x35, 0xE1, + 0x0B, 0xE6, 0x72, 0xF3, 0x63, 0xC3, 0xF3, 0x9F, 0x4C, 0xEE, 0x8D, 0x38, 0xF7, 0x1B, 0x6C, 0xE4, + 0xF2, 0x01, 0x3C, 0x71, 0xB5, 0x9D, 0x7B, 0xDB, 0xF6, 0x3D, 0xDF, 0x55, 0x9D, 0xD6, 0xD8, 0xB0, + 0x5A, 0x9A, 0xE7, 0x35, 0x4A, 0x36, 0xA4, 0xA7, 0xF1, 0x06, 0x9E, 0xE6, 0x1A, 0x8E, 0xCF, 0xE0, + 0x3B, 0xF1, 0xC2, 0xDF, 0xFF, 0x08, 0xB8, 0xFB, 0xD4, 0xEC, 0xB6, 0xF6, 0x5B, 0x0A, 0x75, 0xFE, + 0x77, 0x78, 0xF5, 0xC3, 0x8E, 0x78, 0x2D, 0xA3, 0x4D, 0x72, 0x36, 0x95, 0x1A, 0xDC, 0x07, 0x96, + 0x0E, 0x13, 0x9A, 0x6D, 0x17, 0x6F, 0x78, 0x14, 0x6D, 0xC1, 0x7F, 0xD9, 0xD2, 0x6D, 0x2D, 0x18, + 0xC3, 0x2E, 0xBC, 0x6D, 0xD9, 0xD6, 0xD6, 0x1B, 0xCD, 0x34, 0xB4, 0x6F, 0x6F, 0xB6, 0xD9, 0x9B, + 0x96, 0x6F, 0x0F, 0x87, 0x26, 0x6F, 0xDE, 0xFB, 0x16, 0x7C, 0x1C, 0x04, 0x96, 0xE6, 0x1B, 0xB6, + 0xC5, 0xB6, 0xF8, 0x5B, 0xF6, 0xAF, 0x51, 0x6B, 0xD1, 0x03, 0x2C, 0x3F, 0x70, 0x5D, 0xE8, 0xE2, + 0x4E, 0x75, 0x87, 0xDC, 0x6F, 0x69, 0x23, 0xC3, 0xD4, 0xE1, 0xF3, 0xFF, 0x50, 0xFE, 0xE7, 0x5B, + 0xD9, 0xCD, 0xA9, 0xA9, 0x7A, 0xDE, 0xD6, 0x1B, 0x03, 0x76, 0xBC, 0xA9, 0xA9, 0x2E, 0xF7, 0x9B, + 0xBA, 0xFD, 0x68, 0xB1, 0xD8, 0xE7, 0xC0, 0x79, 0xF3, 0xF6, 0x2F, 0x51, 0xC7, 0xFF, 0xF6, 0x56, + 0x4C, 0x77, 0x7A, 0xF6, 0x08, 0xEC, 0xC9, 0xE4, 0x5B, 0x9E, 0x0F, 0x08, 0xAB, 0x35, 0x87, 0xAE, + 0x1D, 0x38, 0x53, 0xD3, 0x1A, 0x71, 0x63, 0x38, 0xF2, 0x0F, 0x99, 0xF2, 0x97, 0xC4, 0x63, 0xFB, + 0x81, 0xBB, 0x03, 0xD3, 0x7E, 0x3C, 0x64, 0x23, 0x43, 0xD7, 0xB9, 0x95, 0xFC, 0x16, 0x20, 0x68, + 0x79, 0x06, 0x2E, 0xF4, 0x50, 0x76, 0xC0, 0x94, 0xD6, 0xAE, 0xC7, 0xB8, 0xEA, 0xF1, 0xE4, 0x9B, + 0xF7, 0xB6, 0xAB, 0x03, 0xF6, 0xDD, 0xDB, 0xBE, 0x6F, 0x8F, 0x0F, 0x99, 0x67, 0x9B, 0x86, 0xCE, + 0xDA, 0xCE, 0x77, 0xF6, 0x8F, 0x9A, 0x82, 0xFF, 0x8B, 0x2D, 0xE5, 0xA7, 0xC9, 0x7C, 0x4D, 0xC3, + 0xF3, 0xD7, 0x7B, 0xB6, 0xF8, 0xCF, 0x51, 0x75, 0xDD, 0xB0, 0x86, 0x4D, 0x57, 0xCC, 0x69, 0x4F, + 0x71, 0xBE, 0xA7, 0x2F, 0x47, 0x74, 0x0B, 0x44, 0xE1, 0x31, 0x5F, 0xDF, 0x4E, 0x7F, 0x3E, 0x9A, + 0x5A, 0xA9, 0xF8, 0xEE, 0x90, 0x59, 0xB6, 0x35, 0x35, 0xC9, 0x31, 0x60, 0x8F, 0x61, 0x35, 0x4D, + 0x3E, 0x40, 0x40, 0x64, 0x8C, 0x79, 0x1F, 0xC0, 0x12, 0xAC, 0xC3, 0x01, 0x20, 0xAD, 0x37, 0xD5, + 0xB3, 0x1D, 0xF8, 0x40, 0xAC, 0x3C, 0x01, 0xC4, 0xF8, 0x6C, 0x0D, 0x0B, 0xBF, 0x3E, 0x77, 0x5D, + 0xDB, 0x9D, 0x6A, 0xA9, 0x1B, 0x9E, 0x63, 0xAA, 0x4F, 0x87, 0x4C, 0xBC, 0x92, 0x9C, 0x96, 0x66, + 0x9B, 0x36, 0xCC, 0xD7, 0xE5, 0x7A, 0xF2, 0xF9, 0x00, 0x98, 0x57, 0xD3, 0x33, 0xFE, 0x84, 0x01, + 0xBD, 0xB1, 0x6A, 0x9A, 0xDC, 0xCD, 0x1B, 0xB6, 0x1F, 0x68, 0x1A, 0xC2, 0xA3, 0xFA, 0xC0, 0x43, + 0x97, 0x4F, 0x6F, 0x7C, 0xDE, 0xD0, 0xD1, 0xF7, 0x8F, 0x12, 0xA5, 0xEE, 0x6D, 0x53, 0xCF, 0xDA, + 0xBE, 0xEF, 0x4D, 0x6A, 0x3F, 0x35, 0xAB, 0xEC, 0x8D, 0xC0, 0x7F, 0xC4, 0x9E, 0x0F, 0x59, 0x57, + 0xF9, 0xAF, 0xD9, 0xBD, 0x8A, 0x1E, 0x3A, 0x4A, 0x5E, 0xC7, 0x9D, 0x1C, 0xB4, 0x0A, 0x7B, 0xD8, + 0xCD, 0xED, 0x61, 0x37, 0xBB, 0x07, 0xD5, 0xF7, 0x81, 0xE9, 0x4E, 0x35, 0x76, 0xEC, 0x90, 0x5A, + 0xD4, 0x7B, 0x20, 0x81, 0xC0, 0x9F, 0x02, 0xF8, 0x9F, 0x4D, 0xC3, 0xD2, 0xF9, 0xF7, 0x43, 0xD6, + 0x56, 0x94, 0x29, 0x92, 0x90, 0xA4, 0xD0, 0x9E, 0x81, 0x06, 0x1C, 0x4A, 0x4D, 0x09, 0x91, 0x7D, + 0x25, 0xE5, 0x5B, 0x9A, 0xAE, 0x6F, 0x3B, 0x40, 0x46, 0xC9, 0xC9, 0x4A, 0xF6, 0x26, 0x18, 0xDA, + 0x87, 0x1D, 0x71, 0x74, 0xFF, 0xF4, 0xE1, 0xDE, 0xD6, 0x9F, 0x24, 0x8F, 0xD7, 0x8D, 0x07, 0xA6, + 0x21, 0xDF, 0xFC, 0xD8, 0xC0, 0x83, 0x52, 0x05, 0x04, 0x71, 0x1B, 0xCC, 0xD0, 0x3F, 0x36, 0xE4, + 0xF2, 0x2E, 0xE1, 0x71, 0x63, 0xC2, 0x0D, 0xA9, 0x81, 0x6A, 0x1A, 0x43, 0xEB, 0x63, 0x83, 0xE6, + 0xDB, 0x08, 0x9B, 0xCB, 0xF7, 0x63, 0xEF, 0xD2, 0xFB, 0xC6, 0x78, 0x38, 0xDD, 0xDD, 0x85, 0x61, + 0xF2, 0x1B, 0x38, 0xAD, 0x1B, 0x93, 0xA3, 0xE5, 0x44, 0x7C, 0x7B, 0x02, 0x92, 0xC6, 0xB7, 0x96, + 0x63, 0x0D, 0x1B, 0x30, 0x06, 0x1C, 0xD9, 0xF2, 0x31, 0x33, 0xF9, 0x03, 0x37, 0x1B, 0x47, 0xC0, + 0x9B, 0x1D, 0xD5, 0x8A, 0x77, 0xD7, 0xE3, 0xAE, 0x06, 0x67, 0x42, 0x23, 0x31, 0x26, 0xE1, 0xB5, + 0x98, 0x14, 0x61, 0x1E, 0x8C, 0x83, 0x10, 0xF8, 0xD8, 0x08, 0x29, 0x41, 0x12, 0x02, 0x1D, 0x5C, + 0xD0, 0x61, 0x6C, 0x75, 0x3B, 0xB0, 0x3C, 0x09, 0x19, 0xF1, 0x67, 0x1E, 0x94, 0xA6, 0x7A, 0x25, + 0x66, 0x13, 0xDF, 0x0D, 0x42, 0xBE, 0xC9, 0xDE, 0x89, 0xAD, 0x13, 0xC0, 0x75, 0x39, 0x88, 0x4C, + 0x97, 0x56, 0xCF, 0xB5, 0x91, 0x60, 0xE3, 0xF0, 0xBD, 0x3F, 0xBA, 0xC5, 0xEF, 0x7C, 0xE0, 0x8D, + 0x1F, 0x76, 0xEE, 0x8F, 0x3E, 0xDC, 0xBB, 0xF4, 0x1F, 0x4A, 0x3E, 0x42, 0x74, 0x61, 0x86, 0x07, + 0x7C, 0x02, 0xCF, 0x62, 0x78, 0xA5, 0xC5, 0x7A, 0x26, 0x72, 0x62, 0xF6, 0xA8, 0x1A, 0x7E, 0xAB, + 0xD5, 0x5A, 0xD5, 0xD4, 0x51, 0x8C, 0x33, 0xB9, 0xCF, 0x53, 0x66, 0xCE, 0xCE, 0xA0, 0xB3, 0x8C, + 0xA9, 0x8F, 0x54, 0x0F, 0x78, 0xF2, 0x23, 0xA3, 0x3E, 0x56, 0x31, 0xD9, 0x81, 0xE1, 0x8E, 0x1F, + 0xE1, 0xE8, 0xFF, 0xEA, 0x98, 0xB6, 0xAA, 0xA7, 0xCF, 0x7A, 0x7A, 0xBE, 0x17, 0xB2, 0x0D, 0x0B, + 0x1C, 0x5D, 0xF5, 0x39, 0xB0, 0x48, 0xD1, 0xAA, 0xC5, 0x92, 0x9B, 0x20, 0x16, 0x12, 0x6E, 0x44, + 0xC9, 0xC5, 0x1C, 0xFD, 0x94, 0x4A, 0x4A, 0x88, 0xC4, 0xB8, 0xD4, 0xE8, 0x7D, 0x10, 0x49, 0xC7, + 0xCD, 0x76, 0x07, 0x50, 0x14, 0x09, 0x28, 0xA2, 0x13, 0xD7, 0xFF, 0xD6, 0xF4, 0x50, 0x00, 0x8E, + 0x11, 0x49, 0x42, 0x3A, 0xFE, 0xD9, 0xB8, 0x30, 0x84, 0x88, 0x8C, 0xD8, 0x1D, 0x9B, 0x4D, 0x69, + 0x30, 0xC7, 0x00, 0xDB, 0xCE, 0x06, 0xEC, 0x18, 0x1A, 0xF5, 0xD4, 0x21, 0x2F, 0xB9, 0x20, 0xD7, + 0x7E, 0x9C, 0xD9, 0xC7, 0x7B, 0xD3, 0xD6, 0xBE, 0xFD, 0x25, 0xDE, 0x41, 0x41, 0x27, 0xE2, 0x18, + 0x41, 0xB6, 0x3C, 0xC5, 0x64, 0xF0, 0x1F, 0x2E, 0xFE, 0x1C, 0x24, 0x99, 0xA7, 0xC7, 0x11, 0x87, + 0xBD, 0x0B, 0x37, 0xF1, 0x30, 0xC6, 0x33, 0x00, 0x78, 0xE1, 0xE3, 0xBF, 0x71, 0xD7, 0x03, 0x26, + 0x9D, 0xCD, 0x19, 0x1E, 0x94, 0x96, 0x22, 0xB9, 0x03, 0xE2, 0xC4, 0xCC, 0x70, 0x93, 0x5E, 0x87, + 0x96, 0xE7, 0x95, 0xEE, 0xF6, 0xD3, 0x4D, 0xBF, 0x1F, 0x9B, 0x5B, 0x6C, 0x14, 0x56, 0x30, 0x8C, + 0xC0, 0xBB, 0x93, 0xBB, 0xCB, 0xB3, 0xEC, 0xDE, 0xCF, 0x04, 0x6E, 0x9E, 0x98, 0x01, 0xF7, 0x01, + 0x2D, 0x47, 0xEC, 0xF2, 0x0C, 0xCE, 0x56, 0xF8, 0x57, 0x72, 0x0C, 0xCD, 0x06, 0xB9, 0xC9, 0xB0, + 0x00, 0xE9, 0xBD, 0xAB, 0xAB, 0xCF, 0xD9, 0xE3, 0x5C, 0x5D, 0x8D, 0x0E, 0x67, 0xBA, 0x99, 0x82, + 0x0A, 0xB7, 0x75, 0x0E, 0x62, 0xF3, 0x95, 0xEA, 0x67, 0xF7, 0xB3, 0x0B, 0xCB, 0x7F, 0xAF, 0x74, + 0xDE, 0xEF, 0xBE, 0x7B, 0x2F, 0x67, 0xB8, 0x5D, 0xB6, 0xDB, 0x3C, 0x20, 0x37, 0xDB, 0xCA, 0x5E, + 0xAB, 0x7D, 0xB0, 0xA7, 0xEC, 0xBD, 0xDB, 0x6F, 0x57, 0xEC, 0xF8, 0xD8, 0xCC, 0x99, 0x6F, 0x7B, + 0x6F, 0x1F, 0x66, 0x7C, 0x10, 0x4E, 0x96, 0x6D, 0x1D, 0xF7, 0x4E, 0xDF, 0xCE, 0xC2, 0xB3, 0x14, + 0xDA, 0xC4, 0x60, 0x7D, 0x7E, 0x7A, 0x7E, 0x91, 0x3D, 0x28, 0x7E, 0x5B, 0x04, 0x6D, 0xAE, 0xF1, + 0xC1, 0x2F, 0x79, 0x00, 0xE9, 0x1C, 0x28, 0x1D, 0x65, 0xBF, 0xB5, 0xB7, 0x7F, 0x50, 0x12, 0x1E, + 0xD8, 0xE3, 0xAF, 0x39, 0x3D, 0xEE, 0xBE, 0x6B, 0xEF, 0x1F, 0x28, 0xBB, 0xAD, 0x5D, 0xA5, 0x5B, + 0xA1, 0xC7, 0xDF, 0xF2, 0x70, 0xE1, 0x60, 0x7F, 0x7F, 0x7F, 0xAF, 0xB5, 0x7B, 0xB0, 0x3B, 0x7D, + 0x2A, 0x17, 0x01, 0x36, 0xCE, 0xDB, 0x52, 0x3F, 0x8F, 0xDC, 0x90, 0x85, 0x8C, 0xFD, 0xA6, 0x32, + 0x2D, 0xCD, 0xCC, 0xF2, 0x3D, 0x3A, 0x50, 0x66, 0x18, 0xD3, 0x3F, 0x34, 0x9B, 0xAC, 0x19, 0xFE, + 0x63, 0x70, 0x74, 0x0F, 0x40, 0x8E, 0x61, 0xA7, 0xB6, 0x35, 0x30, 0x86, 0xB1, 0x2F, 0x9A, 0xCD, + 0xA3, 0x59, 0x86, 0x26, 0x87, 0xD7, 0x41, 0x2F, 0x03, 0xA5, 0x68, 0xA8, 0x3A, 0xCD, 0x4E, 0x0A, + 0x0F, 0xFB, 0x20, 0x14, 0x8F, 0x48, 0xA2, 0xF2, 0x2D, 0x06, 0xFF, 0x35, 0x1D, 0xD7, 0x80, 0xC9, + 0x3D, 0xB1, 0x89, 0xB2, 0x2C, 0x78, 0xB0, 0x23, 0xA6, 0x20, 0x66, 0xD0, 0x60, 0xFE, 0x93, 0x03, + 0xCB, 0x10, 0x5D, 0x34, 0x18, 0x1C, 0x5D, 0x6A, 0x53, 0xB4, 0xA0, 0xF3, 0xC4, 0x54, 0x1D, 0x8F, + 0x37, 0x52, 0xF7, 0x48, 0xBC, 0x4A, 0x6A, 0xF5, 0xC7, 0xC6, 0x3F, 0x86, 0xEF, 0xF6, 0x92, 0xBD, + 0xAB, 0xAE, 0xA1, 0x36, 0xF9, 0x77, 0xD8, 0x00, 0x9D, 0xE3, 0xC1, 0xAA, 0x9A, 0xD0, 0x9D, 0x78, + 0x8A, 0x67, 0x88, 0x6B, 0x9B, 0xDE, 0x64, 0x9C, 0x64, 0xDB, 0xA3, 0xD4, 0x51, 0x93, 0x00, 0x0C, + 0x5C, 0x95, 0x54, 0xFF, 0x0F, 0x46, 0x62, 0x69, 0xA8, 0xB5, 0x4F, 0x4E, 0x45, 0xD2, 0xE1, 0x51, + 0x9D, 0x67, 0xF7, 0x06, 0x9B, 0x52, 0xF3, 0xF1, 0xB8, 0x33, 0xD2, 0x70, 0x46, 0x00, 0x24, 0x15, + 0x63, 0xB2, 0xB6, 0x29, 0x5C, 0x06, 0x1B, 0xDF, 0xC3, 0x3E, 0x49, 0x72, 0x2D, 0xB7, 0x32, 0xC2, + 0x92, 0xD4, 0xBE, 0xBC, 0x11, 0xC8, 0x0B, 0x85, 0x1D, 0xCE, 0xA0, 0xCF, 0xCC, 0xDC, 0x54, 0x57, + 0x67, 0xF8, 0xA3, 0x89, 0x52, 0xFC, 0x34, 0x92, 0xA6, 0xB5, 0x18, 0xD8, 0xEE, 0x58, 0xDA, 0x03, + 0x00, 0xFD, 0x3B, 0x19, 0xDB, 0x11, 0xDB, 0x92, 0xC3, 0xCC, 0x17, 0x04, 0x35, 0xCB, 0x7E, 0x7D, + 0x5F, 0x62, 0xD9, 0xBD, 0xD7, 0x04, 0x5A, 0xD6, 0xF8, 0x98, 0xCC, 0x6C, 0x42, 0x2B, 0xC8, 0xEC, + 0x82, 0x6C, 0x0A, 0x68, 0xBB, 0x03, 0xC1, 0x85, 0x9B, 0x5C, 0xF3, 0x99, 0xCA, 0xE4, 0x6E, 0x33, + 0xC0, 0x2D, 0xD0, 0xE5, 0xB9, 0xC5, 0xA0, 0x7F, 0x10, 0x00, 0x98, 0x94, 0x83, 0x41, 0xC1, 0xB7, + 0xE1, 0xB9, 0xEA, 0x87, 0x2F, 0xB6, 0xD8, 0xB1, 0x2F, 0x64, 0xC8, 0xED, 0xB8, 0x4C, 0xF6, 0x68, + 0x80, 0x78, 0x10, 0x20, 0xA8, 0xA9, 0x63, 0xAE, 0x4F, 0xDE, 0x0F, 0x91, 0x4D, 0x1B, 0xA9, 0xD6, + 0x90, 0x7B, 0x0C, 0xC5, 0x3B, 0x4F, 0x7D, 0x80, 0x57, 0x1E, 0x69, 0x3C, 0x50, 0x92, 0x07, 0x03, + 0x8E, 0xE6, 0xA5, 0x68, 0x32, 0x20, 0xE1, 0x45, 0xFD, 0x80, 0x32, 0x4F, 0xEF, 0xBD, 0xE9, 0x43, + 0x9B, 0x24, 0xC6, 0xBE, 0xC1, 0x17, 0x1D, 0x98, 0x8C, 0xC7, 0xF5, 0x56, 0x0E, 0x6C, 0x67, 0xC0, + 0x47, 0xF8, 0x6B, 0x58, 0x03, 0xBB, 0xA9, 0x19, 0xAE, 0x06, 0x03, 0xFA, 0xFC, 0xBB, 0x1F, 0xD1, + 0xFA, 0xD8, 0xC3, 0x9D, 0xCA, 0xE2, 0x84, 0x53, 0x1C, 0x31, 0x1D, 0x05, 0xA6, 0xB8, 0x60, 0x09, + 0xF4, 0x40, 0x29, 0xED, 0xA8, 0x60, 0xF3, 0xD3, 0xF9, 0x77, 0x42, 0x67, 0x0E, 0xD9, 0x67, 0x2E, + 0x28, 0x0C, 0xCB, 0x09, 0x7C, 0xC9, 0xB3, 0x5C, 0x55, 0x37, 0xEC, 0x86, 0xB4, 0xE0, 0x4A, 0xF8, + 0xDF, 0x8A, 0x67, 0x0F, 0x2A, 0x08, 0x33, 0x1F, 0x1B, 0x4A, 0x51, 0x77, 0xA6, 0x7A, 0xCF, 0xCD, + 0x38, 0xEB, 0x50, 0x48, 0xC3, 0x3C, 0x92, 0x1B, 0x0F, 0x62, 0x00, 0xBD, 0xB1, 0x10, 0x28, 0x5F, + 0x04, 0x24, 0xDB, 0x95, 0x21, 0xD9, 0x16, 0x90, 0x6C, 0x77, 0xBA, 0xBB, 0x7B, 0xFB, 0xEF, 0x0E, + 0xDE, 0x2B, 0x93, 0xBF, 0x5E, 0xA1, 0x2A, 0xA1, 0xDA, 0xA9, 0x0C, 0xD5, 0x8E, 0x80, 0xEA, 0x2B, + 0x04, 0x25, 0x04, 0xBB, 0x95, 0x21, 0xD8, 0x7D, 0x85, 0x60, 0x02, 0x82, 0xBB, 0x95, 0x21, 0xB8, + 0xFB, 0x0A, 0xC1, 0x04, 0x04, 0xF7, 0x2A, 0x43, 0x70, 0xEF, 0x15, 0x82, 0x09, 0x08, 0xEE, 0x57, + 0x86, 0xE0, 0xFE, 0x2B, 0x04, 0x13, 0x10, 0x7C, 0x57, 0x19, 0x82, 0xEF, 0xEA, 0x83, 0x60, 0x8D, + 0x20, 0x14, 0xD3, 0x84, 0xF7, 0xA3, 0x79, 0x0A, 0x93, 0x7F, 0xA8, 0xDB, 0xC6, 0x2F, 0x70, 0xA4, + 0xB9, 0xB3, 0x4B, 0x7F, 0xEC, 0xD2, 0x4F, 0x1A, 0x88, 0xFA, 0x88, 0x64, 0xB8, 0x5C, 0xB0, 0x60, + 0xE7, 0x87, 0xC5, 0x20, 0x48, 0x2A, 0x66, 0x38, 0xE8, 0x01, 0x0D, 0xF7, 0xAE, 0xCA, 0x26, 0xA2, + 0xA0, 0xDE, 0x48, 0x40, 0x44, 0x6A, 0xC0, 0x09, 0xB5, 0x5C, 0xEC, 0x4A, 0x7E, 0xAF, 0xCE, 0x74, + 0x03, 0xBA, 0x38, 0x8C, 0xFA, 0x8E, 0x5D, 0x26, 0xE2, 0xFE, 0x3A, 0x79, 0x7B, 0x9B, 0x49, 0x01, + 0xB3, 0x03, 0x9D, 0x92, 0x12, 0x74, 0x0D, 0x2A, 0x0B, 0x1A, 0x70, 0x93, 0x83, 0xC9, 0x2B, 0xC4, + 0x9C, 0xE1, 0xEA, 0x47, 0x95, 0x59, 0x23, 0x8C, 0xBC, 0x43, 0xDE, 0x2B, 0x41, 0x5D, 0xD2, 0x64, + 0x92, 0x34, 0x7E, 0xD0, 0x0D, 0x91, 0x6F, 0xD1, 0x7D, 0x84, 0xC4, 0x9E, 0x46, 0x96, 0x55, 0x25, + 0x15, 0x13, 0xF3, 0xF5, 0x57, 0xBA, 0x08, 0xB6, 0x4E, 0xD1, 0x8B, 0x61, 0x66, 0x9C, 0xAD, 0xB7, + 0x0D, 0x79, 0x0F, 0x22, 0x1F, 0xA4, 0x5B, 0x20, 0x96, 0xA4, 0x59, 0xC7, 0xB4, 0x6B, 0x31, 0x89, + 0x69, 0x55, 0x18, 0x55, 0xE9, 0x81, 0xAA, 0xF9, 0x36, 0xAC, 0x5C, 0xE7, 0x03, 0x35, 0x30, 0x7D, + 0xAF, 0x48, 0x6D, 0x5D, 0x8A, 0xEA, 0x5A, 0xC4, 0x91, 0xCA, 0x63, 0xB5, 0x1B, 0x83, 0xFE, 0xB5, + 0x37, 0xAC, 0x0D, 0xA1, 0xD3, 0x8C, 0x44, 0x29, 0xAF, 0x4E, 0xD9, 0x05, 0xC9, 0xC2, 0xBF, 0x42, + 0xA3, 0xE0, 0xD8, 0x07, 0xBE, 0x19, 0xB7, 0x0C, 0xD6, 0x6C, 0x06, 0xC4, 0xF5, 0xCC, 0x65, 0x03, + 0x8C, 0x35, 0x4C, 0x87, 0x7B, 0x0C, 0x52, 0x53, 0xD6, 0x3F, 0xBC, 0x52, 0x79, 0x66, 0xD3, 0x5F, + 0xD2, 0x48, 0x97, 0xBB, 0x96, 0x6C, 0xEB, 0x1C, 0x73, 0xFC, 0x66, 0x3B, 0xD7, 0x44, 0x47, 0x57, + 0x69, 0x5C, 0xF5, 0x02, 0x97, 0x68, 0xFC, 0x56, 0xF5, 0xF9, 0x25, 0x9E, 0x34, 0x39, 0x14, 0x79, + 0x3D, 0x79, 0x9D, 0xE1, 0xFB, 0x87, 0xA5, 0x4E, 0xBB, 0x7C, 0x16, 0x9C, 0x71, 0x36, 0x76, 0x88, + 0x1F, 0xB6, 0x3B, 0x48, 0xD2, 0x5D, 0x36, 0x61, 0xE8, 0x65, 0xF8, 0x45, 0xEC, 0xFC, 0x9F, 0x5A, + 0xE0, 0xE7, 0x3F, 0x13, 0xF7, 0x9C, 0xF1, 0x93, 0xFE, 0xD2, 0x2A, 0xEC, 0x18, 0xFF, 0x7D, 0xFE, + 0xF3, 0xB0, 0xD4, 0x7B, 0x35, 0x32, 0xD5, 0x29, 0xE6, 0x7A, 0x37, 0xE2, 0xCC, 0x0A, 0xC6, 0xF7, + 0xDC, 0x65, 0xF6, 0x80, 0x91, 0x9F, 0x07, 0xE0, 0xAF, 0x87, 0x86, 0x42, 0xD3, 0xD6, 0x04, 0x32, + 0xFF, 0xE7, 0x7F, 0xFC, 0xEF, 0x81, 0xF1, 0x9D, 0x7B, 0xFF, 0xF9, 0x1F, 0xFF, 0x87, 0x39, 0xF0, + 0xA2, 0xC7, 0x01, 0x6D, 0xF5, 0x16, 0x3B, 0xB6, 0x9E, 0xFC, 0x91, 0x61, 0x0D, 0x99, 0x7A, 0x6F, + 0x3F, 0x70, 0xB6, 0xFB, 0xF9, 0x4F, 0x90, 0x29, 0x9F, 0x00, 0x6B, 0xD0, 0x74, 0x39, 0xB9, 0xBB, + 0x83, 0x97, 0x87, 0xDC, 0xA3, 0x9E, 0x80, 0xDE, 0x76, 0xA8, 0xE7, 0xE1, 0x10, 0xDB, 0x81, 0x44, + 0xAA, 0xB9, 0x1C, 0x96, 0xA6, 0x19, 0xDC, 0x6B, 0xB1, 0x1B, 0x1B, 0x90, 0x80, 0xE1, 0x8C, 0x62, + 0x80, 0x66, 0x2E, 0x5E, 0x5D, 0x1B, 0x1E, 0x79, 0x77, 0xB9, 0xE4, 0xD7, 0x85, 0xAC, 0xBF, 0x0D, + 0x83, 0x91, 0x25, 0xD3, 0xB0, 0xD8, 0x09, 0xFA, 0x0D, 0x8C, 0x6D, 0x9D, 0xB7, 0xD8, 0x99, 0x38, + 0x09, 0x0E, 0x71, 0x32, 0x2D, 0x76, 0x65, 0x8C, 0x0D, 0xDF, 0x3B, 0x64, 0x4A, 0x4B, 0x51, 0x94, + 0x76, 0xA7, 0x43, 0x0D, 0x15, 0xF8, 0xA6, 0xC4, 0xBE, 0x2F, 0xF5, 0xBC, 0x28, 0x7B, 0x6E, 0x4C, + 0xDE, 0x2B, 0x90, 0x07, 0x4B, 0x1C, 0x32, 0x19, 0xA4, 0x21, 0xA4, 0xD4, 0xBD, 0x79, 0x28, 0x23, + 0x2E, 0x4A, 0x0A, 0x1C, 0x4A, 0x15, 0x26, 0x63, 0x77, 0x05, 0xB3, 0x04, 0x54, 0x62, 0x18, 0x27, + 0xBD, 0xE9, 0xBC, 0x12, 0x66, 0x91, 0xE8, 0x17, 0x1B, 0x37, 0x71, 0x5D, 0x4F, 0x00, 0xC2, 0x6B, + 0x37, 0x5C, 0x8F, 0x02, 0x83, 0xF0, 0xF1, 0x91, 0xED, 0x7E, 0xD8, 0x81, 0x5F, 0x34, 0xDE, 0x7A, + 0xF0, 0xA4, 0x3E, 0xD7, 0x1A, 0x47, 0x7D, 0x22, 0x50, 0x8F, 0xDD, 0x73, 0xFF, 0x91, 0x03, 0x8D, + 0xC4, 0xDE, 0xF1, 0xD6, 0x8C, 0xE1, 0xE4, 0xCC, 0xB4, 0x05, 0xAC, 0x00, 0xE8, 0x5E, 0x60, 0x99, + 0x81, 0xCE, 0x91, 0xC0, 0x07, 0x2C, 0xE0, 0x02, 0x40, 0xED, 0xD0, 0xD4, 0x4F, 0xE3, 0x13, 0x78, + 0xF1, 0x02, 0xAF, 0x02, 0x03, 0x1A, 0x04, 0xA6, 0x60, 0x10, 0xBE, 0xFA, 0x8D, 0x78, 0x54, 0xE2, + 0x65, 0x8E, 0x0E, 0x16, 0x6C, 0xC0, 0x1F, 0xA3, 0x19, 0xA8, 0x9A, 0x6B, 0x7B, 0xF0, 0x0B, 0x98, + 0x13, 0xBC, 0x0D, 0x2F, 0x3E, 0xF0, 0x27, 0xB6, 0xD5, 0xD9, 0xFD, 0x6F, 0x6C, 0x64, 0x07, 0xAE, + 0xF7, 0xB6, 0x0E, 0xF6, 0x34, 0xE1, 0x47, 0x6D, 0x7C, 0xE9, 0xA0, 0xFD, 0x7E, 0x3F, 0x1C, 0x1F, + 0x58, 0x12, 0xC1, 0xBC, 0x34, 0x38, 0x63, 0xBE, 0x61, 0xAF, 0x5C, 0xA9, 0x56, 0xAE, 0x44, 0x24, + 0x34, 0x27, 0x5B, 0x82, 0xB6, 0x35, 0xF0, 0xA5, 0x39, 0xBE, 0x9E, 0x53, 0x99, 0x15, 0x1E, 0x39, + 0x4F, 0x96, 0x3A, 0x36, 0xB4, 0x6B, 0x40, 0x51, 0xF3, 0xCC, 0xB5, 0x1D, 0x21, 0x8A, 0x96, 0xB2, + 0x88, 0xC4, 0x9B, 0x36, 0x52, 0xF7, 0x70, 0x7F, 0xC6, 0x0A, 0x72, 0x26, 0xDA, 0x30, 0x6A, 0x74, + 0xB8, 0x62, 0x65, 0xF2, 0x58, 0xFF, 0x7B, 0xE0, 0xF9, 0x21, 0x33, 0xF1, 0xB9, 0x6B, 0xA9, 0x26, + 0x53, 0xCD, 0xA1, 0xED, 0x1A, 0xFE, 0x68, 0x8C, 0x54, 0x39, 0x56, 0x7D, 0x6D, 0x44, 0xDF, 0x83, + 0x82, 0x20, 0x54, 0x4E, 0xD5, 0x71, 0x40, 0x45, 0x16, 0xC2, 0x10, 0xB7, 0x1E, 0x0C, 0xD7, 0xB6, + 0x70, 0x6C, 0xC9, 0xA0, 0xE4, 0xE5, 0x2E, 0x33, 0xC6, 0xA0, 0x9A, 0x3E, 0x70, 0xD1, 0xB7, 0xCB, + 0x35, 0x6E, 0x00, 0x4B, 0x78, 0xE3, 0x89, 0x61, 0x1C, 0x90, 0xF1, 0x45, 0x07, 0xC0, 0xBA, 0xE2, + 0x5C, 0x4E, 0xDE, 0x15, 0x07, 0x78, 0xF7, 0x6A, 0x3F, 0x18, 0x3A, 0xDE, 0xE9, 0x02, 0xB7, 0x70, + 0x81, 0x97, 0x69, 0x5A, 0x40, 0xDC, 0x25, 0xF4, 0xC4, 0x45, 0x9F, 0x6D, 0xC0, 0xED, 0x16, 0xBA, + 0xC5, 0xD1, 0x88, 0xF1, 0x81, 0x70, 0xEA, 0x00, 0xAB, 0xC0, 0xF2, 0x02, 0xC3, 0xC7, 0x10, 0x0F, + 0x06, 0x30, 0xF2, 0x11, 0xEE, 0xC4, 0x7B, 0x68, 0xBF, 0xA8, 0xC1, 0x10, 0xDE, 0xB6, 0xB2, 0x96, + 0x84, 0x9C, 0xCC, 0x34, 0xBE, 0x71, 0x13, 0x9D, 0x34, 0xF0, 0x66, 0x1A, 0x84, 0x29, 0xE4, 0x61, + 0xC8, 0x16, 0x81, 0x3B, 0xC2, 0xDC, 0xA3, 0xF1, 0x40, 0x12, 0xC4, 0xDE, 0x41, 0x78, 0x13, 0x6C, + 0x37, 0x9A, 0xA5, 0x98, 0xB7, 0xF6, 0xB4, 0xBE, 0xCA, 0x78, 0x75, 0xE3, 0x9A, 0xC4, 0xE5, 0xC2, + 0x6B, 0x71, 0xE1, 0x08, 0x20, 0xAC, 0xA2, 0x49, 0xDA, 0x98, 0x26, 0xB4, 0x24, 0x53, 0xD2, 0x25, + 0xD9, 0x09, 0xAE, 0x54, 0xB8, 0x3E, 0x1A, 0x66, 0xE5, 0x7C, 0x62, 0x6C, 0x58, 0xE7, 0x26, 0x7F, + 0xC8, 0xD5, 0x85, 0xE7, 0x36, 0x9E, 0xCD, 0xC8, 0x35, 0x62, 0xB0, 0xB2, 0x4C, 0xE5, 0x1A, 0x90, + 0xB4, 0xFF, 0x37, 0x86, 0x4D, 0x08, 0xA9, 0x0F, 0x7F, 0x5A, 0xB1, 0x88, 0x23, 0xF9, 0x0B, 0xCC, + 0x03, 0xC3, 0xAE, 0x18, 0x0F, 0x27, 0x82, 0xD4, 0xA3, 0x73, 0x0C, 0x4B, 0xF0, 0x88, 0x04, 0x55, + 0x61, 0x2E, 0xF0, 0x80, 0xB0, 0x4D, 0xD3, 0xF0, 0xC9, 0x8E, 0x75, 0xCF, 0x51, 0x62, 0xD1, 0x05, + 0xA1, 0x81, 0xAA, 0x55, 0x56, 0x3F, 0x59, 0x9A, 0x6E, 0x52, 0x8E, 0xCC, 0xCA, 0x9C, 0xFE, 0xF3, + 0x92, 0x52, 0x95, 0xA3, 0x3C, 0x81, 0x9D, 0x15, 0x8E, 0x6E, 0xD1, 0x60, 0xF3, 0xCE, 0x6B, 0x98, + 0xF8, 0xE9, 0xCD, 0x97, 0x95, 0x91, 0x21, 0x8C, 0x55, 0x85, 0x0A, 0x4F, 0x77, 0x6E, 0x94, 0xE7, + 0xA6, 0xBE, 0x09, 0x75, 0xA1, 0xFB, 0x95, 0x6A, 0x8A, 0xB8, 0x8B, 0x54, 0x52, 0x9B, 0x98, 0x0C, + 0xF6, 0xF5, 0x13, 0x90, 0xDA, 0x91, 0x46, 0x7F, 0x3B, 0x3F, 0x6B, 0x5E, 0xBC, 0xEF, 0xD1, 0xB1, + 0xD6, 0x56, 0xA2, 0xC7, 0x5F, 0xAF, 0xDF, 0x1F, 0x28, 0xAF, 0xB4, 0x39, 0x1F, 0x6D, 0x22, 0x16, + 0x55, 0x21, 0x4D, 0x78, 0x7F, 0x63, 0x28, 0x13, 0x4D, 0xD7, 0xA1, 0x9D, 0xD5, 0xF2, 0x10, 0xF5, + 0x88, 0xF5, 0x9F, 0x8E, 0xB8, 0xF6, 0xED, 0xC4, 0xFE, 0xCE, 0xBD, 0x92, 0xD2, 0x34, 0x99, 0x8B, + 0xE3, 0x3D, 0x40, 0xC3, 0xE4, 0xE7, 0x12, 0x37, 0x83, 0xB5, 0x7A, 0x36, 0xDE, 0xC5, 0x25, 0x4C, + 0x90, 0x0D, 0x35, 0xD5, 0x21, 0xD9, 0x12, 0x04, 0x41, 0x58, 0xAA, 0x0C, 0x64, 0x05, 0x61, 0x51, + 0xBC, 0x83, 0x32, 0xA9, 0x20, 0x38, 0x38, 0xEB, 0x5C, 0x1B, 0x24, 0x4F, 0x20, 0x2C, 0xC3, 0x31, + 0xF9, 0x84, 0x20, 0x23, 0x45, 0x3B, 0xFA, 0x2A, 0x01, 0x32, 0x50, 0xFA, 0xFB, 0xF6, 0x98, 0xC7, + 0xC5, 0x53, 0x8F, 0xE9, 0x86, 0xE6, 0xA3, 0x1C, 0x8C, 0xD2, 0xAB, 0xC5, 0x81, 0x78, 0xD1, 0x8B, + 0x32, 0x70, 0x51, 0x94, 0x86, 0x69, 0x70, 0x17, 0xE3, 0x3E, 0x92, 0xDD, 0xD0, 0x7C, 0x1C, 0xFC, + 0x0B, 0xE9, 0x5B, 0x88, 0x4B, 0xC2, 0x08, 0x20, 0xA4, 0xDF, 0xE4, 0xCB, 0xE4, 0x6E, 0x29, 0xAC, + 0x96, 0xD3, 0x12, 0x35, 0x2C, 0x06, 0x45, 0x71, 0x7F, 0x64, 0x7B, 0x3C, 0x5A, 0x1A, 0xC8, 0xF2, + 0xD0, 0x49, 0x28, 0x81, 0x8F, 0xC5, 0x52, 0xEF, 0x39, 0x7E, 0x26, 0xDE, 0xA2, 0x07, 0x2E, 0xFE, + 0x1D, 0x09, 0xC4, 0x9A, 0x6A, 0x6A, 0x41, 0xB4, 0xBE, 0x88, 0xDF, 0x1C, 0xC3, 0xA8, 0xDC, 0x42, + 0x70, 0xAE, 0x97, 0xBF, 0x65, 0xC2, 0xA6, 0x9F, 0x80, 0xD4, 0x09, 0x37, 0xCE, 0xEC, 0x60, 0x8A, + 0xCE, 0x11, 0xC9, 0xC5, 0xE5, 0x4D, 0xFC, 0x02, 0xB2, 0xDC, 0x11, 0x33, 0xD3, 0x91, 0x3C, 0x48, + 0x04, 0x39, 0x24, 0xC6, 0xFE, 0x5D, 0x0E, 0x7E, 0x24, 0x7E, 0x97, 0xE3, 0x70, 0x82, 0x49, 0xCD, + 0x8E, 0x42, 0xCF, 0xC3, 0x1B, 0x26, 0x7A, 0x04, 0x73, 0x8F, 0x3C, 0x17, 0x52, 0x48, 0x39, 0x1A, + 0x7D, 0xEE, 0x2B, 0xBE, 0x54, 0x80, 0x7E, 0x52, 0x4D, 0xC3, 0xE4, 0xF6, 0x33, 0x41, 0x34, 0x1C, + 0xFD, 0x48, 0xFE, 0xB1, 0x6A, 0x98, 0x46, 0xE3, 0xD7, 0x0C, 0x54, 0xD3, 0xB6, 0x60, 0x72, 0xCF, + 0x05, 0xD4, 0xAB, 0x2F, 0x37, 0xC7, 0xFD, 0x3E, 0x00, 0x55, 0xFC, 0xB1, 0x72, 0xA0, 0x86, 0xE3, + 0xD7, 0x0C, 0x54, 0xE7, 0xD9, 0x00, 0xDA, 0x43, 0x60, 0xF6, 0x56, 0x0F, 0xC8, 0x5E, 0xED, 0x40, + 0xBC, 0x51, 0x1F, 0x0C, 0xED, 0x99, 0xC0, 0x08, 0x63, 0x5F, 0x9E, 0x36, 0x8E, 0x6E, 0x8E, 0xFF, + 0x76, 0x79, 0xBA, 0x6A, 0x50, 0xCA, 0xB1, 0xEB, 0x05, 0xE6, 0xBF, 0xFC, 0xF9, 0x6C, 0x34, 0xFE, + 0x2F, 0xBF, 0x21, 0x81, 0xE1, 0xCF, 0x55, 0x43, 0x52, 0x8C, 0x5C, 0x2F, 0x20, 0xFB, 0xF7, 0xEA, + 0x73, 0x01, 0xB2, 0x7F, 0x72, 0x0C, 0xCB, 0xC1, 0x9F, 0xAB, 0x06, 0xA4, 0x18, 0x79, 0x21, 0x40, + 0xCE, 0xA5, 0x5A, 0x3B, 0x13, 0xBF, 0x90, 0x84, 0xDC, 0xBB, 0x04, 0x7F, 0xB9, 0x42, 0x45, 0x86, + 0x66, 0x22, 0xCE, 0xE0, 0xCF, 0xAA, 0x27, 0x8D, 0xCA, 0x55, 0x0C, 0x0A, 0x13, 0x3C, 0xA9, 0x03, + 0x35, 0x84, 0x2C, 0xFC, 0x29, 0x9A, 0x50, 0xE3, 0xE8, 0x9C, 0x9E, 0x30, 0xF9, 0x88, 0x7D, 0x3E, + 0xEE, 0xEF, 0x9C, 0xEF, 0x17, 0xEA, 0x90, 0xA7, 0x36, 0x68, 0x25, 0x94, 0x7F, 0xC7, 0x5B, 0x3E, + 0x56, 0xCD, 0x4E, 0x7A, 0xC5, 0x17, 0x1A, 0x5F, 0x41, 0x31, 0xF9, 0x0C, 0x2D, 0xD8, 0xB1, 0x34, + 0xBB, 0xB3, 0x3E, 0x77, 0x29, 0x8A, 0x4C, 0x9B, 0xC0, 0x21, 0xBC, 0x5B, 0xD0, 0xE9, 0x9A, 0x92, + 0xB4, 0x9C, 0x10, 0xA8, 0x09, 0xB2, 0x88, 0x69, 0x27, 0xE7, 0xE5, 0x34, 0x93, 0x75, 0x74, 0xA9, + 0xAB, 0xA4, 0xC1, 0x97, 0xC2, 0xE1, 0x0A, 0xF8, 0x7B, 0xE3, 0xBB, 0x86, 0x73, 0x6A, 0x1A, 0x98, + 0xCC, 0x23, 0x44, 0xE0, 0x9B, 0xBB, 0xDB, 0xCB, 0x1E, 0x13, 0x0F, 0x8B, 0x15, 0xF8, 0xC5, 0xD1, + 0x31, 0x31, 0x87, 0x15, 0x59, 0x0A, 0xBE, 0x92, 0xF6, 0x6C, 0x78, 0x72, 0xB1, 0x1A, 0x8D, 0x8E, + 0x2A, 0x34, 0x5E, 0x6B, 0x60, 0xCE, 0x8A, 0x18, 0x3E, 0xD2, 0x48, 0x42, 0x6D, 0x56, 0x41, 0x3B, + 0xF6, 0x48, 0x95, 0xF6, 0x04, 0xDA, 0xB6, 0xD8, 0xAF, 0x76, 0xE0, 0x86, 0x91, 0x90, 0xE3, 0xC0, + 0xF3, 0xD1, 0x66, 0xF7, 0x68, 0xA0, 0xA7, 0x91, 0x48, 0x0A, 0xE1, 0xA2, 0xD3, 0x2F, 0x53, 0x7D, + 0x86, 0x5E, 0x19, 0xBE, 0x31, 0xE6, 0x71, 0xA5, 0xFA, 0xCC, 0xF0, 0xD6, 0x4F, 0xA3, 0x2E, 0xC5, + 0x89, 0xAD, 0xC9, 0xA6, 0x85, 0x6E, 0x8A, 0xA9, 0x51, 0xBC, 0x4B, 0x36, 0xF8, 0xC6, 0xA7, 0x01, + 0x3B, 0xC3, 0xDD, 0xCF, 0xB6, 0xE7, 0x97, 0xF0, 0x76, 0xDF, 0x9B, 0x31, 0x06, 0x8B, 0xE6, 0x85, + 0xDC, 0x03, 0xFB, 0x3F, 0x9C, 0xD7, 0x60, 0x79, 0x30, 0x9F, 0xC1, 0xB2, 0xC0, 0xF1, 0x3D, 0x1D, + 0x06, 0xA5, 0xAD, 0x97, 0xA9, 0xCD, 0x97, 0x6F, 0xCC, 0x5C, 0x31, 0x5E, 0xF4, 0x30, 0x39, 0xE1, + 0x12, 0xF1, 0x02, 0xFB, 0x5F, 0x35, 0x5E, 0x14, 0x1A, 0xB2, 0xD3, 0xA1, 0x30, 0x3F, 0x66, 0x60, + 0xF3, 0x17, 0x87, 0x19, 0x70, 0x14, 0xB8, 0xCB, 0xC4, 0x0C, 0xEC, 0x7F, 0xDD, 0x39, 0x06, 0xC1, + 0x60, 0x7E, 0xBC, 0xC0, 0xE6, 0x2F, 0x12, 0x2F, 0x7A, 0x3F, 0x17, 0x4B, 0xB6, 0x39, 0x98, 0x93, + 0x75, 0xF1, 0x58, 0x01, 0x73, 0x58, 0xEF, 0xE7, 0xB9, 0x91, 0xE7, 0x9D, 0x40, 0xDC, 0x55, 0x20, + 0x0F, 0x00, 0x6A, 0x31, 0xF4, 0xE9, 0xFD, 0xFC, 0x82, 0x10, 0xE8, 0xDA, 0x0E, 0x2C, 0xBF, 0x67, + 0x1B, 0xD6, 0x7C, 0x47, 0x0E, 0x35, 0x2F, 0x71, 0xE2, 0x40, 0xFF, 0xEB, 0xCB, 0x58, 0x62, 0x30, + 0x98, 0x07, 0x33, 0x26, 0xCD, 0x5F, 0x24, 0x5E, 0x2C, 0x89, 0xB1, 0x54, 0xC0, 0x9C, 0xE2, 0xB7, + 0xD6, 0x98, 0xF1, 0x24, 0x00, 0xB9, 0x18, 0x7A, 0xAD, 0x17, 0xE3, 0x89, 0xF4, 0xFB, 0x76, 0xED, + 0xB6, 0xCC, 0xD8, 0xEA, 0xEF, 0x30, 0xB9, 0xF0, 0xD8, 0xF0, 0x3F, 0x7D, 0x3A, 0x6E, 0x1C, 0x85, + 0x1F, 0x18, 0x7C, 0x42, 0x0D, 0x58, 0xF0, 0xE4, 0xE5, 0xDB, 0xA2, 0x32, 0xE6, 0x53, 0xB8, 0x99, + 0x81, 0x45, 0x1D, 0x72, 0x7D, 0xD5, 0xB6, 0x2B, 0xBA, 0xEA, 0xD7, 0x08, 0x3A, 0x98, 0x0A, 0xF4, + 0x8F, 0xC0, 0x40, 0xB7, 0x57, 0xF8, 0x6B, 0x18, 0x98, 0xAA, 0x3B, 0xB9, 0x40, 0x97, 0xF9, 0x2B, + 0xC9, 0x60, 0x40, 0x37, 0xF4, 0x64, 0xC5, 0xDA, 0x42, 0xF0, 0x8E, 0x45, 0xF0, 0xEF, 0x5B, 0xE6, + 0xC9, 0xCC, 0x4A, 0xF8, 0xBD, 0xE8, 0x12, 0x7E, 0x59, 0x4C, 0x0D, 0x7C, 0x7B, 0x8C, 0x69, 0xAF, + 0x55, 0xD3, 0x7C, 0x92, 0x41, 0xA4, 0xD2, 0x91, 0x40, 0x75, 0xB9, 0xE7, 0x33, 0xF5, 0x41, 0x35, + 0x28, 0x25, 0xFA, 0xB4, 0x7D, 0x22, 0xC5, 0xA8, 0xF0, 0x12, 0x6D, 0x61, 0xC2, 0x89, 0x9D, 0x80, + 0x88, 0x0E, 0xEC, 0x27, 0x22, 0xDC, 0x32, 0x67, 0x2C, 0x19, 0xC5, 0x19, 0x85, 0x0D, 0x0F, 0xB9, + 0x2F, 0x23, 0xB0, 0xAF, 0x0C, 0xCF, 0xDF, 0x7A, 0x3B, 0x13, 0x9F, 0x3C, 0xD6, 0xE9, 0x97, 0x4C, + 0x38, 0x9D, 0x19, 0xEF, 0x99, 0x6F, 0x64, 0x2A, 0x11, 0x0B, 0x5A, 0x18, 0xF7, 0x89, 0x31, 0xB5, + 0xB9, 0xA3, 0xCC, 0x19, 0x16, 0x8A, 0xFD, 0xE6, 0x6F, 0xA0, 0x04, 0x10, 0x85, 0x39, 0x7A, 0xF1, + 0xE0, 0x50, 0x68, 0xBA, 0x78, 0x7C, 0xE8, 0x64, 0xAF, 0x8B, 0x02, 0xB4, 0xCB, 0x93, 0xF0, 0x34, + 0x5E, 0x5C, 0x02, 0x16, 0xDF, 0xE1, 0x69, 0x52, 0xC6, 0x16, 0x78, 0x73, 0x7D, 0x7E, 0x4C, 0xCE, + 0x73, 0xB7, 0xC7, 0x3F, 0xFF, 0x42, 0x29, 0xCA, 0x90, 0xE2, 0xFC, 0x47, 0x9B, 0x8D, 0x6D, 0x20, + 0x39, 0xCD, 0x1E, 0x8F, 0x6D, 0x8B, 0xBC, 0x86, 0xB0, 0xC2, 0x01, 0x3A, 0xF4, 0xC0, 0xF6, 0x7A, + 0xC2, 0x33, 0x5E, 0x00, 0xEA, 0x3E, 0xF0, 0x93, 0xBE, 0x38, 0x5E, 0xE0, 0xE0, 0xBB, 0x9E, 0x70, + 0x8D, 0x07, 0x4A, 0xB7, 0xD8, 0x3B, 0x25, 0x96, 0xEC, 0x4C, 0x36, 0xF4, 0x5A, 0xEC, 0x5C, 0xD5, + 0x46, 0x51, 0x3F, 0x22, 0x3A, 0x47, 0xF0, 0x54, 0xB9, 0x83, 0xEC, 0x71, 0x64, 0x4C, 0xDE, 0x10, + 0x19, 0xD4, 0x74, 0x49, 0xE0, 0x6C, 0x4B, 0x79, 0x4B, 0x13, 0xC7, 0x14, 0x77, 0xF6, 0xC0, 0xC7, + 0x60, 0x1E, 0x8A, 0xF7, 0x11, 0xBD, 0x51, 0xC2, 0x62, 0x39, 0xE5, 0xAD, 0x36, 0xFB, 0x08, 0x44, + 0x30, 0xF9, 0x32, 0xFA, 0x06, 0x43, 0x24, 0xDB, 0xE8, 0x5B, 0xB8, 0xCD, 0xF6, 0xE4, 0x3B, 0xE2, + 0x3B, 0x19, 0x75, 0xB4, 0xC7, 0x28, 0x9A, 0xF2, 0x6D, 0x8C, 0xC1, 0x10, 0xC0, 0x80, 0x9D, 0x6D, + 0xB3, 0x4F, 0x7D, 0xFA, 0x71, 0x87, 0x3F, 0xFE, 0xB6, 0x2D, 0x80, 0x78, 0x7D, 0x1A, 0x0B, 0x65, + 0xC4, 0x03, 0xA5, 0xA3, 0x6C, 0x64, 0x82, 0xB6, 0xA2, 0x90, 0xE4, 0x7C, 0x3A, 0xCA, 0xC9, 0x1D, + 0x98, 0x92, 0xF9, 0x72, 0x2F, 0x25, 0xF1, 0x65, 0x6A, 0x8F, 0xF3, 0xE6, 0x6B, 0x88, 0xF3, 0xC2, + 0xD9, 0x9C, 0x0D, 0xD6, 0x98, 0xAB, 0x72, 0x77, 0xBD, 0xAC, 0x84, 0x0D, 0xE5, 0x3C, 0x5B, 0x23, + 0x3E, 0x4B, 0xD9, 0x01, 0xEE, 0xEC, 0x3E, 0x45, 0xA6, 0x19, 0xD6, 0x30, 0xEC, 0x7E, 0x92, 0xA7, + 0x01, 0x30, 0x23, 0xFA, 0x36, 0xC4, 0x2D, 0xAF, 0x64, 0xD6, 0x86, 0x92, 0x51, 0x5A, 0xCB, 0x81, + 0x96, 0x8C, 0x07, 0x5E, 0x0E, 0xC0, 0xAE, 0x92, 0x9D, 0x27, 0xC0, 0x25, 0xBF, 0x5B, 0x02, 0xB0, + 0xD2, 0x72, 0xE6, 0xA6, 0x9F, 0xBD, 0xB6, 0xA7, 0x1A, 0x1A, 0x32, 0x80, 0xBE, 0xEF, 0x72, 0x75, + 0x1C, 0x06, 0x60, 0x79, 0x65, 0x20, 0x9A, 0xD5, 0x49, 0xBB, 0x44, 0x18, 0x57, 0x96, 0x76, 0xE5, + 0x51, 0x0F, 0x97, 0x18, 0xB4, 0x04, 0xD2, 0x25, 0xF6, 0xF9, 0x3B, 0x48, 0xCB, 0xC4, 0xA1, 0x64, + 0xE7, 0x22, 0xA2, 0x09, 0xBE, 0x3C, 0x2C, 0xE7, 0x68, 0x3C, 0x61, 0x4A, 0xF1, 0xF0, 0x98, 0xD4, + 0x71, 0x68, 0x35, 0xA9, 0xDF, 0x94, 0x0E, 0x8C, 0x9C, 0x37, 0xAC, 0x26, 0x31, 0x53, 0x9B, 0x9C, + 0x47, 0x63, 0x49, 0x1B, 0xDB, 0xCA, 0x18, 0xB0, 0x43, 0x3C, 0x9E, 0xBB, 0x9F, 0x76, 0xE3, 0xA8, + 0x53, 0x47, 0x3F, 0x1D, 0xCC, 0x32, 0x5C, 0x43, 0x3F, 0xDD, 0xC6, 0xD1, 0x5E, 0x1D, 0xFD, 0xEC, + 0x22, 0x7C, 0xEA, 0xE8, 0x68, 0x0F, 0x01, 0x54, 0x47, 0x47, 0xFB, 0xB8, 0xB2, 0x3A, 0x3A, 0x7A, + 0x07, 0x4B, 0x5B, 0xBC, 0x97, 0x03, 0x58, 0xD7, 0xE2, 0xBD, 0xBC, 0x87, 0x45, 0xD5, 0x80, 0x84, + 0x84, 0xCD, 0x35, 0xF4, 0xD3, 0xC6, 0x3C, 0xE2, 0x35, 0xF4, 0x03, 0xD8, 0xDC, 0xAD, 0x63, 0x3E, + 0x80, 0xCD, 0xFB, 0x75, 0xF4, 0x03, 0xD8, 0xDC, 0x19, 0x1B, 0xD6, 0xE2, 0x1D, 0x01, 0x36, 0xEF, + 0xD5, 0xD2, 0xD1, 0x3E, 0xF1, 0x9F, 0x3A, 0x7A, 0x42, 0x74, 0xAE, 0x67, 0x4E, 0x07, 0xB8, 0x6B, + 0xB5, 0xF4, 0xF4, 0x1E, 0xF7, 0xAD, 0x72, 0x4F, 0xC5, 0x51, 0x90, 0x4B, 0xB2, 0x5D, 0x4C, 0xDB, + 0x30, 0x26, 0x26, 0x85, 0xF0, 0x58, 0xA4, 0x60, 0xA1, 0xF8, 0x81, 0xB9, 0x69, 0xE9, 0x46, 0x4A, + 0x49, 0x30, 0x25, 0x25, 0xA1, 0x5C, 0x39, 0xA5, 0x53, 0xAF, 0x9C, 0xD2, 0x4E, 0xC8, 0x29, 0x9D, + 0xA5, 0xC9, 0x29, 0xED, 0x4C, 0x39, 0xA5, 0xFD, 0x2A, 0xA7, 0xBC, 0xCA, 0x29, 0xAF, 0x72, 0xCA, + 0xAB, 0x9C, 0xF2, 0x2A, 0xA7, 0xBC, 0xCA, 0x29, 0x9B, 0x26, 0xA7, 0x74, 0x36, 0x2F, 0x2D, 0x5A, + 0xB1, 0x21, 0xA6, 0xA4, 0x61, 0x2B, 0x66, 0xEE, 0xC6, 0x6B, 0x0C, 0x34, 0x1D, 0x2E, 0x37, 0xBE, + 0xB8, 0xC4, 0xE3, 0xD0, 0xAE, 0x9A, 0x97, 0xA5, 0x93, 0x92, 0x4B, 0x3D, 0x67, 0x96, 0x4E, 0x51, + 0xC3, 0xD0, 0x5B, 0x56, 0xF1, 0x9E, 0x93, 0x58, 0xD7, 0x95, 0xAE, 0x67, 0x62, 0x0D, 0x33, 0xF6, + 0x01, 0x01, 0x99, 0x52, 0x91, 0x2F, 0xA3, 0x74, 0x0D, 0xFE, 0x8B, 0x01, 0x7B, 0x2A, 0xD1, 0x27, + 0x41, 0x60, 0x9D, 0x12, 0x7D, 0xE6, 0x2E, 0x7F, 0xCE, 0x32, 0x3C, 0x24, 0xF3, 0x92, 0x81, 0xF9, + 0xD2, 0x12, 0xB9, 0xBE, 0x0B, 0xBD, 0xD8, 0x13, 0xC9, 0xC2, 0x43, 0x40, 0xDD, 0xC1, 0xC3, 0xBE, + 0xEC, 0x27, 0x4C, 0x21, 0x1E, 0x3E, 0x4F, 0x7A, 0x2B, 0xC8, 0x86, 0x85, 0xD7, 0xD3, 0x71, 0xBD, + 0x60, 0x66, 0x84, 0x23, 0xF1, 0x57, 0xF3, 0xD2, 0x5A, 0x71, 0xF0, 0xFC, 0xA5, 0x48, 0x52, 0xE7, + 0xB8, 0x5C, 0x33, 0x00, 0x71, 0xA2, 0x7C, 0x9A, 0xF6, 0x80, 0xA9, 0x0C, 0xA7, 0xC9, 0x3C, 0x99, + 0x13, 0x8A, 0x8A, 0x30, 0xFA, 0xEC, 0x9B, 0x45, 0x65, 0x9E, 0x7D, 0x4A, 0xA3, 0x79, 0xCF, 0x99, + 0x7D, 0x4F, 0x25, 0x0D, 0x75, 0x76, 0xFF, 0x84, 0x49, 0x38, 0xBD, 0xD0, 0xB8, 0x8F, 0x89, 0x38, + 0xB1, 0xE7, 0xB0, 0xC7, 0x16, 0x65, 0xA5, 0xA3, 0x1E, 0xA1, 0x27, 0xBC, 0x5D, 0xA2, 0x04, 0x17, + 0x78, 0xF3, 0x44, 0x13, 0x17, 0x39, 0xA6, 0xD4, 0x6F, 0x78, 0xDB, 0xE5, 0x38, 0xAE, 0xFD, 0x1D, + 0x68, 0xD9, 0xC7, 0x1C, 0x4F, 0xFB, 0x4A, 0x94, 0xFF, 0xEE, 0xD1, 0x76, 0xFD, 0x91, 0x48, 0xF0, + 0xA4, 0xEA, 0x61, 0xAD, 0x22, 0x31, 0x01, 0x9C, 0x2D, 0x5E, 0x95, 0x0F, 0x60, 0x66, 0xD1, 0x22, + 0x70, 0x34, 0x9D, 0xD9, 0xD6, 0x74, 0x1E, 0xBE, 0x30, 0x6D, 0xDF, 0x98, 0xFB, 0x23, 0x5B, 0x67, + 0xAA, 0x36, 0x32, 0x38, 0x26, 0xC5, 0xFA, 0xF7, 0xAE, 0xA2, 0x8D, 0x53, 0x72, 0x5A, 0xE1, 0x4D, + 0x1F, 0x5E, 0xD4, 0x3F, 0x00, 0x77, 0x69, 0xB1, 0x4B, 0x4B, 0x83, 0xF1, 0xBD, 0x30, 0xB9, 0x55, + 0x98, 0xCF, 0xE3, 0xCB, 0x3D, 0x46, 0x07, 0x88, 0x81, 0xEF, 0x8C, 0x31, 0x0F, 0x13, 0x89, 0xDE, + 0x0A, 0x9F, 0x01, 0x1D, 0x73, 0xC9, 0x5A, 0x0C, 0xAB, 0x06, 0xC6, 0x22, 0xFA, 0x0D, 0xD1, 0x17, + 0x8F, 0x12, 0x52, 0xD1, 0x58, 0x74, 0xF1, 0x88, 0xB9, 0xB2, 0x60, 0x0A, 0x06, 0xE6, 0xF0, 0x3A, + 0xE1, 0x58, 0x80, 0x75, 0xF2, 0x92, 0xE1, 0x85, 0x93, 0xD6, 0x29, 0xEC, 0x80, 0x12, 0x02, 0x36, + 0xE1, 0x95, 0x71, 0x94, 0xB7, 0x54, 0xA6, 0xBB, 0xA2, 0x12, 0x4B, 0x98, 0x93, 0x99, 0xEA, 0x97, + 0x4E, 0xF2, 0x88, 0x28, 0x22, 0xA9, 0xD7, 0x5E, 0x4B, 0x19, 0x4F, 0x2E, 0xEE, 0xF6, 0xE9, 0xE6, + 0x6E, 0x5F, 0x51, 0xBC, 0x6D, 0xD6, 0x6E, 0xD1, 0x07, 0x7A, 0x61, 0xE3, 0xE2, 0x14, 0x42, 0x0E, + 0x20, 0xE3, 0xC5, 0xBC, 0x46, 0x89, 0x78, 0xC3, 0xB0, 0xCD, 0x9C, 0x81, 0x0D, 0x0B, 0x79, 0x8E, + 0x4D, 0xF3, 0x07, 0x7B, 0x82, 0x4B, 0x32, 0x4F, 0x66, 0xAE, 0x4B, 0x61, 0xBB, 0x93, 0x96, 0xE5, + 0x06, 0xB1, 0xB2, 0xDC, 0x6D, 0x54, 0x0C, 0x73, 0x31, 0x56, 0x85, 0x6D, 0x79, 0x6F, 0x0F, 0x4B, + 0x5B, 0x23, 0x8A, 0x32, 0x23, 0x56, 0x30, 0x17, 0x54, 0xF3, 0x73, 0x4F, 0x01, 0x52, 0xC9, 0x61, + 0x9C, 0x8C, 0xF6, 0x8B, 0xF8, 0x84, 0x55, 0x93, 0xF5, 0x56, 0x8E, 0x46, 0x3D, 0xC9, 0xCB, 0xC2, + 0x08, 0xBC, 0x72, 0xB2, 0x79, 0x35, 0x9C, 0x0B, 0x39, 0x5D, 0xA9, 0xAE, 0x89, 0x1B, 0x76, 0xCF, + 0x40, 0xAC, 0x07, 0x3E, 0x84, 0xE7, 0x7B, 0xC4, 0x19, 0x4B, 0x35, 0xDF, 0x1A, 0x2F, 0x8A, 0xA2, + 0x84, 0x9C, 0x12, 0x4F, 0xEF, 0x0B, 0xA3, 0x43, 0x17, 0x46, 0xD1, 0x99, 0x0D, 0x98, 0x17, 0x57, + 0xA7, 0x3B, 0x5A, 0x1D, 0xD2, 0x2E, 0xCB, 0xB5, 0x8B, 0x84, 0x81, 0x45, 0x85, 0xB5, 0x0B, 0xEC, + 0x64, 0x56, 0x52, 0x8B, 0xAC, 0x85, 0x29, 0x32, 0x5B, 0x35, 0x59, 0x4D, 0x0C, 0x70, 0x44, 0xBF, + 0x12, 0x27, 0x9E, 0x28, 0x7B, 0x7E, 0xC4, 0xB6, 0x4E, 0x47, 0x36, 0xA6, 0xE0, 0xC1, 0x1A, 0xB2, + 0xCC, 0x2E, 0x76, 0xF4, 0xFF, 0x24, 0xAB, 0xE0, 0xBE, 0x0D, 0x4B, 0xAD, 0x3E, 0x8B, 0xE4, 0x17, + 0x97, 0xF8, 0xFC, 0x98, 0x84, 0x16, 0xC9, 0x79, 0x28, 0xF8, 0x80, 0x9C, 0x47, 0xD5, 0xA1, 0x85, + 0xCC, 0xC6, 0x41, 0xE2, 0x00, 0x69, 0x44, 0xAE, 0x33, 0x5A, 0x07, 0x8B, 0x55, 0xD9, 0x45, 0x29, + 0x49, 0x84, 0x5A, 0x62, 0x62, 0xCF, 0xA4, 0x9B, 0x94, 0x10, 0x7C, 0xC6, 0x63, 0xAE, 0x1B, 0x42, + 0xC2, 0xBB, 0xE7, 0x43, 0x23, 0x4C, 0x1C, 0x4A, 0x61, 0x96, 0xB7, 0x77, 0xA7, 0xD7, 0xB3, 0xAE, + 0x8E, 0xC7, 0x52, 0x6A, 0x8C, 0xC4, 0x32, 0xC3, 0x13, 0x32, 0x5F, 0x24, 0x82, 0x92, 0x28, 0xD4, + 0xEB, 0xF5, 0xD8, 0x96, 0x23, 0x0A, 0xB5, 0x7B, 0x1C, 0x04, 0xD4, 0xC0, 0x65, 0x7E, 0xE0, 0xDB, + 0xA0, 0x82, 0x99, 0x6F, 0xA9, 0xB8, 0x24, 0xBE, 0x35, 0x25, 0x1A, 0x31, 0x75, 0x08, 0x5D, 0xA0, + 0xAB, 0x25, 0xCC, 0x93, 0xDC, 0xB5, 0xB4, 0x48, 0xF2, 0x8D, 0x89, 0x4D, 0x61, 0xF5, 0xEF, 0x37, + 0xDE, 0x04, 0x6E, 0x98, 0x3D, 0xD9, 0x0E, 0x4C, 0x9D, 0xBB, 0xDB, 0xA0, 0x77, 0x99, 0x36, 0xE0, + 0x96, 0xBD, 0x79, 0x12, 0x13, 0x81, 0xB6, 0x86, 0x98, 0xCE, 0x32, 0x81, 0xF6, 0x19, 0x94, 0x4C, + 0x53, 0x10, 0x3A, 0x61, 0x88, 0x47, 0x48, 0x77, 0xA2, 0x60, 0xB3, 0x2C, 0xE2, 0x24, 0xB7, 0x3E, + 0x41, 0xDB, 0x4A, 0x69, 0xA7, 0xFA, 0x09, 0xED, 0xCF, 0xE1, 0x67, 0x4D, 0xCC, 0x20, 0x6F, 0x8E, + 0x54, 0x3C, 0x9A, 0x4D, 0xBE, 0x88, 0x22, 0xFB, 0x73, 0xAF, 0xA9, 0x4A, 0x39, 0x8B, 0x87, 0x25, + 0x9D, 0x0B, 0x36, 0x68, 0x89, 0x52, 0x45, 0xAC, 0xF1, 0x04, 0x74, 0xBB, 0x91, 0x34, 0x20, 0x02, + 0x4B, 0x0E, 0x66, 0x44, 0x82, 0x92, 0xD7, 0x78, 0x59, 0x4E, 0x57, 0x81, 0x47, 0xA0, 0x8D, 0xC1, + 0xB4, 0x54, 0x65, 0xA1, 0xF2, 0x86, 0xC7, 0xC8, 0x11, 0x6B, 0x76, 0x24, 0x74, 0xC2, 0xBA, 0xC2, + 0x98, 0x70, 0xDA, 0xD6, 0x0B, 0xF4, 0xEB, 0x46, 0x37, 0xC0, 0x72, 0xEE, 0x57, 0xCB, 0xB7, 0x95, + 0xF6, 0x02, 0x99, 0x21, 0x5A, 0x26, 0xB8, 0x13, 0xD3, 0x8C, 0xB1, 0x60, 0x34, 0xA1, 0xDA, 0xF4, + 0x86, 0x60, 0x9B, 0xBF, 0xEC, 0xFC, 0xBA, 0xF3, 0x1B, 0x82, 0x89, 0x7B, 0xAD, 0x97, 0x6B, 0x44, + 0x5D, 0x0D, 0x09, 0x24, 0xCA, 0x23, 0x74, 0xE7, 0xB8, 0x18, 0xA6, 0x2D, 0x39, 0x17, 0x85, 0xE4, + 0xB3, 0xC8, 0x2A, 0x4E, 0x47, 0xBF, 0x54, 0x10, 0x76, 0x2B, 0xDC, 0x77, 0xA7, 0xA9, 0x6D, 0x07, + 0x4B, 0x91, 0x84, 0x63, 0x0B, 0xAE, 0x24, 0xF8, 0x4E, 0xDA, 0xBD, 0x08, 0xE5, 0x6C, 0x29, 0x38, + 0xF4, 0x6B, 0x39, 0x1C, 0xFA, 0xF5, 0xC5, 0xE0, 0xD0, 0xAF, 0x73, 0xE2, 0xD0, 0xAF, 0xAF, 0x38, + 0x94, 0x85, 0x43, 0xBF, 0x95, 0xC3, 0xA1, 0xDF, 0x5E, 0x0C, 0x0E, 0xFD, 0x36, 0x27, 0x0E, 0xFD, + 0xF6, 0x8A, 0x43, 0x53, 0x38, 0x64, 0x81, 0x00, 0x85, 0xE2, 0xB9, 0x10, 0xD4, 0xCB, 0x60, 0x51, + 0xB9, 0xFA, 0xA1, 0xCF, 0x8A, 0x48, 0x45, 0x51, 0xA9, 0xF1, 0x35, 0x57, 0x42, 0xA4, 0x78, 0xCB, + 0x97, 0x63, 0x6F, 0x3C, 0x3A, 0x0D, 0xE3, 0xA5, 0xBE, 0xE2, 0x95, 0x4B, 0x4C, 0x8C, 0x7E, 0xF6, + 0x52, 0x4E, 0x54, 0x2D, 0x04, 0xAD, 0x04, 0x83, 0x84, 0x74, 0x2C, 0xCD, 0x1A, 0x94, 0x0C, 0x19, + 0xE4, 0xE4, 0x3F, 0x02, 0xD8, 0x17, 0x98, 0xBE, 0x66, 0x3B, 0x4F, 0x3B, 0x0E, 0xC6, 0x66, 0x4A, + 0x0B, 0xC8, 0x8C, 0x44, 0xBD, 0xD9, 0x72, 0x74, 0xF9, 0x6A, 0x48, 0xCB, 0xE5, 0x3E, 0x55, 0xD4, + 0xA7, 0x69, 0xB2, 0xA1, 0x18, 0xBF, 0x8C, 0x8A, 0xD1, 0xC0, 0x5C, 0xE4, 0x9B, 0x87, 0x62, 0xA7, + 0x24, 0x68, 0xCA, 0xF9, 0x8A, 0x8A, 0x31, 0xE3, 0x9E, 0x95, 0x7D, 0x61, 0x03, 0x8A, 0x21, 0xB4, + 0x60, 0x73, 0x38, 0xA7, 0xAC, 0xEF, 0x3C, 0xE3, 0x4F, 0xF2, 0xBF, 0x2B, 0x8D, 0x1B, 0x51, 0xC4, + 0xD2, 0xF7, 0xE6, 0xA3, 0xA1, 0xFB, 0xA3, 0xC3, 0xEE, 0x9E, 0x52, 0x2E, 0x5E, 0x29, 0xCB, 0x0F, + 0x08, 0x55, 0x57, 0x61, 0x9F, 0x3A, 0x66, 0xCD, 0x76, 0xE7, 0x40, 0xE9, 0x28, 0xFB, 0xAD, 0xBD, + 0xFD, 0x03, 0xD6, 0xDC, 0x7D, 0xD7, 0xDE, 0x3F, 0x50, 0x76, 0x5B, 0xBB, 0x4A, 0x97, 0xED, 0x2A, + 0x07, 0xFB, 0xFB, 0xFB, 0x7B, 0xAD, 0xDD, 0x83, 0xDD, 0x3A, 0xFC, 0x28, 0xC3, 0x21, 0x4F, 0x56, + 0x34, 0x64, 0x97, 0x86, 0x3C, 0x5D, 0xD1, 0x68, 0xBB, 0x8D, 0xA3, 0x63, 0x3C, 0xB8, 0xEE, 0x46, + 0xAA, 0x7F, 0xE9, 0xDD, 0xD9, 0xF6, 0x95, 0x6D, 0x0D, 0xEF, 0xEC, 0x13, 0x7E, 0x26, 0x30, 0x10, + 0xF8, 0x48, 0xE6, 0x44, 0x2A, 0x55, 0x4C, 0x9B, 0x7B, 0xD2, 0xE5, 0xDD, 0xB8, 0xD6, 0x4D, 0x06, + 0x99, 0xB9, 0x60, 0xAA, 0xD1, 0x86, 0xA4, 0xEA, 0x7A, 0x52, 0x32, 0xA9, 0xD7, 0x70, 0x24, 0xBB, + 0x47, 0x6B, 0xD1, 0xB1, 0xAE, 0x57, 0xB4, 0x0E, 0xE5, 0x44, 0x1B, 0xAA, 0x4B, 0x9D, 0x75, 0xD8, + 0x7F, 0x68, 0xE4, 0xAA, 0x6B, 0xDE, 0x3A, 0x20, 0xA0, 0xCF, 0x97, 0x39, 0xF3, 0xC9, 0x08, 0x38, + 0xF7, 0x33, 0xFA, 0xB4, 0x2E, 0x36, 0x39, 0x40, 0x00, 0x90, 0x25, 0xB6, 0x45, 0x61, 0x5A, 0x55, + 0xA7, 0x64, 0x10, 0xDB, 0x64, 0x82, 0x8B, 0x2A, 0x83, 0xBB, 0x5C, 0x83, 0xD3, 0x22, 0x26, 0x49, + 0xD0, 0xDB, 0x62, 0x51, 0xCC, 0xF0, 0x5B, 0x3F, 0x9E, 0x7B, 0x63, 0x95, 0x6C, 0x29, 0xF5, 0xDF, + 0x2E, 0x7C, 0xC2, 0xCA, 0x06, 0x39, 0x97, 0x0B, 0xED, 0xE7, 0xBF, 0x5C, 0xF8, 0x44, 0xE5, 0x0F, + 0xE4, 0x25, 0x5B, 0xBD, 0x77, 0x0A, 0x43, 0xD9, 0xEB, 0xB3, 0xF9, 0xBC, 0x3C, 0xDB, 0xB5, 0xC2, + 0xA7, 0x68, 0xE5, 0x93, 0xAB, 0x85, 0xAA, 0x61, 0x31, 0xB9, 0x9C, 0x2D, 0x71, 0xB5, 0x90, 0x32, + 0x5A, 0x74, 0xBD, 0x70, 0x75, 0x35, 0x2A, 0x3D, 0xF0, 0xFA, 0xDF, 0x42, 0xC0, 0x6A, 0xA6, 0x2F, + 0x1E, 0xF0, 0xD1, 0xEB, 0xB5, 0x43, 0x1D, 0xFE, 0x3C, 0x04, 0xCF, 0x2B, 0xD5, 0x2F, 0x4E, 0x72, + 0x92, 0xE9, 0xC0, 0xB3, 0x3B, 0x95, 0x87, 0x6E, 0x77, 0x86, 0xB6, 0xA0, 0x7F, 0xC3, 0x0F, 0x74, + 0x5E, 0x83, 0x07, 0xD8, 0xFE, 0x12, 0x2C, 0x2F, 0x09, 0x18, 0x54, 0x37, 0xE1, 0xC9, 0x96, 0x2F, + 0xCD, 0xD3, 0x4B, 0xAC, 0x0D, 0x15, 0x92, 0xA5, 0xA2, 0x06, 0x0C, 0xB0, 0xFE, 0xB8, 0x11, 0x42, + 0x61, 0x0E, 0xE4, 0x90, 0x4D, 0x5F, 0x8C, 0x89, 0x57, 0x88, 0xE4, 0x3E, 0x89, 0x9E, 0x17, 0x58, + 0x08, 0xD7, 0x4F, 0x35, 0xD0, 0x56, 0x33, 0xFA, 0x66, 0x25, 0x9C, 0x03, 0x61, 0x5C, 0x8C, 0xC4, + 0xC4, 0x50, 0x87, 0x15, 0x03, 0x5A, 0x43, 0x53, 0x4F, 0x72, 0xC2, 0xF9, 0xC6, 0x9E, 0x4D, 0xBD, + 0x40, 0xAE, 0xDC, 0x38, 0x95, 0xE0, 0x8F, 0x4D, 0xC1, 0xAA, 0x1B, 0xC5, 0xC4, 0x3C, 0x9B, 0x35, + 0xF2, 0xF3, 0xF1, 0x79, 0xE9, 0xD3, 0xF8, 0x5A, 0x75, 0xBF, 0xED, 0xC0, 0x68, 0xE8, 0x75, 0x39, + 0xDF, 0x11, 0x5E, 0x8F, 0xD4, 0x11, 0x93, 0x3C, 0x3E, 0x73, 0x6C, 0xCA, 0x8E, 0xEF, 0xED, 0x07, + 0xCE, 0xCE, 0x4D, 0xD3, 0x70, 0x3C, 0xDB, 0xD0, 0x43, 0x2F, 0x36, 0x00, 0xC2, 0x37, 0xE9, 0xE4, + 0x6F, 0x48, 0x01, 0x25, 0x12, 0xBD, 0x50, 0xE1, 0x52, 0x25, 0xE4, 0xE2, 0xEF, 0xE3, 0xF3, 0xB1, + 0x6D, 0x05, 0x54, 0x63, 0x5A, 0x06, 0x0D, 0xE0, 0x16, 0x59, 0x7A, 0x15, 0xC1, 0x65, 0xE9, 0xC2, + 0x4B, 0x15, 0x01, 0xA6, 0xB4, 0xCD, 0xB7, 0x90, 0x5D, 0xEF, 0x56, 0x91, 0xDD, 0xAA, 0xDF, 0xC8, + 0x45, 0x98, 0x5C, 0x76, 0x4D, 0xE5, 0xAE, 0x84, 0x4A, 0xBE, 0xE6, 0xCC, 0x4E, 0xA4, 0x86, 0xF4, + 0xA0, 0x4B, 0xE4, 0x24, 0x84, 0x5F, 0xE9, 0x3C, 0x91, 0xC9, 0xBC, 0x57, 0x26, 0x1F, 0xF8, 0x87, + 0xBB, 0x15, 0xCC, 0xC8, 0x69, 0x8A, 0xB3, 0x50, 0x8C, 0x91, 0x38, 0x84, 0x7B, 0x6E, 0xCC, 0x9D, + 0x36, 0x66, 0x00, 0xC3, 0x6A, 0xF5, 0xC0, 0x4D, 0x50, 0xA3, 0xA9, 0xC2, 0xC7, 0x28, 0x14, 0x4C, + 0x35, 0x35, 0x68, 0x8A, 0xFC, 0x05, 0x13, 0x64, 0x8B, 0x1A, 0x94, 0x9C, 0xC1, 0x23, 0xE2, 0x39, + 0x73, 0x9C, 0x20, 0xCB, 0xD0, 0x72, 0x2E, 0x07, 0x61, 0x11, 0xCC, 0xED, 0x68, 0x6A, 0xA2, 0xD2, + 0xA8, 0x9C, 0x30, 0x45, 0x3F, 0xFD, 0xB3, 0x17, 0xDC, 0xFB, 0xAE, 0x4A, 0x55, 0x3C, 0xFF, 0x99, + 0xB8, 0x47, 0xE8, 0x33, 0x7B, 0x0C, 0xBF, 0x2D, 0x4B, 0x65, 0x92, 0x67, 0x61, 0xE0, 0xCD, 0xF1, + 0x6D, 0x6F, 0x92, 0x2B, 0x34, 0xE2, 0x46, 0x51, 0x7E, 0x3E, 0xE8, 0x8E, 0x0A, 0xE0, 0x60, 0x19, + 0xEE, 0xD0, 0x71, 0x76, 0xC2, 0xCF, 0x46, 0xD0, 0xC3, 0x13, 0x7B, 0x1C, 0x71, 0x4B, 0x46, 0x35, + 0x89, 0xBA, 0xA1, 0xC4, 0xC4, 0xC8, 0xBB, 0x55, 0x95, 0x97, 0x57, 0x8E, 0x0D, 0xFC, 0x66, 0x94, + 0x18, 0x75, 0x9B, 0x22, 0x8C, 0x02, 0x4B, 0xBC, 0x40, 0x4D, 0xA2, 0x3A, 0xE0, 0x2D, 0x76, 0x63, + 0xFB, 0xFC, 0x90, 0x22, 0xB5, 0xA2, 0x75, 0xD2, 0x96, 0x53, 0xC4, 0x91, 0xF9, 0xA8, 0x3E, 0x79, + 0xD2, 0x82, 0x25, 0x2B, 0x9C, 0x8E, 0x30, 0xD6, 0x30, 0xE3, 0xE6, 0x8F, 0xF9, 0x08, 0xB2, 0x0D, + 0x54, 0xFA, 0xCA, 0x24, 0x3B, 0x2D, 0x17, 0xB1, 0xBB, 0xB1, 0x04, 0xDE, 0xC9, 0x20, 0x70, 0x56, + 0x2A, 0x0B, 0x6F, 0x3A, 0xA1, 0x9B, 0xD0, 0xC5, 0x71, 0xEF, 0x74, 0x9A, 0xCE, 0xE1, 0xD1, 0x9A, + 0x92, 0x39, 0xCC, 0x2C, 0x85, 0xCA, 0x55, 0x5D, 0x2F, 0x4B, 0xE0, 0x92, 0x42, 0xCA, 0x92, 0xF7, + 0x2B, 0xF1, 0x55, 0x21, 0xBE, 0x15, 0x2A, 0xD6, 0x12, 0x71, 0x8B, 0xA5, 0xEC, 0xBD, 0x34, 0x29, + 0x1B, 0xF1, 0xA8, 0xB4, 0xE0, 0xBC, 0x3C, 0xEC, 0xCE, 0x17, 0x98, 0x43, 0x0C, 0xEE, 0x8D, 0x28, + 0x7E, 0x9C, 0x10, 0x3B, 0x29, 0x40, 0x7B, 0xC1, 0x38, 0x7C, 0x59, 0x95, 0x2F, 0x8B, 0x93, 0x65, + 0x9B, 0x39, 0xD4, 0x48, 0xA3, 0x46, 0x22, 0x1F, 0x2C, 0x9D, 0x2B, 0xE2, 0x6B, 0xC2, 0x6B, 0xF4, + 0xB3, 0x70, 0x19, 0xD7, 0x0D, 0x42, 0xCB, 0x6D, 0xE6, 0x8D, 0xF0, 0xF4, 0xC1, 0xDC, 0x0E, 0x88, + 0x64, 0xA8, 0xE7, 0x51, 0x08, 0x0A, 0x60, 0xF2, 0xCB, 0xF4, 0xA9, 0xC8, 0x95, 0xAD, 0xF7, 0x96, + 0xE7, 0xE9, 0x16, 0x62, 0x6E, 0x98, 0x3C, 0xB8, 0xBA, 0x4D, 0x44, 0xF4, 0xB0, 0x32, 0x8B, 0x08, + 0xDD, 0x6B, 0xAC, 0x86, 0xB4, 0x43, 0x97, 0x92, 0xD0, 0x38, 0xDF, 0x98, 0xC7, 0x24, 0x46, 0xAE, + 0x6C, 0xCF, 0x4C, 0xD9, 0x9F, 0xE0, 0xF8, 0x10, 0xC1, 0x56, 0x14, 0x2E, 0x0E, 0xD2, 0x5F, 0xB8, + 0x34, 0x76, 0xCF, 0x07, 0x98, 0x8B, 0x5A, 0x9C, 0x59, 0x18, 0xCD, 0x25, 0xCF, 0x8D, 0x28, 0xBD, + 0x35, 0xF9, 0x3F, 0xC5, 0x7D, 0x9C, 0xD0, 0x57, 0xEA, 0x07, 0xA4, 0xC1, 0xFD, 0x25, 0x3A, 0x09, + 0x46, 0x08, 0x36, 0x97, 0xA3, 0x60, 0xD8, 0xFA, 0xD5, 0x59, 0x70, 0xE9, 0x84, 0x54, 0xBF, 0xB3, + 0xE0, 0x95, 0xEA, 0xEF, 0xA0, 0x55, 0x19, 0x8D, 0x67, 0xAF, 0x3E, 0x83, 0xCF, 0xE4, 0x33, 0x18, + 0x52, 0x50, 0x49, 0xBF, 0xC1, 0xD2, 0xDB, 0x13, 0xDF, 0xDC, 0xDA, 0xDD, 0x0C, 0x27, 0xA7, 0x52, + 0xBA, 0xAB, 0xE1, 0xE4, 0xFB, 0x35, 0x73, 0x37, 0xDC, 0x55, 0x5A, 0xCA, 0x7B, 0xA5, 0xF3, 0x7E, + 0xF7, 0xDD, 0x7B, 0xD6, 0x6C, 0x2B, 0x7B, 0xAD, 0xF6, 0xC1, 0x9E, 0xB2, 0xF7, 0x6E, 0xBF, 0xCD, + 0xDA, 0x7B, 0xFB, 0xF0, 0xDD, 0xC1, 0xFB, 0x7A, 0x7D, 0x0D, 0x57, 0x30, 0x5E, 0xE8, 0x68, 0xB8, + 0x82, 0xA1, 0x4A, 0x78, 0x19, 0x66, 0xCE, 0xA2, 0x92, 0x8D, 0x7A, 0xBE, 0x19, 0xBF, 0xBA, 0x18, + 0x66, 0xB8, 0x18, 0xCE, 0x0A, 0x91, 0xB5, 0xBB, 0x19, 0x86, 0x43, 0x2C, 0xC1, 0xD5, 0x70, 0xD9, + 0xB3, 0x8F, 0x8F, 0xB1, 0x1C, 0x97, 0xC3, 0x65, 0xAF, 0x20, 0x39, 0xCA, 0xC6, 0xBB, 0x1E, 0xC6, + 0x8F, 0xAE, 0x1F, 0xC6, 0x03, 0x71, 0x33, 0xEB, 0xB4, 0xF7, 0xB9, 0xFB, 0x80, 0x75, 0x5A, 0x13, + 0x75, 0xDA, 0xC5, 0xC3, 0x95, 0xD5, 0x69, 0x0F, 0xE7, 0xF0, 0x3C, 0x75, 0xDA, 0x3D, 0x1A, 0x1D, + 0x05, 0xEF, 0xC0, 0x21, 0xE4, 0x0E, 0xF3, 0x94, 0xBC, 0xF1, 0x66, 0x0A, 0xB6, 0x53, 0xD6, 0xB4, + 0x99, 0x72, 0xED, 0x5F, 0x28, 0x61, 0x89, 0xA8, 0xD7, 0x2E, 0xA4, 0x79, 0x1F, 0x2F, 0x4F, 0x54, + 0x0D, 0xD3, 0x7F, 0x48, 0x85, 0x38, 0xD9, 0x4F, 0x20, 0xB2, 0x82, 0x58, 0x89, 0x52, 0xF1, 0x2F, + 0xA7, 0x86, 0xBB, 0xD8, 0xD0, 0x79, 0xD3, 0x49, 0x7C, 0x28, 0x51, 0x5B, 0x26, 0x35, 0x43, 0x67, + 0xC9, 0x32, 0x6B, 0x49, 0x2E, 0x5F, 0xC8, 0x01, 0x4A, 0x95, 0x5A, 0x9B, 0x59, 0xB6, 0x92, 0x91, + 0xAC, 0xB3, 0x70, 0xB8, 0xA9, 0x64, 0x9E, 0x29, 0x1D, 0x17, 0x33, 0xAD, 0x38, 0x15, 0xB3, 0x36, + 0x66, 0xE8, 0xAC, 0xA1, 0xB6, 0x9A, 0x40, 0x81, 0xC2, 0xFA, 0x6A, 0x15, 0xFC, 0xAD, 0x93, 0x79, + 0x3B, 0x2B, 0xAF, 0xB4, 0xFE, 0x72, 0x58, 0xB5, 0xFB, 0xD1, 0xC4, 0xD7, 0x44, 0x15, 0x19, 0x3F, + 0xDB, 0x9E, 0x3F, 0x47, 0x29, 0x9F, 0x25, 0x94, 0x10, 0x0F, 0xFF, 0xE1, 0x8C, 0x0E, 0x17, 0xF5, + 0xE2, 0x38, 0xA8, 0x64, 0xE5, 0xAA, 0x6C, 0xE9, 0xCA, 0x80, 0x62, 0x85, 0xD1, 0x9C, 0xBC, 0x8E, + 0x16, 0xB5, 0x7D, 0x55, 0xF7, 0x19, 0x79, 0x66, 0x2C, 0xEC, 0xD9, 0xEE, 0x9A, 0x61, 0x21, 0xCE, + 0xE8, 0xB9, 0xB1, 0xB0, 0xF0, 0xCE, 0x23, 0x0B, 0x8E, 0x8B, 0xE3, 0xA1, 0xE8, 0xE8, 0x87, 0xC3, + 0x43, 0x2C, 0xD2, 0xBE, 0x5E, 0x78, 0x88, 0x33, 0xDA, 0x34, 0x6E, 0x28, 0xA1, 0xB8, 0x38, 0x16, + 0x8A, 0x8E, 0x7E, 0x48, 0x2C, 0xEC, 0xFD, 0x5C, 0x13, 0x1E, 0x66, 0x55, 0x51, 0x9F, 0x03, 0x0F, + 0x4B, 0x57, 0x4B, 0xCF, 0x41, 0xC5, 0x77, 0x95, 0xAE, 0x80, 0x6B, 0x41, 0x45, 0x02, 0x65, 0x3D, + 0xC8, 0x88, 0x5D, 0xFD, 0x40, 0xE8, 0x38, 0x29, 0x20, 0xBF, 0x64, 0xA6, 0x48, 0x03, 0x55, 0x38, + 0x9B, 0x61, 0x46, 0x9B, 0xC3, 0x14, 0x13, 0x50, 0x5C, 0x04, 0x0F, 0xE3, 0x1D, 0xFD, 0x90, 0x58, + 0xB8, 0x74, 0xA6, 0x38, 0x07, 0x1E, 0x6E, 0x14, 0x53, 0x9C, 0x02, 0x65, 0x3D, 0xC8, 0xF8, 0x3C, + 0x4C, 0x71, 0x81, 0x57, 0xCA, 0x98, 0x04, 0x36, 0xDE, 0xDE, 0xD3, 0x5E, 0x96, 0xBD, 0xA7, 0x5D, + 0xD5, 0xDE, 0xD3, 0xD9, 0x54, 0x7B, 0x4F, 0xFB, 0xA5, 0xDA, 0x7B, 0xDA, 0xAF, 0xF6, 0x9E, 0x1A, + 0xEC, 0x3D, 0xED, 0xBA, 0xEC, 0x3D, 0xED, 0x1F, 0xD3, 0xDE, 0xD3, 0x7E, 0xB5, 0xF7, 0xD4, 0x62, + 0xEF, 0x69, 0xD7, 0x65, 0xEF, 0x69, 0xFF, 0x98, 0xF6, 0x9E, 0xF6, 0xAB, 0xBD, 0xA7, 0x06, 0x7B, + 0x4F, 0xBB, 0x2E, 0x7B, 0x4F, 0xFB, 0x47, 0xB5, 0xF7, 0xB4, 0x5F, 0xED, 0x3D, 0x75, 0xD9, 0x7B, + 0xDA, 0xF5, 0xD9, 0x7B, 0xDA, 0x3F, 0xA6, 0xBD, 0xA7, 0xFD, 0x6A, 0xEF, 0xA9, 0xC1, 0xDE, 0xD3, + 0xAE, 0xCB, 0xDE, 0xD3, 0xFE, 0x51, 0xED, 0x3D, 0xED, 0x57, 0x7B, 0x4F, 0x5D, 0xF6, 0x9E, 0x76, + 0x7D, 0xF6, 0x9E, 0xF6, 0xAB, 0xBD, 0x67, 0xDD, 0xEC, 0x3D, 0x9D, 0x65, 0xD9, 0x7B, 0x3A, 0x55, + 0xED, 0x3D, 0xDD, 0x4D, 0xB5, 0xF7, 0x74, 0x5E, 0xAA, 0xBD, 0xA7, 0xF3, 0x6A, 0xEF, 0xA9, 0xC1, + 0xDE, 0xD3, 0xA9, 0xCB, 0xDE, 0xD3, 0xF9, 0x31, 0xED, 0x3D, 0x9D, 0x57, 0x7B, 0x4F, 0x2D, 0xF6, + 0x9E, 0x4E, 0x5D, 0xF6, 0x9E, 0xCE, 0x8F, 0x69, 0xEF, 0xE9, 0xBC, 0xDA, 0x7B, 0x6A, 0xB0, 0xF7, + 0x74, 0xEA, 0xB2, 0xF7, 0x74, 0x7E, 0x54, 0x7B, 0x4F, 0xE7, 0xD5, 0xDE, 0x53, 0x97, 0xBD, 0xA7, + 0x53, 0x9F, 0xBD, 0xA7, 0xF3, 0x63, 0xDA, 0x7B, 0x3A, 0xAF, 0xF6, 0x9E, 0x1A, 0xEC, 0x3D, 0x9D, + 0xBA, 0xEC, 0x3D, 0x9D, 0x1F, 0xD5, 0xDE, 0xD3, 0x79, 0xB5, 0xF7, 0xD4, 0x65, 0xEF, 0xE9, 0xD4, + 0x67, 0xEF, 0xE9, 0xBC, 0xDA, 0x7B, 0xD6, 0xCD, 0xDE, 0xD3, 0x5D, 0x96, 0xBD, 0xA7, 0x5B, 0xD5, + 0xDE, 0xB3, 0xBB, 0xA9, 0xF6, 0x9E, 0xEE, 0x4B, 0xB5, 0xF7, 0x74, 0x5F, 0xED, 0x3D, 0x35, 0xD8, + 0x7B, 0xBA, 0x75, 0xD9, 0x7B, 0xBA, 0x3F, 0xA6, 0xBD, 0xA7, 0xFB, 0x6A, 0xEF, 0xA9, 0xC5, 0xDE, + 0xD3, 0xAD, 0xCB, 0xDE, 0xD3, 0xFD, 0x31, 0xED, 0x3D, 0xDD, 0x57, 0x7B, 0x4F, 0x0D, 0xF6, 0x9E, + 0x6E, 0x5D, 0xF6, 0x9E, 0xEE, 0x8F, 0x6A, 0xEF, 0xE9, 0xBE, 0xDA, 0x7B, 0xEA, 0xB2, 0xF7, 0x74, + 0xEB, 0xB3, 0xF7, 0x74, 0x7F, 0x4C, 0x7B, 0x4F, 0xF7, 0xD5, 0xDE, 0x53, 0x83, 0xBD, 0xA7, 0x5B, + 0x97, 0xBD, 0xA7, 0xFB, 0xA3, 0xDA, 0x7B, 0xBA, 0xAF, 0xF6, 0x9E, 0xBA, 0xEC, 0x3D, 0xDD, 0xFA, + 0xEC, 0x3D, 0xDD, 0x17, 0x63, 0xEF, 0x29, 0xCA, 0x11, 0x94, 0xD3, 0xAB, 0xB4, 0x01, 0x45, 0x39, + 0xD1, 0x86, 0xDC, 0xBF, 0xE6, 0x9E, 0xA7, 0x0E, 0xF9, 0x95, 0xE1, 0xF9, 0x58, 0xB8, 0x92, 0x2A, + 0x04, 0xCC, 0x65, 0x22, 0xCA, 0x4F, 0x0B, 0x95, 0x48, 0xFA, 0x56, 0xCA, 0x3C, 0x14, 0x3E, 0xC7, + 0x14, 0xFB, 0xC2, 0xB8, 0x71, 0xED, 0x0D, 0x71, 0x8A, 0xF9, 0x23, 0xA5, 0x5A, 0x90, 0xA6, 0x2D, + 0x44, 0xD9, 0x7D, 0xE7, 0xEF, 0xDA, 0xED, 0xDD, 0xE9, 0x35, 0xBB, 0xA5, 0xE4, 0xB0, 0x1F, 0x0C, + 0x42, 0x37, 0x4C, 0x62, 0x05, 0x6D, 0x4F, 0xD1, 0x22, 0xD4, 0xA8, 0xC3, 0x64, 0x54, 0xC2, 0x5C, + 0x54, 0x3A, 0x53, 0x17, 0xCD, 0xD0, 0xF5, 0xB5, 0x31, 0x4E, 0xF9, 0xD2, 0x1A, 0xD8, 0xC5, 0xB5, + 0xE5, 0x64, 0xFE, 0x2E, 0x5A, 0x28, 0xA6, 0x8D, 0x77, 0x55, 0xCB, 0x1B, 0x1B, 0x7E, 0xAC, 0xE4, + 0x01, 0xAE, 0x98, 0xA9, 0x98, 0xA3, 0x5A, 0x17, 0xA9, 0xB4, 0x30, 0xD5, 0x6E, 0xFB, 0xF3, 0x9F, + 0x94, 0x0B, 0x7E, 0x2C, 0xB0, 0xC9, 0x63, 0x6D, 0x45, 0xD9, 0xDB, 0x86, 0x9F, 0xEF, 0x76, 0xF1, + 0xE7, 0x01, 0xFD, 0x7C, 0x8F, 0x3F, 0xDB, 0x9D, 0x5D, 0x91, 0x60, 0x5E, 0x69, 0x85, 0x8D, 0xDA, + 0x9D, 0xAE, 0x22, 0x33, 0xD5, 0xCB, 0x34, 0xBD, 0xA6, 0xFD, 0x48, 0x55, 0x19, 0xF0, 0x5B, 0xAA, + 0x73, 0xE1, 0x89, 0xAA, 0x28, 0xF0, 0x1C, 0xC6, 0xB7, 0x74, 0x4A, 0x7A, 0x8A, 0x49, 0xEF, 0x7C, + 0xD5, 0x30, 0x6D, 0x57, 0x56, 0x53, 0x90, 0x73, 0x85, 0xDE, 0x9F, 0x76, 0x54, 0xD3, 0x14, 0xBB, + 0x15, 0xCE, 0xA8, 0xC5, 0xAE, 0x0C, 0xF8, 0xD2, 0x3B, 0x64, 0x0A, 0xBE, 0xDC, 0x51, 0xE2, 0xD5, + 0x1A, 0x44, 0x0D, 0x16, 0x82, 0x1D, 0x8C, 0xE7, 0x53, 0xBD, 0x06, 0x1B, 0x38, 0x88, 0x6B, 0xE8, + 0x3A, 0xB7, 0xF0, 0x7D, 0x9C, 0x2B, 0x95, 0x6B, 0x31, 0x2C, 0x86, 0x88, 0xC2, 0xC6, 0xB6, 0xCE, + 0x37, 0x2B, 0x75, 0x58, 0xAA, 0x05, 0x71, 0x1E, 0x4A, 0xA8, 0xDF, 0x88, 0x48, 0x3D, 0x26, 0x9B, + 0xDE, 0xDB, 0x40, 0x05, 0xE3, 0xB0, 0x75, 0x21, 0xC7, 0x4D, 0x4D, 0x2E, 0x99, 0x9E, 0x48, 0x32, + 0x56, 0x18, 0xC5, 0xE5, 0x1E, 0xF7, 0xEF, 0x6C, 0x44, 0x14, 0x99, 0x17, 0x8E, 0xAA, 0xBA, 0xDE, + 0xE2, 0x63, 0xD8, 0xF5, 0x52, 0x67, 0x42, 0xD8, 0xB0, 0x5C, 0x1E, 0xC9, 0xB2, 0x75, 0x67, 0x9E, + 0x17, 0x18, 0x57, 0xF6, 0xE3, 0x49, 0x48, 0x66, 0x11, 0x40, 0x4A, 0x41, 0x03, 0x33, 0x53, 0x02, + 0x91, 0x46, 0xAD, 0x81, 0xEA, 0xAC, 0x6F, 0x95, 0x40, 0x53, 0x0C, 0x1B, 0xC4, 0xDB, 0x71, 0xF2, + 0xD8, 0x6A, 0x2C, 0x3B, 0x7D, 0x64, 0x89, 0xC7, 0x69, 0x83, 0x7C, 0xF8, 0x87, 0x66, 0x93, 0x35, + 0xC3, 0x7F, 0xA1, 0x38, 0xC6, 0xDD, 0x01, 0x26, 0x8E, 0x16, 0xF4, 0x16, 0xFB, 0xBA, 0xD9, 0x9C, + 0xEA, 0x31, 0x46, 0x68, 0x3A, 0xC8, 0xAA, 0x86, 0xCE, 0x86, 0xAA, 0x93, 0x5A, 0xD0, 0x39, 0xE3, + 0x7A, 0x27, 0xF3, 0x3E, 0x07, 0x61, 0xE8, 0x38, 0x61, 0xFA, 0xC0, 0x32, 0xC7, 0xF3, 0x4F, 0xD9, + 0x17, 0x3D, 0xD3, 0x47, 0x76, 0xAF, 0x17, 0x76, 0x5C, 0xE9, 0x34, 0x8E, 0x9A, 0xA5, 0x0E, 0x95, + 0xCC, 0xFA, 0x9D, 0xB1, 0xE1, 0x42, 0xDA, 0x4B, 0xC0, 0x37, 0x70, 0x45, 0x69, 0x12, 0x79, 0x60, + 0x3B, 0xB1, 0x37, 0x16, 0x3F, 0xB5, 0xD3, 0x31, 0x3B, 0x0D, 0x39, 0x0A, 0x39, 0x70, 0xB4, 0xFA, + 0x94, 0x51, 0xB2, 0x19, 0xEE, 0x5C, 0x72, 0xE0, 0x19, 0xA5, 0xD1, 0x64, 0x97, 0x67, 0x87, 0xA1, + 0xD4, 0x3C, 0x82, 0x0E, 0x1F, 0x61, 0xB1, 0x97, 0x67, 0x39, 0xE9, 0xD5, 0x77, 0x8E, 0x51, 0x50, + 0xCE, 0xCD, 0x8F, 0x7E, 0x86, 0x25, 0x8E, 0x40, 0xEA, 0x36, 0x4C, 0xF6, 0x8D, 0xC3, 0x9F, 0xB0, + 0xF5, 0x86, 0xCB, 0xA3, 0x61, 0x74, 0xF8, 0xFA, 0x96, 0x8F, 0x55, 0xC3, 0x32, 0xAC, 0x61, 0xCE, + 0x48, 0x36, 0xFB, 0x2B, 0xB4, 0xCE, 0x14, 0xCB, 0x9F, 0x35, 0xA5, 0x6B, 0x1C, 0xC5, 0x4E, 0xA3, + 0x9C, 0xA3, 0x5E, 0x94, 0xDE, 0x35, 0xFE, 0x7D, 0x2E, 0x53, 0x8A, 0x35, 0x66, 0xAB, 0xC8, 0x03, + 0x9B, 0x39, 0xF1, 0x15, 0xE6, 0x84, 0xBD, 0x6A, 0xE2, 0xC9, 0xC0, 0x76, 0xD8, 0x65, 0x2F, 0x49, + 0xAB, 0x5A, 0x0C, 0x18, 0x24, 0x67, 0xA9, 0x0F, 0x20, 0xDA, 0x51, 0x05, 0xAC, 0xD9, 0x94, 0xAD, + 0x1B, 0x97, 0xB1, 0x75, 0xC8, 0xED, 0xA1, 0xAB, 0x3A, 0x23, 0x43, 0xBB, 0xE5, 0x43, 0x58, 0xE3, + 0x99, 0x6B, 0x3B, 0x82, 0xAB, 0x14, 0x61, 0x24, 0x21, 0xDE, 0x74, 0xF3, 0xC6, 0xD1, 0xA7, 0xE8, + 0x09, 0x13, 0x8F, 0x8A, 0x15, 0xFC, 0x64, 0xB9, 0x82, 0x99, 0x2E, 0x53, 0xE7, 0x99, 0x54, 0xD9, + 0x75, 0x39, 0xEB, 0x30, 0xBB, 0x6C, 0xEE, 0x1E, 0x24, 0x93, 0xE2, 0x2B, 0x8D, 0xA3, 0xAF, 0xFD, + 0x72, 0x89, 0xEA, 0x67, 0x2B, 0x13, 0x9C, 0x7F, 0x9D, 0xAB, 0x25, 0x4C, 0xF1, 0x78, 0xBE, 0x96, + 0xC0, 0x29, 0xFE, 0x7A, 0x3B, 0x57, 0xCB, 0xDD, 0xC6, 0xD1, 0x7F, 0x57, 0x01, 0x57, 0x8A, 0x1B, + 0x17, 0xE7, 0xE1, 0xAF, 0x97, 0xFA, 0xFA, 0x62, 0xF7, 0x9F, 0xEC, 0xC0, 0x65, 0x93, 0x6D, 0x66, + 0x2E, 0xED, 0xB3, 0xD4, 0xBE, 0x40, 0xA1, 0x03, 0x06, 0x2C, 0xD2, 0x29, 0x4B, 0x4A, 0x1D, 0xB8, + 0xFC, 0x8F, 0x80, 0x5B, 0xDA, 0x13, 0xE9, 0x6C, 0x02, 0x2B, 0x54, 0x33, 0xC6, 0xBB, 0x40, 0xAA, + 0x70, 0x0C, 0x2D, 0x46, 0xA4, 0x5F, 0xFB, 0xEB, 0x44, 0x9E, 0x42, 0x36, 0x72, 0x17, 0xA0, 0x5D, + 0xC7, 0xE9, 0x73, 0x1F, 0x93, 0x51, 0x7B, 0x99, 0xE7, 0xF3, 0x62, 0x67, 0x4F, 0xE9, 0xF3, 0x47, + 0x0D, 0x7C, 0x1B, 0xCE, 0xC5, 0x5B, 0x6E, 0xF1, 0x47, 0xD5, 0x04, 0xEC, 0x86, 0xCF, 0x78, 0x50, + 0x32, 0xF9, 0xA4, 0x64, 0xA1, 0x97, 0x45, 0x4E, 0x92, 0xE9, 0x29, 0x94, 0xDF, 0xE8, 0xC5, 0x72, + 0xE5, 0x4B, 0x24, 0xFE, 0x19, 0x4F, 0x06, 0x12, 0x2C, 0x90, 0x17, 0x31, 0x58, 0x2B, 0xE8, 0x1A, + 0x9D, 0x03, 0x86, 0x72, 0x05, 0xAA, 0x1E, 0x24, 0x6E, 0x3C, 0x6D, 0x33, 0x9C, 0x26, 0x56, 0xA4, + 0xC3, 0x9A, 0x95, 0x80, 0xB9, 0xBE, 0xCF, 0xC7, 0x0E, 0x55, 0xCE, 0x02, 0x6C, 0xB3, 0x90, 0x0C, + 0xE0, 0xCF, 0x37, 0x9F, 0xED, 0x31, 0x7F, 0xC3, 0x2C, 0xEE, 0x3F, 0xDA, 0xEE, 0xB7, 0x6D, 0xD0, + 0x83, 0x40, 0x24, 0x52, 0xB1, 0xAB, 0x6D, 0xFC, 0xDA, 0xC5, 0x25, 0xD2, 0x58, 0x31, 0xDC, 0x16, + 0x47, 0xBC, 0x5E, 0xBA, 0xFE, 0x67, 0xCD, 0x89, 0xF5, 0x8B, 0x09, 0xA1, 0xBC, 0x23, 0x51, 0x25, + 0xF3, 0x77, 0xFC, 0x30, 0x8A, 0x0B, 0xD0, 0x42, 0x90, 0xEC, 0xB9, 0xF6, 0xC0, 0x30, 0xF9, 0x9D, + 0xFD, 0x8D, 0x97, 0xF0, 0x0D, 0x2B, 0xBC, 0x7B, 0x99, 0x2D, 0xD1, 0x26, 0xE5, 0x55, 0x39, 0x0E, + 0xA3, 0x81, 0x0E, 0xAB, 0x6D, 0xC1, 0xE2, 0xA5, 0x1A, 0x26, 0x25, 0x46, 0x89, 0x87, 0xDA, 0xEE, + 0x50, 0xB5, 0x8C, 0x3F, 0x85, 0x6E, 0x31, 0x52, 0x3D, 0x4C, 0x5A, 0x6F, 0xBB, 0x8E, 0x4D, 0xE6, + 0x23, 0xE0, 0xA6, 0xD6, 0xB0, 0xEF, 0xBB, 0x5C, 0x1D, 0x13, 0xDF, 0x4C, 0x88, 0x3A, 0xAA, 0xA6, + 0xA1, 0x61, 0x7A, 0x5B, 0x24, 0xC8, 0x37, 0x48, 0xDE, 0x71, 0x39, 0xF6, 0xCA, 0x90, 0x30, 0xA9, + 0x77, 0x2D, 0xF0, 0x00, 0x83, 0x65, 0xBE, 0x7B, 0xE6, 0xC8, 0x85, 0xFB, 0xB8, 0xF0, 0x38, 0x3A, + 0x02, 0x56, 0x3F, 0xB1, 0x26, 0x13, 0xD9, 0xF6, 0x39, 0xEB, 0x3B, 0xAA, 0xFB, 0xED, 0x22, 0xB0, + 0x04, 0x84, 0x1A, 0x73, 0x54, 0xB4, 0xA8, 0xB3, 0x04, 0x44, 0x39, 0x8C, 0x2E, 0xC3, 0xB1, 0xB2, + 0x6E, 0xC6, 0xDE, 0x95, 0x21, 0xC4, 0x0A, 0xD7, 0x10, 0x05, 0xA8, 0x5D, 0xBA, 0x0E, 0x79, 0x7E, + 0x3F, 0x35, 0x14, 0x26, 0xAF, 0x8D, 0x01, 0xD4, 0x7B, 0x40, 0x91, 0xAC, 0xE0, 0xF9, 0x70, 0x40, + 0x7C, 0x75, 0x80, 0xD8, 0x38, 0x1A, 0x8E, 0xE8, 0x09, 0x9D, 0x52, 0xE2, 0xD9, 0x0A, 0x0E, 0xA9, + 0xD9, 0x69, 0x3C, 0xC7, 0x31, 0x25, 0xEB, 0x2C, 0x8B, 0x12, 0x2E, 0x09, 0x06, 0x40, 0x07, 0xD8, + 0xA3, 0x61, 0x9A, 0x68, 0xEA, 0x96, 0x93, 0xE5, 0x3A, 0x31, 0x8A, 0x80, 0x26, 0xAC, 0xA3, 0x7D, + 0x1D, 0x9B, 0x59, 0x80, 0xAF, 0xCC, 0x76, 0xB0, 0xE6, 0x70, 0x60, 0x19, 0xFE, 0x53, 0x75, 0x5D, + 0x68, 0xBD, 0xCF, 0x22, 0xDC, 0xAD, 0xC0, 0xE3, 0xC7, 0x9E, 0x67, 0x78, 0xFE, 0x8D, 0xFD, 0x78, + 0x1A, 0x6E, 0x68, 0xC5, 0xCA, 0xDC, 0xA5, 0xD1, 0xB8, 0x34, 0x2A, 0xC7, 0x67, 0x05, 0x92, 0x56, + 0xF8, 0x67, 0x85, 0x3A, 0x95, 0x8B, 0x60, 0x70, 0x72, 0xF4, 0x67, 0x3A, 0xE9, 0x08, 0x8B, 0xA3, + 0x72, 0xDA, 0x13, 0x10, 0x5C, 0x7F, 0x3A, 0x16, 0x15, 0x56, 0x66, 0x51, 0x18, 0xE4, 0x26, 0x63, + 0x0C, 0xA7, 0xD5, 0x83, 0xAC, 0x8C, 0xAD, 0x6A, 0x7F, 0x04, 0x86, 0x67, 0xD0, 0x19, 0xE9, 0x00, + 0xF6, 0x63, 0x9D, 0x60, 0x4B, 0xE3, 0xF3, 0xA1, 0xF1, 0x1A, 0x1C, 0x56, 0x8B, 0x33, 0x5F, 0xB9, + 0xBB, 0x58, 0xFC, 0xCE, 0x34, 0xFE, 0xE4, 0x3A, 0xAC, 0xDF, 0x77, 0x8D, 0xFB, 0x80, 0x6A, 0x03, + 0xAE, 0x13, 0xF6, 0xA7, 0xCE, 0x50, 0x54, 0xED, 0xA3, 0xC7, 0x2C, 0xFE, 0xBC, 0xC6, 0xF2, 0xAE, + 0x0B, 0x92, 0x4D, 0xC6, 0xB4, 0xD7, 0x82, 0x84, 0xCC, 0x08, 0x76, 0x71, 0x6B, 0x17, 0xDE, 0x71, + 0x92, 0xCC, 0x67, 0xCA, 0x82, 0x88, 0x11, 0x5D, 0x51, 0xB1, 0x52, 0xC3, 0x02, 0xCA, 0x52, 0xA3, + 0x2A, 0xDF, 0x28, 0xAF, 0x80, 0xBC, 0x60, 0xF9, 0xA0, 0xEE, 0xC5, 0x7A, 0xD9, 0x6C, 0x8A, 0x2A, + 0x77, 0xE5, 0x63, 0xA6, 0x6D, 0xED, 0x1D, 0x48, 0x55, 0x57, 0xFC, 0x81, 0x9B, 0x25, 0x4C, 0x6A, + 0x69, 0xDA, 0x4C, 0x7E, 0xA7, 0x59, 0xF8, 0xCE, 0xF0, 0x0D, 0x46, 0xAF, 0x94, 0xF7, 0xAC, 0x49, + 0x1A, 0xE0, 0x0A, 0x06, 0x2E, 0xB1, 0xE2, 0x72, 0x98, 0x38, 0xAF, 0x01, 0x2F, 0xDB, 0x90, 0xD7, + 0x56, 0x14, 0x85, 0x7D, 0xC7, 0x1B, 0x7E, 0xE5, 0xDB, 0x98, 0x74, 0x0E, 0x8F, 0x57, 0xAC, 0x41, + 0x39, 0x63, 0xE2, 0xDB, 0xA3, 0x2E, 0xF7, 0xEA, 0xEA, 0x11, 0x16, 0xD7, 0xD9, 0xC3, 0x1E, 0xE1, + 0x67, 0x3D, 0x3D, 0x76, 0xA7, 0xD7, 0xFD, 0x19, 0x98, 0x01, 0x10, 0x9D, 0x05, 0xA7, 0xDB, 0xD3, + 0x42, 0x3D, 0xEF, 0x26, 0x57, 0x5F, 0x5B, 0xBF, 0x7B, 0x49, 0x18, 0xCC, 0xD7, 0x6F, 0x85, 0x6A, + 0xA1, 0x4B, 0x61, 0xA0, 0xD2, 0x6A, 0x89, 0x9C, 0x6F, 0xC2, 0x3D, 0xF5, 0x38, 0x25, 0xFA, 0x48, + 0x89, 0x26, 0xD2, 0x43, 0x2B, 0xB1, 0x46, 0x54, 0xAC, 0xB1, 0x5E, 0xE2, 0x18, 0x86, 0xD6, 0xB9, + 0xDE, 0x92, 0x48, 0xC0, 0xC6, 0xEA, 0x13, 0xF2, 0x56, 0x9D, 0x3B, 0xF0, 0x2D, 0xCA, 0xDA, 0x31, + 0xD6, 0x99, 0x05, 0xAF, 0x4D, 0x60, 0xA5, 0xB9, 0x86, 0xCE, 0x8A, 0x12, 0xCC, 0x2A, 0x2E, 0xC2, + 0x5D, 0xDF, 0x7B, 0xFE, 0x0B, 0x70, 0x9C, 0xC5, 0xB2, 0xEE, 0xC0, 0xE3, 0x7D, 0x57, 0xBB, 0x06, + 0x8F, 0xB5, 0xCC, 0xBA, 0xE5, 0x9E, 0x40, 0x6F, 0xE6, 0x7A, 0x1B, 0x1B, 0xAF, 0xD5, 0xBD, 0x76, + 0xEE, 0x72, 0xE6, 0xBB, 0xDA, 0x4E, 0x31, 0x62, 0xC2, 0x06, 0xE7, 0x57, 0x3C, 0x44, 0x04, 0xBC, + 0xB0, 0xC3, 0x1A, 0x92, 0xC2, 0x9F, 0x0C, 0xC8, 0x15, 0xA8, 0x92, 0xBB, 0x78, 0xA5, 0x71, 0x76, + 0x7C, 0x77, 0xCC, 0x10, 0x7C, 0xDB, 0xCC, 0x1B, 0x81, 0x9A, 0x33, 0x08, 0x40, 0x0A, 0x93, 0x2C, + 0x15, 0xDD, 0x81, 0xA6, 0x71, 0x33, 0x55, 0x46, 0x09, 0x7B, 0xC3, 0x45, 0x7F, 0x71, 0x8A, 0xEE, + 0x57, 0x13, 0x4D, 0xC9, 0xCF, 0x0D, 0xDB, 0x9D, 0x8E, 0x54, 0xCB, 0x8A, 0x09, 0x34, 0xE1, 0x62, + 0x4B, 0x1E, 0xDA, 0x71, 0xE9, 0x26, 0xEA, 0xF3, 0x44, 0x0D, 0x40, 0x20, 0xBC, 0xC5, 0x8F, 0x84, + 0x3D, 0x0C, 0x1F, 0x90, 0x27, 0xE3, 0x21, 0x9B, 0x53, 0x80, 0x49, 0xF6, 0x9D, 0x5C, 0x82, 0x78, + 0x94, 0x26, 0x7A, 0xCC, 0x27, 0x75, 0xEC, 0x1E, 0x28, 0x20, 0x78, 0xE0, 0xCF, 0x85, 0x8E, 0xC4, + 0xF7, 0xFB, 0xD8, 0x0D, 0xFE, 0x5C, 0x4C, 0x5E, 0x79, 0xDF, 0xC1, 0x7E, 0xE8, 0xD7, 0x62, 0x42, + 0xC5, 0xC1, 0x2E, 0x76, 0x44, 0xBF, 0x16, 0x3B, 0xEB, 0xDF, 0xD1, 0xCA, 0xE8, 0xD7, 0x62, 0x4B, + 0x6B, 0xEF, 0x89, 0xB5, 0xD1, 0xEF, 0xC5, 0x64, 0xB0, 0xAE, 0x42, 0xAB, 0x13, 0xBF, 0x17, 0x13, + 0x91, 0xF6, 0x15, 0x81, 0x00, 0xF4, 0x7B, 0x31, 0x14, 0xE8, 0xB4, 0x05, 0x12, 0xD0, 0xEF, 0xCD, + 0x11, 0x84, 0xEE, 0xC8, 0xF3, 0x16, 0x68, 0x96, 0xEE, 0x17, 0x50, 0x67, 0x44, 0x99, 0xE8, 0xF6, + 0xF8, 0xEC, 0xF2, 0x0B, 0x31, 0xAD, 0xD0, 0x73, 0x56, 0x03, 0xE6, 0x31, 0x14, 0x96, 0x98, 0xB1, + 0xEA, 0x6B, 0xC0, 0xE2, 0x50, 0x8D, 0x74, 0xB1, 0xCE, 0xEE, 0xC8, 0x46, 0xBE, 0x07, 0x7A, 0x24, + 0x91, 0x69, 0x4C, 0xEC, 0x21, 0xB4, 0xB9, 0x77, 0xBC, 0x97, 0x26, 0xE6, 0x94, 0xE3, 0xBB, 0xB8, + 0x3D, 0x35, 0xB3, 0xDD, 0xA9, 0x2E, 0x1B, 0x47, 0xD7, 0xC1, 0x77, 0x26, 0x3F, 0xCC, 0xCD, 0x6F, + 0xA7, 0x3B, 0x4D, 0x9B, 0x7C, 0x9D, 0x3C, 0x17, 0x88, 0xE4, 0xE6, 0xFA, 0xFC, 0x78, 0x51, 0xCD, + 0xAE, 0xD7, 0xEB, 0xEF, 0x9C, 0x3F, 0xA0, 0x63, 0xF5, 0x1D, 0x60, 0xFD, 0x10, 0x4B, 0x5E, 0x2F, + 0xA4, 0xD8, 0x09, 0xEF, 0xCF, 0xE0, 0xBB, 0x5C, 0x31, 0x6C, 0xCD, 0x65, 0xE7, 0x74, 0x51, 0xD5, + 0xEE, 0xF8, 0xEC, 0x74, 0xE7, 0xEC, 0xF8, 0x74, 0xB3, 0xD8, 0x41, 0x24, 0xB0, 0x44, 0xB4, 0x2F, + 0x05, 0x42, 0xE9, 0x38, 0xAF, 0x1B, 0x83, 0x01, 0x77, 0x11, 0xF2, 0xAA, 0xE3, 0x98, 0x86, 0x30, + 0x2E, 0x79, 0x2D, 0x86, 0xBB, 0x8A, 0xDA, 0x11, 0x99, 0x97, 0xF0, 0x45, 0xE0, 0x0F, 0x06, 0x08, + 0x40, 0x77, 0xBF, 0xEC, 0xDC, 0xFE, 0x82, 0xFC, 0x21, 0x32, 0x44, 0x21, 0x5D, 0xBB, 0x63, 0xFA, + 0xBB, 0xC5, 0x70, 0x23, 0xE5, 0x16, 0x26, 0x5A, 0x3B, 0x01, 0x08, 0xB3, 0x68, 0xDD, 0x85, 0x7E, + 0x60, 0x06, 0x3A, 0xB3, 0x03, 0x1F, 0x4D, 0x78, 0x78, 0x9D, 0xB1, 0x67, 0x79, 0x78, 0xDD, 0x19, + 0x10, 0xD3, 0xF2, 0xC3, 0xC6, 0x68, 0xC9, 0x83, 0x79, 0xC0, 0xBE, 0x45, 0x1D, 0xE1, 0xFD, 0xA9, + 0xC5, 0x54, 0x5D, 0x27, 0x5B, 0x31, 0x4C, 0xA6, 0x7F, 0x76, 0xBC, 0xD3, 0x3F, 0xBD, 0x12, 0x86, + 0x66, 0x4D, 0xEC, 0x75, 0x8B, 0xFD, 0x3C, 0xE2, 0xDC, 0xDC, 0x39, 0x33, 0x5C, 0x76, 0x67, 0x68, + 0xDF, 0x12, 0xD3, 0xA0, 0x2B, 0x7F, 0xDB, 0x37, 0x1E, 0x38, 0x0C, 0x00, 0x42, 0xD8, 0x40, 0xD5, + 0x0C, 0x6B, 0xD8, 0x62, 0x72, 0x6B, 0x13, 0xEF, 0xCA, 0xDB, 0xD5, 0x81, 0xE1, 0x8E, 0xD1, 0xE9, + 0x71, 0x0A, 0x3E, 0x11, 0x5F, 0x44, 0x40, 0xBD, 0x38, 0x2B, 0x5A, 0xC8, 0x31, 0x50, 0x44, 0xAB, + 0x93, 0xD7, 0x09, 0x09, 0xF3, 0x0C, 0xB7, 0xAB, 0x26, 0x01, 0x33, 0xD1, 0xF3, 0xCC, 0xDC, 0x5F, + 0xC5, 0xCB, 0x57, 0xF1, 0xF2, 0x55, 0xBC, 0xAC, 0xCD, 0xAB, 0xC5, 0x12, 0xC7, 0x02, 0x46, 0x35, + 0x6D, 0xCB, 0x30, 0xAF, 0x69, 0x61, 0x73, 0xF6, 0xBC, 0xC9, 0x94, 0x35, 0x63, 0x0C, 0x35, 0xC6, + 0x4F, 0x05, 0x7C, 0x37, 0x44, 0xD0, 0xAC, 0xC4, 0x54, 0x23, 0xB5, 0x1F, 0xCF, 0xC2, 0xD0, 0xE8, + 0x33, 0x65, 0x15, 0x29, 0x6B, 0x74, 0x5F, 0xEC, 0x7A, 0xAF, 0xF4, 0x15, 0x9F, 0xB8, 0x95, 0x3A, + 0x8F, 0x4F, 0x3C, 0x72, 0x61, 0x0F, 0x9F, 0x96, 0x0F, 0x33, 0xC6, 0xE6, 0xD5, 0x42, 0x8C, 0x17, + 0xF7, 0x67, 0x9F, 0x9A, 0x7B, 0x75, 0x94, 0x5A, 0x9C, 0x7A, 0x62, 0x14, 0xF4, 0x89, 0x5B, 0x9C, + 0xC8, 0x45, 0x15, 0xD0, 0xC0, 0x28, 0x1F, 0xD6, 0x97, 0x12, 0x11, 0x88, 0x27, 0xF0, 0xDE, 0x58, + 0x06, 0x4F, 0x8E, 0x03, 0xA0, 0x95, 0x01, 0x65, 0x6C, 0xD8, 0x16, 0x76, 0x28, 0xC0, 0x1F, 0x8C, + 0x3E, 0x94, 0xB2, 0x92, 0xF6, 0xD4, 0x62, 0xE8, 0x38, 0x63, 0xB8, 0xDC, 0x13, 0xF7, 0xE8, 0x2E, + 0xD7, 0xB8, 0x33, 0x45, 0x4D, 0xD2, 0x17, 0x51, 0x74, 0xD0, 0x56, 0x94, 0x6D, 0x45, 0x51, 0x02, + 0x4F, 0x8A, 0x63, 0x26, 0xB7, 0x86, 0x64, 0xDF, 0xD2, 0xD9, 0xFB, 0xE8, 0x2B, 0x31, 0x03, 0xEE, + 0x3F, 0x72, 0x6E, 0x89, 0xF7, 0xBC, 0x56, 0x95, 0x00, 0xEB, 0x65, 0x91, 0x63, 0x25, 0xDD, 0xAF, + 0x4A, 0xA4, 0x7F, 0x06, 0x69, 0x9E, 0x71, 0x0C, 0x1B, 0xF5, 0xE6, 0xA6, 0xD0, 0x85, 0x5C, 0x29, + 0xB3, 0xE4, 0xA8, 0xC4, 0x3C, 0xEF, 0x60, 0xA7, 0x4E, 0xC4, 0x46, 0x09, 0xEC, 0x2E, 0xDD, 0xE5, + 0x9C, 0x1E, 0x96, 0x77, 0xB3, 0xA8, 0xC1, 0xB6, 0xFE, 0xDF, 0xFF, 0xF5, 0xDE, 0x1E, 0x96, 0x5F, + 0x4C, 0x15, 0xF2, 0x5F, 0xD8, 0xAD, 0x2F, 0xD3, 0xC5, 0x2F, 0x2F, 0x23, 0x55, 0xA5, 0x5E, 0xF1, + 0xDF, 0x0C, 0x02, 0xCD, 0x6C, 0x4C, 0xC5, 0x99, 0x3A, 0xC5, 0x5D, 0xD6, 0x91, 0xA7, 0xA0, 0xC4, + 0x5D, 0xCF, 0x3C, 0x44, 0xB5, 0x7C, 0xC4, 0xBF, 0x22, 0xBE, 0xB5, 0x74, 0x74, 0xEF, 0xC5, 0x98, + 0x64, 0xA5, 0xB1, 0x04, 0x4D, 0x6C, 0x00, 0xAA, 0xCF, 0xE2, 0x99, 0x04, 0xED, 0xE2, 0x08, 0x2B, + 0x3A, 0xDA, 0x04, 0x34, 0xA5, 0x0B, 0x31, 0xA2, 0x29, 0x7D, 0xC8, 0xE7, 0x55, 0x76, 0x0B, 0x71, + 0xB6, 0x67, 0x9B, 0xAA, 0x8B, 0xB7, 0xC4, 0xAB, 0xC1, 0xDA, 0x70, 0xB8, 0xC3, 0x39, 0x38, 0x6E, + 0x42, 0xBF, 0x4E, 0x5F, 0xC4, 0xEC, 0x7E, 0x2F, 0xB4, 0xBE, 0x79, 0xB4, 0xF3, 0x6C, 0x83, 0xE4, + 0xAD, 0xE1, 0x19, 0xD6, 0x90, 0xE1, 0x76, 0x56, 0x53, 0xD3, 0xB2, 0xED, 0x93, 0x17, 0xAA, 0x69, + 0xCE, 0xDF, 0x67, 0x79, 0xBD, 0x6D, 0x89, 0x12, 0xE8, 0x94, 0x5D, 0x50, 0x48, 0x80, 0x9E, 0x31, + 0x44, 0x3B, 0x5A, 0xE8, 0x4B, 0x36, 0x42, 0x77, 0x06, 0x11, 0x58, 0xA9, 0x91, 0x91, 0x6C, 0xCB, + 0x15, 0xB0, 0xE4, 0xB0, 0xEE, 0xB7, 0x28, 0xA1, 0x62, 0x28, 0x4D, 0xE2, 0x85, 0x81, 0x84, 0x0C, + 0xBD, 0x11, 0x13, 0x3C, 0x63, 0x9B, 0x50, 0x75, 0x43, 0x97, 0x29, 0x41, 0x56, 0x91, 0x22, 0x2B, + 0x30, 0x9E, 0xB9, 0x53, 0x4B, 0xAD, 0x42, 0x6D, 0xFB, 0x2C, 0xC3, 0xB6, 0xC9, 0xC0, 0x7E, 0x65, + 0x0F, 0x87, 0x18, 0x56, 0x2D, 0xB5, 0xB8, 0xD2, 0x40, 0xAB, 0xAC, 0xED, 0x09, 0x73, 0xBE, 0x1C, + 0x6E, 0x25, 0x5A, 0x5F, 0xE9, 0xA9, 0xCD, 0x6A, 0x87, 0xE9, 0x20, 0x7A, 0x66, 0x65, 0x11, 0xE6, + 0x31, 0x71, 0x3C, 0x08, 0xC5, 0x6D, 0x8E, 0x33, 0xF4, 0xDE, 0x0A, 0x85, 0xAE, 0xAB, 0x44, 0xA6, + 0x73, 0xED, 0x89, 0xDD, 0x5E, 0xF7, 0x5B, 0x18, 0xE5, 0x33, 0x08, 0x4C, 0x69, 0x8E, 0xC1, 0x78, + 0x44, 0x66, 0x1A, 0xDF, 0x40, 0x67, 0x0C, 0xF0, 0x52, 0xDF, 0x77, 0x0D, 0xD5, 0x1A, 0x06, 0xA6, + 0xB4, 0xB9, 0xF4, 0xB9, 0x88, 0x08, 0x42, 0xE1, 0x12, 0xE8, 0xE9, 0x1B, 0xDA, 0xE6, 0x89, 0xF1, + 0x49, 0x37, 0xD2, 0xDF, 0xCE, 0xCF, 0x9A, 0x17, 0xEF, 0x7B, 0xEC, 0xD2, 0xF2, 0xF9, 0x50, 0x7A, + 0x90, 0x5C, 0xAB, 0x56, 0xA0, 0x8A, 0xFE, 0xC7, 0xB6, 0xCB, 0x93, 0xD6, 0xFF, 0x62, 0x7D, 0xB4, + 0xA2, 0xDF, 0xE9, 0xE6, 0x6B, 0x94, 0x71, 0x8C, 0xAA, 0x4D, 0xA5, 0xA4, 0x01, 0xB0, 0xE3, 0x65, + 0x89, 0x2C, 0x34, 0xEB, 0x95, 0x89, 0x2C, 0x82, 0x55, 0xD4, 0x2E, 0xB2, 0x24, 0x17, 0x31, 0xBB, + 0x2B, 0x6B, 0x24, 0xB2, 0x60, 0x36, 0x1C, 0xDF, 0x26, 0x77, 0xC2, 0xBA, 0x44, 0x16, 0x72, 0x4D, + 0x14, 0x89, 0x76, 0x5E, 0x86, 0xC4, 0x12, 0xB1, 0x42, 0xC2, 0xFC, 0x48, 0x66, 0x31, 0x81, 0xB6, + 0xB8, 0xCE, 0xD0, 0xC9, 0x73, 0x14, 0xE6, 0x22, 0x33, 0xA6, 0xB8, 0x4E, 0x0C, 0xBC, 0xAF, 0xC2, + 0x48, 0x75, 0xC3, 0x75, 0x00, 0xBA, 0x51, 0x78, 0x5C, 0x62, 0x4C, 0x3F, 0x79, 0x88, 0xAD, 0xA1, + 0x91, 0x3A, 0x36, 0xB7, 0x29, 0x1B, 0x35, 0xA3, 0xC7, 0xA5, 0x37, 0x25, 0x96, 0xF8, 0xE4, 0x19, + 0xEC, 0xD5, 0x55, 0x40, 0x5C, 0x8D, 0xF4, 0x32, 0xC6, 0x29, 0x97, 0xF4, 0x2F, 0x85, 0x2C, 0x25, + 0x94, 0x23, 0xCA, 0x24, 0x9F, 0xA1, 0x78, 0xC4, 0xC9, 0x21, 0xA5, 0xD7, 0xDB, 0xF9, 0x7A, 0xF2, + 0xCB, 0x4E, 0xBF, 0x77, 0x7C, 0x7B, 0x77, 0x83, 0x74, 0x1A, 0x8A, 0x15, 0x5F, 0xE1, 0x41, 0x27, + 0x46, 0xA5, 0x17, 0x6A, 0x35, 0x5B, 0xD9, 0xC6, 0x0A, 0x06, 0x11, 0xE0, 0x05, 0x4C, 0xFA, 0x76, + 0xE0, 0x6A, 0x29, 0xC7, 0x78, 0x65, 0x32, 0x09, 0x8F, 0xF0, 0xD4, 0xFE, 0x81, 0x26, 0xC2, 0x6D, + 0x92, 0x5B, 0x21, 0x9E, 0x57, 0x3C, 0x6E, 0x67, 0x8E, 0xDA, 0xD4, 0xC1, 0xEE, 0x00, 0xD1, 0x1B, + 0xB9, 0xCB, 0xAD, 0x9C, 0xFE, 0x76, 0xDE, 0x03, 0x77, 0xF6, 0x64, 0x14, 0x49, 0x4B, 0xE6, 0x38, + 0x14, 0x67, 0x8E, 0xED, 0xCB, 0x5E, 0xC5, 0x7B, 0xE0, 0x4A, 0xC7, 0xEA, 0xF2, 0x34, 0x0B, 0x8A, + 0x38, 0x93, 0x58, 0x10, 0x8F, 0x32, 0x43, 0x37, 0x17, 0x0C, 0xCC, 0x34, 0x74, 0x71, 0xA2, 0x12, + 0x85, 0xCA, 0x14, 0x04, 0xF1, 0xB4, 0x2F, 0x1E, 0x6D, 0x61, 0x8B, 0x3C, 0xA5, 0x6F, 0xCE, 0xBF, + 0x34, 0xCF, 0xDE, 0x9F, 0x1E, 0x32, 0x89, 0x18, 0x02, 0xBA, 0x31, 0xB2, 0xBE, 0xEC, 0x6D, 0xEA, + 0xFD, 0xD1, 0x02, 0xAF, 0x14, 0x86, 0x79, 0xA2, 0xA3, 0xF9, 0xB1, 0xF9, 0x88, 0x29, 0x49, 0xC8, + 0x91, 0x5C, 0xB2, 0x52, 0x52, 0x9C, 0xA4, 0x6F, 0x14, 0xE6, 0x16, 0x65, 0x5F, 0xFB, 0x27, 0xC5, + 0x4E, 0xE5, 0xCB, 0x0B, 0xD6, 0x17, 0x87, 0xC5, 0x27, 0xCB, 0xF3, 0xEE, 0xEC, 0xAF, 0xDE, 0x7D, + 0x9F, 0x9C, 0xC0, 0xA2, 0xE3, 0x75, 0x7A, 0xB6, 0x85, 0x80, 0x85, 0xD5, 0x2C, 0x3F, 0xB2, 0x3F, + 0x63, 0xCE, 0x2B, 0x0E, 0xEF, 0xFF, 0x22, 0xC0, 0x42, 0x20, 0x92, 0xBE, 0x73, 0xE4, 0xA6, 0xB6, + 0x65, 0xF0, 0x6D, 0xE1, 0x46, 0x41, 0xB9, 0x92, 0xE0, 0x78, 0x7C, 0x2B, 0x76, 0x1A, 0x09, 0x0B, + 0x77, 0x9B, 0x9C, 0x27, 0x62, 0x01, 0x9D, 0x9E, 0xAF, 0xFA, 0x81, 0x17, 0x4B, 0x51, 0x5B, 0xF9, + 0xC0, 0x7C, 0xCE, 0xD0, 0xFE, 0x0A, 0x5F, 0x65, 0x07, 0x09, 0x65, 0x51, 0xD5, 0x54, 0xBC, 0xD0, + 0xCF, 0xC6, 0x85, 0x91, 0x1F, 0x2E, 0x54, 0x32, 0x54, 0xA8, 0x6A, 0x98, 0xD0, 0x5C, 0x51, 0x41, + 0xE9, 0x11, 0x41, 0xB8, 0x86, 0xB9, 0x02, 0x82, 0x62, 0x0D, 0x67, 0x41, 0x1B, 0x83, 0xCC, 0x54, + 0x28, 0xD0, 0xA3, 0x31, 0x30, 0x16, 0x8B, 0x04, 0x9A, 0x8D, 0x02, 0x9A, 0xDE, 0xB5, 0xC2, 0xE8, + 0x9F, 0xCC, 0xB9, 0x57, 0x0B, 0xFC, 0xC9, 0x0F, 0xFA, 0x49, 0xC3, 0xC4, 0x1B, 0x91, 0xD7, 0xC9, + 0x4B, 0xBF, 0xC0, 0xAE, 0x81, 0x29, 0x44, 0x82, 0x32, 0x88, 0x5E, 0x4C, 0x73, 0xB9, 0x0E, 0x8D, + 0x80, 0x15, 0x88, 0x80, 0x6E, 0x98, 0x1B, 0x68, 0xA5, 0xBB, 0x62, 0x77, 0x64, 0x8A, 0x29, 0xA0, + 0xEF, 0x63, 0x50, 0x6C, 0xC3, 0x4F, 0x91, 0x9A, 0xEB, 0xBB, 0x86, 0xCC, 0xFE, 0x41, 0x7E, 0x57, + 0x98, 0x2E, 0x45, 0xBE, 0x33, 0x49, 0x82, 0x98, 0x88, 0x09, 0x6F, 0x95, 0x4D, 0xD9, 0xB8, 0x28, + 0x43, 0xC8, 0xFA, 0x2E, 0xEB, 0x08, 0xAC, 0x7C, 0x37, 0x1C, 0x97, 0x6E, 0x11, 0x5D, 0xE5, 0xA6, + 0xFD, 0xAE, 0xF4, 0xFB, 0x98, 0x89, 0x34, 0x76, 0x63, 0xDA, 0x9D, 0x31, 0x2D, 0xE1, 0x2B, 0xAC, + 0x9D, 0x7F, 0x17, 0x3B, 0xD7, 0xBD, 0x6B, 0x95, 0x8C, 0x41, 0x29, 0x93, 0x96, 0x07, 0x96, 0x0F, + 0xFB, 0x98, 0x37, 0x88, 0x93, 0xDE, 0x7E, 0x9E, 0x6B, 0xD5, 0x7C, 0xA6, 0xBB, 0xC4, 0x5D, 0xEA, + 0x41, 0x1F, 0xF0, 0x97, 0x5E, 0xB0, 0x53, 0xBD, 0x9F, 0x33, 0xC1, 0xB0, 0x56, 0xFB, 0x17, 0x2D, + 0xA7, 0xDA, 0xB6, 0x85, 0xCD, 0x36, 0x69, 0xEB, 0xDA, 0x65, 0x09, 0xAC, 0xB3, 0x46, 0x1B, 0x24, + 0x26, 0x5D, 0x69, 0x73, 0xDA, 0x9B, 0x46, 0x53, 0xED, 0xC5, 0x69, 0x6A, 0xAD, 0xB6, 0x6C, 0x3E, + 0x9A, 0x6A, 0x6F, 0x22, 0x4D, 0x75, 0xCA, 0xD2, 0x54, 0x77, 0x8D, 0x36, 0xA8, 0x53, 0x9D, 0xA6, + 0x3A, 0x9B, 0x46, 0x53, 0x9D, 0xC5, 0x69, 0x6A, 0xAD, 0xB6, 0x6C, 0x3E, 0x9A, 0xEA, 0x6C, 0x22, + 0x4D, 0x75, 0xCB, 0xD2, 0xD4, 0xEE, 0x1A, 0x6D, 0x50, 0xB7, 0x3A, 0x4D, 0x75, 0x37, 0x8D, 0xA6, + 0xBA, 0x8B, 0xD3, 0xD4, 0x5A, 0x6D, 0xD9, 0x7C, 0x34, 0xD5, 0x5D, 0x35, 0x4D, 0x45, 0x7A, 0x3D, + 0xA9, 0xD4, 0x68, 0x8B, 0xAF, 0x72, 0xB9, 0x30, 0xBD, 0x99, 0xA2, 0x97, 0x2F, 0x0F, 0xDC, 0x3D, + 0xEE, 0x35, 0x8E, 0x42, 0x23, 0x02, 0x67, 0xD7, 0xB6, 0x5E, 0x74, 0x79, 0x90, 0xBC, 0x2C, 0x48, + 0x4E, 0xA9, 0x31, 0x35, 0x4D, 0x39, 0x40, 0x55, 0x73, 0xFF, 0xAC, 0x79, 0xFF, 0xB8, 0x84, 0x51, + 0x7E, 0xD6, 0x94, 0x8F, 0x3A, 0x78, 0x7E, 0xBB, 0x7C, 0xE3, 0x7D, 0x7D, 0xB6, 0x82, 0x4B, 0x8B, + 0x1D, 0xF7, 0x62, 0x31, 0x56, 0x51, 0x2A, 0x12, 0xD4, 0xED, 0x5D, 0x5B, 0xD5, 0x35, 0x15, 0x94, + 0x7F, 0x19, 0x0B, 0xAB, 0x69, 0xDC, 0xF3, 0x18, 0xA5, 0x92, 0x65, 0x98, 0xC7, 0x9A, 0xA3, 0x49, + 0xF1, 0xAF, 0x4D, 0x01, 0xD2, 0x16, 0x83, 0xBE, 0xC8, 0xB8, 0x90, 0xDE, 0x5B, 0x2C, 0xCF, 0x35, + 0xE5, 0x4D, 0x12, 0xEF, 0xA2, 0x8D, 0x21, 0x16, 0x27, 0x4C, 0x86, 0x05, 0xBA, 0x5D, 0xE7, 0x4C, + 0xD6, 0xE0, 0x80, 0x41, 0x2E, 0x7B, 0x18, 0x87, 0xEB, 0xC2, 0xE0, 0x6B, 0x69, 0x67, 0xA8, 0x66, + 0x37, 0xBC, 0x3B, 0xED, 0xB1, 0x1D, 0xF6, 0xF5, 0xAC, 0xB7, 0xE9, 0xC6, 0x43, 0x58, 0x08, 0xAC, + 0x62, 0x2E, 0xF3, 0x61, 0xA2, 0xE9, 0x2C, 0x90, 0xA7, 0x41, 0x34, 0x65, 0x45, 0xF4, 0x35, 0xE7, + 0xAB, 0xEE, 0x3C, 0xBB, 0x1D, 0x31, 0x67, 0x11, 0x0B, 0x5A, 0x12, 0x0B, 0x6F, 0x55, 0x2A, 0xDC, + 0xA6, 0xDC, 0x69, 0xCE, 0xA9, 0x69, 0x00, 0x47, 0x68, 0x1C, 0x21, 0x58, 0xC5, 0xDF, 0xF9, 0x7C, + 0x74, 0xF1, 0xEB, 0x90, 0xC9, 0xA0, 0x99, 0xD4, 0x1A, 0xD5, 0xF8, 0xF2, 0xC3, 0x77, 0x4F, 0xEC, + 0xEF, 0x9C, 0x6A, 0x9D, 0x2D, 0x9B, 0xE5, 0x0D, 0x26, 0xF9, 0x2F, 0x33, 0x18, 0x54, 0xC4, 0x9A, + 0x9C, 0xC0, 0x1B, 0x89, 0xFB, 0x13, 0xAC, 0xE6, 0x07, 0x4C, 0x69, 0x68, 0x3C, 0x70, 0x8B, 0x10, + 0xD4, 0xA3, 0x82, 0x9E, 0x93, 0xDB, 0x14, 0xF1, 0x0D, 0xDE, 0xA7, 0xAC, 0x0B, 0x93, 0xCA, 0x3C, + 0xAE, 0x23, 0x90, 0xE7, 0xA6, 0xF4, 0x9A, 0x2B, 0xAC, 0x26, 0x7E, 0x9E, 0x47, 0xC3, 0x60, 0x80, + 0x7C, 0x63, 0xAE, 0xF0, 0x02, 0x68, 0x78, 0x58, 0xD3, 0x55, 0x5A, 0xE4, 0xDD, 0x05, 0x7B, 0x47, + 0xB7, 0x5E, 0xB0, 0xA3, 0x81, 0x17, 0x4F, 0xFC, 0xDB, 0x79, 0xBF, 0x7B, 0xB0, 0xBE, 0x17, 0x5C, + 0x45, 0xB5, 0x74, 0xE6, 0x8D, 0xE7, 0xA9, 0x22, 0x9F, 0x26, 0x77, 0xB4, 0xA0, 0x5F, 0x67, 0xB6, + 0xC9, 0xBC, 0x11, 0x3A, 0xD5, 0xAF, 0xF7, 0xEA, 0x45, 0xE0, 0xCF, 0xB6, 0x37, 0x1F, 0x02, 0x63, + 0x43, 0xEC, 0x2B, 0x17, 0x52, 0x13, 0xBE, 0x7C, 0xB8, 0xE2, 0x6B, 0x63, 0xF4, 0x74, 0x44, 0x71, + 0x99, 0xC2, 0x81, 0x85, 0x84, 0x15, 0xBA, 0x63, 0x8F, 0x70, 0xE6, 0x8F, 0x23, 0x43, 0x1B, 0x09, + 0xAF, 0x6D, 0x98, 0xA3, 0x46, 0x73, 0x4C, 0x26, 0xDA, 0x46, 0x06, 0x49, 0xF1, 0xF6, 0xAD, 0x57, + 0xCA, 0x29, 0x45, 0x39, 0x02, 0x95, 0xCA, 0xDD, 0xC8, 0xA4, 0x91, 0x11, 0xB6, 0x5F, 0x1D, 0x19, + 0xE5, 0x9D, 0x24, 0x95, 0x74, 0x76, 0x27, 0x4D, 0x3A, 0xA8, 0xBA, 0x8E, 0xD2, 0x26, 0x84, 0x9A, + 0x05, 0x28, 0x51, 0xBB, 0x5B, 0x08, 0x50, 0xE2, 0xEF, 0x15, 0x08, 0x50, 0x72, 0xD0, 0x52, 0x02, + 0x94, 0x78, 0xF7, 0xB9, 0x05, 0x28, 0xD0, 0x08, 0xED, 0x47, 0x66, 0x58, 0xF7, 0x76, 0x00, 0xA2, + 0x13, 0x71, 0x0C, 0x21, 0x52, 0x09, 0x77, 0xAF, 0x84, 0x38, 0x95, 0x22, 0x36, 0xC9, 0x50, 0xAF, + 0x90, 0xCD, 0x60, 0xE9, 0x65, 0xD1, 0x7C, 0x7D, 0xAE, 0x97, 0xF3, 0x24, 0x2A, 0xB1, 0x07, 0x4B, + 0x97, 0xA8, 0xC4, 0x30, 0xAF, 0x12, 0xD5, 0xCB, 0x39, 0x17, 0x62, 0x3B, 0x5A, 0xF6, 0x28, 0x98, + 0x34, 0x59, 0xDE, 0x51, 0x50, 0x67, 0x29, 0xD3, 0x38, 0x40, 0x72, 0xF9, 0xDE, 0x8D, 0xEF, 0x1A, + 0xA0, 0xD9, 0x63, 0x1E, 0x92, 0x46, 0x65, 0x0E, 0x37, 0xE3, 0x9C, 0x3C, 0xD3, 0xE5, 0xD1, 0xCD, + 0xDD, 0xED, 0x25, 0x08, 0x5B, 0xF4, 0xA9, 0x44, 0x79, 0xCA, 0x3A, 0xAB, 0x1D, 0x66, 0x71, 0x4D, + 0x3E, 0xC6, 0x10, 0x39, 0x8E, 0x06, 0x36, 0x31, 0x3B, 0x4D, 0xA6, 0x61, 0x21, 0x76, 0x8A, 0x61, + 0xAD, 0x21, 0x47, 0x95, 0x93, 0x27, 0xF6, 0xE8, 0xC5, 0x4B, 0xC7, 0x21, 0x6B, 0x1D, 0x72, 0x5F, + 0x54, 0x97, 0xAF, 0xA8, 0x90, 0x2E, 0x85, 0xFE, 0x4A, 0x54, 0x27, 0x5D, 0x95, 0xA4, 0x21, 0x10, + 0x67, 0x23, 0x24, 0x8D, 0xAF, 0x7A, 0x24, 0x69, 0xA0, 0xED, 0x6B, 0x35, 0x92, 0xC6, 0x64, 0xD0, + 0x09, 0xBD, 0x05, 0xBA, 0xF3, 0xDC, 0xB2, 0xC4, 0xC4, 0xF6, 0x4C, 0xE2, 0x82, 0x07, 0x5D, 0x72, + 0x4B, 0xE3, 0x9E, 0xF4, 0x53, 0x3E, 0xEB, 0xAD, 0xBB, 0x44, 0x10, 0xE8, 0xE5, 0x8A, 0x74, 0x2E, + 0x2C, 0x13, 0x04, 0xFA, 0x3A, 0xCA, 0x04, 0x88, 0xC0, 0xE9, 0x32, 0x41, 0x5B, 0x69, 0xB7, 0x95, + 0x57, 0xA1, 0x20, 0x4F, 0x28, 0x48, 0x6E, 0x69, 0x29, 0xA1, 0x20, 0xD1, 0x64, 0xC3, 0xF5, 0xC3, + 0x88, 0x25, 0xD5, 0xC1, 0xB5, 0xAB, 0x5D, 0xCE, 0x88, 0x74, 0xF4, 0x1B, 0x7E, 0x31, 0x43, 0x8B, + 0x98, 0xEB, 0x5E, 0x26, 0xDE, 0x72, 0x16, 0xBC, 0x71, 0xE0, 0x4C, 0x5D, 0xC9, 0x50, 0x2C, 0xDE, + 0xB3, 0xDF, 0xC8, 0x64, 0x4F, 0x7F, 0x8D, 0x2E, 0x64, 0xCE, 0x3D, 0x87, 0x4A, 0xE8, 0x9D, 0xF7, + 0x7B, 0xCD, 0x9B, 0x2F, 0x3F, 0x2F, 0xFB, 0x7C, 0x0F, 0x87, 0x5B, 0xF2, 0x39, 0x8E, 0x96, 0x44, + 0x4A, 0x72, 0x8C, 0x21, 0x7F, 0xB0, 0xB4, 0x6E, 0x27, 0x4C, 0xC9, 0x19, 0x25, 0x53, 0x16, 0x17, + 0xC7, 0x80, 0xD5, 0x4D, 0xFA, 0x63, 0x1B, 0x8D, 0x8E, 0xD1, 0x23, 0x10, 0x82, 0x7D, 0x43, 0xDC, + 0x2C, 0x8B, 0xB8, 0x4E, 0x74, 0x59, 0x27, 0x79, 0x96, 0x62, 0xAC, 0xC7, 0x86, 0xE7, 0x25, 0xA3, + 0xAC, 0xBF, 0x0C, 0x06, 0x6B, 0xED, 0x73, 0x1E, 0x51, 0xC5, 0x3C, 0x79, 0x18, 0xD2, 0x11, 0x30, + 0x67, 0xBD, 0x82, 0x34, 0xAF, 0x8F, 0x4F, 0x0F, 0x43, 0x56, 0x4A, 0x63, 0xC3, 0x83, 0x06, 0xF3, + 0xFC, 0x27, 0xDC, 0x21, 0x79, 0x9D, 0x7E, 0x28, 0xD8, 0xE8, 0x5F, 0x1A, 0x47, 0xC7, 0xC7, 0x87, + 0x27, 0x27, 0x87, 0xA7, 0xA7, 0x87, 0x67, 0x67, 0x87, 0xE7, 0xE7, 0x87, 0x17, 0x17, 0x55, 0xDD, + 0x42, 0xE6, 0x9A, 0x69, 0x4F, 0x35, 0x30, 0x1B, 0x38, 0x4D, 0xD8, 0x3B, 0xAC, 0x18, 0x69, 0x56, + 0xEE, 0x2C, 0x74, 0x38, 0x77, 0x61, 0xE5, 0x5E, 0xF6, 0xD2, 0x6F, 0x6C, 0x8B, 0xAF, 0x44, 0x3D, + 0x2E, 0x25, 0xCC, 0x61, 0x23, 0x39, 0x53, 0x21, 0xB2, 0x01, 0x63, 0x02, 0x4E, 0x38, 0x3E, 0xDC, + 0x73, 0xBE, 0xFF, 0xA5, 0x68, 0xC9, 0xF2, 0x98, 0x49, 0x1E, 0x1F, 0x08, 0x05, 0x38, 0x55, 0x10, + 0xD6, 0x02, 0xD0, 0x8D, 0xAC, 0x73, 0x28, 0x55, 0x4E, 0x2C, 0xBE, 0x3F, 0x88, 0x54, 0x05, 0x27, + 0x1A, 0x02, 0x94, 0x05, 0x74, 0xD9, 0x20, 0x59, 0x1E, 0x98, 0x89, 0x1B, 0x70, 0x90, 0x2C, 0xE1, + 0x5B, 0xB9, 0xD5, 0xE9, 0xE5, 0x7B, 0x56, 0x70, 0xC5, 0x11, 0xAB, 0xB0, 0xFE, 0x68, 0x4B, 0x1D, + 0xC3, 0xDB, 0x66, 0xFC, 0xBB, 0xE1, 0xA3, 0xEB, 0x8B, 0x3C, 0xEB, 0x85, 0xCF, 0x0A, 0xD9, 0x28, + 0xE9, 0x16, 0xC4, 0xE3, 0x3E, 0x6C, 0x9C, 0x04, 0x6E, 0x60, 0xF9, 0x86, 0xC9, 0xDE, 0xE0, 0x6A, + 0xDE, 0xA0, 0x5D, 0xD2, 0xE3, 0x58, 0xF3, 0xFA, 0xAB, 0x65, 0xF8, 0x32, 0x64, 0xC6, 0x7B, 0x54, + 0x1D, 0xA4, 0xBE, 0xF0, 0x12, 0x85, 0x7B, 0xD2, 0xB1, 0x05, 0xE0, 0xCA, 0xB0, 0xE0, 0x57, 0x60, + 0x51, 0xEE, 0x61, 0x50, 0xE6, 0x55, 0x5F, 0x94, 0xD0, 0x75, 0xEC, 0x47, 0xBC, 0x3D, 0xB6, 0x5A, + 0x9B, 0x1B, 0x52, 0x57, 0x0F, 0x43, 0x58, 0x49, 0x4C, 0xE9, 0x85, 0x8D, 0x32, 0x92, 0xA4, 0x85, + 0x30, 0xA0, 0x54, 0x3C, 0xC4, 0x08, 0xA8, 0xC2, 0x1D, 0x08, 0x71, 0x78, 0x35, 0xD1, 0xA4, 0x89, + 0xD9, 0x02, 0xF6, 0xC9, 0xBA, 0xCD, 0xCF, 0x40, 0x3A, 0x40, 0x0C, 0x94, 0xFF, 0x44, 0xD5, 0x34, + 0x43, 0x17, 0x25, 0x3E, 0x75, 0x6E, 0xF2, 0x30, 0x6F, 0x93, 0x23, 0x98, 0x39, 0x9D, 0x35, 0x22, + 0x58, 0x3B, 0x5C, 0x17, 0x1B, 0x07, 0x78, 0xF3, 0x69, 0xB8, 0xF0, 0xF3, 0x9E, 0x87, 0x95, 0xA7, + 0xE1, 0xCF, 0x01, 0xE6, 0x71, 0xA2, 0xA8, 0x32, 0x41, 0x5B, 0x40, 0x4E, 0x44, 0x71, 0xF9, 0x46, + 0xFE, 0x75, 0xA5, 0x84, 0xF9, 0x8F, 0xAA, 0x3C, 0xBE, 0x9D, 0xDC, 0xFF, 0x74, 0xCE, 0x5D, 0x81, + 0x47, 0x0F, 0xA8, 0x3B, 0x71, 0xF0, 0xCE, 0xF2, 0xEA, 0xA3, 0x09, 0x19, 0x54, 0x63, 0xD5, 0x4E, + 0xDA, 0x74, 0xAF, 0xBD, 0xE1, 0x94, 0xC2, 0xD6, 0x0F, 0xC8, 0x6D, 0x70, 0x59, 0xAA, 0x67, 0xB6, + 0xF4, 0x65, 0xDA, 0xAE, 0x9A, 0x9B, 0xF8, 0x7C, 0x5A, 0x3C, 0xB0, 0x40, 0x2A, 0xA8, 0x24, 0x90, + 0x15, 0xDA, 0xBD, 0xCB, 0x33, 0xA8, 0x2B, 0x98, 0x2C, 0x66, 0x66, 0xBA, 0x55, 0x8B, 0x4D, 0x10, + 0x8B, 0x33, 0x18, 0x31, 0xDA, 0x8A, 0x0C, 0xDF, 0x09, 0xD5, 0x00, 0x57, 0x28, 0xA5, 0xD5, 0xE7, + 0xD4, 0x0F, 0x9E, 0xCB, 0xEA, 0x9D, 0x8D, 0x5C, 0x21, 0xC6, 0xCE, 0x9B, 0xB6, 0x6D, 0x2E, 0x2E, + 0x74, 0x6A, 0xDB, 0xAE, 0x6E, 0x58, 0x42, 0x95, 0xBF, 0xA0, 0xA2, 0xE9, 0x96, 0xF6, 0xC4, 0xB6, + 0xAE, 0x3F, 0xFF, 0xF9, 0xF6, 0x39, 0x7C, 0x51, 0x28, 0x17, 0xFD, 0x20, 0x9A, 0x07, 0xA1, 0x86, + 0xB8, 0xE7, 0x40, 0x43, 0x05, 0x1B, 0xD9, 0x8E, 0x83, 0x32, 0x54, 0x98, 0x15, 0x5C, 0x16, 0xE1, + 0xF1, 0x5A, 0x92, 0x71, 0xC1, 0xB9, 0x42, 0xE2, 0x95, 0x68, 0x35, 0xE2, 0xAA, 0xCB, 0xB8, 0xAA, + 0x8D, 0x98, 0x0D, 0xE7, 0x8D, 0x2B, 0x4E, 0x24, 0xE8, 0x52, 0x24, 0x15, 0x41, 0xAF, 0x17, 0x2D, + 0xBE, 0xFC, 0x68, 0xD8, 0x18, 0x12, 0xBD, 0x6F, 0x2B, 0x00, 0x8A, 0x16, 0xBB, 0x32, 0xC6, 0x20, + 0xEB, 0xC1, 0x67, 0x05, 0x8D, 0x36, 0xEC, 0x7D, 0xE7, 0x1D, 0x3E, 0x7E, 0x01, 0xE7, 0x95, 0x94, + 0xF8, 0x85, 0x4D, 0x78, 0x0F, 0xE7, 0xD0, 0x65, 0x13, 0xC5, 0xA5, 0x8A, 0x49, 0x33, 0x27, 0xF3, + 0xB3, 0xE4, 0xB6, 0x13, 0x9E, 0x3C, 0x81, 0x7A, 0x84, 0x73, 0xE5, 0x34, 0xBB, 0xCC, 0xE6, 0x0B, + 0x5A, 0x3C, 0xEB, 0xA5, 0x2A, 0x51, 0x62, 0xC1, 0x0B, 0x85, 0x1D, 0x9D, 0xEB, 0x06, 0x95, 0xF5, + 0x65, 0xA6, 0xE1, 0xF9, 0xDC, 0x42, 0x0C, 0x46, 0x75, 0x63, 0xD5, 0x04, 0x76, 0x3C, 0xF0, 0xE9, + 0x66, 0x10, 0x24, 0x2E, 0xB1, 0x59, 0x94, 0xEF, 0x43, 0xCC, 0x75, 0x1B, 0x38, 0x34, 0xE8, 0x29, + 0x38, 0x35, 0x99, 0x3E, 0x24, 0xCA, 0x07, 0x03, 0xAF, 0x1B, 0x43, 0xCB, 0x46, 0x39, 0xCF, 0xB3, + 0x05, 0x85, 0x11, 0x13, 0x97, 0xEF, 0x21, 0x17, 0x1F, 0xA0, 0xDF, 0x47, 0x48, 0x94, 0x52, 0xC3, + 0xC2, 0xFC, 0x9C, 0x58, 0xA3, 0x34, 0x16, 0x06, 0x00, 0x94, 0xE3, 0xF2, 0xA6, 0x38, 0x81, 0xA6, + 0x87, 0x89, 0x11, 0x5D, 0x57, 0xF1, 0x26, 0x14, 0xD7, 0x56, 0xB0, 0xD9, 0xBE, 0xA2, 0x78, 0xAF, + 0xE4, 0x36, 0x1F, 0xB9, 0x89, 0x8C, 0x34, 0x98, 0x55, 0xD5, 0x55, 0x35, 0x51, 0xAD, 0x7D, 0xCC, + 0xED, 0xC0, 0xFF, 0xDD, 0x2B, 0x4F, 0x73, 0xD9, 0x7D, 0x2C, 0x83, 0xF0, 0x2A, 0x08, 0x7C, 0xD5, + 0xAC, 0xFB, 0xB1, 0x4C, 0x7B, 0xAC, 0xE7, 0x1A, 0x36, 0xE6, 0xE3, 0xDC, 0x74, 0x63, 0x7F, 0x6C, + 0x4D, 0xE1, 0x92, 0x72, 0x4D, 0xFF, 0x33, 0xDD, 0x66, 0x5C, 0x05, 0x64, 0xF7, 0x3B, 0xBB, 0x33, + 0x71, 0xB8, 0xA6, 0x5E, 0x0F, 0xC4, 0xD2, 0x7E, 0x2D, 0xE9, 0x92, 0xA0, 0xC2, 0x2D, 0x41, 0xD9, + 0x95, 0xD5, 0x92, 0x0E, 0xA6, 0x5C, 0x18, 0x63, 0x0C, 0x3E, 0x22, 0x61, 0x9D, 0x77, 0x65, 0x0C, + 0x38, 0x16, 0xC7, 0xC9, 0xE6, 0xEE, 0x33, 0x17, 0xBD, 0xBB, 0x91, 0x01, 0x6F, 0x9F, 0xFE, 0xD8, + 0x9F, 0xB9, 0xE8, 0x8D, 0xEF, 0x93, 0x18, 0x87, 0x85, 0xE3, 0x1C, 0xAE, 0x48, 0x19, 0x38, 0x8E, + 0xA5, 0x80, 0x93, 0x99, 0xDD, 0x18, 0xA0, 0x28, 0xE5, 0x71, 0x36, 0x06, 0xCC, 0xB2, 0x85, 0x7B, + 0x31, 0x1C, 0x3A, 0x98, 0xD0, 0xD9, 0x78, 0x90, 0xE5, 0x11, 0xE9, 0xD4, 0x1A, 0xAB, 0xD6, 0x53, + 0x78, 0x60, 0xB5, 0x26, 0x04, 0x1C, 0xBA, 0x22, 0x0B, 0x7F, 0x17, 0x19, 0xA7, 0x41, 0x36, 0x36, + 0xCC, 0x30, 0x8F, 0xB9, 0x6B, 0xC2, 0x0C, 0x72, 0xE1, 0xA1, 0xB2, 0x87, 0x6F, 0xB5, 0x3B, 0x4A, + 0xD4, 0xD9, 0x7A, 0x69, 0x0A, 0xE5, 0x22, 0x50, 0xDF, 0x24, 0x0E, 0x93, 0xDD, 0x37, 0xE5, 0xDC, + 0xAF, 0xDE, 0x88, 0x83, 0xE3, 0x4D, 0xD8, 0x49, 0xFC, 0xE0, 0x78, 0x33, 0x4D, 0xAB, 0xD3, 0xB8, + 0x58, 0xFD, 0x76, 0xC0, 0x29, 0xE8, 0x72, 0x69, 0x7E, 0x39, 0x85, 0xC9, 0x98, 0x66, 0x69, 0x61, + 0x72, 0x26, 0x2C, 0x3B, 0x41, 0xD3, 0xB1, 0x87, 0xA5, 0x10, 0x08, 0x4F, 0x9D, 0x10, 0x8B, 0x41, + 0x16, 0x23, 0x5D, 0x25, 0x9E, 0x21, 0x31, 0xC4, 0x5B, 0xB2, 0xE3, 0x60, 0x58, 0xA4, 0x1A, 0x92, + 0x0C, 0xE0, 0x2F, 0x08, 0x6C, 0x2E, 0x47, 0x7D, 0x09, 0xAD, 0xD0, 0x61, 0x37, 0xE1, 0xBB, 0xE4, + 0xC1, 0x2F, 0xB1, 0x9F, 0x6A, 0xE1, 0x7D, 0xC3, 0xF7, 0xE8, 0x31, 0xC8, 0x6A, 0xF0, 0xB4, 0x45, + 0xC5, 0x7F, 0x87, 0x5C, 0xA4, 0x61, 0xF4, 0x54, 0x24, 0x34, 0xF2, 0xBF, 0x7D, 0xD3, 0x87, 0xBF, + 0x93, 0x5C, 0xFC, 0x4D, 0x49, 0x23, 0xDD, 0xDA, 0x24, 0x7A, 0x8A, 0x9F, 0xD4, 0x92, 0x15, 0x8E, + 0xBF, 0x37, 0xB1, 0x1C, 0xAB, 0xC0, 0x88, 0x69, 0xA4, 0x0C, 0xF7, 0xFD, 0xCA, 0xC8, 0x74, 0xC7, + 0x4F, 0xB7, 0xD7, 0x65, 0x98, 0xE6, 0xA2, 0xFE, 0xB1, 0xE3, 0x13, 0x7A, 0x57, 0x69, 0x1C, 0x29, + 0xF9, 0x76, 0xB5, 0x45, 0x47, 0x68, 0x37, 0x8E, 0xDA, 0xCB, 0x1D, 0x01, 0x76, 0xAC, 0xB3, 0xDC, + 0x11, 0xBA, 0x8D, 0xA3, 0xEE, 0x72, 0x47, 0xD8, 0x6D, 0x1C, 0xED, 0x2E, 0x77, 0x84, 0xBD, 0xC6, + 0xD1, 0xDE, 0x72, 0x47, 0xD8, 0x6F, 0x1C, 0xED, 0x2F, 0x77, 0x84, 0x77, 0x8D, 0xA3, 0x77, 0x45, + 0x23, 0xB8, 0x55, 0x86, 0xCE, 0x20, 0x38, 0xA9, 0xF3, 0xCD, 0x61, 0xE4, 0x8E, 0x8C, 0xDB, 0x2E, + 0x6A, 0x99, 0x77, 0xF6, 0x69, 0x76, 0xE7, 0xE8, 0xC5, 0x28, 0x75, 0x51, 0x3B, 0xD4, 0x32, 0x73, + 0x6C, 0xDC, 0x0B, 0x27, 0x86, 0xBC, 0xB4, 0x3C, 0xDF, 0x0D, 0xF0, 0x3C, 0x78, 0x16, 0xDD, 0x02, + 0x41, 0x6D, 0x44, 0x53, 0x08, 0x75, 0x81, 0x1A, 0x35, 0x8E, 0xCB, 0x99, 0xCE, 0x2B, 0xF9, 0x18, + 0xCD, 0x34, 0x9F, 0xDD, 0x82, 0x19, 0x08, 0x4E, 0xA9, 0x13, 0xB1, 0xE5, 0x3D, 0xB7, 0xCB, 0x51, + 0xC1, 0x6A, 0xE6, 0xD0, 0x21, 0xC8, 0xC5, 0xDF, 0x30, 0x2B, 0xC6, 0xE6, 0xD6, 0x7D, 0x1F, 0x71, + 0x47, 0x33, 0x18, 0x3B, 0xDC, 0xF2, 0x08, 0xF4, 0xD1, 0xA5, 0x29, 0x7E, 0x51, 0x60, 0x53, 0x9E, + 0xB4, 0x5A, 0xC5, 0x5D, 0xC6, 0xEC, 0x4C, 0x57, 0xA5, 0xCA, 0x50, 0xB8, 0x13, 0x6E, 0x15, 0x5E, + 0xF1, 0x47, 0xE3, 0x93, 0x6D, 0x0F, 0x59, 0x0D, 0xA8, 0x24, 0xE8, 0xB5, 0xEC, 0x72, 0x7D, 0xB6, + 0x44, 0x6A, 0x6B, 0xA3, 0xEE, 0x26, 0x96, 0x83, 0x68, 0x22, 0x95, 0xF3, 0x9D, 0xE1, 0x1C, 0x9B, + 0x00, 0xD1, 0x40, 0x07, 0xFD, 0x42, 0xA6, 0x31, 0x86, 0x67, 0x2C, 0x7C, 0xB8, 0x5C, 0x14, 0x4A, + 0x99, 0xC3, 0x8A, 0xB0, 0x47, 0x2E, 0xD5, 0xB1, 0x71, 0x3F, 0x61, 0xBD, 0xAA, 0x9C, 0x40, 0x3C, + 0x19, 0xB3, 0x8A, 0x4E, 0xEF, 0x96, 0x1A, 0x7D, 0x97, 0x52, 0xDA, 0x68, 0x83, 0x42, 0x3B, 0xB2, + 0xD9, 0x9D, 0x5C, 0x67, 0x6F, 0x04, 0xEA, 0xCC, 0x29, 0xD1, 0xCC, 0xEF, 0xE3, 0xF1, 0x72, 0xBD, + 0xE6, 0x53, 0x87, 0x6C, 0xA4, 0xDA, 0x69, 0x67, 0xED, 0x28, 0xC7, 0x72, 0x5F, 0xA8, 0x75, 0x3E, + 0x33, 0xA4, 0xAE, 0xD9, 0xD6, 0x78, 0xBC, 0xF2, 0xFB, 0xB4, 0xE3, 0xDE, 0x29, 0xEA, 0x6D, 0x32, + 0x93, 0x8E, 0xAF, 0x5A, 0x1A, 0x5E, 0xAD, 0xD9, 0x63, 0x59, 0x4A, 0x1D, 0x14, 0x47, 0x19, 0xE9, + 0x1D, 0x62, 0x99, 0xB4, 0x9C, 0x84, 0x1F, 0x1D, 0x5C, 0x1C, 0xD3, 0x68, 0x01, 0x2D, 0x76, 0x87, + 0x06, 0x18, 0xF8, 0x7F, 0xE0, 0x05, 0xAA, 0x69, 0x3E, 0xA1, 0xC2, 0x69, 0xF9, 0x61, 0x25, 0x1C, + 0x2C, 0xED, 0xA7, 0xCF, 0xF4, 0x87, 0x1E, 0x50, 0x18, 0xC4, 0xA9, 0x9A, 0x1A, 0x45, 0x38, 0xE9, + 0x4C, 0x0F, 0x5C, 0x72, 0x81, 0x92, 0x2F, 0xC0, 0x37, 0xC6, 0xBD, 0x2B, 0xAB, 0x79, 0x1D, 0x8F, + 0xED, 0x40, 0x44, 0x7D, 0xAA, 0xBA, 0x2E, 0x2E, 0xF0, 0x3E, 0x1F, 0x9F, 0x87, 0x77, 0x28, 0x30, + 0x7F, 0x97, 0xDC, 0xA7, 0x06, 0xC6, 0x77, 0x74, 0x23, 0x51, 0x31, 0xA4, 0x00, 0xB8, 0xFE, 0xD8, + 0xC6, 0xFC, 0x45, 0xA7, 0xDE, 0x21, 0xBB, 0xB3, 0x5D, 0x6D, 0xB4, 0xD5, 0x6E, 0xBF, 0x03, 0x50, + 0xB3, 0xF3, 0xBF, 0xFD, 0x75, 0x6B, 0xB7, 0x83, 0x7F, 0x5D, 0x00, 0xF4, 0x7C, 0x60, 0xC9, 0x9E, + 0x6A, 0x68, 0x5B, 0xFB, 0xEF, 0x27, 0x8F, 0x44, 0xE5, 0x00, 0xF6, 0xD0, 0x49, 0x3C, 0x85, 0x8F, + 0xEF, 0x14, 0xF8, 0xF8, 0x92, 0xE2, 0x13, 0x24, 0x16, 0xD7, 0x74, 0xBB, 0xD0, 0xC8, 0xA6, 0xD8, + 0x72, 0xF7, 0x09, 0xA9, 0x4D, 0x57, 0x1E, 0xB1, 0x50, 0xC8, 0x8C, 0x3E, 0x73, 0xA4, 0xB6, 0xDF, + 0x57, 0xC3, 0x86, 0xC2, 0xC1, 0xAA, 0x32, 0x20, 0xD1, 0x8E, 0x6D, 0xA9, 0xAD, 0x6F, 0x2D, 0xB5, + 0x95, 0x0B, 0xFD, 0x1E, 0x1E, 0x34, 0xA2, 0x4E, 0xEE, 0x5B, 0xE0, 0x47, 0xCF, 0x70, 0xBD, 0x2F, + 0x18, 0x08, 0x99, 0xA0, 0x44, 0x29, 0x78, 0xC9, 0x2F, 0x80, 0x4A, 0xBC, 0xB1, 0x38, 0x08, 0x91, + 0x22, 0xD1, 0xC8, 0x6B, 0x58, 0x9A, 0x19, 0x20, 0x17, 0xC0, 0x62, 0x3F, 0x16, 0x7A, 0x76, 0x78, + 0x2D, 0x76, 0x63, 0x23, 0x6B, 0xA0, 0x6A, 0x5B, 0xAA, 0xC9, 0x8E, 0x6F, 0x7B, 0x58, 0xCB, 0x22, + 0x30, 0x29, 0x7F, 0x58, 0xD8, 0x20, 0x1E, 0x67, 0xD4, 0x3A, 0x18, 0xBF, 0x92, 0x71, 0x29, 0x32, + 0x8E, 0xD0, 0xAF, 0x0A, 0x01, 0x87, 0x8D, 0x9E, 0x97, 0x74, 0x33, 0x54, 0xF3, 0x2C, 0xDD, 0xBC, + 0xFF, 0x04, 0xC2, 0xD5, 0x78, 0xD3, 0xEF, 0xFC, 0xC4, 0x2A, 0xE6, 0xD2, 0xBE, 0x13, 0x4D, 0x67, + 0x41, 0x9C, 0x80, 0xCF, 0x94, 0xD6, 0xED, 0x89, 0xA6, 0xCF, 0x7E, 0x7F, 0x97, 0xB3, 0x84, 0x39, + 0xD5, 0xED, 0xC0, 0x31, 0x6D, 0x55, 0xBF, 0xE1, 0x8F, 0x17, 0x86, 0x3B, 0xC6, 0xCA, 0xAC, 0x67, + 0xC6, 0x43, 0x99, 0x02, 0x97, 0xA5, 0xD4, 0x9C, 0x99, 0xCE, 0x1B, 0x47, 0x12, 0xCA, 0xE1, 0x83, + 0x82, 0xA4, 0xA3, 0xC4, 0xA0, 0x28, 0xA4, 0xC3, 0xFF, 0x16, 0x36, 0xF9, 0x1B, 0x77, 0x91, 0x2B, + 0x7E, 0x75, 0x86, 0xAE, 0x0A, 0x4A, 0x4B, 0x66, 0xA0, 0xC3, 0x83, 0xD2, 0x52, 0xE6, 0xB1, 0xA4, + 0x67, 0x1F, 0x77, 0x39, 0x04, 0x9D, 0xE7, 0xD2, 0x7A, 0x8A, 0x70, 0x89, 0x03, 0x61, 0x2E, 0xB7, + 0xD6, 0xC8, 0xEA, 0xA7, 0x4D, 0x75, 0x87, 0x36, 0x3E, 0x1A, 0x82, 0x6E, 0x0B, 0xE1, 0x8B, 0x08, + 0xB8, 0x13, 0x8C, 0x5B, 0x91, 0x62, 0x27, 0xA6, 0xD1, 0x77, 0x54, 0xF7, 0xDB, 0x45, 0x40, 0xF7, + 0x91, 0x1E, 0xE7, 0x74, 0xB7, 0x09, 0xB3, 0x1A, 0xC8, 0x59, 0x91, 0x9C, 0x1B, 0x55, 0xD2, 0x88, + 0x6E, 0x38, 0x85, 0xA3, 0xCC, 0x5A, 0xE9, 0x74, 0x31, 0xC6, 0x1F, 0x4E, 0x3E, 0xDC, 0x4B, 0xF4, + 0xF5, 0x15, 0x3C, 0xFE, 0x79, 0x9D, 0xFB, 0x6F, 0x4F, 0x27, 0xA4, 0x25, 0x8C, 0x32, 0x27, 0xDC, + 0x57, 0x63, 0x18, 0xB0, 0x1A, 0xAF, 0xFD, 0xF8, 0x34, 0x56, 0x2C, 0x5C, 0xD1, 0x7A, 0x23, 0xDC, + 0x42, 0xAE, 0xAF, 0x1A, 0x96, 0x27, 0x2F, 0xC2, 0xF1, 0xBA, 0x8F, 0x0D, 0xB8, 0xEA, 0x07, 0x78, + 0xC9, 0x0E, 0xD4, 0xC0, 0xC6, 0xEA, 0x13, 0xB3, 0x6C, 0x72, 0xCC, 0x07, 0xC5, 0x0A, 0xA6, 0x8E, + 0xC2, 0x95, 0x8F, 0x37, 0xEE, 0xA0, 0x51, 0x71, 0x3C, 0x46, 0x08, 0x25, 0x07, 0x06, 0x07, 0xE9, + 0x0A, 0xB3, 0x0A, 0xAF, 0xBB, 0xEF, 0xD5, 0xF3, 0xE2, 0xDF, 0x71, 0xE0, 0xDB, 0xE1, 0xD6, 0x7F, + 0x75, 0x60, 0x33, 0x79, 0x64, 0x2D, 0xC5, 0xAF, 0xB0, 0x5E, 0xB5, 0x16, 0x61, 0x63, 0x71, 0xD5, + 0x32, 0xEA, 0x61, 0x65, 0xB1, 0x26, 0x69, 0x93, 0x5F, 0x31, 0xF6, 0x66, 0xE5, 0x80, 0x70, 0xB8, + 0x6B, 0xD8, 0xE8, 0x3B, 0x89, 0x06, 0x07, 0x2D, 0xE2, 0xEE, 0x71, 0x3E, 0xDA, 0x62, 0xD0, 0x58, + 0xA5, 0x47, 0x8E, 0x6B, 0xEB, 0x81, 0xF0, 0x2B, 0x79, 0x10, 0xA7, 0x63, 0x3A, 0xB7, 0xDD, 0xC6, + 0x8B, 0xF0, 0xD0, 0x67, 0x04, 0x8D, 0x6D, 0x22, 0x91, 0xB1, 0x1A, 0xEE, 0x14, 0x8E, 0xB6, 0xD9, + 0xF8, 0x9E, 0xDC, 0x5C, 0x5A, 0x54, 0x72, 0x87, 0x17, 0x29, 0x0D, 0x3E, 0x97, 0xCA, 0x9B, 0xAA, + 0xFA, 0xC6, 0x10, 0x8F, 0x4E, 0x94, 0x6B, 0xC3, 0x0A, 0x00, 0xF1, 0xCB, 0xD5, 0x97, 0xCC, 0xF1, + 0x7E, 0x12, 0x69, 0x2E, 0xDE, 0xCD, 0x28, 0xCD, 0xB2, 0xFF, 0x98, 0xF7, 0x38, 0x0C, 0xEA, 0x1D, + 0x3E, 0x73, 0x75, 0x4C, 0xC4, 0xDF, 0x88, 0x49, 0x44, 0x08, 0x1B, 0xD0, 0x3E, 0x21, 0xDE, 0x46, + 0x94, 0x31, 0x93, 0x4F, 0x3B, 0x95, 0x20, 0x98, 0x3A, 0xF1, 0xF2, 0x25, 0x7F, 0xA9, 0xB1, 0x5C, + 0xF5, 0x08, 0xDD, 0x3A, 0x38, 0x6D, 0x73, 0x42, 0x4B, 0xDE, 0x05, 0xC0, 0x6D, 0xB5, 0x61, 0x3D, + 0x4F, 0x6F, 0x37, 0xAF, 0x70, 0x66, 0xC9, 0x52, 0xB2, 0xA5, 0x3D, 0x67, 0x11, 0x9D, 0xBC, 0x31, + 0x70, 0x00, 0xA9, 0x1E, 0x67, 0xA1, 0x68, 0x89, 0x21, 0x9D, 0xDC, 0x1E, 0xE6, 0x55, 0x9A, 0xCB, + 0xF8, 0x1B, 0x57, 0xF7, 0xAC, 0x8D, 0x2E, 0xF4, 0xB3, 0x8D, 0x5C, 0xAA, 0x69, 0x0C, 0x2D, 0xE0, + 0x14, 0x64, 0xB0, 0x13, 0xD0, 0x81, 0xC7, 0x9F, 0xB8, 0x9F, 0x90, 0xE9, 0xCB, 0x07, 0x54, 0x15, + 0x2A, 0x0C, 0xD3, 0x5D, 0x97, 0x88, 0x5F, 0x2E, 0xA9, 0x3B, 0x0C, 0x13, 0x3D, 0xA3, 0xE6, 0x20, + 0xB8, 0x22, 0x8A, 0xEA, 0x0F, 0xDD, 0x56, 0x7B, 0xB7, 0xD5, 0xDE, 0x2B, 0xA3, 0x35, 0x08, 0x58, + 0x1C, 0x7D, 0x80, 0x83, 0x67, 0x48, 0x31, 0xC3, 0x71, 0x19, 0x59, 0x74, 0xD9, 0x93, 0x5F, 0x9D, + 0xA8, 0x6E, 0x74, 0xF8, 0xB6, 0x3B, 0x0D, 0xA0, 0xCC, 0xEF, 0xF0, 0x87, 0xA2, 0x14, 0x73, 0x0B, + 0x09, 0xD1, 0x47, 0x43, 0xF7, 0x47, 0x87, 0x5D, 0x45, 0xA1, 0x88, 0x70, 0x40, 0x11, 0xD9, 0x71, + 0x29, 0x83, 0x4D, 0xFA, 0x9C, 0x72, 0x22, 0xF5, 0xBA, 0xEF, 0xFE, 0x6B, 0x81, 0xE9, 0x46, 0xAE, + 0xBD, 0x2E, 0xC3, 0x6B, 0x19, 0xF5, 0x7A, 0x5A, 0x51, 0x2C, 0x99, 0x6E, 0x6E, 0x60, 0x98, 0x80, + 0x3D, 0xA2, 0x26, 0xC4, 0x3D, 0x30, 0x29, 0xFA, 0x48, 0xE6, 0x8C, 0xE0, 0x7E, 0x6C, 0xF8, 0x21, + 0x1A, 0x5C, 0xD0, 0x73, 0xDB, 0xD2, 0xC8, 0x2B, 0x2E, 0x0E, 0x33, 0xD4, 0xDE, 0x7F, 0x56, 0x0D, + 0x1F, 0x63, 0x26, 0x77, 0xB2, 0x07, 0x15, 0x2F, 0xB2, 0x93, 0xCB, 0x9B, 0x39, 0xBC, 0x3A, 0x6B, + 0xF3, 0x2C, 0x0C, 0x31, 0x19, 0xCE, 0x8A, 0xC0, 0x32, 0xFC, 0x37, 0xDE, 0xE4, 0x60, 0xB8, 0x7F, + 0x62, 0xC2, 0x14, 0x41, 0x57, 0x30, 0x0C, 0x60, 0x81, 0xF4, 0x83, 0xF0, 0x98, 0x5C, 0x0B, 0x45, + 0x09, 0x37, 0x99, 0x33, 0x02, 0xDA, 0xC5, 0x08, 0xBC, 0xDE, 0xE9, 0xAA, 0x5D, 0xFE, 0xB2, 0x5D, + 0x8B, 0xA6, 0xD1, 0x19, 0x57, 0x53, 0x35, 0xE0, 0x34, 0x0B, 0x3B, 0x53, 0xD9, 0xDF, 0x24, 0x32, + 0x4F, 0xF5, 0xFC, 0xBE, 0x8F, 0xA2, 0xD3, 0x4C, 0x6D, 0x93, 0x42, 0xF3, 0x10, 0x49, 0x3B, 0x51, + 0x07, 0x91, 0xF5, 0xE7, 0x12, 0xF6, 0x07, 0x23, 0x60, 0xE8, 0x69, 0xA5, 0xD2, 0x26, 0x93, 0xBE, + 0x92, 0x73, 0x5B, 0xB4, 0x9C, 0x89, 0xD2, 0x38, 0xBA, 0xB5, 0x29, 0xE5, 0x5C, 0xC5, 0x8A, 0x26, + 0xED, 0xC6, 0xD1, 0x89, 0xEA, 0xF1, 0xCA, 0xED, 0x3A, 0x98, 0x90, 0xB1, 0x7A, 0x01, 0x95, 0xAE, + 0x18, 0x0E, 0xB3, 0x38, 0xAE, 0x47, 0x11, 0x95, 0x5E, 0x20, 0x5C, 0x6B, 0x85, 0x85, 0x14, 0x83, + 0x5D, 0xC5, 0x55, 0xAA, 0x18, 0x1D, 0xA8, 0x89, 0x5C, 0x42, 0xC2, 0xCC, 0x0F, 0x3D, 0xCA, 0xFC, + 0xF0, 0xC5, 0x42, 0xEA, 0x22, 0xBF, 0xB4, 0xD6, 0xDA, 0x27, 0xB2, 0x31, 0xED, 0xE1, 0x9D, 0xDD, + 0x3F, 0x3B, 0x55, 0x33, 0xAB, 0x11, 0xAD, 0x20, 0x40, 0x7A, 0x08, 0x87, 0xFC, 0x10, 0x63, 0xA4, + 0x87, 0x78, 0x52, 0xF7, 0xCF, 0x18, 0x4E, 0x67, 0x35, 0xD1, 0xD2, 0x72, 0xE8, 0xD5, 0x65, 0x0A, + 0x55, 0x41, 0x6E, 0xD7, 0x5C, 0x00, 0x39, 0x59, 0xB0, 0x19, 0x99, 0x06, 0x7D, 0xC2, 0x25, 0xCA, + 0x0B, 0x1A, 0xD5, 0xE7, 0x8E, 0x14, 0x59, 0xD8, 0xA1, 0x61, 0x9A, 0xA3, 0xD1, 0xC6, 0xC5, 0x40, + 0x27, 0x40, 0x5E, 0xA4, 0xA8, 0x96, 0xB7, 0xFB, 0x94, 0xD5, 0x52, 0xE3, 0x3C, 0x1B, 0xA4, 0x34, + 0x98, 0x07, 0x86, 0xBA, 0x35, 0xE6, 0xD2, 0x37, 0xD5, 0xEF, 0x4C, 0xAE, 0xA3, 0x50, 0xCC, 0xC3, + 0x41, 0xD8, 0x16, 0xE8, 0x6A, 0x6F, 0x0F, 0xAB, 0x19, 0x1E, 0x16, 0xD7, 0x45, 0x43, 0x7F, 0x24, + 0xF4, 0x0F, 0x41, 0xA6, 0x05, 0xAB, 0x46, 0x6C, 0x62, 0x18, 0x9E, 0x41, 0x86, 0x13, 0x6D, 0x64, + 0xF0, 0x07, 0x44, 0x3C, 0x53, 0x2C, 0x46, 0xAA, 0x9F, 0x9C, 0x7C, 0x30, 0x26, 0x7E, 0x21, 0x7C, + 0x10, 0x10, 0xDC, 0x98, 0x89, 0x51, 0x36, 0xF8, 0x9E, 0x69, 0xC3, 0x0F, 0x10, 0x13, 0xC7, 0xDB, + 0x14, 0xE6, 0x69, 0xE1, 0x9C, 0xB6, 0xA9, 0xC2, 0x3C, 0xA8, 0xBA, 0x5E, 0xE0, 0x3E, 0xF0, 0x27, + 0x4A, 0x63, 0xAB, 0x42, 0x67, 0x2E, 0x5A, 0x2C, 0xE3, 0x17, 0xC3, 0x30, 0xFA, 0xB4, 0x9A, 0x2A, + 0x55, 0xD9, 0x58, 0x70, 0x28, 0xB6, 0xEE, 0x1C, 0x1C, 0x4C, 0xBE, 0x2A, 0xA9, 0xC2, 0x2E, 0x4D, + 0x7D, 0x2D, 0x67, 0xE3, 0x29, 0x6F, 0xD9, 0xAB, 0xAC, 0xB2, 0xC6, 0x70, 0xB6, 0x94, 0x6E, 0x30, + 0x79, 0x7F, 0x65, 0x21, 0xD4, 0xF3, 0x93, 0xA2, 0x70, 0x5F, 0x58, 0x84, 0x18, 0x0B, 0x37, 0x10, + 0xF5, 0x00, 0xE9, 0x26, 0x21, 0xE9, 0x71, 0xA9, 0xE4, 0x06, 0x94, 0x93, 0xC4, 0xF9, 0x24, 0xC5, + 0x09, 0xCB, 0x26, 0x52, 0x63, 0xC8, 0xE7, 0x31, 0xE6, 0x07, 0x13, 0xE2, 0xA7, 0x11, 0x1E, 0x7D, + 0x47, 0xD1, 0xE5, 0x94, 0x2C, 0xC3, 0xA4, 0x53, 0x41, 0x66, 0xCC, 0x55, 0x05, 0x35, 0x0A, 0xAA, + 0x7B, 0xE9, 0x84, 0xB5, 0x44, 0xCA, 0x92, 0x28, 0x58, 0x81, 0xB6, 0x44, 0x8B, 0xA5, 0x52, 0x97, + 0x14, 0xD1, 0x84, 0x0E, 0x2B, 0x87, 0x28, 0x41, 0x5F, 0x31, 0xC2, 0x2C, 0x61, 0xF8, 0x9D, 0xD1, + 0x68, 0xA6, 0x06, 0x8C, 0xD1, 0x76, 0xC2, 0x28, 0x43, 0x02, 0x1B, 0xA9, 0x99, 0xA8, 0xBD, 0x1C, + 0x0A, 0x14, 0x29, 0x6D, 0x68, 0x8C, 0x2D, 0xED, 0x46, 0x1D, 0xE7, 0xDC, 0x74, 0xF7, 0x2F, 0xCE, + 0x7F, 0x87, 0x91, 0x5A, 0xC1, 0xFD, 0xF7, 0x5A, 0xED, 0x87, 0x0B, 0x58, 0xDB, 0x16, 0xE3, 0x7E, + 0x8B, 0x64, 0x05, 0xCC, 0xB7, 0xAE, 0x91, 0x33, 0xE5, 0x0D, 0x7F, 0x04, 0x70, 0xD5, 0x60, 0x57, + 0x9B, 0xB1, 0xAF, 0xC5, 0xBA, 0x47, 0xE3, 0x5A, 0x1F, 0x3F, 0xD2, 0x95, 0x3C, 0x3C, 0x28, 0x97, + 0x5A, 0x6A, 0x79, 0x52, 0xCE, 0xA9, 0x69, 0x63, 0x72, 0x3E, 0xB2, 0x75, 0x04, 0xAE, 0x8B, 0x11, + 0x26, 0xC8, 0x5D, 0xD1, 0xEF, 0x8C, 0xA6, 0xED, 0x49, 0x96, 0x6B, 0x5B, 0x7C, 0x43, 0x58, 0x5E, + 0xBD, 0xD8, 0x19, 0x69, 0x6D, 0xED, 0x29, 0x22, 0xAE, 0xED, 0xAE, 0xF4, 0xB6, 0x17, 0xA9, 0x53, + 0xE1, 0x1D, 0xE9, 0x6D, 0x2F, 0x94, 0x93, 0x57, 0x76, 0xE9, 0x39, 0x99, 0xC5, 0xF3, 0xA5, 0xD7, + 0x8B, 0x5F, 0x7B, 0x22, 0x42, 0x86, 0x4E, 0x9D, 0xB7, 0x7C, 0xC0, 0x5D, 0x4C, 0x76, 0xCF, 0x7A, + 0xB6, 0x67, 0xC8, 0xDC, 0x44, 0xF6, 0x58, 0x64, 0xBB, 0x6A, 0x2B, 0xCA, 0xDE, 0x0E, 0xFC, 0xD8, + 0x8F, 0x24, 0x82, 0xC8, 0x5D, 0x5A, 0x04, 0xF7, 0x0E, 0x5F, 0xCC, 0xDD, 0x65, 0xB4, 0x47, 0x6B, + 0x71, 0x5D, 0x39, 0x99, 0x0E, 0xA5, 0x41, 0x01, 0xA4, 0x9A, 0x4B, 0x0E, 0x85, 0x6E, 0x4A, 0x71, + 0x15, 0x39, 0x16, 0x0B, 0x07, 0x63, 0x5B, 0xDE, 0xDB, 0x35, 0xB8, 0xAA, 0x44, 0x5A, 0x0D, 0xD5, + 0xC0, 0xE9, 0xCB, 0xC9, 0x1C, 0xFC, 0x4D, 0x5A, 0x29, 0xD0, 0x12, 0x66, 0xC8, 0x75, 0xC9, 0x7A, + 0x73, 0xD3, 0xD9, 0x1D, 0x5E, 0xAF, 0x22, 0xA7, 0xA4, 0xCF, 0x14, 0xF4, 0x2B, 0x7D, 0x09, 0x39, + 0xDB, 0x76, 0xF9, 0xD7, 0x8F, 0xB5, 0xDA, 0x7F, 0xAE, 0x29, 0x7C, 0xA3, 0x06, 0x2B, 0x90, 0x3C, + 0xDE, 0xA0, 0x99, 0xF0, 0xCF, 0x5D, 0xCE, 0x19, 0x27, 0x27, 0x7F, 0x7B, 0x79, 0x73, 0xFE, 0x4B, + 0x74, 0xCA, 0xD1, 0xA7, 0x55, 0x9F, 0x73, 0x89, 0x99, 0xAC, 0xC7, 0x49, 0x27, 0xE0, 0x90, 0xA8, + 0x21, 0x29, 0xB9, 0x82, 0x30, 0xEA, 0x3E, 0x1A, 0xFE, 0x48, 0x66, 0x92, 0x05, 0x51, 0xCD, 0x8A, + 0x18, 0x05, 0xC9, 0x68, 0xA4, 0x46, 0xE8, 0xD2, 0x2F, 0xF9, 0xA5, 0x1C, 0x74, 0xF1, 0x4D, 0x5A, + 0xF8, 0xA8, 0x23, 0x3F, 0x61, 0xA0, 0xE6, 0xEF, 0xA8, 0x31, 0x9D, 0x49, 0x48, 0xA5, 0x5E, 0x5A, + 0x95, 0x71, 0x82, 0x9B, 0x3E, 0x04, 0x69, 0x8E, 0xF1, 0x9E, 0xE7, 0xAA, 0x37, 0x43, 0xBD, 0x94, + 0x62, 0xBF, 0x89, 0xFD, 0x3E, 0xAC, 0xC0, 0x65, 0x13, 0xF7, 0x65, 0x29, 0xB3, 0x46, 0x30, 0x65, + 0x2F, 0xA6, 0xEC, 0xFD, 0x59, 0xFE, 0x5D, 0x5A, 0x9B, 0x7D, 0xB6, 0x83, 0x12, 0x97, 0x69, 0xF9, + 0x17, 0x6B, 0xFB, 0xD4, 0x8B, 0xB7, 0x50, 0x37, 0x98, 0xB8, 0x63, 0xB7, 0x86, 0x7E, 0x00, 0x5D, + 0xDA, 0x7B, 0x4C, 0xBA, 0xB0, 0x94, 0xEF, 0x29, 0xFF, 0x1A, 0x6E, 0xF9, 0x4A, 0x5F, 0x36, 0xCB, + 0x49, 0xA6, 0x96, 0x0A, 0x5D, 0xA5, 0x76, 0xD8, 0x08, 0x41, 0x15, 0xC6, 0x1E, 0xAA, 0xD2, 0xC1, + 0xCA, 0x24, 0xE3, 0x9C, 0xED, 0x70, 0x2B, 0x71, 0xD1, 0x12, 0x42, 0x76, 0x93, 0xF4, 0xC5, 0x0A, + 0x7C, 0xE4, 0xCB, 0x3D, 0x16, 0x3A, 0x27, 0xFA, 0x08, 0xA5, 0x87, 0x7A, 0xD9, 0x09, 0x0C, 0x90, + 0x23, 0x51, 0xD7, 0xC9, 0x4D, 0xEC, 0xC9, 0x52, 0xA2, 0x63, 0x65, 0x31, 0xA6, 0x92, 0x98, 0x7B, + 0xC4, 0x53, 0xD2, 0x56, 0x54, 0x13, 0x4B, 0xF1, 0x16, 0x65, 0x27, 0x9D, 0x85, 0x39, 0xC9, 0xDE, + 0xE2, 0x3C, 0x44, 0x59, 0xAC, 0x8B, 0x5D, 0x64, 0x43, 0x8B, 0x75, 0xB1, 0xD7, 0x38, 0xEA, 0x2E, + 0x38, 0x0B, 0xCC, 0xC2, 0xA3, 0xBC, 0x08, 0x2E, 0xC8, 0x1F, 0x38, 0x30, 0x9B, 0x94, 0x14, 0x7B, + 0x89, 0x94, 0xAC, 0x2F, 0xC7, 0x1C, 0x56, 0x93, 0xD3, 0x9A, 0xF0, 0x54, 0x04, 0x5C, 0xF0, 0x6D, + 0xDB, 0x1F, 0x51, 0x06, 0xEA, 0x3B, 0x10, 0xC9, 0x2B, 0x73, 0xC7, 0x38, 0x47, 0x9C, 0xED, 0xAE, + 0x71, 0x74, 0x12, 0x3E, 0x63, 0x3D, 0xD7, 0xF6, 0x6D, 0xE0, 0x7F, 0x95, 0xBC, 0x85, 0x52, 0xBA, + 0xCC, 0x98, 0x79, 0x0D, 0xFE, 0x43, 0xFD, 0x5E, 0x6F, 0x2E, 0xEF, 0xA1, 0xAB, 0xF3, 0x79, 0x9C, + 0x87, 0x60, 0x34, 0xF6, 0x4F, 0x6C, 0x9E, 0xC6, 0xB0, 0x17, 0x5F, 0x06, 0x83, 0xF5, 0xF0, 0x1E, + 0x3A, 0x8D, 0xEA, 0xC3, 0x60, 0x32, 0x7C, 0xB4, 0xAC, 0x9C, 0x62, 0xAF, 0x86, 0xC6, 0x26, 0x3B, + 0x2F, 0x12, 0xF0, 0x32, 0x2C, 0xEE, 0x87, 0x58, 0x40, 0xC2, 0xC8, 0x16, 0x2C, 0xFF, 0xED, 0x76, + 0xEC, 0xA5, 0x2B, 0xFB, 0xB1, 0x79, 0x6E, 0x71, 0x77, 0xF8, 0xC4, 0xB6, 0x00, 0x28, 0x6F, 0x29, + 0x83, 0xBE, 0x1F, 0xB8, 0x56, 0xEC, 0x1D, 0x7B, 0x30, 0x88, 0xD1, 0x75, 0x04, 0xC0, 0xF5, 0x77, + 0x41, 0xBA, 0xE7, 0xDC, 0xA1, 0xF2, 0xDA, 0x22, 0x7A, 0x79, 0x59, 0xD5, 0xD9, 0x4E, 0x68, 0x98, + 0x58, 0xFC, 0x8E, 0x6E, 0xE0, 0x6F, 0xF1, 0x78, 0xD9, 0xB5, 0xDA, 0xC2, 0xC1, 0x97, 0x9D, 0x7E, + 0x52, 0xD6, 0x69, 0x97, 0x25, 0x19, 0xEE, 0x83, 0x3F, 0xFF, 0xC4, 0x90, 0x01, 0x9B, 0x32, 0xA8, + 0x32, 0x35, 0xA0, 0xF2, 0x0A, 0x9C, 0xEB, 0xF7, 0x2A, 0x66, 0x92, 0x14, 0x86, 0xE5, 0xC0, 0xC3, + 0x2C, 0x20, 0x15, 0xBC, 0x8B, 0xD6, 0x03, 0x6B, 0xC6, 0x5C, 0xF5, 0x02, 0x97, 0xA0, 0xD3, 0xD7, + 0x54, 0x73, 0x31, 0xE6, 0x3C, 0xDD, 0x59, 0xE3, 0xE8, 0x7A, 0xF2, 0x84, 0xD1, 0xA3, 0x4A, 0x9C, + 0x79, 0xA6, 0xBF, 0xD4, 0x29, 0xD7, 0xC0, 0x95, 0xAF, 0x39, 0x6C, 0xB5, 0x37, 0x0F, 0x63, 0xBE, + 0xE0, 0xDC, 0xDF, 0xB9, 0x44, 0xBB, 0x91, 0xB7, 0x1E, 0xCC, 0xF2, 0x4C, 0xDC, 0xFB, 0xCA, 0x4A, + 0x5D, 0x58, 0x0E, 0x24, 0xA0, 0x32, 0x5C, 0x86, 0xC5, 0xC6, 0xB4, 0x4A, 0xE4, 0x79, 0x80, 0xBC, + 0xBE, 0xF4, 0x90, 0xD0, 0x6D, 0x50, 0xE8, 0x30, 0xD6, 0x51, 0x1D, 0x0C, 0x10, 0xF2, 0x54, 0x4D, + 0x58, 0x64, 0x7D, 0x02, 0xF6, 0x68, 0x99, 0x4F, 0x13, 0x3A, 0x90, 0xC1, 0x35, 0xD4, 0xAB, 0xA8, + 0xDF, 0x25, 0x2F, 0x99, 0xE3, 0x92, 0x90, 0x00, 0xE5, 0x26, 0x24, 0x41, 0xAD, 0x9D, 0x35, 0x62, + 0x30, 0x19, 0xF9, 0xAB, 0xA6, 0x44, 0x37, 0x9E, 0x09, 0xD8, 0xC1, 0xD7, 0x78, 0x8B, 0xBA, 0x6C, + 0x3E, 0x19, 0x9B, 0xC9, 0x33, 0x95, 0xA7, 0x4E, 0x84, 0x26, 0xBA, 0x62, 0xD5, 0x13, 0x9F, 0x9C, + 0x11, 0x37, 0x1D, 0x74, 0xCA, 0xA1, 0x84, 0xBA, 0x3A, 0x77, 0x4C, 0xFB, 0x49, 0x38, 0xDD, 0xCB, + 0x2E, 0x0C, 0xCC, 0xE4, 0x0B, 0x24, 0x6E, 0xFB, 0x28, 0x83, 0x6B, 0x32, 0x03, 0xD2, 0x4C, 0x6E, + 0xAF, 0xB5, 0xE7, 0xAE, 0x53, 0x41, 0x86, 0xB4, 0x25, 0xB5, 0x94, 0xBB, 0xAC, 0x9A, 0x46, 0xC7, + 0xE5, 0xF7, 0x20, 0xDD, 0x84, 0xD1, 0x59, 0x35, 0x04, 0x07, 0xE6, 0x6A, 0x19, 0x72, 0xBF, 0xBD, + 0xC3, 0xD5, 0x9B, 0xD1, 0x27, 0xA1, 0x82, 0x72, 0x12, 0xB9, 0x21, 0x82, 0x94, 0x1B, 0xB5, 0x54, + 0x44, 0xE0, 0xE6, 0x26, 0xCA, 0x99, 0xF3, 0x3E, 0x2D, 0x89, 0x31, 0x85, 0xA9, 0x0F, 0x12, 0xAF, + 0xCF, 0x73, 0x7B, 0x36, 0xAF, 0x7E, 0xE9, 0x8D, 0x02, 0x1F, 0xCF, 0xFB, 0x1B, 0xFB, 0x74, 0x84, + 0x69, 0x60, 0x64, 0xE1, 0x0D, 0x39, 0x93, 0x53, 0xC9, 0x25, 0x05, 0xD1, 0xAD, 0xDE, 0x35, 0x3F, + 0x7F, 0x76, 0xA0, 0xA0, 0xC9, 0xEF, 0x45, 0x6A, 0x7F, 0x1F, 0x0B, 0x36, 0x21, 0x39, 0x0E, 0x0F, + 0x97, 0xEB, 0xB6, 0x5F, 0x0E, 0x68, 0xAB, 0xF4, 0xE7, 0x4F, 0x3D, 0x44, 0x48, 0x35, 0x03, 0x85, + 0x4C, 0x16, 0x3E, 0xC0, 0x5C, 0x57, 0x24, 0x88, 0x10, 0x94, 0x80, 0x64, 0x65, 0xD6, 0x75, 0x18, + 0xAD, 0xF0, 0x68, 0x41, 0xF1, 0x07, 0xDD, 0x46, 0x2D, 0xB4, 0xE4, 0x80, 0x04, 0x04, 0x5F, 0x93, + 0xE5, 0x1A, 0xC5, 0x76, 0x4A, 0xF7, 0x20, 0x6A, 0x00, 0x92, 0x34, 0x8F, 0xA3, 0xC6, 0x38, 0x45, + 0x52, 0x23, 0x2C, 0x71, 0xF6, 0x2C, 0x85, 0x19, 0x2C, 0x23, 0xAD, 0x64, 0x3E, 0x1A, 0x3C, 0xCB, + 0x41, 0x55, 0x40, 0x30, 0x8B, 0x9D, 0x5C, 0x78, 0x5B, 0x91, 0xBB, 0x6B, 0xE1, 0xE8, 0xCF, 0x70, + 0x70, 0x79, 0x11, 0x27, 0xC8, 0x39, 0xAF, 0x22, 0x82, 0xC8, 0x3A, 0xB2, 0xB2, 0x09, 0x25, 0x0C, + 0x8F, 0x99, 0xF8, 0x30, 0x2B, 0x6C, 0x2B, 0x2C, 0x71, 0xF9, 0x96, 0xEA, 0x7D, 0x28, 0xDB, 0xCA, + 0x81, 0xD2, 0xFA, 0xE1, 0x4E, 0xBA, 0x22, 0x1E, 0x5D, 0x74, 0xF4, 0xE5, 0xB7, 0x5F, 0xC2, 0x59, + 0xB8, 0x5A, 0xAD, 0xE6, 0x42, 0xD5, 0x7C, 0xDB, 0x9D, 0x64, 0xA2, 0x8F, 0x8A, 0x03, 0x8B, 0xE7, + 0xB1, 0x84, 0xF1, 0xCB, 0xD5, 0x69, 0xA6, 0xE7, 0x51, 0xE4, 0xAD, 0x51, 0x9F, 0x8E, 0x33, 0xBD, + 0x52, 0x41, 0x8B, 0xDC, 0xC5, 0xF4, 0xAF, 0x48, 0x7C, 0x74, 0x86, 0x80, 0x20, 0x89, 0xA1, 0x05, + 0x42, 0x2F, 0x76, 0xA3, 0xCA, 0x6E, 0x91, 0xF2, 0x2C, 0xAB, 0xF5, 0x90, 0x19, 0xC9, 0xF3, 0x6D, + 0xD8, 0x9E, 0xB0, 0x45, 0x8B, 0x1D, 0x43, 0x27, 0x22, 0x12, 0xC1, 0x42, 0x0F, 0x0F, 0x0C, 0x46, + 0x1E, 0xAB, 0x06, 0xE5, 0x28, 0xA2, 0x48, 0x86, 0xD4, 0x32, 0xC3, 0x93, 0x31, 0x96, 0x54, 0x52, + 0x78, 0x95, 0x2A, 0x54, 0x39, 0x8C, 0x6E, 0x54, 0xAD, 0xA8, 0x30, 0x98, 0xC6, 0x99, 0x45, 0xAB, + 0x28, 0x4C, 0x21, 0x61, 0xA2, 0x4C, 0x70, 0x54, 0x42, 0x61, 0x96, 0x32, 0x72, 0x0B, 0x45, 0x38, + 0x69, 0x53, 0xAD, 0x21, 0x6A, 0xBB, 0x5A, 0x51, 0x86, 0x73, 0x2C, 0x01, 0x6A, 0xF1, 0xE7, 0x2B, + 0xC9, 0xC0, 0xE5, 0x04, 0x96, 0x50, 0x90, 0xE1, 0x7C, 0xAA, 0xEB, 0x4A, 0x09, 0x21, 0xA7, 0x1A, + 0xCF, 0x0C, 0x59, 0x2E, 0xA5, 0xC7, 0x14, 0x78, 0xA7, 0x32, 0x47, 0x46, 0x6B, 0x7F, 0xEE, 0x6A, + 0x0D, 0x53, 0x8B, 0xAD, 0xB5, 0xDE, 0x5B, 0x4D, 0x87, 0x92, 0x9C, 0xE1, 0xD9, 0xE7, 0xD3, 0x1E, + 0x9C, 0x45, 0x21, 0x58, 0x03, 0x8C, 0x5A, 0xC0, 0x67, 0x4B, 0x3C, 0x86, 0xE2, 0x23, 0x4F, 0x38, + 0x83, 0x3E, 0xD2, 0x9C, 0x70, 0x1A, 0xC0, 0x0F, 0xB2, 0xCB, 0xD1, 0xAD, 0xE6, 0xB0, 0x8A, 0xEB, + 0x52, 0x11, 0x74, 0xE8, 0xC0, 0xC2, 0xCA, 0xBE, 0x38, 0xF7, 0x56, 0xA8, 0xC3, 0x20, 0xAF, 0xC2, + 0x87, 0xAA, 0x4C, 0x1A, 0x7E, 0xD9, 0x63, 0xC7, 0xBA, 0x8E, 0x07, 0xC3, 0x36, 0x3B, 0xBB, 0xE9, + 0x6F, 0xB3, 0x4F, 0xAA, 0xCF, 0x1F, 0xA5, 0x2D, 0xB9, 0x1F, 0xDC, 0x63, 0x4F, 0xD7, 0xAA, 0xF7, + 0x6D, 0x83, 0xAE, 0x39, 0xF2, 0x93, 0x56, 0xD0, 0xB2, 0x2F, 0x7B, 0x7D, 0x79, 0x10, 0x0B, 0xA4, + 0x0F, 0x81, 0xB6, 0x2C, 0x0D, 0x27, 0x44, 0xA3, 0xCB, 0x5E, 0x22, 0x99, 0xF5, 0xDE, 0x8C, 0xDE, + 0x72, 0x31, 0xB5, 0x29, 0xCF, 0xA0, 0x94, 0x20, 0xBA, 0x90, 0xF2, 0x20, 0xCF, 0xB8, 0x34, 0x94, + 0x22, 0x25, 0x64, 0x1A, 0x81, 0x5E, 0x52, 0x5E, 0xE9, 0xBD, 0x2A, 0x19, 0xA5, 0x71, 0xDE, 0x39, + 0xF9, 0xA4, 0x63, 0x9B, 0x5F, 0x2A, 0x42, 0x72, 0xF2, 0xFE, 0xEA, 0xB2, 0x48, 0xD7, 0x8A, 0xE5, + 0xC0, 0x47, 0x0A, 0xD0, 0x1C, 0xDE, 0x58, 0x67, 0xCC, 0xC6, 0x05, 0xBC, 0x22, 0x73, 0x2E, 0x32, + 0x17, 0x83, 0x68, 0x0A, 0x9B, 0xA1, 0xC1, 0x86, 0xA2, 0xB3, 0x3C, 0x11, 0x0B, 0x50, 0x5A, 0xBE, + 0xB5, 0xCE, 0x68, 0x1D, 0x2E, 0xE4, 0x15, 0xB5, 0x73, 0x51, 0xBB, 0x1C, 0x98, 0xA6, 0xD0, 0x5B, + 0x36, 0xDA, 0x50, 0x14, 0x17, 0x82, 0x5E, 0x01, 0x86, 0xC7, 0xA4, 0xC1, 0x75, 0xC6, 0x72, 0x4F, + 0x4C, 0x73, 0x0C, 0xD3, 0x7C, 0xC5, 0xF4, 0x7C, 0x4C, 0x97, 0xDB, 0x5E, 0x09, 0xD1, 0x45, 0x9B, + 0x35, 0x28, 0x4D, 0x93, 0x2D, 0xE6, 0xCF, 0x5B, 0x70, 0x3C, 0x5C, 0xE2, 0x8D, 0xEF, 0xA0, 0x4F, + 0x61, 0x01, 0x39, 0x44, 0xE8, 0x77, 0x73, 0xD7, 0x23, 0x1F, 0xC4, 0x3A, 0xAA, 0x85, 0x87, 0x08, + 0x3F, 0xD3, 0x79, 0xA4, 0x7F, 0x21, 0x0D, 0xB4, 0x3B, 0xDD, 0x4D, 0x2C, 0xCE, 0x5D, 0x06, 0x95, + 0xAB, 0x95, 0x6A, 0x99, 0xDE, 0xB1, 0x42, 0xBB, 0xFD, 0x54, 0x83, 0x25, 0x5F, 0x5A, 0x57, 0xB3, + 0xC6, 0xE1, 0x56, 0x3F, 0x97, 0x21, 0xCE, 0xF2, 0x9D, 0x25, 0xD8, 0xE0, 0x60, 0x45, 0x73, 0x99, + 0xDF, 0x26, 0xED, 0xE6, 0xB4, 0xBC, 0x4D, 0x40, 0x29, 0x8D, 0x6E, 0xD2, 0xE6, 0x86, 0xCB, 0x7C, + 0x6E, 0x73, 0xDB, 0x64, 0x71, 0xB5, 0x5A, 0xDA, 0xAA, 0x30, 0x3A, 0x0B, 0xB1, 0xDF, 0x34, 0xCF, + 0xBF, 0x3B, 0x00, 0x3E, 0xAB, 0x88, 0xD1, 0xE1, 0xAB, 0x2C, 0x7C, 0xF7, 0x70, 0x45, 0xEE, 0x01, + 0xE2, 0x6A, 0xDF, 0xD2, 0xC9, 0x03, 0xDC, 0x0B, 0x73, 0xB0, 0x19, 0xE3, 0x60, 0x3C, 0x09, 0x7E, + 0x0D, 0x73, 0x96, 0x7B, 0xC2, 0x4A, 0x8E, 0x7E, 0xBA, 0x61, 0x0A, 0xC0, 0x16, 0x3B, 0x6F, 0x0D, + 0x5B, 0xF2, 0x2E, 0x55, 0xF0, 0x4D, 0xB2, 0xEB, 0x61, 0x60, 0xFD, 0x3E, 0xDE, 0xC2, 0x78, 0x93, + 0x9B, 0x1A, 0xEC, 0x0A, 0x33, 0x3B, 0xFD, 0xAF, 0x7D, 0xF6, 0x91, 0xED, 0xEF, 0x7A, 0xAF, 0xAC, + 0x55, 0x92, 0x4A, 0x02, 0x47, 0x0A, 0x59, 0xEB, 0x54, 0x83, 0xFA, 0x59, 0x6B, 0xED, 0x24, 0xE0, + 0x72, 0xCD, 0xF0, 0xE2, 0x21, 0xAE, 0x19, 0xF8, 0x1F, 0xBE, 0xF7, 0x8C, 0xB8, 0xEF, 0x84, 0x73, + 0x08, 0xEB, 0xC3, 0xC9, 0xAC, 0xAA, 0x9A, 0x69, 0x6B, 0xDF, 0xF2, 0x90, 0xBD, 0xD9, 0x51, 0x26, + 0xE8, 0x3E, 0xE9, 0x85, 0xF0, 0x1D, 0xBF, 0xFB, 0xC8, 0xFE, 0xBD, 0x1D, 0xBC, 0xA2, 0x7C, 0x84, + 0xC1, 0x11, 0x4E, 0x94, 0xC2, 0xF7, 0xF0, 0xED, 0xF5, 0x47, 0xF6, 0x5B, 0xDB, 0xF6, 0xCF, 0xB8, + 0x59, 0x68, 0xC6, 0xC0, 0xF7, 0x18, 0xBD, 0xF8, 0x8C, 0xD8, 0xEE, 0xDB, 0x74, 0xD9, 0x6D, 0x07, + 0x96, 0xDE, 0xF4, 0x5D, 0xC3, 0x01, 0xB4, 0x46, 0xF7, 0x76, 0x19, 0x75, 0xE1, 0x46, 0xA9, 0x54, + 0x08, 0xFB, 0xD1, 0xCD, 0x2B, 0x88, 0x7B, 0xA3, 0x2B, 0xAF, 0xD8, 0x2C, 0xF1, 0x73, 0xB2, 0xE9, + 0x65, 0xB0, 0x39, 0x7A, 0x7B, 0x43, 0xB0, 0x19, 0x44, 0x40, 0x51, 0xD2, 0xA6, 0x14, 0x4A, 0x47, + 0x6F, 0xAF, 0x81, 0x04, 0xC3, 0x11, 0x98, 0x80, 0xC7, 0x26, 0xC8, 0xA6, 0x0F, 0xBC, 0x2C, 0x5E, + 0xB7, 0x15, 0xE5, 0x15, 0xB5, 0x13, 0xC8, 0x3A, 0xC1, 0x80, 0xD2, 0xF8, 0x1D, 0x35, 0xD9, 0x00, + 0x24, 0x0F, 0xF1, 0xE1, 0x52, 0x2F, 0xC2, 0xF0, 0x08, 0x73, 0x2E, 0xCF, 0x56, 0x8A, 0xDE, 0x1A, + 0xA6, 0x70, 0x27, 0xE7, 0x24, 0x63, 0x60, 0x48, 0x24, 0x9F, 0x42, 0xE3, 0x18, 0x02, 0x7F, 0xEA, + 0xF5, 0x63, 0xD9, 0x54, 0x31, 0x6B, 0xC1, 0x48, 0x75, 0x55, 0xAD, 0x20, 0x76, 0xE8, 0xE5, 0xE0, + 0x75, 0x81, 0x55, 0x6E, 0x6A, 0xCB, 0x4B, 0xA1, 0xF4, 0xE4, 0xFD, 0xB5, 0x32, 0x65, 0x50, 0xC2, + 0xE0, 0x6B, 0xD5, 0x52, 0xD1, 0x11, 0xB5, 0x16, 0x63, 0x86, 0x6D, 0x69, 0x51, 0xA1, 0x1A, 0xEC, + 0xFD, 0xCA, 0xF0, 0xA8, 0xF8, 0x88, 0xB8, 0xD2, 0x37, 0xB9, 0x1C, 0xAC, 0x31, 0x5F, 0xE5, 0xD9, + 0x0C, 0x7B, 0xC6, 0xB4, 0xD9, 0x23, 0xC3, 0xCC, 0x71, 0x11, 0x1F, 0x3F, 0xD5, 0xD0, 0x31, 0xD3, + 0x7F, 0x86, 0xE1, 0x23, 0xD1, 0x53, 0x39, 0x53, 0x47, 0x02, 0xD4, 0xD2, 0xCC, 0x11, 0x03, 0xC8, + 0xB3, 0x9B, 0x3B, 0xE2, 0x4B, 0x5A, 0xD8, 0xE0, 0x91, 0x2C, 0xB8, 0x94, 0x8E, 0xD4, 0xFD, 0x33, + 0xD6, 0x37, 0xFE, 0xC4, 0xA0, 0x53, 0xE9, 0xAA, 0xAB, 0xE3, 0xC7, 0xEC, 0x1C, 0xB9, 0x0A, 0xBB, + 0x3E, 0x41, 0x0A, 0x61, 0x3B, 0xEC, 0xC2, 0xE5, 0xF1, 0x76, 0xF8, 0xB1, 0xEF, 0x00, 0x6F, 0xCC, + 0x66, 0x88, 0x45, 0x9D, 0x96, 0x37, 0x67, 0x53, 0xC9, 0xC9, 0xE9, 0xDD, 0xBB, 0xC3, 0x87, 0x59, + 0xA7, 0x85, 0xEF, 0x4A, 0x78, 0xBC, 0x31, 0xF9, 0xC0, 0x7F, 0x93, 0xC3, 0x2F, 0xFC, 0xD1, 0x11, + 0xE6, 0x09, 0xFE, 0xB0, 0x03, 0x7F, 0xE4, 0xBE, 0x85, 0x90, 0x2A, 0x7A, 0x4B, 0x3F, 0x4A, 0x30, + 0xB5, 0x89, 0xE3, 0x54, 0x38, 0xF7, 0x3E, 0xC5, 0xBC, 0x1E, 0x9B, 0x69, 0x01, 0xE9, 0xD2, 0xE9, + 0xAA, 0xF0, 0x5A, 0x26, 0xF2, 0xB4, 0x8A, 0x03, 0x83, 0xC8, 0x11, 0xB3, 0xE7, 0xC2, 0x14, 0xB3, + 0x7C, 0xAA, 0x76, 0x7C, 0x77, 0x71, 0x70, 0xE9, 0x94, 0x38, 0xF9, 0xFC, 0x3B, 0x39, 0xCC, 0xFE, + 0x1E, 0xBA, 0x0A, 0xFD, 0xAE, 0xB4, 0xFC, 0xEF, 0x7E, 0xF6, 0xD8, 0x61, 0xDB, 0x3D, 0xDA, 0xFB, + 0xA2, 0xB7, 0x32, 0x80, 0x28, 0x82, 0xA0, 0x71, 0xD5, 0x97, 0x67, 0x02, 0xA4, 0xD9, 0x53, 0x29, + 0x06, 0x63, 0x06, 0xFC, 0x59, 0x9C, 0x41, 0xE4, 0x38, 0xD9, 0x4A, 0x88, 0xAE, 0x10, 0xD6, 0x9D, + 0x4E, 0x5B, 0xE9, 0xB6, 0x7F, 0x57, 0x3A, 0x4A, 0x5B, 0xD9, 0x17, 0x69, 0xAB, 0x8B, 0x00, 0x09, + 0x4D, 0xD8, 0x5F, 0x97, 0x05, 0xF0, 0x99, 0xF9, 0xBC, 0x68, 0x98, 0x77, 0x94, 0xF7, 0xE5, 0x60, + 0xBE, 0xAB, 0x1C, 0xAC, 0x02, 0xE6, 0x72, 0x3E, 0x6B, 0x09, 0x73, 0x78, 0x8A, 0xCC, 0xF9, 0x28, + 0x83, 0x93, 0x17, 0x6E, 0x92, 0x38, 0xC3, 0x0A, 0xB6, 0x29, 0xFF, 0x2A, 0xA7, 0x31, 0x91, 0x8A, + 0x62, 0x0B, 0x05, 0x15, 0x9E, 0xFB, 0xC4, 0x26, 0xC5, 0x5F, 0xC5, 0xD9, 0xC5, 0x4B, 0xEC, 0x63, + 0x1D, 0x6F, 0xCC, 0xB3, 0x16, 0x10, 0x4B, 0xB0, 0x9E, 0x19, 0xAD, 0x46, 0xFE, 0xBD, 0xC8, 0x7A, + 0x0A, 0xB6, 0x32, 0xFD, 0x92, 0x39, 0xDF, 0x65, 0xB9, 0x5C, 0x05, 0xBE, 0xCC, 0xEA, 0x7B, 0xF8, + 0x77, 0x7B, 0x72, 0x76, 0xB6, 0xE3, 0xE5, 0xF6, 0x44, 0x65, 0x3A, 0x14, 0xA0, 0x72, 0xCA, 0xEC, + 0x89, 0x82, 0x6F, 0x3F, 0x95, 0x56, 0x62, 0xD2, 0x2B, 0x34, 0x3A, 0x29, 0x35, 0x19, 0x95, 0x58, + 0x49, 0xC6, 0xC2, 0x92, 0x8B, 0xD9, 0xD5, 0x0F, 0xA5, 0x38, 0x25, 0x16, 0x83, 0x25, 0xD9, 0x02, + 0x2F, 0xAD, 0x40, 0x7A, 0xC5, 0xC8, 0x05, 0x4B, 0x9F, 0xD2, 0x2B, 0x26, 0x6F, 0x8E, 0xDC, 0x74, + 0xF9, 0x74, 0x56, 0xF1, 0x4E, 0x2B, 0xE2, 0x39, 0xA5, 0xDB, 0x61, 0xE4, 0x9D, 0x07, 0x02, 0x32, + 0xFC, 0xDD, 0x26, 0xBD, 0xBB, 0xDD, 0x09, 0x1F, 0x29, 0x59, 0x41, 0x91, 0x39, 0x45, 0x06, 0xD4, + 0x07, 0x7E, 0xE2, 0x5B, 0x33, 0x5A, 0x8A, 0x48, 0x2E, 0x96, 0x24, 0x03, 0x7C, 0x57, 0x5C, 0x14, + 0x52, 0xC1, 0x00, 0xF8, 0x94, 0xBA, 0xFF, 0x53, 0xB1, 0x05, 0x33, 0x8A, 0x32, 0x76, 0x83, 0x4A, + 0x71, 0x3B, 0x52, 0x8A, 0xB3, 0x09, 0x28, 0x94, 0x7C, 0xC5, 0x2C, 0xAB, 0x6A, 0x94, 0xC9, 0xD6, + 0x61, 0xE8, 0x4A, 0xD9, 0x80, 0x96, 0xB4, 0x60, 0x96, 0x12, 0xDB, 0x23, 0xB6, 0xA4, 0xD2, 0x26, + 0xF0, 0xEF, 0x86, 0x9F, 0xB6, 0x09, 0x76, 0xE0, 0xE3, 0x14, 0x53, 0x37, 0x03, 0xDB, 0x4C, 0x36, + 0xE3, 0x1C, 0x3E, 0xA1, 0x83, 0x7C, 0xEA, 0x86, 0x50, 0x48, 0xD0, 0xEC, 0x3E, 0x60, 0x66, 0x8B, + 0x07, 0x69, 0xAB, 0x88, 0x46, 0xA8, 0xB8, 0x31, 0x72, 0xE6, 0x69, 0x1B, 0x53, 0x10, 0x29, 0xE4, + 0x1C, 0xFD, 0x93, 0x75, 0xEF, 0x39, 0x7F, 0x29, 0x02, 0x7B, 0xEC, 0x63, 0xFC, 0x4F, 0x4F, 0x73, + 0x0D, 0xC7, 0x67, 0x9E, 0xAB, 0xC1, 0xFE, 0xBA, 0xDA, 0x0E, 0x46, 0xAA, 0xB5, 0xFE, 0x4E, 0xA3, + 0x89, 0xAF, 0xB2, 0x9A, 0x4C, 0x7A, 0x86, 0x15, 0x7B, 0x18, 0x29, 0x65, 0x63, 0x15, 0x1E, 0x8F, + 0x7D, 0x64, 0xBA, 0xAD, 0x05, 0x68, 0x74, 0x6A, 0xFD, 0x11, 0x70, 0xF7, 0x49, 0x28, 0x0D, 0xB6, + 0x0B, 0x6A, 0xC3, 0xD6, 0x9B, 0x96, 0xEF, 0xBF, 0x79, 0x1B, 0xB5, 0x0C, 0xDB, 0xB4, 0xE0, 0x78, + 0x3F, 0x57, 0xB5, 0xD1, 0x96, 0xCF, 0x3E, 0x1E, 0xB1, 0x7F, 0x4D, 0x2C, 0x03, 0x93, 0x91, 0x62, + 0x32, 0x02, 0xCF, 0x77, 0x55, 0xA7, 0x75, 0x27, 0x5A, 0x6C, 0xF9, 0x93, 0x4E, 0xFE, 0xED, 0xAD, + 0x9C, 0x61, 0x38, 0x2F, 0x00, 0x36, 0x68, 0x9A, 0xC0, 0x37, 0x3E, 0xEC, 0x8C, 0xFC, 0xB1, 0x79, + 0xF4, 0xFF, 0x01, 0x4A, 0x32, 0x29, 0x6B, 0x23, 0x58, 0x00 }; ///index_html //Content of bootstrap.bundle.min.jss with gzip compression From 0909cb7db9c8b0f125f2b09e7590eb94bda88df5 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 13 Jan 2025 11:07:48 -0700 Subject: [PATCH 113/276] Rename networkHasInternet --- Firmware/RTK_Everywhere/Cellular.ino | 4 +- Firmware/RTK_Everywhere/Developer.ino | 8 ++-- Firmware/RTK_Everywhere/Display.ino | 30 +++++++-------- Firmware/RTK_Everywhere/ESPNOW.ino | 6 +-- Firmware/RTK_Everywhere/Ethernet.ino | 4 +- Firmware/RTK_Everywhere/NTP.ino | 2 +- Firmware/RTK_Everywhere/Network.ino | 48 ++++++++++++------------ Firmware/RTK_Everywhere/TcpClient.ino | 2 +- Firmware/RTK_Everywhere/menuFirmware.ino | 2 +- Firmware/RTK_Everywhere/menuMain.ino | 2 +- 10 files changed, 54 insertions(+), 54 deletions(-) diff --git a/Firmware/RTK_Everywhere/Cellular.ino b/Firmware/RTK_Everywhere/Cellular.ino index fa7b12205..45014d02a 100644 --- a/Firmware/RTK_Everywhere/Cellular.ino +++ b/Firmware/RTK_Everywhere/Cellular.ino @@ -84,7 +84,7 @@ void cellularEvent(arduino_event_id_t event) String module; // Take the network offline if necessary - if (networkIsInterfaceOnline(NETWORK_CELLULAR) && (event != ARDUINO_EVENT_ETH_GOT_IP) && + if (networkInterfaceHasInternet(NETWORK_CELLULAR) && (event != ARDUINO_EVENT_ETH_GOT_IP) && (event != ARDUINO_EVENT_ETH_GOT_IP6) && (event != ARDUINO_EVENT_PPP_CONNECTED)) { networkMarkOffline(NETWORK_CELLULAR); @@ -108,7 +108,7 @@ void cellularEvent(arduino_event_id_t event) case ARDUINO_EVENT_PPP_CONNECTED: systemPrintln("Cellular Connected"); - networkMarkOnline(NETWORK_CELLULAR); + networkMarkHasInternet(NETWORK_CELLULAR); break; case ARDUINO_EVENT_PPP_DISCONNECTED: diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index d88965634..9633bb8d1 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -43,11 +43,11 @@ const uint8_t * networkGetMacAddress() #endif return zero; } -bool networkIsOnline() {return false;} -bool networkIsOnline(NetIndex_t index) {return false;} -bool networkIsInterfaceOnline(NetIndex_t index) {return false;} +bool networkHasInternet() {return false;} +bool networkHasInternet(NetIndex_t index) {return false;} +bool networkInterfaceHasInternet(NetIndex_t index) {return false;} void networkMarkOffline(NetIndex_t index) {} -void networkMarkOnline(NetIndex_t index) {} +void networkMarkHasInternet(NetIndex_t index) {} void networkUpdate() {} void networkVerifyTables() {} uint16_t networkGetConsumerTypes() {return(0);} diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index e1c83ab32..a56a272ba 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -359,7 +359,7 @@ void displayUpdate() iconPropertyBlinking prop; prop.icon = EthernetIconProperties.iconDisplay[present.display_type]; #ifdef COMPILE_ETHERNET - if (networkIsInterfaceOnline(NETWORK_ETHERNET)) + if (networkInterfaceHasInternet(NETWORK_ETHERNET)) prop.duty = 0b11111111; else #endif // COMPILE_ETHERNET @@ -381,7 +381,7 @@ void displayUpdate() iconPropertyBlinking prop; prop.icon = EthernetIconProperties.iconDisplay[present.display_type]; #ifdef COMPILE_ETHERNET - if (networkIsInterfaceOnline(NETWORK_ETHERNET)) + if (networkInterfaceHasInternet(NETWORK_ETHERNET)) prop.duty = 0b11111111; else #endif // COMPILE_ETHERNET @@ -405,7 +405,7 @@ void displayUpdate() displayWebConfigNotStarted(); // Display 'Web Config' break; case (STATE_WEB_CONFIG): - if (networkIsInterfaceOnline(NETWORK_ETHERNET)) + if (networkInterfaceHasInternet(NETWORK_ETHERNET)) displayConfigViaEthernet(); else { @@ -822,24 +822,24 @@ void setRadioIcons(std::vector *iconList) usbSerialIncomingRtcm = false; } - bool networkOnline = false; + bool networkHasInternet = false; #ifdef COMPILE_ETHERNET - if (networkIsInterfaceOnline(NETWORK_ETHERNET)) - networkOnline = true; + if (networkInterfaceHasInternet(NETWORK_ETHERNET)) + networkHasInternet = true; #endif // COMPILE_ETHERNET #ifdef COMPILE_WIFI - if (networkIsInterfaceOnline(NETWORK_WIFI)) - networkOnline = true; + if (networkInterfaceHasInternet(NETWORK_WIFI)) + networkHasInternet = true; #endif // COMPILE_WIFI #ifdef COMPILE_CELLULAR - if (networkIsInterfaceOnline(NETWORK_CELLULAR)) - networkOnline = true; + if (networkInterfaceHasInternet(NETWORK_CELLULAR)) + networkHasInternet = true; #endif // COMPILE_CELLULAR - if (networkOnline) + if (networkHasInternet) { if (netIncomingRTCM == true) // Download : Columns 74 - 81 { @@ -1099,7 +1099,7 @@ void setESPNowIcon_TwoRadios(std::vector *iconList) void setWiFiIcon_TwoRadios(std::vector *iconList) { #ifdef COMPILE_WIFI - if (networkIsInterfaceOnline(NETWORK_WIFI)) + if (networkInterfaceHasInternet(NETWORK_WIFI)) { if (netIncomingRTCM || netOutgoingRTCM || mqttClientDataReceived) { @@ -1169,7 +1169,7 @@ void setWiFiIcon_TwoRadios(std::vector *iconList) void setWiFiIcon_ThreeRadios(std::vector *iconList) { #ifdef COMPILE_WIFI - if (networkIsInterfaceOnline(NETWORK_WIFI)) + if (networkInterfaceHasInternet(NETWORK_WIFI)) { if (netIncomingRTCM || netOutgoingRTCM || mqttClientDataReceived) { @@ -1248,7 +1248,7 @@ void setWiFiIcon(std::vector *iconList) icon.icon.yPos = 0; #ifdef COMPILE_WIFI - if (networkIsInterfaceOnline(NETWORK_WIFI)) + if (networkInterfaceHasInternet(NETWORK_WIFI)) icon.duty = 0b11111111; else #endif // COMPILE_WIFI @@ -1534,7 +1534,7 @@ void displayBatteryVsEthernet(std::vector *iconList) #ifdef COMPILE_ETHERNET else // if (present.ethernet_ws5500 == true) { - if (!networkIsInterfaceOnline(NETWORK_ETHERNET)) + if (!networkInterfaceHasInternet(NETWORK_ETHERNET)) return; // Only display the Ethernet icon if we are successfully connected (no blinking) iconPropertyBlinking prop; diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index 267efd7ce..be3876c4f 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -166,7 +166,7 @@ void espnowStart() if (response != ESP_OK) systemPrintf("espnowStart: Failed to get protocols: %s\r\n", esp_err_to_name(response)); - if ((!wifiIsRunning()) && espnowState == ESPNOW_OFF) + if ((wifiIsRunning() == false) && espnowState == ESPNOW_OFF) { // Radio is off, turn it on if (protocols != (WIFI_PROTOCOL_LR)) @@ -362,9 +362,9 @@ void espnowStop() espnowSetState(ESPNOW_OFF); - if (!wifiIsRunning()) + if (wifiIsRunning() == false) { - // ESP Now was the only thing using the radio so turn WiFi radio off entirely + // ESP-NOW was the only thing using the radio so turn WiFi radio off entirely WiFi.mode(WIFI_OFF); if (settings.debugEspNow == true) diff --git a/Firmware/RTK_Everywhere/Ethernet.ino b/Firmware/RTK_Everywhere/Ethernet.ino index e53bc16ff..aec52d685 100644 --- a/Firmware/RTK_Everywhere/Ethernet.ino +++ b/Firmware/RTK_Everywhere/Ethernet.ino @@ -174,7 +174,7 @@ void ethernetEvent(arduino_event_id_t event, arduino_event_info_t info) if (settings.enablePrintEthernetDiag && (!inMainMenu)) systemPrintf("ETH Got IP: '%s'\r\n", ETH.localIP().toString().c_str()); - networkMarkOnline((NetIndex_t)NETWORK_ETHERNET); + networkMarkHasInternet((NetIndex_t)NETWORK_ETHERNET); if (settings.ethernetDHCP) paintEthernetConnected(); @@ -200,7 +200,7 @@ void ethernetEvent(arduino_event_id_t event, arduino_event_info_t info) } // Take the network offline if necessary - if (networkIsInterfaceOnline(NETWORK_ETHERNET) && (event != ARDUINO_EVENT_ETH_GOT_IP)) + if (networkInterfaceHasInternet(NETWORK_ETHERNET) && (event != ARDUINO_EVENT_ETH_GOT_IP)) { networkMarkOffline((NetIndex_t)NETWORK_ETHERNET); } diff --git a/Firmware/RTK_Everywhere/NTP.ino b/Firmware/RTK_Everywhere/NTP.ino index b2794b583..95b7c0192 100644 --- a/Firmware/RTK_Everywhere/NTP.ino +++ b/Firmware/RTK_Everywhere/NTP.ino @@ -791,7 +791,7 @@ void ntpServerUpdate() if (EQ_RTK_MODE(ntpServerMode)) { // The NTP server only works over Ethernet - if (networkIsInterfaceOnline(NETWORK_ETHERNET)) + if (networkInterfaceHasInternet(NETWORK_ETHERNET)) { ntpServerPriority = NETWORK_OFFLINE; ntpServerSetState(NTP_STATE_NETWORK_CONNECTED); diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 4c54ee982..433ca9c28 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -115,7 +115,7 @@ NetPriority_t networkPriority = NETWORK_OFFLINE; // Index into networkPriorityTa // The following entries have one bit per interface // Each bit represents an index into the networkInterfaceTable -NetMask_t networkOnline; // Track the online networks +NetMask_t networkHasInternet_bm; // Track the online networks NetMask_t networkSeqStarting; // Track the starting sequences NetMask_t networkSeqStopping; // Track the stopping sequences @@ -550,11 +550,11 @@ const uint8_t *networkGetMacAddress() return btMACAddress; #endif // COMPILE_BT #ifdef COMPILE_WIFI - if (networkIsInterfaceOnline(NETWORK_WIFI)) + if (networkInterfaceHasInternet(NETWORK_WIFI)) return wifiMACAddress; #endif // COMPILE_WIFI #ifdef COMPILE_ETHERNET - if (networkIsInterfaceOnline(NETWORK_ETHERNET)) + if (networkInterfaceHasInternet(NETWORK_ETHERNET)) return ethernetMACAddress; #endif // COMPILE_ETHERNET return zero; @@ -591,24 +591,24 @@ bool networkIsConnected(NetPriority_t *clientPriority) { // If the client is using the highest priority network and that // network is still available then continue as normal - if (networkOnline && (*clientPriority == networkPriority)) + if (networkHasInternet_bm && (*clientPriority == networkPriority)) return true; // The network has changed, notify the client of the change - *clientPriority = networkPriority; return false; + *clientPriority = networkPriority; } //---------------------------------------- // Determine if the network interface is online //---------------------------------------- -bool networkIsInterfaceOnline(NetIndex_t index) +bool networkInterfaceHasInternet(NetIndex_t index) { // Validate the index networkValidateIndex(index); // Return the network interface state - return (networkOnline & (1 << index)) ? true : false; + return (networkHasInternet_bm & (1 << index)) ? true : false; } //---------------------------------------- @@ -626,10 +626,10 @@ bool networkIsInterfaceStarted(NetIndex_t index) //---------------------------------------- // Determine if any network interface is online //---------------------------------------- -bool networkIsOnline() +bool networkHasInternet() { // Return the network state - return networkOnline ? true : false; + return networkHasInternet_bm ? true : false; } //---------------------------------------- @@ -658,12 +658,12 @@ void networkMarkOffline(NetIndex_t index) // Check for network offline bitMask = 1 << index; - if (!(networkOnline & bitMask)) + if (!(networkHasInternet_bm & bitMask)) // Already offline, nothing to do return; // Mark this network as offline - networkOnline &= ~bitMask; + networkHasInternet_bm &= ~bitMask; // Disable mDNS if necessary networkMulticastDNSStop(index); @@ -686,7 +686,7 @@ void networkMarkOffline(NetIndex_t index) // Is the network online? index = networkIndexTable[priority]; bitMask = 1 << index; - if (networkOnline & bitMask) + if (networkHasInternet_bm & bitMask) { // Successfully found an online network networkMulticastDNSStart(index); @@ -716,7 +716,7 @@ void networkMarkOffline(NetIndex_t index) //---------------------------------------- // Mark network online //---------------------------------------- -void networkMarkOnline(NetIndex_t index) +void networkMarkHasInternet(NetIndex_t index) { NetMask_t bitMask; NetIndex_t previousIndex; @@ -729,12 +729,12 @@ void networkMarkOnline(NetIndex_t index) // Check for network online bitMask = 1 << index; previousIndex = index; - if (networkOnline & bitMask) + if (networkHasInternet_bm & bitMask) // Already online, nothing to do return; // Mark this network as online - networkOnline |= bitMask; + networkHasInternet_bm |= bitMask; // Raise the network priority if necessary previousPriority = networkPriority; @@ -882,7 +882,7 @@ void networkPrintStatus(uint8_t priority) bitMask = (1 << index); highestPriority = (networkPriority == priority) ? '*' : ' '; status = "Starting"; - if (networkOnline & bitMask) + if (networkHasInternet_bm & bitMask) status = "Online"; else if (networkInterfaceTable[index].boot) { @@ -1300,7 +1300,7 @@ void networkStartDelayed(NetIndex_t index, uintptr_t parameter, bool debug) // Only lower priority networks running, start this network interface name = networkGetNameByIndex(index); currentInterfaceName = networkGetCurrentInterfaceName(); - if ((networkOnline & highPriorityBitMask) == 0) + if ((networkHasInternet_bm & highPriorityBitMask) == 0) { if (debug) systemPrintf("%s online, Starting %s\r\n", currentInterfaceName, name); @@ -1406,7 +1406,7 @@ void networkUpdate() // restartWiFi is used by the settings interface to indicate SSIDs or else has changed // Stop WiFi to allow restart with new settings - if (restartWiFi == true && networkIsInterfaceOnline(NETWORK_WIFI)) + if (restartWiFi == true && networkInterfaceHasInternet(NETWORK_WIFI)) { if (settings.debugNetworkLayer) systemPrintln("WiFi settings changed, restarting WiFi"); @@ -1418,9 +1418,9 @@ void networkUpdate() } // If there are no consumers, but the network is online, shut down all networks - if (consumerCount == 0 && networkIsOnline() == true) + if (consumerCount == 0 && networkHasInternet() == true) { - if (settings.debugNetworkLayer && networkIsInterfaceOnline(NETWORK_ETHERNET) == + if (settings.debugNetworkLayer && networkInterfaceHasInternet(NETWORK_ETHERNET) == false) // Ethernet is never stopped, so only print for other networks systemPrintln("Stopping all networks because there are no consumers"); @@ -1446,18 +1446,18 @@ void networkUpdate() // Allow consumers to start networks // Each network is expected to shut itself down if it is unavailable or of a lower priority // so that a networkStart() succeeds. - if (consumerCount > 0 && networkIsOnline() == false) + if (consumerCount > 0 && networkHasInternet() == false) { // Attempt to start any network that is needed, in the order Ethernet/WiFi/Cellular if (consumerTypes && (1 << NETCONSUMER_ETHERNET)) networkStart(NETWORK_ETHERNET, settings.debugNetworkLayer); - if ((networkIsOnline() == false) && (consumerTypes && (1 << NETCONSUMER_WIFI_STA)) || + if ((networkHasInternet() == false) && (consumerTypes && (1 << NETCONSUMER_WIFI_STA)) || (consumerTypes && (1 << NETCONSUMER_WIFI_AP))) networkStart(NETWORK_WIFI, settings.debugNetworkLayer); - if ((networkIsOnline() == false) && (consumerTypes && (1 << NETCONSUMER_CELLULAR))) + if ((networkHasInternet() == false) && (consumerTypes && (1 << NETCONSUMER_CELLULAR))) networkStart(NETWORK_CELLULAR, settings.debugNetworkLayer); } @@ -1731,7 +1731,7 @@ uint8_t networkConsumersOnline() consumerId |= (1 << 2); } - // Network needed for TCP Server + // Network needed for TCP Server - May use WiFi AP or WiFi STA if (online.tcpServer) { consumerCountOnline++; diff --git a/Firmware/RTK_Everywhere/TcpClient.ino b/Firmware/RTK_Everywhere/TcpClient.ino index 20f7630b9..2b7b774a3 100644 --- a/Firmware/RTK_Everywhere/TcpClient.ino +++ b/Firmware/RTK_Everywhere/TcpClient.ino @@ -433,7 +433,7 @@ void tcpClientUpdate() { #ifdef COMPILE_WIFI // Determine if WiFi is required - if ((!strlen(settings.tcpClientHost)) && (!networkIsInterfaceOnline(NETWORK_WIFI))) + if ((!strlen(settings.tcpClientHost)) && (!networkInterfaceHasInternet(NETWORK_WIFI))) { // Wrong network type, WiFi is required but another network is being used if ((millis() - timer) >= (15 * 1000)) diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index c080520fe..b99a4d330 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -446,7 +446,7 @@ bool otaCheckVersion(char *versionAvailable, uint8_t versionAvailableLength) bool gotVersion = false; #ifdef COMPILE_NETWORK - if (networkIsOnline() == false) + if (networkHasInternet() == false) { systemPrintln("Error: Network not available!"); return (false); diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 362094ffd..8efcead3c 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -638,7 +638,7 @@ void menuRadio() } else { - systemPrintln("ESP-NOW channel can't be modified while WiFi is connected."); + systemPrintln("ESP-NOW channel can't be modified while WiFi is active."); } } else if (settings.enableEspNow == true && incoming == 5 && settings.debugEspNow == true) From 643cef0bf0528af8832b273336c3a3646697729b Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 13 Jan 2025 11:08:37 -0700 Subject: [PATCH 114/276] Add wifiApIsRunning --- Firmware/RTK_Everywhere/Developer.ino | 3 +- Firmware/RTK_Everywhere/WiFi.ino | 127 +++++++++++++++----------- 2 files changed, 77 insertions(+), 53 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 9633bb8d1..180b6e80d 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -170,7 +170,8 @@ void sendStringToWebsocket(const char* stringToSend) {} void menuWiFi() {systemPrintln("**WiFi not compiled**");} bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) {return false;} int wifiNetworkCount() {return 0;} -bool wifiIsRunning() {return false;} +bool wifiStationIsRunning() {return false;} +bool wifiApIsRunning() {return false;} uint32_t wifiGetStartTimeout() {return 0;} #define WIFI_STOP() {} diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 47e66b2aa..77ad99953 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -55,7 +55,8 @@ static unsigned long wifiDisplayTimer; // DNS server for Captive Portal static DNSServer dnsServer; -static bool wifiRunning; +static bool wifiStationRunning; +static bool wifiApRunning; //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // WiFi Routines @@ -154,7 +155,8 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) if (startWiFiAP && WiFi.getMode() == WIFI_AP) return (true); // There is nothing needing to be changed - wifiRunning = false; // Mark it as offline while we mess about + wifiStationRunning = false; // Mark it as offline while we mess about + wifiApRunning = false; // Mark it as offline while we mess about wifi_mode_t wifiMode = WIFI_OFF; wifi_interface_t wifiInterface = WIFI_IF_STA; @@ -248,8 +250,6 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) systemPrintf("WiFi AP '%s' started with IP: ", softApSsid); systemPrintln(WiFi.softAPIP()); - networkMarkOnline(NETWORK_WIFI); // Regardless of WiFi STA success of failure, we have some network access - // Start DNS Server if (dnsServer.start(53, "*", WiFi.softAPIP()) == false) { @@ -262,12 +262,11 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) systemPrintln("DNS Server started"); } + wifiApRunning = true; + // If we're only here to start the AP, then we're done if (wifiMode == WIFI_AP) - { - wifiRunning = true; return true; - } } systemPrintln("Connecting to WiFi... "); @@ -288,7 +287,7 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) if (wifiStatus == WL_CONNECTED) { wifiResetTimeout(); // If we successfully connected then reset the throttling timeout - wifiRunning = true; + wifiStationRunning = true; return true; } if (wifiStatus == WL_DISCONNECTED) @@ -297,7 +296,7 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) { systemPrintf("WiFi failed to connect: error #%d - %s\r\n", wifiStatus, wifiPrintState((wl_status_t)wifiStatus)); } - wifiRunning = false; + wifiStationRunning = false; return false; } @@ -306,10 +305,10 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) //---------------------------------------- void wifiDisplayState() { - systemPrintf("WiFi: %s\r\n", networkIsInterfaceOnline(NETWORK_WIFI) ? "Online" : "Offline"); + systemPrintf("WiFi: %s\r\n", networkInterfaceHasInternet(NETWORK_WIFI) ? "Online" : "Offline"); systemPrintf(" MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\r\n", wifiMACAddress[0], wifiMACAddress[1], wifiMACAddress[2], wifiMACAddress[3], wifiMACAddress[4], wifiMACAddress[5]); - if (networkIsInterfaceOnline(NETWORK_WIFI)) + if (networkInterfaceHasInternet(NETWORK_WIFI)) { // Get the DNS addresses IPAddress dns1 = WiFi.STA.dnsIP(0); @@ -351,7 +350,7 @@ void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) if (WiFi.getMode() == WIFI_MODE_STA) { // Take the network offline if necessary - if (networkIsInterfaceOnline(NETWORK_WIFI) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP) && + if (networkInterfaceHasInternet(NETWORK_WIFI) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP6)) { if (settings.debugWifiState) @@ -422,13 +421,13 @@ void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) ipAddress = WiFi.localIP(); systemPrint("WiFi STA Got IPv4: "); systemPrintln(ipAddress); - networkMarkOnline(NETWORK_WIFI); + networkMarkHasInternet(NETWORK_WIFI); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP6: systemPrint("WiFi STA Got IPv6: "); systemPrintln(ipAddress); - networkMarkOnline(NETWORK_WIFI); + networkMarkHasInternet(NETWORK_WIFI); break; case ARDUINO_EVENT_WIFI_STA_LOST_IP: @@ -449,11 +448,29 @@ bool wifiIsConnected() } //---------------------------------------- -// Determine if WIFI is running +// Determine if WiFi Station is running +//---------------------------------------- +bool wifiStationIsRunning() +{ + return wifiStationRunning; +} + +//---------------------------------------- +// Determine if WiFi AP is running +//---------------------------------------- +bool wifiApIsRunning() +{ + return wifiApRunning; +} + +//---------------------------------------- +// Determine if either Station or AP is running //---------------------------------------- bool wifiIsRunning() { - return wifiRunning; + if (wifiStationRunning || wifiApRunning) + return true; + return false; } //---------------------------------------- @@ -511,54 +528,59 @@ bool wifiStart() { int wifiStatus; - // Determine if WiFi is already running - if (!wifiRunning) - { - // Determine which parts of WiFi need to be started - bool startWiFiStation = false; - bool startWiFiAP = false; + // Determine which parts of WiFi need to be started + bool startWiFiStation = false; + bool startWiFiAp = false; - uint16_t consumerTypes = networkGetConsumerTypes(); + uint16_t consumerTypes = networkGetConsumerTypes(); - // The consumers need station - if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) - startWiFiStation = true; + // The consumers need station + if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) + startWiFiStation = true; - // The consumers need AP - if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) - startWiFiAP = true; + // The consumers need AP + if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) + startWiFiAp = true; - if (startWiFiStation == false && startWiFiAP == false) + if (startWiFiStation == false && startWiFiAp == false) + { + systemPrintln("wifiStart() requested without any NETCONSUMER combination"); + WIFI_STOP(); + return (false); + } + + // Determine if WiFi is already running + if (startWiFiStation == wifiStationRunning && startWiFiAp == wifiApRunning) + { + if (settings.debugWifiState == true) + systemPrintln("WiFi is already running with requested setup"); + return (true); + } + + // Handle special cases if no networks have been entered + if (wifiNetworkCount() == 0) + { + if (startWiFiStation == true && startWiFiAp == false) { - systemPrintln("wifiStart() requested without any NETCONSUMER combination"); + systemPrintln("Error: Please enter at least one SSID before using WiFi"); + displayNoSSIDs(2000); WIFI_STOP(); - return (false); + return false; } - - if (wifiNetworkCount() == 0) + else if (startWiFiStation == true && startWiFiAp == true) { - if (startWiFiStation == true && startWiFiAP == false) - { - systemPrintln("Error: Please enter at least one SSID before using WiFi"); - displayNoSSIDs(2000); - WIFI_STOP(); - return false; - } - else if (startWiFiStation == true && startWiFiAP == true) - { - systemPrintln("Error: No SSID available to start WiFi Station during AP"); - // Allow the system to continue in AP only mode - startWiFiStation = false; - } + systemPrintln("Error: No SSID available to start WiFi Station during AP"); + // Allow the system to continue in AP only mode + startWiFiStation = false; } - - // Start WiFi - wifiConnect(startWiFiStation, startWiFiAP, settings.wifiConnectTimeoutMs); } + // Start WiFi + wifiConnect(startWiFiStation, startWiFiAp, settings.wifiConnectTimeoutMs); + // If we are in AP only mode, as long as the AP is started, return true if (WiFi.getMode() == WIFI_MODE_AP) - return (true); + return (wifiApIsRunning); // If we are in STA or AP+STA mode, return if the station connected successfully wifiStatus = WiFi.status(); @@ -690,7 +712,8 @@ void wifiStop() // Display the heap state reportHeapNow(settings.debugWifiState); - wifiRunning = false; + wifiStationRunning = false; + wifiApRunning = false; } // Needed for wifiStopSequence From 2d25085a76164c8b5c33276277867dc8af51e0ea Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 13 Jan 2025 11:52:44 -0700 Subject: [PATCH 115/276] Handle WiFi Station failure gracefully during web config --- Firmware/RTK_Everywhere/AP-Config/src/main.js | 8 +- Firmware/RTK_Everywhere/WebServer.ino | 9 +- Firmware/RTK_Everywhere/menuCommands.ino | 90 +++++++++++-------- Firmware/RTK_Everywhere/menuFirmware.ino | 11 ++- 4 files changed, 72 insertions(+), 46 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/src/main.js b/Firmware/RTK_Everywhere/AP-Config/src/main.js index af2c713d8..de14d03f6 100644 --- a/Firmware/RTK_Everywhere/AP-Config/src/main.js +++ b/Firmware/RTK_Everywhere/AP-Config/src/main.js @@ -2358,7 +2358,13 @@ function checkingNewFirmware() { function newFirmwareVersion(firmwareVersion) { clearMsg('firmwareCheckNewMsg'); - if (firmwareVersion == "ERROR") { + if (firmwareVersion == "NO_INTERNET") { + showMsgError('firmwareCheckNewMsg', "No internet"); + hide("divGetNewFirmware"); + ge("btnCheckNewFirmware").disabled = false; + return; + } + else if (firmwareVersion == "NO_SERVER") { showMsgError('firmwareCheckNewMsg', "Network or Server not available"); hide("divGetNewFirmware"); ge("btnCheckNewFirmware").disabled = false; diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index c96f69e12..96d285e49 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -27,7 +27,6 @@ static const char *const webServerStateNames[] = { static const int webServerStateEntries = sizeof(webServerStateNames) / sizeof(webServerStateNames[0]); -static NetPriority_t webServerPriority = NETWORK_OFFLINE; static uint8_t webServerState; // Once connected to the access point for WiFi Config, the ESP32 sends current setting values in one long string to @@ -784,8 +783,8 @@ void webServerUpdate() // Wait for connection to the network case WEBSERVER_STATE_WAIT_FOR_NETWORK: - // Wait until the network is connected to the media - if (networkIsConnected(&webServerPriority)) + // Wait until the network is connected to the internet or has WiFi AP + if (networkHasInternet() || wifiApIsRunning()) { if (settings.debugWebServer) systemPrintln("Web Server connected to network"); @@ -797,7 +796,7 @@ void webServerUpdate() // Start the web server case WEBSERVER_STATE_NETWORK_CONNECTED: { // Determine if the network has failed - if (!networkIsConnected(&webServerPriority)) + if (networkHasInternet() == false && wifiApIsRunning() == false) webServerStop(); if (settings.debugWebServer) systemPrintln("Assigning web server resources"); @@ -813,7 +812,7 @@ void webServerUpdate() // Allow web services case WEBSERVER_STATE_RUNNING: // Determine if the network has failed - if (!networkIsConnected(&webServerPriority)) + if (networkHasInternet() == false && wifiApIsRunning() == false) webServerStop(); // This state is exited when webServerStop() is called diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index 89b076a76..564ea90f5 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -1290,38 +1290,56 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting sendStringToWebsocket((char *)"checkingNewFirmware,1,"); // Tell the config page we received their request - // Indicate to the OTA state machine that we need to do a version check - otaRequestFirmwareVersionCheck = true; + // We don't use the OTA state machine here because we need to respond to + // Web Config immediately of success or failure + + // If we're in AP only mode (no internet), try WiFi with current SSIDs + if (networkIsInterfaceStarted(NETWORK_WIFI) && networkHasInternet() == false) + { + wifiStart(); + } // Get firmware version from server - // otaCheckVersion will call wifiConnect if needed - // if (otaCheckVersion(reportedVersion, sizeof(reportedVersion))) - // { - // // We got a version number, now determine if it's newer or not - // char currentVersion[21]; - // getFirmwareVersion(currentVersion, sizeof(currentVersion), enableRCFirmware); - // if (isReportedVersionNewer(reportedVersion, currentVersion) == true) - // { - // if (settings.debugWebServer == true) - // systemPrintln("New version detected"); - // snprintf(newVersionCSV, sizeof(newVersionCSV), "newFirmwareVersion,%s,", reportedVersion); - // } - // else - // { - // if (settings.debugWebServer == true) - // systemPrintln("No new firmware available"); - // snprintf(newVersionCSV, sizeof(newVersionCSV), "newFirmwareVersion,CURRENT,"); - // } - // } - // else - // { - // // Failed to get version number - // if (settings.debugWebServer == true) - // systemPrintln("Sending error to AP config page"); - // snprintf(newVersionCSV, sizeof(newVersionCSV), "newFirmwareVersion,ERROR,"); - // } - - // sendStringToWebsocket(newVersionCSV); + char newVersionCSV[40]; + if (networkHasInternet() == false) + { + // No internet. Report error. + if (settings.debugWebServer == true) + systemPrintln("No internet available. Sending error to Web config page."); + snprintf(newVersionCSV, sizeof(newVersionCSV), "newFirmwareVersion,NO_INTERNET,"); + } + else + { + char otaReportedVersion[50]; + if (otaCheckVersion(otaReportedVersion, sizeof(otaReportedVersion))) + { + // We got a version number, now determine if it's newer or not + char currentVersion[40]; + getFirmwareVersion(currentVersion, sizeof(currentVersion), enableRCFirmware); + if (isReportedVersionNewer(otaReportedVersion, currentVersion) == true) + { + if (settings.debugWebServer == true) + systemPrintln("New version detected"); + snprintf(newVersionCSV, sizeof(newVersionCSV), "newFirmwareVersion,%s,", otaReportedVersion); + } + else + { + if (settings.debugWebServer == true) + systemPrintln("No new firmware available"); + snprintf(newVersionCSV, sizeof(newVersionCSV), "newFirmwareVersion,CURRENT,"); + } + } + else + { + // Failed to get version number + if (settings.debugWebServer == true) + systemPrintln("Sending error to Web config page"); + snprintf(newVersionCSV, sizeof(newVersionCSV), "newFirmwareVersion,NO_SERVER,"); + } + } + + sendStringToWebsocket(newVersionCSV); + knownSetting = true; } else if (strcmp(settingName, "getNewFirmware") == 0) @@ -2326,12 +2344,12 @@ SettingValueResponse getSettingValue(bool inCommands, const char *settingName, c break; // System state at power on. Convert various system states to either Rover, Base, NTP, or BaseCast. // Manually handled below - // case tSysState: { - // SystemState *ptr = (SystemState *)var; - // writeToString(settingValueStr, (int)*ptr); - // knownSetting = true; - // } - break; + // case tSysState: { + // SystemState *ptr = (SystemState *)var; + // writeToString(settingValueStr, (int)*ptr); + // knownSetting = true; + // } + break; case tPulseEdg: { pulseEdgeType_e *ptr = (pulseEdgeType_e *)var; writeToString(settingValueStr, (int)*ptr); diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index b99a4d330..3a1e64f59 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -33,7 +33,6 @@ static const int otaStateEntries = sizeof(otaStateNames) / sizeof(otaStateNames[ //---------------------------------------- static uint32_t otaLastUpdateCheck; -static NetPriority_t otaPriority = NETWORK_OFFLINE; static uint8_t otaState; #endif // COMPILE_OTA_AUTO @@ -841,7 +840,9 @@ void otaUpdate() otaUpdateStop(); // Wait until the network is connected to the media - else if (networkIsConnected(&otaPriority)) + // else if (networkHasInternet()) + else if (networkInterfaceHasInternet( + NETWORK_WIFI)) // TODO Remove once OTA works over other network interfaces { if (settings.debugFirmwareUpdate) systemPrintln("Firmware update connected to network"); @@ -854,7 +855,9 @@ void otaUpdate() // Get firmware version from server case OTA_STATE_GET_FIRMWARE_VERSION: // Determine if the network has failed - if (!networkIsConnected(&otaPriority)) + // if (networkHasInternet() == false) + if (networkInterfaceHasInternet(NETWORK_WIFI) == + false) // TODO Remove once OTA works over other network interfaces otaUpdateStop(); if (settings.debugFirmwareUpdate) systemPrintln("Checking for latest firmware version"); @@ -910,7 +913,7 @@ void otaUpdate() // Update the firmware case OTA_STATE_UPDATE_FIRMWARE: // Determine if the network has failed - if (!networkIsConnected(&otaPriority)) + if (networkHasInternet() == false) otaUpdateStop(); else { From 53ace33df8b9ce734f9a5921036f34b34f63ef9c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Jan 2025 18:57:36 +0000 Subject: [PATCH 116/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 249 +++++++++++++++++---------------- 1 file changed, 125 insertions(+), 124 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index bab182952..548a68388 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x35, 0x44, 0x85, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0x1F, 0x62, 0x85, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -919,128 +919,129 @@ static const uint8_t main_js[] PROGMEM = { 0x23, 0x1C, 0x53, 0x75, 0xC1, 0x16, 0xAA, 0x53, 0x0E, 0x7C, 0x72, 0x5F, 0xA4, 0x74, 0x04, 0x09, 0x46, 0x93, 0xC7, 0x7E, 0x08, 0x4C, 0x31, 0x21, 0x0B, 0xBF, 0xD8, 0xD1, 0xCC, 0x71, 0x42, 0xE3, 0x17, 0x5E, 0x63, 0xF1, 0x5A, 0xFD, 0x5B, 0x69, 0x5F, 0x2E, 0x4D, 0xE9, 0x01, 0x54, 0x0D, 0x9E, - 0x67, 0xCE, 0x3F, 0x3F, 0xFF, 0x78, 0xDE, 0xAA, 0x6D, 0x88, 0xC4, 0x48, 0x23, 0x20, 0x11, 0x3E, - 0x4B, 0xB2, 0xEC, 0x1E, 0xF6, 0x2D, 0xB8, 0x79, 0xFC, 0x10, 0x75, 0x47, 0x9B, 0xD0, 0x1C, 0xF7, - 0xF6, 0x3D, 0x8D, 0x14, 0x13, 0xA4, 0xCE, 0xB7, 0xA5, 0x56, 0x4A, 0xDB, 0x5D, 0x54, 0x8D, 0x9D, - 0xB2, 0xC1, 0x69, 0x6A, 0xE7, 0xFE, 0xA7, 0xF3, 0xF3, 0xC3, 0xD3, 0x0B, 0x53, 0x4B, 0x73, 0x1B, - 0x99, 0xA8, 0x39, 0x18, 0xDB, 0xE9, 0x04, 0x2D, 0x1E, 0x4F, 0x58, 0xF8, 0xC4, 0x6D, 0x93, 0x0D, - 0xB9, 0x4E, 0x47, 0xF7, 0x8B, 0x59, 0xBC, 0x1B, 0x30, 0x7A, 0xDB, 0x62, 0xB7, 0x41, 0x14, 0x39, - 0xEC, 0x14, 0x22, 0x32, 0x73, 0xA3, 0xBE, 0x63, 0x85, 0xD8, 0xCF, 0xF2, 0xD6, 0x30, 0x66, 0x55, - 0x54, 0x81, 0x24, 0x85, 0x14, 0x09, 0xD6, 0x4D, 0xA2, 0xD3, 0x0E, 0x77, 0xF4, 0x31, 0xFD, 0x7C, - 0x26, 0xDC, 0x1F, 0xDF, 0xFD, 0xC6, 0x59, 0xBC, 0x92, 0x41, 0xC8, 0x28, 0x7F, 0xB6, 0xA7, 0xA0, - 0xFD, 0xEF, 0xC5, 0xE3, 0x59, 0xB8, 0x59, 0x73, 0x2D, 0x35, 0xEF, 0xE7, 0x44, 0xAF, 0x4E, 0xF4, - 0x86, 0xC9, 0x54, 0xD5, 0xDC, 0xC7, 0x9E, 0x4A, 0x55, 0x6A, 0xC6, 0x89, 0x54, 0x63, 0xC8, 0x34, - 0x8D, 0x0E, 0x39, 0x5E, 0x79, 0xC4, 0x49, 0x81, 0x61, 0xF1, 0xCD, 0x0A, 0xB4, 0xA7, 0xDD, 0x56, - 0xEE, 0xEB, 0x88, 0x46, 0x56, 0x96, 0x8C, 0x96, 0x3A, 0xC6, 0x96, 0x9D, 0x85, 0x1E, 0x69, 0x68, - 0x95, 0x99, 0x7C, 0x66, 0x0D, 0x62, 0x31, 0xA8, 0x5A, 0xAF, 0x3C, 0x56, 0xAA, 0x2E, 0x9D, 0xFC, - 0xC8, 0x8E, 0xA9, 0x8B, 0xA7, 0x00, 0xC5, 0xAE, 0x55, 0xBC, 0x9B, 0x62, 0x74, 0x45, 0xF2, 0xE4, - 0x54, 0x7D, 0x78, 0x6A, 0x54, 0xF8, 0x36, 0x9A, 0xFE, 0x24, 0x60, 0x55, 0x13, 0xAE, 0x21, 0x93, - 0x36, 0xF7, 0x75, 0x32, 0xBB, 0x99, 0xAD, 0x38, 0xED, 0xE5, 0x51, 0x25, 0x9D, 0xC2, 0x7B, 0xF7, - 0x96, 0x7A, 0xC4, 0xC6, 0x27, 0x6C, 0x83, 0x85, 0x50, 0x64, 0x00, 0x43, 0x61, 0xDE, 0xE3, 0x44, - 0x05, 0xDD, 0xEC, 0x45, 0xEE, 0x35, 0xCF, 0xC3, 0x85, 0x71, 0x6F, 0xCC, 0x44, 0x88, 0x35, 0x18, - 0x7E, 0x4B, 0x43, 0x9A, 0x89, 0xEB, 0x91, 0x83, 0x83, 0x8E, 0x13, 0xFF, 0x63, 0x1B, 0xCE, 0xB6, - 0x14, 0xC6, 0x1D, 0xE3, 0x3A, 0x42, 0x5B, 0x81, 0xAF, 0x4E, 0x2D, 0x22, 0xCD, 0x43, 0x0F, 0x48, - 0xA9, 0xEB, 0xD9, 0x18, 0x63, 0x52, 0x11, 0x9A, 0xAF, 0xBE, 0x57, 0x15, 0x76, 0xF6, 0x3F, 0x7E, - 0x3C, 0x3F, 0x38, 0x3A, 0xDD, 0xBB, 0x38, 0xBC, 0x3C, 0x3A, 0x3D, 0xFB, 0x74, 0x71, 0x79, 0xF1, - 0xF9, 0x0C, 0x7F, 0xFD, 0x65, 0xEF, 0xF8, 0xE8, 0xE0, 0xF2, 0xD3, 0xE9, 0x5F, 0x4E, 0x3F, 0xFE, - 0x7A, 0x9A, 0x6E, 0x6A, 0x3B, 0x76, 0x78, 0x23, 0xDD, 0x18, 0x4F, 0xCC, 0x23, 0x86, 0x9C, 0x1B, - 0xBE, 0x3B, 0x74, 0xE0, 0x8E, 0xED, 0x91, 0xA1, 0x84, 0x9B, 0xAA, 0x8F, 0xD7, 0xC7, 0x94, 0xBD, - 0x43, 0xA9, 0x9F, 0xEE, 0x81, 0xF1, 0x00, 0x6F, 0x2B, 0xC2, 0xE7, 0xCE, 0x12, 0xB9, 0xF0, 0x57, - 0x85, 0xF0, 0x2E, 0x32, 0xAA, 0x17, 0xB9, 0xBB, 0xB1, 0xD9, 0x74, 0x35, 0x64, 0x82, 0x07, 0x19, - 0x4F, 0xC3, 0xC4, 0x2A, 0x0F, 0x6C, 0x8F, 0x50, 0x14, 0x08, 0x33, 0x99, 0xAE, 0x07, 0x9D, 0xEF, - 0x3A, 0xEC, 0x56, 0x79, 0x28, 0xAA, 0xEC, 0x11, 0xFE, 0x8D, 0xD7, 0xC2, 0x87, 0x5B, 0x59, 0x1E, - 0x38, 0x7E, 0x0E, 0x18, 0xB6, 0xC9, 0x4A, 0x1B, 0xE3, 0x4D, 0xDB, 0xAC, 0x9B, 0x3A, 0xEA, 0x59, - 0x97, 0x64, 0x7C, 0x13, 0xC1, 0xEB, 0xA6, 0x57, 0xBD, 0x46, 0x1B, 0x3A, 0xEE, 0xD0, 0x8D, 0xD2, - 0x6E, 0xC2, 0x43, 0xDC, 0xBC, 0x2B, 0x95, 0x08, 0xA0, 0x8A, 0x8D, 0x45, 0xD3, 0x1B, 0xE5, 0xB5, - 0xBC, 0x5C, 0xF4, 0xF2, 0x8A, 0x4C, 0x0E, 0xB1, 0x2C, 0xAC, 0x2C, 0x2C, 0xA5, 0x1D, 0xB8, 0xBC, - 0xCC, 0x5E, 0x83, 0x1A, 0x8D, 0xC8, 0xD0, 0xF7, 0x9D, 0x0A, 0xD0, 0x04, 0xA0, 0xD3, 0x7E, 0xAE, - 0x0D, 0xDE, 0x41, 0xE2, 0x52, 0xBB, 0x8A, 0x10, 0xC4, 0x7B, 0x13, 0x8D, 0x94, 0x55, 0x9C, 0x07, - 0xB3, 0x25, 0x0D, 0xA8, 0x11, 0x46, 0xBA, 0x84, 0x8A, 0x0A, 0xB0, 0xC4, 0x02, 0xEA, 0xE1, 0x13, - 0x78, 0xF7, 0xA8, 0x44, 0x13, 0x3F, 0x0C, 0x5D, 0x8C, 0x87, 0xE5, 0x5A, 0x81, 0xE3, 0x34, 0xD6, - 0x97, 0x74, 0x48, 0xA6, 0x1F, 0x4E, 0x4E, 0x3A, 0x63, 0xFE, 0x2F, 0xFD, 0x46, 0x4C, 0x1F, 0x57, - 0x4C, 0x1F, 0x4F, 0x4E, 0xFA, 0xFD, 0x4E, 0xC8, 0xFE, 0x29, 0xE0, 0xC4, 0xF0, 0x19, 0x10, 0xAC, - 0xA4, 0x9F, 0x5F, 0x18, 0xF5, 0x84, 0xDD, 0xE2, 0x9A, 0x5D, 0x72, 0xFF, 0x17, 0x83, 0x84, 0x3D, - 0xBF, 0x43, 0xD6, 0x61, 0xB4, 0x6D, 0x5B, 0x6B, 0x6B, 0xEB, 0x2F, 0x59, 0xFE, 0x3D, 0x26, 0xBF, - 0x4E, 0x1A, 0xA1, 0x9C, 0x8E, 0xF8, 0x37, 0xA4, 0x37, 0x0F, 0xC2, 0x1F, 0x71, 0xFC, 0x59, 0x2C, - 0x27, 0x04, 0x8C, 0xB4, 0x1E, 0xB1, 0x47, 0x98, 0x95, 0xD0, 0x41, 0x46, 0x88, 0xB5, 0x41, 0x7A, - 0x1B, 0x9D, 0x9E, 0xB5, 0xBE, 0x6D, 0x60, 0x25, 0xB5, 0x49, 0x6F, 0xC8, 0xDA, 0x9C, 0x39, 0xE9, - 0x31, 0x66, 0xD6, 0x52, 0x66, 0x56, 0xBA, 0xD6, 0xC6, 0x4A, 0xB7, 0xBB, 0x62, 0x6D, 0x74, 0xBA, - 0x9B, 0x3D, 0x13, 0x3B, 0x66, 0xCB, 0xF6, 0x06, 0x83, 0xFC, 0xE7, 0xC4, 0xDA, 0x4B, 0xE4, 0xE9, - 0x9A, 0xDE, 0xD1, 0x80, 0xF3, 0xD3, 0xED, 0x22, 0x37, 0x5B, 0x5B, 0xDB, 0xDB, 0x3D, 0xB2, 0x78, - 0xC0, 0x35, 0x0B, 0xAB, 0xF0, 0xDF, 0x96, 0x12, 0x1E, 0x53, 0x77, 0xD6, 0xA3, 0x43, 0x3B, 0x02, - 0xBB, 0xD9, 0x77, 0x87, 0x9E, 0xEA, 0x3D, 0xA8, 0x63, 0xD7, 0x4A, 0x0D, 0x47, 0x6A, 0xA5, 0x92, - 0x62, 0xEE, 0x77, 0x61, 0x60, 0xFD, 0x9E, 0x64, 0xDC, 0xDA, 0x28, 0x3A, 0x8C, 0x7D, 0x67, 0x27, - 0x3D, 0x18, 0x7D, 0x0F, 0xC6, 0x8B, 0x89, 0x82, 0x9B, 0x8F, 0xF4, 0xAE, 0x8D, 0xCA, 0x84, 0x1A, - 0xD8, 0x93, 0x74, 0xEA, 0xCA, 0x0A, 0x22, 0xC2, 0x44, 0x9A, 0x69, 0x3F, 0x83, 0xB5, 0xC6, 0x39, - 0xD3, 0xF5, 0xF8, 0xA3, 0x29, 0xAC, 0x84, 0x72, 0x0B, 0xCE, 0xF3, 0x6F, 0xB2, 0xD4, 0x14, 0x82, - 0x68, 0x4C, 0x86, 0x84, 0x40, 0x47, 0xDF, 0xB0, 0x92, 0xF5, 0x98, 0x1B, 0x5A, 0x5C, 0x53, 0x49, - 0xB3, 0x5C, 0xF2, 0x2D, 0xA7, 0x5F, 0x77, 0xD9, 0xED, 0x0D, 0x7C, 0x64, 0x31, 0xB7, 0x7C, 0x73, - 0x09, 0x16, 0x64, 0xAB, 0xAB, 0xD9, 0x11, 0x2F, 0x3F, 0x84, 0xDD, 0x7C, 0xAE, 0xE6, 0x78, 0xA5, - 0x53, 0x79, 0x9E, 0x86, 0x83, 0x1D, 0xBA, 0xF0, 0x6B, 0x3C, 0xEC, 0x28, 0x12, 0xC4, 0xEB, 0x0D, - 0xE2, 0xDB, 0xD1, 0xA9, 0xC3, 0xC0, 0xBA, 0x09, 0x9C, 0x4F, 0x22, 0xF4, 0x46, 0xC1, 0x22, 0xEC, - 0x8B, 0x8A, 0x42, 0x42, 0xCD, 0xEF, 0x46, 0x5B, 0x32, 0x8E, 0x74, 0xE2, 0x4B, 0xAB, 0xAD, 0xEC, - 0x26, 0xA6, 0x8A, 0x9F, 0xB9, 0x2A, 0xF7, 0xA9, 0x59, 0x2A, 0x5F, 0x9E, 0x3E, 0xBE, 0x98, 0x50, - 0x42, 0xE6, 0xE4, 0x44, 0x8E, 0x8B, 0x7B, 0xE7, 0xC2, 0x14, 0x0D, 0xD3, 0x8B, 0x32, 0xE5, 0xA6, - 0x13, 0x33, 0xBB, 0x5C, 0xF4, 0xF1, 0x7A, 0x91, 0x4D, 0x40, 0xD0, 0x1B, 0x2B, 0x5D, 0x7D, 0x6F, - 0x7C, 0x56, 0xD1, 0x5F, 0x9E, 0x7E, 0xBC, 0x3C, 0x38, 0xDC, 0x3F, 0x3A, 0xD9, 0x3B, 0xD6, 0x7A, - 0x21, 0xA4, 0x30, 0x01, 0x39, 0xD8, 0xAC, 0x84, 0x1F, 0x4D, 0xDC, 0xB2, 0x3A, 0xF0, 0xC5, 0x15, - 0x87, 0x30, 0x8A, 0x2C, 0x1D, 0x50, 0xB2, 0xA0, 0x65, 0x90, 0x58, 0x8E, 0x7F, 0x4E, 0xE4, 0x25, - 0x00, 0x40, 0x64, 0x52, 0x18, 0x9A, 0xC1, 0xB5, 0x8A, 0x89, 0x2D, 0xA7, 0x48, 0x56, 0xC9, 0x26, - 0x4C, 0x01, 0xEC, 0x52, 0x7D, 0x4C, 0x63, 0x95, 0xAC, 0x6D, 0x62, 0x36, 0x99, 0x25, 0xED, 0x56, - 0xB8, 0x32, 0x92, 0xCD, 0x7E, 0x8D, 0x89, 0xEC, 0x9F, 0xB1, 0x3B, 0xE4, 0x97, 0x22, 0x1F, 0x4C, - 0xAB, 0x27, 0x6D, 0x88, 0xE2, 0x68, 0x54, 0x07, 0x28, 0x1B, 0x9F, 0xB9, 0xC3, 0x6F, 0x03, 0x47, - 0x67, 0x6E, 0xE9, 0x7A, 0x32, 0x36, 0x95, 0x19, 0x7A, 0x7E, 0x43, 0xB3, 0xE2, 0xC0, 0x4C, 0x47, - 0xA4, 0xA2, 0x21, 0x39, 0xC3, 0x51, 0x1F, 0x1A, 0x75, 0x07, 0x60, 0xEE, 0xF0, 0x33, 0xEB, 0xA9, - 0x22, 0x1A, 0x16, 0xE9, 0x2B, 0x00, 0x0C, 0x88, 0xCD, 0x4A, 0x5A, 0x57, 0xE9, 0x1E, 0x59, 0xBF, - 0x54, 0x05, 0x53, 0xB4, 0xA9, 0xCB, 0xF5, 0x61, 0xE5, 0x91, 0x14, 0xE2, 0xF2, 0xE4, 0xE4, 0xF2, - 0x60, 0xAF, 0xFF, 0x41, 0x53, 0x0B, 0x11, 0x6F, 0x94, 0x9A, 0x2D, 0x71, 0x9B, 0x6C, 0x45, 0xBF, - 0x6D, 0x98, 0xEA, 0x80, 0x30, 0xE5, 0x08, 0x89, 0xF9, 0x8B, 0xD2, 0x0E, 0xCB, 0xE9, 0x5A, 0xB9, - 0x7E, 0xF7, 0xAB, 0x64, 0x4C, 0x33, 0xBD, 0xFB, 0xCC, 0x3A, 0x2B, 0xBF, 0xAF, 0x7A, 0x49, 0x5F, - 0xC5, 0xDE, 0xF1, 0xDC, 0xFB, 0x0A, 0xCC, 0xFB, 0x33, 0xEB, 0xAE, 0x67, 0x33, 0xF7, 0x49, 0xE2, - 0xA9, 0x32, 0x05, 0xCA, 0x0D, 0xEA, 0xA5, 0x0D, 0xCA, 0xCE, 0x81, 0xFF, 0xE8, 0x13, 0x14, 0x57, - 0xCA, 0x74, 0x03, 0x67, 0xAE, 0x3A, 0xB9, 0x53, 0x22, 0xA6, 0xD4, 0x80, 0xFF, 0x30, 0x01, 0x08, - 0x0B, 0x4A, 0x1E, 0xCF, 0x82, 0x56, 0x1C, 0x8D, 0xE4, 0xA7, 0xF1, 0x2C, 0xEA, 0xA7, 0x5E, 0xD2, - 0x4F, 0xE4, 0x71, 0xD6, 0x25, 0xDC, 0x40, 0x3C, 0xA3, 0xCE, 0x7A, 0x6E, 0xA6, 0xF3, 0x7F, 0x9A, - 0xD5, 0x14, 0x1B, 0x5A, 0xCA, 0xC9, 0x90, 0x01, 0x01, 0x3F, 0x1C, 0x32, 0x14, 0x24, 0xD9, 0xB5, - 0xB6, 0x97, 0xB4, 0xAB, 0xF5, 0x86, 0xEE, 0xE0, 0x67, 0x3E, 0xE9, 0xC6, 0xBC, 0xB4, 0xC3, 0x8E, - 0x9B, 0xBA, 0xE9, 0x15, 0xF4, 0x36, 0xF1, 0xA7, 0x11, 0xFE, 0x61, 0x8B, 0x5D, 0x7B, 0x00, 0xEA, - 0xFB, 0xEA, 0x1E, 0x3C, 0x6E, 0x28, 0x5F, 0x81, 0xB4, 0xC6, 0x94, 0x2C, 0x68, 0x43, 0x66, 0xA1, - 0x4D, 0x68, 0x34, 0x90, 0x83, 0x6A, 0x19, 0xDF, 0x8C, 0x0F, 0x89, 0xAF, 0xB6, 0x49, 0x65, 0xCC, - 0xFB, 0xF5, 0x62, 0xF3, 0x52, 0x3A, 0x68, 0xE4, 0x77, 0x0F, 0x0C, 0x1A, 0x57, 0x5D, 0xE5, 0x96, - 0x8C, 0xC3, 0x3A, 0xD5, 0xB0, 0xF4, 0xDB, 0x92, 0x24, 0x66, 0xFD, 0xB4, 0x56, 0x66, 0xC3, 0x7C, - 0xD6, 0x35, 0x23, 0x9B, 0x97, 0xD2, 0x9A, 0x07, 0xD6, 0x6D, 0x33, 0x62, 0x9B, 0x2B, 0xB2, 0xD8, - 0x75, 0x9F, 0x33, 0xCA, 0xFE, 0xE7, 0x93, 0xB7, 0x1F, 0x8F, 0x19, 0x52, 0xFD, 0x52, 0xC7, 0xC8, - 0xF7, 0x86, 0x2C, 0x8F, 0xD1, 0x01, 0x1D, 0x06, 0x54, 0xDF, 0x1F, 0xC9, 0xF4, 0x84, 0xD6, 0xB5, - 0xB0, 0x38, 0xD3, 0x11, 0x18, 0xEB, 0xC1, 0x70, 0xDD, 0xB4, 0x76, 0xB4, 0xDC, 0x90, 0x49, 0xE9, - 0x6B, 0x92, 0x6B, 0xF9, 0xF8, 0x40, 0x97, 0x4C, 0x97, 0xA2, 0x57, 0x83, 0xEC, 0xB0, 0x7D, 0xB9, - 0x94, 0xC9, 0x41, 0x39, 0x63, 0xF7, 0xE6, 0xB1, 0x96, 0x0C, 0xA1, 0x8C, 0x08, 0x97, 0x61, 0x54, - 0x31, 0xEB, 0x12, 0x57, 0xDD, 0xC9, 0x1E, 0x5E, 0xCC, 0x49, 0x51, 0x1A, 0x31, 0xB7, 0xF2, 0x14, - 0xDC, 0x71, 0x9D, 0x6B, 0xC4, 0xDF, 0x7F, 0xFF, 0x97, 0xCA, 0x20, 0x7E, 0x5B, 0x68, 0xA9, 0x6C, - 0x36, 0xC1, 0x4B, 0x4C, 0xED, 0xD6, 0x6C, 0xCB, 0x5C, 0x9A, 0xDE, 0x5F, 0x92, 0x07, 0xF0, 0xEC, - 0x2A, 0x38, 0x67, 0x84, 0xD2, 0xAA, 0xEA, 0x31, 0xF0, 0xEA, 0x3D, 0x3F, 0x27, 0x11, 0x48, 0xAE, - 0xCC, 0x63, 0x70, 0xFD, 0xB8, 0xD8, 0xB5, 0x15, 0xEC, 0xD2, 0x3F, 0xBA, 0x19, 0x56, 0x78, 0x3E, - 0x31, 0x6D, 0xAD, 0xD7, 0xE1, 0x59, 0x20, 0x28, 0xE2, 0xB9, 0xF2, 0x04, 0xB0, 0x39, 0xF7, 0x09, - 0x40, 0x1E, 0x7D, 0x35, 0xA7, 0x80, 0x8C, 0x88, 0x9E, 0x68, 0x6A, 0xC8, 0x8C, 0xEE, 0xBA, 0xB3, - 0x83, 0x89, 0xF1, 0x95, 0x27, 0xE2, 0x7C, 0xE6, 0x99, 0xC3, 0xC4, 0xFC, 0x42, 0x76, 0x4A, 0xF9, - 0xD7, 0x56, 0xEB, 0xB1, 0xDA, 0xB0, 0xD4, 0x78, 0x7A, 0x32, 0xF1, 0x4E, 0x1E, 0x5B, 0xF0, 0xB9, - 0xE6, 0x75, 0x4E, 0xEA, 0x2E, 0x5D, 0x54, 0x34, 0x9A, 0x85, 0x39, 0x2B, 0xD0, 0x8C, 0x2D, 0x29, - 0xEE, 0x87, 0x27, 0x6E, 0x8B, 0x3E, 0x71, 0xCC, 0x7F, 0x44, 0x17, 0x35, 0x28, 0x73, 0x91, 0x47, - 0xA5, 0xA7, 0xC5, 0x3C, 0xC6, 0x41, 0x48, 0x03, 0x7C, 0x54, 0x51, 0xC0, 0xAC, 0xFE, 0xAB, 0xB3, - 0xDA, 0x89, 0xF0, 0x4A, 0xF2, 0x60, 0x69, 0x87, 0xA8, 0x29, 0x13, 0xE2, 0x73, 0x7D, 0x58, 0x12, - 0xB7, 0x79, 0x86, 0x46, 0x58, 0xC1, 0xDE, 0x04, 0x72, 0x90, 0x24, 0x4F, 0x2F, 0xF9, 0x06, 0x57, - 0xCD, 0xF1, 0xD5, 0xA3, 0x15, 0x29, 0x08, 0x05, 0x3E, 0x2B, 0x8B, 0x74, 0xAC, 0xA6, 0x24, 0x46, - 0x14, 0xC9, 0x27, 0x97, 0x11, 0x2F, 0x46, 0x83, 0x2A, 0xE5, 0x1C, 0xF9, 0x32, 0x4B, 0x23, 0x2F, - 0xAF, 0xE3, 0x3D, 0x65, 0xE5, 0x2E, 0x50, 0xDB, 0xF8, 0xA6, 0xA5, 0xC7, 0x73, 0xD9, 0x89, 0x35, - 0xBC, 0x74, 0x5B, 0x58, 0x94, 0xA4, 0xF1, 0x72, 0x05, 0x2B, 0xF1, 0xF0, 0xCE, 0x8D, 0x06, 0x37, - 0xA4, 0xA8, 0x0A, 0x0B, 0x4F, 0xA0, 0xD7, 0xF6, 0x74, 0x14, 0xBD, 0xD2, 0xB2, 0xE1, 0xF3, 0x9E, - 0x68, 0x7D, 0xF2, 0xBE, 0x79, 0xFE, 0x9D, 0xA7, 0xA7, 0x94, 0xD5, 0x5E, 0x5E, 0x18, 0xE0, 0xB5, - 0xDD, 0xC5, 0xCA, 0xEB, 0xF7, 0x1C, 0x5A, 0xF2, 0x36, 0xC5, 0x5C, 0x09, 0xC2, 0xE2, 0x2A, 0x97, - 0x64, 0xBA, 0xEF, 0x39, 0x57, 0x92, 0x97, 0x45, 0x34, 0xC9, 0xE3, 0x11, 0xE5, 0xF3, 0x71, 0x2E, - 0xE5, 0x95, 0x47, 0xA2, 0xCC, 0xBC, 0x97, 0x02, 0x19, 0x27, 0x5B, 0x4C, 0x73, 0x6F, 0x6F, 0x11, - 0x5D, 0x65, 0x73, 0xEB, 0x11, 0x28, 0x97, 0x0B, 0x7B, 0xE5, 0x71, 0xC8, 0xEB, 0x13, 0x69, 0xA1, - 0xE4, 0x1F, 0xA3, 0xE1, 0x55, 0x68, 0x73, 0xE9, 0x3F, 0x96, 0xD8, 0x2B, 0xB1, 0xC0, 0x7B, 0xA0, - 0x80, 0x85, 0x87, 0x17, 0x79, 0xD6, 0xEE, 0xE1, 0xFF, 0x03, 0xDF, 0x1B, 0x82, 0xF1, 0x9B, 0x9A, - 0x00 + 0xED, 0xF8, 0x9D, 0x7E, 0xBC, 0x3C, 0x3A, 0xBD, 0x38, 0x3C, 0x3F, 0x85, 0x35, 0x6A, 0x6D, 0x73, + 0x74, 0xEA, 0xE3, 0x56, 0xAE, 0x32, 0xA7, 0x48, 0xD9, 0xA3, 0xDD, 0xDB, 0xF7, 0x34, 0x52, 0x8C, + 0x8E, 0x3A, 0xC3, 0x96, 0xDA, 0x25, 0x6D, 0x3F, 0x51, 0x35, 0x6F, 0xCA, 0x96, 0x66, 0x4E, 0xCB, + 0xFA, 0x87, 0xE7, 0xBF, 0x1C, 0x9E, 0x37, 0x68, 0x17, 0xB7, 0x23, 0x04, 0xFA, 0x9B, 0xFB, 0x00, + 0x2C, 0x77, 0x89, 0x7D, 0x0B, 0x4E, 0x2C, 0x3F, 0x22, 0x7E, 0x6E, 0x6D, 0xDD, 0xFF, 0x74, 0x7E, + 0x7E, 0x78, 0x6A, 0xEC, 0xC1, 0xDC, 0x46, 0x26, 0x83, 0x18, 0xA6, 0x92, 0xE9, 0x04, 0xED, 0x39, + 0x4F, 0xC7, 0xF8, 0xC4, 0x6D, 0x93, 0xA7, 0x29, 0x9D, 0x8E, 0xEE, 0xF5, 0xB3, 0x68, 0x3E, 0x60, + 0xF4, 0xB6, 0xC5, 0xEE, 0xBA, 0x28, 0x72, 0xD8, 0x29, 0x44, 0x64, 0xE6, 0x46, 0x7D, 0xA5, 0x0B, + 0xB1, 0x9F, 0xE5, 0xAD, 0xD0, 0xCC, 0x03, 0x4D, 0x05, 0x92, 0x86, 0x9B, 0x48, 0x1F, 0x6F, 0x12, + 0x9D, 0x76, 0x74, 0xA5, 0x5B, 0xAC, 0xE7, 0xE3, 0x4E, 0xFC, 0xF8, 0xEE, 0x37, 0xFA, 0x28, 0x95, + 0xCC, 0x5D, 0x46, 0xF9, 0xB3, 0x3D, 0x05, 0xED, 0x7F, 0x2F, 0x9E, 0x06, 0xC3, 0xAD, 0xA8, 0x6B, + 0xA9, 0x79, 0x3F, 0xDD, 0x18, 0xD5, 0x8D, 0x31, 0xB8, 0x0A, 0xAA, 0xE6, 0x3E, 0xB6, 0xA3, 0xA0, + 0x52, 0x33, 0xBA, 0x09, 0x1A, 0x43, 0x26, 0x27, 0x61, 0xC8, 0xF1, 0xCA, 0x23, 0x4E, 0x0A, 0x7B, + 0x8B, 0xEF, 0x8D, 0xA0, 0x3D, 0xED, 0xB6, 0x72, 0xDF, 0x7E, 0x34, 0xB2, 0xB2, 0x64, 0xB4, 0xD4, + 0x31, 0xB6, 0xC3, 0xF3, 0xF3, 0x8F, 0xEA, 0x2C, 0xF4, 0x48, 0x43, 0xAB, 0xCC, 0xE4, 0x33, 0x6B, + 0x10, 0x8B, 0x41, 0xD5, 0x7A, 0xE5, 0x29, 0x56, 0x75, 0x61, 0xE8, 0x47, 0x76, 0x4C, 0x5D, 0x3C, + 0x74, 0x28, 0xF6, 0xE4, 0xE2, 0xBD, 0x22, 0xA3, 0xA3, 0x95, 0x27, 0xA7, 0xEA, 0xC3, 0x53, 0xA3, + 0xC2, 0x37, 0x09, 0xF5, 0x07, 0x0F, 0xAB, 0x9A, 0x70, 0x0D, 0x99, 0x74, 0x74, 0xA1, 0x93, 0xD9, + 0xCD, 0x6C, 0x34, 0x6A, 0xEF, 0xAA, 0x2A, 0xC9, 0x22, 0xDE, 0xBB, 0xB7, 0xD4, 0x23, 0x36, 0x3E, + 0xD0, 0x1B, 0x2C, 0x84, 0x22, 0xBF, 0x19, 0x0A, 0xF3, 0x1E, 0x27, 0x2A, 0xE8, 0x66, 0x2F, 0x72, + 0xAF, 0x79, 0x96, 0x31, 0x8C, 0xEA, 0x63, 0x26, 0x42, 0xAC, 0x30, 0xF1, 0x5B, 0x1A, 0xB0, 0x0D, + 0x9E, 0x14, 0x39, 0x38, 0xE8, 0x38, 0xF1, 0x3F, 0xB6, 0x9D, 0x6E, 0x4B, 0x41, 0xEA, 0x31, 0xAE, + 0x23, 0xB4, 0x15, 0xF8, 0xA6, 0xD6, 0x22, 0xD2, 0x3C, 0xF4, 0x80, 0x94, 0xBA, 0x5A, 0x8F, 0x31, + 0x26, 0x15, 0xA1, 0xF9, 0xEA, 0x6B, 0x5C, 0x61, 0x67, 0xFF, 0xE3, 0xC7, 0xF3, 0x83, 0xA3, 0xD3, + 0xBD, 0x8B, 0x43, 0x70, 0xFF, 0xCE, 0x3E, 0x5D, 0x5C, 0x5E, 0x7C, 0x3E, 0xC3, 0x5F, 0x7F, 0xD9, + 0x3B, 0x3E, 0x3A, 0xB8, 0xFC, 0x74, 0xFA, 0x97, 0xD3, 0x8F, 0xBF, 0x9E, 0xA6, 0x5B, 0xF6, 0x8E, + 0x1D, 0xDE, 0x48, 0xF7, 0xE1, 0x13, 0xF3, 0x88, 0x01, 0xF5, 0x86, 0xEF, 0x0E, 0x1D, 0xB8, 0x63, + 0x7B, 0x64, 0x28, 0xE1, 0xA6, 0xEA, 0xE3, 0xF5, 0x31, 0x65, 0xAF, 0x6C, 0xEA, 0x67, 0x97, 0x60, + 0x3C, 0xC0, 0xDB, 0x8A, 0xF0, 0x31, 0xB7, 0x44, 0x2E, 0xFC, 0xCD, 0x24, 0xBC, 0x69, 0x8D, 0xEA, + 0x45, 0xEE, 0x6E, 0x6C, 0x36, 0x5D, 0x0D, 0x99, 0xE0, 0x41, 0xC6, 0xD3, 0x30, 0xB1, 0xCA, 0x03, + 0xDB, 0x23, 0x14, 0x05, 0xC2, 0x4C, 0xA6, 0xEB, 0x41, 0xE7, 0xBB, 0x0E, 0xBB, 0x33, 0x1F, 0x8A, + 0x2A, 0x7B, 0x84, 0x7F, 0xE3, 0xB5, 0xF0, 0x59, 0x5A, 0x96, 0xE5, 0x8E, 0x9F, 0x72, 0x86, 0x6D, + 0xB2, 0xD2, 0xC6, 0x68, 0xDA, 0x36, 0xEB, 0xA6, 0x8E, 0x7A, 0x92, 0x27, 0x19, 0xDF, 0x44, 0xF0, + 0xBA, 0xE9, 0x55, 0x2F, 0x09, 0x87, 0x8E, 0x3B, 0x74, 0xA3, 0xB4, 0x9B, 0xF0, 0x88, 0x3A, 0xEF, + 0xC2, 0x28, 0x02, 0xA8, 0x62, 0x63, 0x77, 0x05, 0x8C, 0xF2, 0x5A, 0x5E, 0x2E, 0x7A, 0x57, 0x46, + 0x26, 0x87, 0x58, 0x16, 0x56, 0x16, 0x96, 0xD2, 0x0E, 0x5C, 0x5E, 0x66, 0x6F, 0x5D, 0x8D, 0x46, + 0x64, 0xE8, 0xFB, 0x4E, 0x05, 0x68, 0x02, 0xD0, 0x69, 0x3F, 0xD7, 0x06, 0xEF, 0x20, 0x71, 0xA9, + 0x5D, 0x45, 0x08, 0xE2, 0x9D, 0x97, 0x46, 0xCA, 0x2A, 0x4E, 0xBB, 0xD9, 0x82, 0x0D, 0xD4, 0x08, + 0xE3, 0x78, 0x42, 0x45, 0x05, 0x58, 0xDA, 0x04, 0xF5, 0x68, 0x0D, 0xBC, 0x7B, 0x54, 0xA2, 0x89, + 0x1F, 0x86, 0x2E, 0x46, 0xFB, 0x72, 0xAD, 0xC0, 0x71, 0x1A, 0xEB, 0x4B, 0x3A, 0x24, 0xD3, 0x0F, + 0x27, 0x27, 0x9D, 0x31, 0xFF, 0x97, 0x7E, 0x23, 0xA6, 0x8F, 0x2B, 0xA6, 0x8F, 0x27, 0x27, 0xFD, + 0x7E, 0x27, 0x64, 0xFF, 0x14, 0x70, 0x62, 0xF8, 0x0C, 0x08, 0x56, 0xD2, 0xCF, 0x2F, 0x8C, 0x7A, + 0xC2, 0xEE, 0xA8, 0xCD, 0x2E, 0xB9, 0xFF, 0x8B, 0x21, 0xD0, 0x9E, 0xDF, 0x21, 0xEB, 0x30, 0xDA, + 0xB6, 0xAD, 0xB5, 0xB5, 0xF5, 0x97, 0x2C, 0xBB, 0x20, 0x93, 0x5F, 0x27, 0x8D, 0xBF, 0x4E, 0x47, + 0xFC, 0x1B, 0xD2, 0x9B, 0x07, 0xE1, 0x8F, 0x38, 0xFE, 0x2C, 0x96, 0xF1, 0x02, 0x46, 0x5A, 0x8F, + 0xD8, 0x23, 0xCC, 0xB9, 0xE8, 0x20, 0x23, 0xC4, 0xDA, 0x20, 0xBD, 0x8D, 0x4E, 0xCF, 0x5A, 0xDF, + 0x36, 0xB0, 0x92, 0xDA, 0xA4, 0x37, 0x64, 0x6D, 0xCE, 0x9C, 0xF4, 0x18, 0x33, 0x6B, 0x29, 0x33, + 0x2B, 0x5D, 0x6B, 0x63, 0xA5, 0xDB, 0x5D, 0xB1, 0x36, 0x3A, 0xDD, 0xCD, 0x9E, 0x89, 0x1D, 0xB3, + 0x65, 0x7B, 0x83, 0x57, 0x18, 0xE6, 0xC4, 0xDA, 0x4B, 0xE4, 0xE9, 0x9A, 0xDE, 0xD1, 0x80, 0xF3, + 0xD3, 0xED, 0x22, 0x37, 0x5B, 0x5B, 0xDB, 0xDB, 0x3D, 0xB2, 0x78, 0xC0, 0x35, 0x0B, 0xAB, 0xF0, + 0xDF, 0x96, 0x12, 0x1E, 0x53, 0x77, 0xD6, 0xA3, 0x43, 0x3B, 0x02, 0xBB, 0xD9, 0x77, 0x87, 0x9E, + 0xEA, 0x3D, 0xA8, 0x63, 0xD7, 0x4A, 0x0D, 0x47, 0x6A, 0xA5, 0x92, 0x62, 0xEE, 0x77, 0xE1, 0xB5, + 0x81, 0x3D, 0xC9, 0xB8, 0xB5, 0x51, 0x74, 0x18, 0xD9, 0xCF, 0xCE, 0xB1, 0xF0, 0x6E, 0x01, 0x18, + 0x2F, 0x26, 0x0A, 0x6E, 0x3E, 0xD2, 0x9B, 0x44, 0x2A, 0x13, 0x6A, 0xD8, 0x52, 0xD2, 0xA9, 0x2B, + 0x2B, 0x88, 0x08, 0xD3, 0x84, 0xA6, 0xFD, 0x0C, 0xD6, 0x1A, 0xE7, 0x4C, 0xBE, 0xE5, 0xC0, 0xDE, + 0xF0, 0x0E, 0x6F, 0x28, 0xB7, 0xE0, 0x3C, 0xBB, 0x28, 0x4B, 0xBC, 0x21, 0x88, 0xC6, 0x64, 0x48, + 0x08, 0x74, 0xF4, 0xED, 0x38, 0x59, 0x8F, 0xB9, 0xA1, 0xC5, 0x35, 0x95, 0x34, 0xCB, 0x25, 0xDF, + 0x72, 0xFA, 0x75, 0x97, 0xDD, 0x4D, 0xC1, 0x27, 0x24, 0x73, 0xCB, 0x37, 0x97, 0x60, 0x41, 0xB6, + 0xBA, 0x9A, 0x1D, 0xF1, 0xF2, 0x33, 0xDF, 0xCD, 0xE7, 0x6A, 0x8E, 0x57, 0x8A, 0x39, 0xE0, 0x49, + 0x46, 0xD8, 0x91, 0x12, 0xBF, 0xA4, 0xC4, 0x0E, 0x5A, 0x41, 0xBC, 0xDE, 0x20, 0xBE, 0xFB, 0x9D, + 0x3A, 0x0C, 0xAC, 0x9B, 0xC0, 0xF9, 0x24, 0x42, 0x6F, 0x14, 0x2C, 0xC2, 0xBE, 0xA8, 0x28, 0x24, + 0xD4, 0xFC, 0xE6, 0xB7, 0x25, 0xE3, 0x48, 0x27, 0xBE, 0xB4, 0xDA, 0xCA, 0x6E, 0x62, 0xAA, 0xF8, + 0x89, 0xB2, 0x72, 0x5B, 0x9C, 0x25, 0x2A, 0xE6, 0xC9, 0xF1, 0x8B, 0x09, 0x25, 0x64, 0x4E, 0x4E, + 0xE4, 0xA8, 0xBF, 0x77, 0x2E, 0x4C, 0xD1, 0x30, 0xBD, 0x28, 0x53, 0x6E, 0x3A, 0x31, 0xB3, 0xAB, + 0x53, 0x1F, 0xAF, 0x17, 0xD9, 0x04, 0x04, 0xBD, 0xB1, 0xD2, 0xD5, 0x77, 0xFE, 0x67, 0x15, 0xFD, + 0xE5, 0xE9, 0xC7, 0xCB, 0x83, 0xC3, 0xFD, 0xA3, 0x93, 0xBD, 0x63, 0xAD, 0x17, 0x42, 0x0A, 0x13, + 0x90, 0x83, 0xCD, 0x4A, 0xF8, 0xD1, 0xC4, 0x2D, 0xAB, 0x03, 0x5F, 0x5C, 0x71, 0x08, 0xA3, 0xC8, + 0xD2, 0x01, 0x25, 0x0B, 0x5A, 0x06, 0x89, 0xE5, 0xF8, 0xE7, 0x44, 0x5E, 0x02, 0x00, 0x44, 0x26, + 0x05, 0xD9, 0x19, 0x5C, 0xAB, 0x98, 0xD8, 0x72, 0x8A, 0x64, 0x95, 0x6C, 0xC2, 0x14, 0xC0, 0x52, + 0x06, 0xC4, 0x34, 0x56, 0xC9, 0xDA, 0x26, 0xE6, 0xCA, 0x59, 0xD2, 0xEE, 0xBC, 0x2B, 0x23, 0xD9, + 0xEC, 0xD7, 0x98, 0xC8, 0xFE, 0x19, 0xBB, 0x43, 0x7E, 0x07, 0xF3, 0xC1, 0xB4, 0x7A, 0xD2, 0x86, + 0x28, 0x8E, 0x46, 0x75, 0x80, 0xB2, 0xF1, 0x99, 0x3B, 0xFC, 0x36, 0x70, 0x74, 0xE6, 0x96, 0xAE, + 0x27, 0x63, 0x53, 0x99, 0xA1, 0xE7, 0x37, 0x34, 0x2B, 0x0E, 0xCC, 0x74, 0x44, 0x2A, 0x1A, 0x92, + 0x33, 0x1C, 0xF5, 0xA1, 0x51, 0x77, 0x00, 0xE6, 0x0E, 0x3F, 0xB3, 0x9E, 0x2A, 0xA2, 0x61, 0x71, + 0xCC, 0x02, 0xC0, 0x80, 0xD8, 0xAC, 0xA4, 0x75, 0x95, 0xEE, 0x91, 0xF5, 0x4B, 0x55, 0x30, 0x45, + 0x9B, 0xBA, 0x5C, 0x1F, 0x56, 0x1E, 0x49, 0x21, 0x2E, 0x4F, 0x4E, 0x2E, 0x0F, 0xF6, 0xFA, 0x1F, + 0x34, 0xB5, 0x10, 0xD1, 0x54, 0xA9, 0xD9, 0x12, 0x77, 0xE5, 0x56, 0xF4, 0xBB, 0x94, 0xA9, 0x0E, + 0x08, 0x53, 0x8E, 0x90, 0x98, 0x9D, 0x29, 0xED, 0xB0, 0x9C, 0xAE, 0x95, 0xEB, 0x77, 0xBF, 0x4A, + 0xC6, 0x34, 0xD3, 0xBB, 0xCF, 0xAC, 0xB3, 0xF2, 0xFB, 0xAA, 0x97, 0xF4, 0x55, 0xEC, 0x1D, 0xCF, + 0xBD, 0xAF, 0xC0, 0xBC, 0x3F, 0xB3, 0xEE, 0x7A, 0x36, 0x73, 0x9F, 0x24, 0x9E, 0x2A, 0x53, 0xA0, + 0xDC, 0xA0, 0x5E, 0xDA, 0xA0, 0xEC, 0x1C, 0xF8, 0x8F, 0x3E, 0x41, 0x71, 0xA5, 0x4C, 0x37, 0x70, + 0xE6, 0xAA, 0x93, 0x3B, 0x25, 0x62, 0x4A, 0x0D, 0xF8, 0x0F, 0x13, 0x80, 0xB0, 0xA0, 0xE4, 0xF1, + 0x2C, 0x68, 0xC5, 0xD1, 0x48, 0x7E, 0x1A, 0xCF, 0xA2, 0x7E, 0xEA, 0x25, 0xFD, 0x44, 0x1E, 0x67, + 0x5D, 0xC2, 0x0D, 0xC4, 0x33, 0xEA, 0xAC, 0xE7, 0x66, 0x3A, 0xFF, 0xA7, 0x59, 0x4D, 0xB1, 0xA1, + 0xA5, 0x9C, 0x0C, 0x19, 0x10, 0xF0, 0xC3, 0x21, 0x43, 0x41, 0x92, 0x3B, 0x6C, 0x7B, 0x49, 0x4B, + 0x1C, 0x60, 0xE8, 0x0E, 0x7E, 0xE6, 0x93, 0x6E, 0xCC, 0x4B, 0x3B, 0xEC, 0xB8, 0xA9, 0x9B, 0x5E, + 0xB0, 0x6F, 0x13, 0x7F, 0x1A, 0xE1, 0x1F, 0xB6, 0xD8, 0xB5, 0x07, 0xA0, 0xBE, 0xAF, 0xEE, 0xC1, + 0xE3, 0x86, 0xF2, 0x15, 0x48, 0x6B, 0x4C, 0xC9, 0x82, 0x36, 0x64, 0x16, 0xDA, 0x84, 0x46, 0x03, + 0x39, 0x64, 0x98, 0xF1, 0xCD, 0xF8, 0x90, 0xF8, 0x6A, 0x9B, 0x54, 0xC6, 0xBC, 0x5F, 0x2F, 0x36, + 0x2F, 0xA5, 0x83, 0x46, 0x7E, 0xB3, 0xC2, 0xA0, 0x71, 0xD5, 0x55, 0x6E, 0xC9, 0x38, 0xAC, 0x53, + 0x0D, 0x4B, 0xBF, 0x2D, 0x49, 0x62, 0xD6, 0x4F, 0x6B, 0x65, 0x36, 0xCC, 0x67, 0x5D, 0x33, 0xB2, + 0x79, 0x29, 0xAD, 0x79, 0x60, 0xDD, 0x36, 0x23, 0xB6, 0xB9, 0x22, 0x8B, 0x5D, 0xF7, 0x39, 0xA3, + 0xEC, 0x7F, 0x3E, 0x79, 0xFB, 0xF1, 0x98, 0x21, 0xD5, 0xAF, 0xAC, 0x8C, 0x7C, 0x6F, 0xC8, 0xB2, + 0x34, 0x1D, 0xD0, 0x61, 0x40, 0xF5, 0xFD, 0x91, 0x4C, 0x4F, 0x68, 0x5D, 0x0B, 0x8B, 0x33, 0x1D, + 0x81, 0xB1, 0x1E, 0x0C, 0xD7, 0x4D, 0x6B, 0x47, 0xCB, 0x7C, 0x99, 0x94, 0xBE, 0x26, 0xB9, 0x96, + 0x8F, 0x0F, 0x74, 0xC9, 0x74, 0x29, 0x7A, 0x35, 0xC8, 0x0E, 0xDB, 0x97, 0x4B, 0x99, 0x0C, 0x9B, + 0x33, 0x76, 0x6F, 0x1E, 0x6B, 0xC9, 0x10, 0xCA, 0x88, 0x70, 0x19, 0x46, 0x15, 0xB3, 0x2E, 0x71, + 0xD5, 0x9D, 0xEC, 0xE1, 0xC5, 0x9C, 0x14, 0xA5, 0x11, 0x73, 0x2B, 0x4F, 0xC1, 0x1D, 0xD7, 0xB9, + 0x46, 0xFC, 0xFD, 0xF7, 0x7F, 0xA9, 0x0C, 0xE2, 0xB7, 0x85, 0x96, 0xCA, 0x66, 0x13, 0xBC, 0xC4, + 0xD4, 0x6E, 0xCD, 0xB6, 0xCC, 0xA5, 0xE9, 0xFD, 0x25, 0x79, 0x00, 0xCF, 0xAE, 0x82, 0x73, 0x46, + 0x28, 0xAD, 0xAA, 0x1E, 0x03, 0xAF, 0xDE, 0xF3, 0x73, 0x12, 0x81, 0xE4, 0xCA, 0x3C, 0x06, 0xD7, + 0x8F, 0x8B, 0x5D, 0x5B, 0xC1, 0x2E, 0xFD, 0xA3, 0x9B, 0x61, 0x85, 0xE7, 0x13, 0xD3, 0xD6, 0x7A, + 0x1D, 0x9E, 0x05, 0x82, 0x22, 0x9E, 0x2B, 0x4F, 0x00, 0x9B, 0x73, 0x9F, 0x00, 0xE4, 0xD1, 0x57, + 0x73, 0x0A, 0xC8, 0x88, 0xE8, 0x89, 0xA6, 0x86, 0xCC, 0xE8, 0xAE, 0x3B, 0x3B, 0x98, 0x18, 0x5F, + 0x79, 0x22, 0xCE, 0x67, 0x9E, 0x39, 0x4C, 0xCC, 0x2F, 0x64, 0xA7, 0x94, 0x7F, 0x6D, 0xB5, 0x1E, + 0xAB, 0x0D, 0x4B, 0x8D, 0xA7, 0x27, 0x13, 0xEF, 0xE4, 0xB1, 0x05, 0x9F, 0x6B, 0x5E, 0xE7, 0xA4, + 0xEE, 0xD2, 0x35, 0x4C, 0xA3, 0x59, 0x98, 0xB3, 0x02, 0xCD, 0xD8, 0x92, 0xE2, 0x7E, 0x78, 0xE2, + 0xB6, 0xE8, 0x13, 0xC7, 0xFC, 0x47, 0x74, 0x51, 0x83, 0x32, 0xD7, 0x94, 0x54, 0x7A, 0x5A, 0xCC, + 0x63, 0x1C, 0x84, 0x34, 0xC0, 0x27, 0x23, 0x05, 0xCC, 0xEA, 0xBF, 0x3A, 0xAB, 0x9D, 0x08, 0x2F, + 0x5C, 0x0F, 0x96, 0x76, 0x88, 0x9A, 0x10, 0x22, 0x3E, 0xD7, 0x87, 0x25, 0x71, 0x9B, 0xE7, 0x9F, + 0x84, 0x15, 0xEC, 0x4D, 0x20, 0x07, 0x49, 0xF2, 0xE4, 0x99, 0x6F, 0x70, 0xD5, 0x1C, 0x5F, 0xAC, + 0x5A, 0x91, 0x82, 0x50, 0xE0, 0xB3, 0xB2, 0x48, 0xC7, 0x6A, 0x4A, 0xDA, 0x47, 0x91, 0x5A, 0x73, + 0x19, 0xF1, 0x62, 0x34, 0xA8, 0x52, 0xCE, 0x91, 0x2F, 0xB3, 0x24, 0xF9, 0xF2, 0x3A, 0xDE, 0x53, + 0x56, 0xEE, 0x02, 0xB5, 0x8D, 0x2F, 0x76, 0x7A, 0x3C, 0x53, 0x9F, 0x58, 0xC3, 0x4B, 0x77, 0xA1, + 0x45, 0x49, 0x1A, 0x2F, 0x57, 0xB0, 0x12, 0x0F, 0xEF, 0xDC, 0x68, 0x70, 0x43, 0x8A, 0xAA, 0xB0, + 0xF0, 0x04, 0x7A, 0x6D, 0x4F, 0x47, 0xD1, 0x2B, 0x2D, 0xD7, 0x3F, 0xEF, 0x89, 0xD6, 0x27, 0xEF, + 0x9B, 0xE7, 0xDF, 0x79, 0x7A, 0xC2, 0x5C, 0xED, 0x5D, 0x89, 0x01, 0x5E, 0x4A, 0x5E, 0xAC, 0xBC, + 0x7E, 0xCF, 0xA1, 0x25, 0x6F, 0x53, 0xCC, 0x95, 0x20, 0x2C, 0xAE, 0x72, 0x49, 0xA6, 0xFB, 0x9E, + 0x73, 0x25, 0x79, 0x59, 0x44, 0x93, 0x3C, 0x1E, 0x51, 0x3E, 0x1F, 0xE7, 0x52, 0x5E, 0x79, 0x24, + 0xCA, 0xCC, 0x7B, 0x29, 0x90, 0x71, 0xB2, 0xC5, 0x34, 0xF7, 0xF6, 0x16, 0xD1, 0x55, 0x36, 0xB7, + 0x1E, 0x81, 0x72, 0xB9, 0xB0, 0x57, 0x1E, 0x87, 0xBC, 0x3E, 0x91, 0x16, 0x4A, 0xFE, 0x31, 0x1A, + 0x5E, 0x85, 0x36, 0x97, 0xFE, 0x63, 0x89, 0xBD, 0x12, 0x0B, 0xBC, 0x07, 0x0A, 0x58, 0x78, 0x78, + 0x91, 0x67, 0xED, 0x1E, 0xFE, 0x3F, 0x1B, 0x62, 0x1E, 0xA2, 0x79, 0x9B, 0x00 }; ///main_js //To convert AP-Config\index.html to index_html[], run the Python index_html_zipper.py script in the Tools folder: @@ -1048,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x35, 0x44, 0x85, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0x1F, 0x62, 0x85, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From 6e14f7f41b3d5071232a8f535e0c413145781325 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 13 Jan 2025 14:34:48 -0700 Subject: [PATCH 117/276] Add missing functions for compile guards --- Firmware/RTK_Everywhere/Developer.ino | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 180b6e80d..e82a8fb0f 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -46,6 +46,7 @@ const uint8_t * networkGetMacAddress() bool networkHasInternet() {return false;} bool networkHasInternet(NetIndex_t index) {return false;} bool networkInterfaceHasInternet(NetIndex_t index) {return false;} +bool networkIsInterfaceStarted(NetIndex_t index) {return false;} void networkMarkOffline(NetIndex_t index) {} void networkMarkHasInternet(NetIndex_t index) {} void networkUpdate() {} @@ -169,9 +170,11 @@ void sendStringToWebsocket(const char* stringToSend) {} void menuWiFi() {systemPrintln("**WiFi not compiled**");} bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) {return false;} +bool wifiStart() {return false;} int wifiNetworkCount() {return 0;} bool wifiStationIsRunning() {return false;} bool wifiApIsRunning() {return false;} +bool wifiIsRunning() {return false;} uint32_t wifiGetStartTimeout() {return 0;} #define WIFI_STOP() {} From 631a8d6cb3ab3ccac44e4e57d324d30a3a09471a Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 13 Jan 2025 14:35:08 -0700 Subject: [PATCH 118/276] Add LG290P reset for firmware upgrades --- Firmware/RTK_Everywhere/menuSystem.ino | 33 +++++++++++++++++++------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index e04114ea6..2627e52eb 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -203,7 +203,8 @@ void menuSystem() if (settings.shutdownNoChargeTimeoutMinutes == 0) systemPrintln("c) Shutdown if not charging: Disabled"); else - systemPrintf("c) Shutdown if not charging after: %d minutes\r\n", settings.shutdownNoChargeTimeoutMinutes); + systemPrintf("c) Shutdown if not charging after: %d minutes\r\n", + settings.shutdownNoChargeTimeoutMinutes); } systemPrintln("d) Debug software"); @@ -393,7 +394,7 @@ void menuSystem() else if (incoming == 'B') { forceSystemStateUpdate = true; // Immediately go to this new state - baseCasterDisableOverride(); // Leave Caster mode + baseCasterDisableOverride(); // Leave Caster mode changeState(STATE_BASE_NOT_STARTED); } else if (incoming == 'C') @@ -489,6 +490,8 @@ void menuDebugHardware() if (present.gnss_um980) systemPrintln("13) UM980 direct connect"); + else if (present.gnss_lg290p) + systemPrintln("13) LG290P reset for firmware update"); systemPrint("14) PSRAM ("); if (ESP.getPsramSize() == 0) @@ -560,16 +563,28 @@ void menuDebugHardware() { settings.enableImuCompensationDebug ^= 1; } - else if (incoming == 13 && present.gnss_um980) + else if (incoming == 13) { - // Create a file in LittleFS - if (createUm980Passthrough() == true) + if (present.gnss_um980) { - systemPrintln(); - systemPrintln("UM980 passthrough mode has been recorded to LittleFS. Device will now reset."); - systemFlush(); // Complete prints + // Create a file in LittleFS + if (createUm980Passthrough() == true) + { + systemPrintln(); + systemPrintln("UM980 passthrough mode has been recorded to LittleFS. Device will now reset."); + systemFlush(); // Complete prints - ESP.restart(); + ESP.restart(); + } + } + else if (present.gnss_lg290p) + { + systemPrintln(); + systemPrintln("QGNSS must be connected to CH342 Port B at 460800bps. Begin firmware update from QGNSS (hit the play button) then reset the LG290P."); + lg290pReset(); + delay(100); + lg290pBoot(); + systemPrintln("LG290P reset complete."); } } else if (incoming == 14) From a66530dd535eb7bb89521540e404d40f428a8f79 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 13 Jan 2025 15:58:22 -0700 Subject: [PATCH 119/276] Add support for LG290p v4 firmware Add support for GBS, GNS, GST, ZDA, and RTCM3-1033 messages. Configure messages on all ports (1/2/3 = DATA/BT/RADIO). --- Firmware/RTK_Everywhere/GNSS_LG290P.h | 18 ++-- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 131 +++++++++++++++--------- 2 files changed, 97 insertions(+), 52 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.h b/Firmware/RTK_Everywhere/GNSS_LG290P.h index 9c4b96db9..5cc7e4fbf 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.h +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.h @@ -25,24 +25,30 @@ typedef struct { const char msgTextName[11]; const float msgDefaultRate; + const uint8_t firmwareVersionSupported; // The minimum version this message is supported. + // 0 = all versions. + // 9999 = Not supported } lg290pMsg; // Static array containing all the compatible messages // Rate = Output once every N position fix(es). const lg290pMsg lgMessagesNMEA[] = { - {"RMC", 1}, {"GGA", 1}, {"GSV", 1}, {"GSA", 1}, {"VTG", 1}, {"GLL", 1}, + {"RMC", 1, 0}, {"GGA", 1, 0}, {"GSV", 1, 0}, {"GSA", 1, 0}, {"VTG", 1, 0}, {"GLL", 1, 0}, + {"GBS", 0, 4}, {"GBS", 0, 4}, {"GST", 1, 4}, {"ZDA", 0, 4}, }; const lg290pMsg lgMessagesRTCM[] = { - {"RTCM3-1005", 1}, {"RTCM3-1006", 0}, + {"RTCM3-1005", 1, 0}, {"RTCM3-1006", 0, 0}, - {"RTCM3-1019", 0}, + {"RTCM3-1019", 0, 0}, - {"RTCM3-1020", 0}, + {"RTCM3-1020", 0, 0}, - {"RTCM3-1041", 0}, {"RTCM3-1042", 0}, {"RTCM3-1044", 0}, {"RTCM3-1046", 0}, + {"RTCM3-1033", 0, 4}, //v4 and above - {"RTCM3-107X", 1}, {"RTCM3-108X", 1}, {"RTCM3-109X", 1}, {"RTCM3-111X", 1}, {"RTCM3-112X", 1}, {"RTCM3-113X", 1}, + {"RTCM3-1041", 0, 0}, {"RTCM3-1042", 0, 0}, {"RTCM3-1044", 0, 0}, {"RTCM3-1046", 0, 0}, + + {"RTCM3-107X", 1, 0}, {"RTCM3-108X", 1, 0}, {"RTCM3-109X", 1, 0}, {"RTCM3-111X", 1, 0}, {"RTCM3-112X", 1, 0}, {"RTCM3-113X", 1, 0}, }; #define MAX_LG290P_NMEA_MSG (sizeof(lgMessagesNMEA) / sizeof(lg290pMsg)) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index e96a07bc7..1f13663cc 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -8,6 +8,8 @@ GNSS_LG290P.ino #ifdef COMPILE_LG290P +uint8_t lg290pFirmwareVersion = 0; + //---------------------------------------- // If we have decryption keys, configure module // Note: don't check online.lband_neo here. We could be using ip corrections @@ -105,8 +107,23 @@ void GNSS_LG290P::begin() if (_lg290p->getVersionInfo(version, buildDate, buildTime)) snprintf(gnssFirmwareVersion, sizeof(gnssFirmwareVersion), "%s", version.c_str()); - if (sscanf(gnssFirmwareVersion, "%d", &gnssFirmwareVersionInt) != 1) - gnssFirmwareVersionInt = 99; + // Version strings look like LG290P03AANR01A03S and is version 03 + char *spot = strnstr(gnssFirmwareVersion, "LG290P03AANR01A", sizeof(gnssFirmwareVersion)); + if (spot != NULL) + { + spot += strlen("LG290P03AANR01A"); + if (sscanf(spot, "%d", &lg290pFirmwareVersion) != 1) + lg290pFirmwareVersion = 99; + } + + if (lg290pFirmwareVersion < 4) + { + systemPrintf( + "Current LG290P firmware: v%d (full form: %s). GST and DATA port configuration require v4 or newer. Please " + "update the " + "firmware on your LG290P to allow for these features. Please see https://bit.ly/sfe-rtk-lg290p-update\r\n", + lg290pFirmwareVersion, gnssFirmwareVersion); + } snprintf(gnssUniqueId, sizeof(gnssUniqueId), "%s", getId()); } @@ -511,27 +528,35 @@ bool GNSS_LG290P::enableNMEA() bool gpggaEnabled = false; bool gpzdaEnabled = false; - for (int messageNumber = 0; messageNumber < MAX_LG290P_NMEA_MSG; messageNumber++) + for (int portNumber = 0; portNumber < 3; portNumber++) { - if (_lg290p->setMessageRate(lgMessagesNMEA[messageNumber].msgTextName, - settings.lg290pMessageRatesNMEA[messageNumber]) == false) + for (int messageNumber = 0; messageNumber < MAX_LG290P_NMEA_MSG; messageNumber++) { - if (settings.debugGnss) - systemPrintf("Enable NMEA failed at messageNumber %d %s.\r\n", messageNumber, - lgMessagesNMEA[messageNumber].msgTextName); - response &= false; // If any one of the commands fails, report failure overall - } + // Check if this NMEA message is supported by the current LG290P firmware + if (lg290pFirmwareVersion >= lgMessagesNMEA[messageNumber].firmwareVersionSupported) + { + // Enable this message, at this rate, on this port + if (_lg290p->setMessageRateOnPort(lgMessagesNMEA[messageNumber].msgTextName, + settings.lg290pMessageRatesNMEA[messageNumber], portNumber + 1) == false) + { + if (settings.debugGnss) + systemPrintf("Enable NMEA failed at messageNumber %d %s.\r\n", messageNumber, + lgMessagesNMEA[messageNumber].msgTextName); + response &= false; // If any one of the commands fails, report failure overall + } - // If we are using IP based corrections, we need to send local data to the PPL - // The PPL requires being fed GPGGA/ZDA, and RTCM1019/1020/1042/1046 - if (strstr(settings.pointPerfectKeyDistributionTopic, "/ip") != nullptr) - { - // Mark PPL required messages as enabled if rate > 0 - if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "GGA") == 0) - gpggaEnabled = true; - // ZDA not supported on LG290P - // if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "ZDA") == 0) - gpzdaEnabled = true; + // If we are using IP based corrections, we need to send local data to the PPL + // The PPL requires being fed GPGGA/ZDA, and RTCM1019/1020/1042/1046 + if (strstr(settings.pointPerfectKeyDistributionTopic, "/ip") != nullptr) + { + // Mark PPL required messages as enabled if rate > 0 + if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "GGA") == 0) + gpggaEnabled = true; + // ZDA not supported on LG290P + // if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "ZDA") == 0) + gpzdaEnabled = true; + } + } } } @@ -557,36 +582,40 @@ bool GNSS_LG290P::enableRTCMBase() for (int messageNumber = 0; messageNumber < MAX_LG290P_RTCM_MSG; messageNumber++) { - // Setting RTCM-1005 must have only the rate - // Setting RTCM-107X must have rate and offset - if (strchr(lgMessagesRTCM[messageNumber].msgTextName, 'X') == nullptr) + // Check if this RTCM message is supported by the current LG290P firmware + if (lg290pFirmwareVersion >= lgMessagesRTCM[messageNumber].firmwareVersionSupported) { - // No X found. This is RTCM-1??? message. No offset. - if (_lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, - settings.lg290pMessageRatesRTCMBase[messageNumber]) == false) + // Setting RTCM-1005 must have only the rate + // Setting RTCM-107X must have rate and offset + if (strchr(lgMessagesRTCM[messageNumber].msgTextName, 'X') == nullptr) { - // if (settings.debugGnss) - systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, - lgMessagesRTCM[messageNumber].msgTextName); - response &= false; // If any one of the commands fails, report failure overall + // No X found. This is RTCM-1??? message. No offset. + if (_lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, + settings.lg290pMessageRatesRTCMBase[messageNumber]) == false) + { + // if (settings.debugGnss) + systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, + lgMessagesRTCM[messageNumber].msgTextName); + response &= false; // If any one of the commands fails, report failure overall + } } - } - else - { - // X found. This is RTCM-1??X message. Assign 'offset' of 0 - if (_lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, - settings.lg290pMessageRatesRTCMBase[messageNumber], 0) == false) + else { - // if (settings.debugGnss) - systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, - lgMessagesRTCM[messageNumber].msgTextName); - response &= false; // If any one of the commands fails, report failure overall + // X found. This is RTCM-1??X message. Assign 'offset' of 0 + if (_lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, + settings.lg290pMessageRatesRTCMBase[messageNumber], 0) == false) + { + // if (settings.debugGnss) + systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, + lgMessagesRTCM[messageNumber].msgTextName); + response &= false; // If any one of the commands fails, report failure overall + } } - } - // If any message is enabled, enable MSM output - if (settings.lg290pMessageRatesRTCMRover[messageNumber] == true) - enableMSM = true; + // If any message is enabled, enable MSM output + if (settings.lg290pMessageRatesRTCMRover[messageNumber] == true) + enableMSM = true; + } } if (enableMSM == true) @@ -1008,8 +1037,18 @@ uint8_t GNSS_LG290P::getLoggingType() { LoggingType logType = LOGGING_CUSTOM; - if (getActiveNmeaMessageCount() == 6 && getActiveRtcmMessageCount() == 0) - logType = LOGGING_STANDARD; + if (lg290pFirmwareVersion <= 3) + { + // GST is not available/default + if (getActiveNmeaMessageCount() == 6 && getActiveRtcmMessageCount() == 0) + logType = LOGGING_STANDARD; + } + else + { + // GST *is* available/default + if (getActiveNmeaMessageCount() == 7 && getActiveRtcmMessageCount() == 0) + logType = LOGGING_STANDARD; + } // What RTCM messages need to be logged to reach LOGGING_PPP? From 4382746e134b26bb285d81e99c47bbb041e69018 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 14 Jan 2025 09:38:21 -0700 Subject: [PATCH 120/276] Properly enable RTCM/NMEA for PPL if message not enabled. Enable messages on all ports if firmware supports it. The previous code failed to check if the message rate was >0 before setting the rtcm1019Enabled = true. This would cause certain messages not to turn on even though the PPL required it. Additionally, on the LG290P, if firmware is >=v4, enable a given message on all ports. --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 255 +++++++++++++++--------- Firmware/RTK_Everywhere/GNSS_UM980.ino | 62 +++--- 2 files changed, 199 insertions(+), 118 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index 1f13663cc..7f3d42770 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -528,36 +528,52 @@ bool GNSS_LG290P::enableNMEA() bool gpggaEnabled = false; bool gpzdaEnabled = false; - for (int portNumber = 0; portNumber < 3; portNumber++) + int portNumber = 1; + + while (portNumber < 4) { for (int messageNumber = 0; messageNumber < MAX_LG290P_NMEA_MSG; messageNumber++) { // Check if this NMEA message is supported by the current LG290P firmware if (lg290pFirmwareVersion >= lgMessagesNMEA[messageNumber].firmwareVersionSupported) { - // Enable this message, at this rate, on this port - if (_lg290p->setMessageRateOnPort(lgMessagesNMEA[messageNumber].msgTextName, - settings.lg290pMessageRatesNMEA[messageNumber], portNumber + 1) == false) - { - if (settings.debugGnss) - systemPrintf("Enable NMEA failed at messageNumber %d %s.\r\n", messageNumber, - lgMessagesNMEA[messageNumber].msgTextName); - response &= false; // If any one of the commands fails, report failure overall - } + // If firmware is 4 or higher, use setMessageRateOnPort, otherwise setMessageRate + if (lg290pFirmwareVersion >= 4) + // Enable this message, at this rate, on this port + response &= + _lg290p->setMessageRateOnPort(lgMessagesNMEA[messageNumber].msgTextName, + settings.lg290pMessageRatesNMEA[messageNumber], portNumber); + else + // Enable this message, at this rate + response &= _lg290p->setMessageRate(lgMessagesNMEA[messageNumber].msgTextName, + settings.lg290pMessageRatesNMEA[messageNumber]); + if (response == false && settings.debugGnss) + systemPrintf("Enable NMEA failed at messageNumber %d %s.\r\n", messageNumber, + lgMessagesNMEA[messageNumber].msgTextName); // If we are using IP based corrections, we need to send local data to the PPL // The PPL requires being fed GPGGA/ZDA, and RTCM1019/1020/1042/1046 - if (strstr(settings.pointPerfectKeyDistributionTopic, "/ip") != nullptr) + if (settings.enablePointPerfectCorrections) { // Mark PPL required messages as enabled if rate > 0 - if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "GGA") == 0) - gpggaEnabled = true; - // ZDA not supported on LG290P - // if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "ZDA") == 0) - gpzdaEnabled = true; + if (settings.lg290pMessageRatesNMEA[messageNumber] > 0) + { + if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "GGA") == 0) + gpggaEnabled = true; + + // ZDA not supported on LG290P + // if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "ZDA") == 0) + // gpzdaEnabled = true; + } } } } + + portNumber++; + + // setMessageRateOnPort only supported on v4 and above + if (lg290pFirmwareVersion < 4) + break; // Don't step through portNumbers } if (settings.enablePointPerfectCorrections) @@ -565,6 +581,7 @@ bool GNSS_LG290P::enableNMEA() // Force on any messages that are needed for PPL if (gpggaEnabled == false) response &= _lg290p->setMessageRate("GGA", 1); + // if (gpzdaEnabled == false) // response &= _lg290p->setMessageRate("ZDA", 1); } @@ -580,49 +597,73 @@ bool GNSS_LG290P::enableRTCMBase() bool response = true; bool enableMSM = false; // Goes true if we need to enable MSM output reporting - for (int messageNumber = 0; messageNumber < MAX_LG290P_RTCM_MSG; messageNumber++) + int portNumber = 1; + + while (portNumber < 4) { - // Check if this RTCM message is supported by the current LG290P firmware - if (lg290pFirmwareVersion >= lgMessagesRTCM[messageNumber].firmwareVersionSupported) + for (int messageNumber = 0; messageNumber < MAX_LG290P_RTCM_MSG; messageNumber++) { - // Setting RTCM-1005 must have only the rate - // Setting RTCM-107X must have rate and offset - if (strchr(lgMessagesRTCM[messageNumber].msgTextName, 'X') == nullptr) + // Check if this RTCM message is supported by the current LG290P firmware + if (lg290pFirmwareVersion >= lgMessagesRTCM[messageNumber].firmwareVersionSupported) { - // No X found. This is RTCM-1??? message. No offset. - if (_lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, - settings.lg290pMessageRatesRTCMBase[messageNumber]) == false) + // Setting RTCM-1005 must have only the rate + // Setting RTCM-107X must have rate and offset + if (strchr(lgMessagesRTCM[messageNumber].msgTextName, 'X') == nullptr) { - // if (settings.debugGnss) - systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, - lgMessagesRTCM[messageNumber].msgTextName); - response &= false; // If any one of the commands fails, report failure overall + // No X found. This is RTCM-1??? message. No offset. + + // If firmware is 4 or higher, use setMessageRateOnPort, otherwise setMessageRate + if (lg290pFirmwareVersion >= 4) + // Enable this message, at this rate, on this port + response &= + _lg290p->setMessageRateOnPort(lgMessagesNMEA[messageNumber].msgTextName, + settings.lg290pMessageRatesNMEA[messageNumber], portNumber); + else + // Enable this message, at this rate + response &= _lg290p->setMessageRate(lgMessagesNMEA[messageNumber].msgTextName, + settings.lg290pMessageRatesNMEA[messageNumber]); + + if (response == false && settings.debugGnss) + systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, + lgMessagesRTCM[messageNumber].msgTextName); } - } - else - { - // X found. This is RTCM-1??X message. Assign 'offset' of 0 - if (_lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, - settings.lg290pMessageRatesRTCMBase[messageNumber], 0) == false) + else { - // if (settings.debugGnss) - systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, - lgMessagesRTCM[messageNumber].msgTextName); - response &= false; // If any one of the commands fails, report failure overall + // X found. This is RTCM-1??X message. Assign 'offset' of 0 + + // If firmware is 4 or higher, use setMessageRateOnPort, otherwise setMessageRate + if (lg290pFirmwareVersion >= 4) + // Enable this message, at this rate, on this port + response &= _lg290p->setMessageRateOnPort(lgMessagesNMEA[messageNumber].msgTextName, + settings.lg290pMessageRatesNMEA[messageNumber], + portNumber, 0); + else + // Enable this message, at this rate + response &= _lg290p->setMessageRate(lgMessagesNMEA[messageNumber].msgTextName, + settings.lg290pMessageRatesNMEA[messageNumber], 0); + + if (response == false && settings.debugGnss) + systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, + lgMessagesRTCM[messageNumber].msgTextName); } - } - // If any message is enabled, enable MSM output - if (settings.lg290pMessageRatesRTCMRover[messageNumber] == true) - enableMSM = true; + // If any message is enabled, enable MSM output + if (settings.lg290pMessageRatesRTCMBase[messageNumber] > 0) + enableMSM = true; + } } + + portNumber++; + + // setMessageRateOnPort only supported on v4 and above + if (lg290pFirmwareVersion < 4) + break; // Don't step through portNumbers } if (enableMSM == true) { if (settings.debugGnss) - - systemPrintln("Enabling RTCM MSM output"); + systemPrintln("Enabling Base RTCM MSM output"); // PQTMCFGRTCM fails to respond with OK over UART2 of LG290P, so don't look for it _lg290p->sendOkCommand( @@ -644,54 +685,87 @@ bool GNSS_LG290P::enableRTCMRover() bool rtcm1046Enabled = false; bool enableMSM = false; // Goes true if we need to enable MSM output reporting - for (int messageNumber = 0; messageNumber < MAX_LG290P_RTCM_MSG; messageNumber++) + int portNumber = 1; + + while (portNumber < 4) { - // Setting RTCM-1005 must have only the rate - // Setting RTCM-107X must have rate and offset - if (strchr(lgMessagesRTCM[messageNumber].msgTextName, 'X') == nullptr) + for (int messageNumber = 0; messageNumber < MAX_LG290P_RTCM_MSG; messageNumber++) { - // No X found. This is RTCM-1??? message. No offset. - if (_lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, - settings.lg290pMessageRatesRTCMRover[messageNumber]) == false) + // Check if this RTCM message is supported by the current LG290P firmware + if (lg290pFirmwareVersion >= lgMessagesRTCM[messageNumber].firmwareVersionSupported) { - if (settings.debugGnss) - systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, - lgMessagesRTCM[messageNumber].msgTextName); - response &= false; // If any one of the commands fails, report failure overall - } - } - else - { - // X found. This is RTCM-1??X message. Assign 'offset' of 0 - if (_lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, - settings.lg290pMessageRatesRTCMRover[messageNumber], 0) == false) - { - if (settings.debugGnss) - systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, - lgMessagesRTCM[messageNumber].msgTextName); - response &= false; // If any one of the commands fails, report failure overall + // Setting RTCM-1005 must have only the rate + // Setting RTCM-107X must have rate and offset + if (strchr(lgMessagesRTCM[messageNumber].msgTextName, 'X') == nullptr) + { + // No X found. This is RTCM-1??? message. No offset. + + // If firmware is 4 or higher, use setMessageRateOnPort, otherwise setMessageRate + if (lg290pFirmwareVersion >= 4) + { + // If any one of the commands fails, report failure overall + response &= _lg290p->setMessageRateOnPort(lgMessagesRTCM[messageNumber].msgTextName, + settings.lg290pMessageRatesRTCMRover[messageNumber], + portNumber); + } + else + response &= _lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, + settings.lg290pMessageRatesRTCMRover[messageNumber]); + + if (response == false && settings.debugGnss) + systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, + lgMessagesRTCM[messageNumber].msgTextName); + } + else + { + // X found. This is RTCM-1??X message. Assign 'offset' of 0 + + // If firmware is 4 or higher, use setMessageRateOnPort, otherwise setMessageRate + if (lg290pFirmwareVersion >= 4) + { + response &= _lg290p->setMessageRateOnPort(lgMessagesRTCM[messageNumber].msgTextName, + settings.lg290pMessageRatesRTCMRover[messageNumber], + portNumber, 0); + } + else + response &= _lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, + settings.lg290pMessageRatesRTCMRover[messageNumber], 0); + + if (response == false && settings.debugGnss) + systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, + lgMessagesRTCM[messageNumber].msgTextName); + } + + // If any message is enabled, enable MSM output + if (settings.lg290pMessageRatesRTCMRover[messageNumber] > 0) + enableMSM = true; + + // If we are using IP based corrections, we need to send local data to the PPL + // The PPL requires being fed GPGGA/ZDA, and RTCM1019/1020/1042/1046 + if (settings.enablePointPerfectCorrections) + { + // Mark PPL required messages as enabled if rate > 0 + if (settings.lg290pMessageRatesRTCMRover[messageNumber] > 0) + { + if (strcmp(lgMessagesRTCM[messageNumber].msgTextName, "RTCM3-1019") == 0) + rtcm1019Enabled = true; + else if (strcmp(lgMessagesRTCM[messageNumber].msgTextName, "RTCM3-1020") == 0) + rtcm1020Enabled = true; + else if (strcmp(lgMessagesRTCM[messageNumber].msgTextName, "RTCM3-1042") == 0) + rtcm1042Enabled = true; + else if (strcmp(lgMessagesRTCM[messageNumber].msgTextName, "RTCM3-1046") == 0) + rtcm1046Enabled = true; + enableMSM = true; // Force enable MSM output + } + } } } - // If any message is enabled, enable MSM output - if (lgMessagesRTCM[messageNumber].msgTextName, settings.lg290pMessageRatesRTCMRover[messageNumber] == true) - enableMSM = true; + portNumber++; - // If we are using IP based corrections, we need to send local data to the PPL - // The PPL requires being fed GPGGA/ZDA, and RTCM1019/1020/1042/1046 - if (settings.enablePointPerfectCorrections) - { - // Mark PPL required messages as enabled if rate > 0 - if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "RTCM3-1019") == 0) - rtcm1019Enabled = true; - if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "RTCM3-1020") == 0) - rtcm1020Enabled = true; - if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "RTCM3-1042") == 0) - rtcm1042Enabled = true; - if (strcmp(lgMessagesNMEA[messageNumber].msgTextName, "RTCM3-1046") == 0) - rtcm1046Enabled = true; - enableMSM = true; // Force enable MSM output - } + // setMessageRateOnPort only supported on v4 and above + if (lg290pFirmwareVersion < 4) + break; // Don't step through portNumbers } if (settings.enablePointPerfectCorrections) @@ -709,6 +783,9 @@ bool GNSS_LG290P::enableRTCMRover() if (enableMSM == true) { + if (settings.debugGnss) + systemPrintln("Enabling Rover RTCM MSM output"); + // PQTMCFGRTCM fails to respond with OK over UART2 of LG290P, so don't look for it _lg290p->sendOkCommand( "PQTMCFGRTCM,W,7,0,-90,07,06,2,1"); // Enable MSM7, output regular intervals, interval (seconds) @@ -1278,8 +1355,8 @@ bool GNSS_LG290P::isDgpsFixed() } //---------------------------------------- -// Some functions (L-Band area frequency determination) merely need to know if we have a valid fix, not what type of fix -// This function checks to see if the given platform has reached sufficient fix type to be considered valid +// Some functions (L-Band area frequency determination) merely need to know if we have a valid fix, not what type of +// fix This function checks to see if the given platform has reached sufficient fix type to be considered valid //---------------------------------------- bool GNSS_LG290P::isFixed() { @@ -2016,4 +2093,4 @@ void lg290pBoot() void lg290pReset() { digitalWrite(pin_GNSS_Reset, LOW); -} \ No newline at end of file +} diff --git a/Firmware/RTK_Everywhere/GNSS_UM980.ino b/Firmware/RTK_Everywhere/GNSS_UM980.ino index ebd61f1af..724a4029b 100644 --- a/Firmware/RTK_Everywhere/GNSS_UM980.ino +++ b/Firmware/RTK_Everywhere/GNSS_UM980.ino @@ -450,24 +450,26 @@ bool GNSS_UM980::enableNMEA() // has UNLOG or similar. if (settings.um980MessageRatesNMEA[messageNumber] > 0) { - if (_um980->setNMEAPortMessage(umMessagesNMEA[messageNumber].msgTextName, "COM3", - settings.um980MessageRatesNMEA[messageNumber]) == false) - { - if (settings.debugGnss) - systemPrintf("Enable NMEA failed at messageNumber %d %s.\r\n", messageNumber, - umMessagesNMEA[messageNumber].msgTextName); - response &= false; // If any one of the commands fails, report failure overall - } + // If any one of the commands fails, report failure overall + response &= _um980->setNMEAPortMessage(umMessagesNMEA[messageNumber].msgTextName, "COM3", + settings.um980MessageRatesNMEA[messageNumber]); + + if (response == false && settings.debugGnss) + systemPrintf("Enable NMEA failed at messageNumber %d %s.\r\n", messageNumber, + umMessagesNMEA[messageNumber].msgTextName); // If we are using IP based corrections, we need to send local data to the PPL // The PPL requires being fed GPGGA/ZDA, and RTCM1019/1020/1042/1046 - if (strstr(settings.pointPerfectKeyDistributionTopic, "/ip") != nullptr) + if (settings.enablePointPerfectCorrections) { // Mark PPL required messages as enabled if rate > 0 - if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "GPGGA") == 0) - gpggaEnabled = true; - if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "GPZDA") == 0) - gpzdaEnabled = true; + if (settings.um980MessageRatesNMEA[messageNumber] > 0) + { + if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "GPGGA") == 0) + gpggaEnabled = true; + else if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "GPZDA") == 0) + gpzdaEnabled = true; + } } } } @@ -497,14 +499,13 @@ bool GNSS_UM980::enableRTCMBase() // has UNLOG or similar. if (settings.um980MessageRatesRTCMBase[messageNumber] > 0) { - if (_um980->setRTCMPortMessage(umMessagesRTCM[messageNumber].msgTextName, "COM3", - settings.um980MessageRatesRTCMBase[messageNumber]) == false) - { - if (settings.debugGnss) - systemPrintf("Enable RTCM failed at messageNumber %d %s.", messageNumber, - umMessagesRTCM[messageNumber].msgTextName); - response &= false; // If any one of the commands fails, report failure overall - } + // If any one of the commands fails, report failure overall + response &= _um980->setRTCMPortMessage(umMessagesRTCM[messageNumber].msgTextName, "COM3", + settings.um980MessageRatesRTCMBase[messageNumber]); + + if (response == false && settings.debugGnss) + systemPrintf("Enable RTCM failed at messageNumber %d %s.", messageNumber, + umMessagesRTCM[messageNumber].msgTextName); } } @@ -542,14 +543,17 @@ bool GNSS_UM980::enableRTCMRover() if (settings.enablePointPerfectCorrections) { // Mark PPL required messages as enabled if rate > 0 - if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "RTCM1019") == 0) - rtcm1019Enabled = true; - if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "RTCM1020") == 0) - rtcm1020Enabled = true; - if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "RTCM1042") == 0) - rtcm1042Enabled = true; - if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "RTCM1046") == 0) - rtcm1046Enabled = true; + if (settings.um980MessageRatesRTCMRover[messageNumber] > 0) + { + if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "RTCM1019") == 0) + rtcm1019Enabled = true; + else if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "RTCM1020") == 0) + rtcm1020Enabled = true; + else if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "RTCM1042") == 0) + rtcm1042Enabled = true; + else if (strcmp(umMessagesNMEA[messageNumber].msgTextName, "RTCM1046") == 0) + rtcm1046Enabled = true; + } } } } From 2af5f300a45577b9927a32ff615e3492b066705e Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 14 Jan 2025 10:11:38 -0700 Subject: [PATCH 121/276] Replace networkIsConnected with networkHasInternet --- Firmware/RTK_Everywhere/HTTP_Client.ino | 12 ++++----- Firmware/RTK_Everywhere/MQTT_Client.ino | 8 +++--- Firmware/RTK_Everywhere/NTP.ino | 6 ++--- Firmware/RTK_Everywhere/Network.ino | 33 +++++++++---------------- Firmware/RTK_Everywhere/NtripClient.ino | 12 ++++----- Firmware/RTK_Everywhere/NtripServer.ino | 16 ++++++------ Firmware/RTK_Everywhere/TcpClient.ino | 10 +++----- Firmware/RTK_Everywhere/TcpServer.ino | 6 ++--- Firmware/RTK_Everywhere/UdpServer.ino | 10 +++----- Firmware/RTK_Everywhere/menuPP.ino | 3 +-- 10 files changed, 44 insertions(+), 72 deletions(-) diff --git a/Firmware/RTK_Everywhere/HTTP_Client.ino b/Firmware/RTK_Everywhere/HTTP_Client.ino index 95e13444b..fd52d0459 100644 --- a/Firmware/RTK_Everywhere/HTTP_Client.ino +++ b/Firmware/RTK_Everywhere/HTTP_Client.ino @@ -59,7 +59,6 @@ static uint32_t httpClientConnectionAttemptTimeout = 5 * 1000L; // Wait 5s static int httpClientConnectionAttemptsTotal; // Count the number of connection attempts absolutely static volatile uint32_t httpClientLastDataReceived; // Last time data was received via HTTP -static NetPriority_t httpClientPriority = NETWORK_OFFLINE; static NetworkClientSecure *httpSecureClient; @@ -276,7 +275,6 @@ void httpClientUpdate() case HTTP_CLIENT_ON: { if ((millis() - httpClientTimer) > httpClientConnectionAttemptTimeout) { - httpClientPriority = NETWORK_OFFLINE; httpClientSetState(HTTP_CLIENT_NETWORK_STARTED); } break; @@ -288,8 +286,8 @@ void httpClientUpdate() if (!httpClientModeNeeded) httpClientStop(true); - // Wait until the network is connected to the media - else if (networkIsConnected(&httpClientPriority)) + // Wait until the network is connected + else if (networkHasInternet()) httpClientSetState(HTTP_CLIENT_CONNECTING_2_SERVER); break; } @@ -297,7 +295,7 @@ void httpClientUpdate() // Connect to the HTTP server case HTTP_CLIENT_CONNECTING_2_SERVER: { // Determine if the network has failed - if (!networkIsConnected(&httpClientPriority)) + if (networkHasInternet() == false) { // Failed to connect to the network, attempt to restart the network httpClientStop(true); // Was httpClientRestart(); - #StopVsRestart @@ -354,7 +352,7 @@ void httpClientUpdate() case HTTP_CLIENT_CONNECTED: { // Determine if the network has failed - if (!networkIsConnected(&httpClientPriority)) + if (networkHasInternet() == false) { // Failed to connect to the network, attempt to restart the network httpClientStop(true); // Was httpClientRestart(); - #StopVsRestart @@ -558,7 +556,7 @@ void httpClientUpdate() // Hang here until httpClientModeNeeded is set to false by updateProvisioning case HTTP_CLIENT_COMPLETE: { // Determine if the network has failed - if (!networkIsConnected(&httpClientPriority)) + if (networkHasInternet() == false) // Failed to connect to the network, attempt to restart the network httpClientStop(true); // Was httpClientRestart(); - #StopVsRestart break; diff --git a/Firmware/RTK_Everywhere/MQTT_Client.ino b/Firmware/RTK_Everywhere/MQTT_Client.ino index 3bd1cf91c..1b60d4fd9 100644 --- a/Firmware/RTK_Everywhere/MQTT_Client.ino +++ b/Firmware/RTK_Everywhere/MQTT_Client.ino @@ -138,7 +138,6 @@ static uint32_t mqttClientConnectionAttemptTimeout; static int mqttClientConnectionAttemptsTotal; // Count the number of connection attempts absolutely static volatile uint32_t mqttClientLastDataReceived; // Last time data was received via MQTT -static NetPriority_t mqttClientPriority = NETWORK_OFFLINE; static NetworkClientSecure *mqttSecureClient; @@ -723,7 +722,6 @@ void mqttClientUpdate() case MQTT_CLIENT_ON: { if ((millis() - mqttClientTimer) > mqttClientConnectionAttemptTimeout) { - mqttClientPriority = NETWORK_OFFLINE; mqttClientSetState(MQTT_CLIENT_WAIT_FOR_NETWORK); } break; @@ -736,7 +734,7 @@ void mqttClientUpdate() mqttClientStop(true); // Wait until the network is connected to the media - else if (networkIsConnected(&mqttClientPriority)) + else if (networkHasInternet()) mqttClientSetState(MQTT_CLIENT_CONNECTING_2_SERVER); break; } @@ -744,7 +742,7 @@ void mqttClientUpdate() // Connect to the MQTT server case MQTT_CLIENT_CONNECTING_2_SERVER: { // Determine if the network has failed - if (!networkIsConnected(&mqttClientPriority)) + if (networkHasInternet() == false) { // Failed to connect to the network, attempt to restart the network mqttClientStop(true); // Was mqttClientRestart(); - #StopVsRestart @@ -890,7 +888,7 @@ void mqttClientUpdate() case MQTT_CLIENT_SERVICES_CONNECTED: { // Determine if the network has failed - if (!networkIsConnected(&mqttClientPriority)) + if (networkHasInternet() == false) { // Failed to connect to the network, attempt to restart the network mqttClientStop(true); // Was mqttClientRestart(); - #StopVsRestart diff --git a/Firmware/RTK_Everywhere/NTP.ino b/Firmware/RTK_Everywhere/NTP.ino index 95b7c0192..e03d0a217 100644 --- a/Firmware/RTK_Everywhere/NTP.ino +++ b/Firmware/RTK_Everywhere/NTP.ino @@ -75,7 +75,6 @@ const RtkMode_t ntpServerMode = RTK_MODE_NTP; // Locals //---------------------------------------- -static NetPriority_t ntpServerPriority = NETWORK_OFFLINE; static NetworkUDP *ntpServer; // This will be instantiated when we know the NTP port static uint8_t ntpServerState; static uint32_t lastLoggedNTPRequest; @@ -793,7 +792,6 @@ void ntpServerUpdate() // The NTP server only works over Ethernet if (networkInterfaceHasInternet(NETWORK_ETHERNET)) { - ntpServerPriority = NETWORK_OFFLINE; ntpServerSetState(NTP_STATE_NETWORK_CONNECTED); } } @@ -801,7 +799,7 @@ void ntpServerUpdate() case NTP_STATE_NETWORK_CONNECTED: // Determine if the network has failed - if (!networkIsConnected(&ntpServerPriority)) + if (networkHasInternet() == false) // Stop the NTP server, restart it if possible ntpServerStop(); @@ -825,7 +823,7 @@ void ntpServerUpdate() case NTP_STATE_SERVER_RUNNING: // Determine if the network has failed - if (!networkIsConnected(&ntpServerPriority)) + if (networkHasInternet() == false) // Stop the NTP server, restart it if possible ntpServerStop(); diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 433ca9c28..fc355f0db 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -584,21 +584,6 @@ const char *networkGetNameByPriority(NetPriority_t priority) return "None"; } -//---------------------------------------- -// Determine if the network is available -//---------------------------------------- -bool networkIsConnected(NetPriority_t *clientPriority) -{ - // If the client is using the highest priority network and that - // network is still available then continue as normal - if (networkHasInternet_bm && (*clientPriority == networkPriority)) - return true; - - // The network has changed, notify the client of the change - return false; - *clientPriority = networkPriority; -} - //---------------------------------------- // Determine if the network interface is online //---------------------------------------- @@ -1406,15 +1391,19 @@ void networkUpdate() // restartWiFi is used by the settings interface to indicate SSIDs or else has changed // Stop WiFi to allow restart with new settings - if (restartWiFi == true && networkInterfaceHasInternet(NETWORK_WIFI)) + if (restartWiFi == true) { - if (settings.debugNetworkLayer) - systemPrintln("WiFi settings changed, restarting WiFi"); - restartWiFi = false; - wifiResetThrottleTimeout(); - WIFI_STOP(); - networkStop(NETWORK_WIFI, settings.debugNetworkLayer); + + if (networkInterfaceHasInternet(NETWORK_WIFI)) + { + if (settings.debugNetworkLayer) + systemPrintln("WiFi settings changed, restarting WiFi"); + + wifiResetThrottleTimeout(); + WIFI_STOP(); + networkStop(NETWORK_WIFI, settings.debugNetworkLayer); + } } // If there are no consumers, but the network is online, shut down all networks diff --git a/Firmware/RTK_Everywhere/NtripClient.ino b/Firmware/RTK_Everywhere/NtripClient.ino index 6aafb6ffa..a000c2d6a 100644 --- a/Firmware/RTK_Everywhere/NtripClient.ino +++ b/Firmware/RTK_Everywhere/NtripClient.ino @@ -187,7 +187,6 @@ static volatile uint8_t ntripClientState = NTRIP_CLIENT_OFF; static int ntripClientConnectionAttempts; // Count the number of connection attempts between restarts static uint32_t ntripClientConnectionAttemptTimeout; static int ntripClientConnectionAttemptsTotal; // Count the number of connection attempts absolutely -static NetPriority_t ntripClientPriority = NETWORK_OFFLINE; // NTRIP client timer usage: // * Reconnection delay @@ -563,7 +562,6 @@ void ntripClientUpdate() // Start the network case NTRIP_CLIENT_ON: - ntripClientPriority = NETWORK_OFFLINE; ntripClientSetState(NTRIP_CLIENT_WAIT_FOR_NETWORK); break; @@ -573,8 +571,8 @@ void ntripClientUpdate() if (ntripClientForcedShutdown || NEQ_RTK_MODE(ntripClientMode) || !settings.enableNtripClient) ntripClientStop(true); - // Wait until the network is connected to the media - else if (networkIsConnected(&ntripClientPriority)) + // Wait until the network is connected + else if (networkHasInternet()) { // Allocate the ntripClient structure ntripClient = new NetworkClient(); @@ -596,7 +594,7 @@ void ntripClientUpdate() case NTRIP_CLIENT_NETWORK_CONNECTED: // Determine if the network has failed - if (!networkIsConnected(&ntripClientPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripClientStop(true); // Was ntripClientRestart(); - #StopVsRestart @@ -631,7 +629,7 @@ void ntripClientUpdate() case NTRIP_CLIENT_WAIT_RESPONSE: // Determine if the network has failed - if (!networkIsConnected(&ntripClientPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripClientStop(true); // Was ntripClientRestart(); - #StopVsRestart @@ -752,7 +750,7 @@ void ntripClientUpdate() case NTRIP_CLIENT_CONNECTED: // Determine if the network has failed - if (!networkIsConnected(&ntripClientPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripClientStop(true); // Was ntripClientRestart(); - #StopVsRestart diff --git a/Firmware/RTK_Everywhere/NtripServer.ino b/Firmware/RTK_Everywhere/NtripServer.ino index 00c5e6a2a..edb72a424 100644 --- a/Firmware/RTK_Everywhere/NtripServer.ino +++ b/Firmware/RTK_Everywhere/NtripServer.ino @@ -175,7 +175,6 @@ const RtkMode_t ntripServerMode = RTK_MODE_BASE_FIXED; // NTRIP Servers static NTRIP_SERVER_DATA ntripServerArray[NTRIP_SERVER_MAX]; -static NetPriority_t ntripServerPriority = NETWORK_OFFLINE; //---------------------------------------- // NTRIP Server Routines @@ -608,7 +607,6 @@ void ntripServerUpdate(int serverIndex) // Start the network case NTRIP_SERVER_ON: - ntripServerPriority = NETWORK_OFFLINE; ntripServerSetState(ntripServer, NTRIP_SERVER_WAIT_FOR_NETWORK); break; @@ -623,8 +621,8 @@ void ntripServerUpdate(int serverIndex) ntripServerStop(serverIndex, true); } - // Wait until the network is connected to the media - else if (networkIsConnected(&ntripServerPriority)) + // Wait until the network is connected + else if (networkHasInternet()) { // Allocate the networkClient structure ntripServer->networkClient = new NetworkClient(); @@ -647,7 +645,7 @@ void ntripServerUpdate(int serverIndex) // Network available case NTRIP_SERVER_NETWORK_CONNECTED: // Determine if the network has failed - if (!networkIsConnected(&ntripServerPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -665,7 +663,7 @@ void ntripServerUpdate(int serverIndex) // Wait for GNSS correction data case NTRIP_SERVER_WAIT_GNSS_DATA: // Determine if the network has failed - if (!networkIsConnected(&ntripServerPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -675,7 +673,7 @@ void ntripServerUpdate(int serverIndex) // Initiate the connection to the NTRIP caster case NTRIP_SERVER_CONNECTING: // Determine if the network has failed - if (!networkIsConnected(&ntripServerPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -703,7 +701,7 @@ void ntripServerUpdate(int serverIndex) // Wait for authorization response case NTRIP_SERVER_AUTHORIZATION: // Determine if the network has failed - if (!networkIsConnected(&ntripServerPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -797,7 +795,7 @@ void ntripServerUpdate(int serverIndex) // NTRIP server authorized to send RTCM correction data to NTRIP caster case NTRIP_SERVER_CASTING: // Determine if the network has failed - if (!networkIsConnected(&ntripServerPriority)) + if (networkHasInternet() == false) // Failed to connect to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart diff --git a/Firmware/RTK_Everywhere/TcpClient.ino b/Firmware/RTK_Everywhere/TcpClient.ino index 2b7b774a3..d59ff2e3c 100644 --- a/Firmware/RTK_Everywhere/TcpClient.ino +++ b/Firmware/RTK_Everywhere/TcpClient.ino @@ -148,7 +148,6 @@ const RtkMode_t tcpClientMode = RTK_MODE_BASE_FIXED | RTK_MODE_BASE_SURVEY_IN | static NetworkClient *tcpClient; static IPAddress tcpClientIpAddress; -static NetPriority_t tcpClientPriority = NETWORK_OFFLINE; static uint8_t tcpClientState; static volatile RING_BUFFER_OFFSET tcpClientTail; static volatile bool tcpClientWriteError; @@ -417,7 +416,6 @@ void tcpClientUpdate() if (EQ_RTK_MODE(tcpClientMode) && settings.enableTcpClient) { timer = 0; - tcpClientPriority = NETWORK_OFFLINE; tcpClientSetState(TCP_CLIENT_STATE_WAIT_FOR_NETWORK); } break; @@ -428,8 +426,8 @@ void tcpClientUpdate() if (NEQ_RTK_MODE(tcpClientMode) || !settings.enableTcpClient) tcpClientStop(); - // Wait until the network is connected to the media - else if (networkIsConnected(&tcpClientPriority)) + // Wait until the network is connected + else if (networkHasInternet()) { #ifdef COMPILE_WIFI // Determine if WiFi is required @@ -465,7 +463,7 @@ void tcpClientUpdate() // Attempt the connection ot the TCP server case TCP_CLIENT_STATE_CLIENT_STARTING: // Determine if the network has failed - if (!networkIsConnected(&tcpClientPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network tcpClientStop(); @@ -510,7 +508,7 @@ void tcpClientUpdate() // Wait for the TCP client to shutdown or a TCP client link failure case TCP_CLIENT_STATE_CONNECTED: // Determine if the network has failed - if (!networkIsConnected(&tcpClientPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network tcpClientStop(); diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index 9aeddbf6d..2ac74fdcf 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -76,7 +76,6 @@ static volatile uint8_t tcpServerClientWriteError; static NetworkClient *tcpServerClient[TCP_SERVER_MAX_CLIENTS]; static IPAddress tcpServerClientIpAddress[TCP_SERVER_MAX_CLIENTS]; static volatile RING_BUFFER_OFFSET tcpServerClientTails[TCP_SERVER_MAX_CLIENTS]; -static NetPriority_t tcpServerPriority = NETWORK_OFFLINE; //---------------------------------------- // TCP Server handleGnssDataTask Support Routines @@ -381,7 +380,6 @@ void tcpServerUpdate() { if (settings.debugTcpServer && (!inMainMenu)) systemPrintln("TCP server start"); - tcpServerPriority = NETWORK_OFFLINE; tcpServerSetState(TCP_SERVER_STATE_WAIT_FOR_NETWORK); } break; @@ -393,7 +391,7 @@ void tcpServerUpdate() tcpServerStop(); // Wait until the network is connected to the media - else if (networkIsConnected(&tcpServerPriority)) + else if (networkHasInternet()) { // Delay before starting the TCP server if ((millis() - tcpServerTimer) >= (1 * 1000)) @@ -411,7 +409,7 @@ void tcpServerUpdate() // Handle client connections and link failures case TCP_SERVER_STATE_RUNNING: // Determine if the network has failed - if ((networkIsConnected(&tcpServerPriority) == false) || (!settings.enableTcpServer && !settings.baseCasterOverride)) + if ((networkHasInternet() == false) || (!settings.enableTcpServer && !settings.baseCasterOverride)) { if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu)) { diff --git a/Firmware/RTK_Everywhere/UdpServer.ino b/Firmware/RTK_Everywhere/UdpServer.ino index 033e3ceb1..f8bc048d0 100644 --- a/Firmware/RTK_Everywhere/UdpServer.ino +++ b/Firmware/RTK_Everywhere/UdpServer.ino @@ -94,7 +94,6 @@ static NetworkUDP *udpServer = nullptr; static uint8_t udpServerState; static uint32_t udpServerTimer; static volatile RING_BUFFER_OFFSET udpServerTail; -static NetPriority_t udpServerPriority; //---------------------------------------- // UDP Server handleGnssDataTask Support Routines @@ -107,7 +106,7 @@ int32_t udpServerSendDataBroadcast(uint8_t *data, uint16_t length) return 0; // Send the data as broadcast - if (settings.enableUdpServer && online.udpServer && networkIsConnected(&udpServerPriority)) + if (settings.enableUdpServer && online.udpServer && networkHasInternet()) { IPAddress broadcastAddress = networkGetBroadcastIpAddress(); udpServer->beginPacket(broadcastAddress, settings.udpServerPort); @@ -325,7 +324,6 @@ void udpServerUpdate() { if (settings.debugUdpServer && (!inMainMenu)) systemPrintln("UDP server starting the network"); - udpServerPriority = NETWORK_OFFLINE; udpServerSetState(UDP_SERVER_STATE_WAIT_FOR_NETWORK); } break; @@ -336,8 +334,8 @@ void udpServerUpdate() if (NEQ_RTK_MODE(udpServerMode) || !settings.enableUdpServer) udpServerStop(); - // Wait until the network is connected to the media - else if (networkIsConnected(&udpServerPriority)) + // Wait until the network is connected + else if (networkHasInternet()) { // Delay before starting the UDP server if ((millis() - udpServerTimer) >= (1 * 1000)) @@ -355,7 +353,7 @@ void udpServerUpdate() // Handle client connections and link failures case UDP_SERVER_STATE_RUNNING: // Determine if the network has failed - if ((!settings.enableUdpServer) || (!networkIsConnected(&udpServerPriority))) + if ((!settings.enableUdpServer) || (networkHasInternet() == false)) { if ((settings.debugUdpServer || PERIODIC_DISPLAY(PD_UDP_SERVER_DATA)) && (!inMainMenu)) { diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index a491617ca..5b1e2cff6 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -21,7 +21,6 @@ static const uint8_t ppIpToken[16] = {POINTPERFECT_IP_TOKEN}; // Toke static const uint8_t ppLbandIpToken[16] = {POINTPERFECT_LBAND_IP_TOKEN}; // Token in HEX form #ifdef COMPILE_NETWORK -static NetPriority_t pointperfectPriority = NETWORK_OFFLINE; MqttClient *menuppMqttClient; #endif // COMPILE_NETWORK @@ -1309,7 +1308,7 @@ void provisioningUpdate() } // Wait until the network is available #ifdef COMPILE_NETWORK - else if (networkIsConnected(&pointperfectPriority)) + else if (networkHasInternet()) { if (settings.debugPpCertificate) systemPrintln("PointPerfect key update connected to network"); From babc25a76e16bb2f1cf416c3bd6140ab9286bf5e Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 14 Jan 2025 11:59:34 -0700 Subject: [PATCH 122/276] Enable MSM if RTCM is turned on in rover mode. Reset Rover after settings are applied. --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 50 ++++++++++++++++++------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index 7f3d42770..ec5c8661e 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -329,6 +329,9 @@ bool GNSS_LG290P::configureRover() if (settingsWereSaved) settings.updateGNSSSettings = false; + //For RTCM and MSM messages to take effect (ie, PointPerfect is active) we must save/reset + softwareReset(); + if (settings.debugGnss) systemPrintln("LG290P Rover configured"); } @@ -546,7 +549,7 @@ bool GNSS_LG290P::enableNMEA() else // Enable this message, at this rate response &= _lg290p->setMessageRate(lgMessagesNMEA[messageNumber].msgTextName, - settings.lg290pMessageRatesNMEA[messageNumber]); + settings.lg290pMessageRatesNMEA[messageNumber]); if (response == false && settings.debugGnss) systemPrintf("Enable NMEA failed at messageNumber %d %s.\r\n", messageNumber, lgMessagesNMEA[messageNumber].msgTextName); @@ -616,12 +619,12 @@ bool GNSS_LG290P::enableRTCMBase() if (lg290pFirmwareVersion >= 4) // Enable this message, at this rate, on this port response &= - _lg290p->setMessageRateOnPort(lgMessagesNMEA[messageNumber].msgTextName, - settings.lg290pMessageRatesNMEA[messageNumber], portNumber); + _lg290p->setMessageRateOnPort(lgMessagesRTCM[messageNumber].msgTextName, + settings.lg290pMessageRatesRTCMBase[messageNumber], portNumber); else // Enable this message, at this rate - response &= _lg290p->setMessageRate(lgMessagesNMEA[messageNumber].msgTextName, - settings.lg290pMessageRatesNMEA[messageNumber]); + response &= _lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, + settings.lg290pMessageRatesRTCMBase[messageNumber]); if (response == false && settings.debugGnss) systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, @@ -634,13 +637,13 @@ bool GNSS_LG290P::enableRTCMBase() // If firmware is 4 or higher, use setMessageRateOnPort, otherwise setMessageRate if (lg290pFirmwareVersion >= 4) // Enable this message, at this rate, on this port - response &= _lg290p->setMessageRateOnPort(lgMessagesNMEA[messageNumber].msgTextName, - settings.lg290pMessageRatesNMEA[messageNumber], + response &= _lg290p->setMessageRateOnPort(lgMessagesRTCM[messageNumber].msgTextName, + settings.lg290pMessageRatesRTCMBase[messageNumber], portNumber, 0); else // Enable this message, at this rate - response &= _lg290p->setMessageRate(lgMessagesNMEA[messageNumber].msgTextName, - settings.lg290pMessageRatesNMEA[messageNumber], 0); + response &= _lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, + settings.lg290pMessageRatesRTCMBase[messageNumber], 0); if (response == false && settings.debugGnss) systemPrintf("Enable RTCM failed at messageNumber %d %s\r\n", messageNumber, @@ -755,7 +758,6 @@ bool GNSS_LG290P::enableRTCMRover() rtcm1042Enabled = true; else if (strcmp(lgMessagesRTCM[messageNumber].msgTextName, "RTCM3-1046") == 0) rtcm1046Enabled = true; - enableMSM = true; // Force enable MSM output } } } @@ -770,20 +772,40 @@ bool GNSS_LG290P::enableRTCMRover() if (settings.enablePointPerfectCorrections) { + enableMSM = true; // Force enable MSM output + // Force on any messages that are needed for PPL if (rtcm1019Enabled == false) + { + if (settings.debugCorrections) + systemPrintln("PPL Enabling RTCM3-1019"); response &= _lg290p->setMessageRate("RTCM3-1019", 1); + } if (rtcm1020Enabled == false) + { + if (settings.debugCorrections) + systemPrintln("PPL Enabling RTCM3-1020"); + response &= _lg290p->setMessageRate("RTCM3-1020", 1); + } if (rtcm1042Enabled == false) + { + if (settings.debugCorrections) + systemPrintln("PPL Enabling RTCM3-1042"); + response &= _lg290p->setMessageRate("RTCM3-1042", 1); + } if (rtcm1046Enabled == false) + { + if (settings.debugCorrections) + systemPrintln("PPL Enabling RTCM3-1046"); response &= _lg290p->setMessageRate("RTCM3-1046", 1); + } } if (enableMSM == true) { - if (settings.debugGnss) + if (settings.debugCorrections) systemPrintln("Enabling Rover RTCM MSM output"); // PQTMCFGRTCM fails to respond with OK over UART2 of LG290P, so don't look for it @@ -1908,7 +1930,7 @@ bool GNSS_LG290P::setRate(double secondsBetweenSolutions) int currentMode = getMode(); if (currentMode == 2) // Base { - if (settings.debugGnss) + if (settings.debugGnss || settings.debugCorrections) systemPrintln("Error: setRate can only be used in Rover mode"); return (false); } @@ -1929,7 +1951,7 @@ bool GNSS_LG290P::setRate(double secondsBetweenSolutions) { if (fixInterval != msBetweenSolutions) { - if (settings.debugGnss) + if (settings.debugGnss || settings.debugCorrections) systemPrintf("Modifying fix interval to %d\r\n", msBetweenSolutions); // Set the fix interval @@ -1938,7 +1960,7 @@ bool GNSS_LG290P::setRate(double secondsBetweenSolutions) // Reboot receiver to apply changes if (response == true) { - if (settings.debugGnss) + if (settings.debugGnss || settings.debugCorrections) systemPrintln("Rebooting LG290P"); response &= saveConfiguration(); From 75ff8bd3eab785938651bc229c6db0fcd42fae87 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 14 Jan 2025 19:01:05 +0000 Subject: [PATCH 123/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index 548a68388..c7a76f2ea 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x1F, 0x62, 0x85, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0x70, 0xB4, 0x86, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -1049,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x1F, 0x62, 0x85, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0x70, 0xB4, 0x86, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From 7e20716dc9832c7c5e63ff32f0ff5f60b576cf8b Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 14 Jan 2025 12:05:32 -0700 Subject: [PATCH 124/276] Typo fix --- Firmware/RTK_Everywhere/GNSS_LG290P.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.h b/Firmware/RTK_Everywhere/GNSS_LG290P.h index 5cc7e4fbf..7cbe15a2b 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.h +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.h @@ -34,7 +34,7 @@ typedef struct // Rate = Output once every N position fix(es). const lg290pMsg lgMessagesNMEA[] = { {"RMC", 1, 0}, {"GGA", 1, 0}, {"GSV", 1, 0}, {"GSA", 1, 0}, {"VTG", 1, 0}, {"GLL", 1, 0}, - {"GBS", 0, 4}, {"GBS", 0, 4}, {"GST", 1, 4}, {"ZDA", 0, 4}, + {"GBS", 0, 4}, {"GNS", 0, 4}, {"GST", 1, 4}, {"ZDA", 0, 4}, }; const lg290pMsg lgMessagesRTCM[] = { From 12b8776a7efc2da96a0851913a743363ae29759d Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 14 Jan 2025 12:17:18 -0700 Subject: [PATCH 125/276] Update compile-rtk-everywhere.yml --- .github/workflows/compile-rtk-everywhere.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile-rtk-everywhere.yml b/.github/workflows/compile-rtk-everywhere.yml index 46a055a5d..df6749231 100644 --- a/.github/workflows/compile-rtk-everywhere.yml +++ b/.github/workflows/compile-rtk-everywhere.yml @@ -94,7 +94,7 @@ jobs: "SparkFun u-blox PointPerfect Library"@1.11.4 "SparkFun IM19 IMU Arduino Library"@1.0.1 "SparkFun UM980 Triband RTK GNSS Arduino Library"@1.0.4 - "SparkFun LG290P Quadband RTK GNSS Arduino Library"@1.0.0 + "SparkFun LG290P Quadband RTK GNSS Arduino Library"@1.0.2 "SparkFun I2C Expander Arduino Library"@1.0.1 - name: Patch libmbedtls From b04ac05b40573a537958e200bd580b507b47d0df Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 14 Jan 2025 19:36:14 +0000 Subject: [PATCH 126/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index c7a76f2ea..dca88594a 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x70, 0xB4, 0x86, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0xAD, 0xBC, 0x86, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -1049,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x70, 0xB4, 0x86, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0xAD, 0xBC, 0x86, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From 51f74120fd515d038fa755293f41565af189b0a5 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 15 Jan 2025 11:17:47 -0700 Subject: [PATCH 127/276] Fix pointer on web socket server Fix #514 --- Firmware/RTK_Everywhere/WebServer.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index 96d285e49..ecd92a895 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -592,11 +592,11 @@ void webServerStopSockets() { websocketConnected = false; - if (*wsserver) + if (wsserver != nullptr) { // Stop the httpd server esp_err_t ret = httpd_stop(*wsserver); - //*wsserver = nullptr; + wsserver = nullptr; } } From 188e6c5b906e703e6c5400be6030c7440b354411 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 15 Jan 2025 11:44:39 -0700 Subject: [PATCH 128/276] Add a compilation note about partition files --- .github/workflows/compile-rtk-everywhere.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-rtk-everywhere.yml b/.github/workflows/compile-rtk-everywhere.yml index df6749231..7d6da8848 100644 --- a/.github/workflows/compile-rtk-everywhere.yml +++ b/.github/workflows/compile-rtk-everywhere.yml @@ -140,7 +140,10 @@ jobs: - name: Copy custom RTKEverywhere.csv run: - # Use the 16MB partitions by default. 8MB (Postcard) partitions must be compiled separately + # Compile the source using the 16MB partition file. Other platforms (ie, the 8MB Postcard) use + # the same binary but use a different partition binary during the upload phase. + # View the different RTK partition files used during upload here: + # https://github.com/sparkfun/SparkFun_RTK_Firmware_Uploader/tree/main/RTK_Firmware_Uploader/resource cp Firmware/RTKEverywhere.csv /home/runner/.arduino15/packages/esp32/hardware/esp32/${{ env.CORE_VERSION }}/tools/partitions/RTKEverywhere.csv - name: Compile Sketch From 1473922f1dd79f6658e2a51b353748ffb9f1b268 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 15 Jan 2025 14:34:29 -0700 Subject: [PATCH 129/276] Start webserver with default IP This is a return to previous code. --- Firmware/RTK_Everywhere/WebServer.ino | 34 ++++----------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index ecd92a895..1cb1fac21 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -300,30 +300,7 @@ bool webServerAssignResources(int httpPort = 80) dnsserver->start(); } - // Start the server with a given IP - if (WiFi.getMode() == WIFI_MODE_APSTA) - { - // If we are connected to a local AP, use that IP - if (settings.wifiConfigOverAP == false && wifiIsConnected()) - webServer = new WebServer(WiFi.localIP(), httpPort); - else // Use our own AP's IP - webServer = new WebServer(WiFi.softAPIP(), httpPort); - } - else if (WiFi.getMode() == WIFI_MODE_AP) - webServer = new WebServer(WiFi.softAPIP(), httpPort); - else if (WiFi.getMode() == WIFI_MODE_STA) - webServer = new WebServer(WiFi.localIP(), httpPort); - - // If WiFi is off, fall back to ethernet - else if (WiFi.getMode() == WIFI_OFF && present.ethernet_ws5500) - webServer = new WebServer(ETH.localIP(), httpPort); - - else - { - systemPrintln("Error: Unknown WebServer connection mode."); - return (false); - } - + webServer = new WebServer(httpPort); if (!webServer) { systemPrintln("ERROR: Failed to allocate webServer"); @@ -466,10 +443,9 @@ bool webServerAssignResources(int httpPort = 80) webServer->send_P(200, "text/plain", (const char *)icomoon_woof, sizeof(icomoon_woof)); }); - //https://lemariva.com/blog/2017/11/white-hacking-wemos-captive-portal-using-micropython - webServer->on("/connecttest.txt", HTTP_GET, []() { - webServer->send(200, "text/plain", "Microsoft Connect Test"); - }); + // https://lemariva.com/blog/2017/11/white-hacking-wemos-captive-portal-using-micropython + webServer->on("/connecttest.txt", HTTP_GET, + []() { webServer->send(200, "text/plain", "Microsoft Connect Test"); }); // Handler for the /uploadFile form POST webServer->on( @@ -1132,7 +1108,7 @@ void createDynamicDataString(char *settingsCSV) stringRecord(settingsCSV, "batteryIconFileName", batteryIconFileName); - //Limit batteryLevelPercent to sane levels + // Limit batteryLevelPercent to sane levels if (batteryLevelPercent > 100) batteryLevelPercent = 100; From a06420ef89e4f85e2b506140a141168d89fcf7b0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jan 2025 21:56:21 +0000 Subject: [PATCH 130/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index dca88594a..0acc0d156 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xAD, 0xBC, 0x86, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0x05, 0x2F, 0x88, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -1049,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xAD, 0xBC, 0x86, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0x05, 0x2F, 0x88, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From 8c124d79a65d153d8869e85c7bc8a8d14d4c3277 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 15 Jan 2025 15:58:24 -0700 Subject: [PATCH 131/276] Fix serial output in base caster mode --- Firmware/RTK_Everywhere/System.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/System.ino b/Firmware/RTK_Everywhere/System.ino index 0677ba460..33e52115b 100644 --- a/Firmware/RTK_Everywhere/System.ino +++ b/Firmware/RTK_Everywhere/System.ino @@ -394,7 +394,10 @@ void printReports() // If we are in base mode, display SIV only else if (inBaseMode() == true) { - systemPrintf("Base Mode - SIV: %d\r\n", gnss->getSatellitesInView()); + if (settings.baseCasterOverride == true) + systemPrintf("Base Caster Mode - SIV: %d\r\n", gnss->getSatellitesInView()); + else + systemPrintf("Base Mode - SIV: %d\r\n", gnss->getSatellitesInView()); } } } From 95f2d4ea7511a760eb5df907bde120a26fe4b2cf Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 15 Jan 2025 16:29:34 -0700 Subject: [PATCH 132/276] Allow TCP/UDP to run during WiFi AP --- Firmware/RTK_Everywhere/Network.ino | 9 ++++----- Firmware/RTK_Everywhere/TcpServer.ino | 6 +++--- Firmware/RTK_Everywhere/UdpServer.ino | 4 ++-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index fc355f0db..9d6fc6411 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -518,16 +518,15 @@ IPAddress networkGetIpAddress() NetIndex_t index; IPAddress ip; + // NETIF doesn't capture the IP address of a soft AP + if (wifiApIsRunning() == true && wifiStationIsRunning() == false) + return WiFi.softAPIP(); + // Get the networkInterfaceTable index index = networkPriority; if (index < NETWORK_OFFLINE) { index = networkIndexTable[index]; - - // NETIF doesn't capture the IP address of a soft AP - if (index == NETWORK_WIFI && (WiFi.getMode() == WIFI_AP || WiFi.getMode() == WIFI_AP_STA)) - return WiFi.softAPIP(); - return networkInterfaceTable[index].netif->localIP(); } diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index 2ac74fdcf..eed335ca5 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -244,7 +244,7 @@ bool tcpServerStart() online.tcpServer = true; localIp = networkGetIpAddress(); - if (settings.enableNtripCaster) + if (settings.enableNtripCaster || settings.baseCasterOverride) systemPrintf("TCP server online, IP address %s:%d, responding as NTRIP Caster\r\n", localIp.toString().c_str(), tcpPort); else @@ -391,7 +391,7 @@ void tcpServerUpdate() tcpServerStop(); // Wait until the network is connected to the media - else if (networkHasInternet()) + else if (networkHasInternet() || wifiApIsRunning()) { // Delay before starting the TCP server if ((millis() - tcpServerTimer) >= (1 * 1000)) @@ -409,7 +409,7 @@ void tcpServerUpdate() // Handle client connections and link failures case TCP_SERVER_STATE_RUNNING: // Determine if the network has failed - if ((networkHasInternet() == false) || (!settings.enableTcpServer && !settings.baseCasterOverride)) + if ((networkHasInternet() == false && wifiApIsRunning() == false) || (!settings.enableTcpServer && !settings.baseCasterOverride)) { if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu)) { diff --git a/Firmware/RTK_Everywhere/UdpServer.ino b/Firmware/RTK_Everywhere/UdpServer.ino index f8bc048d0..5f0316f59 100644 --- a/Firmware/RTK_Everywhere/UdpServer.ino +++ b/Firmware/RTK_Everywhere/UdpServer.ino @@ -335,7 +335,7 @@ void udpServerUpdate() udpServerStop(); // Wait until the network is connected - else if (networkHasInternet()) + else if (networkHasInternet() || wifiApIsRunning()) { // Delay before starting the UDP server if ((millis() - udpServerTimer) >= (1 * 1000)) @@ -353,7 +353,7 @@ void udpServerUpdate() // Handle client connections and link failures case UDP_SERVER_STATE_RUNNING: // Determine if the network has failed - if ((!settings.enableUdpServer) || (networkHasInternet() == false)) + if ((networkHasInternet() == false && wifiApIsRunning() == false) || (!settings.enableUdpServer && !settings.baseCasterOverride)) { if ((settings.debugUdpServer || PERIODIC_DISPLAY(PD_UDP_SERVER_DATA)) && (!inMainMenu)) { From c937edb8fd7ec8fb33b5434d013350c38bec6bd0 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 15 Jan 2025 16:29:53 -0700 Subject: [PATCH 133/276] LG290P: Mark messages that require a firmware update --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 38 ++++++++++++++++++------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index ec5c8661e..3201b7ef1 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -329,7 +329,7 @@ bool GNSS_LG290P::configureRover() if (settingsWereSaved) settings.updateGNSSSettings = false; - //For RTCM and MSM messages to take effect (ie, PointPerfect is active) we must save/reset + // For RTCM and MSM messages to take effect (ie, PointPerfect is active) we must save/reset softwareReset(); if (settings.debugGnss) @@ -618,9 +618,9 @@ bool GNSS_LG290P::enableRTCMBase() // If firmware is 4 or higher, use setMessageRateOnPort, otherwise setMessageRate if (lg290pFirmwareVersion >= 4) // Enable this message, at this rate, on this port - response &= - _lg290p->setMessageRateOnPort(lgMessagesRTCM[messageNumber].msgTextName, - settings.lg290pMessageRatesRTCMBase[messageNumber], portNumber); + response &= _lg290p->setMessageRateOnPort(lgMessagesRTCM[messageNumber].msgTextName, + settings.lg290pMessageRatesRTCMBase[messageNumber], + portNumber); else // Enable this message, at this rate response &= _lg290p->setMessageRate(lgMessagesRTCM[messageNumber].msgTextName, @@ -1639,24 +1639,42 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message endOfBlock = MAX_LG290P_NMEA_MSG; for (int x = 0; x < MAX_LG290P_NMEA_MSG; x++) - systemPrintf("%d) Message %s: %d\r\n", x + 1, lgMessagesNMEA[x].msgTextName, - settings.lg290pMessageRatesNMEA[x]); + { + if (lg290pFirmwareVersion <= lgMessagesNMEA[x].firmwareVersionSupported) + systemPrintf("%d) Message %s: %d - Requires firmware update\r\n", x + 1, + lgMessagesNMEA[x].msgTextName, settings.lg290pMessageRatesNMEA[x]); + else + systemPrintf("%d) Message %s: %d\r\n", x + 1, lgMessagesNMEA[x].msgTextName, + settings.lg290pMessageRatesNMEA[x]); + } } else if (strcmp(messageType, "RTCMRover") == 0) { endOfBlock = MAX_LG290P_RTCM_MSG; for (int x = 0; x < MAX_LG290P_RTCM_MSG; x++) - systemPrintf("%d) Message %s: %d\r\n", x + 1, lgMessagesRTCM[x].msgTextName, - settings.lg290pMessageRatesRTCMRover[x]); + { + if (lg290pFirmwareVersion <= lgMessagesRTCM[x].firmwareVersionSupported) + systemPrintf("%d) Message %s: %d - Requires firmware update\r\n", x + 1, + lgMessagesRTCM[x].msgTextName, settings.lg290pMessageRatesRTCMRover[x]); + else + systemPrintf("%d) Message %s: %d\r\n", x + 1, lgMessagesRTCM[x].msgTextName, + settings.lg290pMessageRatesRTCMRover[x]); + } } else if (strcmp(messageType, "RTCMBase") == 0) { endOfBlock = MAX_LG290P_RTCM_MSG; for (int x = 0; x < MAX_LG290P_RTCM_MSG; x++) - systemPrintf("%d) Message %s: %d\r\n", x + 1, lgMessagesRTCM[x].msgTextName, - settings.lg290pMessageRatesRTCMBase[x]); + { + if (lg290pFirmwareVersion <= lgMessagesRTCM[x].firmwareVersionSupported) + systemPrintf("%d) Message %s: %d - Requires firmware update\r\n", x + 1, lgMessagesRTCM[x].msgTextName, + settings.lg290pMessageRatesRTCMBase[x]); + else + systemPrintf("%d) Message %s: %d\r\n", x + 1, lgMessagesRTCM[x].msgTextName, + settings.lg290pMessageRatesRTCMBase[x]); + } } systemPrintln("x) Exit"); From b2f84907e80c5346ee4c3e948148d742b49855a2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Jan 2025 23:31:14 +0000 Subject: [PATCH 134/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index 0acc0d156..aecf3ff4b 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x05, 0x2F, 0x88, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0x41, 0x45, 0x88, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -1049,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x05, 0x2F, 0x88, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0x41, 0x45, 0x88, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From 2c617364772012cbeaad9ff0c0d7d5c256f57d8a Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 16 Jan 2025 11:51:53 -0700 Subject: [PATCH 135/276] Add input boxes from web config that don't have an impact on settings --- Firmware/RTK_Everywhere/menuCommands.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index 564ea90f5..af91d0d6f 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -1372,7 +1372,8 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting const char *table[] = { "baseTypeSurveyIn", "enableFactoryDefaults", "enableFirmwareUpdate", "enableForgetRadios", "fileSelectAll", "fixedBaseCoordinateTypeGeo", "fixedHAEAPC", "measurementRateSec", - "nicknameECEF", "nicknameGeodetic", "saveToArduino", + "nicknameECEF", "nicknameGeodetic", "saveToArduino", "enableAutoReset", + "shutdownNoChargeTimeoutMinutesCheckbox", }; const int tableEntries = sizeof(table) / sizeof(table[0]); From f491465ade00264daa4d320efed6b1f8d4c1702a Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 16 Jan 2025 11:52:34 -0700 Subject: [PATCH 136/276] Return bool from websocketServerStart Teardown webserver if sockets fail to start --- Firmware/RTK_Everywhere/WebServer.ino | 31 +++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index 1cb1fac21..71bfc3bae 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -150,18 +150,27 @@ static esp_err_t ws_handler(httpd_req_t *req) if (ws_pkt.type == HTTPD_WS_TYPE_TEXT) { - if (settings.debugWebServer == true) - systemPrintf("Got packet with message: %s\r\n", ws_pkt.payload); - if (currentlyParsingData == false) { + if (settings.debugWebServer == true) + systemPrint("Got packet with message: \r\n"); //We can't %s the payload as it's not string terminated + for (int i = 0; i < ws_pkt.len; i++) { incomingSettings[incomingSettingsSpot++] = ws_pkt.payload[i]; incomingSettingsSpot %= AP_CONFIG_SETTING_SIZE; + + //Print payload if needed + if (settings.debugWebServer == true) + systemWrite(ws_pkt.payload[i]); } timeSinceLastIncomingSetting = millis(); } + else + { + if (settings.debugWebServer == true) + systemPrintln("Got packet but ignoring due to parsing block"); + } } else if (ws_pkt.type == HTTPD_WS_TYPE_CLOSE) { @@ -184,7 +193,7 @@ static const httpd_uri_t ws = {.uri = "/ws", .handle_ws_control_frames = true, .supported_subprotocol = NULL}; -static void start_wsserver(void) +bool websocketServerStart(void) { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); @@ -207,10 +216,11 @@ static void start_wsserver(void) if (settings.debugWebServer == true) systemPrintln("Registering URI handlers"); httpd_register_uri_handler(*wsserver, &ws); - return; + return true; } systemPrintln("Error starting wsserver!"); + return false; } // ===== Request Handler class used to answer more complex requests ===== @@ -510,7 +520,16 @@ bool webServerAssignResources(int httpPort = 80) reportHeapNow(false); // Start the web socket server on port 81 using - start_wsserver(); + if (websocketServerStart() == false) + { + if (settings.debugWebServer == true) + systemPrintln("Web Sockets failed to start"); + + webServerStopSockets(); + webServerReleaseResources(); + + return (false); + } if (settings.debugWebServer == true) systemPrintln("Web Socket Server Started"); From 4b7daf5f25266f8fc6aad88c422fba6578930046 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 16 Jan 2025 12:05:07 -0700 Subject: [PATCH 137/276] Correctly turn off provisioning state machine Prevent infinite loop --- Firmware/RTK_Everywhere/menuPP.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index 5b1e2cff6..40f21a958 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -1304,7 +1304,7 @@ void provisioningUpdate() // Determine if the key update request has been canceled while waiting if (settings.requestKeyUpdate == false) { - provisioningSetState(PROVISIONING_NOT_STARTED); + provisioningSetState(PROVISIONING_OFF); } // Wait until the network is available #ifdef COMPILE_NETWORK From 95c5177c0818239d1b4803a0c23198228a01c5d1 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 16 Jan 2025 12:41:12 -0700 Subject: [PATCH 138/276] Assign TCP server's IP to network IP If both AP and STA are active, TCP server can get assigned to the STA when base caster is active. This assigns the TCP server to the IP recognized as the network IP. --- Firmware/RTK_Everywhere/States.ino | 1 + Firmware/RTK_Everywhere/TcpServer.ino | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 16714afba..8f2311a7f 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -522,6 +522,7 @@ void stateUpdate() otaReportedVersion[0] = '\0'; // Zero out the reported version } + } #endif // COMPILE_AP diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index eed335ca5..b862ef7ed 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -235,14 +235,15 @@ bool tcpServerStart() if(settings.baseCasterOverride == true) tcpPort = 2101; + localIp = networkGetIpAddress(); + // Start the TCP server - tcpServer = new NetworkServer(tcpPort, TCP_SERVER_MAX_CLIENTS); + tcpServer = new NetworkServer(localIp, tcpPort, TCP_SERVER_MAX_CLIENTS); if (!tcpServer) return false; tcpServer->begin(); online.tcpServer = true; - localIp = networkGetIpAddress(); if (settings.enableNtripCaster || settings.baseCasterOverride) systemPrintf("TCP server online, IP address %s:%d, responding as NTRIP Caster\r\n", localIp.toString().c_str(), From 489098277f0840f995fca7f0f487b2a38d941cb4 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 16 Jan 2025 13:30:32 -0700 Subject: [PATCH 139/276] Revert TCP IP assignment TCP Server is streaming RTCM over both AP and STA wifi connections with the original setup so this is unneeded. --- Firmware/RTK_Everywhere/TcpServer.ino | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index b862ef7ed..6e1ecac51 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -235,16 +235,15 @@ bool tcpServerStart() if(settings.baseCasterOverride == true) tcpPort = 2101; - localIp = networkGetIpAddress(); - // Start the TCP server - tcpServer = new NetworkServer(localIp, tcpPort, TCP_SERVER_MAX_CLIENTS); + tcpServer = new NetworkServer(tcpPort, TCP_SERVER_MAX_CLIENTS); if (!tcpServer) return false; tcpServer->begin(); online.tcpServer = true; + localIp = networkGetIpAddress(); if (settings.enableNtripCaster || settings.baseCasterOverride) systemPrintf("TCP server online, IP address %s:%d, responding as NTRIP Caster\r\n", localIp.toString().c_str(), tcpPort); From b9df0c813e73d0d2779aaa68970934ce7d86eb9f Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 16 Jan 2025 16:43:12 -0700 Subject: [PATCH 140/276] Fix typo --- Firmware/RTK_Everywhere/HTTP_Client.ino | 2 +- Firmware/RTK_Everywhere/LARA.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/HTTP_Client.ino b/Firmware/RTK_Everywhere/HTTP_Client.ino index fd52d0459..d2e15b9b6 100644 --- a/Firmware/RTK_Everywhere/HTTP_Client.ino +++ b/Firmware/RTK_Everywhere/HTTP_Client.ino @@ -547,7 +547,7 @@ void httpClientUpdate() ztpResponse = ZTP_SUCCESS; httpClientSetState(HTTP_CLIENT_COMPLETE); } - } // JSON Derialized correctly + } // JSON Deserialized correctly } // HTTP Response was 200 break; } diff --git a/Firmware/RTK_Everywhere/LARA.ino b/Firmware/RTK_Everywhere/LARA.ino index 2972f8093..3a6bc1a48 100644 --- a/Firmware/RTK_Everywhere/LARA.ino +++ b/Firmware/RTK_Everywhere/LARA.ino @@ -128,7 +128,7 @@ NETWORK_POLL_SEQUENCE laraBootSequence[] = {laraPowerHigh, LARA_SETTLE_TIME, "Finish power off sequence"}, {networkDelay, (uintptr_t)&laraTimer, "Delay for power off"}, - // After a short delay if on other network device is available, turn on LARA + // After a short delay if no other network device is available, turn on LARA // State Parameter Description {networkStartDelayed, (30 * 1000), "Attempt to start cellular if necessary"}, {nullptr, 0, "Termination"}, From 9f9fa63296cf686848c74cd1aeb263b516fe34eb Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 16 Jan 2025 16:43:41 -0700 Subject: [PATCH 141/276] Move WiFi status to debug prints --- Firmware/RTK_Everywhere/WiFi.ino | 55 +++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 77ad99953..33097d5b3 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -36,16 +36,8 @@ WiFiMulti *wifiMulti; // Locals //---------------------------------------- -static uint32_t wifiLastConnectionAttempt; - -// Throttle the time between connection attempts -// ms - Max of 4,294,967,295 or 4.3M seconds or 71,000 minutes or 1193 hours or 49 days between attempts -static uint32_t wifiConnectionAttemptsTotal; // Count the number of connection attempts absolutely -static uint32_t wifiConnectionAttemptTimeout; - // Start timeout static uint32_t wifiStartTimeout; - static uint32_t wifiStartLastTry; // The last time WiFi start was attempted // WiFi Timer usage: @@ -381,27 +373,35 @@ void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) break; case ARDUINO_EVENT_WIFI_READY: - systemPrintln("WiFi Ready"); + if (settings.debugWifiState) + systemPrintln("WiFi Ready"); WiFi.setHostname(settings.mdnsHostName); break; case ARDUINO_EVENT_WIFI_SCAN_DONE: - systemPrintln("WiFi Scan Done"); + if (settings.debugWifiState) + systemPrintln("WiFi Scan Done"); // wifi_event_sta_scan_done_t info.wifi_scan_done; break; case ARDUINO_EVENT_WIFI_STA_START: - systemPrintln("WiFi STA Started"); + if (settings.debugWifiState) + systemPrintln("WiFi STA Started"); break; case ARDUINO_EVENT_WIFI_STA_STOP: - systemPrintln("WiFi STA Stopped"); + if (settings.debugWifiState) + systemPrintln("WiFi STA Stopped"); break; case ARDUINO_EVENT_WIFI_STA_CONNECTED: memcpy(ssid, info.wifi_sta_connected.ssid, info.wifi_sta_connected.ssid_len); ssid[info.wifi_sta_connected.ssid_len] = 0; - systemPrintf("WiFi STA connected to %s\r\n", ssid); + + ipAddress = WiFi.localIP(); + systemPrintf("WiFi STA connected to %s with IP address: ", ssid); + systemPrintln(ipAddress); + WiFi.setHostname(settings.mdnsHostName); break; @@ -418,15 +418,22 @@ void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) break; case ARDUINO_EVENT_WIFI_STA_GOT_IP: - ipAddress = WiFi.localIP(); - systemPrint("WiFi STA Got IPv4: "); - systemPrintln(ipAddress); + if (settings.debugWifiState) + { + ipAddress = WiFi.localIP(); + systemPrint("WiFi STA Got IPv4: "); + systemPrintln(ipAddress); + } networkMarkHasInternet(NETWORK_WIFI); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP6: - systemPrint("WiFi STA Got IPv6: "); - systemPrintln(ipAddress); + if (settings.debugWifiState) + { + ipAddress = WiFi.localIP(); + systemPrint("WiFi STA Got IPv6: "); + systemPrintln(ipAddress); + } networkMarkHasInternet(NETWORK_WIFI); break; @@ -723,4 +730,16 @@ void wifiStop(NetIndex_t index, uintptr_t parameter, bool debug) networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); } +// Returns true when more than two attempts have failed +bool wifiUnavailable() +{ + if(wifiNetworkCount() == 0) + return true; + + if ((millis() - wifiStartLastTry) > (WIFI_MIN_TIMEOUT * 2)) + return true; + + return false; +} + #endif // COMPILE_WIFI From fb07e79d65f5f459f111da5fbb8ac40b4098cfbc Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 16 Jan 2025 16:43:56 -0700 Subject: [PATCH 142/276] Expand network consumer type prints --- Firmware/RTK_Everywhere/Network.ino | 36 ++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 9d6fc6411..b332598d5 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1422,7 +1422,41 @@ void networkUpdate() if (consumerTypes != previousConsumerTypes) { if (settings.debugNetworkLayer) - systemPrintf("Changing from consumer type 0x%02X to 0x%02X\r\n", previousConsumerTypes, consumerTypes); + { + systemPrint("Changing network from consumer type: "); + + if (previousConsumerTypes == NETCONSUMER_NONE) + systemPrint("None"); + else + { + if (previousConsumerTypes && (1 << NETCONSUMER_WIFI_STA)) + systemPrint("/STA"); + if (previousConsumerTypes && (1 << NETCONSUMER_WIFI_AP)) + systemPrint("/AP"); + if (previousConsumerTypes && (1 << NETCONSUMER_CELLULAR)) + systemPrint("/CELL"); + if (previousConsumerTypes && (1 << NETCONSUMER_ETHERNET)) + systemPrint("/ETH"); + } + + systemPrint(" to: "); + + if (consumerTypes == NETCONSUMER_NONE) + systemPrint("None"); + else + { + if (consumerTypes && (1 << NETCONSUMER_WIFI_STA)) + systemPrint("/STA"); + if (consumerTypes && (1 << NETCONSUMER_WIFI_AP)) + systemPrint("/AP"); + if (consumerTypes && (1 << NETCONSUMER_CELLULAR)) + systemPrint("/CELL"); + if (consumerTypes && (1 << NETCONSUMER_ETHERNET)) + systemPrint("/ETH"); + } + + systemPrintln(); + } previousConsumerTypes = networkGetConsumerTypes(); // Update the previous consumer types From f77ef2402fe529445d7559fbcfd86ef4128d9760 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 17 Jan 2025 11:20:29 -0700 Subject: [PATCH 143/276] Revert provisioning statemachine start --- Firmware/RTK_Everywhere/menuPP.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index 40f21a958..6d62f4f54 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -1301,10 +1301,10 @@ void provisioningUpdate() // Wait for connection to the network case PROVISIONING_WAIT_FOR_NETWORK: { - // Determine if the key update request has been canceled while waiting - if (settings.requestKeyUpdate == false) + // Stop waiting if PointPerfect has been disabled + if (settings.enablePointPerfectCorrections == false) { - provisioningSetState(PROVISIONING_OFF); + provisioningSetState(PROVISIONING_NOT_STARTED); } // Wait until the network is available #ifdef COMPILE_NETWORK From 96b68235556240553c7a0e8f4e4d049fa50cd166 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 17 Jan 2025 11:21:06 -0700 Subject: [PATCH 144/276] Correct bit comparisions --- Firmware/RTK_Everywhere/Network.ino | 50 ++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index b332598d5..62f38cd01 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1423,39 +1423,39 @@ void networkUpdate() { if (settings.debugNetworkLayer) { - systemPrint("Changing network from consumer type: "); + systemPrintf("Changing network from consumer type: 0x%02X (", previousConsumerTypes); if (previousConsumerTypes == NETCONSUMER_NONE) systemPrint("None"); else { - if (previousConsumerTypes && (1 << NETCONSUMER_WIFI_STA)) + if (previousConsumerTypes & (1 << NETCONSUMER_WIFI_STA)) systemPrint("/STA"); - if (previousConsumerTypes && (1 << NETCONSUMER_WIFI_AP)) + if (previousConsumerTypes & (1 << NETCONSUMER_WIFI_AP)) systemPrint("/AP"); - if (previousConsumerTypes && (1 << NETCONSUMER_CELLULAR)) + if (previousConsumerTypes & (1 << NETCONSUMER_CELLULAR)) systemPrint("/CELL"); - if (previousConsumerTypes && (1 << NETCONSUMER_ETHERNET)) + if (previousConsumerTypes & (1 << NETCONSUMER_ETHERNET)) systemPrint("/ETH"); } - systemPrint(" to: "); + systemPrintf(") to: 0x%02X (", consumerTypes); if (consumerTypes == NETCONSUMER_NONE) systemPrint("None"); else { - if (consumerTypes && (1 << NETCONSUMER_WIFI_STA)) + if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) systemPrint("/STA"); - if (consumerTypes && (1 << NETCONSUMER_WIFI_AP)) + if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) systemPrint("/AP"); - if (consumerTypes && (1 << NETCONSUMER_CELLULAR)) + if (consumerTypes & (1 << NETCONSUMER_CELLULAR)) systemPrint("/CELL"); - if (consumerTypes && (1 << NETCONSUMER_ETHERNET)) + if (consumerTypes & (1 << NETCONSUMER_ETHERNET)) systemPrint("/ETH"); } - systemPrintln(); + systemPrintln(")"); } previousConsumerTypes = networkGetConsumerTypes(); // Update the previous consumer types @@ -1472,15 +1472,33 @@ void networkUpdate() { // Attempt to start any network that is needed, in the order Ethernet/WiFi/Cellular - if (consumerTypes && (1 << NETCONSUMER_ETHERNET)) + if (consumerTypes & (1 << NETCONSUMER_ETHERNET)) + { networkStart(NETWORK_ETHERNET, settings.debugNetworkLayer); + } + + // Start WiFi if we need AP, or if we need STA+Internet + Serial.println("\r\n wifi check"); + if ((consumerTypes & (1 << NETCONSUMER_WIFI_AP)) || + ((consumerTypes & (1 << NETCONSUMER_WIFI_STA) && networkHasInternet() == false))) + { + Serial.println("\r\n start wifi"); - if ((networkHasInternet() == false) && (consumerTypes && (1 << NETCONSUMER_WIFI_STA)) || - (consumerTypes && (1 << NETCONSUMER_WIFI_AP))) networkStart(NETWORK_WIFI, settings.debugNetworkLayer); + } - if ((networkHasInternet() == false) && (consumerTypes && (1 << NETCONSUMER_CELLULAR))) - networkStart(NETWORK_CELLULAR, settings.debugNetworkLayer); + if ((networkHasInternet() == false) && (consumerTypes & (1 << NETCONSUMER_CELLULAR))) + { + // If we're in AP only mode (no internet), don't start cellular + if (wifiApIsRunning() == false) + { + // Don't start cellular until WiFi has failed to connect + if (wifiUnavailable() == true) + { + networkStart(NETWORK_CELLULAR, settings.debugNetworkLayer); + } + } + } } // Walk the list of network priorities in descending order From 7627d4f003d193104d21e5ecc849fbc322d4c199 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 17 Jan 2025 11:52:16 -0700 Subject: [PATCH 145/276] Add wifiFailedConnectionAttempts --- Firmware/RTK_Everywhere/WiFi.ino | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 33097d5b3..658c458f1 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -17,7 +17,7 @@ // Globals //---------------------------------------- -int wifiConnectionAttempts; // Count the number of connection attempts between restarts +int wifiFailedConnectionAttempts = 0; // Count the number of connection attempts between restarts bool restartWiFi = false; // Restart WiFi if user changes anything @@ -636,7 +636,10 @@ void wifiThrottledStart(NetIndex_t index, uintptr_t parameter, bool debug) // Start WiFi if (wifiStart()) + { networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); + wifiFailedConnectionAttempts = 0; + } else { // Increase the timeout @@ -646,6 +649,8 @@ void wifiThrottledStart(NetIndex_t index, uintptr_t parameter, bool debug) else if (wifiStartTimeout > WIFI_MAX_TIMEOUT) wifiStartTimeout = WIFI_MAX_TIMEOUT; + wifiFailedConnectionAttempts++; + // Display the delay seconds = wifiStartTimeout / MILLISECONDS_IN_A_SECOND; minutes = seconds / SECONDS_IN_A_MINUTE; @@ -685,7 +690,7 @@ void wifiStop() if (((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) && settings.enableCaptivePortal) dnsServer.stop(); - wifiConnectionAttempts = 0; // Reset the timeout + wifiFailedConnectionAttempts = 0; // Reset the counter // If ESP-Now is active, change protocol to only Long Range if (espnowState > ESPNOW_OFF) @@ -730,13 +735,14 @@ void wifiStop(NetIndex_t index, uintptr_t parameter, bool debug) networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); } -// Returns true when more than two attempts have failed +// Returns true if we deem WiFi is not going to connect +// Used to allow cellular to start bool wifiUnavailable() { if(wifiNetworkCount() == 0) return true; - if ((millis() - wifiStartLastTry) > (WIFI_MIN_TIMEOUT * 2)) + if (wifiFailedConnectionAttempts > 2) return true; return false; From 0ac2da72189df422a6c7fe5de15e80b7db5d98ac Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 17 Jan 2025 11:52:35 -0700 Subject: [PATCH 146/276] Remove debug statements --- Firmware/RTK_Everywhere/Network.ino | 3 --- 1 file changed, 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 62f38cd01..3fadb1c4f 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1478,12 +1478,9 @@ void networkUpdate() } // Start WiFi if we need AP, or if we need STA+Internet - Serial.println("\r\n wifi check"); if ((consumerTypes & (1 << NETCONSUMER_WIFI_AP)) || ((consumerTypes & (1 << NETCONSUMER_WIFI_STA) && networkHasInternet() == false))) { - Serial.println("\r\n start wifi"); - networkStart(NETWORK_WIFI, settings.debugNetworkLayer); } From 2b9a61ad41ad6b344c746c176b065e7bb70ddf2d Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 20 Jan 2025 10:50:40 -0700 Subject: [PATCH 147/276] Correctly print parser debug messages CRC is rarely 0x00, and should not be. SEMP tests for valid CRC before this point. --- Firmware/RTK_Everywhere/Tasks.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index 46d771056..b26907295 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -582,7 +582,7 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type) int32_t use; // Display the message - if ((settings.enablePrintLogFileMessages || PERIODIC_DISPLAY(PD_GNSS_DATA_RX)) && (!parse->crc) && (!inMainMenu)) + if ((settings.enablePrintLogFileMessages || PERIODIC_DISPLAY(PD_GNSS_DATA_RX)) && (!inMainMenu)) { PERIODIC_CLEAR(PD_GNSS_DATA_RX); if (settings.enablePrintLogFileMessages) From 10d5a9247ec735ef2dc41414f9b981fe803d9046 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 20 Jan 2025 10:51:26 -0700 Subject: [PATCH 148/276] Push GGA on non ZED platforms Fix #515 --- Firmware/RTK_Everywhere/GNSS.ino | 36 ++++++++++++++++++++++ Firmware/RTK_Everywhere/GNSS_ZED.ino | 41 +++++-------------------- Firmware/RTK_Everywhere/NtripClient.ino | 2 -- Firmware/RTK_Everywhere/Tasks.ino | 6 ++++ 4 files changed, 50 insertions(+), 35 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS.ino b/Firmware/RTK_Everywhere/GNSS.ino index 0a862dc98..e5e9884cc 100644 --- a/Firmware/RTK_Everywhere/GNSS.ino +++ b/Firmware/RTK_Everywhere/GNSS.ino @@ -4,6 +4,14 @@ GNSS.ino GNSS layer implementation ------------------------------------------------------------------------------*/ +extern int NTRIPCLIENT_MS_BETWEEN_GGA; + +#ifdef COMPILE_NETWORK +extern NetworkClient *ntripClient; +#endif // COMPILE_NETWORK + +extern unsigned long lastGGAPush; + //---------------------------------------- // Setup the general configuration of the GNSS // Not Rover or Base specific (ie, baud rates) @@ -46,3 +54,31 @@ bool GNSS::setMinCno(uint8_t cnoValue) // Pass the value to the GNSS receiver return gnss->setMinCnoRadio(cnoValue); } + +// Periodically push GGA sentence over NTRIP Client, to Caster, if enabled +void pushGPGGA(char *ggaData) +{ +#ifdef COMPILE_NETWORK + // Wait until the client has been created + if (ntripClient != nullptr) + { + // Provide the caster with our current position as needed + if (ntripClient->connected() && settings.ntripClient_TransmitGGA == true) + { + if (millis() - lastGGAPush > NTRIPCLIENT_MS_BETWEEN_GGA) + { + lastGGAPush = millis(); + + if (settings.debugNtripClientRtcm || PERIODIC_DISPLAY(PD_NTRIP_CLIENT_GGA)) + { + PERIODIC_CLEAR(PD_NTRIP_CLIENT_GGA); + systemPrintf("NTRIP Client pushing GGA to server: %s", (const char *)ggaData); + } + + // Push our current GGA sentence to caster + ntripClient->print((const char *)ggaData); + } + } + } +#endif // COMPILE_NETWORK +} \ No newline at end of file diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.ino b/Firmware/RTK_Everywhere/GNSS_ZED.ino index 752adfc80..604d454bc 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.ino +++ b/Firmware/RTK_Everywhere/GNSS_ZED.ino @@ -6,14 +6,6 @@ GNSS_ZED.ino #ifdef COMPILE_ZED -extern int NTRIPCLIENT_MS_BETWEEN_GGA; - -#ifdef COMPILE_NETWORK -extern NetworkClient *ntripClient; -#endif // COMPILE_NETWORK - -extern unsigned long lastGGAPush; - //---------------------------------------- // If we have decryption keys, configure module // Note: don't check online.lband_neo here. We could be using ip corrections @@ -865,7 +857,7 @@ void GNSS_ZED::enableGgaForNtrip() { // Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA _zed->setVal8(UBLOX_CFG_NMEA_MAINTALKERID, 1); - _zed->setNMEAGPGGAcallbackPtr(&pushGPGGA); // Set up the callback for GPGGA + _zed->setNMEAGPGGAcallbackPtr(&zedPushGPGGA); // Set up the callback for GPGGA float measurementFrequency = (1000.0 / settings.measurementRateMs) / settings.navigationRate; if (measurementFrequency < 0.2) @@ -2768,30 +2760,6 @@ void checkRXMCOR(UBX_RXM_COR_data_t *ubxDataStruct) } } -// Call back for incoming GGA data to be pushed to NTRIP Caster -void pushGPGGA(NMEA_GGA_data_t *nmeaData) -{ -#ifdef COMPILE_NETWORK - // Provide the caster with our current position as needed - if (ntripClient->connected() && settings.ntripClient_TransmitGGA == true) - { - if (millis() - lastGGAPush > NTRIPCLIENT_MS_BETWEEN_GGA) - { - lastGGAPush = millis(); - - if (settings.debugNtripClientRtcm || PERIODIC_DISPLAY(PD_NTRIP_CLIENT_GGA)) - { - PERIODIC_CLEAR(PD_NTRIP_CLIENT_GGA); - systemPrintf("NTRIP Client pushing GGA to server: %s", (const char *)nmeaData->nmea); - } - - // Push our current GGA sentence to caster - ntripClient->print((const char *)nmeaData->nmea); - } - } -#endif // COMPILE_NETWORK -} - // ZED-F9x call back void eventTriggerReceived(UBX_TIM_TM2_data_t *ubxDataStruct) { @@ -2911,4 +2879,11 @@ void inputMessageRate(uint8_t &localMessageRate, uint8_t messageNumber) localMessageRate = rate; } +// Push GGA sentence over NTRIP Client, to Caster, if enabled +// ZED uses callback, other platforms call this from processUart1Message() +void zedPushGPGGA(NMEA_GGA_data_t *nmeaData) +{ + pushGPGGA((char *)nmeaData->nmea); +} + #endif // COMPILE_ZED diff --git a/Firmware/RTK_Everywhere/NtripClient.ino b/Firmware/RTK_Everywhere/NtripClient.ino index a000c2d6a..9b54aaaf4 100644 --- a/Firmware/RTK_Everywhere/NtripClient.ino +++ b/Firmware/RTK_Everywhere/NtripClient.ino @@ -598,8 +598,6 @@ void ntripClientUpdate() // Failed to connect to to the network, attempt to restart the network ntripClientStop(true); // Was ntripClientRestart(); - #StopVsRestart - - // If GGA transmission is enabled, wait for GNSS lock before connecting to NTRIP Caster // If GGA transmission is not enabled, start connecting to NTRIP Caster else if ((settings.ntripClient_TransmitGGA == false) || (gnss->isFixed() == true)) diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index b26907295..e387bc96d 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -747,6 +747,12 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type) } } + // Push GGA to Caster if enabled + if (type == RTK_NMEA_PARSER_INDEX && strstr(sempNmeaGetSentenceName(parse), "GGA") != nullptr) + { + pushGPGGA((char *)parse->buffer); + } + // Determine if this message will fit into the ring buffer bytesToCopy = parse->length; space = availableHandlerSpace; From 391e7fc5cc3d39df68cdc79dbf5faff15805071f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 20 Jan 2025 17:54:23 +0000 Subject: [PATCH 149/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index aecf3ff4b..b176825b4 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x41, 0x45, 0x88, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0xCE, 0x8D, 0x8E, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -1049,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x41, 0x45, 0x88, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0xCE, 0x8D, 0x8E, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From a0d50f9e824505cef8d5a095a910046dae081022 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Sun, 12 Jan 2025 10:06:40 -1000 Subject: [PATCH 150/276] ESP-NOW: Move COMPILE_ESPNOW conditionals into Developer.ino --- Firmware/RTK_Everywhere/Developer.ino | 21 ++++++++++++- Firmware/RTK_Everywhere/ESPNOW.ino | 44 +++------------------------ 2 files changed, 24 insertions(+), 41 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index e82a8fb0f..6e03624a2 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -162,12 +162,31 @@ bool parseIncomingSettings() {return false;} void sendStringToWebsocket(const char* stringToSend) {} #endif // COMPILE_AP -#ifndef COMPILE_WIFI + +//---------------------------------------- +// ESP-NOW +//---------------------------------------- + +#ifndef COMPILE_ESPNOW + +bool espnowIsPaired() {return false;} +void espnowProcessRTCM(byte incoming) {} +esp_err_t espnowRemovePeer(uint8_t *peerMac) {return ESP_OK;} +esp_err_t espnowSendPairMessage(uint8_t *sendToMac) {return ESP_OK;} +bool espnowSetChannel(uint8_t channelNumber) {return false;} +void espnowStart() {} +void espnowStaticPairing() {} +void espnowStop() {} +void updateEspnow() {} + +#endif // COMPILE_ESPNOW //---------------------------------------- // WiFi //---------------------------------------- +#ifndef COMPILE_WIFI + void menuWiFi() {systemPrintln("**WiFi not compiled**");} bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) {return false;} bool wifiStart() {return false;} diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index be3876c4f..6c2d46c39 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -13,12 +13,13 @@ few seconds so a single dropped frame is not critical. */ +#ifdef COMPILE_ESPNOW + // Called from main loop // Control incoming/outgoing RTCM data from internal ESP NOW radio // Use the ESP32 to directly transmit/receive RTCM over 2.4GHz (no WiFi needed) void updateEspnow() { -#ifdef COMPILE_ESPNOW if (settings.enableEspNow == true) { if (espnowState == ESPNOW_PAIRED || espnowState == ESPNOW_BROADCASTING) @@ -51,7 +52,6 @@ void updateEspnow() espnowRSSI = -255; } } -#endif // COMPILE_ESPNOW } // Create a struct for ESP NOW pairing @@ -64,7 +64,6 @@ typedef struct PairMessage } PairMessage; // Callback when data is sent -#ifdef COMPILE_ESPNOW void espnowOnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { // systemPrint("Last Packet Send Status: "); @@ -73,16 +72,10 @@ void espnowOnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) // else // systemPrintln("Delivery Fail"); } -#endif // COMPILE_ESPNOW - -#ifndef COMPILE_ESPNOW -#define esp_now_recv_info uint8_t -#endif // Callback when data is received void espnowOnDataReceived(const esp_now_recv_info *mac, const uint8_t *incomingData, int len) { -#ifdef COMPILE_ESPNOW if (espnowState == ESPNOW_PAIRING) { if (len == sizeof(PairMessage)) // First error check @@ -127,7 +120,6 @@ void espnowOnDataReceived(const esp_now_recv_info *mac, const uint8_t *incomingD espnowIncomingRTCM = true; // Display a download icon lastEspnowRssiUpdate = millis(); } -#endif // COMPILE_ESPNOW } // Callback for all RX Packets @@ -154,8 +146,6 @@ void espnowStart() return; } -#ifdef COMPILE_ESPNOW - // Before we can issue esp_wifi_() commands WiFi must be started if (WiFi.getMode() != WIFI_STA) WiFi.mode(WIFI_STA); @@ -298,14 +288,12 @@ void espnowStart() } systemPrintln("ESP-Now Started"); -#endif // COMPILE_ESPNOW } // If WiFi is already enabled, simply remove the LR protocol // If WiFi is off, stop the radio entirely void espnowStop() { -#ifdef COMPILE_ESPNOW if (espnowState == ESPNOW_OFF) return; @@ -377,8 +365,6 @@ void espnowStop() systemPrintln("ESP-Now starting WiFi"); wifiStart(); // Force WiFi to restart } - -#endif // COMPILE_ESPNOW } // Start ESP-Now if needed, put ESP-Now into broadcast state @@ -396,7 +382,6 @@ void espnowBeginPairing() // Regularly call during pairing to see if we've received a Pairing message bool espnowIsPaired() { -#ifdef COMPILE_ESPNOW if (espnowState == ESPNOW_MAC_RECEIVED) { // Remove broadcast peer @@ -430,14 +415,12 @@ bool espnowIsPaired() espnowSetState(ESPNOW_PAIRED); return (true); } -#endif // COMPILE_ESPNOW return (false); } // Create special pair packet to a given MAC esp_err_t espnowSendPairMessage(uint8_t *sendToMac) { -#ifdef COMPILE_ESPNOW // Assemble message to send PairMessage pairMessage; @@ -451,9 +434,6 @@ esp_err_t espnowSendPairMessage(uint8_t *sendToMac) pairMessage.crc += wifiMACAddress[x]; return (esp_now_send(sendToMac, (uint8_t *)&pairMessage, sizeof(pairMessage))); // Send packet to given MAC -#else // COMPILE_ESPNOW - return (ESP_OK); -#endif // COMPILE_ESPNOW } // Add a given MAC address to the peer list @@ -464,7 +444,6 @@ esp_err_t espnowAddPeer(uint8_t *peerMac) esp_err_t espnowAddPeer(uint8_t *peerMac, bool encrypt) { -#ifdef COMPILE_ESPNOW esp_now_peer_info_t peerInfo; memcpy(peerInfo.peer_addr, peerMac, 6); @@ -482,15 +461,11 @@ esp_err_t espnowAddPeer(uint8_t *peerMac, bool encrypt) peerMac[3], peerMac[4], peerMac[5]); } return (result); -#else // COMPILE_ESPNOW - return (ESP_OK); -#endif // COMPILE_ESPNOW } // Remove a given MAC address from the peer list esp_err_t espnowRemovePeer(uint8_t *peerMac) { -#ifdef COMPILE_ESPNOW esp_err_t response = esp_now_del_peer(peerMac); if (response != ESP_OK) { @@ -499,9 +474,6 @@ esp_err_t espnowRemovePeer(uint8_t *peerMac) } return (response); -#else // COMPILE_ESPNOW - return (ESP_OK); -#endif // COMPILE_ESPNOW } // Update the state of the ESP Now state machine @@ -540,7 +512,6 @@ void espnowSetState(ESPNOWState newState) void espnowProcessRTCM(byte incoming) { -#ifdef COMPILE_ESPNOW // If we are paired, // Or if the radio is broadcasting // Then add bytes to the outgoing buffer @@ -571,7 +542,6 @@ void espnowProcessRTCM(byte incoming) espnowOutgoingRTCM = true; } -#endif // COMPILE_ESPNOW } // A blocking function that is used to pair two devices @@ -622,7 +592,6 @@ void espnowStaticPairing() // Returns the current channel being used by WiFi uint8_t espnowGetChannel() { -#ifdef COMPILE_ESPNOW if (espnowState == ESPNOW_OFF) return 0; @@ -647,15 +616,11 @@ uint8_t espnowGetChannel() esp_wifi_set_promiscuous(false); return (primaryChannelNumber); -#else - return (0); -#endif } // Returns the current channel being used by WiFi bool espnowSetChannel(uint8_t channelNumber) { -#ifdef COMPILE_ESPNOW if (wifiIsConnected() == true) { systemPrintln("ESP-NOW channel can't be modified while WiFi is connected."); @@ -683,7 +648,6 @@ bool espnowSetChannel(uint8_t channelNumber) esp_wifi_set_promiscuous(false); return (setSuccess); -#else - return (false); -#endif } + +#endif // COMPILE_ESPNOW From 51314af4d3d4c92c4a14950b089c3eb4cee68b1b Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Tue, 21 Jan 2025 06:23:44 -1000 Subject: [PATCH 151/276] Verify COMPILE_* for AP, CELLULAR, ESPNOW, ETHERNET, MQTT, OTA and WIFI Commenting out COMPILE_NETWORK alone still fails --- Firmware/RTK_Everywhere/Developer.ino | 29 +++++++++++++++------- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 4 +-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 6e03624a2..76a7dfe95 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -33,8 +33,10 @@ void ntpServerStop() {} void menuTcpUdp() {systemPrint("**Network not compiled**");} void networkBegin() {} +uint8_t networkConsumers() {return(0);} +uint16_t networkGetConsumerTypes() {return(0);} IPAddress networkGetIpAddress() {return("0.0.0.0");} -const uint8_t * networkGetMacAddress() +const uint8_t * networkGetMacAddress() { static const uint8_t zero[6] = {0, 0, 0, 0, 0, 0}; #ifdef COMPILE_BT @@ -49,10 +51,11 @@ bool networkInterfaceHasInternet(NetIndex_t index) {return false;} bool networkIsInterfaceStarted(NetIndex_t index) {return false;} void networkMarkOffline(NetIndex_t index) {} void networkMarkHasInternet(NetIndex_t index) {} +void networkSequenceBoot(NetIndex_t index) {} +void networkSequenceNextEntry(NetIndex_t index, bool debug) {} void networkUpdate() {} +void networkValidateIndex(NetIndex_t index) {} void networkVerifyTables() {} -uint16_t networkGetConsumerTypes() {return(0);} -uint8_t networkConsumers() {return(0);} //---------------------------------------- // NTRIP client @@ -114,9 +117,10 @@ void discardUdpServerBytes(RING_BUFFER_OFFSET previousTail, RING_BUFFER_OFFSET n #ifndef COMPILE_OTA_AUTO void otaAutoUpdate() {} +bool otaNeedsNetwork() {return false;} +void otaUpdate() {} void otaUpdateStop() {} void otaVerifyTables() {} -void otaUpdate() {} #endif // COMPILE_OTA_AUTO @@ -127,6 +131,7 @@ void otaUpdate() {} #ifndef COMPILE_MQTT_CLIENT bool mqttClientIsConnected() {return false;} +bool mqttClientNeedsNetwork() {return false;} void mqttClientPrintStatus() {} void mqttClientRestart() {} void mqttClientUpdate() {} @@ -157,9 +162,12 @@ bool webServerStart(int httpPort = 80) systemPrintln("**AP not compiled**"); return false; } -void webServerStop() {} bool parseIncomingSettings() {return false;} void sendStringToWebsocket(const char* stringToSend) {} +void stopWebServer() {} +bool webServerNeedsNetwork() {return false;} +void webServerStop() {} +void webServerUpdate() {} #endif // COMPILE_AP @@ -188,14 +196,17 @@ void updateEspnow() {} #ifndef COMPILE_WIFI void menuWiFi() {systemPrintln("**WiFi not compiled**");} +bool wifiApIsRunning() {return false;} bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) {return false;} -bool wifiStart() {return false;} +uint32_t wifiGetStartTimeout() {return 0;} +bool wifiIsRunning() {return false;} int wifiNetworkCount() {return 0;} +void wifiResetThrottleTimeout() {} +void wifiResetTimeout() {} +bool wifiStart() {return false;} bool wifiStationIsRunning() {return false;} -bool wifiApIsRunning() {return false;} -bool wifiIsRunning() {return false;} -uint32_t wifiGetStartTimeout() {return 0;} #define WIFI_STOP() {} +bool wifiUnavailable() {return true;} #endif // COMPILE_WIFI diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 5e3304589..5a99d38df 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -41,12 +41,12 @@ #define COMPILE_POINTPERFECT_LIBRARY // Comment out to remove PPL support #define COMPILE_BQ40Z50 // Comment out to remove BQ40Z50 functionality -#if defined(COMPILE_WIFI) || defined(COMPILE_ETHERNET) +#if defined(COMPILE_WIFI) || defined(COMPILE_ETHERNET) || defined(COMPILE_CELLULAR) #define COMPILE_NETWORK #define COMPILE_MQTT_CLIENT // Comment out to remove MQTT Client functionality #define COMPILE_OTA_AUTO // Comment out to disable automatic over-the-air firmware update #define COMPILE_HTTP_CLIENT // Comment out to disable HTTP Client (PointPerfect ZTP) functionality -#endif // COMPILE_WIFI || COMPILE_ETHERNET +#endif // COMPILE_WIFI || COMPILE_ETHERNET || COMPILE_CELLULAR // Always define ENABLE_DEVELOPER to enable its use in conditional statements #ifndef ENABLE_DEVELOPER From e04675a6eca98b64b082a6ee67f466ac90576194 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 13 Jan 2025 09:51:15 -1000 Subject: [PATCH 152/276] Reduce frequency of "No GNSS date/time available for system RTC" messges --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 5e3304589..d4365030b 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -1483,7 +1483,13 @@ void rtcUpdate() } else { - systemPrintln("No GNSS date/time available for system RTC."); + // Reduce the output frequency + static uint32_t lastErrorMsec = -1000 * 1000 * 1000; + if ((millis() - lastErrorMsec) > (30 * 1000)) + { + lastErrorMsec = millis(); + systemPrintln("No GNSS date/time available for system RTC."); + } } // End timeValid } // End lastRTCAttempt } // End online.gnss From 34febf367c6cc2f0bced3072234abe8ec5d8c251 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 13 Jan 2025 09:51:15 -1000 Subject: [PATCH 153/276] Reduce frequency of "No GNSS date/time available for system RTC" messges --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 5a99d38df..3c0fa916f 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -1483,7 +1483,13 @@ void rtcUpdate() } else { - systemPrintln("No GNSS date/time available for system RTC."); + // Reduce the output frequency + static uint32_t lastErrorMsec = -1000 * 1000 * 1000; + if ((millis() - lastErrorMsec) > (30 * 1000)) + { + lastErrorMsec = millis(); + systemPrintln("No GNSS date/time available for system RTC."); + } } // End timeValid } // End lastRTCAttempt } // End online.gnss From daf41798b0fb13a59e8bd78b494d9b59e93d2b26 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Sat, 4 Jan 2025 10:27:25 -1000 Subject: [PATCH 154/276] Add new WiFi and ESP-NOW layer code, add _old to previous file names WiFi: Rename WiFi.ino to WiFi_old.ino WiFi: Add new WiFi code, remove calls to espNowStart and espNowStop ESP-NOW: Rename ESPNOW.ino to ESPNOW_old.ino ESP-NOW: Add new ESP-NOW code WiFi: Use network layer mDNS routines WiFi: Switch from _debug to settings.debugWifiState WiFi: Remove use of _display WiFi: Pass verbose setting in during constructor WiFi: Remove start and stop of wifiEventHandler WiFi: Display start and stop components WiFi: Add start WiFi station components comment WiFi: Start and stop the DNS server WiFi: Don't display restarted items as failed to stop --- Firmware/RTK_Everywhere/Developer.ino | 3 + Firmware/RTK_Everywhere/ESPNOW.ino | 904 +++--- Firmware/RTK_Everywhere/ESPNOW_old.ino | 653 +++++ Firmware/RTK_Everywhere/Network.ino | 6 +- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 4 +- Firmware/RTK_Everywhere/WiFi.ino | 2977 ++++++++++++++++---- Firmware/RTK_Everywhere/WiFi_old.ino | 751 +++++ Firmware/RTK_Everywhere/settings.h | 356 +++ 8 files changed, 4503 insertions(+), 1151 deletions(-) create mode 100644 Firmware/RTK_Everywhere/ESPNOW_old.ino create mode 100644 Firmware/RTK_Everywhere/WiFi_old.ino diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 76a7dfe95..239e5bd38 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -177,6 +177,9 @@ void webServerUpdate() {} #ifndef COMPILE_ESPNOW +bool espNowStart() {return false;} +bool espNowStop() {return false;} + bool espnowIsPaired() {return false;} void espnowProcessRTCM(byte incoming) {} esp_err_t espnowRemovePeer(uint8_t *peerMac) {return ESP_OK;} diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index 6c2d46c39..0b5477a8c 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -1,87 +1,168 @@ -/* - Use ESP NOW protocol to transmit RTCM between RTK Products via 2.4GHz +/********************************************************************** + ESPNOW.ino - How pairing works: - 1. Device enters pairing mode - 2. Device adds the broadcast MAC (all 0xFFs) as peer - 3. Device waits for incoming pairing packet from remote - 4. If valid pairing packet received, add peer, immediately transmit a pairing packet to that peer and exit. - - ESP NOW is bare metal, there is no guaranteed packet delivery. For RTCM byte transmissions using ESP NOW: - We don't care about dropped packets or packets out of order. The ZED will check the integrity of the RTCM packet. - We don't care if the ESP NOW packet is corrupt or not. RTCM has its own CRC. RTK needs valid RTCM once every - few seconds so a single dropped frame is not critical. -*/ + Handle the ESP-NOW events +**********************************************************************/ #ifdef COMPILE_ESPNOW -// Called from main loop -// Control incoming/outgoing RTCM data from internal ESP NOW radio -// Use the ESP32 to directly transmit/receive RTCM over 2.4GHz (no WiFi needed) -void updateEspnow() -{ - if (settings.enableEspNow == true) - { - if (espnowState == ESPNOW_PAIRED || espnowState == ESPNOW_BROADCASTING) - { - // If it's been longer than a few ms since we last added a byte to the buffer - // then we've reached the end of the RTCM stream. Send partial buffer. - if (espnowOutgoingSpot > 0 && (millis() - espnowLastAdd) > 50) - { - if (espnowState == ESPNOW_PAIRED) - esp_now_send(0, (uint8_t *)&espnowOutgoing, espnowOutgoingSpot); // Send partial packet to all peers - else // if (espnowState == ESPNOW_BROADCASTING) - { - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - esp_now_send(broadcastMac, (uint8_t *)&espnowOutgoing, - espnowOutgoingSpot); // Send packet via broadcast - } +//**************************************** +// Constants +//**************************************** - if (!inMainMenu) - { - if (settings.debugEspNow == true) - systemPrintf("ESPNOW transmitted %d RTCM bytes\r\n", espnowBytesSent + espnowOutgoingSpot); - } - espnowBytesSent = 0; - espnowOutgoingSpot = 0; // Reset - } +const uint8_t peerBroadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - // If we don't receive an ESP NOW packet after some time, set RSSI to very negative - // This removes the ESPNOW icon from the display when the link goes down - if (millis() - lastEspnowRssiUpdate > 5000 && espnowRSSI > -255) - espnowRSSI = -255; - } - } -} +//**************************************** +// Locals +//**************************************** -// Create a struct for ESP NOW pairing -typedef struct PairMessage -{ - uint8_t macAddress[6]; - bool encrypt; - uint8_t channel; - uint8_t crc; // Simple check - add MAC together and limit to 8 bit -} PairMessage; - -// Callback when data is sent -void espnowOnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) +bool espNowDebug; +bool espNowDisplay; +ESP_NOW_STATE espNowState; +bool espNowVerbose; + +//********************************************************************* +// Add a peer to the ESP-NOW network +esp_err_t espNowAddPeer(const uint8_t * peerMac) { - // systemPrint("Last Packet Send Status: "); - // if (status == ESP_NOW_SEND_SUCCESS) - // systemPrintln("Delivery Success"); - // else - // systemPrintln("Delivery Fail"); + esp_now_peer_info_t peerInfo; + + // Describe the peer + memcpy(peerInfo.peer_addr, peerMac, 6); + peerInfo.channel = 0; + peerInfo.ifidx = WIFI_IF_STA; + peerInfo.encrypt = false; + + // Add the peer + if (espNowDebug) + systemPrintf("Calling esp_now_add_peer\r\n"); + esp_err_t result = esp_now_add_peer(&peerInfo); + if (result != ESP_OK) + { + systemPrintf("ERROR: Failed to add ESP-NOW peer %02x:%02x:%02x:%02x:%02x:%02x, result: %d\r\n", + peerBroadcast[0], peerBroadcast[1], + peerBroadcast[2], peerBroadcast[3], + peerBroadcast[4], peerBroadcast[5], + result); + } + else if (espNowDebug) + systemPrintf("Added ESP-NOW peer %02x:%02x:%02x:%02x:%02x:%02x\r\n", + peerBroadcast[0], peerBroadcast[1], + peerBroadcast[2], peerBroadcast[3], + peerBroadcast[4], peerBroadcast[5]); + return result; } +//---------------------------------------------------------------------- +// ESP-NOW bringup from example 4_9_ESP_NOW +// 1. Set station mode +// 2. Create nowSerial as new ESP_NOW_Serial_Class +// 3. nowSerial.begin +// ESP-NOW bringup from RTK +// 1. Get WiFi mode +// 2. Set WiFi station mode if necessary +// 3. Get WiFi station protocols +// 4. Set WIFI_PROTOCOL_LR protocol +// 5. Call esp_now_init +// 6. Call esp_wifi_set_promiscuous(true) +// 7. Set promiscuous receive callback [esp_wifi_set_promiscuous_rx_cb(promiscuous_rx_cb)] +// to get RSSI of action frames +// 8. Assign a channel if necessary, call espnowSetChannel +// 9. Set receive callback [esp_now_register_recv_cb(espnowOnDataReceived)] +// 10. Add peers from settings +// A. If no peers exist +// i. Determine if broadcast peer exists, call esp_now_is_peer_exist +// ii. Add broadcast peer if necessary, call espnowAddPeer +// iii. Set ESP-NOW state, call espnowSetState(ESP_NOW_BROADCASTING) +// B. If peers exist, +// i. Set ESP-NOW state, call espnowSetState(ESP_NOW_PAIRED) +// ii. Loop through peers listed in settings, for each +// a. Determine if peer exists, call esp_now_is_peer_exist +// b. Add peer if necessary, call espnowAddPeer +// +// In espnowOnDataReceived +// 11. Save ESP-NOW RSSI +// 12. Set lastEspnowRssiUpdate = millis() +// 13. If in ESP_NOW_PAIRING state +// A. Validate message CRC +// B. If valid CRC +// i. Save peer MAC address +// ii. espnowSetState(ESP_NOW_MAC_RECEIVED) +// 14. Else if ESP_NOW_MAC_RECEIVED state +// A. If ESP-NOW is corrections source, correctionLastSeen(CORR_ESPNOW) +// i. gnss->pushRawData +// 15. Set espnowIncomingRTCM +// +// ESP-NOW shutdown from RTK +// 1. esp_wifi_set_promiscuous(false) +// 2. esp_wifi_set_promiscuous_rx_cb(nullptr) +// 3. esp_now_unregister_recv_cb() +// 4. Remove all peers by calling espnowRemovePeer +// 5. Get WiFi mode +// 6. Set WiFi station mode if necessary +// 7. esp_wifi_get_protocol +// 8. Turn off long range protocol if necessary, call esp_wifi_set_protocol +// 9. Turn off ESP-NOW. call esp_now_deinit +// 10. Set ESP-NOW state, call espnowSetState(ESP_NOW_OFF) +// 11. Restart WiFi if necessary +//---------------------------------------------------------------------- + +//********************************************************************* +// Update the state of the ESP Now state machine +// +// +---------------------+ +// | ESP_NOW_OFF | +// +---------------------+ +// | | +// | | No pairs listed +// | V +// | +----------------------+ +// | | ESP_NOW_BROADCASTING | +// | +----------------------+ +// | | +// | | +// | V +// | +---------------------+ +// | | ESP_NOW_PAIRING | +// | +---------------------+ +// | | +// | | +// | V +// | +---------------------+ +// | | ESP_NOW_MAC_RECEIVED | +// | +---------------------+ +// | | +// | | +// | V +// | +---------------------+ +// '->| ESP_NOW_PAIRED | +// +---------------------+ +// +// Send RTCM in either ESP_NOW_BROADCASTING or ESP_NOW_PAIRED state. +// Receive RTCM in ESP_NOW_BROADCASTING, ESP_NOW_MAC_RECEIVED and +// ESP_NOW_PAIRED states. +//********************************************************************* + +//********************************************************************* // Callback when data is received -void espnowOnDataReceived(const esp_now_recv_info *mac, const uint8_t *incomingData, int len) +void espNowRxHandler(const esp_now_recv_info *mac, + const uint8_t *incomingData, + int len) { - if (espnowState == ESPNOW_PAIRING) +// typedef struct esp_now_recv_info { +// uint8_t * src_addr; // Source address of ESPNOW packet +// uint8_t * des_addr; // Destination address of ESPNOW packet +// wifi_pkt_rx_ctrl_t * rx_ctrl; // Rx control info of ESPNOW packet +// } esp_now_recv_info_t; + + uint8_t receivedMAC[6]; + + if (espNowState == ESP_NOW_PAIRING) { - if (len == sizeof(PairMessage)) // First error check + ESP_NOW_PAIR_MESSAGE pairMessage; + if (len == sizeof(pairMessage)) // First error check { - PairMessage pairMessage; - memcpy(&pairMessage, incomingData, sizeof(pairMessage)); + memcpy(&pairMessage, incomingData, len); // Check CRC uint8_t tempCRC = 0; @@ -91,563 +172,270 @@ void espnowOnDataReceived(const esp_now_recv_info *mac, const uint8_t *incomingD if (tempCRC == pairMessage.crc) // 2nd error check { memcpy(&receivedMAC, pairMessage.macAddress, 6); - espnowSetState(ESPNOW_MAC_RECEIVED); + espNowSetState(ESP_NOW_MAC_RECEIVED); } // else Pair CRC failed } } else { - espnowRSSI = packetRSSI; // Record this packet's RSSI as an ESP NOW packet - - // We've just received ESP-Now data. We assume this is RTCM and push it directly to the GNSS. - // Determine if ESPNOW is the correction source - if (correctionLastSeen(CORR_ESPNOW)) - { - // Pass RTCM bytes (presumably) from ESP NOW out ESP32-UART to GNSS - gnss->pushRawData((uint8_t *)incomingData, len); - - if ((settings.debugEspNow == true || settings.debugCorrections == true) && !inMainMenu) - systemPrintf("ESPNOW received %d RTCM bytes, pushed to GNSS, RSSI: %d\r\n", len, espnowRSSI); - } - else - { - if ((settings.debugEspNow == true || settings.debugCorrections == true) && !inMainMenu) - systemPrintf("ESPNOW received %d RTCM bytes, NOT pushed due to priority, RSSI: %d\r\n", len, - espnowRSSI); - } - - espnowIncomingRTCM = true; // Display a download icon - lastEspnowRssiUpdate = millis(); + if (espNowDisplay == true) + systemPrintf("*** ESP-NOW: RX %02x:%02x:%02x:%02x:%02x:%02x --> %02x:%02x:%02x:%02x:%02x:%02x, %d bytes, rssi: %d\r\n", + mac->src_addr[0], mac->src_addr[1], mac->src_addr[2], + mac->src_addr[3], mac->src_addr[4], mac->src_addr[5], + mac->des_addr[0], mac->des_addr[1], mac->des_addr[2], + mac->des_addr[3], mac->des_addr[4], mac->des_addr[5], + len, packetRSSI); } } -// Callback for all RX Packets -// Get RSSI of all incoming management packets: https://esp32.com/viewtopic.php?t=13889 -#ifdef COMPILE_ESPNOW -void promiscuous_rx_cb(void *buf, wifi_promiscuous_pkt_type_t type) +//********************************************************************* +// Update the state of the ESP-NOW subsystem +void espNowSetState(ESP_NOW_STATE newState) { - // All espnow traffic uses action frames which are a subtype of the mgmnt frames so filter out everything else. - if (type != WIFI_PKT_MGMT) - return; - - const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buf; - packetRSSI = ppkt->rx_ctrl.rssi; -} -#endif // COMPILE_ESPNOW - -// If WiFi is already enabled, simply add the LR protocol -// If the radio is off entirely, start the radio, turn on only the LR protocol -void espnowStart() -{ - if (settings.enableEspNow == false) + const char * name[] = { - espnowStop(); - return; - } - - // Before we can issue esp_wifi_() commands WiFi must be started - if (WiFi.getMode() != WIFI_STA) - WiFi.mode(WIFI_STA); - - // Verify that the necessary protocols are set - uint8_t protocols = 0; - esp_err_t response = esp_wifi_get_protocol(WIFI_IF_STA, &protocols); - if (response != ESP_OK) - systemPrintf("espnowStart: Failed to get protocols: %s\r\n", esp_err_to_name(response)); - - if ((wifiIsRunning() == false) && espnowState == ESPNOW_OFF) + "ESP_NOW_OFF", + "ESP_NOW_BROADCASTING", + "ESP_NOW_PAIRING", + "ESP_NOW_MAC_RECEIVED", + "ESP_NOW_PAIRED", + }; + const int nameCount = sizeof(name) / sizeof(name[0]); + const char * newName; + char nLine[80]; + const char * oldName; + char oLine[80]; + + if (espNowDebug == true) { - // Radio is off, turn it on - if (protocols != (WIFI_PROTOCOL_LR)) - { - response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); // Stops WiFi Station. - if (response != ESP_OK) - systemPrintf("espnowStart: Error setting ESP-Now lone protocol: %s\r\n", esp_err_to_name(response)); - else - { - if (settings.debugEspNow == true) - systemPrintln("WiFi off, ESP-Now added to protocols"); - } - } + // Get the old state name + if (espNowState < ESP_NOW_MAX) + oldName = name[espNowState]; else { - if (settings.debugEspNow == true) - systemPrintln("LR protocol already in place"); - } - } - // If WiFi is on but ESP NOW is off, then enable LR protocol - else if (wifiIsRunning() && espnowState == ESPNOW_OFF) - { - // Enable WiFi + ESP-Now - // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps - if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR)) - { - response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | - WIFI_PROTOCOL_LR); - if (response != ESP_OK) - systemPrintf("espnowStart: Error setting ESP-Now + WiFi protocols: %s\r\n", esp_err_to_name(response)); - else - { - if (settings.debugEspNow == true) - systemPrintln("WiFi on, ESP-Now added to protocols"); - } + sprintf(oLine, "Unknown state: %d", espNowState); + oldName = &oLine[0]; } + + // Get the new state name + if (newState < ESP_NOW_MAX) + newName = name[newState]; else { - if (settings.debugEspNow == true) - systemPrintln("WiFi was already on, and LR protocol already in place"); + sprintf(nLine, "Unknown state: %d", newState); + newName = &nLine[0]; } - } - - // If ESP-Now is already active, do nothing - else - { - if (settings.debugEspNow == true) - systemPrintln("ESP-Now already on."); - } - - // WiFi.setSleep(false); //We must disable sleep so that ESP-NOW can readily receive packets - // See: https://github.com/sparkfun/SparkFun_RTK_Everywhere_Firmware/issues/241 - // Init ESP-NOW - if (esp_now_init() != ESP_OK) - { - systemPrintln("espnowStart: Error starting ESP-Now"); - return; + // Display the state change + if (newState == espNowState) + systemPrintf("ESP-NOW: *%s\r\n", newName); + else + systemPrintf("ESP-NOW: %s --> %s\r\n", oldName, newName); } + espNowState = newState; +} - // Use promiscuous callback to capture RSSI of packet - response = esp_wifi_set_promiscuous(true); - if (response != ESP_OK) - systemPrintf("espnowStart: Error setting promiscuous mode: %s\r\n", esp_err_to_name(response)); - - esp_wifi_set_promiscuous_rx_cb(&promiscuous_rx_cb); - - // Assign channel if not connected to an AP - if (wifiIsConnected() == false) - espnowSetChannel(settings.wifiChannel); - - // Register callbacks - // esp_now_register_send_cb(espnowOnDataSent); - esp_now_register_recv_cb(espnowOnDataReceived); +//********************************************************************* +// Start ESP-NOW layer +bool espNowStart() +{ + int index; + bool started; + esp_err_t status; - if (settings.espnowPeerCount == 0) + do { - // Enter broadcast mode + started = false; - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - - if (esp_now_is_peer_exist(broadcastMac) == true) + // 5. Call esp_now_init + if (espNowDebug && espNowVerbose) + systemPrintf("Calling esp_now_init\r\n"); + status = esp_now_init(); + if (status != ESP_OK) { - if (settings.debugEspNow == true) - systemPrintln("Broadcast peer already exists"); + systemPrintf("ERROR: Failed to initialize ESP-NOW, status: %d\r\n", status); + break; } - else + + // 9. Set receive callback [esp_now_register_recv_cb(espnowOnDataReceived)] + if (espNowDebug && espNowVerbose) + systemPrintf("Calling esp_now_register_recv_cb\r\n"); + status = esp_now_register_recv_cb(espNowRxHandler); + if (status != ESP_OK) { - esp_err_t result = espnowAddPeer(broadcastMac, false); // Encryption not support for broadcast MAC - if (result != ESP_OK) - { - if (settings.debugEspNow == true) - systemPrintln("Failed to add broadcast peer"); - } - else - { - if (settings.debugEspNow == true) - systemPrintln("Broadcast peer added"); - } + systemPrintf("ERROR: Failed to set ESP_NOW RX callback, status: %d\r\n", status); + break; } - espnowSetState(ESPNOW_BROADCASTING); - } - else - { - // If we have peers, move to paired state - espnowSetState(ESPNOW_PAIRED); - - if (settings.debugEspNow == true) - systemPrintf("Adding %d espnow peers\r\n", settings.espnowPeerCount); + // 10. Add peers from settings + // i. Set ESP-NOW state, call espNowSetState(ESP_NOW_PAIRED) + if (espNowDebug && espNowVerbose) + systemPrintf("Calling espNowSetState\r\n"); + espNowSetState(ESP_NOW_PAIRED); - for (int x = 0; x < settings.espnowPeerCount; x++) + // ii. Loop through peers listed in settings, for each + for (index = 0; index < ESPNOW_MAX_PEERS; index++) { - if (esp_now_is_peer_exist(settings.espnowPeers[x]) == true) - { - if (settings.debugEspNow == true) - systemPrintf("Peer #%d already exists\r\n", x); - } - else + // a. Determine if peer exists, call esp_now_is_peer_exist + if (espNowDebug && espNowVerbose) + systemPrintf("Calling esp_now_is_peer_exist\r\n"); + if (esp_now_is_peer_exist(settings.espnowPeers[index]) == false) { - esp_err_t result = espnowAddPeer(settings.espnowPeers[x]); - if (result != ESP_OK) + // b. Add peer if necessary, call espnowAddPeer + if (espNowDebug && espNowVerbose) + systemPrintf("Calling espNowAddPeer\r\n"); + status = espNowAddPeer(&settings.espnowPeers[index][0]); + if (status != ESP_OK) { - if (settings.debugEspNow == true) - systemPrintf("Failed to add peer #%d\r\n", x); + systemPrintf("ERROR: Failed to add ESP-NOW peer %02x:%02x:%02x:%02x:%02x:%02x, status: %d\r\n", + settings.espnowPeers[index][0], + settings.espnowPeers[index][1], + settings.espnowPeers[index][2], + settings.espnowPeers[index][3], + settings.espnowPeers[index][4], + settings.espnowPeers[index][5], + status); + break; } } - } - } - - systemPrintln("ESP-Now Started"); -} - -// If WiFi is already enabled, simply remove the LR protocol -// If WiFi is off, stop the radio entirely -void espnowStop() -{ - if (espnowState == ESPNOW_OFF) - return; - - // Turn off promiscuous WiFi mode - esp_err_t response = esp_wifi_set_promiscuous(false); - if (response != ESP_OK) - systemPrintf("espnowStop: Failed to set promiscuous mode: %s\r\n", esp_err_to_name(response)); - - esp_wifi_set_promiscuous_rx_cb(nullptr); - - // Deregister callbacks - // esp_now_unregister_send_cb(); - response = esp_now_unregister_recv_cb(); - if (response != ESP_OK) - systemPrintf("espnowStop: Failed to unregister receive callback: %s\r\n", esp_err_to_name(response)); - - // Forget all ESP-Now Peers - for (int x = 0; x < settings.espnowPeerCount; x++) - espnowRemovePeer(settings.espnowPeers[x]); - - if (WiFi.getMode() != WIFI_STA) - WiFi.mode(WIFI_STA); - - // Verify that the necessary protocols are set - uint8_t protocols = 0; - response = esp_wifi_get_protocol(WIFI_IF_STA, &protocols); - if (response != ESP_OK) - systemPrintf("espnowStop: Failed to get protocols: %s\r\n", esp_err_to_name(response)); - - // Leave WiFi with default settings (no WIFI_PROTOCOL_LR for ESP NOW) - if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N)) - { - response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N); - if (response != ESP_OK) - systemPrintf("espnowStop: Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); - else - { - if (settings.debugEspNow == true) - systemPrintln("espnowStop: WiFi on, ESP-Now removed from protocols"); - } - } - else - { - if (settings.debugEspNow == true) - systemPrintln("espnowStop: ESP-Now already removed from protocols"); - } - - // Deinit ESP-NOW - if (esp_now_deinit() != ESP_OK) - { - systemPrintln("Error deinitializing ESP-NOW"); - return; - } - - espnowSetState(ESPNOW_OFF); - - if (wifiIsRunning() == false) - { - // ESP-NOW was the only thing using the radio so turn WiFi radio off entirely - WiFi.mode(WIFI_OFF); - - if (settings.debugEspNow == true) - systemPrintln("WiFi Radio off entirely"); - } - // If WiFi is on, then restart WiFi - else if (wifiIsRunning()) - { - if (settings.debugEspNow == true) - systemPrintln("ESP-Now starting WiFi"); - wifiStart(); // Force WiFi to restart - } -} - -// Start ESP-Now if needed, put ESP-Now into broadcast state -void espnowBeginPairing() -{ - espnowStart(); - - // To begin pairing, we must add the broadcast MAC to the peer list - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - espnowAddPeer(broadcastMac, false); // Encryption is not supported for multicast addresses - - espnowSetState(ESPNOW_PAIRING); -} -// Regularly call during pairing to see if we've received a Pairing message -bool espnowIsPaired() -{ - if (espnowState == ESPNOW_MAC_RECEIVED) - { - // Remove broadcast peer - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - espnowRemovePeer(broadcastMac); - - if (esp_now_is_peer_exist(receivedMAC) == true) - { - if (settings.debugEspNow == true) - systemPrintln("Peer already exists"); - } - else - { - // Add new peer to system - espnowAddPeer(receivedMAC); - - // Record this MAC to peer list - memcpy(settings.espnowPeers[settings.espnowPeerCount], receivedMAC, 6); - settings.espnowPeerCount++; - settings.espnowPeerCount %= ESPNOW_MAX_PEERS; + // Determine if an error occurred + if (index < ESPNOW_MAX_PEERS) + break; } - // Send message directly to the received MAC (not unicast), then exit - espnowSendPairMessage(receivedMAC); - - // Enable radio. User may have arrived here from the setup menu rather than serial menu. - settings.enableEspNow = true; - - recordSystemSettings(); // Record enableEspNow and espnowPeerCount to NVM - - espnowSetState(ESPNOW_PAIRED); - return (true); - } - return (false); -} - -// Create special pair packet to a given MAC -esp_err_t espnowSendPairMessage(uint8_t *sendToMac) -{ - // Assemble message to send - PairMessage pairMessage; - - // Get unit MAC address - memcpy(pairMessage.macAddress, wifiMACAddress, 6); - pairMessage.encrypt = false; - pairMessage.channel = 0; + // ESP-NOW has started successfully + if (espNowDebug) + systemPrintf("ESP-NOW online\r\n"); - pairMessage.crc = 0; // Calculate CRC - for (int x = 0; x < 6; x++) - pairMessage.crc += wifiMACAddress[x]; + started = true; + } while (0); - return (esp_now_send(sendToMac, (uint8_t *)&pairMessage, sizeof(pairMessage))); // Send packet to given MAC -} - -// Add a given MAC address to the peer list -esp_err_t espnowAddPeer(uint8_t *peerMac) -{ - return (espnowAddPeer(peerMac, true)); // Encrypt by default + return started; } -esp_err_t espnowAddPeer(uint8_t *peerMac, bool encrypt) +//********************************************************************* +// Stop ESP-NOW layer +bool espNowStop() { - esp_now_peer_info_t peerInfo; - - memcpy(peerInfo.peer_addr, peerMac, 6); - peerInfo.channel = 0; - peerInfo.ifidx = WIFI_IF_STA; - // memcpy(peerInfo.lmk, "RTKProductsLMK56", 16); - // peerInfo.encrypt = encrypt; - peerInfo.encrypt = false; - - esp_err_t result = esp_now_add_peer(&peerInfo); - if (result != ESP_OK) - { - if (settings.debugEspNow == true) - systemPrintf("Failed to add peer: 0x%02X%02X%02X%02X%02X%02X\r\n", peerMac[0], peerMac[1], peerMac[2], - peerMac[3], peerMac[4], peerMac[5]); - } - return (result); -} - -// Remove a given MAC address from the peer list -esp_err_t espnowRemovePeer(uint8_t *peerMac) -{ - esp_err_t response = esp_now_del_peer(peerMac); - if (response != ESP_OK) + uint8_t mode; + esp_now_peer_num_t peerCount; + uint8_t primaryChannel; + uint8_t protocols; + wifi_second_chan_t secondaryChannel; + bool stopped; + esp_err_t status; + + do { - if (settings.debugEspNow == true) - systemPrintf("Failed to remove peer: %s\r\n", esp_err_to_name(response)); - } - - return (response); -} - -// Update the state of the ESP Now state machine -void espnowSetState(ESPNOWState newState) -{ - if (espnowState == newState && settings.debugEspNow == true) - systemPrint("*"); - espnowState = newState; + stopped = false; - if (settings.debugEspNow == true) - { - systemPrint("espnowState: "); - switch (newState) + // 3. esp_now_unregister_recv_cb() + if (espNowDebug) + systemPrintf("Calling esp_now_unregister_recv_cb\r\n"); + status = esp_now_unregister_recv_cb(); + if (status != ESP_OK) { - case ESPNOW_OFF: - systemPrintln("ESPNOW_OFF"); - break; - case ESPNOW_BROADCASTING: - systemPrintln("ESPNOW_BROADCASTING"); - break; - case ESPNOW_PAIRING: - systemPrintln("ESPNOW_PAIRING"); - break; - case ESPNOW_MAC_RECEIVED: - systemPrintln("ESPNOW_MAC_RECEIVED"); - break; - case ESPNOW_PAIRED: - systemPrintln("ESPNOW_PAIRED"); - break; - default: - systemPrintf("Unknown ESPNOW state: %d\r\n", newState); + systemPrintf("ERROR: Failed to clear ESP_NOW RX callback, status: %d\r\n", status); break; } - } -} + if (espNowDebug && espNowVerbose) + systemPrintf("ESP-NOW: RX callback removed\r\n"); -void espnowProcessRTCM(byte incoming) -{ - // If we are paired, - // Or if the radio is broadcasting - // Then add bytes to the outgoing buffer - if (espnowState == ESPNOW_PAIRED || espnowState == ESPNOW_BROADCASTING) - { - // Move this byte into ESP NOW to send buffer - espnowOutgoing[espnowOutgoingSpot++] = incoming; - espnowLastAdd = millis(); - } + if (espNowDisplay) + systemPrintf("ESP-NOW offline\r\n"); - // Send buffer when full - if (espnowOutgoingSpot == sizeof(espnowOutgoing)) - { - espnowOutgoingSpot = 0; // Wrap - - if (espnowState == ESPNOW_PAIRED) - esp_now_send(0, (uint8_t *)&espnowOutgoing, sizeof(espnowOutgoing)); // Send packet to all peers - else // if (espnowState == ESPNOW_BROADCASTING) + // 4. Remove all peers by calling espnowRemovePeer + if (espNowDebug && espNowVerbose) + systemPrintf("Calling esp_now_is_peer_exist\r\n"); + if (esp_now_is_peer_exist(peerBroadcast)) { - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - esp_now_send(broadcastMac, (uint8_t *)&espnowOutgoing, - sizeof(espnowOutgoing)); // Send packet via broadcast + if (espNowDebug && espNowVerbose) + systemPrintf("Calling esp_now_del_peer\r\n"); + status = esp_now_del_peer(peerBroadcast); + if (status != ESP_OK) + { + systemPrintf("ERROR: Failed to delete broadcast peer, status: %d\r\n", status); + break; + } + if (espNowDebug && espNowVerbose) + systemPrintf("ESP-NOW removed broadcast peer\r\n"); } - delay(10); // We need a small delay between sending multiple packets - - espnowBytesSent += sizeof(espnowOutgoing); - - espnowOutgoingRTCM = true; - } -} - -// A blocking function that is used to pair two devices -// either through the serial menu or AP config -void espnowStaticPairing() -{ - systemPrintln("Begin ESP NOW Pairing"); - - // Start ESP-Now if needed, put ESP-Now into broadcast state - espnowBeginPairing(); - - // Begin sending our MAC every 250ms until a remote device sends us there info - randomSeed(millis()); - - systemPrintln("Begin pairing. Place other unit in pairing mode. Press any key to exit."); - clearBuffer(); + // Walk the unicast peers + while (1) + { + esp_now_peer_info_t peerInfo; - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + // Get the next unicast peer + if (espNowDebug && espNowVerbose) + systemPrintf("Calling esp_now_fetch_peer\r\n"); + status = esp_now_fetch_peer(true, &peerInfo); + if (status != ESP_OK) + break; - bool exitPair = false; - while (exitPair == false) - { - if (systemAvailable()) + // Remove the unicast peer + if (espNowDebug && espNowVerbose) + systemPrintf("Calling esp_now_del_peer\r\n"); + status = esp_now_del_peer(peerInfo.peer_addr); + if (status != ESP_OK) + { + systemPrintf("ERROR: Failed to delete peer %02x:%02x:%02x:%02x:%02x:%02x, status: %d\r\n", + peerInfo.peer_addr[0], peerInfo.peer_addr[1], + peerInfo.peer_addr[2], peerInfo.peer_addr[3], + peerInfo.peer_addr[4], peerInfo.peer_addr[5], + status); + break; + } + if (espNowDebug && espNowVerbose) + systemPrintf("ESP-NOW removed peer %02x:%02x:%02x:%02x:%02x:%02x\r\n", + peerInfo.peer_addr[0], peerInfo.peer_addr[1], + peerInfo.peer_addr[2], peerInfo.peer_addr[3], + peerInfo.peer_addr[4], peerInfo.peer_addr[5]); + } + if (status != ESP_ERR_ESPNOW_NOT_FOUND) { - systemPrintln("User pressed button. Pairing canceled."); + systemPrintf("ERROR: Failed to get peer info for deletion, status: %d\r\n", status); break; } - int timeout = 1000 + random(0, 100); // Delay 1000 to 1100ms - for (int x = 0; x < timeout; x++) + // Get the number of peers + if (espNowDebug && espNowVerbose) { - delay(1); - - if (espnowIsPaired() == true) // Check if we've received a pairing message + systemPrintf("Calling esp_now_get_peer_num\r\n"); + status = esp_now_get_peer_num(&peerCount); + if (status != ESP_OK) { - systemPrintln("Pairing compete"); - exitPair = true; + systemPrintf("ERROR: Failed to get the peer count, status: %d\r\n", status); break; } + systemPrintf("peerCount: %d\r\n", peerCount); } - espnowSendPairMessage(broadcastMac); // Send unit's MAC address over broadcast, no ack, no encryption - - systemPrintln("Scanning for other radio..."); - } -} - -// Returns the current channel being used by WiFi -uint8_t espnowGetChannel() -{ - if (espnowState == ESPNOW_OFF) - return 0; - - bool originalPromiscuousMode = false; - esp_err_t response = esp_wifi_get_promiscuous(&originalPromiscuousMode); - if (response != ESP_OK) - systemPrintf("getPromiscuous failed: %s\r\n", esp_err_to_name(response)); - - // We must be in promiscuous mode to get the channel number - if (originalPromiscuousMode == false) - esp_wifi_set_promiscuous(true); - - uint8_t primaryChannelNumber = 0; - wifi_second_chan_t secondaryChannelNumber; + // Stop the ESP-NOW state machine + espNowSetState(ESP_NOW_OFF); - response = esp_wifi_get_channel(&primaryChannelNumber, &secondaryChannelNumber); - if (response != ESP_OK) - systemPrintf("getChannel failed: %s\r\n", esp_err_to_name(response)); - - // Return to the original mode - if (originalPromiscuousMode == false) - esp_wifi_set_promiscuous(false); - - return (primaryChannelNumber); -} - -// Returns the current channel being used by WiFi -bool espnowSetChannel(uint8_t channelNumber) -{ - if (wifiIsConnected() == true) - { - systemPrintln("ESP-NOW channel can't be modified while WiFi is connected."); - return (false); - } - - bool originalPromiscuousMode = false; - esp_err_t response = esp_wifi_get_promiscuous(&originalPromiscuousMode); - if (response != ESP_OK) - systemPrintf("getPromiscuous failed: %s\r\n", esp_err_to_name(response)); - - // We must be in promiscuous mode to set the channel number - if (originalPromiscuousMode == false) - esp_wifi_set_promiscuous(true); + // 9. Turn off ESP-NOW. call esp_now_deinit + if (espNowDebug && espNowVerbose) + systemPrintf("Calling esp_now_deinit\r\n"); + status = esp_now_deinit(); + if (status != ESP_OK) + { + systemPrintf("ERROR: Failed to deinit ESP-NOW, status: %d\r\n", status); + break; + } - bool setSuccess = false; - response = esp_wifi_set_channel(channelNumber, WIFI_SECOND_CHAN_NONE); - if (response != ESP_OK) - systemPrintf("setChannel to %d failed: %s\r\n", channelNumber, esp_err_to_name(response)); - else - setSuccess = true; + // 11. Restart WiFi if necessary - // Return to the original mode - if (originalPromiscuousMode == false) - esp_wifi_set_promiscuous(false); + // ESP-NOW has stopped successfully + if (espNowDebug) + systemPrintf("ESP-NOW stopped\r\n"); + stopped = true; + } while (0); - return (setSuccess); + // Return the stopped status + return stopped; } #endif // COMPILE_ESPNOW diff --git a/Firmware/RTK_Everywhere/ESPNOW_old.ino b/Firmware/RTK_Everywhere/ESPNOW_old.ino new file mode 100644 index 000000000..6c2d46c39 --- /dev/null +++ b/Firmware/RTK_Everywhere/ESPNOW_old.ino @@ -0,0 +1,653 @@ +/* + Use ESP NOW protocol to transmit RTCM between RTK Products via 2.4GHz + + How pairing works: + 1. Device enters pairing mode + 2. Device adds the broadcast MAC (all 0xFFs) as peer + 3. Device waits for incoming pairing packet from remote + 4. If valid pairing packet received, add peer, immediately transmit a pairing packet to that peer and exit. + + ESP NOW is bare metal, there is no guaranteed packet delivery. For RTCM byte transmissions using ESP NOW: + We don't care about dropped packets or packets out of order. The ZED will check the integrity of the RTCM packet. + We don't care if the ESP NOW packet is corrupt or not. RTCM has its own CRC. RTK needs valid RTCM once every + few seconds so a single dropped frame is not critical. +*/ + +#ifdef COMPILE_ESPNOW + +// Called from main loop +// Control incoming/outgoing RTCM data from internal ESP NOW radio +// Use the ESP32 to directly transmit/receive RTCM over 2.4GHz (no WiFi needed) +void updateEspnow() +{ + if (settings.enableEspNow == true) + { + if (espnowState == ESPNOW_PAIRED || espnowState == ESPNOW_BROADCASTING) + { + // If it's been longer than a few ms since we last added a byte to the buffer + // then we've reached the end of the RTCM stream. Send partial buffer. + if (espnowOutgoingSpot > 0 && (millis() - espnowLastAdd) > 50) + { + if (espnowState == ESPNOW_PAIRED) + esp_now_send(0, (uint8_t *)&espnowOutgoing, espnowOutgoingSpot); // Send partial packet to all peers + else // if (espnowState == ESPNOW_BROADCASTING) + { + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + esp_now_send(broadcastMac, (uint8_t *)&espnowOutgoing, + espnowOutgoingSpot); // Send packet via broadcast + } + + if (!inMainMenu) + { + if (settings.debugEspNow == true) + systemPrintf("ESPNOW transmitted %d RTCM bytes\r\n", espnowBytesSent + espnowOutgoingSpot); + } + espnowBytesSent = 0; + espnowOutgoingSpot = 0; // Reset + } + + // If we don't receive an ESP NOW packet after some time, set RSSI to very negative + // This removes the ESPNOW icon from the display when the link goes down + if (millis() - lastEspnowRssiUpdate > 5000 && espnowRSSI > -255) + espnowRSSI = -255; + } + } +} + +// Create a struct for ESP NOW pairing +typedef struct PairMessage +{ + uint8_t macAddress[6]; + bool encrypt; + uint8_t channel; + uint8_t crc; // Simple check - add MAC together and limit to 8 bit +} PairMessage; + +// Callback when data is sent +void espnowOnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) +{ + // systemPrint("Last Packet Send Status: "); + // if (status == ESP_NOW_SEND_SUCCESS) + // systemPrintln("Delivery Success"); + // else + // systemPrintln("Delivery Fail"); +} + +// Callback when data is received +void espnowOnDataReceived(const esp_now_recv_info *mac, const uint8_t *incomingData, int len) +{ + if (espnowState == ESPNOW_PAIRING) + { + if (len == sizeof(PairMessage)) // First error check + { + PairMessage pairMessage; + memcpy(&pairMessage, incomingData, sizeof(pairMessage)); + + // Check CRC + uint8_t tempCRC = 0; + for (int x = 0; x < 6; x++) + tempCRC += pairMessage.macAddress[x]; + + if (tempCRC == pairMessage.crc) // 2nd error check + { + memcpy(&receivedMAC, pairMessage.macAddress, 6); + espnowSetState(ESPNOW_MAC_RECEIVED); + } + // else Pair CRC failed + } + } + else + { + espnowRSSI = packetRSSI; // Record this packet's RSSI as an ESP NOW packet + + // We've just received ESP-Now data. We assume this is RTCM and push it directly to the GNSS. + // Determine if ESPNOW is the correction source + if (correctionLastSeen(CORR_ESPNOW)) + { + // Pass RTCM bytes (presumably) from ESP NOW out ESP32-UART to GNSS + gnss->pushRawData((uint8_t *)incomingData, len); + + if ((settings.debugEspNow == true || settings.debugCorrections == true) && !inMainMenu) + systemPrintf("ESPNOW received %d RTCM bytes, pushed to GNSS, RSSI: %d\r\n", len, espnowRSSI); + } + else + { + if ((settings.debugEspNow == true || settings.debugCorrections == true) && !inMainMenu) + systemPrintf("ESPNOW received %d RTCM bytes, NOT pushed due to priority, RSSI: %d\r\n", len, + espnowRSSI); + } + + espnowIncomingRTCM = true; // Display a download icon + lastEspnowRssiUpdate = millis(); + } +} + +// Callback for all RX Packets +// Get RSSI of all incoming management packets: https://esp32.com/viewtopic.php?t=13889 +#ifdef COMPILE_ESPNOW +void promiscuous_rx_cb(void *buf, wifi_promiscuous_pkt_type_t type) +{ + // All espnow traffic uses action frames which are a subtype of the mgmnt frames so filter out everything else. + if (type != WIFI_PKT_MGMT) + return; + + const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buf; + packetRSSI = ppkt->rx_ctrl.rssi; +} +#endif // COMPILE_ESPNOW + +// If WiFi is already enabled, simply add the LR protocol +// If the radio is off entirely, start the radio, turn on only the LR protocol +void espnowStart() +{ + if (settings.enableEspNow == false) + { + espnowStop(); + return; + } + + // Before we can issue esp_wifi_() commands WiFi must be started + if (WiFi.getMode() != WIFI_STA) + WiFi.mode(WIFI_STA); + + // Verify that the necessary protocols are set + uint8_t protocols = 0; + esp_err_t response = esp_wifi_get_protocol(WIFI_IF_STA, &protocols); + if (response != ESP_OK) + systemPrintf("espnowStart: Failed to get protocols: %s\r\n", esp_err_to_name(response)); + + if ((wifiIsRunning() == false) && espnowState == ESPNOW_OFF) + { + // Radio is off, turn it on + if (protocols != (WIFI_PROTOCOL_LR)) + { + response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); // Stops WiFi Station. + if (response != ESP_OK) + systemPrintf("espnowStart: Error setting ESP-Now lone protocol: %s\r\n", esp_err_to_name(response)); + else + { + if (settings.debugEspNow == true) + systemPrintln("WiFi off, ESP-Now added to protocols"); + } + } + else + { + if (settings.debugEspNow == true) + systemPrintln("LR protocol already in place"); + } + } + // If WiFi is on but ESP NOW is off, then enable LR protocol + else if (wifiIsRunning() && espnowState == ESPNOW_OFF) + { + // Enable WiFi + ESP-Now + // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps + if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR)) + { + response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | + WIFI_PROTOCOL_LR); + if (response != ESP_OK) + systemPrintf("espnowStart: Error setting ESP-Now + WiFi protocols: %s\r\n", esp_err_to_name(response)); + else + { + if (settings.debugEspNow == true) + systemPrintln("WiFi on, ESP-Now added to protocols"); + } + } + else + { + if (settings.debugEspNow == true) + systemPrintln("WiFi was already on, and LR protocol already in place"); + } + } + + // If ESP-Now is already active, do nothing + else + { + if (settings.debugEspNow == true) + systemPrintln("ESP-Now already on."); + } + + // WiFi.setSleep(false); //We must disable sleep so that ESP-NOW can readily receive packets + // See: https://github.com/sparkfun/SparkFun_RTK_Everywhere_Firmware/issues/241 + + // Init ESP-NOW + if (esp_now_init() != ESP_OK) + { + systemPrintln("espnowStart: Error starting ESP-Now"); + return; + } + + // Use promiscuous callback to capture RSSI of packet + response = esp_wifi_set_promiscuous(true); + if (response != ESP_OK) + systemPrintf("espnowStart: Error setting promiscuous mode: %s\r\n", esp_err_to_name(response)); + + esp_wifi_set_promiscuous_rx_cb(&promiscuous_rx_cb); + + // Assign channel if not connected to an AP + if (wifiIsConnected() == false) + espnowSetChannel(settings.wifiChannel); + + // Register callbacks + // esp_now_register_send_cb(espnowOnDataSent); + esp_now_register_recv_cb(espnowOnDataReceived); + + if (settings.espnowPeerCount == 0) + { + // Enter broadcast mode + + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + if (esp_now_is_peer_exist(broadcastMac) == true) + { + if (settings.debugEspNow == true) + systemPrintln("Broadcast peer already exists"); + } + else + { + esp_err_t result = espnowAddPeer(broadcastMac, false); // Encryption not support for broadcast MAC + if (result != ESP_OK) + { + if (settings.debugEspNow == true) + systemPrintln("Failed to add broadcast peer"); + } + else + { + if (settings.debugEspNow == true) + systemPrintln("Broadcast peer added"); + } + } + + espnowSetState(ESPNOW_BROADCASTING); + } + else + { + // If we have peers, move to paired state + espnowSetState(ESPNOW_PAIRED); + + if (settings.debugEspNow == true) + systemPrintf("Adding %d espnow peers\r\n", settings.espnowPeerCount); + + for (int x = 0; x < settings.espnowPeerCount; x++) + { + if (esp_now_is_peer_exist(settings.espnowPeers[x]) == true) + { + if (settings.debugEspNow == true) + systemPrintf("Peer #%d already exists\r\n", x); + } + else + { + esp_err_t result = espnowAddPeer(settings.espnowPeers[x]); + if (result != ESP_OK) + { + if (settings.debugEspNow == true) + systemPrintf("Failed to add peer #%d\r\n", x); + } + } + } + } + + systemPrintln("ESP-Now Started"); +} + +// If WiFi is already enabled, simply remove the LR protocol +// If WiFi is off, stop the radio entirely +void espnowStop() +{ + if (espnowState == ESPNOW_OFF) + return; + + // Turn off promiscuous WiFi mode + esp_err_t response = esp_wifi_set_promiscuous(false); + if (response != ESP_OK) + systemPrintf("espnowStop: Failed to set promiscuous mode: %s\r\n", esp_err_to_name(response)); + + esp_wifi_set_promiscuous_rx_cb(nullptr); + + // Deregister callbacks + // esp_now_unregister_send_cb(); + response = esp_now_unregister_recv_cb(); + if (response != ESP_OK) + systemPrintf("espnowStop: Failed to unregister receive callback: %s\r\n", esp_err_to_name(response)); + + // Forget all ESP-Now Peers + for (int x = 0; x < settings.espnowPeerCount; x++) + espnowRemovePeer(settings.espnowPeers[x]); + + if (WiFi.getMode() != WIFI_STA) + WiFi.mode(WIFI_STA); + + // Verify that the necessary protocols are set + uint8_t protocols = 0; + response = esp_wifi_get_protocol(WIFI_IF_STA, &protocols); + if (response != ESP_OK) + systemPrintf("espnowStop: Failed to get protocols: %s\r\n", esp_err_to_name(response)); + + // Leave WiFi with default settings (no WIFI_PROTOCOL_LR for ESP NOW) + if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N)) + { + response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N); + if (response != ESP_OK) + systemPrintf("espnowStop: Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); + else + { + if (settings.debugEspNow == true) + systemPrintln("espnowStop: WiFi on, ESP-Now removed from protocols"); + } + } + else + { + if (settings.debugEspNow == true) + systemPrintln("espnowStop: ESP-Now already removed from protocols"); + } + + // Deinit ESP-NOW + if (esp_now_deinit() != ESP_OK) + { + systemPrintln("Error deinitializing ESP-NOW"); + return; + } + + espnowSetState(ESPNOW_OFF); + + if (wifiIsRunning() == false) + { + // ESP-NOW was the only thing using the radio so turn WiFi radio off entirely + WiFi.mode(WIFI_OFF); + + if (settings.debugEspNow == true) + systemPrintln("WiFi Radio off entirely"); + } + // If WiFi is on, then restart WiFi + else if (wifiIsRunning()) + { + if (settings.debugEspNow == true) + systemPrintln("ESP-Now starting WiFi"); + wifiStart(); // Force WiFi to restart + } +} + +// Start ESP-Now if needed, put ESP-Now into broadcast state +void espnowBeginPairing() +{ + espnowStart(); + + // To begin pairing, we must add the broadcast MAC to the peer list + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + espnowAddPeer(broadcastMac, false); // Encryption is not supported for multicast addresses + + espnowSetState(ESPNOW_PAIRING); +} + +// Regularly call during pairing to see if we've received a Pairing message +bool espnowIsPaired() +{ + if (espnowState == ESPNOW_MAC_RECEIVED) + { + // Remove broadcast peer + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + espnowRemovePeer(broadcastMac); + + if (esp_now_is_peer_exist(receivedMAC) == true) + { + if (settings.debugEspNow == true) + systemPrintln("Peer already exists"); + } + else + { + // Add new peer to system + espnowAddPeer(receivedMAC); + + // Record this MAC to peer list + memcpy(settings.espnowPeers[settings.espnowPeerCount], receivedMAC, 6); + settings.espnowPeerCount++; + settings.espnowPeerCount %= ESPNOW_MAX_PEERS; + } + + // Send message directly to the received MAC (not unicast), then exit + espnowSendPairMessage(receivedMAC); + + // Enable radio. User may have arrived here from the setup menu rather than serial menu. + settings.enableEspNow = true; + + recordSystemSettings(); // Record enableEspNow and espnowPeerCount to NVM + + espnowSetState(ESPNOW_PAIRED); + return (true); + } + return (false); +} + +// Create special pair packet to a given MAC +esp_err_t espnowSendPairMessage(uint8_t *sendToMac) +{ + // Assemble message to send + PairMessage pairMessage; + + // Get unit MAC address + memcpy(pairMessage.macAddress, wifiMACAddress, 6); + pairMessage.encrypt = false; + pairMessage.channel = 0; + + pairMessage.crc = 0; // Calculate CRC + for (int x = 0; x < 6; x++) + pairMessage.crc += wifiMACAddress[x]; + + return (esp_now_send(sendToMac, (uint8_t *)&pairMessage, sizeof(pairMessage))); // Send packet to given MAC +} + +// Add a given MAC address to the peer list +esp_err_t espnowAddPeer(uint8_t *peerMac) +{ + return (espnowAddPeer(peerMac, true)); // Encrypt by default +} + +esp_err_t espnowAddPeer(uint8_t *peerMac, bool encrypt) +{ + esp_now_peer_info_t peerInfo; + + memcpy(peerInfo.peer_addr, peerMac, 6); + peerInfo.channel = 0; + peerInfo.ifidx = WIFI_IF_STA; + // memcpy(peerInfo.lmk, "RTKProductsLMK56", 16); + // peerInfo.encrypt = encrypt; + peerInfo.encrypt = false; + + esp_err_t result = esp_now_add_peer(&peerInfo); + if (result != ESP_OK) + { + if (settings.debugEspNow == true) + systemPrintf("Failed to add peer: 0x%02X%02X%02X%02X%02X%02X\r\n", peerMac[0], peerMac[1], peerMac[2], + peerMac[3], peerMac[4], peerMac[5]); + } + return (result); +} + +// Remove a given MAC address from the peer list +esp_err_t espnowRemovePeer(uint8_t *peerMac) +{ + esp_err_t response = esp_now_del_peer(peerMac); + if (response != ESP_OK) + { + if (settings.debugEspNow == true) + systemPrintf("Failed to remove peer: %s\r\n", esp_err_to_name(response)); + } + + return (response); +} + +// Update the state of the ESP Now state machine +void espnowSetState(ESPNOWState newState) +{ + if (espnowState == newState && settings.debugEspNow == true) + systemPrint("*"); + espnowState = newState; + + if (settings.debugEspNow == true) + { + systemPrint("espnowState: "); + switch (newState) + { + case ESPNOW_OFF: + systemPrintln("ESPNOW_OFF"); + break; + case ESPNOW_BROADCASTING: + systemPrintln("ESPNOW_BROADCASTING"); + break; + case ESPNOW_PAIRING: + systemPrintln("ESPNOW_PAIRING"); + break; + case ESPNOW_MAC_RECEIVED: + systemPrintln("ESPNOW_MAC_RECEIVED"); + break; + case ESPNOW_PAIRED: + systemPrintln("ESPNOW_PAIRED"); + break; + default: + systemPrintf("Unknown ESPNOW state: %d\r\n", newState); + break; + } + } +} + +void espnowProcessRTCM(byte incoming) +{ + // If we are paired, + // Or if the radio is broadcasting + // Then add bytes to the outgoing buffer + if (espnowState == ESPNOW_PAIRED || espnowState == ESPNOW_BROADCASTING) + { + // Move this byte into ESP NOW to send buffer + espnowOutgoing[espnowOutgoingSpot++] = incoming; + espnowLastAdd = millis(); + } + + // Send buffer when full + if (espnowOutgoingSpot == sizeof(espnowOutgoing)) + { + espnowOutgoingSpot = 0; // Wrap + + if (espnowState == ESPNOW_PAIRED) + esp_now_send(0, (uint8_t *)&espnowOutgoing, sizeof(espnowOutgoing)); // Send packet to all peers + else // if (espnowState == ESPNOW_BROADCASTING) + { + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + esp_now_send(broadcastMac, (uint8_t *)&espnowOutgoing, + sizeof(espnowOutgoing)); // Send packet via broadcast + } + + delay(10); // We need a small delay between sending multiple packets + + espnowBytesSent += sizeof(espnowOutgoing); + + espnowOutgoingRTCM = true; + } +} + +// A blocking function that is used to pair two devices +// either through the serial menu or AP config +void espnowStaticPairing() +{ + systemPrintln("Begin ESP NOW Pairing"); + + // Start ESP-Now if needed, put ESP-Now into broadcast state + espnowBeginPairing(); + + // Begin sending our MAC every 250ms until a remote device sends us there info + randomSeed(millis()); + + systemPrintln("Begin pairing. Place other unit in pairing mode. Press any key to exit."); + clearBuffer(); + + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + bool exitPair = false; + while (exitPair == false) + { + if (systemAvailable()) + { + systemPrintln("User pressed button. Pairing canceled."); + break; + } + + int timeout = 1000 + random(0, 100); // Delay 1000 to 1100ms + for (int x = 0; x < timeout; x++) + { + delay(1); + + if (espnowIsPaired() == true) // Check if we've received a pairing message + { + systemPrintln("Pairing compete"); + exitPair = true; + break; + } + } + + espnowSendPairMessage(broadcastMac); // Send unit's MAC address over broadcast, no ack, no encryption + + systemPrintln("Scanning for other radio..."); + } +} + +// Returns the current channel being used by WiFi +uint8_t espnowGetChannel() +{ + if (espnowState == ESPNOW_OFF) + return 0; + + bool originalPromiscuousMode = false; + esp_err_t response = esp_wifi_get_promiscuous(&originalPromiscuousMode); + if (response != ESP_OK) + systemPrintf("getPromiscuous failed: %s\r\n", esp_err_to_name(response)); + + // We must be in promiscuous mode to get the channel number + if (originalPromiscuousMode == false) + esp_wifi_set_promiscuous(true); + + uint8_t primaryChannelNumber = 0; + wifi_second_chan_t secondaryChannelNumber; + + response = esp_wifi_get_channel(&primaryChannelNumber, &secondaryChannelNumber); + if (response != ESP_OK) + systemPrintf("getChannel failed: %s\r\n", esp_err_to_name(response)); + + // Return to the original mode + if (originalPromiscuousMode == false) + esp_wifi_set_promiscuous(false); + + return (primaryChannelNumber); +} + +// Returns the current channel being used by WiFi +bool espnowSetChannel(uint8_t channelNumber) +{ + if (wifiIsConnected() == true) + { + systemPrintln("ESP-NOW channel can't be modified while WiFi is connected."); + return (false); + } + + bool originalPromiscuousMode = false; + esp_err_t response = esp_wifi_get_promiscuous(&originalPromiscuousMode); + if (response != ESP_OK) + systemPrintf("getPromiscuous failed: %s\r\n", esp_err_to_name(response)); + + // We must be in promiscuous mode to set the channel number + if (originalPromiscuousMode == false) + esp_wifi_set_promiscuous(true); + + bool setSuccess = false; + response = esp_wifi_set_channel(channelNumber, WIFI_SECOND_CHAN_NONE); + if (response != ESP_OK) + systemPrintf("setChannel to %d failed: %s\r\n", channelNumber, esp_err_to_name(response)); + else + setSuccess = true; + + // Return to the original mode + if (originalPromiscuousMode == false) + esp_wifi_set_promiscuous(false); + + return (setSuccess); +} + +#endif // COMPILE_ESPNOW diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 3fadb1c4f..27e911383 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -786,11 +786,13 @@ void networkMulticastDNSSwitch(NetIndex_t startIndex) //---------------------------------------- // Start multicast DNS //---------------------------------------- -void networkMulticastDNSStart(NetIndex_t index) +bool networkMulticastDNSStart(NetIndex_t index) { NetMask_t bitMask; + bool started; // Start mDNS if it is enabled and not running on this network + started = false; bitMask = 1 << index; if (settings.mdnsEnable && (!(networkMdnsRunning & bitMask)) && (mDNSUse & bitMask)) { @@ -801,11 +803,13 @@ void networkMulticastDNSStart(NetIndex_t index) { MDNS.addService("http", "tcp", settings.httpPort); // Add service to MDNS networkMdnsRunning |= bitMask; + started = true; if (settings.debugNetworkLayer) systemPrintf("mDNS started as %s.local\r\n", settings.mdnsHostName); } } + return started; } //---------------------------------------- diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 3c0fa916f..1ab19d6c9 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -303,6 +303,9 @@ char logFileName[sizeof("SFE_Reference_Station_230101_120101.ubx_plusExtraSpace" #include "esp_ota_ops.h" //Needed for partition counting and updateFromSD #ifdef COMPILE_WIFI +int packetRSSI; +RTK_WIFI wifi(false); + #define WIFI_STOP() \ { \ if (settings.debugWifiState) \ @@ -606,7 +609,6 @@ uint8_t espnowOutgoingSpot; // ESP Now has a max of 250 characters uint16_t espnowBytesSent; // May be more than 255 uint8_t receivedMAC[6]; // Holds the broadcast MAC during pairing -int packetRSSI; unsigned long lastEspnowRssiUpdate; #endif // COMPILE_ESPNOW diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 658c458f1..c65860e1d 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -1,751 +1,2546 @@ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - WiFi Status Values: - WL_CONNECTED: assigned when connected to a WiFi network - WL_CONNECTION_LOST: assigned when the connection is lost - WL_CONNECT_FAILED: assigned when the connection fails for all the attempts - WL_DISCONNECTED: assigned when disconnected from a network - WL_IDLE_STATUS: it is a temporary status assigned when WiFi.begin() is called and - remains active until the number of attempts expires (resulting in - WL_CONNECT_FAILED) or a connection is established (resulting in - WL_CONNECTED) - WL_NO_SHIELD: assigned when no WiFi shield is present - WL_NO_SSID_AVAIL: assigned when no SSID are available - WL_SCAN_COMPLETED: assigned when the scan networks is completed - =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -//---------------------------------------- -// Globals -//---------------------------------------- - -int wifiFailedConnectionAttempts = 0; // Count the number of connection attempts between restarts +/********************************************************************** + Wifi.ino -bool restartWiFi = false; // Restart WiFi if user changes anything + WiFi layer, supports use by ESP-NOW, soft AP and WiFi station +**********************************************************************/ #ifdef COMPILE_WIFI -WiFiMulti *wifiMulti; - -//---------------------------------------- +//**************************************** // Constants -//---------------------------------------- +//**************************************** -#define WIFI_MAX_TIMEOUT (15 * 60 * 1000) -#define WIFI_MIN_TIMEOUT (15 * 1000) +#define WIFI_RECONNECTION_DELAY 1000 +#define WIFI_DEFAULT_CHANNEL 1 +#define WIFI_IP_ADDRESS_TIMEOUT_MSEC (15 * 1000) -//---------------------------------------- -// Locals -//---------------------------------------- +static const char * wifiAuthorizationName[] = +{ + "Open", + "WEP", + "WPA_PSK", + "WPA2_PSK", + "WPA_WPA2_PSK", + "WPA2_Enterprise", + "WPA3_PSK", + "WPA2_WPA3_PSK", + "WAPI_PSK", + "OWE", + "WPA3_ENT_192", +}; +static const int wifiAuthorizationNameEntries = + sizeof(wifiAuthorizationName) / sizeof(wifiAuthorizationName[0]); + +const char * arduinoEventName[] = +{ + "ARDUINO_EVENT_NONE", + "ARDUINO_EVENT_ETH_START", + "ARDUINO_EVENT_ETH_STOP", + "ARDUINO_EVENT_ETH_CONNECTED", + "ARDUINO_EVENT_ETH_DISCONNECTED", + "ARDUINO_EVENT_ETH_GOT_IP", + "ARDUINO_EVENT_ETH_LOST_IP", + "ARDUINO_EVENT_ETH_GOT_IP6", + "ARDUINO_EVENT_WIFI_OFF", + "ARDUINO_EVENT_WIFI_READY", + "ARDUINO_EVENT_WIFI_SCAN_DONE", + "ARDUINO_EVENT_WIFI_STA_START", + "ARDUINO_EVENT_WIFI_STA_STOP", + "ARDUINO_EVENT_WIFI_STA_CONNECTED", + "ARDUINO_EVENT_WIFI_STA_DISCONNECTED", + "ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE", + "ARDUINO_EVENT_WIFI_STA_GOT_IP", + "ARDUINO_EVENT_WIFI_STA_GOT_IP6", + "ARDUINO_EVENT_WIFI_STA_LOST_IP", + "ARDUINO_EVENT_WIFI_AP_START", + "ARDUINO_EVENT_WIFI_AP_STOP", + "ARDUINO_EVENT_WIFI_AP_STACONNECTED", + "ARDUINO_EVENT_WIFI_AP_STADISCONNECTED", + "ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED", + "ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED", + "ARDUINO_EVENT_WIFI_AP_GOT_IP6", + "ARDUINO_EVENT_WIFI_FTM_REPORT", + "ARDUINO_EVENT_WPS_ER_SUCCESS", + "ARDUINO_EVENT_WPS_ER_FAILED", + "ARDUINO_EVENT_WPS_ER_TIMEOUT", + "ARDUINO_EVENT_WPS_ER_PIN", + "ARDUINO_EVENT_WPS_ER_PBC_OVERLAP", + "ARDUINO_EVENT_SC_SCAN_DONE", + "ARDUINO_EVENT_SC_FOUND_CHANNEL", + "ARDUINO_EVENT_SC_GOT_SSID_PSWD", + "ARDUINO_EVENT_SC_SEND_ACK_DONE", + "ARDUINO_EVENT_PROV_INIT", + "ARDUINO_EVENT_PROV_DEINIT", + "ARDUINO_EVENT_PROV_START", + "ARDUINO_EVENT_PROV_END", + "ARDUINO_EVENT_PROV_CRED_RECV", + "ARDUINO_EVENT_PROV_CRED_FAIL", + "ARDUINO_EVENT_PROV_CRED_SUCCESS", + "ARDUINO_EVENT_PPP_START", + "ARDUINO_EVENT_PPP_STOP", + "ARDUINO_EVENT_PPP_CONNECTED", + "ARDUINO_EVENT_PPP_DISCONNECTED", + "ARDUINO_EVENT_PPP_GOT_IP", + "ARDUINO_EVENT_PPP_LOST_IP", + "ARDUINO_EVENT_PPP_GOT_IP6", +}; +const int arduinoEventNameEntries = sizeof(arduinoEventName) / sizeof(arduinoEventName[0]); + +//---------------------------------------------------------------------- +// ESP-NOW bringup from example 4_9_ESP_NOW +// 1. Set station mode +// 2. Create nowSerial as new ESP_NOW_Serial_Class +// 3. nowSerial.begin +// ESP-NOW bringup from RTK +// 1. Get WiFi mode +// 2. Set WiFi station mode if necessary +// 3. Get WiFi station protocols +// 4. Set WIFI_PROTOCOL_LR protocol +// 5. Call esp_now_init +// 6. Call esp_wifi_set_promiscuous(true) +// 7. Set promiscuous receive callback [esp_wifi_set_promiscuous_rx_cb(promiscuous_rx_cb)] +// to get RSSI of action frames +// 8. Assign a channel if necessary, call espnowSetChannel +// 9. Set receive callback [esp_now_register_recv_cb(espnowOnDataReceived)] +// 10. Add peers from settings +// A. If no peers exist +// i. Determine if broadcast peer exists, call esp_now_is_peer_exist +// ii. Add broadcast peer if necessary, call espnowAddPeer +// iii. Set ESP-NOW state, call espnowSetState(ESPNOW_BROADCASTING) +// B. If peers exist, +// i. Set ESP-NOW state, call espnowSetState(ESPNOW_PAIRED) +// ii. Loop through peers listed in settings, for each +// a. Determine if peer exists, call esp_now_is_peer_exist +// b. Add peer if necessary, call espnowAddPeer +// +// In espnowOnDataReceived +// 11. Save ESP-NOW RSSI +// 12. Set lastEspnowRssiUpdate = millis() +// 13. If in ESPNOW_PAIRING state +// A. Validate message CRC +// B. If valid CRC +// i. Save peer MAC address +// ii. espnowSetState(ESPNOW_MAC_RECEIVED) +// 14. Else if ESPNOW_MAC_RECEIVED state +// A. If ESP-NOW is corrections source, correctionLastSeen(CORR_ESPNOW) +// i. gnss->pushRawData +// 15. Set espnowIncomingRTCM +// +// ESP-NOW shutdown from RTK +// 1. esp_wifi_set_promiscuous(false) +// 2. esp_wifi_set_promiscuous_rx_cb(nullptr) +// 3. esp_now_unregister_recv_cb() +// 4. Remove all peers by calling espnowRemovePeer +// 5. Get WiFi mode +// 6. Set WiFi station mode if necessary +// 7. esp_wifi_get_protocol +// 8. Turn off long range protocol if necessary, call esp_wifi_set_protocol +// 9. Turn off ESP-NOW. call esp_now_deinit +// 10. Set ESP-NOW state, call espnowSetState(ESPNOW_OFF) +// 11. Restart WiFi if necessary +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Soft AP startup from example 4_11 +// 1. Get mode +// 2. Start WiFi event handler +// 3. Set SSID and password, call softApCreate +// 4. Set IP addresses, call softApConfiguration +// 5. esp_wifi_get_protocol +// 6. Set AP protocols, call esp_wifi_set_protocol(b, g, n) +// 7. Set AP mode +// 8. Set host name +// 9. Set mDNS +// +// Soft AP shutdown from example 4_11 +// 1. Stop mDNS +// 2. Get mode +// 3. Disable AP mode +// 4. Stop WiFi event handler +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// WiFi station startup from example 4_8 +// 1. Get mode +// 2. Start WiFi event handler +// 3. Set WiFi station mode +// 4. Start Wifi scan +// +// In WiFi event handler for scan complete +// 5. Select AP and channel +// 6. Get mode +// 7. Start WiFi station mode +// 8. Set host name +// 9. Disable auto reconnect +// 10. Connect to AP +// +// In WiFi event handler for station connected +// 11. Set stationConnected +// +// In WiFi event handler for GOT_IP or GOT_IP6 +// 12. Set stationHasIp +// 13. Save IP address +// 14. Save IP address type +// 15. Display IP address +// 16. Start mDNS +// +// In WiFi event handler for LOST_IP +// 1. Clear stationHasIp +// 2. Display IP address +// +// In WiFi event handler for all other WiFi station events except +// GOT_IP, GOT_IP6 or LOST_IP +// 1. Clear WiFi channel +// 2. Clear stationConnected +// 3. Clear stationHasIp +// 4. For STOP +// A. Clear timer +// Else for DISCONNECTED +// A. Start timer (set to non-zero value) +// +// In wifiUpdate +// 5. When timer fires +// A. Start scan +// +// WiFi station shutdown from example 4-8 +// 1. Get mode +// 2. Exit if WiFi station is not running +// 3. Stop mDNS +// 4. Disconnect from remote AP +// 5. Stop WiFi station mode +// 6. Stop the event handler +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Combining Soft AP shutdown with WiFi shutdown +// 1. Stop mDNS +// 2. Get mode +// 3. Disconnect from remote AP +// 4. Stop necessary modes (AP and station) +// 5. Stop the event handler +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// Combining soft AP starting with WiFi station starting, do the following +// synchronously: +// 1. Get mode +// 2. Start WiFi event handler +// 3. Set AP SSID and password, call softApCreate +// 4. Set AP IP addresses, call softApConfiguration +// 5. Get the AP protocols, call esp_wifi_get_protocol +// 6. Set AP protocols, call esp_wifi_set_protocol(b, g, n) +// 7. Set the necessary WiFi modes +// 8. Set AP host name +// 9. If starting AP +// Start mDNS +// 10. If starting WiFi station +// Start Wifi scan +// +// The rest of the startup is handled asynchronously by the WiFi +// event handler: +// +// For SCAN_COMPLETE +// 11. Select AP and channel +// 12. Set station host name +// 13. Disable auto reconnect +// 14. Connect to AP +// +// For STA_CONNECTED +// 15. Set stationConnected +// +// For GOT_IP or GOT_IP6 +// 16. Set stationHasIp +// 17. Save IP address +// 18. Save IP address type +// 19. Display IP address +// 20. If AP mode not running +// Start mDNS +// +// For LOST_IP +// 1. Clear stationHasIp +// 2. Display IP address +// +// In WiFi event handler for all other WiFi station events except +// STA_GOT_IP, STA_GOT_IP6 or STA_LOST_IP +// 1. If ESP-NOW and soft AP not running +// Clear WiFi channel +// 2. Clear stationConnected +// 3. Clear stationHasIp +// 4. For STA_STOP +// A. Clear timer +// Else for STA_DISCONNECTED +// A. Start timer (set to non-zero value) +// +// In wifiUpdate +// 5. When timer fires +// A. Start scan +//---------------------------------------------------------------------- + +//**************************************** +// Constants +//**************************************** + +// Radio operations +#define WIFI_AP_SET_MODE 1 +#define WIFI_EN_SET_MODE 2 +#define WIFI_STA_SET_MODE 4 +#define WIFI_AP_SET_PROTOCOLS 8 +#define WIFI_EN_SET_PROTOCOLS 0x00000010 +#define WIFI_STA_SET_PROTOCOLS 0x00000020 +#define WIFI_STA_START_SCAN 0x00000040 +#define WIFI_STA_SELECT_REMOTE_AP 0x00000080 +#define WIFI_AP_SELECT_CHANNEL 0x00000100 +#define WIFI_EN_SELECT_CHANNEL 0x00000200 +#define WIFI_STA_SELECT_CHANNEL 0x00000400 + +// Soft AP +#define WIFI_AP_SET_SSID_PASSWORD 0x00000800 +#define WIFI_AP_SET_IP_ADDR 0x00001000 +#define WIFI_AP_SET_HOST_NAME 0x00002000 +#define WIFI_AP_START_MDNS 0x00004000 +#define WIFI_AP_START_DNS_SERVER 0x00008000 +#define WIFI_AP_ONLINE 0x00010000 + +// WiFi station +#define WIFI_STA_SET_HOST_NAME 0x00020000 +#define WIFI_STA_DISABLE_AUTO_RECONNECT 0x00040000 +#define WIFI_STA_CONNECT_TO_REMOTE_AP 0x00080000 +#define WIFI_STA_START_MDNS 0x00100000 +#define WIFI_STA_ONLINE 0x00200000 + +// ESP-NOW +#define WIFI_EN_SET_CHANNEL 0x00400000 +#define WIFI_EN_SET_PROMISCUOUS_MODE 0x00800000 +#define WIFI_EN_PROMISCUOUS_RX_CALLBACK 0x01000000 +#define WIFI_EN_START_ESP_NOW 0x02000000 +#define WIFI_EN_ESP_NOW_ONLINE 0x04000000 + +// WIFI_MAX_START must be the last value in the define list +#define WIFI_MAX_START 0x08000000 + +const char * const wifiStartNames[] = +{ + "WIFI_AP_SET_MODE", + "WIFI_EN_SET_MODE", + "WIFI_STA_SET_MODE", + "WIFI_AP_SET_PROTOCOLS", + "WIFI_EN_SET_PROTOCOLS", + "WIFI_STA_SET_PROTOCOLS", + "WIFI_STA_START_SCAN", + "WIFI_STA_SELECT_REMOTE_AP", + "WIFI_AP_SELECT_CHANNEL", + "WIFI_EN_SELECT_CHANNEL", + "WIFI_STA_SELECT_CHANNEL", + + "WIFI_AP_SET_SSID_PASSWORD", + "WIFI_AP_SET_IP_ADDR", + "WIFI_AP_SET_HOST_NAME", + "WIFI_AP_START_MDNS", + "WIFI_AP_ONLINE", + + "WIFI_STA_SET_HOST_NAME", + "WIFI_STA_DISABLE_AUTO_RECONNECT", + "WIFI_STA_CONNECT_TO_REMOTE_AP", + "WIFI_STA_START_MDNS", + "WIFI_STA_ONLINE", + + "WIFI_EN_SET_CHANNEL", + "WIFI_EN_SET_PROMISCUOUS_MODE", + "WIFI_EN_PROMISCUOUS_RX_CALLBACK", + "WIFI_EN_START_ESP_NOW", + "WIFI_EN_ESP_NOW_ONLINE", +}; +const int wifiStartNamesEntries = sizeof(wifiStartNames) / sizeof(wifiStartNames[0]); + +#define WIFI_START_ESP_NOW (WIFI_EN_SET_MODE \ + | WIFI_EN_SET_PROTOCOLS \ + | WIFI_EN_SELECT_CHANNEL \ + | WIFI_EN_SET_CHANNEL \ + | WIFI_EN_PROMISCUOUS_RX_CALLBACK \ + | WIFI_EN_SET_PROMISCUOUS_MODE \ + | WIFI_EN_START_ESP_NOW \ + | WIFI_EN_ESP_NOW_ONLINE) + +#define WIFI_START_SOFT_AP (WIFI_AP_SET_MODE \ + | WIFI_AP_SET_PROTOCOLS \ + | WIFI_AP_SELECT_CHANNEL \ + | WIFI_AP_SET_SSID_PASSWORD \ + | WIFI_AP_SET_IP_ADDR \ + | WIFI_AP_SET_HOST_NAME \ + | WIFI_AP_START_MDNS \ + | WIFI_AP_START_DNS_SERVER \ + | WIFI_AP_ONLINE) + +#define WIFI_START_STATION (WIFI_STA_SET_MODE \ + | WIFI_STA_SET_PROTOCOLS \ + | WIFI_STA_START_SCAN \ + | WIFI_STA_SELECT_CHANNEL \ + | WIFI_STA_SELECT_REMOTE_AP \ + | WIFI_STA_SET_HOST_NAME \ + | WIFI_STA_DISABLE_AUTO_RECONNECT \ + | WIFI_STA_CONNECT_TO_REMOTE_AP \ + | WIFI_STA_START_MDNS \ + | WIFI_STA_ONLINE) + +#define WIFI_STA_RECONNECT (WIFI_STA_START_SCAN \ + | WIFI_STA_SELECT_CHANNEL \ + | WIFI_STA_SELECT_REMOTE_AP \ + | WIFI_STA_SET_HOST_NAME \ + | WIFI_STA_DISABLE_AUTO_RECONNECT \ + | WIFI_STA_CONNECT_TO_REMOTE_AP \ + | WIFI_STA_START_MDNS \ + | WIFI_STA_ONLINE) + +#define WIFI_SELECT_CHANNEL (WIFI_AP_SELECT_CHANNEL \ + | WIFI_EN_SELECT_CHANNEL \ + | WIFI_STA_SELECT_CHANNEL) + +#define WIFI_STA_NO_REMOTE_AP (WIFI_STA_SELECT_CHANNEL \ + | WIFI_STA_SET_HOST_NAME \ + | WIFI_STA_DISABLE_AUTO_RECONNECT \ + | WIFI_STA_CONNECT_TO_REMOTE_AP \ + | WIFI_STA_START_MDNS \ + | WIFI_STA_ONLINE) + +#define WIFI_STA_FAILED_SCAN (WIFI_STA_START_SCAN \ + | WIFI_STA_SELECT_REMOTE_AP \ + | WIFI_STA_NO_REMOTE_AP) + +const char * wifiSoftApSsid = "RTK Config"; +const char * wifiSoftApPassword = nullptr; + +//**************************************** +// Globals +//**************************************** -// Start timeout -static uint32_t wifiStartTimeout; -static uint32_t wifiStartLastTry; // The last time WiFi start was attempted +bool wifiRestartRequested = false; // Restart WiFi if user changes anything -// WiFi Timer usage: -// * Measure interval to display IP address -static unsigned long wifiDisplayTimer; +//**************************************** +// Locals +//**************************************** // DNS server for Captive Portal static DNSServer dnsServer; -static bool wifiStationRunning; -static bool wifiApRunning; - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// WiFi Routines -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - -//---------------------------------------- -// Set WiFi credentials -// Enable TCP connections -//---------------------------------------- -void menuWiFi() +//********************************************************************* +// Callback for all WiFi RX Packets +// Get RSSI of all incoming management packets: https://esp32.com/viewtopic.php?t=13889 +void wifiPromiscuousRxHandler(void *buf, wifi_promiscuous_pkt_type_t type) { - while (1) - { - networkDisplayInterface(NETWORK_WIFI); - - systemPrintln(); - systemPrintln("Menu: WiFi Networks"); - - for (int x = 0; x < MAX_WIFI_NETWORKS; x++) - { - systemPrintf("%d) SSID %d: %s\r\n", (x * 2) + 1, x + 1, settings.wifiNetworks[x].ssid); - systemPrintf("%d) Password %d: %s\r\n", (x * 2) + 2, x + 1, settings.wifiNetworks[x].password); - } + const wifi_promiscuous_pkt_t *ppkt; // Defined in esp_wifi_types_native.h - systemPrint("a) Configure device via WiFi Access Point or connect to WiFi: "); - systemPrintf("%s\r\n", settings.wifiConfigOverAP ? "AP" : "WiFi"); + // All espnow traffic uses action frames which are a subtype of the + // mgmnt frames so filter out everything else. + if (type != WIFI_PKT_MGMT) + return; - systemPrint("c) Captive Portal: "); - systemPrintf("%s\r\n", settings.enableCaptivePortal ? "Enabled" : "Disabled"); + ppkt = (wifi_promiscuous_pkt_t *)buf; + packetRSSI = ppkt->rx_ctrl.rssi; +} - systemPrintln("x) Exit"); +//********************************************************************* +// Constructor +// Inputs: +// verbose: Set to true to display additional WiFi debug data +RTK_WIFI::RTK_WIFI(bool verbose) + : _apChannel{0}, _apCount{0}, _apDnsAddress{IPAddress((uint32_t)0)}, + _apFirstDhcpAddress{IPAddress("192.168.4.32")}, + _apGatewayAddress{(uint32_t)0}, + _apIpAddress{IPAddress("192.168.4.1")}, + _apMacAddress{0, 0, 0, 0, 0, 0}, + _apSubnetMask{IPAddress("255.255.255.0")}, _channel{0}, + _espNowChannel{0}, _espNowRunning{false}, + _hostName{nullptr}, _scanRunning{false}, _softApRunning{false}, + _staIpAddress{IPAddress((uint32_t)0)}, _staIpType{0}, + _staMacAddress{0, 0, 0, 0, 0, 0}, + _staRemoteApSsid{nullptr}, _staRemoteApPassword{nullptr}, + _started{false}, _stationChannel{0}, + _timer{0}, _verbose{verbose} +{ +} - byte incoming = getUserInputCharacterNumber(); +//********************************************************************* +// Attempts a connection to all provided SSIDs +bool RTK_WIFI::connect(unsigned long timeout, + bool startAP) +{ + bool started; - if (incoming >= 1 && incoming <= MAX_WIFI_NETWORKS * 2) - { - int arraySlot = ((incoming - 1) / 2); // Adjust incoming to array starting at 0 + // Display warning + log_w("WiFi: Not using timeout parameter for connect!\r\n"); - if (incoming % 2 == 1) - { - systemPrintf("Enter SSID network %d: ", arraySlot + 1); - getUserInputString(settings.wifiNetworks[arraySlot].ssid, - sizeof(settings.wifiNetworks[arraySlot].ssid)); - restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi - } - else - { - systemPrintf("Enter Password for %s: ", settings.wifiNetworks[arraySlot].ssid); - getUserInputString(settings.wifiNetworks[arraySlot].password, - sizeof(settings.wifiNetworks[arraySlot].password)); - restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi - } - } - else if (incoming == 'a') - { - settings.wifiConfigOverAP ^= 1; - restartWiFi = true; - } - else if (incoming == 'c') - { - settings.enableCaptivePortal ^= 1; - } - else if (incoming == 'x') - break; - else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_EMPTY) - break; - else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_TIMEOUT) - break; - else - printUnknown(incoming); + // Enable WiFi station if necessary + if (_stationRunning == false) + { + displayWiFiConnect(); + started = enable(_espNowRunning, _softApRunning, true); } + else if (startAP && !_softApRunning) + started = enable(_espNowRunning, true, _stationRunning); - // Erase passwords from empty SSID entries - for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + // Determine the WiFi station status + if (started) { - if (strlen(settings.wifiNetworks[x].ssid) == 0) - strcpy(settings.wifiNetworks[x].password, ""); + wl_status_t wifiStatus = WiFi.STA.status(); + started = (wifiStatus == WL_CONNECTED); + if (wifiStatus == WL_DISCONNECTED) + systemPrint("No friendly WiFi networks detected.\r\n"); + else if (wifiStatus != WL_CONNECTED) + systemPrintf("WiFi failed to connect: error #%d - %s\r\n", + wifiStatus, wifiPrintState(wifiStatus)); } - - clearBuffer(); // Empty buffer of any newline chars + return started; } -//---------------------------------------- -// Starts WiFi in STA, AP, or STA_AP mode depending on bools -// Returns true if STA connects, or if AP is started -//---------------------------------------- -bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) +//********************************************************************* +// Display components begin started or stopped +// Inputs: +// text: Text describing the component list +// components: A bit mask of the components +void RTK_WIFI::displayComponents(const char * text, WIFI_ACTION_t components) { - // Is a change needed? - if (startWiFiStation && startWiFiAP && WiFi.getMode() == WIFI_AP_STA && WiFi.status() == WL_CONNECTED) - return (true); // There is nothing needing to be changed - - if (startWiFiStation && WiFi.getMode() == WIFI_STA && WiFi.status() == WL_CONNECTED) - return (true); // There is nothing needing to be changed + WIFI_ACTION_t mask; - if (startWiFiAP && WiFi.getMode() == WIFI_AP) - return (true); // There is nothing needing to be changed - - wifiStationRunning = false; // Mark it as offline while we mess about - wifiApRunning = false; // Mark it as offline while we mess about - - wifi_mode_t wifiMode = WIFI_OFF; - wifi_interface_t wifiInterface = WIFI_IF_STA; - - // Establish what WiFi mode we need to be in - if (startWiFiStation && startWiFiAP) - { - systemPrintln("Starting WiFi AP+Station"); - wifiMode = WIFI_AP_STA; - wifiInterface = WIFI_IF_AP; // There is no WIFI_IF_AP_STA - } - else if (startWiFiStation) - { - systemPrintln("Starting WiFi Station"); - wifiMode = WIFI_STA; - wifiInterface = WIFI_IF_STA; - } - else if (startWiFiAP) + systemPrintf("%s: 0x%08x\r\n", text, components); + for (int index = wifiStartNamesEntries - 1; index >= 0; index--) { - systemPrintln("Starting WiFi AP"); - wifiMode = WIFI_AP; - wifiInterface = WIFI_IF_AP; + mask = 1 << index; + if (components & mask) + systemPrintf(" 0x%08lx: %s\r\n", mask, wifiStartNames[index]); } +} - displayWiFiConnect(); +//********************************************************************* +// Enable or disable the WiFi modes +// Inputs: +// enableESPNow: Enable ESP-NOW mode +// enableSoftAP: Enable soft AP mode +// enableStataion: Enable station mode +// Outputs: +// Returns true if the modes were successfully configured +bool RTK_WIFI::enable(bool enableESPNow, bool enableSoftAP, bool enableStation) +{ + int authIndex; + WIFI_ACTION_t starting; + WIFI_ACTION_t stopping; + + // Determine the next actions + starting = 0; + stopping = 0; - if (WiFi.mode(wifiMode) == false) // Start WiFi in the appropriate mode + // Display the parameters + if (settings.debugWifiState && _verbose) { - systemPrintln("WiFi failed to set mode"); - return (false); + systemPrintf("enableESPNow: %s\r\n", enableESPNow ? "true" : "false"); + systemPrintf("enableSoftAP: %s\r\n", enableSoftAP ? "true" : "false"); + systemPrintf("enableStation: %s\r\n", enableStation ? "true" : "false"); } - // Verify that the necessary protocols are set - uint8_t protocols = 0; - esp_err_t response = esp_wifi_get_protocol(wifiInterface, &protocols); - if (response != ESP_OK) - systemPrintf("Failed to get protocols: %s\r\n", esp_err_to_name(response)); - - // If ESP-NOW is running, blend in ESP-NOW protocol. - if (espnowState > ESPNOW_OFF) + // Update the ESP-NOW state + if (enableESPNow) { - if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR)) - { - esp_err_t response = - esp_wifi_set_protocol(wifiInterface, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | - WIFI_PROTOCOL_LR); // Enable WiFi + ESP-Now. - if (response != ESP_OK) - systemPrintf("Error setting WiFi + ESP-NOW protocols: %s\r\n", esp_err_to_name(response)); - } + starting |= WIFI_START_ESP_NOW; + _espNowRunning = true; } else { - // Make sure default WiFi protocols are in place - if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N)) - { - esp_err_t response = esp_wifi_set_protocol(wifiInterface, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | - WIFI_PROTOCOL_11N); // Enable WiFi. - if (response != ESP_OK) - systemPrintf("Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); - } + stopping |= WIFI_START_ESP_NOW; + _espNowRunning = false; } - // Start AP with fixed IP - if (wifiMode == WIFI_AP || wifiMode == WIFI_AP_STA) + // Update the soft AP state + if (enableSoftAP) { - IPAddress local_IP(192, 168, 4, 1); - IPAddress gateway(192, 168, 4, 1); - IPAddress subnet(255, 255, 255, 0); - - WiFi.softAPConfig(local_IP, gateway, subnet); - - // Determine the AP name - // If in web config mode then 'RTK Config' - // otherwise 'RTK Caster' - - char softApSsid[strlen("RTK Config")]; // Must be short enough to fit OLED Width - - if (inWebConfigMode()) - strncpy(softApSsid, "RTK Config", sizeof(softApSsid)); - // snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Config"); // TODO use - // settings.webconfigApName - else - strncpy(softApSsid, "RTK Caster", sizeof(softApSsid)); - // snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Caster"); - - if (WiFi.softAP(softApSsid) == false) - { - systemPrintln("WiFi AP failed to start"); - return (false); - } - systemPrintf("WiFi AP '%s' started with IP: ", softApSsid); - systemPrintln(WiFi.softAPIP()); - - // Start DNS Server - if (dnsServer.start(53, "*", WiFi.softAPIP()) == false) + // Verify that the SSID is set + if (wifiSoftApSsid && strlen(wifiSoftApSsid) && wifiSoftApPassword) { - systemPrintln("WiFi DNS Server failed to start"); - return (false); + starting |= WIFI_START_SOFT_AP; + _softApRunning = true; } else - { - if (settings.debugWifiState == true) - systemPrintln("DNS Server started"); - } - - wifiApRunning = true; - - // If we're only here to start the AP, then we're done - if (wifiMode == WIFI_AP) - return true; + systemPrintf("ERROR: AP SSID or password is missing\r\n"); } - - systemPrintln("Connecting to WiFi... "); - - if (wifiMulti == nullptr) - wifiMulti = new WiFiMulti; - - // Load SSIDs - wifiMulti->APlistClean(); - for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + else { - if (strlen(settings.wifiNetworks[x].ssid) > 0) - wifiMulti->addAP((const char *)&settings.wifiNetworks[x].ssid, - (const char *)&settings.wifiNetworks[x].password); + stopping |= WIFI_START_SOFT_AP; + _softApRunning = false; } - int wifiStatus = wifiMulti->run(timeout); - if (wifiStatus == WL_CONNECTED) + // Update the station state + if (enableStation) { - wifiResetTimeout(); // If we successfully connected then reset the throttling timeout - wifiStationRunning = true; - return true; + // Verify that at least one WiFi access point is in the list + if (MAX_WIFI_NETWORKS == 0) + systemPrintf("ERROR: No entries in wiFiSsidPassword\r\n"); + else + { + // Verify that at least one SSID is set + for (authIndex = 0; authIndex < MAX_WIFI_NETWORKS; authIndex++) + if (strlen(settings.wifiNetworks[authIndex].ssid)) + { + break; + } + if (authIndex >= MAX_WIFI_NETWORKS) + systemPrintf("ERROR: No valid SSID in settings\r\n"); + else + { + // Start the WiFi station + starting |= WIFI_START_STATION; + _stationRunning = true; + } + } } - if (wifiStatus == WL_DISCONNECTED) - systemPrint("No friendly WiFi networks detected.\r\n"); else { - systemPrintf("WiFi failed to connect: error #%d - %s\r\n", wifiStatus, wifiPrintState((wl_status_t)wifiStatus)); + // Stop the WiFi station + stopping |= WIFI_START_STATION; + _stationRunning = false; } - wifiStationRunning = false; - return false; + + // Stop and start the WiFi components + return stopStart(stopping, starting); } -//---------------------------------------- -// Display the WiFi state -//---------------------------------------- -void wifiDisplayState() +//********************************************************************* +// Get the ESP-NOW status +// Outputs: +// Returns true when ESP-NOW is online and ready for use +bool RTK_WIFI::espNowOnline() { - systemPrintf("WiFi: %s\r\n", networkInterfaceHasInternet(NETWORK_WIFI) ? "Online" : "Offline"); - systemPrintf(" MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\r\n", wifiMACAddress[0], wifiMACAddress[1], - wifiMACAddress[2], wifiMACAddress[3], wifiMACAddress[4], wifiMACAddress[5]); - if (networkInterfaceHasInternet(NETWORK_WIFI)) - { - // Get the DNS addresses - IPAddress dns1 = WiFi.STA.dnsIP(0); - IPAddress dns2 = WiFi.STA.dnsIP(1); - IPAddress dns3 = WiFi.STA.dnsIP(2); - - // Get the WiFi status - wl_status_t wifiStatus = WiFi.status(); - - const char *wifiStatusString = wifiPrintState(wifiStatus); - - // Display the WiFi state - systemPrintf(" SSID: %s\r\n", WiFi.STA.SSID()); - systemPrintf(" IP Address: %s\r\n", WiFi.STA.localIP().toString().c_str()); - systemPrintf(" Subnet Mask: %s\r\n", WiFi.STA.subnetMask().toString().c_str()); - systemPrintf(" Gateway Address: %s\r\n", WiFi.STA.gatewayIP().toString().c_str()); - if ((uint32_t)dns3) - systemPrintf(" DNS Address: %s, %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str(), - dns3.toString().c_str()); - else if ((uint32_t)dns3) - systemPrintf(" DNS Address: %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str()); - else - systemPrintf(" DNS Address: %s\r\n", dns1.toString().c_str()); - systemPrintf(" WiFi Strength: %d dBm\r\n", WiFi.RSSI()); - systemPrintf(" WiFi Status: %d\r\n", wifiStatusString); - } + return (_started & WIFI_EN_ESP_NOW_ONLINE) ? true : false; } -//---------------------------------------- -// Process the WiFi events -//---------------------------------------- -void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) +//********************************************************************* +// Get the ESP-NOW status +bool RTK_WIFI::espNowRunning() { - char ssid[sizeof(info.wifi_sta_connected.ssid) + 1]; - IPAddress ipAddress; + return _espNowRunning; +} - // If we are in AP or AP_STA, the network is immediately marked online - // Once AP is online, don't stop WiFi because STA has various events - if (WiFi.getMode() == WIFI_MODE_STA) - { - // Take the network offline if necessary - if (networkInterfaceHasInternet(NETWORK_WIFI) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP) && - (event != ARDUINO_EVENT_WIFI_STA_GOT_IP6)) - { - if (settings.debugWifiState) - systemPrintf("Stopping WiFi because of event # %d\r\n", event); +//********************************************************************* +// Handle the WiFi event +void RTK_WIFI::eventHandler(arduino_event_id_t event, arduino_event_info_t info) +{ + bool success; - networkStop(NETWORK_WIFI, settings.debugNetworkLayer); // Stop WiFi to allow it to restart - } - } + if (settings.debugWifiState) + systemPrintf("event: %d (%s)\r\n", event, arduinoEventName[event]); - // WiFi State Machine - // - // .--------+<----------+<-----------+<-------------+<----------+<----------+<------------. - // v | | | | | | | - // STOP --> READY --> STA_START --> SCAN_DONE --> CONNECTED --> GOT_IP --> LOST_IP --> DISCONNECTED - // ^ ^ | | - // | '-----------' | - // '-------------------------------------' - // // Handle the event switch (event) { - default: - systemPrintf("ERROR: Unknown WiFi event: %d\r\n", event); - break; - case ARDUINO_EVENT_WIFI_OFF: - systemPrintln("WiFi Off"); - break; + //------------------------------ + // Controller events + //------------------------------ + case ARDUINO_EVENT_WIFI_OFF: case ARDUINO_EVENT_WIFI_READY: - if (settings.debugWifiState) - systemPrintln("WiFi Ready"); - WiFi.setHostname(settings.mdnsHostName); break; + //---------------------------------------- + // Scan events + //---------------------------------------- + case ARDUINO_EVENT_WIFI_SCAN_DONE: - if (settings.debugWifiState) - systemPrintln("WiFi Scan Done"); - // wifi_event_sta_scan_done_t info.wifi_scan_done; + stationEventHandler(event, info); break; + //------------------------------ + // Station events + //------------------------------ case ARDUINO_EVENT_WIFI_STA_START: - if (settings.debugWifiState) - systemPrintln("WiFi STA Started"); - break; - - case ARDUINO_EVENT_WIFI_STA_STOP: - if (settings.debugWifiState) - systemPrintln("WiFi STA Stopped"); - break; - case ARDUINO_EVENT_WIFI_STA_CONNECTED: - memcpy(ssid, info.wifi_sta_connected.ssid, info.wifi_sta_connected.ssid_len); - ssid[info.wifi_sta_connected.ssid_len] = 0; - - ipAddress = WiFi.localIP(); - systemPrintf("WiFi STA connected to %s with IP address: ", ssid); - systemPrintln(ipAddress); - - WiFi.setHostname(settings.mdnsHostName); - break; - - case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: - memcpy(ssid, info.wifi_sta_disconnected.ssid, info.wifi_sta_disconnected.ssid_len); - ssid[info.wifi_sta_disconnected.ssid_len] = 0; - systemPrintf("WiFi STA disconnected from %s\r\n", ssid); - // wifi_event_sta_disconnected_t info.wifi_sta_disconnected; - break; - - case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: - systemPrintln("WiFi STA Auth Mode Changed"); - // wifi_event_sta_authmode_change_t info.wifi_sta_authmode_change; - break; - case ARDUINO_EVENT_WIFI_STA_GOT_IP: - if (settings.debugWifiState) - { - ipAddress = WiFi.localIP(); - systemPrint("WiFi STA Got IPv4: "); - systemPrintln(ipAddress); - } - networkMarkHasInternet(NETWORK_WIFI); - break; - case ARDUINO_EVENT_WIFI_STA_GOT_IP6: - if (settings.debugWifiState) - { - ipAddress = WiFi.localIP(); - systemPrint("WiFi STA Got IPv6: "); - systemPrintln(ipAddress); - } - networkMarkHasInternet(NETWORK_WIFI); + case ARDUINO_EVENT_WIFI_STA_LOST_IP: + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: + case ARDUINO_EVENT_WIFI_STA_STOP: + case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: + stationEventHandler(event, info); break; - case ARDUINO_EVENT_WIFI_STA_LOST_IP: - systemPrintln("WiFi STA Lost IP"); + //---------------------------------------- + // Soft AP events + //---------------------------------------- + + case ARDUINO_EVENT_WIFI_AP_START: + case ARDUINO_EVENT_WIFI_AP_STOP: + case ARDUINO_EVENT_WIFI_AP_STACONNECTED: + case ARDUINO_EVENT_WIFI_AP_STADISCONNECTED: + case ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED: + case ARDUINO_EVENT_WIFI_AP_PROBEREQRECVED: + case ARDUINO_EVENT_WIFI_AP_GOT_IP6: + softApEventHandler(event, info); break; } } -//---------------------------------------- -// Determine if WIFI is connected -//---------------------------------------- -bool wifiIsConnected() +//********************************************************************* +// Get the mDNS host name +const char * RTK_WIFI::hostNameGet() { - bool connected; - - connected = (WiFi.status() == WL_CONNECTED); - return connected; + return _hostName; } -//---------------------------------------- -// Determine if WiFi Station is running -//---------------------------------------- -bool wifiStationIsRunning() +//********************************************************************* +// Get the mDNS host name +void RTK_WIFI::hostNameSet(const char * mDnsHostName) { - return wifiStationRunning; + _hostName = mDnsHostName; } -//---------------------------------------- -// Determine if WiFi AP is running -//---------------------------------------- -bool wifiApIsRunning() +//********************************************************************* +// Restart WiFi +bool RTK_WIFI::restart(bool always) { - return wifiApRunning; + // Determine if restart should be perforrmed + if (always || wifiRestartRequested) + { + wifiRestartRequested = false; + + // Determine how WiFi is being used + bool started = false; + bool espNowRunning = _espNowRunning; + bool softApRunning = _softApRunning; + + // Stop the WiFi layer + started = enable(false, false, false); + + // Restart the WiFi layer + if (started) + started = enable(espNowRunning, + softApRunning, + networkConsumers() ? true : false); + + // Return the started state + return started; + } + else + return false; } -//---------------------------------------- -// Determine if either Station or AP is running -//---------------------------------------- -bool wifiIsRunning() +//********************************************************************* +// Determine if any use of WiFi is starting or is online +bool RTK_WIFI::running() { - if (wifiStationRunning || wifiApRunning) - return true; - return false; + return _espNowRunning | _softApRunning | _stationRunning; } -//---------------------------------------- -// Counts the number of entered SSIDs -//---------------------------------------- -int wifiNetworkCount() +//********************************************************************* +// Set the WiFi mode +// Inputs: +// setMode: Modes to set +// xorMode: Modes to toggle +// +// Math: result = (mode | setMode) ^ xorMode +// +// setMode +// 0 1 +// xorMode 0 No change Set bit +// 1 Toggle bit Clear bit +// +// Outputs: +// Returns true if successful and false upon failure +bool RTK_WIFI::setWiFiMode(uint8_t setMode, uint8_t xorMode) { - // Count SSIDs - int networkCount = 0; - for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + uint8_t mode; + uint8_t newMode; + bool started; + esp_err_t status; + + started = false; + do { - if (strlen(settings.wifiNetworks[x].ssid) > 0) - networkCount++; - } - return networkCount; + // Get the current mode + mode = (uint8_t)WiFi.getMode(); + if (settings.debugWifiState && _verbose) + systemPrintf("Current WiFi mode: 0x%08x (%s)\r\n", + mode, + ((mode == 0) ? "WiFi off" + : ((mode & (WIFI_MODE_AP | WIFI_MODE_STA)) == (WIFI_MODE_AP | WIFI_MODE_STA) ? "Soft AP + STA" + : ((mode & (WIFI_MODE_AP | WIFI_MODE_STA)) == WIFI_MODE_AP ? "Soft AP" + : "STA")))); + + // Determine the new mode + newMode = (mode | setMode) ^ xorMode; + started = (newMode == mode); + if (started) + break; + + // Set the new mode + started = WiFi.mode((wifi_mode_t)newMode); + if (!started) + { + systemPrintf("ERROR: Failed to set %d (%s), status: %d!\r\n", + newMode, + ((newMode == 0) ? "WiFi off" + : ((newMode & (WIFI_MODE_AP | WIFI_MODE_STA)) == (WIFI_MODE_AP | WIFI_MODE_STA) ? "Soft AP + STA mode" + : ((newMode & (WIFI_MODE_AP | WIFI_MODE_STA)) == WIFI_MODE_AP ? "Soft AP mode" + : "STA mode"))), status); + break; + } + if (settings.debugWifiState && _verbose) + systemPrintf("Set WiFi: %d (%s)\r\n", + newMode, + ((newMode == 0) ? "Off" + : ((newMode & (WIFI_MODE_AP | WIFI_MODE_STA)) == (WIFI_MODE_AP | WIFI_MODE_STA) ? "Soft AP + STA mode" + : ((newMode & (WIFI_MODE_AP | WIFI_MODE_STA)) == WIFI_MODE_AP ? "Soft AP mode" + : "STA mode")))); + } while (0); + + // Return the final status + return started; } -//---------------------------------------- -// Given a status, return the associated state or error -//---------------------------------------- -const char *wifiPrintState(wl_status_t wifiStatus) +//********************************************************************* +// Set the WiFi radio protocols +// Inputs: +// interface: Interface on which to set the protocols +// enableWiFiProtocols: When true, enable the WiFi protocols +// enableLongRangeProtocol: When true, enable the long range protocol +// Outputs: +// Returns true if successful and false upon failure +bool RTK_WIFI::setWiFiProtocols(wifi_interface_t interface, + bool enableWiFiProtocols, + bool enableLongRangeProtocol) { - switch (wifiStatus) + uint8_t newProtocols; + uint8_t oldProtocols; + bool started; + esp_err_t status; + + started = false; + do { - case WL_NO_SHIELD: - return ("WL_NO_SHIELD"); // 255 - case WL_STOPPED: - return ("WL_STOPPED"); - case WL_IDLE_STATUS: // 0 - return ("WL_IDLE_STATUS"); - case WL_NO_SSID_AVAIL: // 1 - return ("WL_NO_SSID_AVAIL"); - case WL_SCAN_COMPLETED: // 2 - return ("WL_SCAN_COMPLETED"); - case WL_CONNECTED: // 3 - return ("WL_CONNECTED"); - case WL_CONNECT_FAILED: // 4 - return ("WL_CONNECT_FAILED"); - case WL_CONNECTION_LOST: // 5 - return ("WL_CONNECTION_LOST"); - case WL_DISCONNECTED: // 6 - return ("WL_DISCONNECTED"); - } - return ("WiFi Status Unknown"); -} + // Get the current protocols + status = esp_wifi_get_protocol(interface, &oldProtocols); + started = (status == ESP_OK); + if (!started) + { + systemPrintf("ERROR: Failed to get the WiFi %s radio protocols!\r\n", + (interface == WIFI_IF_AP) ? "soft AP" : "station"); + break; + } + if (settings.debugWifiState && _verbose) + systemPrintf("Current WiFi protocols (%d%s%s%s%s%s)\r\n", + oldProtocols, + oldProtocols & WIFI_PROTOCOL_11AX ? ", 11AX" : "", + oldProtocols & WIFI_PROTOCOL_11B ? ", 11B" : "", + oldProtocols & WIFI_PROTOCOL_11G ? ", 11G" : "", + oldProtocols & WIFI_PROTOCOL_11N ? ", 11N" : "", + oldProtocols & WIFI_PROTOCOL_LR ? ", LR" : ""); + + // Determine which protocols to enable + newProtocols = oldProtocols; + if (enableLongRangeProtocol || enableWiFiProtocols) + { + // Enable the WiFi protocols + newProtocols |= WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N; -//---------------------------------------- -// Starts the WiFi connection state machine (moves from WIFI_STATE_OFF to WIFI_STATE_CONNECTING) -// Sets the appropriate protocols (WiFi + ESP-Now) -// If radio is off entirely, start WiFi -// If ESP-Now is active, only add the LR protocol -// Returns true if WiFi has connected and false otherwise -//---------------------------------------- -bool wifiStart() -{ - int wifiStatus; + // Enable the ESP-NOW long range protocol + if (enableLongRangeProtocol) + newProtocols |= WIFI_PROTOCOL_LR; + else + newProtocols &= ~WIFI_PROTOCOL_LR; + } - // Determine which parts of WiFi need to be started - bool startWiFiStation = false; - bool startWiFiAp = false; + // Disable the protocols + else + newProtocols = 0; + + // Display the new protocols + if (settings.debugWifiState && _verbose) + systemPrintf("Setting WiFi protocols (%d%s%s%s%s%s)\r\n", + newProtocols, + newProtocols & WIFI_PROTOCOL_11AX ? ", 11AX" : "", + newProtocols & WIFI_PROTOCOL_11B ? ", 11B" : "", + newProtocols & WIFI_PROTOCOL_11G ? ", 11G" : "", + newProtocols & WIFI_PROTOCOL_11N ? ", 11N" : "", + newProtocols & WIFI_PROTOCOL_LR ? ", LR" : ""); + + // Set the new protocols + started = true; + if (newProtocols != oldProtocols) + { + status = esp_wifi_set_protocol(interface, newProtocols); + started = (status == ESP_OK); + } + if (!started) + { + systemPrintf("Current WiFi protocols (%d%s%s%s%s%s)\r\n", + oldProtocols, + oldProtocols & WIFI_PROTOCOL_11AX ? ", 11AX" : "", + oldProtocols & WIFI_PROTOCOL_11B ? ", 11B" : "", + oldProtocols & WIFI_PROTOCOL_11G ? ", 11G" : "", + oldProtocols & WIFI_PROTOCOL_11N ? ", 11N" : "", + oldProtocols & WIFI_PROTOCOL_LR ? ", LR" : ""); + systemPrintf("Setting WiFi protocols (%d%s%s%s%s%s)\r\n", + newProtocols, + newProtocols & WIFI_PROTOCOL_11AX ? ", 11AX" : "", + newProtocols & WIFI_PROTOCOL_11B ? ", 11B" : "", + newProtocols & WIFI_PROTOCOL_11G ? ", 11G" : "", + newProtocols & WIFI_PROTOCOL_11N ? ", 11N" : "", + newProtocols & WIFI_PROTOCOL_LR ? ", LR" : ""); + systemPrintf("ERROR: Failed to set the WiFi %s radio protocols!\r\n", + (interface == WIFI_IF_AP) ? "soft AP" : "station"); + break; + } + } while (0); - uint16_t consumerTypes = networkGetConsumerTypes(); + // Return the final status + return started; +} - // The consumers need station - if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) - startWiFiStation = true; +//********************************************************************* +// Configure the soft AP +// Inputs: +// ipAddress: IP address of the soft AP +// subnetMask: Subnet mask for the soft AP network +// firstDhcpAddress: First IP address to use in the DHCP range +// dnsAddress: IP address to use for DNS lookup (translate name to IP address) +// gatewayAddress: IP address of the gateway to a larger network (internet?) +// Outputs: +// Returns true if the soft AP was successfully configured. +bool RTK_WIFI::softApConfiguration(IPAddress ipAddress, + IPAddress subnetMask, + IPAddress firstDhcpAddress, + IPAddress dnsAddress, + IPAddress gatewayAddress) +{ + bool success; - // The consumers need AP - if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) - startWiFiAp = true; + _apIpAddress = ipAddress; + _apSubnetMask = subnetMask; + _apFirstDhcpAddress = firstDhcpAddress; + _apDnsAddress = dnsAddress; + _apGatewayAddress = gatewayAddress; - if (startWiFiStation == false && startWiFiAp == false) + // Restart the soft AP if necessary + success = true; + if (softApOnline()) { - systemPrintln("wifiStart() requested without any NETCONSUMER combination"); - WIFI_STOP(); - return (false); + success = enable(false, false, stationRunning()); + if (success) + success = enable(false, true, stationRunning()); } + return success; +} - // Determine if WiFi is already running - if (startWiFiStation == wifiStationRunning && startWiFiAp == wifiApRunning) +//********************************************************************* +// Display the soft AP configuration +// Inputs: +// display: Address of a Print object +void RTK_WIFI::softApConfigurationDisplay(Print * display) +{ + display->printf("Soft AP configuration:\r\n"); + display->printf(" %s: IP Address\r\n", _apIpAddress.toString().c_str()); + display->printf(" %s: Subnet mask\r\n", _apSubnetMask.toString().c_str()); + if ((uint32_t)_apFirstDhcpAddress) + display->printf(" %s: First DHCP address\r\n", _apFirstDhcpAddress.toString().c_str()); + if ((uint32_t)_apDnsAddress) + display->printf(" %s: DNS address\r\n", _apDnsAddress.toString().c_str()); + if ((uint32_t)_apGatewayAddress) + display->printf(" %s: Gateway address\r\n", _apGatewayAddress.toString().c_str()); +} + +//********************************************************************* +// Handle the soft AP events +void RTK_WIFI::softApEventHandler(arduino_event_id_t event, arduino_event_info_t info) +{ + // Handle the event + switch (event) { - if (settings.debugWifiState == true) - systemPrintln("WiFi is already running with requested setup"); - return (true); + case ARDUINO_EVENT_WIFI_AP_STOP: + // Mark the soft AP as offline + if (settings.debugWifiState && softApOnline()) + systemPrintf("AP: Offline\r\n"); + _started = _started & ~WIFI_AP_ONLINE; + if (settings.debugWifiState && _verbose) + systemPrintf("_started: 0x%08x\r\n", _started); + break; } +} - // Handle special cases if no networks have been entered - if (wifiNetworkCount() == 0) +//********************************************************************* +// Set the soft AP host name +// Inputs: +// hostName: Zero terminated host name character string +// Outputs: +// Returns true if successful and false upon failure +bool RTK_WIFI::softApSetHostName(const char * hostName) +{ + bool nameSet; + + do { - if (startWiFiStation == true && startWiFiAp == false) + // Verify that a host name was specified + nameSet = (hostName != nullptr) && (strlen(hostName) != 0); + if (!nameSet) { - systemPrintln("Error: Please enter at least one SSID before using WiFi"); - displayNoSSIDs(2000); - WIFI_STOP(); - return false; + systemPrintf("ERROR: No host name specified!\r\n"); + break; } - else if (startWiFiStation == true && startWiFiAp == true) + + // Set the host name + if (settings.debugWifiState) + systemPrintf("WiFI setting AP host name\r\n"); + nameSet = WiFi.AP.setHostname(hostName); + if (!nameSet) { - systemPrintln("Error: No SSID available to start WiFi Station during AP"); - // Allow the system to continue in AP only mode - startWiFiStation = false; + systemPrintf("ERROR: Failed to set the Wifi AP host name!\r\n"); + break; } + if (settings.debugWifiState) + systemPrintf("WiFi AP hostname: %s\r\n", hostName); + } while (0); + return nameSet; +} + +//********************************************************************* +// Set the soft AP configuration +// Inputs: +// ipAddress: IP address of the server, nullptr or empty string causes +// default 192.168.4.1 to be used +// subnetMask: Subnet mask for local network segment, nullptr or empty +// string causes default 0.0.0.0 to be used, unless ipAddress +// is not specified, in which case 255.255.255.0 is used +// gatewayAddress: Gateway to internet IP address, nullptr or empty string +// causes default 0.0.0.0 to be used (no access to internet) +// dnsAddress: Domain name server (name to IP address translation) IP address, +// nullptr or empty string causes 0.0.0.0 to be used (only +// mDNS name translation, if started) +// dhcpStartAddress: Start of DHCP IP address assignments for the local +// network segment, nullptr or empty string causes default +// 0.0.0.0 to be used (disable DHCP server) unless ipAddress +// was not specified in which case 192.168.4.2 +// Outputs: +// Returns true if successful and false upon failure +bool RTK_WIFI::softApSetIpAddress(const char * ipAddress, + const char * subnetMask, + const char * gatewayAddress, + const char * dnsAddress, + const char * dhcpFirstAddress) +{ + bool configured; + uint32_t uDhcpFirstAddress; + uint32_t uDnsAddress; + uint32_t uGatewayAddress; + uint32_t uIpAddress; + uint32_t uSubnetMask; + + // Convert the IP address + if ((!ipAddress) || (strlen(ipAddress) == 0)) + uIpAddress = 0; + else + uIpAddress = (uint32_t)IPAddress(ipAddress); + + // Convert the subnet mask + if ((!subnetMask) || (strlen(subnetMask) == 0)) + { + if (uIpAddress == 0) + uSubnetMask = IPAddress("255.255.255.0"); + else + uSubnetMask = 0; } + else + uSubnetMask = (uint32_t)IPAddress(subnetMask); - // Start WiFi - wifiConnect(startWiFiStation, startWiFiAp, settings.wifiConnectTimeoutMs); + // Convert the gateway address + if ((!gatewayAddress) || (strlen(gatewayAddress) == 0)) + uGatewayAddress = 0; + else + uGatewayAddress = (uint32_t)IPAddress(gatewayAddress); - // If we are in AP only mode, as long as the AP is started, return true - if (WiFi.getMode() == WIFI_MODE_AP) - return (wifiApIsRunning); + // Convert the first DHCP address + if ((!dhcpFirstAddress) || (strlen(dhcpFirstAddress) == 0)) + { + if (uIpAddress == 0) + uDhcpFirstAddress = IPAddress("192.168.4.32"); + else + uDhcpFirstAddress = uIpAddress + 0x1f000000; + } + else + uDhcpFirstAddress = (uint32_t)IPAddress(dhcpFirstAddress); - // If we are in STA or AP+STA mode, return if the station connected successfully - wifiStatus = WiFi.status(); - return (wifiStatus == WL_CONNECTED); + // Convert the DNS address + if ((!dnsAddress) || (strlen(dnsAddress) == 0)) + uDnsAddress = 0; + else + uDnsAddress = (uint32_t)IPAddress(dnsAddress); + + // Use the default IP address if not specified + if (uIpAddress == 0) + uIpAddress = IPAddress("192.168.4.1"); + + // Display the soft AP configuration + if (settings.debugWifiState) + softApConfigurationDisplay(&Serial); + + // Configure the soft AP + configured = WiFi.AP.config(IPAddress(uIpAddress), + IPAddress(uGatewayAddress), + IPAddress(uSubnetMask), + IPAddress(uDhcpFirstAddress), + IPAddress(uDnsAddress)); + if (!configured) + systemPrintf("ERROR: Failed to configure the soft AP with IP addresses!\r\n"); + return configured; } -//---------------------------------------- -// Set WiFi timeout back to zero -// Useful if other things (such as a successful ethernet connection) need to reset wifi timeout -//---------------------------------------- -void wifiResetTimeout() +//********************************************************************* +// Get the soft AP status +bool RTK_WIFI::softApOnline() { - wifiStartTimeout = 0; - if (settings.debugWifiState == true) - systemPrintln("WiFi: Start timeout reset to zero"); + return (_started & WIFI_AP_ONLINE) ? true : false; } -//---------------------------------------- -//---------------------------------------- -uint32_t wifiGetStartTimeout() +//********************************************************************* +// Determine if the soft AP is being started or is onine +bool RTK_WIFI::softApRunning() { - return (wifiStartTimeout); + return _softApRunning; } -//---------------------------------------- -// Reset the last WiFi start attempt -// Useful when WiFi settings have changed -//---------------------------------------- -void wifiResetThrottleTimeout() +//********************************************************************* +// Set the soft AP SSID and password +// Outputs: +// Returns true if successful and false upon failure +bool RTK_WIFI::softApSetSsidPassword(const char * ssid, const char * password) { - wifiStartLastTry = 0; + bool created; + + // Set the WiFi soft AP SSID and password + if (settings.debugWifiState) + systemPrintf("WiFi AP: Attempting to set AP SSID and password\r\n"); + created = WiFi.AP.create(ssid, password); + if (!created) + systemPrintf("ERROR: Failed to set soft AP SSID and Password!\r\n"); + else if (settings.debugWifiState) + systemPrintf("WiFi AP: SSID: %s, Password: %s\r\n", ssid, password); + return created; } -//---------------------------------------- -// Start WiFi with throttling -//---------------------------------------- -void wifiThrottledStart(NetIndex_t index, uintptr_t parameter, bool debug) +//********************************************************************* +// Attempt to start the soft AP mode +// Inputs: +// forceAP: Set to true to force AP to start, false will only start +// soft AP if settings.wifiConfigOverAP is true +// Outputs: +// Returns true if the soft AP was started successfully and false +// otherwise +bool RTK_WIFI::startAp(bool forceAP) { - int seconds; - int minutes; + return enable(_espNowRunning, forceAP | settings.wifiConfigOverAP, _stationRunning); +} - // Restart delay - if ((millis() - wifiStartLastTry) < wifiStartTimeout) - return; - wifiStartLastTry = millis(); +//********************************************************************* +// Connect the station to a remote AP +// Return true if the connection was successful and false upon failure. +bool RTK_WIFI::stationConnectAP() +{ + bool connected; - // Start WiFi - if (wifiStart()) - { - networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); - wifiFailedConnectionAttempts = 0; - } - else + do { - // Increase the timeout - wifiStartTimeout <<= 1; - if (!wifiStartTimeout) - wifiStartTimeout = WIFI_MIN_TIMEOUT; - else if (wifiStartTimeout > WIFI_MAX_TIMEOUT) - wifiStartTimeout = WIFI_MAX_TIMEOUT; - - wifiFailedConnectionAttempts++; - - // Display the delay - seconds = wifiStartTimeout / MILLISECONDS_IN_A_SECOND; - minutes = seconds / SECONDS_IN_A_MINUTE; - seconds -= minutes * SECONDS_IN_A_MINUTE; + // Connect to the remote AP if (settings.debugWifiState) - systemPrintf("WiFi: Delaying %2d:%02d before restarting WiFi\r\n", minutes, seconds); - } + systemPrintf("WiFi connecting to %s on channel %d with %s authorization\r\n", + _staRemoteApSsid, + _channel, + (_staAuthType < WIFI_AUTH_MAX) ? wifiAuthorizationName[_staAuthType] : "Unknown"); + connected = (WiFi.STA.connect(_staRemoteApSsid, _staRemoteApPassword, _channel)); + if (!connected) + { + if (settings.debugWifiState) + systemPrintf("WIFI failed to connect to SSID %s with password %s\r\n", + _staRemoteApSsid, _staRemoteApPassword); + break; + } + if (settings.debugWifiState) + systemPrintf("WiFi station connected to %s on channel %d with %s authorization\r\n", + _staRemoteApSsid, + _channel, + (_staAuthType < WIFI_AUTH_MAX) ? wifiAuthorizationName[_staAuthType] : "Unknown"); + } while (0); + return connected; } -//---------------------------------------- -// WiFi start sequence -//---------------------------------------- -NETWORK_POLL_SEQUENCE wifiStartSequence[] = { - // State Parameter Description - {wifiThrottledStart, 0, "Initialize WiFi"}, - {nullptr, 0, "Termination"}, -}; - -//---------------------------------------- -// WiFi stop sequence -//---------------------------------------- -NETWORK_POLL_SEQUENCE wifiStopSequence[] = { - // State Parameter Description - {wifiStop, 0, "Shutdown WiFi"}, - {nullptr, 0, "Termination"}, -}; - -//---------------------------------------- -// Stop WiFi and release all resources -//---------------------------------------- -void wifiStop() +//********************************************************************* +// Disconnect the station from an AP +// Outputs: +// Returns true if successful and false upon failure +bool RTK_WIFI::stationDisconnect() { - // Stop the web server - stopWebServer(); + bool disconnected; + + do + { + // Determine if station is connected to a remote AP + disconnected = !_staConnected; + if (disconnected) + { + if (settings.debugWifiState) + systemPrintf("Station already disconnected from remote AP\r\n"); + break; + } - // Stop the DNS server if we were using the captive portal - if (((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) && settings.enableCaptivePortal) - dnsServer.stop(); + // Disconnect from the remote AP + if (settings.debugWifiState) + systemPrintf("WiFI disconnecting station from remote AP\r\n"); + disconnected = WiFi.STA.disconnect(); + if (!disconnected) + { + systemPrintf("ERROR: Failed to disconnect WiFi from the remote AP!\r\n"); + break; + } + if (settings.debugWifiState) + systemPrintf("WiFi disconnected from the remote AP\r\n"); + } while (0); + return disconnected; +} - wifiFailedConnectionAttempts = 0; // Reset the counter +//********************************************************************* +// Handle the WiFi station events +void RTK_WIFI::stationEventHandler(arduino_event_id_t event, arduino_event_info_t info) +{ + WIFI_CHANNEL_t channel; + IPAddress ipAddress; + bool success; + int type; - // If ESP-Now is active, change protocol to only Long Range - if (espnowState > ESPNOW_OFF) + // Notify the upper layers that WiFi is no longer available + switch (event) { - if (WiFi.getMode() != WIFI_STA) - WiFi.mode(WIFI_STA); + case ARDUINO_EVENT_WIFI_STA_START: + WiFi.STA.macAddress(_staMacAddress); + if (settings.debugWifiState) + systemPrintf("WiFi Event: Station start: MAC: %02x:%02x:%02x:%02x:%02x:%02x\r\n", + _staMacAddress[0], _staMacAddress[1], _staMacAddress[2], + _staMacAddress[3], _staMacAddress[4], _staMacAddress[5]); - // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps - // esp_wifi_set_protocol requires WiFi to be started - esp_err_t response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); - if (response != ESP_OK) - systemPrintf("wifiShutdown: Error setting ESP-Now lone protocol: %s\r\n", esp_err_to_name(response)); + // Fall through + // | + // | + // V + + case ARDUINO_EVENT_WIFI_STA_STOP: + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: + // Start the reconnection timer + if (event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) + { + if (settings.debugWifiState && _verbose && !_timer) + systemPrintf("Reconnection timer started\r\n"); + _timer = millis(); + if (!_timer) + _timer = 1; + } else { - if (settings.debugWifiState == true) - systemPrintln("WiFi disabled, ESP-Now left in place"); + // Stop the reconnection timer + if (settings.debugWifiState && _verbose && _timer) + systemPrintf("Reconnection timer stopped\r\n"); + _timer = 0; } - } - else - { - WiFi.mode(WIFI_OFF); - if (settings.debugWifiState == true) - systemPrintln("WiFi Stopped"); - } - // Take the network offline - networkMarkOffline(NETWORK_WIFI); + // Fall through + // | + // | + // V - if (wifiMulti != nullptr) - wifiMulti = nullptr; + case ARDUINO_EVENT_WIFI_SCAN_DONE: + case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: + // The WiFi station is no longer connected to the remote AP + if (settings.debugWifiState && _staConnected) + systemPrintf("WiFi station disconnected from %s\r\n", + _staRemoteApSsid); + _staConnected = false; - // Display the heap state - reportHeapNow(settings.debugWifiState); - wifiStationRunning = false; - wifiApRunning = false; -} + // Fall through + // | + // | + // V -// Needed for wifiStopSequence -void wifiStop(NetIndex_t index, uintptr_t parameter, bool debug) -{ - wifiStop(); - networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); -} + case ARDUINO_EVENT_WIFI_STA_LOST_IP: + // Mark the WiFi station offline + if (_started & WIFI_STA_ONLINE) + systemPrintf("WiFi: Station offline!\r\n"); + _started = _started & ~WIFI_STA_ONLINE; + + // Notify user of loss of IP address + if (settings.debugWifiState && _staHasIp) + systemPrintf("WiFi station lost IPv%c address %s\r\n", + _staIpType, _staIpAddress.toString().c_str()); + _staHasIp = false; + + // Stop mDNS if necessary + if (_started & WIFI_STA_START_MDNS) + { + if (settings.debugWifiState && _verbose) + systemPrintf("Calling networkMulticastDNSStop for WiFi station from %s event\r\n", + arduinoEventName[event]); + _started = _started & ~WIFI_STA_START_MDNS; + networkMulticastDNSStop(NETWORK_WIFI); + } + _staIpAddress = IPAddress((uint32_t)0); + _staIpType = 0; + break; + + //------------------------------ + // WiFi Station State Machine + // + // .--------+<----------+<-----------+<-------------+<----------+<----------+<------------. + // v | | | | | | | + // STOP --> READY --> STA_START --> SCAN_DONE --> CONNECTED --> GOT_IP --> LOST_IP --> DISCONNECTED + // ^ ^ ^ | | + // | | '-----------' | + // OFF -------' '-------------------------------------' + // + // Handle the WiFi station events + //------------------------------ + + case ARDUINO_EVENT_WIFI_STA_CONNECTED: + _staConnected = true; + break; + + case ARDUINO_EVENT_WIFI_STA_GOT_IP: + case ARDUINO_EVENT_WIFI_STA_GOT_IP6: + ipAddress = WiFi.STA.localIP(); + type = (event == ARDUINO_EVENT_WIFI_STA_GOT_IP) ? '4' : '6'; + + // Display the IP address + if (settings.debugWifiState) + systemPrintf("WiFi Event: Got IPv%c address %s\r\n", + type, ipAddress.toString().c_str()); + break; + } // End of switch +} + +//********************************************************************* +// Set the station's host name +// Inputs: +// hostName: Zero terminated host name character string +// Outputs: +// Returns true if successful and false upon failure +bool RTK_WIFI::stationHostName(const char * hostName) +{ + bool nameSet; + + do + { + // Verify that a host name was specified + nameSet = (hostName != nullptr) && (strlen(hostName) != 0); + if (!nameSet) + { + systemPrintf("ERROR: No host name specified!\r\n"); + break; + } + + // Set the host name + if (settings.debugWifiState) + systemPrintf("WiFI setting station host name\r\n"); + nameSet = WiFi.STA.setHostname(hostName); + if (!nameSet) + { + systemPrintf("ERROR: Failed to set the Wifi station host name!\r\n"); + break; + } + if (settings.debugWifiState) + systemPrintf("WiFi station hostname: %s\r\n", hostName); + } while (0); + return nameSet; +} + +//********************************************************************* +// Get the station status +bool RTK_WIFI::stationOnline() +{ + return (_started & WIFI_STA_ONLINE) ? true : false; +} + +//********************************************************************* +// Handle WiFi station reconnection requests +void RTK_WIFI::stationReconnectionRequest() +{ + uint32_t currentMsec; + + // Check for reconnection request + currentMsec = millis(); + if (_timer) + { + if ((currentMsec - _timer) >= WIFI_RECONNECTION_DELAY) + { + _timer = 0; + if (settings.debugWifiState) + systemPrintf("Reconnection timer fired!\r\n"); + + // Start the WiFi scan + if (stationRunning()) + { + _started = _started & ~WIFI_STA_RECONNECT; + stopStart(WIFI_AP_START_MDNS, WIFI_STA_RECONNECT); + } + } + } +} + +//********************************************************************* +// Scan the WiFi network for remote APs +// Inputs: +// channel: Channel number for the scan, zero (0) scan all channels +// Outputs: +// Returns the number of access points +int16_t RTK_WIFI::stationScanForAPs(WIFI_CHANNEL_t channel) +{ + int16_t apCount; + int16_t status; -// Returns true if we deem WiFi is not going to connect -// Used to allow cellular to start -bool wifiUnavailable() + do + { + // Determine if the WiFi scan is already running + if (_scanRunning) + { + if (settings.debugWifiState) + systemPrintf("WiFi scan already running"); + break; + } + + // Determine if scanning a single channel or all channels + if (settings.debugWifiState) + { + if (channel) + systemPrintf("WiFI starting scan for remote APs on channel %d\r\n", channel); + else + systemPrintf("WiFI starting scan for remote APs\r\n"); + } + + // Start the WiFi scan + apCount = WiFi.scanNetworks(false, // async + false, // show_hidden + false, // passive + 300, // max_ms_per_chan + channel, // channel number + nullptr, // ssid * + nullptr); // bssid * + if (settings.debugWifiState && _verbose) + Serial.printf("apCount: %d\r\n", apCount); + if (apCount < 0) + { + systemPrintf("ERROR: WiFi scan failed, status: %d!\r\n", apCount); + break; + } + _apCount = apCount; + if (settings.debugWifiState) + systemPrintf("WiFi scan complete, found %d remote APs\r\n", _apCount); + } while (0); + return apCount; +} + +//********************************************************************* +// Get the station status +bool RTK_WIFI::stationRunning() +{ + return _stationRunning; +} + +//********************************************************************* +// Select the AP and channel to use for WiFi station +// Inputs: +// apCount: Number to APs detected by the WiFi scan +// list: Determine if the APs should be listed +// Outputs: +// Returns the channel number of the AP +WIFI_CHANNEL_t RTK_WIFI::stationSelectAP(uint8_t apCount, bool list) { - if(wifiNetworkCount() == 0) - return true; + int ap; + WIFI_CHANNEL_t apChannel; + bool apFound; + int authIndex; + WIFI_CHANNEL_t channel; + const char * ssid; + String ssidString; + int type; + + // Verify that an AP was found + if (apCount == 0) + return 0; + + // Print the header + // 1 1 2 3 + // 1234 1234 123456789012345 12345678901234567890123456789012 + if (settings.debugWifiState || list) + { + systemPrintf(" dBm Chan Authorization SSID\r\n"); + systemPrintf("---- ---- --------------- --------------------------------\r\n"); + } + + // Walk the list of APs that were found during the scan + apFound = false; + apChannel = 0; + for (ap = 0; ap < apCount; ap++) + { + // The APs are listed in decending signal strength order + // Check for a requested AP + ssidString = WiFi.SSID(ap); + ssid = ssidString.c_str(); + type = WiFi.encryptionType(ap); + channel = WiFi.channel(ap); + if (!apFound) + { + for (authIndex = 0; authIndex < MAX_WIFI_NETWORKS; authIndex++) + { + // Determine if this authorization matches the AP's SSID + if (strlen(settings.wifiNetworks[authIndex].ssid) + && (strcmp(ssid, settings.wifiNetworks[authIndex].ssid) == 0) + && ((type == WIFI_AUTH_OPEN) + || (strlen(settings.wifiNetworks[authIndex].password)))) + { + if (settings.debugWifiState) + systemPrintf("WiFi: Found remote AP: %s\r\n", ssid); + + // A match was found, save it and stop looking + _staRemoteApSsid = settings.wifiNetworks[authIndex].ssid; + _staRemoteApPassword = settings.wifiNetworks[authIndex].password; + apChannel = channel; + _staAuthType = type; + apFound = true; + break; + } + } + + // Check for done + if (apFound && (!(settings.debugWifiState | list))) + break; + } + + // Display the list of APs + if (settings.debugWifiState || list) + systemPrintf("%4d %4d %s %s\r\n", + WiFi.RSSI(ap), + channel, + (type < WIFI_AUTH_MAX) ? wifiAuthorizationName[type] : "Unknown", + ssid); + } + + // Return the channel number + return apChannel; +} + +//********************************************************************* +// Stop and start WiFi components +// Inputs: +// stopping: WiFi components that need to be stopped +// starting: WiFi components that neet to be started +// Outputs: +// Returns true if the modes were successfully configured +bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) +{ + int authIndex; + WIFI_CHANNEL_t channel; + WIFI_ACTION_t delta; + bool enabled; + WIFI_ACTION_t mask; + WIFI_ACTION_t notStarted; + uint8_t primaryChannel; + WIFI_ACTION_t restarting; + wifi_second_chan_t secondaryChannel; + WIFI_ACTION_t startingNow; + esp_err_t status; + WIFI_ACTION_t stillRunning; + + // Determine the next actions + notStarted = 0; + enabled = true; + + // Display the parameters + if (settings.debugWifiState && _verbose) + { + systemPrintf("stopping: 0x%08x\r\n", stopping); + systemPrintf("starting: 0x%08x\r\n", starting); + } + + //**************************************** + // Select the channel + // + // The priority order for the channel is: + // 1. Active channel + // 2. _stationChannel + // 3. Remote AP channel determined by scan + // 4. _espNowChannel + // 5. _apChannel + // 6. Channel 1 + //**************************************** + + // Determine if there is an active channel + if (((_started & ~stopping) & (WIFI_AP_ONLINE | WIFI_EN_ESP_NOW_ONLINE | WIFI_STA_ONLINE)) + && _channel) + { + // Continue to use the active channel + channel = _channel; + if (settings.debugWifiState && _verbose) + systemPrintf("channel: %d, active channel\r\n", channel); + } + + // Use the station channel if specified + else if (_stationChannel && (starting & WIFI_STA_ONLINE)) + { + channel = _stationChannel; + if (settings.debugWifiState && _verbose) + systemPrintf("channel: %d, WiFi station channel\r\n", channel); + } + + // Determine if a scan for remote APs is needed + else if (starting & WIFI_STA_START_SCAN) + { + channel = 0; + if (settings.debugWifiState && _verbose) + systemPrintf("channel: Determine by remote AP scan\r\n"); + } + + // Determine if the ESP-NOW channel was specified + else if (_espNowChannel & ((starting | _started) & WIFI_EN_ESP_NOW_ONLINE)) + { + channel = _espNowChannel; + if (settings.debugWifiState && _verbose) + systemPrintf("channel: %d, ESP-NOW channel\r\n", channel); + } + + // Determine if the AP channel was specified + else if (_apChannel && ((starting | _started) & WIFI_AP_ONLINE)) + { + channel = _apChannel; + if (settings.debugWifiState && _verbose) + systemPrintf("channel: %d, soft AP channel\r\n", channel); + } + + // No channel specified and scan not being done, use the default channel + else + { + channel = WIFI_DEFAULT_CHANNEL; + if (settings.debugWifiState && _verbose) + systemPrintf("channel: %d, default channel\r\n", channel); + } + + //**************************************** + // Determine the use of mDNS + //**************************************** + + // It is much more difficult to determine the DHCP address of the RTK + // versus the hard coded IP address of the server. As such give + // priority to the WiFi station for mDNS use. When the station is + // not running or being started, let mDNS start for the soft AP. + + // Determine if mDNS is being used for WiFi station + if (starting & WIFI_STA_START_MDNS) + { + // Don't start mDNS for soft AP + starting &= ~WIFI_AP_START_MDNS; + + // Stop it if it is being used for soft AP + if (_started & WIFI_AP_START_MDNS) + stopping |= WIFI_AP_START_MDNS; + } + + //**************************************** + // Determine if DNS needs to start + //**************************************** + + if (starting & WIFI_AP_START_DNS_SERVER) + { + // Only start the DNS server when the captive portal is enabled + if (!settings.enableCaptivePortal) + starting &= ~WIFI_AP_START_DNS_SERVER; + } + + //**************************************** + // Perform some optimizations + //**************************************** + + // Only stop the started components + stopping &= _started; + + // Determine which components are being restarted + restarting = _started & stopping & starting; + if (settings.debugWifiState && _verbose) + { + systemPrintf("0x%08x: _started\r\n", _started); + systemPrintf("0x%08x: stopping\r\n", stopping); + systemPrintf("0x%08x: starting\r\n", starting); + systemPrintf("0x%08x: restarting\r\n", starting); + } + + // Don't start components that are already running and are not being + // stopped + starting &= ~(_started & ~stopping); + + // Display the starting and stopping + if (settings.debugWifiState) + { + bool startEspNow = starting & WIFI_EN_ESP_NOW_ONLINE; + bool startSoftAP = starting & WIFI_AP_ONLINE; + bool startStation = starting & WIFI_STA_ONLINE; + bool start = startEspNow || startSoftAP || startStation; + bool stopEspNow = stopping & WIFI_EN_ESP_NOW_ONLINE; + bool stopSoftAP = stopping & WIFI_AP_ONLINE; + bool stopStation = stopping & WIFI_STA_ONLINE; + bool stop = stopEspNow || stopSoftAP || stopStation; + + if (start || stop) + systemPrintf("WiFi:%s%s%s%s%s%s%s%s%s%s%s%s%s%s\r\n", + start ? " Starting (" : "", + startEspNow ? "ESP-NOW" : "", + (startEspNow && (startSoftAP || startStation)) ? ", " : "", + startSoftAP ? "Soft AP" : "", + (startSoftAP && startStation) ? ", " : "", + startStation ? "Station" : "", + start ? ")" : "", + stop ? " Stopping (" : "", + stopEspNow ? "ESP-NOW" : "", + (stopEspNow && (stopSoftAP || stopStation)) ? ", " : "", + stopSoftAP ? "Soft AP" : "", + (stopSoftAP && stopStation) ? ", " : "", + stopStation ? "Station" : "", + stop ? ")" : ""); + } + + //**************************************** + // Return the use of mDNS to soft AP when WiFi STA stops + //**************************************** + + // Determine if WiFi STA is stopping + if (stopping & WIFI_STA_START_MDNS) + { + // Determine if mDNS should continue to run on soft AP + if ((_started & WIFI_AP_ONLINE) && !(stopping & WIFI_AP_ONLINE)) + { + // Restart mDNS for soft AP + _started = _started & ~WIFI_AP_START_MDNS; + starting |= WIFI_AP_START_MDNS; + } + } + + // Stop the components + startingNow = starting; + do + { + //**************************************** + // Display the items being stopped + //**************************************** + + if (settings.debugWifiState && _verbose && stopping) + displayComponents("Stopping", stopping); + + //**************************************** + // Stop the ESP-NOW components + //**************************************** + + // Mark the ESP-NOW offline + if (stopping & WIFI_EN_ESP_NOW_ONLINE) + { + if (settings.debugWifiState) + systemPrintf("WiFi: ESP-NOW offline!\r\n"); + _started = _started & ~WIFI_EN_ESP_NOW_ONLINE; + } + + // Stop the ESP-NOW layer + if (stopping & WIFI_EN_START_ESP_NOW) + { + if (settings.debugWifiState && _verbose) + systemPrintf("WiFi: Stopping ESP-NOW\r\n"); + if (!espNowStop()) + { + systemPrintf("ERROR: Failed to stop ESP-NOW!\r\n"); + break; + } + _started = _started & ~WIFI_EN_START_ESP_NOW; + if (settings.debugWifiState && _verbose) + systemPrintf("WiFi: ESP-NOW stopped\r\n"); + } + + // Stop the promiscuous RX callback handler + if (stopping & WIFI_EN_PROMISCUOUS_RX_CALLBACK) + { + if (settings.debugWifiState && _verbose) + systemPrintf("Calling esp_wifi_set_promiscuous_rx_cb\r\n"); + status = esp_wifi_set_promiscuous_rx_cb(nullptr); + if (status != ESP_OK) + { + systemPrintf("ERROR: Failed to stop WiFi promiscuous RX callback\r\n"); + break; + } + if (settings.debugWifiState) + systemPrintf("WiFi: Stopped WiFi promiscuous RX callback\r\n"); + _started = _started & ~WIFI_EN_PROMISCUOUS_RX_CALLBACK; + } + + // Stop promiscuous mode + if (stopping & WIFI_EN_SET_PROMISCUOUS_MODE) + { + if (settings.debugWifiState && _verbose) + systemPrintf("Calling esp_wifi_set_promiscuous\r\n"); + status = esp_wifi_set_promiscuous(false); + if (status != ESP_OK) + { + systemPrintf("ERROR: Failed to stop WiFi promiscuous mode, status: %d\r\n", status); + break; + } + if (settings.debugWifiState && _verbose) + systemPrintf("WiFi: Promiscuous mode stopped\r\n"); + _started = _started & ~WIFI_EN_SET_PROMISCUOUS_MODE; + } + + // Handle WiFi set channel + if (stopping & WIFI_EN_SET_CHANNEL) + _started = _started & ~WIFI_EN_SET_CHANNEL; + + // Stop the long range radio protocols + if (stopping & WIFI_EN_SET_PROTOCOLS) + { + if (!setWiFiProtocols(WIFI_IF_STA, true, false)) + break; + _started = _started & ~WIFI_EN_SET_PROTOCOLS; + } + + //**************************************** + // Stop the WiFi station components + //**************************************** + + // Mark the WiFi station offline + if (stopping & WIFI_STA_ONLINE) + { + if (_started & WIFI_STA_ONLINE) + systemPrintf("WiFi: Station offline!\r\n"); + _started = _started & ~WIFI_STA_ONLINE; + } + + // Stop mDNS on WiFi station + if (stopping & WIFI_STA_START_MDNS) + { + if (_started & WIFI_STA_START_MDNS) + { + _started = _started & ~WIFI_STA_START_MDNS; + if (settings.debugWifiState && _verbose) + systemPrintf("Calling networkMulticastDNSStop for WiFi station\r\n"); + networkMulticastDNSStop(NETWORK_WIFI); + } + } + + // Disconnect from the remote AP + if (stopping & WIFI_STA_CONNECT_TO_REMOTE_AP) + { + if (!stationDisconnect()) + break; + _started = _started & ~WIFI_STA_CONNECT_TO_REMOTE_AP; + } + + // Handle auto reconnect + if (stopping & WIFI_STA_DISABLE_AUTO_RECONNECT) + _started = _started & ~WIFI_STA_DISABLE_AUTO_RECONNECT; + + // Handle WiFi station host name + if (stopping & WIFI_STA_SET_HOST_NAME) + _started = _started & ~WIFI_STA_SET_HOST_NAME; + + // Handle WiFi select channel + if (stopping & WIFI_SELECT_CHANNEL) + _started = _started & ~(stopping & WIFI_SELECT_CHANNEL); + + // Handle WiFi station select remote AP + if (stopping & WIFI_STA_SELECT_REMOTE_AP) + _started = _started & ~WIFI_STA_SELECT_REMOTE_AP; + + // Handle WiFi station scan + if (stopping & WIFI_STA_START_SCAN) + _started = _started & ~WIFI_STA_START_SCAN; + + // Stop the WiFi station radio protocols + if (stopping & WIFI_STA_SET_PROTOCOLS) + _started = _started & ~WIFI_STA_SET_PROTOCOLS; + + // Stop station mode + if (stopping & (WIFI_EN_SET_MODE | WIFI_STA_SET_MODE)) + { + // Determine which bits to clear + mask = ~(stopping & (WIFI_EN_SET_MODE | WIFI_STA_SET_MODE)); + + // Stop WiFi station if users are gone + if (!(_started & mask & (WIFI_EN_SET_MODE | WIFI_STA_SET_MODE))) + { + if (!setWiFiMode(WIFI_MODE_STA, WIFI_MODE_STA)) + break; + } + + // Remove this WiFi station user + _started = _started & mask; + } + + //**************************************** + // Stop the soft AP components + //**************************************** + + // Stop soft AP mode + // Mark the soft AP offline + if (stopping & WIFI_AP_ONLINE) + { + if (softApOnline()) + systemPrintf("WiFi: Soft AP offline!\r\n"); + _started = _started & ~WIFI_AP_ONLINE; + } + + // Stop the DNS server + if (stopping & _started & WIFI_AP_START_DNS_SERVER) + { + if (settings.debugWifiState && _verbose) + systemPrintf("Calling dnsServer.stop for soft AP\r\n"); + dnsServer.stop(); + _started = _started & ~WIFI_AP_START_DNS_SERVER; + } + + // Stop mDNS + if (stopping & WIFI_AP_START_MDNS) + { + _started = _started & ~WIFI_AP_START_MDNS; + if (settings.debugWifiState && _verbose) + systemPrintf("Calling networkMulticastDNSStop for soft AP\r\n"); + networkMulticastDNSStop(NETWORK_WIFI); + } + + // Handle the soft AP host name + if (stopping & WIFI_AP_SET_HOST_NAME) + _started = _started & ~WIFI_AP_SET_HOST_NAME; + + // Stop soft AP mode + if (stopping & WIFI_AP_SET_MODE) + { + if (!setWiFiMode(WIFI_MODE_AP, WIFI_MODE_AP)) + break; + _started = _started & ~WIFI_AP_SET_MODE; + } + + // Disable the radio protocols for soft AP + if (stopping & WIFI_AP_SET_PROTOCOLS) + _started = _started & ~WIFI_AP_SET_PROTOCOLS; + + // Stop using the soft AP IP address + if (stopping & WIFI_AP_SET_IP_ADDR) + _started = _started & ~WIFI_AP_SET_IP_ADDR; + + // Stop use of SSID and password + if (stopping & WIFI_AP_SET_SSID_PASSWORD) + _started = _started & ~WIFI_AP_SET_SSID_PASSWORD; - if (wifiFailedConnectionAttempts > 2) - return true; + stillRunning = _started; - return false; + //**************************************** + // Channel reset + //**************************************** + + // Reset the channel if all components are stopped + if ((softApOnline() == false) && (stationOnline() == false)) + _channel = 0; + + //**************************************** + // Delay to allow mDNS to shutdown and restart properly + //**************************************** + + delay(100); + + //**************************************** + // Display the items already started and being started + //**************************************** + + if (settings.debugWifiState && _verbose && _started) + displayComponents("Started", _started); + + if (settings.debugWifiState && _verbose && startingNow) + displayComponents("Starting", startingNow); + + //**************************************** + // Start the radio operations + //**************************************** + + // Start the soft AP mode + if (starting & WIFI_AP_SET_MODE) + { + if (!setWiFiMode(WIFI_MODE_AP, 0)) + break; + _started = _started | WIFI_AP_SET_MODE; + } + + // Start the station mode + if (starting & (WIFI_EN_SET_MODE | WIFI_STA_SET_MODE)) + { + if (!setWiFiMode(WIFI_MODE_STA, 0)) + break; + _started = _started | (starting & (WIFI_EN_SET_MODE | WIFI_STA_SET_MODE)); + } + + // Start the soft AP protocols + if (starting & WIFI_AP_SET_PROTOCOLS) + { + if (!setWiFiProtocols(WIFI_IF_AP, true, false)) + break; + _started = _started | WIFI_AP_SET_PROTOCOLS; + } + + // Start the WiFi station radio protocols + if (starting & (WIFI_EN_SET_PROTOCOLS | WIFI_STA_SET_PROTOCOLS)) + { + bool lrEnable = (starting & WIFI_EN_SET_PROTOCOLS) ? true : false; + if (!setWiFiProtocols(WIFI_IF_STA, true, lrEnable)) + break; + _started = _started | (starting & (WIFI_EN_SET_PROTOCOLS | WIFI_STA_SET_PROTOCOLS)); + } + + // Start the WiFi scan for remote APs + if (starting & WIFI_STA_START_SCAN) + { + if (settings.debugWifiState && _verbose) + systemPrintf("channel: %d\r\n", channel); + _started = _started | WIFI_STA_START_SCAN; + + // Determine if WiFi scan failed, stop WiFi station startup + if (wifi.stationScanForAPs(channel) < 0) + { + starting &= ~WIFI_STA_FAILED_SCAN; + starting |= ((_started | starting) & WIFI_AP_ONLINE) ? WIFI_AP_START_MDNS : 0; + stopping &= ~WIFI_AP_START_MDNS; + notStarted |= WIFI_STA_FAILED_SCAN; + } + } + + // Select an AP from the list + if (starting & WIFI_STA_SELECT_REMOTE_AP) + { + channel = stationSelectAP(_apCount, false); + _started = _started | WIFI_STA_SELECT_REMOTE_AP; + if (channel == 0) + { + if (_channel) + systemPrintf("WiFi STA: No compatible remote AP found on channel %d!\r\n", _channel); + else + systemPrintf("WiFi STA: No compatible remote AP found!\r\n"); + + // Stop bringing up WiFi station + starting &= ~WIFI_STA_NO_REMOTE_AP; + starting |= ((_started | starting) & WIFI_AP_ONLINE) ? WIFI_AP_START_MDNS : 0; + stopping &= ~WIFI_AP_START_MDNS; + notStarted |= WIFI_STA_FAILED_SCAN; + } + } + + // Finish the channel selection + if (starting & WIFI_SELECT_CHANNEL) + { + _started = _started | starting & WIFI_SELECT_CHANNEL; + if (channel & (starting & WIFI_STA_START_SCAN)) + { + if (settings.debugWifiState && _verbose) + systemPrintf("Channel: %d, determined by remote AP scan\r\n", + channel); + } + + // Use the default channel if necessary + if (!channel) + channel = WIFI_DEFAULT_CHANNEL; + _channel = channel; + + // Display the selected channel + if (settings.debugWifiState) + systemPrintf("Channel: %d selected\r\n", _channel); + } + + //**************************************** + // Start the soft AP components + //**************************************** + + // Set the soft AP SSID and password + if (starting & WIFI_AP_SET_SSID_PASSWORD) + { + if (!softApSetSsidPassword(wifiSoftApSsid, wifiSoftApPassword)) + break; + _started = _started | WIFI_AP_SET_SSID_PASSWORD; + } + + // Set the soft AP subnet mask, IP, gateway, DNS, and first DHCP addresses + if (starting & WIFI_AP_SET_IP_ADDR) + { + if (!softApSetIpAddress(_apIpAddress.toString().c_str(), + _apSubnetMask.toString().c_str(), + _apGatewayAddress.toString().c_str(), + _apDnsAddress.toString().c_str(), + _apFirstDhcpAddress.toString().c_str())) + { + break; + } + _started = _started | WIFI_AP_SET_IP_ADDR; + } + + // Get the soft AP MAC address + WiFi.AP.macAddress(_apMacAddress); + + // Set the soft AP host name + if (starting & WIFI_AP_SET_HOST_NAME) + { + // Display the host name + if (settings.debugWifiState && _verbose) + systemPrintf("_hostName: %p%s%s%s\r\n", _hostName, + _hostName ? " (" : "", + _hostName ? _hostName : "", + _hostName ? ")" : ""); + + // Set the host name + if (_hostName && (!softApSetHostName(_hostName))) + break; + _started = _started | WIFI_AP_SET_HOST_NAME; + } + + // Start mDNS for the AP network + if (starting & WIFI_AP_START_MDNS) + { + if (settings.debugWifiState) + systemPrintf("Starting mDNS on soft AP\r\n"); + if (!networkMulticastDNSStart(NETWORK_WIFI)) + { + systemPrintf("ERROR: Failed to start mDNS for soft AP!\r\n"); + break; + } + if (settings.debugWifiState) + { + systemPrintf("mDNS started on soft AP as %s.local (%s)\r\n", + _hostName, + _apIpAddress.toString().c_str()); + } + _started = _started | WIFI_AP_START_MDNS; + } + + // Start the DNS server + if (starting & WIFI_AP_START_DNS_SERVER) + { + if (settings.debugWifiState) + systemPrintf("Starting DNS on soft AP\r\n"); + if (dnsServer.start(53, "*", WiFi.softAPIP()) == false) + { + systemPrintf("ERROR: Failed to start DNS Server for soft AP\r\n"); + break; + } + if (settings.debugWifiState) + systemPrintf("DNS Server started for soft AP\r\n"); + _started = _started | WIFI_AP_START_DNS_SERVER; + } + + // Mark the soft AP as online + if (starting & WIFI_AP_ONLINE) + { + _started = _started | WIFI_AP_ONLINE; + + // Display the soft AP status + String mdnsName(""); + if (_started & WIFI_AP_START_MDNS) + mdnsName = String(", local.") + String(_hostName); + systemPrintf("WiFi: Soft AP online, SSID: %s (%s%s), Password: %s\r\n", + wifiSoftApSsid, + _apIpAddress.toString().c_str(), + mdnsName, + wifiSoftApPassword); + } + + //**************************************** + // Start the WiFi station components + //**************************************** + + // Set the host name + if (starting & WIFI_STA_SET_HOST_NAME) + { + // Display the host name + if (settings.debugWifiState && _verbose) + systemPrintf("_hostName: %p%s%s%s\r\n", _hostName, + _hostName ? " (" : "", + _hostName ? _hostName : "", + _hostName ? ")" : ""); + + // Set the host name + if (_hostName && (!stationHostName(_hostName))) + break; + _started = _started | WIFI_STA_SET_HOST_NAME; + } + + // Disable auto reconnect + if (starting & WIFI_STA_DISABLE_AUTO_RECONNECT) + { + if (!WiFi.setAutoReconnect(false)) + { + systemPrintf("ERROR: Failed to disable auto-reconnect!\r\n"); + break; + } + _started = _started | WIFI_STA_DISABLE_AUTO_RECONNECT; + if (settings.debugWifiState) + systemPrintf("WiFi auto-reconnect disabled\r\n"); + } + + // Connect to the remote AP + if (starting & WIFI_STA_CONNECT_TO_REMOTE_AP) + { + IPAddress ipAddress; + uint32_t timer; + + if (!stationConnectAP()) + break; + _started = _started | WIFI_STA_CONNECT_TO_REMOTE_AP; + + // Wait for an IP address + ipAddress = WiFi.STA.localIP(); + timer = millis(); + while (!(uint32_t)ipAddress) + { + if ((millis() - timer) >= WIFI_IP_ADDRESS_TIMEOUT_MSEC) + break; + delay(10); + ipAddress = WiFi.STA.localIP(); + } + if ((millis() - timer) >= WIFI_IP_ADDRESS_TIMEOUT_MSEC) + { + systemPrintf("ERROR: Failed to get WiFi station IP address!\r\n"); + break; + } + + // Save the IP address + _staHasIp = true; + _staIpAddress = WiFi.STA.localIP(); + _staIpType = (_staIpAddress.type() == IPv4) ? '4' : '6'; + } + + // Start mDNS for the WiFi station + if (starting & WIFI_STA_START_MDNS) + { + if (settings.debugWifiState) + systemPrintf("Starting mDNS on WiFi station\r\n"); + if (!networkMulticastDNSStart(NETWORK_WIFI)) + systemPrintf("ERROR: Failed to start mDNS for WiFi station!\r\n"); + else + { + if (settings.debugWifiState) + systemPrintf("mDNS started on WiFi station as %s.local (%s)\r\n", + _hostName, + _staIpAddress.toString().c_str()); + _started = _started | WIFI_STA_START_MDNS; + } + } + + // Mark the station online + if (starting & WIFI_STA_ONLINE) + { + _started = _started | WIFI_STA_ONLINE; + String mdnsName(""); + if (_hostName && (_started & WIFI_STA_START_MDNS)) + mdnsName = String(", local.") + String(_hostName); + systemPrintf("WiFi: Station online (%s: %s%s)\r\n", + _staRemoteApSsid, _staIpAddress.toString().c_str(), + mdnsName); + } + + //**************************************** + // Start the ESP-NOW components + //**************************************** + + // Select the ESP-NOW channel + if (starting & WIFI_EN_SET_CHANNEL) + { + if (settings.debugWifiState && _verbose) + systemPrintf("Calling esp_wifi_get_channel\r\n"); + status = esp_wifi_get_channel(&primaryChannel, &secondaryChannel); + if (status != ESP_OK) + { + systemPrintf("ERROR: Failed to get the WiFi channels, status: %d\r\n", status); + break; + } + if (settings.debugWifiState && _verbose) + { + systemPrintf("primaryChannel: %d\r\n", primaryChannel); + systemPrintf("secondaryChannel: %d (%s)\r\n", secondaryChannel, + (secondaryChannel == WIFI_SECOND_CHAN_NONE) ? "None" + : ((secondaryChannel == WIFI_SECOND_CHAN_ABOVE) ? "Above" + : "Below")); + } + + // Set the ESP-NOW channel + if (primaryChannel != _channel) + { + if (settings.debugWifiState && _verbose) + systemPrintf("Calling esp_wifi_set_channel\r\n"); + status = esp_wifi_set_channel(primaryChannel, secondaryChannel); + if (status != ESP_OK) + { + systemPrintf("ERROR: Failed to set WiFi primary channel to %d, status: %d\r\n", primaryChannel, status); + break; + } + if (settings.debugWifiState) + systemPrintf("WiFi: Set channel %d\r\n", primaryChannel); + } + _started = _started | WIFI_EN_SET_CHANNEL; + } + + // Set promiscuous mode + if (starting & WIFI_EN_SET_PROMISCUOUS_MODE) + { + if (settings.debugWifiState && _verbose) + systemPrintf("Calling esp_wifi_set_promiscuous\r\n"); + status = esp_wifi_set_promiscuous(true); + if (status != ESP_OK) + { + systemPrintf("ERROR: Failed to set WiFi promiscuous mode, status: %d\r\n", status); + break; + } + if (settings.debugWifiState && _verbose) + systemPrintf("WiFi: Enabled promiscuous mode\r\n"); + _started = _started | WIFI_EN_SET_PROMISCUOUS_MODE; + } + + // Set promiscuous receive callback to get RSSI of action frames + if (starting & WIFI_EN_PROMISCUOUS_RX_CALLBACK) + { + if (settings.debugWifiState && _verbose) + systemPrintf("Calling esp_wifi_set_promiscuous_rx_cb\r\n"); + status = esp_wifi_set_promiscuous_rx_cb(wifiPromiscuousRxHandler); + if (status != ESP_OK) + { + systemPrintf("ERROR: Failed to set the WiFi promiscuous RX callback, status: %d\r\n", status); + break; + } + if (settings.debugWifiState && _verbose) + systemPrintf("WiFi: Promiscuous RX callback established\r\n"); + _started = _started | WIFI_EN_PROMISCUOUS_RX_CALLBACK; + } + + // Start ESP-NOW + if (starting & WIFI_EN_START_ESP_NOW) + { + if (settings.debugWifiState && _verbose) + systemPrintf("Calling espNowStart\r\n"); + if (!espNowStart()) + { + systemPrintf("ERROR: Failed to start ESP-NOW\r\n"); + break; + } + if (settings.debugWifiState) + systemPrintf("WiFi: ESP-NOW started\r\n"); + _started = _started | WIFI_EN_START_ESP_NOW; + } + + // Mark ESP-NOW online + if (starting & WIFI_EN_ESP_NOW_ONLINE) + { + _started = _started | WIFI_EN_ESP_NOW_ONLINE; + systemPrintf("WiFi: ESP-NOW online (%02x:%02x:%02x:%02x:%02x:%02x, channel: %d)\r\n", + _staMacAddress[0], _staMacAddress[1], _staMacAddress[2], + _staMacAddress[3], _staMacAddress[4], _staMacAddress[5], + _channel); + } + + // All components started successfully + enabled = true; + } while (0); + + //**************************************** + // Display the items that were not stopped + //**************************************** + if (settings.debugWifiState && _verbose) + { + systemPrintf("0x%08x: stopping\r\n", stopping); + systemPrintf("0x%08x: stillRunning\r\n", stillRunning); + } + + // Determine which components were not stopped + stopping &= stillRunning; + if (settings.debugWifiState && stopping) + displayComponents("ERROR: Items NOT stopped", stopping); + + //**************************************** + // Display the items that were not started + //**************************************** + + if (settings.debugWifiState && _verbose && _verbose) + { + systemPrintf("0x%08x: startingNow\r\n", startingNow); + systemPrintf("0x%08x: _started\r\n", _started); + } + startingNow &= ~_started; + if (settings.debugWifiState && startingNow) + displayComponents("ERROR: Items NOT started", startingNow); + + //**************************************** + // Display the items that were not started + //**************************************** + + if (settings.debugWifiState && _verbose) + { + systemPrintf("0x%08x: startingNow\r\n", startingNow); + systemPrintf("0x%08x: _started\r\n", _started); + } + + // Clear the items that were not started + _started = _started & ~notStarted; + + if (settings.debugWifiState && _verbose && _started) + displayComponents("Started items", _started); + + // Return the enable status + if (!enabled) + systemPrintf("ERROR: RTK_WIFI::enable failed!\r\n"); + return enabled; +} + +//********************************************************************* +// Test the WiFi modes +void RTK_WIFI::test(uint32_t testDurationMsec) +{ + uint32_t currentMsec; + bool disconnectFirst; + static uint32_t lastScanMsec = - (1000 * 1000); + int rand; + + // Delay the mode change until after the WiFi scan completes + currentMsec = millis(); + if (_scanRunning) + lastScanMsec = currentMsec; + + // Check if it time for a mode change + else if ((currentMsec - lastScanMsec) < testDurationMsec) + return; + + // Perform the test + lastScanMsec = currentMsec; + + // Get a random number + rand = random() & 0x1f; + disconnectFirst = (rand & 0x10) ? true : false; + + // Determine the next actions + switch (rand) + { + default: + lastScanMsec = currentMsec - (1000 * 1000); + break; + + case 0: + systemPrintf("-------------------- %d: All Stop --------------------\r\n", rand); + enable(false, false, false); + break; + + case 1: + systemPrintf("-------------------- %d: STA Start -------------------\r\n", rand); + enable(false, false, true); + break; + + case 2: + systemPrintf("-------------------- %d: STA Disconnect --------------\r\n", rand); + wifi.stationDisconnect(); + break; + + case 4: + systemPrintf("-------------------- %d: Soft AP Start -------------------\r\n", rand); + enable(false, true, false); + break; + + case 5: + systemPrintf("-------------------- %d: Soft AP & STA Start --------------------\r\n", rand); + enable(false, true, true); + break; + + case 6: + systemPrintf("-------------------- %d: Soft AP Start, STA Disconnect -------------------\r\n", rand); + if (disconnectFirst) + wifi.stationDisconnect(); + enable(false, true, false); + if (!disconnectFirst) + wifi.stationDisconnect(); + break; + + case 8: + systemPrintf("-------------------- %d: ESP-NOW Start --------------------\r\n", rand); + enable(true, false, false); + break; + + case 9: + systemPrintf("-------------------- %d: ESP-NOW & STA Start -------------------\r\n", rand); + enable(true, false, true); + break; + + case 0xa: + systemPrintf("-------------------- %d: ESP-NOW Start, STA Disconnect --------------\r\n", rand); + if (disconnectFirst) + wifi.stationDisconnect(); + enable(true, false, false); + if (!disconnectFirst) + wifi.stationDisconnect(); + break; + + case 0xc: + systemPrintf("-------------------- %d: ESP-NOW & Soft AP Start -------------------\r\n", rand); + enable(true, true, false); + break; + + case 0xd: + systemPrintf("-------------------- %d: ESP-NOW, Soft AP & STA Start --------------------\r\n", rand); + enable(true, true, true); + break; + + case 0xe: + systemPrintf("-------------------- %d: ESP-NOW & Soft AP Start, STA Disconnect -------------------\r\n", rand); + if (disconnectFirst) + wifi.stationDisconnect(); + enable(true, true, false); + if (!disconnectFirst) + wifi.stationDisconnect(); + break; + } +} + +//********************************************************************* +// Enable or disable verbose debug output +// Inputs: +// enable: Set true to enable verbose debug output +// Outputs: +// Return the previous enable value +bool RTK_WIFI::verbose(bool enable) +{ + bool oldVerbose; + + oldVerbose = _verbose; + _verbose = enable; + return oldVerbose; +} + +//********************************************************************* +// Verify the WiFi tables +void RTK_WIFI::verifyTables() +{ + // Verify the authorization name table + if (WIFI_AUTH_MAX != wifiAuthorizationNameEntries) + { + systemPrintf("ERROR: Fix wifiAuthorizationName list to match wifi_auth_mode_t in esp_wifi_types.h!\r\n"); + while (1) + { + } + } + + // Verify the Arduino event name table + if (ARDUINO_EVENT_MAX != arduinoEventNameEntries) + { + systemPrintf("ERROR: Fix arduinoEventName list to match arduino_event_id_t in NetworkEvents.h!\r\n"); + while (1) + { + } + } + + // Verify the start name table + if (WIFI_MAX_START != (1 << wifiStartNamesEntries)) + { + systemPrintf("ERROR: Fix wifiStartNames list to match list of defines!\r\n"); + while (1) + { + } + } } -#endif // COMPILE_WIFI +#endif // COMPILE_WIFI diff --git a/Firmware/RTK_Everywhere/WiFi_old.ino b/Firmware/RTK_Everywhere/WiFi_old.ino new file mode 100644 index 000000000..6dc9de890 --- /dev/null +++ b/Firmware/RTK_Everywhere/WiFi_old.ino @@ -0,0 +1,751 @@ +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + WiFi Status Values: + WL_CONNECTED: assigned when connected to a WiFi network + WL_CONNECTION_LOST: assigned when the connection is lost + WL_CONNECT_FAILED: assigned when the connection fails for all the attempts + WL_DISCONNECTED: assigned when disconnected from a network + WL_IDLE_STATUS: it is a temporary status assigned when WiFi.begin() is called and + remains active until the number of attempts expires (resulting in + WL_CONNECT_FAILED) or a connection is established (resulting in + WL_CONNECTED) + WL_NO_SHIELD: assigned when no WiFi shield is present + WL_NO_SSID_AVAIL: assigned when no SSID are available + WL_SCAN_COMPLETED: assigned when the scan networks is completed + =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +//---------------------------------------- +// Globals +//---------------------------------------- + +int wifiFailedConnectionAttempts = 0; // Count the number of connection attempts between restarts + +bool restartWiFi = false; // Restart WiFi if user changes anything + +#ifdef COMPILE_WIFI + +WiFiMulti *wifiMulti; + +//---------------------------------------- +// Constants +//---------------------------------------- + +#define WIFI_MAX_TIMEOUT (15 * 60 * 1000) +#define WIFI_MIN_TIMEOUT (15 * 1000) + +//---------------------------------------- +// Locals +//---------------------------------------- + +// Start timeout +static uint32_t wifiStartTimeout; +static uint32_t wifiStartLastTry; // The last time WiFi start was attempted + +// WiFi Timer usage: +// * Measure interval to display IP address +static unsigned long wifiDisplayTimer; + +// DNS server for Captive Portal +extern DNSServer dnsServer; + +static bool wifiStationRunning; +static bool wifiApRunning; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// WiFi Routines +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +//---------------------------------------- +// Set WiFi credentials +// Enable TCP connections +//---------------------------------------- +void menuWiFi() +{ + while (1) + { + networkDisplayInterface(NETWORK_WIFI); + + systemPrintln(); + systemPrintln("Menu: WiFi Networks"); + + for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + { + systemPrintf("%d) SSID %d: %s\r\n", (x * 2) + 1, x + 1, settings.wifiNetworks[x].ssid); + systemPrintf("%d) Password %d: %s\r\n", (x * 2) + 2, x + 1, settings.wifiNetworks[x].password); + } + + systemPrint("a) Configure device via WiFi Access Point or connect to WiFi: "); + systemPrintf("%s\r\n", settings.wifiConfigOverAP ? "AP" : "WiFi"); + + systemPrint("c) Captive Portal: "); + systemPrintf("%s\r\n", settings.enableCaptivePortal ? "Enabled" : "Disabled"); + + systemPrintln("x) Exit"); + + byte incoming = getUserInputCharacterNumber(); + + if (incoming >= 1 && incoming <= MAX_WIFI_NETWORKS * 2) + { + int arraySlot = ((incoming - 1) / 2); // Adjust incoming to array starting at 0 + + if (incoming % 2 == 1) + { + systemPrintf("Enter SSID network %d: ", arraySlot + 1); + getUserInputString(settings.wifiNetworks[arraySlot].ssid, + sizeof(settings.wifiNetworks[arraySlot].ssid)); + restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi + } + else + { + systemPrintf("Enter Password for %s: ", settings.wifiNetworks[arraySlot].ssid); + getUserInputString(settings.wifiNetworks[arraySlot].password, + sizeof(settings.wifiNetworks[arraySlot].password)); + restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi + } + } + else if (incoming == 'a') + { + settings.wifiConfigOverAP ^= 1; + restartWiFi = true; + } + else if (incoming == 'c') + { + settings.enableCaptivePortal ^= 1; + } + else if (incoming == 'x') + break; + else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_EMPTY) + break; + else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_TIMEOUT) + break; + else + printUnknown(incoming); + } + + // Erase passwords from empty SSID entries + for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + { + if (strlen(settings.wifiNetworks[x].ssid) == 0) + strcpy(settings.wifiNetworks[x].password, ""); + } + + clearBuffer(); // Empty buffer of any newline chars +} + +//---------------------------------------- +// Starts WiFi in STA, AP, or STA_AP mode depending on bools +// Returns true if STA connects, or if AP is started +//---------------------------------------- +bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) +{ + // Is a change needed? + if (startWiFiStation && startWiFiAP && WiFi.getMode() == WIFI_AP_STA && WiFi.status() == WL_CONNECTED) + return (true); // There is nothing needing to be changed + + if (startWiFiStation && WiFi.getMode() == WIFI_STA && WiFi.status() == WL_CONNECTED) + return (true); // There is nothing needing to be changed + + if (startWiFiAP && WiFi.getMode() == WIFI_AP) + return (true); // There is nothing needing to be changed + + wifiStationRunning = false; // Mark it as offline while we mess about + wifiApRunning = false; // Mark it as offline while we mess about + + wifi_mode_t wifiMode = WIFI_OFF; + wifi_interface_t wifiInterface = WIFI_IF_STA; + + // Establish what WiFi mode we need to be in + if (startWiFiStation && startWiFiAP) + { + systemPrintln("Starting WiFi AP+Station"); + wifiMode = WIFI_AP_STA; + wifiInterface = WIFI_IF_AP; // There is no WIFI_IF_AP_STA + } + else if (startWiFiStation) + { + systemPrintln("Starting WiFi Station"); + wifiMode = WIFI_STA; + wifiInterface = WIFI_IF_STA; + } + else if (startWiFiAP) + { + systemPrintln("Starting WiFi AP"); + wifiMode = WIFI_AP; + wifiInterface = WIFI_IF_AP; + } + + displayWiFiConnect(); + + if (WiFi.mode(wifiMode) == false) // Start WiFi in the appropriate mode + { + systemPrintln("WiFi failed to set mode"); + return (false); + } + + // Verify that the necessary protocols are set + uint8_t protocols = 0; + esp_err_t response = esp_wifi_get_protocol(wifiInterface, &protocols); + if (response != ESP_OK) + systemPrintf("Failed to get protocols: %s\r\n", esp_err_to_name(response)); + + // If ESP-NOW is running, blend in ESP-NOW protocol. + if (espnowState > ESPNOW_OFF) + { + if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR)) + { + esp_err_t response = + esp_wifi_set_protocol(wifiInterface, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | + WIFI_PROTOCOL_LR); // Enable WiFi + ESP-Now. + if (response != ESP_OK) + systemPrintf("Error setting WiFi + ESP-NOW protocols: %s\r\n", esp_err_to_name(response)); + } + } + else + { + // Make sure default WiFi protocols are in place + if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N)) + { + esp_err_t response = esp_wifi_set_protocol(wifiInterface, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | + WIFI_PROTOCOL_11N); // Enable WiFi. + if (response != ESP_OK) + systemPrintf("Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); + } + } + + // Start AP with fixed IP + if (wifiMode == WIFI_AP || wifiMode == WIFI_AP_STA) + { + IPAddress local_IP(192, 168, 4, 1); + IPAddress gateway(192, 168, 4, 1); + IPAddress subnet(255, 255, 255, 0); + + WiFi.softAPConfig(local_IP, gateway, subnet); + + // Determine the AP name + // If in web config mode then 'RTK Config' + // otherwise 'RTK Caster' + + char softApSsid[strlen("RTK Config")]; // Must be short enough to fit OLED Width + + if (inWebConfigMode()) + strncpy(softApSsid, "RTK Config", sizeof(softApSsid)); + // snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Config"); // TODO use + // settings.webconfigApName + else + strncpy(softApSsid, "RTK Caster", sizeof(softApSsid)); + // snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Caster"); + + if (WiFi.softAP(softApSsid) == false) + { + systemPrintln("WiFi AP failed to start"); + return (false); + } + systemPrintf("WiFi AP '%s' started with IP: ", softApSsid); + systemPrintln(WiFi.softAPIP()); + + // Start DNS Server + if (dnsServer.start(53, "*", WiFi.softAPIP()) == false) + { + systemPrintln("WiFi DNS Server failed to start"); + return (false); + } + else + { + if (settings.debugWifiState == true) + systemPrintln("DNS Server started"); + } + + wifiApRunning = true; + + // If we're only here to start the AP, then we're done + if (wifiMode == WIFI_AP) + return true; + } + + systemPrintln("Connecting to WiFi... "); + + if (wifiMulti == nullptr) + wifiMulti = new WiFiMulti; + + // Load SSIDs + wifiMulti->APlistClean(); + for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + { + if (strlen(settings.wifiNetworks[x].ssid) > 0) + wifiMulti->addAP((const char *)&settings.wifiNetworks[x].ssid, + (const char *)&settings.wifiNetworks[x].password); + } + + int wifiStatus = wifiMulti->run(timeout); + if (wifiStatus == WL_CONNECTED) + { + wifiResetTimeout(); // If we successfully connected then reset the throttling timeout + wifiStationRunning = true; + return true; + } + if (wifiStatus == WL_DISCONNECTED) + systemPrint("No friendly WiFi networks detected.\r\n"); + else + { + systemPrintf("WiFi failed to connect: error #%d - %s\r\n", wifiStatus, wifiPrintState((wl_status_t)wifiStatus)); + } + wifiStationRunning = false; + return false; +} + +//---------------------------------------- +// Display the WiFi state +//---------------------------------------- +void wifiDisplayState() +{ + systemPrintf("WiFi: %s\r\n", networkInterfaceHasInternet(NETWORK_WIFI) ? "Online" : "Offline"); + systemPrintf(" MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\r\n", wifiMACAddress[0], wifiMACAddress[1], + wifiMACAddress[2], wifiMACAddress[3], wifiMACAddress[4], wifiMACAddress[5]); + if (networkInterfaceHasInternet(NETWORK_WIFI)) + { + // Get the DNS addresses + IPAddress dns1 = WiFi.STA.dnsIP(0); + IPAddress dns2 = WiFi.STA.dnsIP(1); + IPAddress dns3 = WiFi.STA.dnsIP(2); + + // Get the WiFi status + wl_status_t wifiStatus = WiFi.status(); + + const char *wifiStatusString = wifiPrintState(wifiStatus); + + // Display the WiFi state + systemPrintf(" SSID: %s\r\n", WiFi.STA.SSID()); + systemPrintf(" IP Address: %s\r\n", WiFi.STA.localIP().toString().c_str()); + systemPrintf(" Subnet Mask: %s\r\n", WiFi.STA.subnetMask().toString().c_str()); + systemPrintf(" Gateway Address: %s\r\n", WiFi.STA.gatewayIP().toString().c_str()); + if ((uint32_t)dns3) + systemPrintf(" DNS Address: %s, %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str(), + dns3.toString().c_str()); + else if ((uint32_t)dns3) + systemPrintf(" DNS Address: %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str()); + else + systemPrintf(" DNS Address: %s\r\n", dns1.toString().c_str()); + systemPrintf(" WiFi Strength: %d dBm\r\n", WiFi.RSSI()); + systemPrintf(" WiFi Status: %d\r\n", wifiStatusString); + } +} + +//---------------------------------------- +// Process the WiFi events +//---------------------------------------- +void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) +{ + char ssid[sizeof(info.wifi_sta_connected.ssid) + 1]; + IPAddress ipAddress; + + // If we are in AP or AP_STA, the network is immediately marked online + // Once AP is online, don't stop WiFi because STA has various events + if (WiFi.getMode() == WIFI_MODE_STA) + { + // Take the network offline if necessary + if (networkInterfaceHasInternet(NETWORK_WIFI) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP) && + (event != ARDUINO_EVENT_WIFI_STA_GOT_IP6)) + { + if (settings.debugWifiState) + systemPrintf("Stopping WiFi because of event # %d\r\n", event); + + networkStop(NETWORK_WIFI, settings.debugNetworkLayer); // Stop WiFi to allow it to restart + } + } + + // WiFi State Machine + // + // .--------+<----------+<-----------+<-------------+<----------+<----------+<------------. + // v | | | | | | | + // STOP --> READY --> STA_START --> SCAN_DONE --> CONNECTED --> GOT_IP --> LOST_IP --> DISCONNECTED + // ^ ^ | | + // | '-----------' | + // '-------------------------------------' + // + // Handle the event + switch (event) + { + default: + systemPrintf("ERROR: Unknown WiFi event: %d\r\n", event); + break; + + case ARDUINO_EVENT_WIFI_OFF: + systemPrintln("WiFi Off"); + break; + + case ARDUINO_EVENT_WIFI_READY: + if (settings.debugWifiState) + systemPrintln("WiFi Ready"); + WiFi.setHostname(settings.mdnsHostName); + break; + + case ARDUINO_EVENT_WIFI_SCAN_DONE: + if (settings.debugWifiState) + systemPrintln("WiFi Scan Done"); + // wifi_event_sta_scan_done_t info.wifi_scan_done; + break; + + case ARDUINO_EVENT_WIFI_STA_START: + if (settings.debugWifiState) + systemPrintln("WiFi STA Started"); + break; + + case ARDUINO_EVENT_WIFI_STA_STOP: + if (settings.debugWifiState) + systemPrintln("WiFi STA Stopped"); + break; + + case ARDUINO_EVENT_WIFI_STA_CONNECTED: + memcpy(ssid, info.wifi_sta_connected.ssid, info.wifi_sta_connected.ssid_len); + ssid[info.wifi_sta_connected.ssid_len] = 0; + + ipAddress = WiFi.localIP(); + systemPrintf("WiFi STA connected to %s with IP address: ", ssid); + systemPrintln(ipAddress); + + WiFi.setHostname(settings.mdnsHostName); + break; + + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: + memcpy(ssid, info.wifi_sta_disconnected.ssid, info.wifi_sta_disconnected.ssid_len); + ssid[info.wifi_sta_disconnected.ssid_len] = 0; + systemPrintf("WiFi STA disconnected from %s\r\n", ssid); + // wifi_event_sta_disconnected_t info.wifi_sta_disconnected; + break; + + case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: + systemPrintln("WiFi STA Auth Mode Changed"); + // wifi_event_sta_authmode_change_t info.wifi_sta_authmode_change; + break; + + case ARDUINO_EVENT_WIFI_STA_GOT_IP: + if (settings.debugWifiState) + { + ipAddress = WiFi.localIP(); + systemPrint("WiFi STA Got IPv4: "); + systemPrintln(ipAddress); + } + networkMarkHasInternet(NETWORK_WIFI); + break; + + case ARDUINO_EVENT_WIFI_STA_GOT_IP6: + if (settings.debugWifiState) + { + ipAddress = WiFi.localIP(); + systemPrint("WiFi STA Got IPv6: "); + systemPrintln(ipAddress); + } + networkMarkHasInternet(NETWORK_WIFI); + break; + + case ARDUINO_EVENT_WIFI_STA_LOST_IP: + systemPrintln("WiFi STA Lost IP"); + break; + } +} + +//---------------------------------------- +// Determine if WIFI is connected +//---------------------------------------- +bool wifiIsConnected() +{ + bool connected; + + connected = (WiFi.status() == WL_CONNECTED); + return connected; +} + +//---------------------------------------- +// Determine if WiFi Station is running +//---------------------------------------- +bool wifiStationIsRunning() +{ + return wifiStationRunning; +} + +//---------------------------------------- +// Determine if WiFi AP is running +//---------------------------------------- +bool wifiApIsRunning() +{ + return wifiApRunning; +} + +//---------------------------------------- +// Determine if either Station or AP is running +//---------------------------------------- +bool wifiIsRunning() +{ + if (wifiStationRunning || wifiApRunning) + return true; + return false; +} + +//---------------------------------------- +// Counts the number of entered SSIDs +//---------------------------------------- +int wifiNetworkCount() +{ + // Count SSIDs + int networkCount = 0; + for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + { + if (strlen(settings.wifiNetworks[x].ssid) > 0) + networkCount++; + } + return networkCount; +} + +//---------------------------------------- +// Given a status, return the associated state or error +//---------------------------------------- +const char *wifiPrintState(wl_status_t wifiStatus) +{ + switch (wifiStatus) + { + case WL_NO_SHIELD: + return ("WL_NO_SHIELD"); // 255 + case WL_STOPPED: + return ("WL_STOPPED"); + case WL_IDLE_STATUS: // 0 + return ("WL_IDLE_STATUS"); + case WL_NO_SSID_AVAIL: // 1 + return ("WL_NO_SSID_AVAIL"); + case WL_SCAN_COMPLETED: // 2 + return ("WL_SCAN_COMPLETED"); + case WL_CONNECTED: // 3 + return ("WL_CONNECTED"); + case WL_CONNECT_FAILED: // 4 + return ("WL_CONNECT_FAILED"); + case WL_CONNECTION_LOST: // 5 + return ("WL_CONNECTION_LOST"); + case WL_DISCONNECTED: // 6 + return ("WL_DISCONNECTED"); + } + return ("WiFi Status Unknown"); +} + +//---------------------------------------- +// Starts the WiFi connection state machine (moves from WIFI_STATE_OFF to WIFI_STATE_CONNECTING) +// Sets the appropriate protocols (WiFi + ESP-Now) +// If radio is off entirely, start WiFi +// If ESP-Now is active, only add the LR protocol +// Returns true if WiFi has connected and false otherwise +//---------------------------------------- +bool wifiStart() +{ + int wifiStatus; + + // Determine which parts of WiFi need to be started + bool startWiFiStation = false; + bool startWiFiAp = false; + + uint16_t consumerTypes = networkGetConsumerTypes(); + + // The consumers need station + if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) + startWiFiStation = true; + + // The consumers need AP + if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) + startWiFiAp = true; + + if (startWiFiStation == false && startWiFiAp == false) + { + systemPrintln("wifiStart() requested without any NETCONSUMER combination"); + WIFI_STOP(); + return (false); + } + + // Determine if WiFi is already running + if (startWiFiStation == wifiStationRunning && startWiFiAp == wifiApRunning) + { + if (settings.debugWifiState == true) + systemPrintln("WiFi is already running with requested setup"); + return (true); + } + + // Handle special cases if no networks have been entered + if (wifiNetworkCount() == 0) + { + if (startWiFiStation == true && startWiFiAp == false) + { + systemPrintln("Error: Please enter at least one SSID before using WiFi"); + displayNoSSIDs(2000); + WIFI_STOP(); + return false; + } + else if (startWiFiStation == true && startWiFiAp == true) + { + systemPrintln("Error: No SSID available to start WiFi Station during AP"); + // Allow the system to continue in AP only mode + startWiFiStation = false; + } + } + + // Start WiFi + wifiConnect(startWiFiStation, startWiFiAp, settings.wifiConnectTimeoutMs); + + // If we are in AP only mode, as long as the AP is started, return true + if (WiFi.getMode() == WIFI_MODE_AP) + return (wifiApIsRunning); + + // If we are in STA or AP+STA mode, return if the station connected successfully + wifiStatus = WiFi.status(); + return (wifiStatus == WL_CONNECTED); +} + +//---------------------------------------- +// Set WiFi timeout back to zero +// Useful if other things (such as a successful ethernet connection) need to reset wifi timeout +//---------------------------------------- +void wifiResetTimeout() +{ + wifiStartTimeout = 0; + if (settings.debugWifiState == true) + systemPrintln("WiFi: Start timeout reset to zero"); +} + +//---------------------------------------- +//---------------------------------------- +uint32_t wifiGetStartTimeout() +{ + return (wifiStartTimeout); +} + +//---------------------------------------- +// Reset the last WiFi start attempt +// Useful when WiFi settings have changed +//---------------------------------------- +void wifiResetThrottleTimeout() +{ + wifiStartLastTry = 0; +} + +//---------------------------------------- +// Start WiFi with throttling +//---------------------------------------- +void wifiThrottledStart(NetIndex_t index, uintptr_t parameter, bool debug) +{ + int seconds; + int minutes; + + // Restart delay + if ((millis() - wifiStartLastTry) < wifiStartTimeout) + return; + wifiStartLastTry = millis(); + + // Start WiFi + if (wifiStart()) + { + networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); + wifiFailedConnectionAttempts = 0; + } + else + { + // Increase the timeout + wifiStartTimeout <<= 1; + if (!wifiStartTimeout) + wifiStartTimeout = WIFI_MIN_TIMEOUT; + else if (wifiStartTimeout > WIFI_MAX_TIMEOUT) + wifiStartTimeout = WIFI_MAX_TIMEOUT; + + wifiFailedConnectionAttempts++; + + // Display the delay + seconds = wifiStartTimeout / MILLISECONDS_IN_A_SECOND; + minutes = seconds / SECONDS_IN_A_MINUTE; + seconds -= minutes * SECONDS_IN_A_MINUTE; + if (settings.debugWifiState) + systemPrintf("WiFi: Delaying %2d:%02d before restarting WiFi\r\n", minutes, seconds); + } +} + +//---------------------------------------- +// WiFi start sequence +//---------------------------------------- +NETWORK_POLL_SEQUENCE wifiStartSequence[] = { + // State Parameter Description + {wifiThrottledStart, 0, "Initialize WiFi"}, + {nullptr, 0, "Termination"}, +}; + +//---------------------------------------- +// WiFi stop sequence +//---------------------------------------- +NETWORK_POLL_SEQUENCE wifiStopSequence[] = { + // State Parameter Description + {wifiStop, 0, "Shutdown WiFi"}, + {nullptr, 0, "Termination"}, +}; + +//---------------------------------------- +// Stop WiFi and release all resources +//---------------------------------------- +void wifiStop() +{ + // Stop the web server + stopWebServer(); + + // Stop the DNS server if we were using the captive portal + if (((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) && settings.enableCaptivePortal) + dnsServer.stop(); + + wifiFailedConnectionAttempts = 0; // Reset the counter + + // If ESP-Now is active, change protocol to only Long Range + if (espnowState > ESPNOW_OFF) + { + if (WiFi.getMode() != WIFI_STA) + WiFi.mode(WIFI_STA); + + // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps + // esp_wifi_set_protocol requires WiFi to be started + esp_err_t response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); + if (response != ESP_OK) + systemPrintf("wifiShutdown: Error setting ESP-Now lone protocol: %s\r\n", esp_err_to_name(response)); + else + { + if (settings.debugWifiState == true) + systemPrintln("WiFi disabled, ESP-Now left in place"); + } + } + else + { + WiFi.mode(WIFI_OFF); + if (settings.debugWifiState == true) + systemPrintln("WiFi Stopped"); + } + + // Take the network offline + networkMarkOffline(NETWORK_WIFI); + + if (wifiMulti != nullptr) + wifiMulti = nullptr; + + // Display the heap state + reportHeapNow(settings.debugWifiState); + wifiStationRunning = false; + wifiApRunning = false; +} + +// Needed for wifiStopSequence +void wifiStop(NetIndex_t index, uintptr_t parameter, bool debug) +{ + wifiStop(); + networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); +} + +// Returns true if we deem WiFi is not going to connect +// Used to allow cellular to start +bool wifiUnavailable() +{ + if(wifiNetworkCount() == 0) + return true; + + if (wifiFailedConnectionAttempts > 2) + return true; + + return false; +} + +#endif // COMPILE_WIFI diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index e8325e5f5..37aead000 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -1898,5 +1898,361 @@ o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU rqXRfboQnoZsG4q5WTP468SQvvG5 -----END CERTIFICATE----- )====="; + +#ifdef COMPILE_WIFI + +//**************************************** +// WiFi class +//**************************************** + +// Handle the WiFi event +// Inputs: +// event: Arduino ESP32 event number found on +// https://github.com/espressif/arduino-esp32 +// in libraries/Network/src/NetworkEvents.h +// info: Additional data about the event +void wifiEventHandler(arduino_event_id_t event, arduino_event_info_t info); + +typedef uint32_t WIFI_ACTION_t; +typedef uint8_t WIFI_CHANNEL_t; + +// Class to simplify WiFi handling +class RTK_WIFI +{ + private: + + WIFI_CHANNEL_t _apChannel; // Channel required for soft AP, zero (0) use _channel + int16_t _apCount; // The number or remote APs detected in the WiFi network + IPAddress _apDnsAddress; // DNS IP address to use while translating names into IP addresses + IPAddress _apFirstDhcpAddress; // First IP address to use for DHCP + IPAddress _apGatewayAddress;// IP address of the gateway to the larger network (internet?) + IPAddress _apIpAddress; // IP address of the soft AP + uint8_t _apMacAddress[6]; // MAC address of the soft AP + IPAddress _apSubnetMask; // Subnet mask for soft AP + WIFI_CHANNEL_t _channel; // Current WiFi channel number + WIFI_CHANNEL_t _espNowChannel; // Channel required for ESPNow, zero (0) use _channel + bool _espNowRunning; // ESPNow started or running + const char * _hostName; // Name of this host + volatile bool _scanRunning; // Scan running + bool _softApRunning; // Soft AP is starting or running + int _staAuthType; // Authorization type for the remote AP + bool _staConnected; // True when station is connected + bool _staHasIp; // True when station has IP address + IPAddress _staIpAddress; // IP address of the station + uint8_t _staIpType; // 4 or 6 when IP address is assigned + uint8_t _staMacAddress[6]; // MAC address of the station + const char * _staRemoteApSsid; // SSID of remote AP + const char * _staRemoteApPassword; // Password of remote AP + volatile WIFI_ACTION_t _started; // Components that are started and running + WIFI_CHANNEL_t _stationChannel; // Channel required for station, zero (0) use _channel + bool _stationRunning; // True while station is starting or running + uint32_t _timer; // Reconnection timer + bool _verbose; // True causes more debug output to be displayed + + // Display components begin started or stopped + // Inputs: + // text: Text describing the component list + // components: A bit mask of the components + void displayComponents(const char * text, WIFI_ACTION_t components); + + // Start the WiFi event handler + void eventHandlerStart(); + + // Stop the WiFi event handler + void eventHandlerStop(); + + // Set the WiFi mode + // Inputs: + // setMode: Modes to set + // xorMode: Modes to toggle + // + // Math: result = (mode | setMode) ^ xorMode + // + // setMode + // 0 1 + // xorMode 0 No change Set bit + // 1 Toggle bit Clear bit + // + // Outputs: + // Returns true if successful and false upon failure + bool setWiFiMode(uint8_t setMode, uint8_t xorMode); + + // Set the WiFi radio protocols + // Inputs: + // interface: Interface on which to set the protocols + // enableWiFiProtocols: When true, enable the WiFi protocols + // enableLongRangeProtocol: When true, enable the long range protocol + // Outputs: + // Returns true if successful and false upon failure + bool setWiFiProtocols(wifi_interface_t interface, + bool enableWiFiProtocols, + bool enableLongRangeProtocol); + + // Handle the soft AP events + // Inputs: + // event: Arduino ESP32 event number found on + // https://github.com/espressif/arduino-esp32 + // in libraries/Network/src/NetworkEvents.h + // info: Additional data about the event + void softApEventHandler(arduino_event_id_t event, arduino_event_info_t info); + + // Set the soft AP host name + // Inputs: + // hostName: Zero terminated host name character string + // Outputs: + // Returns true if successful and false upon failure + bool softApSetHostName(const char * hostName); + + // Set the soft AP configuration + // Inputs: + // ipAddress: IP address of the server, nullptr or empty string causes + // default 192.168.4.1 to be used + // subnetMask: Subnet mask for local network segment, nullptr or empty + // string causes default 0.0.0.0 to be used, unless ipAddress + // is not specified, in which case 255.255.255.0 is used + // gatewayAddress: Gateway to internet IP address, nullptr or empty string + // causes default 0.0.0.0 to be used (no access to internet) + // dnsAddress: Domain name server (name to IP address translation) IP address, + // nullptr or empty string causes 0.0.0.0 to be used (only + // mDNS name translation, if started) + // dhcpStartAddress: Start of DHCP IP address assignments for the local + // network segment, nullptr or empty string causes default + // 0.0.0.0 to be used (disable DHCP server) unless ipAddress + // was not specified in which case 192.168.4.2 + // Outputs: + // Returns true if successful and false upon failure + bool softApSetIpAddress(const char * ipAddress, + const char * subnetMask, + const char * gatewayAddress, + const char * dnsAddress, + const char * dhcpFirstAddress); + + // Set the soft AP SSID and password + // Outputs: + // Returns true if successful and false upon failure + bool softApSetSsidPassword(const char * ssid, const char * password); + + // Connect to an access point + // Outputs: + // Return true if the connection was successful and false upon failure. + bool stationConnectAP(); + + // Disconnect the station from an AP + // Outputs: + // Returns true if successful and false upon failure + bool stationDisconnect(); + + // Handle the WiFi station events + // Inputs: + // event: Arduino ESP32 event number found on + // https://github.com/espressif/arduino-esp32 + // in libraries/Network/src/NetworkEvents.h + // info: Additional data about the event + void stationEventHandler(arduino_event_id_t event, arduino_event_info_t info); + + // Set the station's host name + // Inputs: + // hostName: Zero terminated host name character string + // Outputs: + // Returns true if successful and false upon failure + bool stationHostName(const char * hostName); + + // Start the WiFi scan + // Inputs: + // channel: Channel number for the scan, zero (0) scan all channels + // Outputs: + // Returns the number of access points + int16_t stationScanForAPs(WIFI_CHANNEL_t channel); + + // Select the AP and channel to use for WiFi station + // Inputs: + // apCount: Number to APs detected by the WiFi scan + // list: Determine if the APs should be listed + // Outputs: + // Returns the channel number of the AP + WIFI_CHANNEL_t stationSelectAP(uint8_t apCount, bool list); + + // Stop and start WiFi components + // Inputs: + // stopping: WiFi components that need to be stopped + // starting: WiFi components that neet to be started + // Outputs: + // Returns true if the modes were successfully configured + bool stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting); + + // Handle the WiFi event + // Inputs: + // event: Arduino ESP32 event number found on + // https://github.com/espressif/arduino-esp32 + // in libraries/Network/src/NetworkEvents.h + // info: Additional data about the event + void wifiEvent(arduino_event_id_t event, arduino_event_info_t info); + + public: + + // Constructor + // Inputs: + // verbose: Set to true to display additional WiFi debug data + RTK_WIFI(bool verbose = false); + + // Attempts a connection to all provided SSIDs + // Inputs: + // timeout: Number of milliseconds to wait for the connection + // startAP: Set true to start AP mode, false does not change soft AP + // status + // Outputs: + // Returns true if successful and false upon timeout, no matching + // SSID or other failure + bool connect(unsigned long timeout, + bool startAP); + + // Enable or disable the WiFi modes + // Inputs: + // enableESPNow: Enable ESP-NOW mode + // enableSoftAP: Enable soft AP mode + // enableStataion: Enable station mode + // Outputs: + // Returns true if the modes were successfully configured + bool enable(bool enableESPNow, bool enableSoftAP, bool enableStation); + + // Get the ESP-NOW status + // Outputs: + // Returns true when ESP-NOW is online and ready for use + bool espNowOnline(); + + // Get the ESP-NOW status + // Outputs: + // Returns true if ESP-NOW is being started or is online + bool espNowRunning(); + + // Handle the WiFi event + // Inputs: + // event: Arduino ESP32 event number found on + // https://github.com/espressif/arduino-esp32 + // in libraries/Network/src/NetworkEvents.h + // info: Additional data about the event + void eventHandler(arduino_event_id_t event, arduino_event_info_t info); + + // Get the mDNS host name + // Outputs: + // Returns the mDNS host name as a pointer to a zero terminated string + // of characters + const char * hostNameGet(); + + // Set the mDNS host name + // Inputs + // Address of a zero terminated string containing the mDNS host name + void hostNameSet(const char * mDnsHostName); + + // Restart WiFi + // Inputs: + // always: Set true if this routine should always restart WiFi, + // when false determine restart using _restartRequest + // Outputs: + // Returns true if the WiFi layer was successfully restarted and + // false upon restart failure + bool restart(bool always); + + // Determine if any use of WiFi is starting or is online + // Outputs: + // Returns true if any WiFi use is being started or is online + bool running(); + + // Configure the soft AP + // Inputs: + // ipAddress: IP address of the soft AP + // subnetMask: Subnet mask for the soft AP network + // firstDhcpAddress: First IP address to use in the DHCP range + // dnsAddress: IP address to use for DNS lookup (translate name to IP address) + // gatewayAddress: IP address of the gateway to a larger network (internet?) + // Outputs: + // Returns true if the soft AP was successfully configured. + bool softApConfiguration(IPAddress ipAddress, + IPAddress subnetMask, + IPAddress firstDhcpAddress, + IPAddress dnsAddress, + IPAddress gateway); + + // Display the soft AP configuration + // Inputs: + // display: Address of a Print object + void softApConfigurationDisplay(Print * display); + + // Get the soft AP status + // Outputs: + // Returns true when the soft AP is ready for use + bool softApOnline(); + + // Determine if the soft AP is being started or is onine + // Outputs: + // Returns true if the soft AP is being started or is online + bool softApRunning(); + + // Attempt to start the soft AP mode + // Inputs: + // forceAP: Set to true to force AP to start, false will only start + // soft AP if settings.wifiConfigOverAP is true + // Outputs: + // Returns true if the soft AP was started successfully and false + // otherwise + bool startAp(bool forceAP); + + // Get the station status + // Outputs: + // Returns true when the WiFi station is online and ready for use + bool stationOnline(); + + // Handle WiFi station reconnection requests + void stationReconnectionRequest(); + + // Get the station status + // Outputs: + // Returns true if the WiFi station is being started or is online + bool stationRunning(); + + // Test the WiFi modes + // Inputs: + // testDurationMsec: Milliseconds to run each test + void test(uint32_t testDurationMsec); + + // Enable or disable verbose debug output + // Inputs: + // enable: Set true to enable verbose debug output + // Outputs: + // Return the previous enable value + bool verbose(bool enable); + + // Verify the WiFi tables + void verifyTables(); +}; + +#endif // COMPILE_WIFI #endif // COMPILE_NETWORK + +//**************************************** +// ESP-NOW +//**************************************** + +#ifdef COMPILE_ESPNOW + +typedef enum +{ + ESP_NOW_OFF = 0, + ESP_NOW_BROADCASTING, + ESP_NOW_PAIRING, + ESP_NOW_MAC_RECEIVED, + ESP_NOW_PAIRED, + ESP_NOW_MAX +} ESP_NOW_STATE; + +// Create a struct for ESP NOW pairing +typedef struct _ESP_NOW_PAIR_MESSAGE +{ + uint8_t macAddress[6]; + bool encrypt; + uint8_t channel; + uint8_t crc; // Simple check - add MAC together and limit to 8 bit +} ESP_NOW_PAIR_MESSAGE; + +#endif // COMPILE_ESPNOW #endif // __SETTINGS_H__ From cb6ee0df1bb576f1e1d59d6a9e2314a99af5a5fc Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Tue, 21 Jan 2025 07:58:50 -1000 Subject: [PATCH 155/276] Rename old networkMarkO* routines to networkInterfaceInternetConnection* --- Firmware/RTK_Everywhere/Cellular.ino | 4 ++-- Firmware/RTK_Everywhere/Ethernet.ino | 4 ++-- Firmware/RTK_Everywhere/Network.ino | 6 +++--- Firmware/RTK_Everywhere/WiFi_old.ino | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Firmware/RTK_Everywhere/Cellular.ino b/Firmware/RTK_Everywhere/Cellular.ino index 45014d02a..2cbd4cc81 100644 --- a/Firmware/RTK_Everywhere/Cellular.ino +++ b/Firmware/RTK_Everywhere/Cellular.ino @@ -87,7 +87,7 @@ void cellularEvent(arduino_event_id_t event) if (networkInterfaceHasInternet(NETWORK_CELLULAR) && (event != ARDUINO_EVENT_ETH_GOT_IP) && (event != ARDUINO_EVENT_ETH_GOT_IP6) && (event != ARDUINO_EVENT_PPP_CONNECTED)) { - networkMarkOffline(NETWORK_CELLULAR); + networkInterfaceInternetConnectionLost(NETWORK_CELLULAR); } // Cellular State Machine @@ -108,7 +108,7 @@ void cellularEvent(arduino_event_id_t event) case ARDUINO_EVENT_PPP_CONNECTED: systemPrintln("Cellular Connected"); - networkMarkHasInternet(NETWORK_CELLULAR); + networkInterfaceInternetConnectionAvailable(NETWORK_CELLULAR); break; case ARDUINO_EVENT_PPP_DISCONNECTED: diff --git a/Firmware/RTK_Everywhere/Ethernet.ino b/Firmware/RTK_Everywhere/Ethernet.ino index aec52d685..d24cc4042 100644 --- a/Firmware/RTK_Everywhere/Ethernet.ino +++ b/Firmware/RTK_Everywhere/Ethernet.ino @@ -174,7 +174,7 @@ void ethernetEvent(arduino_event_id_t event, arduino_event_info_t info) if (settings.enablePrintEthernetDiag && (!inMainMenu)) systemPrintf("ETH Got IP: '%s'\r\n", ETH.localIP().toString().c_str()); - networkMarkHasInternet((NetIndex_t)NETWORK_ETHERNET); + networkInterfaceInternetConnectionAvailable((NetIndex_t)NETWORK_ETHERNET); if (settings.ethernetDHCP) paintEthernetConnected(); @@ -202,7 +202,7 @@ void ethernetEvent(arduino_event_id_t event, arduino_event_info_t info) // Take the network offline if necessary if (networkInterfaceHasInternet(NETWORK_ETHERNET) && (event != ARDUINO_EVENT_ETH_GOT_IP)) { - networkMarkOffline((NetIndex_t)NETWORK_ETHERNET); + networkInterfaceInternetConnectionLost((NetIndex_t)NETWORK_ETHERNET); } } diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 27e911383..1a12ee8b3 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -631,7 +631,7 @@ bool networkIsPresent(NetIndex_t index) //---------------------------------------- // Mark network offline //---------------------------------------- -void networkMarkOffline(NetIndex_t index) +void networkInterfaceInternetConnectionLost(NetIndex_t index) { NetMask_t bitMask; NetPriority_t previousPriority; @@ -700,7 +700,7 @@ void networkMarkOffline(NetIndex_t index) //---------------------------------------- // Mark network online //---------------------------------------- -void networkMarkHasInternet(NetIndex_t index) +void networkInterfaceInternetConnectionAvailable(NetIndex_t index) { NetMask_t bitMask; NetIndex_t previousIndex; @@ -1855,4 +1855,4 @@ uint8_t networkConsumersOnline() return (consumerCountOnline); } -#endif // COMPILE_NETWORK \ No newline at end of file +#endif // COMPILE_NETWORK diff --git a/Firmware/RTK_Everywhere/WiFi_old.ino b/Firmware/RTK_Everywhere/WiFi_old.ino index 6dc9de890..25112b6d6 100644 --- a/Firmware/RTK_Everywhere/WiFi_old.ino +++ b/Firmware/RTK_Everywhere/WiFi_old.ino @@ -424,7 +424,7 @@ void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) systemPrint("WiFi STA Got IPv4: "); systemPrintln(ipAddress); } - networkMarkHasInternet(NETWORK_WIFI); + networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP6: @@ -434,7 +434,7 @@ void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) systemPrint("WiFi STA Got IPv6: "); systemPrintln(ipAddress); } - networkMarkHasInternet(NETWORK_WIFI); + networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); break; case ARDUINO_EVENT_WIFI_STA_LOST_IP: @@ -717,7 +717,7 @@ void wifiStop() } // Take the network offline - networkMarkOffline(NETWORK_WIFI); + networkInterfaceInternetConnectionLost(NETWORK_WIFI); if (wifiMulti != nullptr) wifiMulti = nullptr; From 49bdce7fca4113832630a27c272568df3969d112 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 24 Jan 2025 15:47:26 +0000 Subject: [PATCH 156/276] Update paintSystemTest for the mosaic-X5 --- Firmware/RTK_Everywhere/Display.ino | 36 ++++++++++++++++++------- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 8 ++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index a56a272ba..61c66f45b 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -2387,15 +2387,31 @@ void paintSystemTest() drawFrame(); // Outside edge oled->setFont(QW_FONT_5X7); // Set font to smallest - oled->setCursor(xOffset, yOffset); // x, y - oled->print("SD:"); - if (online.microSD == false) - beginSD(); // Test if SD is present - if (online.microSD == true) - oled->print("OK"); - else - oled->print("FAIL"); + if (present.microSD) + { + oled->setCursor(xOffset, yOffset); // x, y + oled->print("SD:"); + + if (online.microSD == false) + beginSD(); // Test if SD is present + if (online.microSD == true) + oled->print("OK"); + else + oled->print("FAIL"); + } + else if (present.gnss_mosaicX5) + { + // Facet mosaic has an SD card, but it is connected directly to the mosaic-X5 + // Calling gnss->update() during the GNSS check will cause sdCardSize to be updated + oled->setCursor(xOffset, yOffset); // x, y + oled->print("SD:"); + + if (sdCardSize > 0) + oled->print("OK"); + else + oled->print("FAIL"); + } if (present.fuelgauge_max17048 || present.fuelgauge_bq40z50) { @@ -2510,14 +2526,14 @@ void paintSystemTest() oled->print(" "); oled->print(gnssFirmwareVersionInt); oled->print("-"); - if ((present.gnss_zedf9p) && (gnssFirmwareVersionInt < 130)) + if ((present.gnss_zedf9p) && (gnssFirmwareVersionInt < 150)) oled->print("FAIL"); else oled->print("OK"); oled->setCursor(xOffset, yOffset + (2 * charHeight)); // x, y oled->print("LBand:"); - if (online.lband_neo == true) + if ((online.lband_neo == true) || (present.gnss_mosaicX5)) oled->print("OK"); else oled->print("FAIL"); diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 15009f258..58d073591 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2646,9 +2646,17 @@ void processSBFReceiverSetup(SEMP_PARSE_STATE *parse, uint16_t type) if (sempSbfGetBlockNumber(parse) == 5902) { snprintf(gnssUniqueId, sizeof(gnssUniqueId), "%s", sempSbfGetString(parse, 156)); // Extract RxSerialNumber + snprintf(gnssFirmwareVersion, sizeof(gnssFirmwareVersion), "%s", sempSbfGetString(parse, 196)); // Extract RXVersion + // gnssFirmwareVersion is 4.14.4, 4.14.10.1, etc. + // Create gnssFirmwareVersionInt from the first two fields only so it will fit on the OLED + int verMajor = 0; + int verMinor = 0; + sscanf(gnssFirmwareVersion, "%d.%d.", &verMajor, &verMinor); // Do we care if this fails? + gnssFirmwareVersionInt = (verMajor * 100) + verMinor; + GNSS_MOSAIC *mosaic = (GNSS_MOSAIC *)gnss; mosaic->_receiverSetupSeen = true; } From 55d198a777cb1f8ea09f36f57f0a43c19fb499e6 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 24 Jan 2025 16:49:25 +0000 Subject: [PATCH 157/276] Convert SIV of 255 ("Do-Not_Use") to zero --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 58d073591..b32d79d00 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2375,6 +2375,8 @@ void GNSS_MOSAIC::storeBlock4007(SEMP_PARSE_STATE *parse) _altitude = (float)sempSbfGetF8(parse, 32); _horizontalAccuracy = ((float)sempSbfGetU2(parse, 90)) / 100.0; // Convert from cm to m _satellitesInView = sempSbfGetU1(parse, 74); + if (_satellitesInView == 255) + _satellitesInView = 0; _fixType = sempSbfGetU1(parse, 14) & 0x0F; _determiningFixedPosition = (sempSbfGetU1(parse, 14) >> 6) & 0x01; _clkBias_ms = sempSbfGetF8(parse, 60); From abd79bd87db4badc138bdbd2d8371eef12267805 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 24 Jan 2025 16:55:37 +0000 Subject: [PATCH 158/276] Update comments --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index b32d79d00..f349c0abf 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2375,7 +2375,7 @@ void GNSS_MOSAIC::storeBlock4007(SEMP_PARSE_STATE *parse) _altitude = (float)sempSbfGetF8(parse, 32); _horizontalAccuracy = ((float)sempSbfGetU2(parse, 90)) / 100.0; // Convert from cm to m _satellitesInView = sempSbfGetU1(parse, 74); - if (_satellitesInView == 255) + if (_satellitesInView == 255) // 255 indicates "Do-Not-Use" _satellitesInView = 0; _fixType = sempSbfGetU1(parse, 14) & 0x0F; _determiningFixedPosition = (sempSbfGetU1(parse, 14) >> 6) & 0x01; @@ -2653,7 +2653,7 @@ void processSBFReceiverSetup(SEMP_PARSE_STATE *parse, uint16_t type) sempSbfGetString(parse, 196)); // Extract RXVersion // gnssFirmwareVersion is 4.14.4, 4.14.10.1, etc. - // Create gnssFirmwareVersionInt from the first two fields only so it will fit on the OLED + // Create gnssFirmwareVersionInt from the first two fields only, so it will fit on the OLED int verMajor = 0; int verMinor = 0; sscanf(gnssFirmwareVersion, "%d.%d.", &verMajor, &verMinor); // Do we care if this fails? From af81f62e951ea8bec2e8b5ae1062737f6232fc2e Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 24 Jan 2025 17:06:21 +0000 Subject: [PATCH 159/276] Fix typo. Update MCP73833 diagnostic print --- Firmware/RTK_Everywhere/Display.ino | 2 +- Firmware/RTK_Everywhere/System.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 61c66f45b..8ad1bed5a 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -2388,7 +2388,7 @@ void paintSystemTest() oled->setFont(QW_FONT_5X7); // Set font to smallest - if (present.microSD) + if (present.microSd) { oled->setCursor(xOffset, yOffset); // x, y oled->print("SD:"); diff --git a/Firmware/RTK_Everywhere/System.ino b/Firmware/RTK_Everywhere/System.ino index 33e52115b..cd5fbb940 100644 --- a/Firmware/RTK_Everywhere/System.ino +++ b/Firmware/RTK_Everywhere/System.ino @@ -98,7 +98,7 @@ void updateBattery() ((uint8_t)readAnalogPinAsDigital(pin_chargerLED)); systemPrint("MCP73833 Charger: "); if (combinedStat == 3) - systemPrintln("standby / fault"); + systemPrintln("standby"); else if (combinedStat == 2) systemPrintln("battery is charging"); else if (combinedStat == 1) From 00d61e59a1cb88c13a71f93bf99e1a4d02aecd3a Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 24 Jan 2025 08:34:41 -1000 Subject: [PATCH 160/276] Merge ESPNOW_old.ino into ESPNOW.ino and WiFi_old.ino into WiFi.ino --- Firmware/RTK_Everywhere/ESPNOW.ino | 650 +++++++++++++++++++++ Firmware/RTK_Everywhere/ESPNOW_old.ino | 653 --------------------- Firmware/RTK_Everywhere/WiFi.ino | 745 ++++++++++++++++++++++++ Firmware/RTK_Everywhere/WiFi_old.ino | 751 ------------------------- 4 files changed, 1395 insertions(+), 1404 deletions(-) delete mode 100644 Firmware/RTK_Everywhere/ESPNOW_old.ino delete mode 100644 Firmware/RTK_Everywhere/WiFi_old.ino diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index 0b5477a8c..342603784 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -438,4 +438,654 @@ bool espNowStop() return stopped; } +/* + Use ESP NOW protocol to transmit RTCM between RTK Products via 2.4GHz + + How pairing works: + 1. Device enters pairing mode + 2. Device adds the broadcast MAC (all 0xFFs) as peer + 3. Device waits for incoming pairing packet from remote + 4. If valid pairing packet received, add peer, immediately transmit a pairing packet to that peer and exit. + + ESP NOW is bare metal, there is no guaranteed packet delivery. For RTCM byte transmissions using ESP NOW: + We don't care about dropped packets or packets out of order. The ZED will check the integrity of the RTCM packet. + We don't care if the ESP NOW packet is corrupt or not. RTCM has its own CRC. RTK needs valid RTCM once every + few seconds so a single dropped frame is not critical. +*/ + +// Called from main loop +// Control incoming/outgoing RTCM data from internal ESP NOW radio +// Use the ESP32 to directly transmit/receive RTCM over 2.4GHz (no WiFi needed) +void updateEspnow() +{ + if (settings.enableEspNow == true) + { + if (espnowState == ESPNOW_PAIRED || espnowState == ESPNOW_BROADCASTING) + { + // If it's been longer than a few ms since we last added a byte to the buffer + // then we've reached the end of the RTCM stream. Send partial buffer. + if (espnowOutgoingSpot > 0 && (millis() - espnowLastAdd) > 50) + { + if (espnowState == ESPNOW_PAIRED) + esp_now_send(0, (uint8_t *)&espnowOutgoing, espnowOutgoingSpot); // Send partial packet to all peers + else // if (espnowState == ESPNOW_BROADCASTING) + { + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + esp_now_send(broadcastMac, (uint8_t *)&espnowOutgoing, + espnowOutgoingSpot); // Send packet via broadcast + } + + if (!inMainMenu) + { + if (settings.debugEspNow == true) + systemPrintf("ESPNOW transmitted %d RTCM bytes\r\n", espnowBytesSent + espnowOutgoingSpot); + } + espnowBytesSent = 0; + espnowOutgoingSpot = 0; // Reset + } + + // If we don't receive an ESP NOW packet after some time, set RSSI to very negative + // This removes the ESPNOW icon from the display when the link goes down + if (millis() - lastEspnowRssiUpdate > 5000 && espnowRSSI > -255) + espnowRSSI = -255; + } + } +} + +// Create a struct for ESP NOW pairing +typedef struct PairMessage +{ + uint8_t macAddress[6]; + bool encrypt; + uint8_t channel; + uint8_t crc; // Simple check - add MAC together and limit to 8 bit +} PairMessage; + +// Callback when data is sent +void espnowOnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) +{ + // systemPrint("Last Packet Send Status: "); + // if (status == ESP_NOW_SEND_SUCCESS) + // systemPrintln("Delivery Success"); + // else + // systemPrintln("Delivery Fail"); +} + +// Callback when data is received +void espnowOnDataReceived(const esp_now_recv_info *mac, const uint8_t *incomingData, int len) +{ + if (espnowState == ESPNOW_PAIRING) + { + if (len == sizeof(PairMessage)) // First error check + { + PairMessage pairMessage; + memcpy(&pairMessage, incomingData, sizeof(pairMessage)); + + // Check CRC + uint8_t tempCRC = 0; + for (int x = 0; x < 6; x++) + tempCRC += pairMessage.macAddress[x]; + + if (tempCRC == pairMessage.crc) // 2nd error check + { + memcpy(&receivedMAC, pairMessage.macAddress, 6); + espnowSetState(ESPNOW_MAC_RECEIVED); + } + // else Pair CRC failed + } + } + else + { + espnowRSSI = packetRSSI; // Record this packet's RSSI as an ESP NOW packet + + // We've just received ESP-Now data. We assume this is RTCM and push it directly to the GNSS. + // Determine if ESPNOW is the correction source + if (correctionLastSeen(CORR_ESPNOW)) + { + // Pass RTCM bytes (presumably) from ESP NOW out ESP32-UART to GNSS + gnss->pushRawData((uint8_t *)incomingData, len); + + if ((settings.debugEspNow == true || settings.debugCorrections == true) && !inMainMenu) + systemPrintf("ESPNOW received %d RTCM bytes, pushed to GNSS, RSSI: %d\r\n", len, espnowRSSI); + } + else + { + if ((settings.debugEspNow == true || settings.debugCorrections == true) && !inMainMenu) + systemPrintf("ESPNOW received %d RTCM bytes, NOT pushed due to priority, RSSI: %d\r\n", len, + espnowRSSI); + } + + espnowIncomingRTCM = true; // Display a download icon + lastEspnowRssiUpdate = millis(); + } +} + +// Callback for all RX Packets +// Get RSSI of all incoming management packets: https://esp32.com/viewtopic.php?t=13889 +#ifdef COMPILE_ESPNOW +void promiscuous_rx_cb(void *buf, wifi_promiscuous_pkt_type_t type) +{ + // All espnow traffic uses action frames which are a subtype of the mgmnt frames so filter out everything else. + if (type != WIFI_PKT_MGMT) + return; + + const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buf; + packetRSSI = ppkt->rx_ctrl.rssi; +} +#endif // COMPILE_ESPNOW + +// If WiFi is already enabled, simply add the LR protocol +// If the radio is off entirely, start the radio, turn on only the LR protocol +void espnowStart() +{ + if (settings.enableEspNow == false) + { + espnowStop(); + return; + } + + // Before we can issue esp_wifi_() commands WiFi must be started + if (WiFi.getMode() != WIFI_STA) + WiFi.mode(WIFI_STA); + + // Verify that the necessary protocols are set + uint8_t protocols = 0; + esp_err_t response = esp_wifi_get_protocol(WIFI_IF_STA, &protocols); + if (response != ESP_OK) + systemPrintf("espnowStart: Failed to get protocols: %s\r\n", esp_err_to_name(response)); + + if ((wifiIsRunning() == false) && espnowState == ESPNOW_OFF) + { + // Radio is off, turn it on + if (protocols != (WIFI_PROTOCOL_LR)) + { + response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); // Stops WiFi Station. + if (response != ESP_OK) + systemPrintf("espnowStart: Error setting ESP-Now lone protocol: %s\r\n", esp_err_to_name(response)); + else + { + if (settings.debugEspNow == true) + systemPrintln("WiFi off, ESP-Now added to protocols"); + } + } + else + { + if (settings.debugEspNow == true) + systemPrintln("LR protocol already in place"); + } + } + // If WiFi is on but ESP NOW is off, then enable LR protocol + else if (wifiIsRunning() && espnowState == ESPNOW_OFF) + { + // Enable WiFi + ESP-Now + // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps + if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR)) + { + response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | + WIFI_PROTOCOL_LR); + if (response != ESP_OK) + systemPrintf("espnowStart: Error setting ESP-Now + WiFi protocols: %s\r\n", esp_err_to_name(response)); + else + { + if (settings.debugEspNow == true) + systemPrintln("WiFi on, ESP-Now added to protocols"); + } + } + else + { + if (settings.debugEspNow == true) + systemPrintln("WiFi was already on, and LR protocol already in place"); + } + } + + // If ESP-Now is already active, do nothing + else + { + if (settings.debugEspNow == true) + systemPrintln("ESP-Now already on."); + } + + // WiFi.setSleep(false); //We must disable sleep so that ESP-NOW can readily receive packets + // See: https://github.com/sparkfun/SparkFun_RTK_Everywhere_Firmware/issues/241 + + // Init ESP-NOW + if (esp_now_init() != ESP_OK) + { + systemPrintln("espnowStart: Error starting ESP-Now"); + return; + } + + // Use promiscuous callback to capture RSSI of packet + response = esp_wifi_set_promiscuous(true); + if (response != ESP_OK) + systemPrintf("espnowStart: Error setting promiscuous mode: %s\r\n", esp_err_to_name(response)); + + esp_wifi_set_promiscuous_rx_cb(&promiscuous_rx_cb); + + // Assign channel if not connected to an AP + if (wifiIsConnected() == false) + espnowSetChannel(settings.wifiChannel); + + // Register callbacks + // esp_now_register_send_cb(espnowOnDataSent); + esp_now_register_recv_cb(espnowOnDataReceived); + + if (settings.espnowPeerCount == 0) + { + // Enter broadcast mode + + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + if (esp_now_is_peer_exist(broadcastMac) == true) + { + if (settings.debugEspNow == true) + systemPrintln("Broadcast peer already exists"); + } + else + { + esp_err_t result = espnowAddPeer(broadcastMac, false); // Encryption not support for broadcast MAC + if (result != ESP_OK) + { + if (settings.debugEspNow == true) + systemPrintln("Failed to add broadcast peer"); + } + else + { + if (settings.debugEspNow == true) + systemPrintln("Broadcast peer added"); + } + } + + espnowSetState(ESPNOW_BROADCASTING); + } + else + { + // If we have peers, move to paired state + espnowSetState(ESPNOW_PAIRED); + + if (settings.debugEspNow == true) + systemPrintf("Adding %d espnow peers\r\n", settings.espnowPeerCount); + + for (int x = 0; x < settings.espnowPeerCount; x++) + { + if (esp_now_is_peer_exist(settings.espnowPeers[x]) == true) + { + if (settings.debugEspNow == true) + systemPrintf("Peer #%d already exists\r\n", x); + } + else + { + esp_err_t result = espnowAddPeer(settings.espnowPeers[x]); + if (result != ESP_OK) + { + if (settings.debugEspNow == true) + systemPrintf("Failed to add peer #%d\r\n", x); + } + } + } + } + + systemPrintln("ESP-Now Started"); +} + +// If WiFi is already enabled, simply remove the LR protocol +// If WiFi is off, stop the radio entirely +void espnowStop() +{ + if (espnowState == ESPNOW_OFF) + return; + + // Turn off promiscuous WiFi mode + esp_err_t response = esp_wifi_set_promiscuous(false); + if (response != ESP_OK) + systemPrintf("espnowStop: Failed to set promiscuous mode: %s\r\n", esp_err_to_name(response)); + + esp_wifi_set_promiscuous_rx_cb(nullptr); + + // Deregister callbacks + // esp_now_unregister_send_cb(); + response = esp_now_unregister_recv_cb(); + if (response != ESP_OK) + systemPrintf("espnowStop: Failed to unregister receive callback: %s\r\n", esp_err_to_name(response)); + + // Forget all ESP-Now Peers + for (int x = 0; x < settings.espnowPeerCount; x++) + espnowRemovePeer(settings.espnowPeers[x]); + + if (WiFi.getMode() != WIFI_STA) + WiFi.mode(WIFI_STA); + + // Verify that the necessary protocols are set + uint8_t protocols = 0; + response = esp_wifi_get_protocol(WIFI_IF_STA, &protocols); + if (response != ESP_OK) + systemPrintf("espnowStop: Failed to get protocols: %s\r\n", esp_err_to_name(response)); + + // Leave WiFi with default settings (no WIFI_PROTOCOL_LR for ESP NOW) + if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N)) + { + response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N); + if (response != ESP_OK) + systemPrintf("espnowStop: Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); + else + { + if (settings.debugEspNow == true) + systemPrintln("espnowStop: WiFi on, ESP-Now removed from protocols"); + } + } + else + { + if (settings.debugEspNow == true) + systemPrintln("espnowStop: ESP-Now already removed from protocols"); + } + + // Deinit ESP-NOW + if (esp_now_deinit() != ESP_OK) + { + systemPrintln("Error deinitializing ESP-NOW"); + return; + } + + espnowSetState(ESPNOW_OFF); + + if (wifiIsRunning() == false) + { + // ESP-NOW was the only thing using the radio so turn WiFi radio off entirely + WiFi.mode(WIFI_OFF); + + if (settings.debugEspNow == true) + systemPrintln("WiFi Radio off entirely"); + } + // If WiFi is on, then restart WiFi + else if (wifiIsRunning()) + { + if (settings.debugEspNow == true) + systemPrintln("ESP-Now starting WiFi"); + wifiStart(); // Force WiFi to restart + } +} + +// Start ESP-Now if needed, put ESP-Now into broadcast state +void espnowBeginPairing() +{ + espnowStart(); + + // To begin pairing, we must add the broadcast MAC to the peer list + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + espnowAddPeer(broadcastMac, false); // Encryption is not supported for multicast addresses + + espnowSetState(ESPNOW_PAIRING); +} + +// Regularly call during pairing to see if we've received a Pairing message +bool espnowIsPaired() +{ + if (espnowState == ESPNOW_MAC_RECEIVED) + { + // Remove broadcast peer + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + espnowRemovePeer(broadcastMac); + + if (esp_now_is_peer_exist(receivedMAC) == true) + { + if (settings.debugEspNow == true) + systemPrintln("Peer already exists"); + } + else + { + // Add new peer to system + espnowAddPeer(receivedMAC); + + // Record this MAC to peer list + memcpy(settings.espnowPeers[settings.espnowPeerCount], receivedMAC, 6); + settings.espnowPeerCount++; + settings.espnowPeerCount %= ESPNOW_MAX_PEERS; + } + + // Send message directly to the received MAC (not unicast), then exit + espnowSendPairMessage(receivedMAC); + + // Enable radio. User may have arrived here from the setup menu rather than serial menu. + settings.enableEspNow = true; + + recordSystemSettings(); // Record enableEspNow and espnowPeerCount to NVM + + espnowSetState(ESPNOW_PAIRED); + return (true); + } + return (false); +} + +// Create special pair packet to a given MAC +esp_err_t espnowSendPairMessage(uint8_t *sendToMac) +{ + // Assemble message to send + PairMessage pairMessage; + + // Get unit MAC address + memcpy(pairMessage.macAddress, wifiMACAddress, 6); + pairMessage.encrypt = false; + pairMessage.channel = 0; + + pairMessage.crc = 0; // Calculate CRC + for (int x = 0; x < 6; x++) + pairMessage.crc += wifiMACAddress[x]; + + return (esp_now_send(sendToMac, (uint8_t *)&pairMessage, sizeof(pairMessage))); // Send packet to given MAC +} + +// Add a given MAC address to the peer list +esp_err_t espnowAddPeer(uint8_t *peerMac) +{ + return (espnowAddPeer(peerMac, true)); // Encrypt by default +} + +esp_err_t espnowAddPeer(uint8_t *peerMac, bool encrypt) +{ + esp_now_peer_info_t peerInfo; + + memcpy(peerInfo.peer_addr, peerMac, 6); + peerInfo.channel = 0; + peerInfo.ifidx = WIFI_IF_STA; + // memcpy(peerInfo.lmk, "RTKProductsLMK56", 16); + // peerInfo.encrypt = encrypt; + peerInfo.encrypt = false; + + esp_err_t result = esp_now_add_peer(&peerInfo); + if (result != ESP_OK) + { + if (settings.debugEspNow == true) + systemPrintf("Failed to add peer: 0x%02X%02X%02X%02X%02X%02X\r\n", peerMac[0], peerMac[1], peerMac[2], + peerMac[3], peerMac[4], peerMac[5]); + } + return (result); +} + +// Remove a given MAC address from the peer list +esp_err_t espnowRemovePeer(uint8_t *peerMac) +{ + esp_err_t response = esp_now_del_peer(peerMac); + if (response != ESP_OK) + { + if (settings.debugEspNow == true) + systemPrintf("Failed to remove peer: %s\r\n", esp_err_to_name(response)); + } + + return (response); +} + +// Update the state of the ESP Now state machine +void espnowSetState(ESPNOWState newState) +{ + if (espnowState == newState && settings.debugEspNow == true) + systemPrint("*"); + espnowState = newState; + + if (settings.debugEspNow == true) + { + systemPrint("espnowState: "); + switch (newState) + { + case ESPNOW_OFF: + systemPrintln("ESPNOW_OFF"); + break; + case ESPNOW_BROADCASTING: + systemPrintln("ESPNOW_BROADCASTING"); + break; + case ESPNOW_PAIRING: + systemPrintln("ESPNOW_PAIRING"); + break; + case ESPNOW_MAC_RECEIVED: + systemPrintln("ESPNOW_MAC_RECEIVED"); + break; + case ESPNOW_PAIRED: + systemPrintln("ESPNOW_PAIRED"); + break; + default: + systemPrintf("Unknown ESPNOW state: %d\r\n", newState); + break; + } + } +} + +void espnowProcessRTCM(byte incoming) +{ + // If we are paired, + // Or if the radio is broadcasting + // Then add bytes to the outgoing buffer + if (espnowState == ESPNOW_PAIRED || espnowState == ESPNOW_BROADCASTING) + { + // Move this byte into ESP NOW to send buffer + espnowOutgoing[espnowOutgoingSpot++] = incoming; + espnowLastAdd = millis(); + } + + // Send buffer when full + if (espnowOutgoingSpot == sizeof(espnowOutgoing)) + { + espnowOutgoingSpot = 0; // Wrap + + if (espnowState == ESPNOW_PAIRED) + esp_now_send(0, (uint8_t *)&espnowOutgoing, sizeof(espnowOutgoing)); // Send packet to all peers + else // if (espnowState == ESPNOW_BROADCASTING) + { + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + esp_now_send(broadcastMac, (uint8_t *)&espnowOutgoing, + sizeof(espnowOutgoing)); // Send packet via broadcast + } + + delay(10); // We need a small delay between sending multiple packets + + espnowBytesSent += sizeof(espnowOutgoing); + + espnowOutgoingRTCM = true; + } +} + +// A blocking function that is used to pair two devices +// either through the serial menu or AP config +void espnowStaticPairing() +{ + systemPrintln("Begin ESP NOW Pairing"); + + // Start ESP-Now if needed, put ESP-Now into broadcast state + espnowBeginPairing(); + + // Begin sending our MAC every 250ms until a remote device sends us there info + randomSeed(millis()); + + systemPrintln("Begin pairing. Place other unit in pairing mode. Press any key to exit."); + clearBuffer(); + + uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + bool exitPair = false; + while (exitPair == false) + { + if (systemAvailable()) + { + systemPrintln("User pressed button. Pairing canceled."); + break; + } + + int timeout = 1000 + random(0, 100); // Delay 1000 to 1100ms + for (int x = 0; x < timeout; x++) + { + delay(1); + + if (espnowIsPaired() == true) // Check if we've received a pairing message + { + systemPrintln("Pairing compete"); + exitPair = true; + break; + } + } + + espnowSendPairMessage(broadcastMac); // Send unit's MAC address over broadcast, no ack, no encryption + + systemPrintln("Scanning for other radio..."); + } +} + +// Returns the current channel being used by WiFi +uint8_t espnowGetChannel() +{ + if (espnowState == ESPNOW_OFF) + return 0; + + bool originalPromiscuousMode = false; + esp_err_t response = esp_wifi_get_promiscuous(&originalPromiscuousMode); + if (response != ESP_OK) + systemPrintf("getPromiscuous failed: %s\r\n", esp_err_to_name(response)); + + // We must be in promiscuous mode to get the channel number + if (originalPromiscuousMode == false) + esp_wifi_set_promiscuous(true); + + uint8_t primaryChannelNumber = 0; + wifi_second_chan_t secondaryChannelNumber; + + response = esp_wifi_get_channel(&primaryChannelNumber, &secondaryChannelNumber); + if (response != ESP_OK) + systemPrintf("getChannel failed: %s\r\n", esp_err_to_name(response)); + + // Return to the original mode + if (originalPromiscuousMode == false) + esp_wifi_set_promiscuous(false); + + return (primaryChannelNumber); +} + +// Returns the current channel being used by WiFi +bool espnowSetChannel(uint8_t channelNumber) +{ + if (wifiIsConnected() == true) + { + systemPrintln("ESP-NOW channel can't be modified while WiFi is connected."); + return (false); + } + + bool originalPromiscuousMode = false; + esp_err_t response = esp_wifi_get_promiscuous(&originalPromiscuousMode); + if (response != ESP_OK) + systemPrintf("getPromiscuous failed: %s\r\n", esp_err_to_name(response)); + + // We must be in promiscuous mode to set the channel number + if (originalPromiscuousMode == false) + esp_wifi_set_promiscuous(true); + + bool setSuccess = false; + response = esp_wifi_set_channel(channelNumber, WIFI_SECOND_CHAN_NONE); + if (response != ESP_OK) + systemPrintf("setChannel to %d failed: %s\r\n", channelNumber, esp_err_to_name(response)); + else + setSuccess = true; + + // Return to the original mode + if (originalPromiscuousMode == false) + esp_wifi_set_promiscuous(false); + + return (setSuccess); +} + #endif // COMPILE_ESPNOW diff --git a/Firmware/RTK_Everywhere/ESPNOW_old.ino b/Firmware/RTK_Everywhere/ESPNOW_old.ino deleted file mode 100644 index 6c2d46c39..000000000 --- a/Firmware/RTK_Everywhere/ESPNOW_old.ino +++ /dev/null @@ -1,653 +0,0 @@ -/* - Use ESP NOW protocol to transmit RTCM between RTK Products via 2.4GHz - - How pairing works: - 1. Device enters pairing mode - 2. Device adds the broadcast MAC (all 0xFFs) as peer - 3. Device waits for incoming pairing packet from remote - 4. If valid pairing packet received, add peer, immediately transmit a pairing packet to that peer and exit. - - ESP NOW is bare metal, there is no guaranteed packet delivery. For RTCM byte transmissions using ESP NOW: - We don't care about dropped packets or packets out of order. The ZED will check the integrity of the RTCM packet. - We don't care if the ESP NOW packet is corrupt or not. RTCM has its own CRC. RTK needs valid RTCM once every - few seconds so a single dropped frame is not critical. -*/ - -#ifdef COMPILE_ESPNOW - -// Called from main loop -// Control incoming/outgoing RTCM data from internal ESP NOW radio -// Use the ESP32 to directly transmit/receive RTCM over 2.4GHz (no WiFi needed) -void updateEspnow() -{ - if (settings.enableEspNow == true) - { - if (espnowState == ESPNOW_PAIRED || espnowState == ESPNOW_BROADCASTING) - { - // If it's been longer than a few ms since we last added a byte to the buffer - // then we've reached the end of the RTCM stream. Send partial buffer. - if (espnowOutgoingSpot > 0 && (millis() - espnowLastAdd) > 50) - { - if (espnowState == ESPNOW_PAIRED) - esp_now_send(0, (uint8_t *)&espnowOutgoing, espnowOutgoingSpot); // Send partial packet to all peers - else // if (espnowState == ESPNOW_BROADCASTING) - { - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - esp_now_send(broadcastMac, (uint8_t *)&espnowOutgoing, - espnowOutgoingSpot); // Send packet via broadcast - } - - if (!inMainMenu) - { - if (settings.debugEspNow == true) - systemPrintf("ESPNOW transmitted %d RTCM bytes\r\n", espnowBytesSent + espnowOutgoingSpot); - } - espnowBytesSent = 0; - espnowOutgoingSpot = 0; // Reset - } - - // If we don't receive an ESP NOW packet after some time, set RSSI to very negative - // This removes the ESPNOW icon from the display when the link goes down - if (millis() - lastEspnowRssiUpdate > 5000 && espnowRSSI > -255) - espnowRSSI = -255; - } - } -} - -// Create a struct for ESP NOW pairing -typedef struct PairMessage -{ - uint8_t macAddress[6]; - bool encrypt; - uint8_t channel; - uint8_t crc; // Simple check - add MAC together and limit to 8 bit -} PairMessage; - -// Callback when data is sent -void espnowOnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) -{ - // systemPrint("Last Packet Send Status: "); - // if (status == ESP_NOW_SEND_SUCCESS) - // systemPrintln("Delivery Success"); - // else - // systemPrintln("Delivery Fail"); -} - -// Callback when data is received -void espnowOnDataReceived(const esp_now_recv_info *mac, const uint8_t *incomingData, int len) -{ - if (espnowState == ESPNOW_PAIRING) - { - if (len == sizeof(PairMessage)) // First error check - { - PairMessage pairMessage; - memcpy(&pairMessage, incomingData, sizeof(pairMessage)); - - // Check CRC - uint8_t tempCRC = 0; - for (int x = 0; x < 6; x++) - tempCRC += pairMessage.macAddress[x]; - - if (tempCRC == pairMessage.crc) // 2nd error check - { - memcpy(&receivedMAC, pairMessage.macAddress, 6); - espnowSetState(ESPNOW_MAC_RECEIVED); - } - // else Pair CRC failed - } - } - else - { - espnowRSSI = packetRSSI; // Record this packet's RSSI as an ESP NOW packet - - // We've just received ESP-Now data. We assume this is RTCM and push it directly to the GNSS. - // Determine if ESPNOW is the correction source - if (correctionLastSeen(CORR_ESPNOW)) - { - // Pass RTCM bytes (presumably) from ESP NOW out ESP32-UART to GNSS - gnss->pushRawData((uint8_t *)incomingData, len); - - if ((settings.debugEspNow == true || settings.debugCorrections == true) && !inMainMenu) - systemPrintf("ESPNOW received %d RTCM bytes, pushed to GNSS, RSSI: %d\r\n", len, espnowRSSI); - } - else - { - if ((settings.debugEspNow == true || settings.debugCorrections == true) && !inMainMenu) - systemPrintf("ESPNOW received %d RTCM bytes, NOT pushed due to priority, RSSI: %d\r\n", len, - espnowRSSI); - } - - espnowIncomingRTCM = true; // Display a download icon - lastEspnowRssiUpdate = millis(); - } -} - -// Callback for all RX Packets -// Get RSSI of all incoming management packets: https://esp32.com/viewtopic.php?t=13889 -#ifdef COMPILE_ESPNOW -void promiscuous_rx_cb(void *buf, wifi_promiscuous_pkt_type_t type) -{ - // All espnow traffic uses action frames which are a subtype of the mgmnt frames so filter out everything else. - if (type != WIFI_PKT_MGMT) - return; - - const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buf; - packetRSSI = ppkt->rx_ctrl.rssi; -} -#endif // COMPILE_ESPNOW - -// If WiFi is already enabled, simply add the LR protocol -// If the radio is off entirely, start the radio, turn on only the LR protocol -void espnowStart() -{ - if (settings.enableEspNow == false) - { - espnowStop(); - return; - } - - // Before we can issue esp_wifi_() commands WiFi must be started - if (WiFi.getMode() != WIFI_STA) - WiFi.mode(WIFI_STA); - - // Verify that the necessary protocols are set - uint8_t protocols = 0; - esp_err_t response = esp_wifi_get_protocol(WIFI_IF_STA, &protocols); - if (response != ESP_OK) - systemPrintf("espnowStart: Failed to get protocols: %s\r\n", esp_err_to_name(response)); - - if ((wifiIsRunning() == false) && espnowState == ESPNOW_OFF) - { - // Radio is off, turn it on - if (protocols != (WIFI_PROTOCOL_LR)) - { - response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); // Stops WiFi Station. - if (response != ESP_OK) - systemPrintf("espnowStart: Error setting ESP-Now lone protocol: %s\r\n", esp_err_to_name(response)); - else - { - if (settings.debugEspNow == true) - systemPrintln("WiFi off, ESP-Now added to protocols"); - } - } - else - { - if (settings.debugEspNow == true) - systemPrintln("LR protocol already in place"); - } - } - // If WiFi is on but ESP NOW is off, then enable LR protocol - else if (wifiIsRunning() && espnowState == ESPNOW_OFF) - { - // Enable WiFi + ESP-Now - // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps - if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR)) - { - response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | - WIFI_PROTOCOL_LR); - if (response != ESP_OK) - systemPrintf("espnowStart: Error setting ESP-Now + WiFi protocols: %s\r\n", esp_err_to_name(response)); - else - { - if (settings.debugEspNow == true) - systemPrintln("WiFi on, ESP-Now added to protocols"); - } - } - else - { - if (settings.debugEspNow == true) - systemPrintln("WiFi was already on, and LR protocol already in place"); - } - } - - // If ESP-Now is already active, do nothing - else - { - if (settings.debugEspNow == true) - systemPrintln("ESP-Now already on."); - } - - // WiFi.setSleep(false); //We must disable sleep so that ESP-NOW can readily receive packets - // See: https://github.com/sparkfun/SparkFun_RTK_Everywhere_Firmware/issues/241 - - // Init ESP-NOW - if (esp_now_init() != ESP_OK) - { - systemPrintln("espnowStart: Error starting ESP-Now"); - return; - } - - // Use promiscuous callback to capture RSSI of packet - response = esp_wifi_set_promiscuous(true); - if (response != ESP_OK) - systemPrintf("espnowStart: Error setting promiscuous mode: %s\r\n", esp_err_to_name(response)); - - esp_wifi_set_promiscuous_rx_cb(&promiscuous_rx_cb); - - // Assign channel if not connected to an AP - if (wifiIsConnected() == false) - espnowSetChannel(settings.wifiChannel); - - // Register callbacks - // esp_now_register_send_cb(espnowOnDataSent); - esp_now_register_recv_cb(espnowOnDataReceived); - - if (settings.espnowPeerCount == 0) - { - // Enter broadcast mode - - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - - if (esp_now_is_peer_exist(broadcastMac) == true) - { - if (settings.debugEspNow == true) - systemPrintln("Broadcast peer already exists"); - } - else - { - esp_err_t result = espnowAddPeer(broadcastMac, false); // Encryption not support for broadcast MAC - if (result != ESP_OK) - { - if (settings.debugEspNow == true) - systemPrintln("Failed to add broadcast peer"); - } - else - { - if (settings.debugEspNow == true) - systemPrintln("Broadcast peer added"); - } - } - - espnowSetState(ESPNOW_BROADCASTING); - } - else - { - // If we have peers, move to paired state - espnowSetState(ESPNOW_PAIRED); - - if (settings.debugEspNow == true) - systemPrintf("Adding %d espnow peers\r\n", settings.espnowPeerCount); - - for (int x = 0; x < settings.espnowPeerCount; x++) - { - if (esp_now_is_peer_exist(settings.espnowPeers[x]) == true) - { - if (settings.debugEspNow == true) - systemPrintf("Peer #%d already exists\r\n", x); - } - else - { - esp_err_t result = espnowAddPeer(settings.espnowPeers[x]); - if (result != ESP_OK) - { - if (settings.debugEspNow == true) - systemPrintf("Failed to add peer #%d\r\n", x); - } - } - } - } - - systemPrintln("ESP-Now Started"); -} - -// If WiFi is already enabled, simply remove the LR protocol -// If WiFi is off, stop the radio entirely -void espnowStop() -{ - if (espnowState == ESPNOW_OFF) - return; - - // Turn off promiscuous WiFi mode - esp_err_t response = esp_wifi_set_promiscuous(false); - if (response != ESP_OK) - systemPrintf("espnowStop: Failed to set promiscuous mode: %s\r\n", esp_err_to_name(response)); - - esp_wifi_set_promiscuous_rx_cb(nullptr); - - // Deregister callbacks - // esp_now_unregister_send_cb(); - response = esp_now_unregister_recv_cb(); - if (response != ESP_OK) - systemPrintf("espnowStop: Failed to unregister receive callback: %s\r\n", esp_err_to_name(response)); - - // Forget all ESP-Now Peers - for (int x = 0; x < settings.espnowPeerCount; x++) - espnowRemovePeer(settings.espnowPeers[x]); - - if (WiFi.getMode() != WIFI_STA) - WiFi.mode(WIFI_STA); - - // Verify that the necessary protocols are set - uint8_t protocols = 0; - response = esp_wifi_get_protocol(WIFI_IF_STA, &protocols); - if (response != ESP_OK) - systemPrintf("espnowStop: Failed to get protocols: %s\r\n", esp_err_to_name(response)); - - // Leave WiFi with default settings (no WIFI_PROTOCOL_LR for ESP NOW) - if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N)) - { - response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N); - if (response != ESP_OK) - systemPrintf("espnowStop: Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); - else - { - if (settings.debugEspNow == true) - systemPrintln("espnowStop: WiFi on, ESP-Now removed from protocols"); - } - } - else - { - if (settings.debugEspNow == true) - systemPrintln("espnowStop: ESP-Now already removed from protocols"); - } - - // Deinit ESP-NOW - if (esp_now_deinit() != ESP_OK) - { - systemPrintln("Error deinitializing ESP-NOW"); - return; - } - - espnowSetState(ESPNOW_OFF); - - if (wifiIsRunning() == false) - { - // ESP-NOW was the only thing using the radio so turn WiFi radio off entirely - WiFi.mode(WIFI_OFF); - - if (settings.debugEspNow == true) - systemPrintln("WiFi Radio off entirely"); - } - // If WiFi is on, then restart WiFi - else if (wifiIsRunning()) - { - if (settings.debugEspNow == true) - systemPrintln("ESP-Now starting WiFi"); - wifiStart(); // Force WiFi to restart - } -} - -// Start ESP-Now if needed, put ESP-Now into broadcast state -void espnowBeginPairing() -{ - espnowStart(); - - // To begin pairing, we must add the broadcast MAC to the peer list - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - espnowAddPeer(broadcastMac, false); // Encryption is not supported for multicast addresses - - espnowSetState(ESPNOW_PAIRING); -} - -// Regularly call during pairing to see if we've received a Pairing message -bool espnowIsPaired() -{ - if (espnowState == ESPNOW_MAC_RECEIVED) - { - // Remove broadcast peer - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - espnowRemovePeer(broadcastMac); - - if (esp_now_is_peer_exist(receivedMAC) == true) - { - if (settings.debugEspNow == true) - systemPrintln("Peer already exists"); - } - else - { - // Add new peer to system - espnowAddPeer(receivedMAC); - - // Record this MAC to peer list - memcpy(settings.espnowPeers[settings.espnowPeerCount], receivedMAC, 6); - settings.espnowPeerCount++; - settings.espnowPeerCount %= ESPNOW_MAX_PEERS; - } - - // Send message directly to the received MAC (not unicast), then exit - espnowSendPairMessage(receivedMAC); - - // Enable radio. User may have arrived here from the setup menu rather than serial menu. - settings.enableEspNow = true; - - recordSystemSettings(); // Record enableEspNow and espnowPeerCount to NVM - - espnowSetState(ESPNOW_PAIRED); - return (true); - } - return (false); -} - -// Create special pair packet to a given MAC -esp_err_t espnowSendPairMessage(uint8_t *sendToMac) -{ - // Assemble message to send - PairMessage pairMessage; - - // Get unit MAC address - memcpy(pairMessage.macAddress, wifiMACAddress, 6); - pairMessage.encrypt = false; - pairMessage.channel = 0; - - pairMessage.crc = 0; // Calculate CRC - for (int x = 0; x < 6; x++) - pairMessage.crc += wifiMACAddress[x]; - - return (esp_now_send(sendToMac, (uint8_t *)&pairMessage, sizeof(pairMessage))); // Send packet to given MAC -} - -// Add a given MAC address to the peer list -esp_err_t espnowAddPeer(uint8_t *peerMac) -{ - return (espnowAddPeer(peerMac, true)); // Encrypt by default -} - -esp_err_t espnowAddPeer(uint8_t *peerMac, bool encrypt) -{ - esp_now_peer_info_t peerInfo; - - memcpy(peerInfo.peer_addr, peerMac, 6); - peerInfo.channel = 0; - peerInfo.ifidx = WIFI_IF_STA; - // memcpy(peerInfo.lmk, "RTKProductsLMK56", 16); - // peerInfo.encrypt = encrypt; - peerInfo.encrypt = false; - - esp_err_t result = esp_now_add_peer(&peerInfo); - if (result != ESP_OK) - { - if (settings.debugEspNow == true) - systemPrintf("Failed to add peer: 0x%02X%02X%02X%02X%02X%02X\r\n", peerMac[0], peerMac[1], peerMac[2], - peerMac[3], peerMac[4], peerMac[5]); - } - return (result); -} - -// Remove a given MAC address from the peer list -esp_err_t espnowRemovePeer(uint8_t *peerMac) -{ - esp_err_t response = esp_now_del_peer(peerMac); - if (response != ESP_OK) - { - if (settings.debugEspNow == true) - systemPrintf("Failed to remove peer: %s\r\n", esp_err_to_name(response)); - } - - return (response); -} - -// Update the state of the ESP Now state machine -void espnowSetState(ESPNOWState newState) -{ - if (espnowState == newState && settings.debugEspNow == true) - systemPrint("*"); - espnowState = newState; - - if (settings.debugEspNow == true) - { - systemPrint("espnowState: "); - switch (newState) - { - case ESPNOW_OFF: - systemPrintln("ESPNOW_OFF"); - break; - case ESPNOW_BROADCASTING: - systemPrintln("ESPNOW_BROADCASTING"); - break; - case ESPNOW_PAIRING: - systemPrintln("ESPNOW_PAIRING"); - break; - case ESPNOW_MAC_RECEIVED: - systemPrintln("ESPNOW_MAC_RECEIVED"); - break; - case ESPNOW_PAIRED: - systemPrintln("ESPNOW_PAIRED"); - break; - default: - systemPrintf("Unknown ESPNOW state: %d\r\n", newState); - break; - } - } -} - -void espnowProcessRTCM(byte incoming) -{ - // If we are paired, - // Or if the radio is broadcasting - // Then add bytes to the outgoing buffer - if (espnowState == ESPNOW_PAIRED || espnowState == ESPNOW_BROADCASTING) - { - // Move this byte into ESP NOW to send buffer - espnowOutgoing[espnowOutgoingSpot++] = incoming; - espnowLastAdd = millis(); - } - - // Send buffer when full - if (espnowOutgoingSpot == sizeof(espnowOutgoing)) - { - espnowOutgoingSpot = 0; // Wrap - - if (espnowState == ESPNOW_PAIRED) - esp_now_send(0, (uint8_t *)&espnowOutgoing, sizeof(espnowOutgoing)); // Send packet to all peers - else // if (espnowState == ESPNOW_BROADCASTING) - { - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - esp_now_send(broadcastMac, (uint8_t *)&espnowOutgoing, - sizeof(espnowOutgoing)); // Send packet via broadcast - } - - delay(10); // We need a small delay between sending multiple packets - - espnowBytesSent += sizeof(espnowOutgoing); - - espnowOutgoingRTCM = true; - } -} - -// A blocking function that is used to pair two devices -// either through the serial menu or AP config -void espnowStaticPairing() -{ - systemPrintln("Begin ESP NOW Pairing"); - - // Start ESP-Now if needed, put ESP-Now into broadcast state - espnowBeginPairing(); - - // Begin sending our MAC every 250ms until a remote device sends us there info - randomSeed(millis()); - - systemPrintln("Begin pairing. Place other unit in pairing mode. Press any key to exit."); - clearBuffer(); - - uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - - bool exitPair = false; - while (exitPair == false) - { - if (systemAvailable()) - { - systemPrintln("User pressed button. Pairing canceled."); - break; - } - - int timeout = 1000 + random(0, 100); // Delay 1000 to 1100ms - for (int x = 0; x < timeout; x++) - { - delay(1); - - if (espnowIsPaired() == true) // Check if we've received a pairing message - { - systemPrintln("Pairing compete"); - exitPair = true; - break; - } - } - - espnowSendPairMessage(broadcastMac); // Send unit's MAC address over broadcast, no ack, no encryption - - systemPrintln("Scanning for other radio..."); - } -} - -// Returns the current channel being used by WiFi -uint8_t espnowGetChannel() -{ - if (espnowState == ESPNOW_OFF) - return 0; - - bool originalPromiscuousMode = false; - esp_err_t response = esp_wifi_get_promiscuous(&originalPromiscuousMode); - if (response != ESP_OK) - systemPrintf("getPromiscuous failed: %s\r\n", esp_err_to_name(response)); - - // We must be in promiscuous mode to get the channel number - if (originalPromiscuousMode == false) - esp_wifi_set_promiscuous(true); - - uint8_t primaryChannelNumber = 0; - wifi_second_chan_t secondaryChannelNumber; - - response = esp_wifi_get_channel(&primaryChannelNumber, &secondaryChannelNumber); - if (response != ESP_OK) - systemPrintf("getChannel failed: %s\r\n", esp_err_to_name(response)); - - // Return to the original mode - if (originalPromiscuousMode == false) - esp_wifi_set_promiscuous(false); - - return (primaryChannelNumber); -} - -// Returns the current channel being used by WiFi -bool espnowSetChannel(uint8_t channelNumber) -{ - if (wifiIsConnected() == true) - { - systemPrintln("ESP-NOW channel can't be modified while WiFi is connected."); - return (false); - } - - bool originalPromiscuousMode = false; - esp_err_t response = esp_wifi_get_promiscuous(&originalPromiscuousMode); - if (response != ESP_OK) - systemPrintf("getPromiscuous failed: %s\r\n", esp_err_to_name(response)); - - // We must be in promiscuous mode to set the channel number - if (originalPromiscuousMode == false) - esp_wifi_set_promiscuous(true); - - bool setSuccess = false; - response = esp_wifi_set_channel(channelNumber, WIFI_SECOND_CHAN_NONE); - if (response != ESP_OK) - systemPrintf("setChannel to %d failed: %s\r\n", channelNumber, esp_err_to_name(response)); - else - setSuccess = true; - - // Return to the original mode - if (originalPromiscuousMode == false) - esp_wifi_set_promiscuous(false); - - return (setSuccess); -} - -#endif // COMPILE_ESPNOW diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index c65860e1d..3f1ed70d4 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -2543,4 +2543,749 @@ void RTK_WIFI::verifyTables() } } +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + WiFi Status Values: + WL_CONNECTED: assigned when connected to a WiFi network + WL_CONNECTION_LOST: assigned when the connection is lost + WL_CONNECT_FAILED: assigned when the connection fails for all the attempts + WL_DISCONNECTED: assigned when disconnected from a network + WL_IDLE_STATUS: it is a temporary status assigned when WiFi.begin() is called and + remains active until the number of attempts expires (resulting in + WL_CONNECT_FAILED) or a connection is established (resulting in + WL_CONNECTED) + WL_NO_SHIELD: assigned when no WiFi shield is present + WL_NO_SSID_AVAIL: assigned when no SSID are available + WL_SCAN_COMPLETED: assigned when the scan networks is completed + =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +//---------------------------------------- +// Globals +//---------------------------------------- + +int wifiFailedConnectionAttempts = 0; // Count the number of connection attempts between restarts + +bool restartWiFi = false; // Restart WiFi if user changes anything + +WiFiMulti *wifiMulti; + +//---------------------------------------- +// Constants +//---------------------------------------- + +#define WIFI_MAX_TIMEOUT (15 * 60 * 1000) +#define WIFI_MIN_TIMEOUT (15 * 1000) + +//---------------------------------------- +// Locals +//---------------------------------------- + +// Start timeout +static uint32_t wifiStartTimeout; +static uint32_t wifiStartLastTry; // The last time WiFi start was attempted + +// WiFi Timer usage: +// * Measure interval to display IP address +static unsigned long wifiDisplayTimer; + +static bool wifiStationRunning; +static bool wifiApRunning; + +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +// WiFi Routines +//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +//---------------------------------------- +// Set WiFi credentials +// Enable TCP connections +//---------------------------------------- +void menuWiFi() +{ + while (1) + { + networkDisplayInterface(NETWORK_WIFI); + + systemPrintln(); + systemPrintln("Menu: WiFi Networks"); + + for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + { + systemPrintf("%d) SSID %d: %s\r\n", (x * 2) + 1, x + 1, settings.wifiNetworks[x].ssid); + systemPrintf("%d) Password %d: %s\r\n", (x * 2) + 2, x + 1, settings.wifiNetworks[x].password); + } + + systemPrint("a) Configure device via WiFi Access Point or connect to WiFi: "); + systemPrintf("%s\r\n", settings.wifiConfigOverAP ? "AP" : "WiFi"); + + systemPrint("c) Captive Portal: "); + systemPrintf("%s\r\n", settings.enableCaptivePortal ? "Enabled" : "Disabled"); + + systemPrintln("x) Exit"); + + byte incoming = getUserInputCharacterNumber(); + + if (incoming >= 1 && incoming <= MAX_WIFI_NETWORKS * 2) + { + int arraySlot = ((incoming - 1) / 2); // Adjust incoming to array starting at 0 + + if (incoming % 2 == 1) + { + systemPrintf("Enter SSID network %d: ", arraySlot + 1); + getUserInputString(settings.wifiNetworks[arraySlot].ssid, + sizeof(settings.wifiNetworks[arraySlot].ssid)); + restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi + } + else + { + systemPrintf("Enter Password for %s: ", settings.wifiNetworks[arraySlot].ssid); + getUserInputString(settings.wifiNetworks[arraySlot].password, + sizeof(settings.wifiNetworks[arraySlot].password)); + restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi + } + } + else if (incoming == 'a') + { + settings.wifiConfigOverAP ^= 1; + restartWiFi = true; + } + else if (incoming == 'c') + { + settings.enableCaptivePortal ^= 1; + } + else if (incoming == 'x') + break; + else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_EMPTY) + break; + else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_TIMEOUT) + break; + else + printUnknown(incoming); + } + + // Erase passwords from empty SSID entries + for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + { + if (strlen(settings.wifiNetworks[x].ssid) == 0) + strcpy(settings.wifiNetworks[x].password, ""); + } + + clearBuffer(); // Empty buffer of any newline chars +} + +//---------------------------------------- +// Starts WiFi in STA, AP, or STA_AP mode depending on bools +// Returns true if STA connects, or if AP is started +//---------------------------------------- +bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) +{ + // Is a change needed? + if (startWiFiStation && startWiFiAP && WiFi.getMode() == WIFI_AP_STA && WiFi.status() == WL_CONNECTED) + return (true); // There is nothing needing to be changed + + if (startWiFiStation && WiFi.getMode() == WIFI_STA && WiFi.status() == WL_CONNECTED) + return (true); // There is nothing needing to be changed + + if (startWiFiAP && WiFi.getMode() == WIFI_AP) + return (true); // There is nothing needing to be changed + + wifiStationRunning = false; // Mark it as offline while we mess about + wifiApRunning = false; // Mark it as offline while we mess about + + wifi_mode_t wifiMode = WIFI_OFF; + wifi_interface_t wifiInterface = WIFI_IF_STA; + + // Establish what WiFi mode we need to be in + if (startWiFiStation && startWiFiAP) + { + systemPrintln("Starting WiFi AP+Station"); + wifiMode = WIFI_AP_STA; + wifiInterface = WIFI_IF_AP; // There is no WIFI_IF_AP_STA + } + else if (startWiFiStation) + { + systemPrintln("Starting WiFi Station"); + wifiMode = WIFI_STA; + wifiInterface = WIFI_IF_STA; + } + else if (startWiFiAP) + { + systemPrintln("Starting WiFi AP"); + wifiMode = WIFI_AP; + wifiInterface = WIFI_IF_AP; + } + + displayWiFiConnect(); + + if (WiFi.mode(wifiMode) == false) // Start WiFi in the appropriate mode + { + systemPrintln("WiFi failed to set mode"); + return (false); + } + + // Verify that the necessary protocols are set + uint8_t protocols = 0; + esp_err_t response = esp_wifi_get_protocol(wifiInterface, &protocols); + if (response != ESP_OK) + systemPrintf("Failed to get protocols: %s\r\n", esp_err_to_name(response)); + + // If ESP-NOW is running, blend in ESP-NOW protocol. + if (espnowState > ESPNOW_OFF) + { + if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR)) + { + esp_err_t response = + esp_wifi_set_protocol(wifiInterface, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | + WIFI_PROTOCOL_LR); // Enable WiFi + ESP-Now. + if (response != ESP_OK) + systemPrintf("Error setting WiFi + ESP-NOW protocols: %s\r\n", esp_err_to_name(response)); + } + } + else + { + // Make sure default WiFi protocols are in place + if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N)) + { + esp_err_t response = esp_wifi_set_protocol(wifiInterface, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | + WIFI_PROTOCOL_11N); // Enable WiFi. + if (response != ESP_OK) + systemPrintf("Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); + } + } + + // Start AP with fixed IP + if (wifiMode == WIFI_AP || wifiMode == WIFI_AP_STA) + { + IPAddress local_IP(192, 168, 4, 1); + IPAddress gateway(192, 168, 4, 1); + IPAddress subnet(255, 255, 255, 0); + + WiFi.softAPConfig(local_IP, gateway, subnet); + + // Determine the AP name + // If in web config mode then 'RTK Config' + // otherwise 'RTK Caster' + + char softApSsid[strlen("RTK Config")]; // Must be short enough to fit OLED Width + + if (inWebConfigMode()) + strncpy(softApSsid, "RTK Config", sizeof(softApSsid)); + // snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Config"); // TODO use + // settings.webconfigApName + else + strncpy(softApSsid, "RTK Caster", sizeof(softApSsid)); + // snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Caster"); + + if (WiFi.softAP(softApSsid) == false) + { + systemPrintln("WiFi AP failed to start"); + return (false); + } + systemPrintf("WiFi AP '%s' started with IP: ", softApSsid); + systemPrintln(WiFi.softAPIP()); + + // Start DNS Server + if (dnsServer.start(53, "*", WiFi.softAPIP()) == false) + { + systemPrintln("WiFi DNS Server failed to start"); + return (false); + } + else + { + if (settings.debugWifiState == true) + systemPrintln("DNS Server started"); + } + + wifiApRunning = true; + + // If we're only here to start the AP, then we're done + if (wifiMode == WIFI_AP) + return true; + } + + systemPrintln("Connecting to WiFi... "); + + if (wifiMulti == nullptr) + wifiMulti = new WiFiMulti; + + // Load SSIDs + wifiMulti->APlistClean(); + for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + { + if (strlen(settings.wifiNetworks[x].ssid) > 0) + wifiMulti->addAP((const char *)&settings.wifiNetworks[x].ssid, + (const char *)&settings.wifiNetworks[x].password); + } + + int wifiStatus = wifiMulti->run(timeout); + if (wifiStatus == WL_CONNECTED) + { + wifiResetTimeout(); // If we successfully connected then reset the throttling timeout + wifiStationRunning = true; + return true; + } + if (wifiStatus == WL_DISCONNECTED) + systemPrint("No friendly WiFi networks detected.\r\n"); + else + { + systemPrintf("WiFi failed to connect: error #%d - %s\r\n", wifiStatus, wifiPrintState((wl_status_t)wifiStatus)); + } + wifiStationRunning = false; + return false; +} + +//---------------------------------------- +// Display the WiFi state +//---------------------------------------- +void wifiDisplayState() +{ + systemPrintf("WiFi: %s\r\n", networkInterfaceHasInternet(NETWORK_WIFI) ? "Online" : "Offline"); + systemPrintf(" MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\r\n", wifiMACAddress[0], wifiMACAddress[1], + wifiMACAddress[2], wifiMACAddress[3], wifiMACAddress[4], wifiMACAddress[5]); + if (networkInterfaceHasInternet(NETWORK_WIFI)) + { + // Get the DNS addresses + IPAddress dns1 = WiFi.STA.dnsIP(0); + IPAddress dns2 = WiFi.STA.dnsIP(1); + IPAddress dns3 = WiFi.STA.dnsIP(2); + + // Get the WiFi status + wl_status_t wifiStatus = WiFi.status(); + + const char *wifiStatusString = wifiPrintState(wifiStatus); + + // Display the WiFi state + systemPrintf(" SSID: %s\r\n", WiFi.STA.SSID()); + systemPrintf(" IP Address: %s\r\n", WiFi.STA.localIP().toString().c_str()); + systemPrintf(" Subnet Mask: %s\r\n", WiFi.STA.subnetMask().toString().c_str()); + systemPrintf(" Gateway Address: %s\r\n", WiFi.STA.gatewayIP().toString().c_str()); + if ((uint32_t)dns3) + systemPrintf(" DNS Address: %s, %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str(), + dns3.toString().c_str()); + else if ((uint32_t)dns3) + systemPrintf(" DNS Address: %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str()); + else + systemPrintf(" DNS Address: %s\r\n", dns1.toString().c_str()); + systemPrintf(" WiFi Strength: %d dBm\r\n", WiFi.RSSI()); + systemPrintf(" WiFi Status: %d\r\n", wifiStatusString); + } +} + +//---------------------------------------- +// Process the WiFi events +//---------------------------------------- +void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) +{ + char ssid[sizeof(info.wifi_sta_connected.ssid) + 1]; + IPAddress ipAddress; + + // If we are in AP or AP_STA, the network is immediately marked online + // Once AP is online, don't stop WiFi because STA has various events + if (WiFi.getMode() == WIFI_MODE_STA) + { + // Take the network offline if necessary + if (networkInterfaceHasInternet(NETWORK_WIFI) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP) && + (event != ARDUINO_EVENT_WIFI_STA_GOT_IP6)) + { + if (settings.debugWifiState) + systemPrintf("Stopping WiFi because of event # %d\r\n", event); + + networkStop(NETWORK_WIFI, settings.debugNetworkLayer); // Stop WiFi to allow it to restart + } + } + + // WiFi State Machine + // + // .--------+<----------+<-----------+<-------------+<----------+<----------+<------------. + // v | | | | | | | + // STOP --> READY --> STA_START --> SCAN_DONE --> CONNECTED --> GOT_IP --> LOST_IP --> DISCONNECTED + // ^ ^ | | + // | '-----------' | + // '-------------------------------------' + // + // Handle the event + switch (event) + { + default: + systemPrintf("ERROR: Unknown WiFi event: %d\r\n", event); + break; + + case ARDUINO_EVENT_WIFI_OFF: + systemPrintln("WiFi Off"); + break; + + case ARDUINO_EVENT_WIFI_READY: + if (settings.debugWifiState) + systemPrintln("WiFi Ready"); + WiFi.setHostname(settings.mdnsHostName); + break; + + case ARDUINO_EVENT_WIFI_SCAN_DONE: + if (settings.debugWifiState) + systemPrintln("WiFi Scan Done"); + // wifi_event_sta_scan_done_t info.wifi_scan_done; + break; + + case ARDUINO_EVENT_WIFI_STA_START: + if (settings.debugWifiState) + systemPrintln("WiFi STA Started"); + break; + + case ARDUINO_EVENT_WIFI_STA_STOP: + if (settings.debugWifiState) + systemPrintln("WiFi STA Stopped"); + break; + + case ARDUINO_EVENT_WIFI_STA_CONNECTED: + memcpy(ssid, info.wifi_sta_connected.ssid, info.wifi_sta_connected.ssid_len); + ssid[info.wifi_sta_connected.ssid_len] = 0; + + ipAddress = WiFi.localIP(); + systemPrintf("WiFi STA connected to %s with IP address: ", ssid); + systemPrintln(ipAddress); + + WiFi.setHostname(settings.mdnsHostName); + break; + + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: + memcpy(ssid, info.wifi_sta_disconnected.ssid, info.wifi_sta_disconnected.ssid_len); + ssid[info.wifi_sta_disconnected.ssid_len] = 0; + systemPrintf("WiFi STA disconnected from %s\r\n", ssid); + // wifi_event_sta_disconnected_t info.wifi_sta_disconnected; + break; + + case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: + systemPrintln("WiFi STA Auth Mode Changed"); + // wifi_event_sta_authmode_change_t info.wifi_sta_authmode_change; + break; + + case ARDUINO_EVENT_WIFI_STA_GOT_IP: + if (settings.debugWifiState) + { + ipAddress = WiFi.localIP(); + systemPrint("WiFi STA Got IPv4: "); + systemPrintln(ipAddress); + } + networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); + break; + + case ARDUINO_EVENT_WIFI_STA_GOT_IP6: + if (settings.debugWifiState) + { + ipAddress = WiFi.localIP(); + systemPrint("WiFi STA Got IPv6: "); + systemPrintln(ipAddress); + } + networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); + break; + + case ARDUINO_EVENT_WIFI_STA_LOST_IP: + systemPrintln("WiFi STA Lost IP"); + break; + } +} + +//---------------------------------------- +// Determine if WIFI is connected +//---------------------------------------- +bool wifiIsConnected() +{ + bool connected; + + connected = (WiFi.status() == WL_CONNECTED); + return connected; +} + +//---------------------------------------- +// Determine if WiFi Station is running +//---------------------------------------- +bool wifiStationIsRunning() +{ + return wifiStationRunning; +} + +//---------------------------------------- +// Determine if WiFi AP is running +//---------------------------------------- +bool wifiApIsRunning() +{ + return wifiApRunning; +} + +//---------------------------------------- +// Determine if either Station or AP is running +//---------------------------------------- +bool wifiIsRunning() +{ + if (wifiStationRunning || wifiApRunning) + return true; + return false; +} + +//---------------------------------------- +// Counts the number of entered SSIDs +//---------------------------------------- +int wifiNetworkCount() +{ + // Count SSIDs + int networkCount = 0; + for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + { + if (strlen(settings.wifiNetworks[x].ssid) > 0) + networkCount++; + } + return networkCount; +} + +//---------------------------------------- +// Given a status, return the associated state or error +//---------------------------------------- +const char *wifiPrintState(wl_status_t wifiStatus) +{ + switch (wifiStatus) + { + case WL_NO_SHIELD: + return ("WL_NO_SHIELD"); // 255 + case WL_STOPPED: + return ("WL_STOPPED"); + case WL_IDLE_STATUS: // 0 + return ("WL_IDLE_STATUS"); + case WL_NO_SSID_AVAIL: // 1 + return ("WL_NO_SSID_AVAIL"); + case WL_SCAN_COMPLETED: // 2 + return ("WL_SCAN_COMPLETED"); + case WL_CONNECTED: // 3 + return ("WL_CONNECTED"); + case WL_CONNECT_FAILED: // 4 + return ("WL_CONNECT_FAILED"); + case WL_CONNECTION_LOST: // 5 + return ("WL_CONNECTION_LOST"); + case WL_DISCONNECTED: // 6 + return ("WL_DISCONNECTED"); + } + return ("WiFi Status Unknown"); +} + +//---------------------------------------- +// Starts the WiFi connection state machine (moves from WIFI_STATE_OFF to WIFI_STATE_CONNECTING) +// Sets the appropriate protocols (WiFi + ESP-Now) +// If radio is off entirely, start WiFi +// If ESP-Now is active, only add the LR protocol +// Returns true if WiFi has connected and false otherwise +//---------------------------------------- +bool wifiStart() +{ + int wifiStatus; + + // Determine which parts of WiFi need to be started + bool startWiFiStation = false; + bool startWiFiAp = false; + + uint16_t consumerTypes = networkGetConsumerTypes(); + + // The consumers need station + if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) + startWiFiStation = true; + + // The consumers need AP + if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) + startWiFiAp = true; + + if (startWiFiStation == false && startWiFiAp == false) + { + systemPrintln("wifiStart() requested without any NETCONSUMER combination"); + WIFI_STOP(); + return (false); + } + + // Determine if WiFi is already running + if (startWiFiStation == wifiStationRunning && startWiFiAp == wifiApRunning) + { + if (settings.debugWifiState == true) + systemPrintln("WiFi is already running with requested setup"); + return (true); + } + + // Handle special cases if no networks have been entered + if (wifiNetworkCount() == 0) + { + if (startWiFiStation == true && startWiFiAp == false) + { + systemPrintln("Error: Please enter at least one SSID before using WiFi"); + displayNoSSIDs(2000); + WIFI_STOP(); + return false; + } + else if (startWiFiStation == true && startWiFiAp == true) + { + systemPrintln("Error: No SSID available to start WiFi Station during AP"); + // Allow the system to continue in AP only mode + startWiFiStation = false; + } + } + + // Start WiFi + wifiConnect(startWiFiStation, startWiFiAp, settings.wifiConnectTimeoutMs); + + // If we are in AP only mode, as long as the AP is started, return true + if (WiFi.getMode() == WIFI_MODE_AP) + return (wifiApIsRunning); + + // If we are in STA or AP+STA mode, return if the station connected successfully + wifiStatus = WiFi.status(); + return (wifiStatus == WL_CONNECTED); +} + +//---------------------------------------- +// Set WiFi timeout back to zero +// Useful if other things (such as a successful ethernet connection) need to reset wifi timeout +//---------------------------------------- +void wifiResetTimeout() +{ + wifiStartTimeout = 0; + if (settings.debugWifiState == true) + systemPrintln("WiFi: Start timeout reset to zero"); +} + +//---------------------------------------- +//---------------------------------------- +uint32_t wifiGetStartTimeout() +{ + return (wifiStartTimeout); +} + +//---------------------------------------- +// Reset the last WiFi start attempt +// Useful when WiFi settings have changed +//---------------------------------------- +void wifiResetThrottleTimeout() +{ + wifiStartLastTry = 0; +} + +//---------------------------------------- +// Start WiFi with throttling +//---------------------------------------- +void wifiThrottledStart(NetIndex_t index, uintptr_t parameter, bool debug) +{ + int seconds; + int minutes; + + // Restart delay + if ((millis() - wifiStartLastTry) < wifiStartTimeout) + return; + wifiStartLastTry = millis(); + + // Start WiFi + if (wifiStart()) + { + networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); + wifiFailedConnectionAttempts = 0; + } + else + { + // Increase the timeout + wifiStartTimeout <<= 1; + if (!wifiStartTimeout) + wifiStartTimeout = WIFI_MIN_TIMEOUT; + else if (wifiStartTimeout > WIFI_MAX_TIMEOUT) + wifiStartTimeout = WIFI_MAX_TIMEOUT; + + wifiFailedConnectionAttempts++; + + // Display the delay + seconds = wifiStartTimeout / MILLISECONDS_IN_A_SECOND; + minutes = seconds / SECONDS_IN_A_MINUTE; + seconds -= minutes * SECONDS_IN_A_MINUTE; + if (settings.debugWifiState) + systemPrintf("WiFi: Delaying %2d:%02d before restarting WiFi\r\n", minutes, seconds); + } +} + +//---------------------------------------- +// WiFi start sequence +//---------------------------------------- +NETWORK_POLL_SEQUENCE wifiStartSequence[] = { + // State Parameter Description + {wifiThrottledStart, 0, "Initialize WiFi"}, + {nullptr, 0, "Termination"}, +}; + +//---------------------------------------- +// WiFi stop sequence +//---------------------------------------- +NETWORK_POLL_SEQUENCE wifiStopSequence[] = { + // State Parameter Description + {wifiStop, 0, "Shutdown WiFi"}, + {nullptr, 0, "Termination"}, +}; + +//---------------------------------------- +// Stop WiFi and release all resources +//---------------------------------------- +void wifiStop() +{ + // Stop the web server + stopWebServer(); + + // Stop the DNS server if we were using the captive portal + if (((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) && settings.enableCaptivePortal) + dnsServer.stop(); + + wifiFailedConnectionAttempts = 0; // Reset the counter + + // If ESP-Now is active, change protocol to only Long Range + if (espnowState > ESPNOW_OFF) + { + if (WiFi.getMode() != WIFI_STA) + WiFi.mode(WIFI_STA); + + // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps + // esp_wifi_set_protocol requires WiFi to be started + esp_err_t response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); + if (response != ESP_OK) + systemPrintf("wifiShutdown: Error setting ESP-Now lone protocol: %s\r\n", esp_err_to_name(response)); + else + { + if (settings.debugWifiState == true) + systemPrintln("WiFi disabled, ESP-Now left in place"); + } + } + else + { + WiFi.mode(WIFI_OFF); + if (settings.debugWifiState == true) + systemPrintln("WiFi Stopped"); + } + + // Take the network offline + networkInterfaceInternetConnectionLost(NETWORK_WIFI); + + if (wifiMulti != nullptr) + wifiMulti = nullptr; + + // Display the heap state + reportHeapNow(settings.debugWifiState); + wifiStationRunning = false; + wifiApRunning = false; +} + +// Needed for wifiStopSequence +void wifiStop(NetIndex_t index, uintptr_t parameter, bool debug) +{ + wifiStop(); + networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); +} + +// Returns true if we deem WiFi is not going to connect +// Used to allow cellular to start +bool wifiUnavailable() +{ + if(wifiNetworkCount() == 0) + return true; + + if (wifiFailedConnectionAttempts > 2) + return true; + + return false; +} + #endif // COMPILE_WIFI diff --git a/Firmware/RTK_Everywhere/WiFi_old.ino b/Firmware/RTK_Everywhere/WiFi_old.ino deleted file mode 100644 index 25112b6d6..000000000 --- a/Firmware/RTK_Everywhere/WiFi_old.ino +++ /dev/null @@ -1,751 +0,0 @@ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - WiFi Status Values: - WL_CONNECTED: assigned when connected to a WiFi network - WL_CONNECTION_LOST: assigned when the connection is lost - WL_CONNECT_FAILED: assigned when the connection fails for all the attempts - WL_DISCONNECTED: assigned when disconnected from a network - WL_IDLE_STATUS: it is a temporary status assigned when WiFi.begin() is called and - remains active until the number of attempts expires (resulting in - WL_CONNECT_FAILED) or a connection is established (resulting in - WL_CONNECTED) - WL_NO_SHIELD: assigned when no WiFi shield is present - WL_NO_SSID_AVAIL: assigned when no SSID are available - WL_SCAN_COMPLETED: assigned when the scan networks is completed - =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -//---------------------------------------- -// Globals -//---------------------------------------- - -int wifiFailedConnectionAttempts = 0; // Count the number of connection attempts between restarts - -bool restartWiFi = false; // Restart WiFi if user changes anything - -#ifdef COMPILE_WIFI - -WiFiMulti *wifiMulti; - -//---------------------------------------- -// Constants -//---------------------------------------- - -#define WIFI_MAX_TIMEOUT (15 * 60 * 1000) -#define WIFI_MIN_TIMEOUT (15 * 1000) - -//---------------------------------------- -// Locals -//---------------------------------------- - -// Start timeout -static uint32_t wifiStartTimeout; -static uint32_t wifiStartLastTry; // The last time WiFi start was attempted - -// WiFi Timer usage: -// * Measure interval to display IP address -static unsigned long wifiDisplayTimer; - -// DNS server for Captive Portal -extern DNSServer dnsServer; - -static bool wifiStationRunning; -static bool wifiApRunning; - -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// WiFi Routines -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - -//---------------------------------------- -// Set WiFi credentials -// Enable TCP connections -//---------------------------------------- -void menuWiFi() -{ - while (1) - { - networkDisplayInterface(NETWORK_WIFI); - - systemPrintln(); - systemPrintln("Menu: WiFi Networks"); - - for (int x = 0; x < MAX_WIFI_NETWORKS; x++) - { - systemPrintf("%d) SSID %d: %s\r\n", (x * 2) + 1, x + 1, settings.wifiNetworks[x].ssid); - systemPrintf("%d) Password %d: %s\r\n", (x * 2) + 2, x + 1, settings.wifiNetworks[x].password); - } - - systemPrint("a) Configure device via WiFi Access Point or connect to WiFi: "); - systemPrintf("%s\r\n", settings.wifiConfigOverAP ? "AP" : "WiFi"); - - systemPrint("c) Captive Portal: "); - systemPrintf("%s\r\n", settings.enableCaptivePortal ? "Enabled" : "Disabled"); - - systemPrintln("x) Exit"); - - byte incoming = getUserInputCharacterNumber(); - - if (incoming >= 1 && incoming <= MAX_WIFI_NETWORKS * 2) - { - int arraySlot = ((incoming - 1) / 2); // Adjust incoming to array starting at 0 - - if (incoming % 2 == 1) - { - systemPrintf("Enter SSID network %d: ", arraySlot + 1); - getUserInputString(settings.wifiNetworks[arraySlot].ssid, - sizeof(settings.wifiNetworks[arraySlot].ssid)); - restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi - } - else - { - systemPrintf("Enter Password for %s: ", settings.wifiNetworks[arraySlot].ssid); - getUserInputString(settings.wifiNetworks[arraySlot].password, - sizeof(settings.wifiNetworks[arraySlot].password)); - restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi - } - } - else if (incoming == 'a') - { - settings.wifiConfigOverAP ^= 1; - restartWiFi = true; - } - else if (incoming == 'c') - { - settings.enableCaptivePortal ^= 1; - } - else if (incoming == 'x') - break; - else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_EMPTY) - break; - else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_TIMEOUT) - break; - else - printUnknown(incoming); - } - - // Erase passwords from empty SSID entries - for (int x = 0; x < MAX_WIFI_NETWORKS; x++) - { - if (strlen(settings.wifiNetworks[x].ssid) == 0) - strcpy(settings.wifiNetworks[x].password, ""); - } - - clearBuffer(); // Empty buffer of any newline chars -} - -//---------------------------------------- -// Starts WiFi in STA, AP, or STA_AP mode depending on bools -// Returns true if STA connects, or if AP is started -//---------------------------------------- -bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) -{ - // Is a change needed? - if (startWiFiStation && startWiFiAP && WiFi.getMode() == WIFI_AP_STA && WiFi.status() == WL_CONNECTED) - return (true); // There is nothing needing to be changed - - if (startWiFiStation && WiFi.getMode() == WIFI_STA && WiFi.status() == WL_CONNECTED) - return (true); // There is nothing needing to be changed - - if (startWiFiAP && WiFi.getMode() == WIFI_AP) - return (true); // There is nothing needing to be changed - - wifiStationRunning = false; // Mark it as offline while we mess about - wifiApRunning = false; // Mark it as offline while we mess about - - wifi_mode_t wifiMode = WIFI_OFF; - wifi_interface_t wifiInterface = WIFI_IF_STA; - - // Establish what WiFi mode we need to be in - if (startWiFiStation && startWiFiAP) - { - systemPrintln("Starting WiFi AP+Station"); - wifiMode = WIFI_AP_STA; - wifiInterface = WIFI_IF_AP; // There is no WIFI_IF_AP_STA - } - else if (startWiFiStation) - { - systemPrintln("Starting WiFi Station"); - wifiMode = WIFI_STA; - wifiInterface = WIFI_IF_STA; - } - else if (startWiFiAP) - { - systemPrintln("Starting WiFi AP"); - wifiMode = WIFI_AP; - wifiInterface = WIFI_IF_AP; - } - - displayWiFiConnect(); - - if (WiFi.mode(wifiMode) == false) // Start WiFi in the appropriate mode - { - systemPrintln("WiFi failed to set mode"); - return (false); - } - - // Verify that the necessary protocols are set - uint8_t protocols = 0; - esp_err_t response = esp_wifi_get_protocol(wifiInterface, &protocols); - if (response != ESP_OK) - systemPrintf("Failed to get protocols: %s\r\n", esp_err_to_name(response)); - - // If ESP-NOW is running, blend in ESP-NOW protocol. - if (espnowState > ESPNOW_OFF) - { - if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR)) - { - esp_err_t response = - esp_wifi_set_protocol(wifiInterface, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | - WIFI_PROTOCOL_LR); // Enable WiFi + ESP-Now. - if (response != ESP_OK) - systemPrintf("Error setting WiFi + ESP-NOW protocols: %s\r\n", esp_err_to_name(response)); - } - } - else - { - // Make sure default WiFi protocols are in place - if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N)) - { - esp_err_t response = esp_wifi_set_protocol(wifiInterface, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | - WIFI_PROTOCOL_11N); // Enable WiFi. - if (response != ESP_OK) - systemPrintf("Error setting WiFi protocols: %s\r\n", esp_err_to_name(response)); - } - } - - // Start AP with fixed IP - if (wifiMode == WIFI_AP || wifiMode == WIFI_AP_STA) - { - IPAddress local_IP(192, 168, 4, 1); - IPAddress gateway(192, 168, 4, 1); - IPAddress subnet(255, 255, 255, 0); - - WiFi.softAPConfig(local_IP, gateway, subnet); - - // Determine the AP name - // If in web config mode then 'RTK Config' - // otherwise 'RTK Caster' - - char softApSsid[strlen("RTK Config")]; // Must be short enough to fit OLED Width - - if (inWebConfigMode()) - strncpy(softApSsid, "RTK Config", sizeof(softApSsid)); - // snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Config"); // TODO use - // settings.webconfigApName - else - strncpy(softApSsid, "RTK Caster", sizeof(softApSsid)); - // snprintf("%s", sizeof(softApSsid), softApSsid, (const char)"RTK Caster"); - - if (WiFi.softAP(softApSsid) == false) - { - systemPrintln("WiFi AP failed to start"); - return (false); - } - systemPrintf("WiFi AP '%s' started with IP: ", softApSsid); - systemPrintln(WiFi.softAPIP()); - - // Start DNS Server - if (dnsServer.start(53, "*", WiFi.softAPIP()) == false) - { - systemPrintln("WiFi DNS Server failed to start"); - return (false); - } - else - { - if (settings.debugWifiState == true) - systemPrintln("DNS Server started"); - } - - wifiApRunning = true; - - // If we're only here to start the AP, then we're done - if (wifiMode == WIFI_AP) - return true; - } - - systemPrintln("Connecting to WiFi... "); - - if (wifiMulti == nullptr) - wifiMulti = new WiFiMulti; - - // Load SSIDs - wifiMulti->APlistClean(); - for (int x = 0; x < MAX_WIFI_NETWORKS; x++) - { - if (strlen(settings.wifiNetworks[x].ssid) > 0) - wifiMulti->addAP((const char *)&settings.wifiNetworks[x].ssid, - (const char *)&settings.wifiNetworks[x].password); - } - - int wifiStatus = wifiMulti->run(timeout); - if (wifiStatus == WL_CONNECTED) - { - wifiResetTimeout(); // If we successfully connected then reset the throttling timeout - wifiStationRunning = true; - return true; - } - if (wifiStatus == WL_DISCONNECTED) - systemPrint("No friendly WiFi networks detected.\r\n"); - else - { - systemPrintf("WiFi failed to connect: error #%d - %s\r\n", wifiStatus, wifiPrintState((wl_status_t)wifiStatus)); - } - wifiStationRunning = false; - return false; -} - -//---------------------------------------- -// Display the WiFi state -//---------------------------------------- -void wifiDisplayState() -{ - systemPrintf("WiFi: %s\r\n", networkInterfaceHasInternet(NETWORK_WIFI) ? "Online" : "Offline"); - systemPrintf(" MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\r\n", wifiMACAddress[0], wifiMACAddress[1], - wifiMACAddress[2], wifiMACAddress[3], wifiMACAddress[4], wifiMACAddress[5]); - if (networkInterfaceHasInternet(NETWORK_WIFI)) - { - // Get the DNS addresses - IPAddress dns1 = WiFi.STA.dnsIP(0); - IPAddress dns2 = WiFi.STA.dnsIP(1); - IPAddress dns3 = WiFi.STA.dnsIP(2); - - // Get the WiFi status - wl_status_t wifiStatus = WiFi.status(); - - const char *wifiStatusString = wifiPrintState(wifiStatus); - - // Display the WiFi state - systemPrintf(" SSID: %s\r\n", WiFi.STA.SSID()); - systemPrintf(" IP Address: %s\r\n", WiFi.STA.localIP().toString().c_str()); - systemPrintf(" Subnet Mask: %s\r\n", WiFi.STA.subnetMask().toString().c_str()); - systemPrintf(" Gateway Address: %s\r\n", WiFi.STA.gatewayIP().toString().c_str()); - if ((uint32_t)dns3) - systemPrintf(" DNS Address: %s, %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str(), - dns3.toString().c_str()); - else if ((uint32_t)dns3) - systemPrintf(" DNS Address: %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str()); - else - systemPrintf(" DNS Address: %s\r\n", dns1.toString().c_str()); - systemPrintf(" WiFi Strength: %d dBm\r\n", WiFi.RSSI()); - systemPrintf(" WiFi Status: %d\r\n", wifiStatusString); - } -} - -//---------------------------------------- -// Process the WiFi events -//---------------------------------------- -void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) -{ - char ssid[sizeof(info.wifi_sta_connected.ssid) + 1]; - IPAddress ipAddress; - - // If we are in AP or AP_STA, the network is immediately marked online - // Once AP is online, don't stop WiFi because STA has various events - if (WiFi.getMode() == WIFI_MODE_STA) - { - // Take the network offline if necessary - if (networkInterfaceHasInternet(NETWORK_WIFI) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP) && - (event != ARDUINO_EVENT_WIFI_STA_GOT_IP6)) - { - if (settings.debugWifiState) - systemPrintf("Stopping WiFi because of event # %d\r\n", event); - - networkStop(NETWORK_WIFI, settings.debugNetworkLayer); // Stop WiFi to allow it to restart - } - } - - // WiFi State Machine - // - // .--------+<----------+<-----------+<-------------+<----------+<----------+<------------. - // v | | | | | | | - // STOP --> READY --> STA_START --> SCAN_DONE --> CONNECTED --> GOT_IP --> LOST_IP --> DISCONNECTED - // ^ ^ | | - // | '-----------' | - // '-------------------------------------' - // - // Handle the event - switch (event) - { - default: - systemPrintf("ERROR: Unknown WiFi event: %d\r\n", event); - break; - - case ARDUINO_EVENT_WIFI_OFF: - systemPrintln("WiFi Off"); - break; - - case ARDUINO_EVENT_WIFI_READY: - if (settings.debugWifiState) - systemPrintln("WiFi Ready"); - WiFi.setHostname(settings.mdnsHostName); - break; - - case ARDUINO_EVENT_WIFI_SCAN_DONE: - if (settings.debugWifiState) - systemPrintln("WiFi Scan Done"); - // wifi_event_sta_scan_done_t info.wifi_scan_done; - break; - - case ARDUINO_EVENT_WIFI_STA_START: - if (settings.debugWifiState) - systemPrintln("WiFi STA Started"); - break; - - case ARDUINO_EVENT_WIFI_STA_STOP: - if (settings.debugWifiState) - systemPrintln("WiFi STA Stopped"); - break; - - case ARDUINO_EVENT_WIFI_STA_CONNECTED: - memcpy(ssid, info.wifi_sta_connected.ssid, info.wifi_sta_connected.ssid_len); - ssid[info.wifi_sta_connected.ssid_len] = 0; - - ipAddress = WiFi.localIP(); - systemPrintf("WiFi STA connected to %s with IP address: ", ssid); - systemPrintln(ipAddress); - - WiFi.setHostname(settings.mdnsHostName); - break; - - case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: - memcpy(ssid, info.wifi_sta_disconnected.ssid, info.wifi_sta_disconnected.ssid_len); - ssid[info.wifi_sta_disconnected.ssid_len] = 0; - systemPrintf("WiFi STA disconnected from %s\r\n", ssid); - // wifi_event_sta_disconnected_t info.wifi_sta_disconnected; - break; - - case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: - systemPrintln("WiFi STA Auth Mode Changed"); - // wifi_event_sta_authmode_change_t info.wifi_sta_authmode_change; - break; - - case ARDUINO_EVENT_WIFI_STA_GOT_IP: - if (settings.debugWifiState) - { - ipAddress = WiFi.localIP(); - systemPrint("WiFi STA Got IPv4: "); - systemPrintln(ipAddress); - } - networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); - break; - - case ARDUINO_EVENT_WIFI_STA_GOT_IP6: - if (settings.debugWifiState) - { - ipAddress = WiFi.localIP(); - systemPrint("WiFi STA Got IPv6: "); - systemPrintln(ipAddress); - } - networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); - break; - - case ARDUINO_EVENT_WIFI_STA_LOST_IP: - systemPrintln("WiFi STA Lost IP"); - break; - } -} - -//---------------------------------------- -// Determine if WIFI is connected -//---------------------------------------- -bool wifiIsConnected() -{ - bool connected; - - connected = (WiFi.status() == WL_CONNECTED); - return connected; -} - -//---------------------------------------- -// Determine if WiFi Station is running -//---------------------------------------- -bool wifiStationIsRunning() -{ - return wifiStationRunning; -} - -//---------------------------------------- -// Determine if WiFi AP is running -//---------------------------------------- -bool wifiApIsRunning() -{ - return wifiApRunning; -} - -//---------------------------------------- -// Determine if either Station or AP is running -//---------------------------------------- -bool wifiIsRunning() -{ - if (wifiStationRunning || wifiApRunning) - return true; - return false; -} - -//---------------------------------------- -// Counts the number of entered SSIDs -//---------------------------------------- -int wifiNetworkCount() -{ - // Count SSIDs - int networkCount = 0; - for (int x = 0; x < MAX_WIFI_NETWORKS; x++) - { - if (strlen(settings.wifiNetworks[x].ssid) > 0) - networkCount++; - } - return networkCount; -} - -//---------------------------------------- -// Given a status, return the associated state or error -//---------------------------------------- -const char *wifiPrintState(wl_status_t wifiStatus) -{ - switch (wifiStatus) - { - case WL_NO_SHIELD: - return ("WL_NO_SHIELD"); // 255 - case WL_STOPPED: - return ("WL_STOPPED"); - case WL_IDLE_STATUS: // 0 - return ("WL_IDLE_STATUS"); - case WL_NO_SSID_AVAIL: // 1 - return ("WL_NO_SSID_AVAIL"); - case WL_SCAN_COMPLETED: // 2 - return ("WL_SCAN_COMPLETED"); - case WL_CONNECTED: // 3 - return ("WL_CONNECTED"); - case WL_CONNECT_FAILED: // 4 - return ("WL_CONNECT_FAILED"); - case WL_CONNECTION_LOST: // 5 - return ("WL_CONNECTION_LOST"); - case WL_DISCONNECTED: // 6 - return ("WL_DISCONNECTED"); - } - return ("WiFi Status Unknown"); -} - -//---------------------------------------- -// Starts the WiFi connection state machine (moves from WIFI_STATE_OFF to WIFI_STATE_CONNECTING) -// Sets the appropriate protocols (WiFi + ESP-Now) -// If radio is off entirely, start WiFi -// If ESP-Now is active, only add the LR protocol -// Returns true if WiFi has connected and false otherwise -//---------------------------------------- -bool wifiStart() -{ - int wifiStatus; - - // Determine which parts of WiFi need to be started - bool startWiFiStation = false; - bool startWiFiAp = false; - - uint16_t consumerTypes = networkGetConsumerTypes(); - - // The consumers need station - if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) - startWiFiStation = true; - - // The consumers need AP - if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) - startWiFiAp = true; - - if (startWiFiStation == false && startWiFiAp == false) - { - systemPrintln("wifiStart() requested without any NETCONSUMER combination"); - WIFI_STOP(); - return (false); - } - - // Determine if WiFi is already running - if (startWiFiStation == wifiStationRunning && startWiFiAp == wifiApRunning) - { - if (settings.debugWifiState == true) - systemPrintln("WiFi is already running with requested setup"); - return (true); - } - - // Handle special cases if no networks have been entered - if (wifiNetworkCount() == 0) - { - if (startWiFiStation == true && startWiFiAp == false) - { - systemPrintln("Error: Please enter at least one SSID before using WiFi"); - displayNoSSIDs(2000); - WIFI_STOP(); - return false; - } - else if (startWiFiStation == true && startWiFiAp == true) - { - systemPrintln("Error: No SSID available to start WiFi Station during AP"); - // Allow the system to continue in AP only mode - startWiFiStation = false; - } - } - - // Start WiFi - wifiConnect(startWiFiStation, startWiFiAp, settings.wifiConnectTimeoutMs); - - // If we are in AP only mode, as long as the AP is started, return true - if (WiFi.getMode() == WIFI_MODE_AP) - return (wifiApIsRunning); - - // If we are in STA or AP+STA mode, return if the station connected successfully - wifiStatus = WiFi.status(); - return (wifiStatus == WL_CONNECTED); -} - -//---------------------------------------- -// Set WiFi timeout back to zero -// Useful if other things (such as a successful ethernet connection) need to reset wifi timeout -//---------------------------------------- -void wifiResetTimeout() -{ - wifiStartTimeout = 0; - if (settings.debugWifiState == true) - systemPrintln("WiFi: Start timeout reset to zero"); -} - -//---------------------------------------- -//---------------------------------------- -uint32_t wifiGetStartTimeout() -{ - return (wifiStartTimeout); -} - -//---------------------------------------- -// Reset the last WiFi start attempt -// Useful when WiFi settings have changed -//---------------------------------------- -void wifiResetThrottleTimeout() -{ - wifiStartLastTry = 0; -} - -//---------------------------------------- -// Start WiFi with throttling -//---------------------------------------- -void wifiThrottledStart(NetIndex_t index, uintptr_t parameter, bool debug) -{ - int seconds; - int minutes; - - // Restart delay - if ((millis() - wifiStartLastTry) < wifiStartTimeout) - return; - wifiStartLastTry = millis(); - - // Start WiFi - if (wifiStart()) - { - networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); - wifiFailedConnectionAttempts = 0; - } - else - { - // Increase the timeout - wifiStartTimeout <<= 1; - if (!wifiStartTimeout) - wifiStartTimeout = WIFI_MIN_TIMEOUT; - else if (wifiStartTimeout > WIFI_MAX_TIMEOUT) - wifiStartTimeout = WIFI_MAX_TIMEOUT; - - wifiFailedConnectionAttempts++; - - // Display the delay - seconds = wifiStartTimeout / MILLISECONDS_IN_A_SECOND; - minutes = seconds / SECONDS_IN_A_MINUTE; - seconds -= minutes * SECONDS_IN_A_MINUTE; - if (settings.debugWifiState) - systemPrintf("WiFi: Delaying %2d:%02d before restarting WiFi\r\n", minutes, seconds); - } -} - -//---------------------------------------- -// WiFi start sequence -//---------------------------------------- -NETWORK_POLL_SEQUENCE wifiStartSequence[] = { - // State Parameter Description - {wifiThrottledStart, 0, "Initialize WiFi"}, - {nullptr, 0, "Termination"}, -}; - -//---------------------------------------- -// WiFi stop sequence -//---------------------------------------- -NETWORK_POLL_SEQUENCE wifiStopSequence[] = { - // State Parameter Description - {wifiStop, 0, "Shutdown WiFi"}, - {nullptr, 0, "Termination"}, -}; - -//---------------------------------------- -// Stop WiFi and release all resources -//---------------------------------------- -void wifiStop() -{ - // Stop the web server - stopWebServer(); - - // Stop the DNS server if we were using the captive portal - if (((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) && settings.enableCaptivePortal) - dnsServer.stop(); - - wifiFailedConnectionAttempts = 0; // Reset the counter - - // If ESP-Now is active, change protocol to only Long Range - if (espnowState > ESPNOW_OFF) - { - if (WiFi.getMode() != WIFI_STA) - WiFi.mode(WIFI_STA); - - // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps - // esp_wifi_set_protocol requires WiFi to be started - esp_err_t response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); - if (response != ESP_OK) - systemPrintf("wifiShutdown: Error setting ESP-Now lone protocol: %s\r\n", esp_err_to_name(response)); - else - { - if (settings.debugWifiState == true) - systemPrintln("WiFi disabled, ESP-Now left in place"); - } - } - else - { - WiFi.mode(WIFI_OFF); - if (settings.debugWifiState == true) - systemPrintln("WiFi Stopped"); - } - - // Take the network offline - networkInterfaceInternetConnectionLost(NETWORK_WIFI); - - if (wifiMulti != nullptr) - wifiMulti = nullptr; - - // Display the heap state - reportHeapNow(settings.debugWifiState); - wifiStationRunning = false; - wifiApRunning = false; -} - -// Needed for wifiStopSequence -void wifiStop(NetIndex_t index, uintptr_t parameter, bool debug) -{ - wifiStop(); - networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); -} - -// Returns true if we deem WiFi is not going to connect -// Used to allow cellular to start -bool wifiUnavailable() -{ - if(wifiNetworkCount() == 0) - return true; - - if (wifiFailedConnectionAttempts > 2) - return true; - - return false; -} - -#endif // COMPILE_WIFI From 5a6450d62334c7d1af2dd01ab7e934058030177b Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Thu, 23 Jan 2025 10:32:28 -1000 Subject: [PATCH 161/276] Remove some blank lines and extra spaces --- Firmware/RTK_Everywhere/AP-Config/src/main.js | 4 ++-- Firmware/RTK_Everywhere/States.ino | 1 - Firmware/RTK_Everywhere/menuCommands.ino | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/AP-Config/src/main.js b/Firmware/RTK_Everywhere/AP-Config/src/main.js index de14d03f6..33370bd6c 100644 --- a/Firmware/RTK_Everywhere/AP-Config/src/main.js +++ b/Firmware/RTK_Everywhere/AP-Config/src/main.js @@ -529,7 +529,7 @@ function parseIncoming(msg) { else if (id.includes("antennaHeight_mm")) { ge("antennaHeight_m").value = val / 1000.0; } - + //Check boxes / radio buttons else if (val == "true") { try { @@ -2700,4 +2700,4 @@ function printableInputType(coordinateInputType) { break; } return ("Unknown"); -} \ No newline at end of file +} diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 8f2311a7f..16714afba 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -522,7 +522,6 @@ void stateUpdate() otaReportedVersion[0] = '\0'; // Zero out the reported version } - } #endif // COMPILE_AP diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index af91d0d6f..a7b8a63a8 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -1514,7 +1514,6 @@ void createSettingsString(char *newSettings) break; case tSysState: { SystemState *ptr = (SystemState *)rtkSettingsEntries[i].var; - stringRecord(newSettings, rtkSettingsEntries[i].name, (int)*ptr); } break; From 2ae9b033d15cbdc51115aef00c8defa797417a1b Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Tue, 21 Jan 2025 16:08:48 -1000 Subject: [PATCH 162/276] WiFi: Replace wifiIsRunning with WIFI_IS_RUNNING macro --- Firmware/RTK_Everywhere/Developer.ino | 2 +- Firmware/RTK_Everywhere/Display.ino | 6 +++--- Firmware/RTK_Everywhere/ESPNOW.ino | 8 ++++---- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 1 + Firmware/RTK_Everywhere/menuMain.ino | 2 +- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 239e5bd38..a605a08dc 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -202,7 +202,7 @@ void menuWiFi() {systemPrintln("**WiFi not compiled**");} bool wifiApIsRunning() {return false;} bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) {return false;} uint32_t wifiGetStartTimeout() {return 0;} -bool wifiIsRunning() {return false;} +#define WIFI_IS_RUNNING() int wifiNetworkCount() {return 0;} void wifiResetThrottleTimeout() {} void wifiResetTimeout() {} diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index a56a272ba..67d3a4720 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -654,7 +654,7 @@ void setRadioIcons(std::vector *iconList) // Count the number of radios in use uint8_t numberOfRadios = 1; // Bluetooth always indicated. TODO don't count if BT radio type is OFF. - if (wifiIsRunning()) + if (WIFI_IS_RUNNING()) numberOfRadios++; if (espnowState > ESPNOW_OFF) numberOfRadios++; @@ -671,7 +671,7 @@ void setRadioIcons(std::vector *iconList) setBluetoothIcon_TwoRadios(iconList); // Do we have WiFi or ESP - if (wifiIsRunning()) + if (WIFI_IS_RUNNING()) setWiFiIcon_TwoRadios(iconList); else if (espnowState > ESPNOW_OFF) setESPNowIcon_TwoRadios(iconList); @@ -706,7 +706,7 @@ void setRadioIcons(std::vector *iconList) iconList->push_back(prop); } - if (wifiIsRunning()) // WiFi : Columns 34 - 46 + if (WIFI_IS_RUNNING()) // WiFi : Columns 34 - 46 { #ifdef COMPILE_WIFI int wifiRSSI = WiFi.RSSI(); diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index 342603784..4608640e7 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -594,7 +594,7 @@ void espnowStart() if (response != ESP_OK) systemPrintf("espnowStart: Failed to get protocols: %s\r\n", esp_err_to_name(response)); - if ((wifiIsRunning() == false) && espnowState == ESPNOW_OFF) + if ((WIFI_IS_RUNNING() == false) && espnowState == ESPNOW_OFF) { // Radio is off, turn it on if (protocols != (WIFI_PROTOCOL_LR)) @@ -615,7 +615,7 @@ void espnowStart() } } // If WiFi is on but ESP NOW is off, then enable LR protocol - else if (wifiIsRunning() && espnowState == ESPNOW_OFF) + else if (WIFI_IS_RUNNING() && espnowState == ESPNOW_OFF) { // Enable WiFi + ESP-Now // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps @@ -788,7 +788,7 @@ void espnowStop() espnowSetState(ESPNOW_OFF); - if (wifiIsRunning() == false) + if (WIFI_IS_RUNNING() == false) { // ESP-NOW was the only thing using the radio so turn WiFi radio off entirely WiFi.mode(WIFI_OFF); @@ -797,7 +797,7 @@ void espnowStop() systemPrintln("WiFi Radio off entirely"); } // If WiFi is on, then restart WiFi - else if (wifiIsRunning()) + else if (WIFI_IS_RUNNING()) { if (settings.debugEspNow == true) systemPrintln("ESP-Now starting WiFi"); diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 1ab19d6c9..ce3a9781c 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -306,6 +306,7 @@ char logFileName[sizeof("SFE_Reference_Station_230101_120101.ubx_plusExtraSpace" int packetRSSI; RTK_WIFI wifi(false); +#define WIFI_IS_RUNNING() wifiIsRunning() #define WIFI_STOP() \ { \ if (settings.debugWifiState) \ diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 8efcead3c..a3804eb0c 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -630,7 +630,7 @@ void menuRadio() } else if (settings.enableEspNow == true && incoming == 4) { - if (wifiIsRunning() == false) + if (WIFI_IS_RUNNING() == false) { if (getNewSetting("Enter the WiFi channel to use for ESP-NOW communication", 1, 14, &settings.wifiChannel) == INPUT_RESPONSE_VALID) From 7b0e01a043256234def4fc76b8377a8048fb7273 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Tue, 21 Jan 2025 16:13:27 -1000 Subject: [PATCH 163/276] WiFi: Replace wifiIsConnected with WIFI_IS_CONNECTED macro --- Firmware/RTK_Everywhere/ESPNOW.ino | 4 ++-- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index 4608640e7..03efb13fe 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -663,7 +663,7 @@ void espnowStart() esp_wifi_set_promiscuous_rx_cb(&promiscuous_rx_cb); // Assign channel if not connected to an AP - if (wifiIsConnected() == false) + if (WIFI_IS_CONNECTED() == false) espnowSetChannel(settings.wifiChannel); // Register callbacks @@ -1059,7 +1059,7 @@ uint8_t espnowGetChannel() // Returns the current channel being used by WiFi bool espnowSetChannel(uint8_t channelNumber) { - if (wifiIsConnected() == true) + if (WIFI_IS_CONNECTED() == true) { systemPrintln("ESP-NOW channel can't be modified while WiFi is connected."); return (false); diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index ce3a9781c..0174c5690 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -306,6 +306,7 @@ char logFileName[sizeof("SFE_Reference_Station_230101_120101.ubx_plusExtraSpace" int packetRSSI; RTK_WIFI wifi(false); +#define WIFI_IS_CONNECTED() wifiIsConnected() #define WIFI_IS_RUNNING() wifiIsRunning() #define WIFI_STOP() \ { \ From 0cd1e7737cf42383399e4bc7c90df7a65aa01329 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Tue, 21 Jan 2025 16:24:05 -1000 Subject: [PATCH 164/276] WiFi: Replace wifiApIsRunning with WIFI_SOFT_AP_RUNNING --- Firmware/RTK_Everywhere/Developer.ino | 1 + Firmware/RTK_Everywhere/Network.ino | 4 ++-- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 1 + Firmware/RTK_Everywhere/TcpServer.ino | 4 ++-- Firmware/RTK_Everywhere/UdpServer.ino | 4 ++-- Firmware/RTK_Everywhere/WebServer.ino | 6 +++--- Firmware/RTK_Everywhere/WiFi.ino | 2 +- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index a605a08dc..dbbdb888e 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -206,6 +206,7 @@ uint32_t wifiGetStartTimeout() {return 0;} int wifiNetworkCount() {return 0;} void wifiResetThrottleTimeout() {} void wifiResetTimeout() {} +#define WIFI_SOFT_AP_RUNNING() {return false;} bool wifiStart() {return false;} bool wifiStationIsRunning() {return false;} #define WIFI_STOP() {} diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 1a12ee8b3..6797fb32c 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -519,7 +519,7 @@ IPAddress networkGetIpAddress() IPAddress ip; // NETIF doesn't capture the IP address of a soft AP - if (wifiApIsRunning() == true && wifiStationIsRunning() == false) + if (WIFI_SOFT_AP_RUNNING() == true && wifiStationIsRunning() == false) return WiFi.softAPIP(); // Get the networkInterfaceTable index @@ -1491,7 +1491,7 @@ void networkUpdate() if ((networkHasInternet() == false) && (consumerTypes & (1 << NETCONSUMER_CELLULAR))) { // If we're in AP only mode (no internet), don't start cellular - if (wifiApIsRunning() == false) + if (WIFI_SOFT_AP_RUNNING() == false) { // Don't start cellular until WiFi has failed to connect if (wifiUnavailable() == true) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 0174c5690..55501ec35 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -308,6 +308,7 @@ RTK_WIFI wifi(false); #define WIFI_IS_CONNECTED() wifiIsConnected() #define WIFI_IS_RUNNING() wifiIsRunning() +#define WIFI_SOFT_AP_RUNNING() wifiApIsRunning() #define WIFI_STOP() \ { \ if (settings.debugWifiState) \ diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index 6e1ecac51..fac038922 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -391,7 +391,7 @@ void tcpServerUpdate() tcpServerStop(); // Wait until the network is connected to the media - else if (networkHasInternet() || wifiApIsRunning()) + else if (networkHasInternet() || WIFI_SOFT_AP_RUNNING()) { // Delay before starting the TCP server if ((millis() - tcpServerTimer) >= (1 * 1000)) @@ -409,7 +409,7 @@ void tcpServerUpdate() // Handle client connections and link failures case TCP_SERVER_STATE_RUNNING: // Determine if the network has failed - if ((networkHasInternet() == false && wifiApIsRunning() == false) || (!settings.enableTcpServer && !settings.baseCasterOverride)) + if ((networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) || (!settings.enableTcpServer && !settings.baseCasterOverride)) { if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu)) { diff --git a/Firmware/RTK_Everywhere/UdpServer.ino b/Firmware/RTK_Everywhere/UdpServer.ino index 5f0316f59..3a9a8d27f 100644 --- a/Firmware/RTK_Everywhere/UdpServer.ino +++ b/Firmware/RTK_Everywhere/UdpServer.ino @@ -335,7 +335,7 @@ void udpServerUpdate() udpServerStop(); // Wait until the network is connected - else if (networkHasInternet() || wifiApIsRunning()) + else if (networkHasInternet() || WIFI_SOFT_AP_RUNNING()) { // Delay before starting the UDP server if ((millis() - udpServerTimer) >= (1 * 1000)) @@ -353,7 +353,7 @@ void udpServerUpdate() // Handle client connections and link failures case UDP_SERVER_STATE_RUNNING: // Determine if the network has failed - if ((networkHasInternet() == false && wifiApIsRunning() == false) || (!settings.enableUdpServer && !settings.baseCasterOverride)) + if ((networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) || (!settings.enableUdpServer && !settings.baseCasterOverride)) { if ((settings.debugUdpServer || PERIODIC_DISPLAY(PD_UDP_SERVER_DATA)) && (!inMainMenu)) { diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index 71bfc3bae..f4358e801 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -779,7 +779,7 @@ void webServerUpdate() // Wait for connection to the network case WEBSERVER_STATE_WAIT_FOR_NETWORK: // Wait until the network is connected to the internet or has WiFi AP - if (networkHasInternet() || wifiApIsRunning()) + if (networkHasInternet() || WIFI_SOFT_AP_RUNNING()) { if (settings.debugWebServer) systemPrintln("Web Server connected to network"); @@ -791,7 +791,7 @@ void webServerUpdate() // Start the web server case WEBSERVER_STATE_NETWORK_CONNECTED: { // Determine if the network has failed - if (networkHasInternet() == false && wifiApIsRunning() == false) + if (networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) webServerStop(); if (settings.debugWebServer) systemPrintln("Assigning web server resources"); @@ -807,7 +807,7 @@ void webServerUpdate() // Allow web services case WEBSERVER_STATE_RUNNING: // Determine if the network has failed - if (networkHasInternet() == false && wifiApIsRunning() == false) + if (networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) webServerStop(); // This state is exited when webServerStop() is called diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 3f1ed70d4..e736cc919 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -3127,7 +3127,7 @@ bool wifiStart() // If we are in AP only mode, as long as the AP is started, return true if (WiFi.getMode() == WIFI_MODE_AP) - return (wifiApIsRunning); + return WIFI_SOFT_AP_RUNNING(); // If we are in STA or AP+STA mode, return if the station connected successfully wifiStatus = WiFi.status(); From e68fb7f7856766ec0d6726bf16920e8bab20a24b Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Tue, 21 Jan 2025 16:43:24 -1000 Subject: [PATCH 165/276] ESP-NOW: Replace espnowState with espnowGetState() --- Firmware/RTK_Everywhere/Display.ino | 10 +++++----- Firmware/RTK_Everywhere/ESPNOW.ino | 7 +++++++ Firmware/RTK_Everywhere/WiFi.ino | 4 ++-- Firmware/RTK_Everywhere/menuMain.ino | 8 ++++---- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 67d3a4720..e40ec2db6 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -656,7 +656,7 @@ void setRadioIcons(std::vector *iconList) uint8_t numberOfRadios = 1; // Bluetooth always indicated. TODO don't count if BT radio type is OFF. if (WIFI_IS_RUNNING()) numberOfRadios++; - if (espnowState > ESPNOW_OFF) + if (espnowGetState() > ESPNOW_OFF) numberOfRadios++; // Bluetooth only @@ -673,7 +673,7 @@ void setRadioIcons(std::vector *iconList) // Do we have WiFi or ESP if (WIFI_IS_RUNNING()) setWiFiIcon_TwoRadios(iconList); - else if (espnowState > ESPNOW_OFF) + else if (espnowGetState() > ESPNOW_OFF) setESPNowIcon_TwoRadios(iconList); setModeIcon(iconList); // Turn on Rover/Base type icons @@ -753,7 +753,7 @@ void setRadioIcons(std::vector *iconList) } #endif // /COMPILE_CELLULAR - if (espnowState == ESPNOW_PAIRED) // ESPNOW : Columns 64 - 71 + if (espnowGetState() == ESPNOW_PAIRED) // ESPNOW : Columns 64 - 71 { iconPropertyBlinking prop; prop.duty = 0b11111111; @@ -792,7 +792,7 @@ void setRadioIcons(std::vector *iconList) } } - if (espnowState == ESPNOW_PAIRED) + if (espnowGetState() == ESPNOW_PAIRED) { if (espnowIncomingRTCM == true) // Download : Columns 74 - 81 { @@ -1023,7 +1023,7 @@ void setBluetoothIcon_TwoRadios(std::vector *iconList) // This is 64x48-specific void setESPNowIcon_TwoRadios(std::vector *iconList) { - if (espnowState == ESPNOW_PAIRED) + if (espnowGetState() == ESPNOW_PAIRED) { if (espnowIncomingRTCM == true || espnowOutgoingRTCM == true) { diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index 03efb13fe..42477e1b9 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -53,6 +53,13 @@ esp_err_t espNowAddPeer(const uint8_t * peerMac) return result; } +//********************************************************************* +// Get the current ESP-NOW state +ESPNOWState espnowGetState() +{ + return espnowState; +} + //---------------------------------------------------------------------- // ESP-NOW bringup from example 4_9_ESP_NOW // 1. Set station mode diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index e736cc919..ee087ca73 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -2728,7 +2728,7 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) systemPrintf("Failed to get protocols: %s\r\n", esp_err_to_name(response)); // If ESP-NOW is running, blend in ESP-NOW protocol. - if (espnowState > ESPNOW_OFF) + if (espnowGetState() > ESPNOW_OFF) { if (protocols != (WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_LR)) { @@ -3233,7 +3233,7 @@ void wifiStop() wifiFailedConnectionAttempts = 0; // Reset the counter // If ESP-Now is active, change protocol to only Long Range - if (espnowState > ESPNOW_OFF) + if (espnowGetState() > ESPNOW_OFF) { if (WiFi.getMode() != WIFI_STA) WiFi.mode(WIFI_STA); diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index a3804eb0c..b5b23d91f 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -619,7 +619,7 @@ void menuRadio() byte bContinue = getUserInputCharacterNumber(); if (bContinue == 'y') { - if (espnowState > ESPNOW_OFF) + if (espnowGetState() > ESPNOW_OFF) { for (int x = 0; x < settings.espnowPeerCount; x++) espnowRemovePeer(settings.espnowPeers[x]); @@ -643,7 +643,7 @@ void menuRadio() } else if (settings.enableEspNow == true && incoming == 5 && settings.debugEspNow == true) { - if (espnowState == ESPNOW_OFF) + if (espnowGetState() == ESPNOW_OFF) espnowStart(); uint8_t peer1[] = {0xB8, 0xD6, 0x1A, 0x0D, 0x8F, 0x9C}; // Random MAC @@ -667,7 +667,7 @@ void menuRadio() } else if (settings.enableEspNow == true && incoming == 6 && settings.debugEspNow == true) { - if (espnowState == ESPNOW_OFF) + if (espnowGetState() == ESPNOW_OFF) espnowStart(); uint8_t espnowData[] = @@ -680,7 +680,7 @@ void menuRadio() } else if (settings.enableEspNow == true && incoming == 7 && settings.debugEspNow == true) { - if (espnowState == ESPNOW_OFF) + if (espnowGetState() == ESPNOW_OFF) espnowStart(); uint8_t espnowData[] = From c82ab4577f9c85bc83e115e2af18c7ad498ded70 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Tue, 21 Jan 2025 18:11:32 -1000 Subject: [PATCH 166/276] Revert from networkHasInternet --> networkIsConnected, notify net fail Ensure that each client and server gets notified of the network failover in a timely manor. Using networkHasInternet may either not change or only a subset of clients and servers may get notified. Using networkIsConnected ensures that the client gets rapid notification of the failover. --- Firmware/RTK_Everywhere/HTTP_Client.ino | 12 +++++++----- Firmware/RTK_Everywhere/MQTT_Client.ino | 8 +++++--- Firmware/RTK_Everywhere/NTP.ino | 2 ++ Firmware/RTK_Everywhere/Network.ino | 16 ++++++++++++++++ Firmware/RTK_Everywhere/NtripClient.ino | 12 +++++++----- Firmware/RTK_Everywhere/NtripServer.ino | 14 ++++++++------ Firmware/RTK_Everywhere/TcpClient.ino | 8 +++++--- Firmware/RTK_Everywhere/TcpServer.ino | 6 ++++-- Firmware/RTK_Everywhere/UdpServer.ino | 8 +++++--- Firmware/RTK_Everywhere/WebServer.ino | 8 +++++--- Firmware/RTK_Everywhere/menuFirmware.ino | 11 ++++------- Firmware/RTK_Everywhere/menuPP.ino | 3 ++- 12 files changed, 70 insertions(+), 38 deletions(-) diff --git a/Firmware/RTK_Everywhere/HTTP_Client.ino b/Firmware/RTK_Everywhere/HTTP_Client.ino index d2e15b9b6..837a97b5e 100644 --- a/Firmware/RTK_Everywhere/HTTP_Client.ino +++ b/Firmware/RTK_Everywhere/HTTP_Client.ino @@ -59,6 +59,7 @@ static uint32_t httpClientConnectionAttemptTimeout = 5 * 1000L; // Wait 5s static int httpClientConnectionAttemptsTotal; // Count the number of connection attempts absolutely static volatile uint32_t httpClientLastDataReceived; // Last time data was received via HTTP +static NetPriority_t httpClientPriority = NETWORK_OFFLINE; static NetworkClientSecure *httpSecureClient; @@ -275,6 +276,7 @@ void httpClientUpdate() case HTTP_CLIENT_ON: { if ((millis() - httpClientTimer) > httpClientConnectionAttemptTimeout) { + httpClientPriority = NETWORK_OFFLINE; httpClientSetState(HTTP_CLIENT_NETWORK_STARTED); } break; @@ -286,8 +288,8 @@ void httpClientUpdate() if (!httpClientModeNeeded) httpClientStop(true); - // Wait until the network is connected - else if (networkHasInternet()) + // Wait until the network is connected to the media + else if (networkIsConnected(&httpClientPriority)) httpClientSetState(HTTP_CLIENT_CONNECTING_2_SERVER); break; } @@ -295,7 +297,7 @@ void httpClientUpdate() // Connect to the HTTP server case HTTP_CLIENT_CONNECTING_2_SERVER: { // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&httpClientPriority)) { // Failed to connect to the network, attempt to restart the network httpClientStop(true); // Was httpClientRestart(); - #StopVsRestart @@ -352,7 +354,7 @@ void httpClientUpdate() case HTTP_CLIENT_CONNECTED: { // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&httpClientPriority)) { // Failed to connect to the network, attempt to restart the network httpClientStop(true); // Was httpClientRestart(); - #StopVsRestart @@ -556,7 +558,7 @@ void httpClientUpdate() // Hang here until httpClientModeNeeded is set to false by updateProvisioning case HTTP_CLIENT_COMPLETE: { // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&httpClientPriority)) // Failed to connect to the network, attempt to restart the network httpClientStop(true); // Was httpClientRestart(); - #StopVsRestart break; diff --git a/Firmware/RTK_Everywhere/MQTT_Client.ino b/Firmware/RTK_Everywhere/MQTT_Client.ino index 1b60d4fd9..3bd1cf91c 100644 --- a/Firmware/RTK_Everywhere/MQTT_Client.ino +++ b/Firmware/RTK_Everywhere/MQTT_Client.ino @@ -138,6 +138,7 @@ static uint32_t mqttClientConnectionAttemptTimeout; static int mqttClientConnectionAttemptsTotal; // Count the number of connection attempts absolutely static volatile uint32_t mqttClientLastDataReceived; // Last time data was received via MQTT +static NetPriority_t mqttClientPriority = NETWORK_OFFLINE; static NetworkClientSecure *mqttSecureClient; @@ -722,6 +723,7 @@ void mqttClientUpdate() case MQTT_CLIENT_ON: { if ((millis() - mqttClientTimer) > mqttClientConnectionAttemptTimeout) { + mqttClientPriority = NETWORK_OFFLINE; mqttClientSetState(MQTT_CLIENT_WAIT_FOR_NETWORK); } break; @@ -734,7 +736,7 @@ void mqttClientUpdate() mqttClientStop(true); // Wait until the network is connected to the media - else if (networkHasInternet()) + else if (networkIsConnected(&mqttClientPriority)) mqttClientSetState(MQTT_CLIENT_CONNECTING_2_SERVER); break; } @@ -742,7 +744,7 @@ void mqttClientUpdate() // Connect to the MQTT server case MQTT_CLIENT_CONNECTING_2_SERVER: { // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&mqttClientPriority)) { // Failed to connect to the network, attempt to restart the network mqttClientStop(true); // Was mqttClientRestart(); - #StopVsRestart @@ -888,7 +890,7 @@ void mqttClientUpdate() case MQTT_CLIENT_SERVICES_CONNECTED: { // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&mqttClientPriority)) { // Failed to connect to the network, attempt to restart the network mqttClientStop(true); // Was mqttClientRestart(); - #StopVsRestart diff --git a/Firmware/RTK_Everywhere/NTP.ino b/Firmware/RTK_Everywhere/NTP.ino index e03d0a217..75ade00a0 100644 --- a/Firmware/RTK_Everywhere/NTP.ino +++ b/Firmware/RTK_Everywhere/NTP.ino @@ -75,6 +75,7 @@ const RtkMode_t ntpServerMode = RTK_MODE_NTP; // Locals //---------------------------------------- +static NetPriority_t ntpServerPriority = NETWORK_OFFLINE; static NetworkUDP *ntpServer; // This will be instantiated when we know the NTP port static uint8_t ntpServerState; static uint32_t lastLoggedNTPRequest; @@ -792,6 +793,7 @@ void ntpServerUpdate() // The NTP server only works over Ethernet if (networkInterfaceHasInternet(NETWORK_ETHERNET)) { + ntpServerPriority = NETWORK_OFFLINE; ntpServerSetState(NTP_STATE_NETWORK_CONNECTED); } } diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 6797fb32c..d0000b706 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -583,6 +583,22 @@ const char *networkGetNameByPriority(NetPriority_t priority) return "None"; } +//---------------------------------------- +// Determine if the network is available +//---------------------------------------- +bool networkIsConnected(NetPriority_t *clientPriority) +{ + // If the client is using the highest priority network and that + // network is still available then continue as normal + if (networkHasInternet_bm && (*clientPriority == networkPriority)) + return (networkHasInternet_bm & (1 << networkIndexTable[networkPriority])) + ? true : false; + + // The network has changed, notify the client of the change + *clientPriority = networkPriority; + return false; +} + //---------------------------------------- // Determine if the network interface is online //---------------------------------------- diff --git a/Firmware/RTK_Everywhere/NtripClient.ino b/Firmware/RTK_Everywhere/NtripClient.ino index 9b54aaaf4..b6007c8a0 100644 --- a/Firmware/RTK_Everywhere/NtripClient.ino +++ b/Firmware/RTK_Everywhere/NtripClient.ino @@ -187,6 +187,7 @@ static volatile uint8_t ntripClientState = NTRIP_CLIENT_OFF; static int ntripClientConnectionAttempts; // Count the number of connection attempts between restarts static uint32_t ntripClientConnectionAttemptTimeout; static int ntripClientConnectionAttemptsTotal; // Count the number of connection attempts absolutely +static NetPriority_t ntripClientPriority = NETWORK_OFFLINE; // NTRIP client timer usage: // * Reconnection delay @@ -562,6 +563,7 @@ void ntripClientUpdate() // Start the network case NTRIP_CLIENT_ON: + ntripClientPriority = NETWORK_OFFLINE; ntripClientSetState(NTRIP_CLIENT_WAIT_FOR_NETWORK); break; @@ -571,8 +573,8 @@ void ntripClientUpdate() if (ntripClientForcedShutdown || NEQ_RTK_MODE(ntripClientMode) || !settings.enableNtripClient) ntripClientStop(true); - // Wait until the network is connected - else if (networkHasInternet()) + // Wait until the network is connected to the media + else if (networkIsConnected(&ntripClientPriority)) { // Allocate the ntripClient structure ntripClient = new NetworkClient(); @@ -594,7 +596,7 @@ void ntripClientUpdate() case NTRIP_CLIENT_NETWORK_CONNECTED: // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&ntripClientPriority)) // Failed to connect to to the network, attempt to restart the network ntripClientStop(true); // Was ntripClientRestart(); - #StopVsRestart @@ -627,7 +629,7 @@ void ntripClientUpdate() case NTRIP_CLIENT_WAIT_RESPONSE: // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&ntripClientPriority)) // Failed to connect to to the network, attempt to restart the network ntripClientStop(true); // Was ntripClientRestart(); - #StopVsRestart @@ -748,7 +750,7 @@ void ntripClientUpdate() case NTRIP_CLIENT_CONNECTED: // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&ntripClientPriority)) // Failed to connect to to the network, attempt to restart the network ntripClientStop(true); // Was ntripClientRestart(); - #StopVsRestart diff --git a/Firmware/RTK_Everywhere/NtripServer.ino b/Firmware/RTK_Everywhere/NtripServer.ino index edb72a424..c3d45704b 100644 --- a/Firmware/RTK_Everywhere/NtripServer.ino +++ b/Firmware/RTK_Everywhere/NtripServer.ino @@ -175,6 +175,7 @@ const RtkMode_t ntripServerMode = RTK_MODE_BASE_FIXED; // NTRIP Servers static NTRIP_SERVER_DATA ntripServerArray[NTRIP_SERVER_MAX]; +static NetPriority_t ntripServerPriority = NETWORK_OFFLINE; //---------------------------------------- // NTRIP Server Routines @@ -607,6 +608,7 @@ void ntripServerUpdate(int serverIndex) // Start the network case NTRIP_SERVER_ON: + ntripServerPriority = NETWORK_OFFLINE; ntripServerSetState(ntripServer, NTRIP_SERVER_WAIT_FOR_NETWORK); break; @@ -622,7 +624,7 @@ void ntripServerUpdate(int serverIndex) } // Wait until the network is connected - else if (networkHasInternet()) + else if (networkIsConnected(&ntripServerPriority)) { // Allocate the networkClient structure ntripServer->networkClient = new NetworkClient(); @@ -645,7 +647,7 @@ void ntripServerUpdate(int serverIndex) // Network available case NTRIP_SERVER_NETWORK_CONNECTED: // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&ntripServerPriority)) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -663,7 +665,7 @@ void ntripServerUpdate(int serverIndex) // Wait for GNSS correction data case NTRIP_SERVER_WAIT_GNSS_DATA: // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&ntripServerPriority)) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -673,7 +675,7 @@ void ntripServerUpdate(int serverIndex) // Initiate the connection to the NTRIP caster case NTRIP_SERVER_CONNECTING: // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&ntripServerPriority)) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -701,7 +703,7 @@ void ntripServerUpdate(int serverIndex) // Wait for authorization response case NTRIP_SERVER_AUTHORIZATION: // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&ntripServerPriority)) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -795,7 +797,7 @@ void ntripServerUpdate(int serverIndex) // NTRIP server authorized to send RTCM correction data to NTRIP caster case NTRIP_SERVER_CASTING: // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&ntripServerPriority)) // Failed to connect to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart diff --git a/Firmware/RTK_Everywhere/TcpClient.ino b/Firmware/RTK_Everywhere/TcpClient.ino index d59ff2e3c..21078879c 100644 --- a/Firmware/RTK_Everywhere/TcpClient.ino +++ b/Firmware/RTK_Everywhere/TcpClient.ino @@ -148,6 +148,7 @@ const RtkMode_t tcpClientMode = RTK_MODE_BASE_FIXED | RTK_MODE_BASE_SURVEY_IN | static NetworkClient *tcpClient; static IPAddress tcpClientIpAddress; +static NetPriority_t tcpClientPriority = NETWORK_OFFLINE; static uint8_t tcpClientState; static volatile RING_BUFFER_OFFSET tcpClientTail; static volatile bool tcpClientWriteError; @@ -416,6 +417,7 @@ void tcpClientUpdate() if (EQ_RTK_MODE(tcpClientMode) && settings.enableTcpClient) { timer = 0; + tcpClientPriority = NETWORK_OFFLINE; tcpClientSetState(TCP_CLIENT_STATE_WAIT_FOR_NETWORK); } break; @@ -427,7 +429,7 @@ void tcpClientUpdate() tcpClientStop(); // Wait until the network is connected - else if (networkHasInternet()) + else if (networkIsConnected(&tcpClientPriority)) { #ifdef COMPILE_WIFI // Determine if WiFi is required @@ -463,7 +465,7 @@ void tcpClientUpdate() // Attempt the connection ot the TCP server case TCP_CLIENT_STATE_CLIENT_STARTING: // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&tcpClientPriority)) // Failed to connect to to the network, attempt to restart the network tcpClientStop(); @@ -508,7 +510,7 @@ void tcpClientUpdate() // Wait for the TCP client to shutdown or a TCP client link failure case TCP_CLIENT_STATE_CONNECTED: // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&tcpClientPriority)) // Failed to connect to to the network, attempt to restart the network tcpClientStop(); diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index fac038922..3506abbde 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -76,6 +76,7 @@ static volatile uint8_t tcpServerClientWriteError; static NetworkClient *tcpServerClient[TCP_SERVER_MAX_CLIENTS]; static IPAddress tcpServerClientIpAddress[TCP_SERVER_MAX_CLIENTS]; static volatile RING_BUFFER_OFFSET tcpServerClientTails[TCP_SERVER_MAX_CLIENTS]; +static NetPriority_t tcpServerPriority = NETWORK_OFFLINE; //---------------------------------------- // TCP Server handleGnssDataTask Support Routines @@ -380,6 +381,7 @@ void tcpServerUpdate() { if (settings.debugTcpServer && (!inMainMenu)) systemPrintln("TCP server start"); + tcpServerPriority = NETWORK_OFFLINE; tcpServerSetState(TCP_SERVER_STATE_WAIT_FOR_NETWORK); } break; @@ -391,7 +393,7 @@ void tcpServerUpdate() tcpServerStop(); // Wait until the network is connected to the media - else if (networkHasInternet() || WIFI_SOFT_AP_RUNNING()) + else if (networkIsConnected(&tcpServerPriority)) { // Delay before starting the TCP server if ((millis() - tcpServerTimer) >= (1 * 1000)) @@ -409,7 +411,7 @@ void tcpServerUpdate() // Handle client connections and link failures case TCP_SERVER_STATE_RUNNING: // Determine if the network has failed - if ((networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) || (!settings.enableTcpServer && !settings.baseCasterOverride)) + if ((networkIsConnected(&tcpServerPriority) == false && WIFI_SOFT_AP_RUNNING() == false) || (!settings.enableTcpServer && !settings.baseCasterOverride)) { if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu)) { diff --git a/Firmware/RTK_Everywhere/UdpServer.ino b/Firmware/RTK_Everywhere/UdpServer.ino index 3a9a8d27f..ce60629f9 100644 --- a/Firmware/RTK_Everywhere/UdpServer.ino +++ b/Firmware/RTK_Everywhere/UdpServer.ino @@ -94,6 +94,7 @@ static NetworkUDP *udpServer = nullptr; static uint8_t udpServerState; static uint32_t udpServerTimer; static volatile RING_BUFFER_OFFSET udpServerTail; +static NetPriority_t udpServerPriority; //---------------------------------------- // UDP Server handleGnssDataTask Support Routines @@ -106,7 +107,7 @@ int32_t udpServerSendDataBroadcast(uint8_t *data, uint16_t length) return 0; // Send the data as broadcast - if (settings.enableUdpServer && online.udpServer && networkHasInternet()) + if (settings.enableUdpServer && online.udpServer && networkIsConnected(&udpServerPriority)) { IPAddress broadcastAddress = networkGetBroadcastIpAddress(); udpServer->beginPacket(broadcastAddress, settings.udpServerPort); @@ -324,6 +325,7 @@ void udpServerUpdate() { if (settings.debugUdpServer && (!inMainMenu)) systemPrintln("UDP server starting the network"); + udpServerPriority = NETWORK_OFFLINE; udpServerSetState(UDP_SERVER_STATE_WAIT_FOR_NETWORK); } break; @@ -335,7 +337,7 @@ void udpServerUpdate() udpServerStop(); // Wait until the network is connected - else if (networkHasInternet() || WIFI_SOFT_AP_RUNNING()) + else if (networkIsConnected(&udpServerPriority) || WIFI_SOFT_AP_RUNNING()) { // Delay before starting the UDP server if ((millis() - udpServerTimer) >= (1 * 1000)) @@ -353,7 +355,7 @@ void udpServerUpdate() // Handle client connections and link failures case UDP_SERVER_STATE_RUNNING: // Determine if the network has failed - if ((networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) || (!settings.enableUdpServer && !settings.baseCasterOverride)) + if ((networkIsConnected(&udpServerPriority) == false && WIFI_SOFT_AP_RUNNING() == false) || (!settings.enableUdpServer && !settings.baseCasterOverride)) { if ((settings.debugUdpServer || PERIODIC_DISPLAY(PD_UDP_SERVER_DATA)) && (!inMainMenu)) { diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index f4358e801..615d67d89 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -27,6 +27,8 @@ static const char *const webServerStateNames[] = { static const int webServerStateEntries = sizeof(webServerStateNames) / sizeof(webServerStateNames[0]); +static NetPriority_t webServerPriority = NETWORK_OFFLINE; + static uint8_t webServerState; // Once connected to the access point for WiFi Config, the ESP32 sends current setting values in one long string to @@ -779,7 +781,7 @@ void webServerUpdate() // Wait for connection to the network case WEBSERVER_STATE_WAIT_FOR_NETWORK: // Wait until the network is connected to the internet or has WiFi AP - if (networkHasInternet() || WIFI_SOFT_AP_RUNNING()) + if (networkIsConnected(&webServerPriority) || WIFI_SOFT_AP_RUNNING()) { if (settings.debugWebServer) systemPrintln("Web Server connected to network"); @@ -791,7 +793,7 @@ void webServerUpdate() // Start the web server case WEBSERVER_STATE_NETWORK_CONNECTED: { // Determine if the network has failed - if (networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) + if (networkIsConnected(&webServerPriority) == false && WIFI_SOFT_AP_RUNNING() == false) webServerStop(); if (settings.debugWebServer) systemPrintln("Assigning web server resources"); @@ -807,7 +809,7 @@ void webServerUpdate() // Allow web services case WEBSERVER_STATE_RUNNING: // Determine if the network has failed - if (networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) + if (networkIsConnected(&webServerPriority) == false && WIFI_SOFT_AP_RUNNING() == false) webServerStop(); // This state is exited when webServerStop() is called diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index 3a1e64f59..b99a4d330 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -33,6 +33,7 @@ static const int otaStateEntries = sizeof(otaStateNames) / sizeof(otaStateNames[ //---------------------------------------- static uint32_t otaLastUpdateCheck; +static NetPriority_t otaPriority = NETWORK_OFFLINE; static uint8_t otaState; #endif // COMPILE_OTA_AUTO @@ -840,9 +841,7 @@ void otaUpdate() otaUpdateStop(); // Wait until the network is connected to the media - // else if (networkHasInternet()) - else if (networkInterfaceHasInternet( - NETWORK_WIFI)) // TODO Remove once OTA works over other network interfaces + else if (networkIsConnected(&otaPriority)) { if (settings.debugFirmwareUpdate) systemPrintln("Firmware update connected to network"); @@ -855,9 +854,7 @@ void otaUpdate() // Get firmware version from server case OTA_STATE_GET_FIRMWARE_VERSION: // Determine if the network has failed - // if (networkHasInternet() == false) - if (networkInterfaceHasInternet(NETWORK_WIFI) == - false) // TODO Remove once OTA works over other network interfaces + if (!networkIsConnected(&otaPriority)) otaUpdateStop(); if (settings.debugFirmwareUpdate) systemPrintln("Checking for latest firmware version"); @@ -913,7 +910,7 @@ void otaUpdate() // Update the firmware case OTA_STATE_UPDATE_FIRMWARE: // Determine if the network has failed - if (networkHasInternet() == false) + if (!networkIsConnected(&otaPriority)) otaUpdateStop(); else { diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index 6d62f4f54..bd3db6850 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -21,6 +21,7 @@ static const uint8_t ppIpToken[16] = {POINTPERFECT_IP_TOKEN}; // Toke static const uint8_t ppLbandIpToken[16] = {POINTPERFECT_LBAND_IP_TOKEN}; // Token in HEX form #ifdef COMPILE_NETWORK +static NetPriority_t pointperfectPriority = NETWORK_OFFLINE; MqttClient *menuppMqttClient; #endif // COMPILE_NETWORK @@ -1308,7 +1309,7 @@ void provisioningUpdate() } // Wait until the network is available #ifdef COMPILE_NETWORK - else if (networkHasInternet()) + else if (networkIsConnected(&pointperfectPriority)) { if (settings.debugPpCertificate) systemPrintln("PointPerfect key update connected to network"); From 397c99cee6cf74c1df0b7a7b38e95621cda21119 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 24 Jan 2025 10:12:04 -1000 Subject: [PATCH 167/276] WiFi: Move constants and variables --- Firmware/RTK_Everywhere/WiFi.ino | 51 ++++++++++++-------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index ee087ca73..1ec26f676 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -406,6 +406,9 @@ const int wifiStartNamesEntries = sizeof(wifiStartNames) / sizeof(wifiStartNames | WIFI_STA_SELECT_REMOTE_AP \ | WIFI_STA_NO_REMOTE_AP) +#define WIFI_MAX_TIMEOUT (15 * 60 * 1000) // Timeout in milliseconds +#define WIFI_MIN_TIMEOUT (15 * 1000) // Timeout in milliseconds + const char * wifiSoftApSsid = "RTK Config"; const char * wifiSoftApPassword = nullptr; @@ -413,6 +416,7 @@ const char * wifiSoftApPassword = nullptr; // Globals //**************************************** +bool restartWiFi = false; // Restart WiFi if user changes anything bool wifiRestartRequested = false; // Restart WiFi if user changes anything //**************************************** @@ -422,6 +426,21 @@ bool wifiRestartRequested = false; // Restart WiFi if user changes anything // DNS server for Captive Portal static DNSServer dnsServer; +// Start timeout +static uint32_t wifiStartTimeout; +static uint32_t wifiStartLastTry; // The last time WiFi start was attempted + +// WiFi Timer usage: +// * Measure interval to display IP address +static unsigned long wifiDisplayTimer; + +// WiFi interface status +static bool wifiApRunning; +static bool wifiStationRunning; + +static int wifiFailedConnectionAttempts = 0; // Count the number of connection attempts between restarts +static WiFiMulti *wifiMulti; + //********************************************************************* // Callback for all WiFi RX Packets // Get RSSI of all incoming management packets: https://esp32.com/viewtopic.php?t=13889 @@ -2558,38 +2577,6 @@ void RTK_WIFI::verifyTables() WL_SCAN_COMPLETED: assigned when the scan networks is completed =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -//---------------------------------------- -// Globals -//---------------------------------------- - -int wifiFailedConnectionAttempts = 0; // Count the number of connection attempts between restarts - -bool restartWiFi = false; // Restart WiFi if user changes anything - -WiFiMulti *wifiMulti; - -//---------------------------------------- -// Constants -//---------------------------------------- - -#define WIFI_MAX_TIMEOUT (15 * 60 * 1000) -#define WIFI_MIN_TIMEOUT (15 * 1000) - -//---------------------------------------- -// Locals -//---------------------------------------- - -// Start timeout -static uint32_t wifiStartTimeout; -static uint32_t wifiStartLastTry; // The last time WiFi start was attempted - -// WiFi Timer usage: -// * Measure interval to display IP address -static unsigned long wifiDisplayTimer; - -static bool wifiStationRunning; -static bool wifiApRunning; - //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // WiFi Routines //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= From ef9a9e732f0f81a1d6f20b00e5022f2a2f61dcb0 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 24 Jan 2025 09:32:54 -1000 Subject: [PATCH 168/276] WiFi: Move wifiNetworkCount --- Firmware/RTK_Everywhere/WiFi.ino | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 1ec26f676..b5b5bbcd7 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -441,6 +441,20 @@ static bool wifiStationRunning; static int wifiFailedConnectionAttempts = 0; // Count the number of connection attempts between restarts static WiFiMulti *wifiMulti; +//********************************************************************* +// Counts the number of entered SSIDs +int wifiNetworkCount() +{ + // Count SSIDs + int networkCount = 0; + for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + { + if (strlen(settings.wifiNetworks[x].ssid) > 0) + networkCount++; + } + return networkCount; +} + //********************************************************************* // Callback for all WiFi RX Packets // Get RSSI of all incoming management packets: https://esp32.com/viewtopic.php?t=13889 @@ -3007,21 +3021,6 @@ bool wifiIsRunning() return false; } -//---------------------------------------- -// Counts the number of entered SSIDs -//---------------------------------------- -int wifiNetworkCount() -{ - // Count SSIDs - int networkCount = 0; - for (int x = 0; x < MAX_WIFI_NETWORKS; x++) - { - if (strlen(settings.wifiNetworks[x].ssid) > 0) - networkCount++; - } - return networkCount; -} - //---------------------------------------- // Given a status, return the associated state or error //---------------------------------------- From 9fae969f8a9e0c973c47e02932e9bd7be65cb1ad Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 24 Jan 2025 09:38:21 -1000 Subject: [PATCH 169/276] WiFi: Move wifiPrintState --- Firmware/RTK_Everywhere/WiFi.ino | 57 ++++++++++++++++---------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index b5b5bbcd7..32f8bbaa0 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -455,6 +455,34 @@ int wifiNetworkCount() return networkCount; } +//********************************************************************* +// Given a status, return the associated state or error +const char *wifiPrintState(wl_status_t wifiStatus) +{ + switch (wifiStatus) + { + case WL_NO_SHIELD: // 255 + return ("WL_NO_SHIELD"); + case WL_STOPPED: // 254 + return ("WL_STOPPED"); + case WL_IDLE_STATUS: // 0 + return ("WL_IDLE_STATUS"); + case WL_NO_SSID_AVAIL: // 1 + return ("WL_NO_SSID_AVAIL"); + case WL_SCAN_COMPLETED: // 2 + return ("WL_SCAN_COMPLETED"); + case WL_CONNECTED: // 3 + return ("WL_CONNECTED"); + case WL_CONNECT_FAILED: // 4 + return ("WL_CONNECT_FAILED"); + case WL_CONNECTION_LOST: // 5 + return ("WL_CONNECTION_LOST"); + case WL_DISCONNECTED: // 6 + return ("WL_DISCONNECTED"); + } + return ("WiFi Status Unknown"); +} + //********************************************************************* // Callback for all WiFi RX Packets // Get RSSI of all incoming management packets: https://esp32.com/viewtopic.php?t=13889 @@ -3021,35 +3049,6 @@ bool wifiIsRunning() return false; } -//---------------------------------------- -// Given a status, return the associated state or error -//---------------------------------------- -const char *wifiPrintState(wl_status_t wifiStatus) -{ - switch (wifiStatus) - { - case WL_NO_SHIELD: - return ("WL_NO_SHIELD"); // 255 - case WL_STOPPED: - return ("WL_STOPPED"); - case WL_IDLE_STATUS: // 0 - return ("WL_IDLE_STATUS"); - case WL_NO_SSID_AVAIL: // 1 - return ("WL_NO_SSID_AVAIL"); - case WL_SCAN_COMPLETED: // 2 - return ("WL_SCAN_COMPLETED"); - case WL_CONNECTED: // 3 - return ("WL_CONNECTED"); - case WL_CONNECT_FAILED: // 4 - return ("WL_CONNECT_FAILED"); - case WL_CONNECTION_LOST: // 5 - return ("WL_CONNECTION_LOST"); - case WL_DISCONNECTED: // 6 - return ("WL_DISCONNECTED"); - } - return ("WiFi Status Unknown"); -} - //---------------------------------------- // Starts the WiFi connection state machine (moves from WIFI_STATE_OFF to WIFI_STATE_CONNECTING) // Sets the appropriate protocols (WiFi + ESP-Now) From c8ea58adbfba72e56032ec2940135655c216f11b Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 24 Jan 2025 09:41:09 -1000 Subject: [PATCH 170/276] WiFi: Move wifiDisplayState --- Firmware/RTK_Everywhere/WiFi.ino | 73 ++++++++++++++++---------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 32f8bbaa0..7e90c1329 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -441,6 +441,42 @@ static bool wifiStationRunning; static int wifiFailedConnectionAttempts = 0; // Count the number of connection attempts between restarts static WiFiMulti *wifiMulti; +//********************************************************************* +// Display the WiFi state +void wifiDisplayState() +{ + systemPrintf("WiFi: %s\r\n", networkInterfaceHasInternet(NETWORK_WIFI) ? "Online" : "Offline"); + systemPrintf(" MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\r\n", wifiMACAddress[0], wifiMACAddress[1], + wifiMACAddress[2], wifiMACAddress[3], wifiMACAddress[4], wifiMACAddress[5]); + if (networkInterfaceHasInternet(NETWORK_WIFI)) + { + // Get the DNS addresses + IPAddress dns1 = WiFi.STA.dnsIP(0); + IPAddress dns2 = WiFi.STA.dnsIP(1); + IPAddress dns3 = WiFi.STA.dnsIP(2); + + // Get the WiFi status + wl_status_t wifiStatus = WiFi.status(); + + const char *wifiStatusString = wifiPrintState(wifiStatus); + + // Display the WiFi state + systemPrintf(" SSID: %s\r\n", WiFi.STA.SSID()); + systemPrintf(" IP Address: %s\r\n", WiFi.STA.localIP().toString().c_str()); + systemPrintf(" Subnet Mask: %s\r\n", WiFi.STA.subnetMask().toString().c_str()); + systemPrintf(" Gateway Address: %s\r\n", WiFi.STA.gatewayIP().toString().c_str()); + if ((uint32_t)dns3) + systemPrintf(" DNS Address: %s, %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str(), + dns3.toString().c_str()); + else if ((uint32_t)dns3) + systemPrintf(" DNS Address: %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str()); + else + systemPrintf(" DNS Address: %s\r\n", dns1.toString().c_str()); + systemPrintf(" WiFi Strength: %d dBm\r\n", WiFi.RSSI()); + systemPrintf(" WiFi Status: %d (%s)\r\n", wifiStatus, wifiStatusString); + } +} + //********************************************************************* // Counts the number of entered SSIDs int wifiNetworkCount() @@ -2861,43 +2897,6 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) return false; } -//---------------------------------------- -// Display the WiFi state -//---------------------------------------- -void wifiDisplayState() -{ - systemPrintf("WiFi: %s\r\n", networkInterfaceHasInternet(NETWORK_WIFI) ? "Online" : "Offline"); - systemPrintf(" MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\r\n", wifiMACAddress[0], wifiMACAddress[1], - wifiMACAddress[2], wifiMACAddress[3], wifiMACAddress[4], wifiMACAddress[5]); - if (networkInterfaceHasInternet(NETWORK_WIFI)) - { - // Get the DNS addresses - IPAddress dns1 = WiFi.STA.dnsIP(0); - IPAddress dns2 = WiFi.STA.dnsIP(1); - IPAddress dns3 = WiFi.STA.dnsIP(2); - - // Get the WiFi status - wl_status_t wifiStatus = WiFi.status(); - - const char *wifiStatusString = wifiPrintState(wifiStatus); - - // Display the WiFi state - systemPrintf(" SSID: %s\r\n", WiFi.STA.SSID()); - systemPrintf(" IP Address: %s\r\n", WiFi.STA.localIP().toString().c_str()); - systemPrintf(" Subnet Mask: %s\r\n", WiFi.STA.subnetMask().toString().c_str()); - systemPrintf(" Gateway Address: %s\r\n", WiFi.STA.gatewayIP().toString().c_str()); - if ((uint32_t)dns3) - systemPrintf(" DNS Address: %s, %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str(), - dns3.toString().c_str()); - else if ((uint32_t)dns3) - systemPrintf(" DNS Address: %s, %s\r\n", dns1.toString().c_str(), dns2.toString().c_str()); - else - systemPrintf(" DNS Address: %s\r\n", dns1.toString().c_str()); - systemPrintf(" WiFi Strength: %d dBm\r\n", WiFi.RSSI()); - systemPrintf(" WiFi Status: %d\r\n", wifiStatusString); - } -} - //---------------------------------------- // Process the WiFi events //---------------------------------------- From 8f55181aee6cbea97785bfadc39d52113fae98c1 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 24 Jan 2025 09:50:22 -1000 Subject: [PATCH 171/276] WiFi: Move menuWiFi --- Firmware/RTK_Everywhere/WiFi.ino | 153 +++++++++++++++---------------- 1 file changed, 76 insertions(+), 77 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 7e90c1329..300a44c0c 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -441,6 +441,82 @@ static bool wifiStationRunning; static int wifiFailedConnectionAttempts = 0; // Count the number of connection attempts between restarts static WiFiMulti *wifiMulti; +//********************************************************************* +// Set WiFi credentials +// Enable TCP connections +void menuWiFi() +{ + while (1) + { + networkDisplayInterface(NETWORK_WIFI); + + systemPrintln(); + systemPrintln("Menu: WiFi Networks"); + + for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + { + systemPrintf("%d) SSID %d: %s\r\n", (x * 2) + 1, x + 1, settings.wifiNetworks[x].ssid); + systemPrintf("%d) Password %d: %s\r\n", (x * 2) + 2, x + 1, settings.wifiNetworks[x].password); + } + + systemPrint("a) Configure device via WiFi Access Point or connect to WiFi: "); + systemPrintf("%s\r\n", settings.wifiConfigOverAP ? "AP" : "WiFi"); + + systemPrint("c) Captive Portal: "); + systemPrintf("%s\r\n", settings.enableCaptivePortal ? "Enabled" : "Disabled"); + + systemPrintln("x) Exit"); + + byte incoming = getUserInputCharacterNumber(); + + if (incoming >= 1 && incoming <= MAX_WIFI_NETWORKS * 2) + { + int arraySlot = ((incoming - 1) / 2); // Adjust incoming to array starting at 0 + + if (incoming % 2 == 1) + { + systemPrintf("Enter SSID network %d: ", arraySlot + 1); + getUserInputString(settings.wifiNetworks[arraySlot].ssid, + sizeof(settings.wifiNetworks[arraySlot].ssid)); + restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi + } + else + { + systemPrintf("Enter Password for %s: ", settings.wifiNetworks[arraySlot].ssid); + getUserInputString(settings.wifiNetworks[arraySlot].password, + sizeof(settings.wifiNetworks[arraySlot].password)); + restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi + } + } + else if (incoming == 'a') + { + settings.wifiConfigOverAP ^= 1; + restartWiFi = true; + } + else if (incoming == 'c') + { + settings.enableCaptivePortal ^= 1; + } + else if (incoming == 'x') + break; + else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_EMPTY) + break; + else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_TIMEOUT) + break; + else + printUnknown(incoming); + } + + // Erase passwords from empty SSID entries + for (int x = 0; x < MAX_WIFI_NETWORKS; x++) + { + if (strlen(settings.wifiNetworks[x].ssid) == 0) + strcpy(settings.wifiNetworks[x].password, ""); + } + + clearBuffer(); // Empty buffer of any newline chars +} + //********************************************************************* // Display the WiFi state void wifiDisplayState() @@ -2659,83 +2735,6 @@ void RTK_WIFI::verifyTables() // WiFi Routines //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -//---------------------------------------- -// Set WiFi credentials -// Enable TCP connections -//---------------------------------------- -void menuWiFi() -{ - while (1) - { - networkDisplayInterface(NETWORK_WIFI); - - systemPrintln(); - systemPrintln("Menu: WiFi Networks"); - - for (int x = 0; x < MAX_WIFI_NETWORKS; x++) - { - systemPrintf("%d) SSID %d: %s\r\n", (x * 2) + 1, x + 1, settings.wifiNetworks[x].ssid); - systemPrintf("%d) Password %d: %s\r\n", (x * 2) + 2, x + 1, settings.wifiNetworks[x].password); - } - - systemPrint("a) Configure device via WiFi Access Point or connect to WiFi: "); - systemPrintf("%s\r\n", settings.wifiConfigOverAP ? "AP" : "WiFi"); - - systemPrint("c) Captive Portal: "); - systemPrintf("%s\r\n", settings.enableCaptivePortal ? "Enabled" : "Disabled"); - - systemPrintln("x) Exit"); - - byte incoming = getUserInputCharacterNumber(); - - if (incoming >= 1 && incoming <= MAX_WIFI_NETWORKS * 2) - { - int arraySlot = ((incoming - 1) / 2); // Adjust incoming to array starting at 0 - - if (incoming % 2 == 1) - { - systemPrintf("Enter SSID network %d: ", arraySlot + 1); - getUserInputString(settings.wifiNetworks[arraySlot].ssid, - sizeof(settings.wifiNetworks[arraySlot].ssid)); - restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi - } - else - { - systemPrintf("Enter Password for %s: ", settings.wifiNetworks[arraySlot].ssid); - getUserInputString(settings.wifiNetworks[arraySlot].password, - sizeof(settings.wifiNetworks[arraySlot].password)); - restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi - } - } - else if (incoming == 'a') - { - settings.wifiConfigOverAP ^= 1; - restartWiFi = true; - } - else if (incoming == 'c') - { - settings.enableCaptivePortal ^= 1; - } - else if (incoming == 'x') - break; - else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_EMPTY) - break; - else if (incoming == INPUT_RESPONSE_GETCHARACTERNUMBER_TIMEOUT) - break; - else - printUnknown(incoming); - } - - // Erase passwords from empty SSID entries - for (int x = 0; x < MAX_WIFI_NETWORKS; x++) - { - if (strlen(settings.wifiNetworks[x].ssid) == 0) - strcpy(settings.wifiNetworks[x].password, ""); - } - - clearBuffer(); // Empty buffer of any newline chars -} - //---------------------------------------- // Starts WiFi in STA, AP, or STA_AP mode depending on bools // Returns true if STA connects, or if AP is started From a441447ca90a83e181d1a7e76165f941c3163ada Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 24 Jan 2025 09:51:41 -1000 Subject: [PATCH 172/276] WiFi: Move wifiResetTimeout --- Firmware/RTK_Everywhere/WiFi.ino | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 300a44c0c..ec2f91f6a 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -611,6 +611,17 @@ void wifiPromiscuousRxHandler(void *buf, wifi_promiscuous_pkt_type_t type) packetRSSI = ppkt->rx_ctrl.rssi; } +//********************************************************************* +// Set WiFi timeout back to zero +// Useful if other things (such as a successful ethernet connection) need +// to reset wifi timeout +void wifiResetTimeout() +{ + wifiStartTimeout = 0; + if (settings.debugWifiState == true) + systemPrintln("WiFi: Start timeout reset to zero"); +} + //********************************************************************* // Constructor // Inputs: @@ -3117,17 +3128,6 @@ bool wifiStart() return (wifiStatus == WL_CONNECTED); } -//---------------------------------------- -// Set WiFi timeout back to zero -// Useful if other things (such as a successful ethernet connection) need to reset wifi timeout -//---------------------------------------- -void wifiResetTimeout() -{ - wifiStartTimeout = 0; - if (settings.debugWifiState == true) - systemPrintln("WiFi: Start timeout reset to zero"); -} - //---------------------------------------- //---------------------------------------- uint32_t wifiGetStartTimeout() From 3961f18b06af98019aadbf3d6ab5942241422f7c Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 24 Jan 2025 09:52:48 -1000 Subject: [PATCH 173/276] WiFi: Move wifiStart --- Firmware/RTK_Everywhere/WiFi.ino | 139 +++++++++++++++---------------- 1 file changed, 69 insertions(+), 70 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index ec2f91f6a..2ec5a4561 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -622,6 +622,75 @@ void wifiResetTimeout() systemPrintln("WiFi: Start timeout reset to zero"); } +//********************************************************************* +// Starts the WiFi connection state machine (moves from WIFI_STATE_OFF to WIFI_STATE_CONNECTING) +// Sets the appropriate protocols (WiFi + ESP-Now) +// If radio is off entirely, start WiFi +// If ESP-Now is active, only add the LR protocol +// Returns true if WiFi has connected and false otherwise +bool wifiStart() +{ + int wifiStatus; + + // Determine which parts of WiFi need to be started + bool startWiFiStation = false; + bool startWiFiAp = false; + + uint16_t consumerTypes = networkGetConsumerTypes(); + + // The consumers need station + if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) + startWiFiStation = true; + + // The consumers need AP + if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) + startWiFiAp = true; + + if (startWiFiStation == false && startWiFiAp == false) + { + systemPrintln("wifiStart() requested without any NETCONSUMER combination"); + WIFI_STOP(); + return (false); + } + + // Determine if WiFi is already running + if (startWiFiStation == wifiStationRunning && startWiFiAp == wifiApRunning) + { + if (settings.debugWifiState == true) + systemPrintln("WiFi is already running with requested setup"); + return (true); + } + + // Handle special cases if no networks have been entered + if (wifiNetworkCount() == 0) + { + if (startWiFiStation == true && startWiFiAp == false) + { + systemPrintln("Error: Please enter at least one SSID before using WiFi"); + displayNoSSIDs(2000); + WIFI_STOP(); + return false; + } + else if (startWiFiStation == true && startWiFiAp == true) + { + systemPrintln("Error: No SSID available to start WiFi Station during AP"); + // Allow the system to continue in AP only mode + startWiFiStation = false; + } + } + + // Start WiFi + wifiConnect(startWiFiStation, startWiFiAp, settings.wifiConnectTimeoutMs); + + // If we are in AP only mode, as long as the AP is started, return true + if (WiFi.getMode() == WIFI_MODE_AP) + return WIFI_SOFT_AP_RUNNING(); + + // If we are in STA or AP+STA mode, return if the station connected successfully + wifiStatus = WiFi.status(); + return (wifiStatus == WL_CONNECTED); +} + //********************************************************************* // Constructor // Inputs: @@ -3058,76 +3127,6 @@ bool wifiIsRunning() return false; } -//---------------------------------------- -// Starts the WiFi connection state machine (moves from WIFI_STATE_OFF to WIFI_STATE_CONNECTING) -// Sets the appropriate protocols (WiFi + ESP-Now) -// If radio is off entirely, start WiFi -// If ESP-Now is active, only add the LR protocol -// Returns true if WiFi has connected and false otherwise -//---------------------------------------- -bool wifiStart() -{ - int wifiStatus; - - // Determine which parts of WiFi need to be started - bool startWiFiStation = false; - bool startWiFiAp = false; - - uint16_t consumerTypes = networkGetConsumerTypes(); - - // The consumers need station - if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) - startWiFiStation = true; - - // The consumers need AP - if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) - startWiFiAp = true; - - if (startWiFiStation == false && startWiFiAp == false) - { - systemPrintln("wifiStart() requested without any NETCONSUMER combination"); - WIFI_STOP(); - return (false); - } - - // Determine if WiFi is already running - if (startWiFiStation == wifiStationRunning && startWiFiAp == wifiApRunning) - { - if (settings.debugWifiState == true) - systemPrintln("WiFi is already running with requested setup"); - return (true); - } - - // Handle special cases if no networks have been entered - if (wifiNetworkCount() == 0) - { - if (startWiFiStation == true && startWiFiAp == false) - { - systemPrintln("Error: Please enter at least one SSID before using WiFi"); - displayNoSSIDs(2000); - WIFI_STOP(); - return false; - } - else if (startWiFiStation == true && startWiFiAp == true) - { - systemPrintln("Error: No SSID available to start WiFi Station during AP"); - // Allow the system to continue in AP only mode - startWiFiStation = false; - } - } - - // Start WiFi - wifiConnect(startWiFiStation, startWiFiAp, settings.wifiConnectTimeoutMs); - - // If we are in AP only mode, as long as the AP is started, return true - if (WiFi.getMode() == WIFI_MODE_AP) - return WIFI_SOFT_AP_RUNNING(); - - // If we are in STA or AP+STA mode, return if the station connected successfully - wifiStatus = WiFi.status(); - return (wifiStatus == WL_CONNECTED); -} - //---------------------------------------- //---------------------------------------- uint32_t wifiGetStartTimeout() From 067f1bb0cf83628f10a39299ededaaea47b60583 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 24 Jan 2025 09:55:20 -1000 Subject: [PATCH 174/276] WiFi: Move wifiStop --- Firmware/RTK_Everywhere/WiFi.ino | 114 +++++++++++++++---------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 2ec5a4561..6f141707a 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -691,6 +691,63 @@ bool wifiStart() return (wifiStatus == WL_CONNECTED); } +//********************************************************************* +// Stop WiFi and release all resources +void wifiStop() +{ + // Stop the web server + stopWebServer(); + + // Stop the DNS server if we were using the captive portal + if (((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) && settings.enableCaptivePortal) + dnsServer.stop(); + + wifiFailedConnectionAttempts = 0; // Reset the counter + + // If ESP-Now is active, change protocol to only Long Range + if (espnowGetState() > ESPNOW_OFF) + { + if (WiFi.getMode() != WIFI_STA) + WiFi.mode(WIFI_STA); + + // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps + // esp_wifi_set_protocol requires WiFi to be started + esp_err_t response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); + if (response != ESP_OK) + systemPrintf("wifiShutdown: Error setting ESP-Now lone protocol: %s\r\n", esp_err_to_name(response)); + else + { + if (settings.debugWifiState == true) + systemPrintln("WiFi disabled, ESP-Now left in place"); + } + } + else + { + WiFi.mode(WIFI_OFF); + if (settings.debugWifiState == true) + systemPrintln("WiFi Stopped"); + } + + // Take the network offline + networkInterfaceInternetConnectionLost(NETWORK_WIFI); + + if (wifiMulti != nullptr) + wifiMulti = nullptr; + + // Display the heap state + reportHeapNow(settings.debugWifiState); + wifiStationRunning = false; + wifiApRunning = false; +} + +//********************************************************************* +// Needed for wifiStopSequence +void wifiStop(NetIndex_t index, uintptr_t parameter, bool debug) +{ + wifiStop(); + networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); +} + //********************************************************************* // Constructor // Inputs: @@ -3200,63 +3257,6 @@ NETWORK_POLL_SEQUENCE wifiStopSequence[] = { {nullptr, 0, "Termination"}, }; -//---------------------------------------- -// Stop WiFi and release all resources -//---------------------------------------- -void wifiStop() -{ - // Stop the web server - stopWebServer(); - - // Stop the DNS server if we were using the captive portal - if (((WiFi.getMode() == WIFI_AP) || (WiFi.getMode() == WIFI_AP_STA)) && settings.enableCaptivePortal) - dnsServer.stop(); - - wifiFailedConnectionAttempts = 0; // Reset the counter - - // If ESP-Now is active, change protocol to only Long Range - if (espnowGetState() > ESPNOW_OFF) - { - if (WiFi.getMode() != WIFI_STA) - WiFi.mode(WIFI_STA); - - // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps - // esp_wifi_set_protocol requires WiFi to be started - esp_err_t response = esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); - if (response != ESP_OK) - systemPrintf("wifiShutdown: Error setting ESP-Now lone protocol: %s\r\n", esp_err_to_name(response)); - else - { - if (settings.debugWifiState == true) - systemPrintln("WiFi disabled, ESP-Now left in place"); - } - } - else - { - WiFi.mode(WIFI_OFF); - if (settings.debugWifiState == true) - systemPrintln("WiFi Stopped"); - } - - // Take the network offline - networkInterfaceInternetConnectionLost(NETWORK_WIFI); - - if (wifiMulti != nullptr) - wifiMulti = nullptr; - - // Display the heap state - reportHeapNow(settings.debugWifiState); - wifiStationRunning = false; - wifiApRunning = false; -} - -// Needed for wifiStopSequence -void wifiStop(NetIndex_t index, uintptr_t parameter, bool debug) -{ - wifiStop(); - networkSequenceNextEntry(NETWORK_WIFI, settings.debugNetworkLayer); -} - // Returns true if we deem WiFi is not going to connect // Used to allow cellular to start bool wifiUnavailable() From 60742221a589261c7c090bdd2ffb8579789b8c45 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 24 Jan 2025 09:58:38 -1000 Subject: [PATCH 175/276] WiFi: Move wifiEvent --- Firmware/RTK_Everywhere/WiFi.ino | 227 +++++++++++++++---------------- 1 file changed, 113 insertions(+), 114 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 6f141707a..15d60ae39 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -553,6 +553,119 @@ void wifiDisplayState() } } +//********************************************************************* +// Process the WiFi events +void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) +{ + char ssid[sizeof(info.wifi_sta_connected.ssid) + 1]; + IPAddress ipAddress; + + // If we are in AP or AP_STA, the network is immediately marked online + // Once AP is online, don't stop WiFi because STA has various events + if (WiFi.getMode() == WIFI_MODE_STA) + { + // Take the network offline if necessary + if (networkInterfaceHasInternet(NETWORK_WIFI) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP) && + (event != ARDUINO_EVENT_WIFI_STA_GOT_IP6)) + { + if (settings.debugWifiState) + systemPrintf("Stopping WiFi because of event # %d\r\n", event); + + networkStop(NETWORK_WIFI, settings.debugNetworkLayer); // Stop WiFi to allow it to restart + } + } + + // WiFi State Machine + // + // .--------+<----------+<-----------+<-------------+<----------+<----------+<------------. + // v | | | | | | | + // STOP --> READY --> STA_START --> SCAN_DONE --> CONNECTED --> GOT_IP --> LOST_IP --> DISCONNECTED + // ^ ^ | | + // | '-----------' | + // '-------------------------------------' + // + // Handle the event + switch (event) + { + default: + systemPrintf("ERROR: Unknown WiFi event: %d\r\n", event); + break; + + case ARDUINO_EVENT_WIFI_OFF: + systemPrintln("WiFi Off"); + break; + + case ARDUINO_EVENT_WIFI_READY: + if (settings.debugWifiState) + systemPrintln("WiFi Ready"); + WiFi.setHostname(settings.mdnsHostName); + break; + + case ARDUINO_EVENT_WIFI_SCAN_DONE: + if (settings.debugWifiState) + systemPrintln("WiFi Scan Done"); + // wifi_event_sta_scan_done_t info.wifi_scan_done; + break; + + case ARDUINO_EVENT_WIFI_STA_START: + if (settings.debugWifiState) + systemPrintln("WiFi STA Started"); + break; + + case ARDUINO_EVENT_WIFI_STA_STOP: + if (settings.debugWifiState) + systemPrintln("WiFi STA Stopped"); + break; + + case ARDUINO_EVENT_WIFI_STA_CONNECTED: + memcpy(ssid, info.wifi_sta_connected.ssid, info.wifi_sta_connected.ssid_len); + ssid[info.wifi_sta_connected.ssid_len] = 0; + + ipAddress = WiFi.localIP(); + systemPrintf("WiFi STA connected to %s with IP address: ", ssid); + systemPrintln(ipAddress); + + WiFi.setHostname(settings.mdnsHostName); + break; + + case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: + memcpy(ssid, info.wifi_sta_disconnected.ssid, info.wifi_sta_disconnected.ssid_len); + ssid[info.wifi_sta_disconnected.ssid_len] = 0; + systemPrintf("WiFi STA disconnected from %s\r\n", ssid); + // wifi_event_sta_disconnected_t info.wifi_sta_disconnected; + break; + + case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: + systemPrintln("WiFi STA Auth Mode Changed"); + // wifi_event_sta_authmode_change_t info.wifi_sta_authmode_change; + break; + + case ARDUINO_EVENT_WIFI_STA_GOT_IP: + if (settings.debugWifiState) + { + ipAddress = WiFi.localIP(); + systemPrint("WiFi STA Got IPv4: "); + systemPrintln(ipAddress); + } + networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); + break; + + case ARDUINO_EVENT_WIFI_STA_GOT_IP6: + if (settings.debugWifiState) + { + ipAddress = WiFi.localIP(); + systemPrint("WiFi STA Got IPv6: "); + systemPrintln(ipAddress); + } + networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); + break; + + case ARDUINO_EVENT_WIFI_STA_LOST_IP: + systemPrintln("WiFi STA Lost IP"); + break; + } +} + //********************************************************************* // Counts the number of entered SSIDs int wifiNetworkCount() @@ -3033,120 +3146,6 @@ bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) return false; } -//---------------------------------------- -// Process the WiFi events -//---------------------------------------- -void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) -{ - char ssid[sizeof(info.wifi_sta_connected.ssid) + 1]; - IPAddress ipAddress; - - // If we are in AP or AP_STA, the network is immediately marked online - // Once AP is online, don't stop WiFi because STA has various events - if (WiFi.getMode() == WIFI_MODE_STA) - { - // Take the network offline if necessary - if (networkInterfaceHasInternet(NETWORK_WIFI) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP) && - (event != ARDUINO_EVENT_WIFI_STA_GOT_IP6)) - { - if (settings.debugWifiState) - systemPrintf("Stopping WiFi because of event # %d\r\n", event); - - networkStop(NETWORK_WIFI, settings.debugNetworkLayer); // Stop WiFi to allow it to restart - } - } - - // WiFi State Machine - // - // .--------+<----------+<-----------+<-------------+<----------+<----------+<------------. - // v | | | | | | | - // STOP --> READY --> STA_START --> SCAN_DONE --> CONNECTED --> GOT_IP --> LOST_IP --> DISCONNECTED - // ^ ^ | | - // | '-----------' | - // '-------------------------------------' - // - // Handle the event - switch (event) - { - default: - systemPrintf("ERROR: Unknown WiFi event: %d\r\n", event); - break; - - case ARDUINO_EVENT_WIFI_OFF: - systemPrintln("WiFi Off"); - break; - - case ARDUINO_EVENT_WIFI_READY: - if (settings.debugWifiState) - systemPrintln("WiFi Ready"); - WiFi.setHostname(settings.mdnsHostName); - break; - - case ARDUINO_EVENT_WIFI_SCAN_DONE: - if (settings.debugWifiState) - systemPrintln("WiFi Scan Done"); - // wifi_event_sta_scan_done_t info.wifi_scan_done; - break; - - case ARDUINO_EVENT_WIFI_STA_START: - if (settings.debugWifiState) - systemPrintln("WiFi STA Started"); - break; - - case ARDUINO_EVENT_WIFI_STA_STOP: - if (settings.debugWifiState) - systemPrintln("WiFi STA Stopped"); - break; - - case ARDUINO_EVENT_WIFI_STA_CONNECTED: - memcpy(ssid, info.wifi_sta_connected.ssid, info.wifi_sta_connected.ssid_len); - ssid[info.wifi_sta_connected.ssid_len] = 0; - - ipAddress = WiFi.localIP(); - systemPrintf("WiFi STA connected to %s with IP address: ", ssid); - systemPrintln(ipAddress); - - WiFi.setHostname(settings.mdnsHostName); - break; - - case ARDUINO_EVENT_WIFI_STA_DISCONNECTED: - memcpy(ssid, info.wifi_sta_disconnected.ssid, info.wifi_sta_disconnected.ssid_len); - ssid[info.wifi_sta_disconnected.ssid_len] = 0; - systemPrintf("WiFi STA disconnected from %s\r\n", ssid); - // wifi_event_sta_disconnected_t info.wifi_sta_disconnected; - break; - - case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: - systemPrintln("WiFi STA Auth Mode Changed"); - // wifi_event_sta_authmode_change_t info.wifi_sta_authmode_change; - break; - - case ARDUINO_EVENT_WIFI_STA_GOT_IP: - if (settings.debugWifiState) - { - ipAddress = WiFi.localIP(); - systemPrint("WiFi STA Got IPv4: "); - systemPrintln(ipAddress); - } - networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); - break; - - case ARDUINO_EVENT_WIFI_STA_GOT_IP6: - if (settings.debugWifiState) - { - ipAddress = WiFi.localIP(); - systemPrint("WiFi STA Got IPv6: "); - systemPrintln(ipAddress); - } - networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); - break; - - case ARDUINO_EVENT_WIFI_STA_LOST_IP: - systemPrintln("WiFi STA Lost IP"); - break; - } -} - //---------------------------------------- // Determine if WIFI is connected //---------------------------------------- From 7eeb5b9e02cfe81ada08ef3cbb0158183ef27d13 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 24 Jan 2025 10:26:12 -1000 Subject: [PATCH 176/276] WiFi: Rename wifiRestartRequested to restartWiFi --- Firmware/RTK_Everywhere/WiFi.ino | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 15d60ae39..cb2427436 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -417,7 +417,6 @@ const char * wifiSoftApPassword = nullptr; //**************************************** bool restartWiFi = false; // Restart WiFi if user changes anything -bool wifiRestartRequested = false; // Restart WiFi if user changes anything //**************************************** // Locals @@ -1118,9 +1117,9 @@ void RTK_WIFI::hostNameSet(const char * mDnsHostName) bool RTK_WIFI::restart(bool always) { // Determine if restart should be perforrmed - if (always || wifiRestartRequested) + if (always || restartWiFi) { - wifiRestartRequested = false; + restartWiFi = false; // Determine how WiFi is being used bool started = false; From 4b7e558761a11e55ac9c62eba8f3a97c5777eec4 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 24 Jan 2025 14:41:01 -0700 Subject: [PATCH 177/276] Increase check for v150 during test screen --- Firmware/RTK_Everywhere/Display.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index a56a272ba..61873e7f2 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -2510,7 +2510,7 @@ void paintSystemTest() oled->print(" "); oled->print(gnssFirmwareVersionInt); oled->print("-"); - if ((present.gnss_zedf9p) && (gnssFirmwareVersionInt < 130)) + if ((present.gnss_zedf9p) && (gnssFirmwareVersionInt < 150)) oled->print("FAIL"); else oled->print("OK"); From 202f1bcf204ea13fe899c0f51ed6ea722c8da947 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 27 Jan 2025 08:40:25 -0700 Subject: [PATCH 178/276] Fix compile guards --- Firmware/RTK_Everywhere/Developer.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index dbbdb888e..2b154260c 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -180,6 +180,7 @@ void webServerUpdate() {} bool espNowStart() {return false;} bool espNowStop() {return false;} +bool espnowGetState() {return ESPNOW_OFF;} bool espnowIsPaired() {return false;} void espnowProcessRTCM(byte incoming) {} esp_err_t espnowRemovePeer(uint8_t *peerMac) {return ESP_OK;} @@ -202,7 +203,7 @@ void menuWiFi() {systemPrintln("**WiFi not compiled**");} bool wifiApIsRunning() {return false;} bool wifiConnect(bool startWiFiStation, bool startWiFiAP, unsigned long timeout) {return false;} uint32_t wifiGetStartTimeout() {return 0;} -#define WIFI_IS_RUNNING() +#define WIFI_IS_RUNNING() 0 int wifiNetworkCount() {return 0;} void wifiResetThrottleTimeout() {} void wifiResetTimeout() {} From a167a9ae1b26a62ae55d2493627318dcc434e84e Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 27 Jan 2025 06:00:02 -1000 Subject: [PATCH 179/276] Remove dead code ethernetWebServerStartESP32W5500 ethernetWebServerStopESP32W5500 --- Firmware/RTK_Everywhere/Ethernet.ino | 27 ------------------------ Firmware/RTK_Everywhere/NVM.ino | 5 ----- Firmware/RTK_Everywhere/menuCommands.ino | 8 ------- 3 files changed, 40 deletions(-) diff --git a/Firmware/RTK_Everywhere/Ethernet.ino b/Firmware/RTK_Everywhere/Ethernet.ino index d24cc4042..595c4b57e 100644 --- a/Firmware/RTK_Everywhere/Ethernet.ino +++ b/Firmware/RTK_Everywhere/Ethernet.ino @@ -261,31 +261,4 @@ void ethernetStart() SPI); // SPIClass & } -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// Web server routines -//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - -//---------------------------------------- -// Start Ethernet for the web server -//---------------------------------------- -// void ethernetWebServerStartESP32W5500() -// { -// Network.onEvent(ethernetEvent); - -// // begin(ETH_PHY_TYPE, ETH_PHY_ADDR, CS, IRQ, RST, SPIClass &) -// ETH.begin(ETH_PHY_W5500, 0, pin_Ethernet_CS, pin_Ethernet_Interrupt, -1, SPI); - -// if (!settings.ethernetDHCP) -// ETH.config(settings.ethernetIP, settings.ethernetGateway, settings.ethernetSubnet, settings.ethernetDNS); -// } - -// //---------------------------------------- -// // Stop Ethernet for the web server -// //---------------------------------------- -// void ethernetWebServerStopESP32W5500() -// { -// ETH.end(); -// Network.removeEvent(ethernetEvent); -// } - #endif // COMPILE_ETHERNET diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index b9b39604e..9ec2b9d01 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -222,11 +222,6 @@ void recordSystemSettingsToFile(File *settingsFile) if (settingAvailableOnPlatform(i) == false) continue; - // Exceptions not stored in NVM: - // none currently - // if (strcmp(rtkSettingsEntries[i].name, "example") == 0) - // continue; - switch (rtkSettingsEntries[i].type) { default: diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index a7b8a63a8..4e004d265 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -2342,14 +2342,6 @@ SettingValueResponse getSettingValue(bool inCommands, const char *settingName, c knownSetting = true; } break; - // System state at power on. Convert various system states to either Rover, Base, NTP, or BaseCast. - // Manually handled below - // case tSysState: { - // SystemState *ptr = (SystemState *)var; - // writeToString(settingValueStr, (int)*ptr); - // knownSetting = true; - // } - break; case tPulseEdg: { pulseEdgeType_e *ptr = (pulseEdgeType_e *)var; writeToString(settingValueStr, (int)*ptr); From 51c2af794bfd134963d510a903dc0783c75f9efe Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 27 Jan 2025 10:01:57 -1000 Subject: [PATCH 180/276] Settings: Add new values and RTK_WIFI specific changes --- Firmware/RTK_Everywhere/settings.h | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 37aead000..1b3476dfc 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -357,11 +357,12 @@ typedef struct _NTRIP_SERVER_DATA typedef enum { - ESPNOW_OFF, + ESPNOW_OFF = 0, ESPNOW_BROADCASTING, ESPNOW_PAIRING, ESPNOW_MAC_RECEIVED, ESPNOW_PAIRED, + ESPNOW_MAX } ESPNOWState; volatile ESPNOWState espnowState = ESPNOW_OFF; @@ -1932,7 +1933,6 @@ class RTK_WIFI WIFI_CHANNEL_t _channel; // Current WiFi channel number WIFI_CHANNEL_t _espNowChannel; // Channel required for ESPNow, zero (0) use _channel bool _espNowRunning; // ESPNow started or running - const char * _hostName; // Name of this host volatile bool _scanRunning; // Scan running bool _softApRunning; // Soft AP is starting or running int _staAuthType; // Authorization type for the remote AP @@ -1940,13 +1940,14 @@ class RTK_WIFI bool _staHasIp; // True when station has IP address IPAddress _staIpAddress; // IP address of the station uint8_t _staIpType; // 4 or 6 when IP address is assigned - uint8_t _staMacAddress[6]; // MAC address of the station + volatile uint8_t _staMacAddress[6]; // MAC address of the station const char * _staRemoteApSsid; // SSID of remote AP const char * _staRemoteApPassword; // Password of remote AP volatile WIFI_ACTION_t _started; // Components that are started and running WIFI_CHANNEL_t _stationChannel; // Channel required for station, zero (0) use _channel bool _stationRunning; // True while station is starting or running uint32_t _timer; // Reconnection timer + bool _usingDefaultChannel; // Using default WiFi channel bool _verbose; // True causes more debug output to be displayed // Display components begin started or stopped @@ -1985,8 +1986,8 @@ class RTK_WIFI // Outputs: // Returns true if successful and false upon failure bool setWiFiProtocols(wifi_interface_t interface, - bool enableWiFiProtocols, - bool enableLongRangeProtocol); + bool enableWiFiProtocols, + bool enableLongRangeProtocol); // Handle the soft AP events // Inputs: @@ -2125,6 +2126,11 @@ class RTK_WIFI // Returns true if ESP-NOW is being started or is online bool espNowRunning(); + // Set the ESP-NOW channel + // Inputs: + // channel: New ESP-NOW channel number + void espNowSetChannel(WIFI_CHANNEL_t channel); + // Handle the WiFi event // Inputs: // event: Arduino ESP32 event number found on @@ -2133,16 +2139,10 @@ class RTK_WIFI // info: Additional data about the event void eventHandler(arduino_event_id_t event, arduino_event_info_t info); - // Get the mDNS host name + // Get the current WiFi channel // Outputs: - // Returns the mDNS host name as a pointer to a zero terminated string - // of characters - const char * hostNameGet(); - - // Set the mDNS host name - // Inputs - // Address of a zero terminated string containing the mDNS host name - void hostNameSet(const char * mDnsHostName); + // Returns the current WiFi channel number + WIFI_CHANNEL_t getChannel(); // Restart WiFi // Inputs: From 724efe541f59a286bf449ab504f51ec6f6af472e Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 27 Jan 2025 10:17:42 -1000 Subject: [PATCH 181/276] ESP-NOW: Merge state values and pair message data structure --- Firmware/RTK_Everywhere/ESPNOW.ino | 100 +++++++++++++++-------------- Firmware/RTK_Everywhere/settings.h | 27 -------- 2 files changed, 52 insertions(+), 75 deletions(-) diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index 42477e1b9..2642c1b07 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -12,13 +12,26 @@ const uint8_t peerBroadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +//**************************************** +// Types +//**************************************** + +// Create a struct for ESP NOW pairing +typedef struct _ESP_NOW_PAIR_MESSAGE +{ + uint8_t macAddress[6]; + bool encrypt; + uint8_t channel; + uint8_t crc; // Simple check - add MAC together and limit to 8 bit +} ESP_NOW_PAIR_MESSAGE; + //**************************************** // Locals //**************************************** bool espNowDebug; bool espNowDisplay; -ESP_NOW_STATE espNowState; +ESPNOWState espNowState; bool espNowVerbose; //********************************************************************* @@ -94,8 +107,8 @@ ESPNOWState espnowGetState() // A. Validate message CRC // B. If valid CRC // i. Save peer MAC address -// ii. espnowSetState(ESP_NOW_MAC_RECEIVED) -// 14. Else if ESP_NOW_MAC_RECEIVED state +// ii. espnowSetState(ESPNOW_MAC_RECEIVED) +// 14. Else if ESPNOW_MAC_RECEIVED state // A. If ESP-NOW is corrections source, correctionLastSeen(CORR_ESPNOW) // i. gnss->pushRawData // 15. Set espnowIncomingRTCM @@ -110,44 +123,44 @@ ESPNOWState espnowGetState() // 7. esp_wifi_get_protocol // 8. Turn off long range protocol if necessary, call esp_wifi_set_protocol // 9. Turn off ESP-NOW. call esp_now_deinit -// 10. Set ESP-NOW state, call espnowSetState(ESP_NOW_OFF) +// 10. Set ESP-NOW state, call espnowSetState(ESPNOW_OFF) // 11. Restart WiFi if necessary //---------------------------------------------------------------------- //********************************************************************* // Update the state of the ESP Now state machine // -// +---------------------+ -// | ESP_NOW_OFF | -// +---------------------+ +// +--------------------+ +// | ESPNOW_OFF | +// +--------------------+ // | | // | | No pairs listed // | V -// | +----------------------+ -// | | ESP_NOW_BROADCASTING | -// | +----------------------+ +// | +---------------------+ +// | | ESPNOW_BROADCASTING | +// | +---------------------+ // | | // | | // | V -// | +---------------------+ -// | | ESP_NOW_PAIRING | -// | +---------------------+ +// | +--------------------+ +// | | ESPNOW_PAIRING | +// | +--------------------+ // | | // | | // | V -// | +---------------------+ -// | | ESP_NOW_MAC_RECEIVED | -// | +---------------------+ +// | +--------------------+ +// | | ESPNOW_MAC_RECEIVED | +// | +--------------------+ // | | // | | // | V -// | +---------------------+ -// '->| ESP_NOW_PAIRED | -// +---------------------+ +// | +--------------------+ +// '->| ESPNOW_PAIRED | +// +--------------------+ // -// Send RTCM in either ESP_NOW_BROADCASTING or ESP_NOW_PAIRED state. -// Receive RTCM in ESP_NOW_BROADCASTING, ESP_NOW_MAC_RECEIVED and -// ESP_NOW_PAIRED states. +// Send RTCM in either ESPNOW_BROADCASTING or ESPNOW_PAIRED state. +// Receive RTCM in ESPNOW_BROADCASTING, ESPNOW_MAC_RECEIVED and +// ESPNOW_PAIRED states. //********************************************************************* //********************************************************************* @@ -164,7 +177,7 @@ void espNowRxHandler(const esp_now_recv_info *mac, uint8_t receivedMAC[6]; - if (espNowState == ESP_NOW_PAIRING) + if (espNowState == ESPNOW_PAIRING) { ESP_NOW_PAIR_MESSAGE pairMessage; if (len == sizeof(pairMessage)) // First error check @@ -179,7 +192,7 @@ void espNowRxHandler(const esp_now_recv_info *mac, if (tempCRC == pairMessage.crc) // 2nd error check { memcpy(&receivedMAC, pairMessage.macAddress, 6); - espNowSetState(ESP_NOW_MAC_RECEIVED); + espNowSetState(ESPNOW_MAC_RECEIVED); } // else Pair CRC failed } @@ -198,15 +211,15 @@ void espNowRxHandler(const esp_now_recv_info *mac, //********************************************************************* // Update the state of the ESP-NOW subsystem -void espNowSetState(ESP_NOW_STATE newState) +void espNowSetState(ESPNOWState newState) { const char * name[] = { - "ESP_NOW_OFF", - "ESP_NOW_BROADCASTING", - "ESP_NOW_PAIRING", - "ESP_NOW_MAC_RECEIVED", - "ESP_NOW_PAIRED", + "ESPNOW_OFF", + "ESPNOW_BROADCASTING", + "ESPNOW_PAIRING", + "ESPNOW_MAC_RECEIVED", + "ESPNOW_PAIRED", }; const int nameCount = sizeof(name) / sizeof(name[0]); const char * newName; @@ -217,7 +230,7 @@ void espNowSetState(ESP_NOW_STATE newState) if (espNowDebug == true) { // Get the old state name - if (espNowState < ESP_NOW_MAX) + if (espNowState < ESPNOW_MAX) oldName = name[espNowState]; else { @@ -226,7 +239,7 @@ void espNowSetState(ESP_NOW_STATE newState) } // Get the new state name - if (newState < ESP_NOW_MAX) + if (newState < ESPNOW_MAX) newName = name[newState]; else { @@ -276,10 +289,10 @@ bool espNowStart() } // 10. Add peers from settings - // i. Set ESP-NOW state, call espNowSetState(ESP_NOW_PAIRED) + // i. Set ESP-NOW state, call espNowSetState(ESPNOW_PAIRED) if (espNowDebug && espNowVerbose) systemPrintf("Calling espNowSetState\r\n"); - espNowSetState(ESP_NOW_PAIRED); + espNowSetState(ESPNOW_PAIRED); // ii. Loop through peers listed in settings, for each for (index = 0; index < ESPNOW_MAX_PEERS; index++) @@ -421,7 +434,7 @@ bool espNowStop() } // Stop the ESP-NOW state machine - espNowSetState(ESP_NOW_OFF); + espNowSetState(ESPNOW_OFF); // 9. Turn off ESP-NOW. call esp_now_deinit if (espNowDebug && espNowVerbose) @@ -499,20 +512,11 @@ void updateEspnow() } } -// Create a struct for ESP NOW pairing -typedef struct PairMessage -{ - uint8_t macAddress[6]; - bool encrypt; - uint8_t channel; - uint8_t crc; // Simple check - add MAC together and limit to 8 bit -} PairMessage; - // Callback when data is sent void espnowOnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { // systemPrint("Last Packet Send Status: "); - // if (status == ESP_NOW_SEND_SUCCESS) + // if (status == ESPNOW_SEND_SUCCESS) // systemPrintln("Delivery Success"); // else // systemPrintln("Delivery Fail"); @@ -523,9 +527,9 @@ void espnowOnDataReceived(const esp_now_recv_info *mac, const uint8_t *incomingD { if (espnowState == ESPNOW_PAIRING) { - if (len == sizeof(PairMessage)) // First error check + if (len == sizeof(ESP_NOW_PAIR_MESSAGE)) // First error check { - PairMessage pairMessage; + ESP_NOW_PAIR_MESSAGE pairMessage; memcpy(&pairMessage, incomingData, sizeof(pairMessage)); // Check CRC @@ -867,7 +871,7 @@ bool espnowIsPaired() esp_err_t espnowSendPairMessage(uint8_t *sendToMac) { // Assemble message to send - PairMessage pairMessage; + ESP_NOW_PAIR_MESSAGE pairMessage; // Get unit MAC address memcpy(pairMessage.macAddress, wifiMACAddress, 6); diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 1b3476dfc..3e464b7d8 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -2228,31 +2228,4 @@ class RTK_WIFI #endif // COMPILE_WIFI #endif // COMPILE_NETWORK - -//**************************************** -// ESP-NOW -//**************************************** - -#ifdef COMPILE_ESPNOW - -typedef enum -{ - ESP_NOW_OFF = 0, - ESP_NOW_BROADCASTING, - ESP_NOW_PAIRING, - ESP_NOW_MAC_RECEIVED, - ESP_NOW_PAIRED, - ESP_NOW_MAX -} ESP_NOW_STATE; - -// Create a struct for ESP NOW pairing -typedef struct _ESP_NOW_PAIR_MESSAGE -{ - uint8_t macAddress[6]; - bool encrypt; - uint8_t channel; - uint8_t crc; // Simple check - add MAC together and limit to 8 bit -} ESP_NOW_PAIR_MESSAGE; - -#endif // COMPILE_ESPNOW #endif // __SETTINGS_H__ From b63ffa79ba7dbd2bad43a3e1e0e55b0fa1e02c10 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 27 Jan 2025 11:00:19 -1000 Subject: [PATCH 182/276] WiFi: Merge RTK_WIFI specific changes --- Firmware/RTK_Everywhere/Network.ino | 11 ++ Firmware/RTK_Everywhere/WiFi.ino | 187 +++++++++++++++++++--------- 2 files changed, 141 insertions(+), 57 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 6797fb32c..cc33c1f41 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -113,6 +113,9 @@ NetIndex_t networkIndexTable[NETWORK_OFFLINE]; // Priority of the default network interface NetPriority_t networkPriority = NETWORK_OFFLINE; // Index into networkPriorityTable +// Interface event handlers set these flags, networkUpdate performs action +bool networkEventStop[NETWORK_OFFLINE]; + // The following entries have one bit per interface // Each bit represents an index into the networkInterfaceTable NetMask_t networkHasInternet_bm; // Track the online networks @@ -628,6 +631,14 @@ bool networkIsPresent(NetIndex_t index) return ((!networkInterfaceTable[index].present) || *(networkInterfaceTable[index].present)); } +//---------------------------------------- +// Interface stop event +//---------------------------------------- +void networkInterfaceEventStop(NetIndex_t index) +{ + networkEventStop[index] = true; +} + //---------------------------------------- // Mark network offline //---------------------------------------- diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index cb2427436..e3e5c639f 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -477,15 +477,16 @@ void menuWiFi() systemPrintf("Enter SSID network %d: ", arraySlot + 1); getUserInputString(settings.wifiNetworks[arraySlot].ssid, sizeof(settings.wifiNetworks[arraySlot].ssid)); - restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi } else { systemPrintf("Enter Password for %s: ", settings.wifiNetworks[arraySlot].ssid); getUserInputString(settings.wifiNetworks[arraySlot].password, sizeof(settings.wifiNetworks[arraySlot].password)); - restartWiFi = true; // If we are modifying the SSID table, force restart of WiFi } + + // If we are modifying the SSID table, force restart of WiFi + restartWiFi = true; } else if (incoming == 'a') { @@ -872,12 +873,12 @@ RTK_WIFI::RTK_WIFI(bool verbose) _apMacAddress{0, 0, 0, 0, 0, 0}, _apSubnetMask{IPAddress("255.255.255.0")}, _channel{0}, _espNowChannel{0}, _espNowRunning{false}, - _hostName{nullptr}, _scanRunning{false}, _softApRunning{false}, + _scanRunning{false}, _softApRunning{false}, _staIpAddress{IPAddress((uint32_t)0)}, _staIpType{0}, _staMacAddress{0, 0, 0, 0, 0, 0}, _staRemoteApSsid{nullptr}, _staRemoteApPassword{nullptr}, _started{false}, _stationChannel{0}, - _timer{0}, _verbose{verbose} + _timer{0}, _usingDefaultChannel{true}, _verbose{verbose} { } @@ -993,7 +994,10 @@ bool RTK_WIFI::enable(bool enableESPNow, bool enableSoftAP, bool enableStation) { // Verify that at least one WiFi access point is in the list if (MAX_WIFI_NETWORKS == 0) + { systemPrintf("ERROR: No entries in wiFiSsidPassword\r\n"); + displayNoSSIDs(2000); + } else { // Verify that at least one SSID is set @@ -1003,7 +1007,10 @@ bool RTK_WIFI::enable(bool enableESPNow, bool enableSoftAP, bool enableStation) break; } if (authIndex >= MAX_WIFI_NETWORKS) + { systemPrintf("ERROR: No valid SSID in settings\r\n"); + displayNoSSIDs(2000); + } else { // Start the WiFi station @@ -1039,6 +1046,15 @@ bool RTK_WIFI::espNowRunning() return _espNowRunning; } +//********************************************************************* +// Set the ESP-NOW channel +// Inputs: +// channel: New ESP-NOW channel number +void RTK_WIFI::espNowSetChannel(WIFI_CHANNEL_t channel) +{ + _espNowChannel = channel; +} + //********************************************************************* // Handle the WiFi event void RTK_WIFI::eventHandler(arduino_event_id_t event, arduino_event_info_t info) @@ -1099,17 +1115,12 @@ void RTK_WIFI::eventHandler(arduino_event_id_t event, arduino_event_info_t info) } //********************************************************************* -// Get the mDNS host name -const char * RTK_WIFI::hostNameGet() -{ - return _hostName; -} - -//********************************************************************* -// Get the mDNS host name -void RTK_WIFI::hostNameSet(const char * mDnsHostName) +// Get the current WiFi channel +// Outputs: +// Returns the current WiFi channel number +WIFI_CHANNEL_t RTK_WIFI::getChannel() { - _hostName = mDnsHostName; + return _channel; } //********************************************************************* @@ -1584,6 +1595,9 @@ bool RTK_WIFI::stationConnectAP() _staRemoteApSsid, _channel, (_staAuthType < WIFI_AUTH_MAX) ? wifiAuthorizationName[_staAuthType] : "Unknown"); + + // Don't delay the next WiFi start request + wifiResetTimeout(); } while (0); return connected; } @@ -1628,14 +1642,48 @@ void RTK_WIFI::stationEventHandler(arduino_event_id_t event, arduino_event_info_ { WIFI_CHANNEL_t channel; IPAddress ipAddress; + char ssid[sizeof(info.wifi_sta_connected.ssid) + 1]; bool success; int type; + // Take the network offline if necessary + if (networkInterfaceHasInternet(NETWORK_WIFI) && (event != ARDUINO_EVENT_WIFI_STA_GOT_IP) && + (event != ARDUINO_EVENT_WIFI_STA_GOT_IP6)) + { + // Stop WiFi to allow it to restart + networkInterfaceEventStop(NETWORK_WIFI); + } + + //------------------------------ + // WiFi Status Values: + // WL_CONNECTED: assigned when connected to a WiFi network + // WL_CONNECTION_LOST: assigned when the connection is lost + // WL_CONNECT_FAILED: assigned when the connection fails for all the attempts + // WL_DISCONNECTED: assigned when disconnected from a network + // WL_IDLE_STATUS: it is a temporary status assigned when WiFi.begin() is called and + // remains active until the number of attempts expires (resulting in + // WL_CONNECT_FAILED) or a connection is established (resulting in + // WL_CONNECTED) + // WL_NO_SHIELD: assigned when no WiFi shield is present + // WL_NO_SSID_AVAIL: assigned when no SSID are available + // WL_SCAN_COMPLETED: assigned when the scan networks is completed + // + // WiFi Station State Machine + // + // .--------+<----------+<-----------+<-------------+<----------+<----------+<------------. + // v | | | | | | | + // STOP --> READY --> STA_START --> SCAN_DONE --> CONNECTED --> GOT_IP --> LOST_IP --> DISCONNECTED + // ^ ^ ^ | | + // | | '-----------' | + // OFF -------' '-------------------------------------' + // // Notify the upper layers that WiFi is no longer available + //------------------------------ + switch (event) { case ARDUINO_EVENT_WIFI_STA_START: - WiFi.STA.macAddress(_staMacAddress); + WiFi.STA.macAddress((uint8_t *)_staMacAddress); if (settings.debugWifiState) systemPrintf("WiFi Event: Station start: MAC: %02x:%02x:%02x:%02x:%02x:%02x\r\n", _staMacAddress[0], _staMacAddress[1], _staMacAddress[2], @@ -1652,7 +1700,7 @@ void RTK_WIFI::stationEventHandler(arduino_event_id_t event, arduino_event_info_ if (event == ARDUINO_EVENT_WIFI_STA_DISCONNECTED) { if (settings.debugWifiState && _verbose && !_timer) - systemPrintf("Reconnection timer started\r\n"); + systemPrintf("WiFi: Reconnection timer started\r\n"); _timer = millis(); if (!_timer) _timer = 1; @@ -1661,7 +1709,7 @@ void RTK_WIFI::stationEventHandler(arduino_event_id_t event, arduino_event_info_ { // Stop the reconnection timer if (settings.debugWifiState && _verbose && _timer) - systemPrintf("Reconnection timer stopped\r\n"); + systemPrintf("WiFi: Reconnection timer stopped\r\n"); _timer = 0; } @@ -1674,7 +1722,7 @@ void RTK_WIFI::stationEventHandler(arduino_event_id_t event, arduino_event_info_ case ARDUINO_EVENT_WIFI_STA_AUTHMODE_CHANGE: // The WiFi station is no longer connected to the remote AP if (settings.debugWifiState && _staConnected) - systemPrintf("WiFi station disconnected from %s\r\n", + systemPrintf("WiFi: Station disconnected from %s\r\n", _staRemoteApSsid); _staConnected = false; @@ -1709,31 +1757,31 @@ void RTK_WIFI::stationEventHandler(arduino_event_id_t event, arduino_event_info_ break; //------------------------------ - // WiFi Station State Machine - // - // .--------+<----------+<-----------+<-------------+<----------+<----------+<------------. - // v | | | | | | | - // STOP --> READY --> STA_START --> SCAN_DONE --> CONNECTED --> GOT_IP --> LOST_IP --> DISCONNECTED - // ^ ^ ^ | | - // | | '-----------' | - // OFF -------' '-------------------------------------' - // - // Handle the WiFi station events + // Bring the WiFi station back online //------------------------------ case ARDUINO_EVENT_WIFI_STA_CONNECTED: _staConnected = true; + if (settings.debugWifiState) + { + memcpy(ssid, info.wifi_sta_connected.ssid, info.wifi_sta_connected.ssid_len); + ssid[info.wifi_sta_connected.ssid_len] = 0; + systemPrintf("WiFi: STA connected to %s\r\n", ssid); + } + break; + break; case ARDUINO_EVENT_WIFI_STA_GOT_IP: case ARDUINO_EVENT_WIFI_STA_GOT_IP6: - ipAddress = WiFi.STA.localIP(); + _staIpAddress = WiFi.STA.localIP(); type = (event == ARDUINO_EVENT_WIFI_STA_GOT_IP) ? '4' : '6'; // Display the IP address if (settings.debugWifiState) - systemPrintf("WiFi Event: Got IPv%c address %s\r\n", - type, ipAddress.toString().c_str()); + systemPrintf("WiFi: Got IPv%c address %s\r\n", + type, _staIpAddress.toString().c_str()); + networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); break; } // End of switch } @@ -1959,6 +2007,7 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) { int authIndex; WIFI_CHANNEL_t channel; + bool defaultChannel; WIFI_ACTION_t delta; bool enabled; WIFI_ACTION_t mask; @@ -1985,7 +2034,7 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) // Select the channel // // The priority order for the channel is: - // 1. Active channel + // 1. Active channel (not using default channel) // 2. _stationChannel // 3. Remote AP channel determined by scan // 4. _espNowChannel @@ -1994,8 +2043,10 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) //**************************************** // Determine if there is an active channel + defaultChannel = _usingDefaultChannel; + _usingDefaultChannel = false; if (((_started & ~stopping) & (WIFI_AP_ONLINE | WIFI_EN_ESP_NOW_ONLINE | WIFI_STA_ONLINE)) - && _channel) + && _channel && !defaultChannel) { // Continue to use the active channel channel = _channel; @@ -2017,6 +2068,14 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) channel = 0; if (settings.debugWifiState && _verbose) systemPrintf("channel: Determine by remote AP scan\r\n"); + + // Restart ESP-NOW if necessary + if (espNowRunning()) + stopping |= WIFI_START_ESP_NOW; + + // Restart soft AP if necessary + if (softApRunning()) + stopping |= WIFI_START_SOFT_AP; } // Determine if the ESP-NOW channel was specified @@ -2039,6 +2098,7 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) else { channel = WIFI_DEFAULT_CHANNEL; + _usingDefaultChannel = true; if (settings.debugWifiState && _verbose) systemPrintf("channel: %d, default channel\r\n", channel); } @@ -2053,16 +2113,24 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) // not running or being started, let mDNS start for the soft AP. // Determine if mDNS is being used for WiFi station - if (starting & WIFI_STA_START_MDNS) + if (strlen(&settings.mdnsHostName[0])) { - // Don't start mDNS for soft AP - starting &= ~WIFI_AP_START_MDNS; + if (starting & WIFI_STA_START_MDNS) + { + // Don't start mDNS for soft AP + starting &= ~WIFI_AP_START_MDNS; - // Stop it if it is being used for soft AP - if (_started & WIFI_AP_START_MDNS) - stopping |= WIFI_AP_START_MDNS; + // Stop it if it is being used for soft AP + if (_started & WIFI_AP_START_MDNS) + stopping |= WIFI_AP_START_MDNS; + } } + // Don't set host name or start mDNS if the host name is not specified + else + starting &= ~(WIFI_AP_SET_HOST_NAME | WIFI_AP_START_MDNS + | WIFI_STA_SET_HOST_NAME | WIFI_STA_START_MDNS); + //**************************************** // Determine if DNS needs to start //**************************************** @@ -2359,7 +2427,10 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) // Reset the channel if all components are stopped if ((softApOnline() == false) && (stationOnline() == false)) + { _channel = 0; + _usingDefaultChannel = true; + } //**************************************** // Delay to allow mDNS to shutdown and restart properly @@ -2506,13 +2577,10 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) { // Display the host name if (settings.debugWifiState && _verbose) - systemPrintf("_hostName: %p%s%s%s\r\n", _hostName, - _hostName ? " (" : "", - _hostName ? _hostName : "", - _hostName ? ")" : ""); + systemPrintf("Host name: %s\r\n", &settings.mdnsHostName[0]); // Set the host name - if (_hostName && (!softApSetHostName(_hostName))) + if (!softApSetHostName(&settings.mdnsHostName[0])) break; _started = _started | WIFI_AP_SET_HOST_NAME; } @@ -2530,7 +2598,7 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) if (settings.debugWifiState) { systemPrintf("mDNS started on soft AP as %s.local (%s)\r\n", - _hostName, + &settings.mdnsHostName[0], _apIpAddress.toString().c_str()); } _started = _started | WIFI_AP_START_MDNS; @@ -2559,11 +2627,11 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) // Display the soft AP status String mdnsName(""); if (_started & WIFI_AP_START_MDNS) - mdnsName = String(", local.") + String(_hostName); + mdnsName = String(", local.") + String(&settings.mdnsHostName[0]); systemPrintf("WiFi: Soft AP online, SSID: %s (%s%s), Password: %s\r\n", wifiSoftApSsid, _apIpAddress.toString().c_str(), - mdnsName, + mdnsName.c_str(), wifiSoftApPassword); } @@ -2576,13 +2644,10 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) { // Display the host name if (settings.debugWifiState && _verbose) - systemPrintf("_hostName: %p%s%s%s\r\n", _hostName, - _hostName ? " (" : "", - _hostName ? _hostName : "", - _hostName ? ")" : ""); + systemPrintf("Host name: %s\r\n", &settings.mdnsHostName[0]); // Set the host name - if (_hostName && (!stationHostName(_hostName))) + if (!stationHostName(&settings.mdnsHostName[0])) break; _started = _started | WIFI_STA_SET_HOST_NAME; } @@ -2626,9 +2691,12 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) break; } + // Wait for the station MAC address to be set + while (!_staMacAddress[0]) + delay(1); + // Save the IP address _staHasIp = true; - _staIpAddress = WiFi.STA.localIP(); _staIpType = (_staIpAddress.type() == IPv4) ? '4' : '6'; } @@ -2643,7 +2711,7 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) { if (settings.debugWifiState) systemPrintf("mDNS started on WiFi station as %s.local (%s)\r\n", - _hostName, + &settings.mdnsHostName[0], _staIpAddress.toString().c_str()); _started = _started | WIFI_STA_START_MDNS; } @@ -2654,11 +2722,11 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) { _started = _started | WIFI_STA_ONLINE; String mdnsName(""); - if (_hostName && (_started & WIFI_STA_START_MDNS)) - mdnsName = String(", local.") + String(_hostName); + if (_started & WIFI_STA_START_MDNS) + mdnsName = String(", local.") + String(&settings.mdnsHostName[0]); systemPrintf("WiFi: Station online (%s: %s%s)\r\n", _staRemoteApSsid, _staIpAddress.toString().c_str(), - mdnsName); + mdnsName.c_str()); } //**************************************** @@ -2752,6 +2820,11 @@ bool RTK_WIFI::stopStart(WIFI_ACTION_t stopping, WIFI_ACTION_t starting) // Mark ESP-NOW online if (starting & WIFI_EN_ESP_NOW_ONLINE) { + // Wait for the station MAC address to be set + while (!_staMacAddress[0]) + delay(1); + + // Display the ESP-NOW MAC address _started = _started | WIFI_EN_ESP_NOW_ONLINE; systemPrintf("WiFi: ESP-NOW online (%02x:%02x:%02x:%02x:%02x:%02x, channel: %d)\r\n", _staMacAddress[0], _staMacAddress[1], _staMacAddress[2], From da21d67bdc5d6e814e146f9aadf29b16df5cc88a Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 27 Jan 2025 11:36:00 -1000 Subject: [PATCH 183/276] ESP-NOW: Rename espnowState to espNowState --- Firmware/RTK_Everywhere/ESPNOW.ino | 32 +++++++++++++++--------------- Firmware/RTK_Everywhere/settings.h | 1 - 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index 2642c1b07..e58f5824e 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -70,7 +70,7 @@ esp_err_t espNowAddPeer(const uint8_t * peerMac) // Get the current ESP-NOW state ESPNOWState espnowGetState() { - return espnowState; + return espNowState; } //---------------------------------------------------------------------- @@ -480,15 +480,15 @@ void updateEspnow() { if (settings.enableEspNow == true) { - if (espnowState == ESPNOW_PAIRED || espnowState == ESPNOW_BROADCASTING) + if (espNowState == ESPNOW_PAIRED || espNowState == ESPNOW_BROADCASTING) { // If it's been longer than a few ms since we last added a byte to the buffer // then we've reached the end of the RTCM stream. Send partial buffer. if (espnowOutgoingSpot > 0 && (millis() - espnowLastAdd) > 50) { - if (espnowState == ESPNOW_PAIRED) + if (espNowState == ESPNOW_PAIRED) esp_now_send(0, (uint8_t *)&espnowOutgoing, espnowOutgoingSpot); // Send partial packet to all peers - else // if (espnowState == ESPNOW_BROADCASTING) + else // if (espNowState == ESPNOW_BROADCASTING) { uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; esp_now_send(broadcastMac, (uint8_t *)&espnowOutgoing, @@ -525,7 +525,7 @@ void espnowOnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) // Callback when data is received void espnowOnDataReceived(const esp_now_recv_info *mac, const uint8_t *incomingData, int len) { - if (espnowState == ESPNOW_PAIRING) + if (espNowState == ESPNOW_PAIRING) { if (len == sizeof(ESP_NOW_PAIR_MESSAGE)) // First error check { @@ -605,7 +605,7 @@ void espnowStart() if (response != ESP_OK) systemPrintf("espnowStart: Failed to get protocols: %s\r\n", esp_err_to_name(response)); - if ((WIFI_IS_RUNNING() == false) && espnowState == ESPNOW_OFF) + if ((WIFI_IS_RUNNING() == false) && espNowState == ESPNOW_OFF) { // Radio is off, turn it on if (protocols != (WIFI_PROTOCOL_LR)) @@ -626,7 +626,7 @@ void espnowStart() } } // If WiFi is on but ESP NOW is off, then enable LR protocol - else if (WIFI_IS_RUNNING() && espnowState == ESPNOW_OFF) + else if (WIFI_IS_RUNNING() && espNowState == ESPNOW_OFF) { // Enable WiFi + ESP-Now // Enable long range, PHY rate of ESP32 will be 512Kbps or 256Kbps @@ -743,7 +743,7 @@ void espnowStart() // If WiFi is off, stop the radio entirely void espnowStop() { - if (espnowState == ESPNOW_OFF) + if (espNowState == ESPNOW_OFF) return; // Turn off promiscuous WiFi mode @@ -831,7 +831,7 @@ void espnowBeginPairing() // Regularly call during pairing to see if we've received a Pairing message bool espnowIsPaired() { - if (espnowState == ESPNOW_MAC_RECEIVED) + if (espNowState == ESPNOW_MAC_RECEIVED) { // Remove broadcast peer uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; @@ -928,13 +928,13 @@ esp_err_t espnowRemovePeer(uint8_t *peerMac) // Update the state of the ESP Now state machine void espnowSetState(ESPNOWState newState) { - if (espnowState == newState && settings.debugEspNow == true) + if (espNowState == newState && settings.debugEspNow == true) systemPrint("*"); - espnowState = newState; + espNowState = newState; if (settings.debugEspNow == true) { - systemPrint("espnowState: "); + systemPrint("espNowState: "); switch (newState) { case ESPNOW_OFF: @@ -964,7 +964,7 @@ void espnowProcessRTCM(byte incoming) // If we are paired, // Or if the radio is broadcasting // Then add bytes to the outgoing buffer - if (espnowState == ESPNOW_PAIRED || espnowState == ESPNOW_BROADCASTING) + if (espNowState == ESPNOW_PAIRED || espNowState == ESPNOW_BROADCASTING) { // Move this byte into ESP NOW to send buffer espnowOutgoing[espnowOutgoingSpot++] = incoming; @@ -976,9 +976,9 @@ void espnowProcessRTCM(byte incoming) { espnowOutgoingSpot = 0; // Wrap - if (espnowState == ESPNOW_PAIRED) + if (espNowState == ESPNOW_PAIRED) esp_now_send(0, (uint8_t *)&espnowOutgoing, sizeof(espnowOutgoing)); // Send packet to all peers - else // if (espnowState == ESPNOW_BROADCASTING) + else // if (espNowState == ESPNOW_BROADCASTING) { uint8_t broadcastMac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; esp_now_send(broadcastMac, (uint8_t *)&espnowOutgoing, @@ -1041,7 +1041,7 @@ void espnowStaticPairing() // Returns the current channel being used by WiFi uint8_t espnowGetChannel() { - if (espnowState == ESPNOW_OFF) + if (espNowState == ESPNOW_OFF) return 0; bool originalPromiscuousMode = false; diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 3e464b7d8..b930a9615 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -364,7 +364,6 @@ typedef enum ESPNOW_PAIRED, ESPNOW_MAX } ESPNOWState; -volatile ESPNOWState espnowState = ESPNOW_OFF; const uint8_t ESPNOW_MAX_PEERS = 5; // Maximum of 5 rovers From 06bbecd6b246149d5db49a2d936aac116e1186b6 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 27 Jan 2025 08:20:13 -1000 Subject: [PATCH 184/276] Rename networkInterfaceInternetConnectionLost to *EventInternetLost --- Firmware/RTK_Everywhere/Cellular.ino | 2 +- Firmware/RTK_Everywhere/Ethernet.ino | 2 +- Firmware/RTK_Everywhere/Network.ino | 2 +- Firmware/RTK_Everywhere/WiFi.ino | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/Cellular.ino b/Firmware/RTK_Everywhere/Cellular.ino index 2cbd4cc81..ebcc7eca5 100644 --- a/Firmware/RTK_Everywhere/Cellular.ino +++ b/Firmware/RTK_Everywhere/Cellular.ino @@ -87,7 +87,7 @@ void cellularEvent(arduino_event_id_t event) if (networkInterfaceHasInternet(NETWORK_CELLULAR) && (event != ARDUINO_EVENT_ETH_GOT_IP) && (event != ARDUINO_EVENT_ETH_GOT_IP6) && (event != ARDUINO_EVENT_PPP_CONNECTED)) { - networkInterfaceInternetConnectionLost(NETWORK_CELLULAR); + networkInterfaceEventInternetLost(NETWORK_CELLULAR); } // Cellular State Machine diff --git a/Firmware/RTK_Everywhere/Ethernet.ino b/Firmware/RTK_Everywhere/Ethernet.ino index 595c4b57e..d50dd9d2f 100644 --- a/Firmware/RTK_Everywhere/Ethernet.ino +++ b/Firmware/RTK_Everywhere/Ethernet.ino @@ -202,7 +202,7 @@ void ethernetEvent(arduino_event_id_t event, arduino_event_info_t info) // Take the network offline if necessary if (networkInterfaceHasInternet(NETWORK_ETHERNET) && (event != ARDUINO_EVENT_ETH_GOT_IP)) { - networkInterfaceInternetConnectionLost((NetIndex_t)NETWORK_ETHERNET); + networkInterfaceEventInternetLost((NetIndex_t)NETWORK_ETHERNET); } } diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index cc33c1f41..c53cae112 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -642,7 +642,7 @@ void networkInterfaceEventStop(NetIndex_t index) //---------------------------------------- // Mark network offline //---------------------------------------- -void networkInterfaceInternetConnectionLost(NetIndex_t index) +void networkInterfaceEventInternetLost(NetIndex_t index) { NetMask_t bitMask; NetPriority_t previousPriority; diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index e3e5c639f..e940aa0de 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -842,7 +842,7 @@ void wifiStop() } // Take the network offline - networkInterfaceInternetConnectionLost(NETWORK_WIFI); + networkInterfaceEventInternetLost(NETWORK_WIFI); if (wifiMulti != nullptr) wifiMulti = nullptr; From 1233c51cae8dea19fa32eaa6b208e364df093ae2 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 27 Jan 2025 08:31:30 -1000 Subject: [PATCH 185/276] Rename *InternetConnectionAvailable to *EventInternetAvailable --- Firmware/RTK_Everywhere/Cellular.ino | 2 +- Firmware/RTK_Everywhere/Ethernet.ino | 2 +- Firmware/RTK_Everywhere/Network.ino | 2 +- Firmware/RTK_Everywhere/WiFi.ino | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Firmware/RTK_Everywhere/Cellular.ino b/Firmware/RTK_Everywhere/Cellular.ino index ebcc7eca5..395288606 100644 --- a/Firmware/RTK_Everywhere/Cellular.ino +++ b/Firmware/RTK_Everywhere/Cellular.ino @@ -108,7 +108,7 @@ void cellularEvent(arduino_event_id_t event) case ARDUINO_EVENT_PPP_CONNECTED: systemPrintln("Cellular Connected"); - networkInterfaceInternetConnectionAvailable(NETWORK_CELLULAR); + networkInterfaceEventInternetAvailable(NETWORK_CELLULAR); break; case ARDUINO_EVENT_PPP_DISCONNECTED: diff --git a/Firmware/RTK_Everywhere/Ethernet.ino b/Firmware/RTK_Everywhere/Ethernet.ino index d50dd9d2f..5e17a081b 100644 --- a/Firmware/RTK_Everywhere/Ethernet.ino +++ b/Firmware/RTK_Everywhere/Ethernet.ino @@ -174,7 +174,7 @@ void ethernetEvent(arduino_event_id_t event, arduino_event_info_t info) if (settings.enablePrintEthernetDiag && (!inMainMenu)) systemPrintf("ETH Got IP: '%s'\r\n", ETH.localIP().toString().c_str()); - networkInterfaceInternetConnectionAvailable((NetIndex_t)NETWORK_ETHERNET); + networkInterfaceEventInternetAvailable((NetIndex_t)NETWORK_ETHERNET); if (settings.ethernetDHCP) paintEthernetConnected(); diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index c53cae112..3f5a4d6a0 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -711,7 +711,7 @@ void networkInterfaceEventInternetLost(NetIndex_t index) //---------------------------------------- // Mark network online //---------------------------------------- -void networkInterfaceInternetConnectionAvailable(NetIndex_t index) +void networkInterfaceEventInternetAvailable(NetIndex_t index) { NetMask_t bitMask; NetIndex_t previousIndex; diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index e940aa0de..4853a7498 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -647,7 +647,7 @@ void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) systemPrint("WiFi STA Got IPv4: "); systemPrintln(ipAddress); } - networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); + networkInterfaceEventInternetAvailable(NETWORK_WIFI); break; case ARDUINO_EVENT_WIFI_STA_GOT_IP6: @@ -657,7 +657,7 @@ void wifiEvent(arduino_event_id_t event, arduino_event_info_t info) systemPrint("WiFi STA Got IPv6: "); systemPrintln(ipAddress); } - networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); + networkInterfaceEventInternetAvailable(NETWORK_WIFI); break; case ARDUINO_EVENT_WIFI_STA_LOST_IP: @@ -1781,7 +1781,7 @@ void RTK_WIFI::stationEventHandler(arduino_event_id_t event, arduino_event_info_ if (settings.debugWifiState) systemPrintf("WiFi: Got IPv%c address %s\r\n", type, _staIpAddress.toString().c_str()); - networkInterfaceInternetConnectionAvailable(NETWORK_WIFI); + networkInterfaceEventInternetAvailable(NETWORK_WIFI); break; } // End of switch } From b6103cb9decb751e81aca7f5b85ff54ea879a7eb Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 28 Jan 2025 16:40:41 +0000 Subject: [PATCH 186/276] Mosaic logging improvements Remove redundant gnss-> pointers Remove redundant comments Correct getLoggingType() - bad use of loggingType Perform a soft reset when SD card is inserted or removed (probably needs a "displayCardChange" on the OLED) --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 68 +++++++++++++++++++------ 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index f349c0abf..606de3422 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -266,11 +266,11 @@ void GNSS_MOSAIC::begin() } // Set COM2 (Radio) and COM3 (Data) baud rates - gnss->setRadioBaudRate(settings.radioPortBaud); - gnss->setDataBaudRate(settings.dataPortBaud); + setRadioBaudRate(settings.radioPortBaud); + setDataBaudRate(settings.dataPortBaud); // Set COM2 (Radio) protocol(s) - gnss->setCorrRadioExtPort(settings.enableExtCorrRadio, true); // Force the setting + setCorrRadioExtPort(settings.enableExtCorrRadio, true); // Force the setting updateSD(); // Check card size and free space @@ -454,8 +454,6 @@ bool GNSS_MOSAIC::configureLogging() bool response = true; String setting; - // TODO: use sdCardPresent() here? Except the mosaic seems pretty good at figuring out if the microSD is present... - // Configure logging if ((settings.enableLogging == true) || (settings.enableLoggingRINEX == true)) { @@ -480,8 +478,6 @@ bool GNSS_MOSAIC::configureLogging() response &= sendWithResponse(setting, "RINEXLogging"); } - // TODO: use sdCardPresent() here? Except the mosaic seems pretty good at figuring out if the microSD is present... - if (settings.enableExternalHardwareEventLogging) { setting = String("sso,Stream" + String(MOSAIC_SBF_EXTEVENT_STREAM) + @@ -819,9 +815,6 @@ bool GNSS_MOSAIC::enableNMEA() response &= sendWithResponse(setting, "NMEAOutput"); } - // TODO: use sdCardPresent() here? Except the mosaic seems pretty good at figuring out if the microSD is - // present... - if (settings.enableLogging) { setting = @@ -1267,10 +1260,10 @@ uint8_t GNSS_MOSAIC::getLoggingType() { if (checkNMEARates()) { - loggingType = LOGGING_STANDARD; + logType = LOGGING_STANDARD; if (checkPPPRates()) - loggingType = LOGGING_PPP; + logType = LOGGING_PPP; } } @@ -1652,7 +1645,7 @@ void GNSS_MOSAIC::menuConstellations() } // Apply current settings to module - gnss->setConstellations(); + setConstellations(); clearBuffer(); // Empty buffer of any newline chars } @@ -1814,7 +1807,7 @@ void GNSS_MOSAIC::menuMessages() systemPrintln(); systemPrintln("Menu: GNSS Messages"); - systemPrintf("Active messages: %d\r\n", gnss->getActiveMessageCount()); + systemPrintf("Active messages: %d\r\n", getActiveMessageCount()); systemPrintln("1) Set NMEA Messages"); systemPrintln("2) Set Rover RTCM Messages"); @@ -2474,6 +2467,12 @@ bool GNSS_MOSAIC::surveyInStart() //---------------------------------------- void GNSS_MOSAIC::update() { + // The mosaic-X5 supports microSD logging. But the microSD is connected directly to the X5, not the ESP32. + // present.microSd is false, but present.microSdCardDetectLow is true. + // If the microSD card is not inserted at power-on, the X5 does not recognise it if it is inserted later. + // The only way to get the X5 to recognise the card seems to be to perform a soft reset. + // Where should we perform the soft reset? updateSD seems the best place... + // Update the SD card size, free space and logIncreasing static unsigned long sdCardSizeLastCheck = 0; const unsigned long sdCardSizeCheckInterval = 5000; // Matches the interval in logUpdate @@ -2482,6 +2481,7 @@ void GNSS_MOSAIC::update() if (millis() > (sdCardSizeLastCheck + sdCardSizeCheckInterval)) { updateSD(); + if (previousFreeSpace == 0) previousFreeSpace = sdFreeSpace; if (sdFreeSpace < previousFreeSpace) @@ -2512,7 +2512,45 @@ void GNSS_MOSAIC::update() //---------------------------------------- bool GNSS_MOSAIC::updateSD() { - // TODO: use sdCardPresent() here? Except the mosaic seems pretty good at figuring out if the microSD is present... + // See comments in update() above + // updateSD() is probably the best place to check if an SD card has been inserted / removed + static bool previousCardPresent = sdCardPresent(); // This only gets called once + + // Check if card has been inserted / removed + // In both cases, perform a soft reset + // The X5 is not good at recognizing if a card is inserted after power-on, or was present but has been removed + if (previousCardPresent != sdCardPresent()) + { + previousCardPresent = sdCardPresent(); + + systemPrint("microSD card has been "); + systemPrint(previousCardPresent ? "inserted" : "removed"); + systemPrintln(". Performing a soft reset..."); + + sendWithResponse("erst,soft,none\n\r", "ResetReceiver"); + + // Allow many retries + int retries = 0; + int retryLimit = 20; + + // Set COM4 to: CMD input (only), SBF output (only) + while (!sendWithResponse("sdio,COM4,CMD,SBF\n\r", "DataInOut")) + { + if (retries == retryLimit) + break; + retries++; + sendWithResponse("SSSSSSSSSSSSSSSSSSSS\n\r", "COM4>"); // Send escape sequence + } + + if (retries == retryLimit) + { + systemPrintln("Soft reset failed!"); + return false; + } + } + + if (!previousCardPresent) // If the card is not present, skip the list disk info + return false; char diskInfo[200]; bool response = From 6b2e0d8534d6dff287da188bdbbc9d14befb2c61 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 27 Jan 2025 19:10:53 -1000 Subject: [PATCH 187/276] ESP-NOW: Replace espnowStart with ESPNOW_START macro --- Firmware/RTK_Everywhere/Developer.ino | 2 +- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 1 + Firmware/RTK_Everywhere/States.ino | 6 +++--- Firmware/RTK_Everywhere/menuMain.ino | 10 +++++----- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 2b154260c..79e602b0f 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -177,7 +177,6 @@ void webServerUpdate() {} #ifndef COMPILE_ESPNOW -bool espNowStart() {return false;} bool espNowStop() {return false;} bool espnowGetState() {return ESPNOW_OFF;} @@ -187,6 +186,7 @@ esp_err_t espnowRemovePeer(uint8_t *peerMac) {return ESP_OK;} esp_err_t espnowSendPairMessage(uint8_t *sendToMac) {return ESP_OK;} bool espnowSetChannel(uint8_t channelNumber) {return false;} void espnowStart() {} +#define ESPNOW_START() false void espnowStaticPairing() {} void espnowStop() {} void updateEspnow() {} diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 55501ec35..e8b7c7992 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -614,6 +614,7 @@ uint8_t receivedMAC[6]; // Holds the broadcast MAC during pairing unsigned long lastEspnowRssiUpdate; +#define ESPNOW_START() espnowStart() #endif // COMPILE_ESPNOW int espnowRSSI; diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 16714afba..2ecdc6096 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -113,7 +113,7 @@ void stateUpdate() setMuxport(settings.dataPortChannel); // Return mux to original channel bluetoothStart(); // Turn on Bluetooth with 'Rover' name - espnowStart(); // Start internal radio if enabled, otherwise disable + ESPNOW_START(); // Start internal radio if enabled, otherwise disable webServerStop(); // Stop the web config server baseCasterDisableOverride(); // Disable casting overrides @@ -333,7 +333,7 @@ void stateUpdate() // Start the NTRIP server if requested RTK_MODE(RTK_MODE_BASE_FIXED); - espnowStart(); // Start internal radio if enabled, otherwise disable + ESPNOW_START(); // Start internal radio if enabled, otherwise disable rtcmPacketsSent = 0; // Reset any previous number changeState(STATE_BASE_TEMP_TRANSMITTING); @@ -400,7 +400,7 @@ void stateUpdate() { baseStatusLedOn(); // Turn on the base/status LED - espnowStart(); // Start internal radio if enabled, otherwise disable + ESPNOW_START(); // Start internal radio if enabled, otherwise disable changeState(STATE_BASE_FIXED_TRANSMITTING); } diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index b5b23d91f..5dde939ba 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -605,7 +605,7 @@ void menuRadio() // Start ESP-NOW so that getChannel runs correctly if (settings.enableEspNow == true) - espnowStart(); + ESPNOW_START(); else espnowStop(); } @@ -644,7 +644,7 @@ void menuRadio() else if (settings.enableEspNow == true && incoming == 5 && settings.debugEspNow == true) { if (espnowGetState() == ESPNOW_OFF) - espnowStart(); + ESPNOW_START(); uint8_t peer1[] = {0xB8, 0xD6, 0x1A, 0x0D, 0x8F, 0x9C}; // Random MAC #ifdef COMPILE_ESPNOW @@ -668,7 +668,7 @@ void menuRadio() else if (settings.enableEspNow == true && incoming == 6 && settings.debugEspNow == true) { if (espnowGetState() == ESPNOW_OFF) - espnowStart(); + ESPNOW_START(); uint8_t espnowData[] = "This is the long string to test how quickly we can send one string to the other unit. I am going to " @@ -681,7 +681,7 @@ void menuRadio() else if (settings.enableEspNow == true && incoming == 7 && settings.debugEspNow == true) { if (espnowGetState() == ESPNOW_OFF) - espnowStart(); + ESPNOW_START(); uint8_t espnowData[] = "This is the long string to test how quickly we can send one string to the other unit. I am going to " @@ -717,7 +717,7 @@ void menuRadio() printUnknown(incoming); } - espnowStart(); + ESPNOW_START(); // LoRa radio state machine will start/stop radio upon next updateLora in loop() From 4fef3c360187f111f07d1d11560ba2afd69a6733 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 27 Jan 2025 19:17:43 -1000 Subject: [PATCH 188/276] ESP-NOW: Replace espnowStop with ESPNOW_STOP macro --- Firmware/RTK_Everywhere/Developer.ino | 3 +-- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 1 + Firmware/RTK_Everywhere/States.ino | 2 +- Firmware/RTK_Everywhere/menuFirmware.ino | 2 +- Firmware/RTK_Everywhere/menuMain.ino | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 79e602b0f..6ac3e11a0 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -177,8 +177,6 @@ void webServerUpdate() {} #ifndef COMPILE_ESPNOW -bool espNowStop() {return false;} - bool espnowGetState() {return ESPNOW_OFF;} bool espnowIsPaired() {return false;} void espnowProcessRTCM(byte incoming) {} @@ -189,6 +187,7 @@ void espnowStart() {} #define ESPNOW_START() false void espnowStaticPairing() {} void espnowStop() {} +#define ESPNOW_STOP() true void updateEspnow() {} #endif // COMPILE_ESPNOW diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index e8b7c7992..7c5efed00 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -615,6 +615,7 @@ uint8_t receivedMAC[6]; // Holds the broadcast MAC during pairing unsigned long lastEspnowRssiUpdate; #define ESPNOW_START() espnowStart() +#define ESPNOW_STOP() espnowStop() #endif // COMPILE_ESPNOW int espnowRSSI; diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 2ecdc6096..11a624c6e 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -442,7 +442,7 @@ void stateUpdate() displayWebConfigNotStarted(); // Display immediately while we wait for server to start bluetoothStop(); // Bluetooth must be stopped to allow enough RAM for AP+STA (firmware check) - espnowStop(); // We don't need ESP-NOW during web config + ESPNOW_STOP(); // We don't need ESP-NOW during web config // The GNSS UART task is left running to allow GNSS receivers to obtain LLh data for 1Hz page updates diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index 3a1e64f59..25af250c6 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -261,7 +261,7 @@ void updateFromSD(const char *firmwareFileName) } // Turn off any tasks so that we are not disrupted - espnowStop(); + ESPNOW_STOP(); WIFI_STOP(); bluetoothStop(); diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 5dde939ba..14b659935 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -607,7 +607,7 @@ void menuRadio() if (settings.enableEspNow == true) ESPNOW_START(); else - espnowStop(); + ESPNOW_STOP(); } else if (settings.enableEspNow == true && incoming == 2) { From 83d6e91f772fe86f5f3ec670575051ef382dc3ef Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 27 Jan 2025 19:46:37 -1000 Subject: [PATCH 189/276] Rename NETCONSUMER_* to NETIF_* --- Firmware/RTK_Everywhere/Network.ino | 42 ++++++++++++++--------------- Firmware/RTK_Everywhere/WiFi.ino | 4 +-- Firmware/RTK_Everywhere/settings.h | 14 +++++----- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 3f5a4d6a0..894b41d02 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1398,8 +1398,8 @@ void networkUpdate() // Once services have been updated, determine if the network needs to be started/stopped - static uint16_t previousConsumerTypes = NETCONSUMER_NONE; - static uint16_t consumerTypes = NETCONSUMER_NONE; + static uint16_t previousConsumerTypes = NETIF_NONE; + static uint16_t consumerTypes = NETIF_NONE; int consumerCount = networkConsumers(&consumerTypes); // Update the current consumer types @@ -1440,33 +1440,33 @@ void networkUpdate() { systemPrintf("Changing network from consumer type: 0x%02X (", previousConsumerTypes); - if (previousConsumerTypes == NETCONSUMER_NONE) + if (previousConsumerTypes == NETIF_NONE) systemPrint("None"); else { - if (previousConsumerTypes & (1 << NETCONSUMER_WIFI_STA)) + if (previousConsumerTypes & (1 << NETIF_WIFI_STA)) systemPrint("/STA"); - if (previousConsumerTypes & (1 << NETCONSUMER_WIFI_AP)) + if (previousConsumerTypes & (1 << NETIF_WIFI_AP)) systemPrint("/AP"); - if (previousConsumerTypes & (1 << NETCONSUMER_CELLULAR)) + if (previousConsumerTypes & (1 << NETIF_CELLULAR)) systemPrint("/CELL"); - if (previousConsumerTypes & (1 << NETCONSUMER_ETHERNET)) + if (previousConsumerTypes & (1 << NETIF_ETHERNET)) systemPrint("/ETH"); } systemPrintf(") to: 0x%02X (", consumerTypes); - if (consumerTypes == NETCONSUMER_NONE) + if (consumerTypes == NETIF_NONE) systemPrint("None"); else { - if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) + if (consumerTypes & (1 << NETIF_WIFI_STA)) systemPrint("/STA"); - if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) + if (consumerTypes & (1 << NETIF_WIFI_AP)) systemPrint("/AP"); - if (consumerTypes & (1 << NETCONSUMER_CELLULAR)) + if (consumerTypes & (1 << NETIF_CELLULAR)) systemPrint("/CELL"); - if (consumerTypes & (1 << NETCONSUMER_ETHERNET)) + if (consumerTypes & (1 << NETIF_ETHERNET)) systemPrint("/ETH"); } @@ -1487,19 +1487,19 @@ void networkUpdate() { // Attempt to start any network that is needed, in the order Ethernet/WiFi/Cellular - if (consumerTypes & (1 << NETCONSUMER_ETHERNET)) + if (consumerTypes & (1 << NETIF_ETHERNET)) { networkStart(NETWORK_ETHERNET, settings.debugNetworkLayer); } // Start WiFi if we need AP, or if we need STA+Internet - if ((consumerTypes & (1 << NETCONSUMER_WIFI_AP)) || - ((consumerTypes & (1 << NETCONSUMER_WIFI_STA) && networkHasInternet() == false))) + if ((consumerTypes & (1 << NETIF_WIFI_AP)) || + ((consumerTypes & (1 << NETIF_WIFI_STA) && networkHasInternet() == false))) { networkStart(NETWORK_WIFI, settings.debugNetworkLayer); } - if ((networkHasInternet() == false) && (consumerTypes & (1 << NETCONSUMER_CELLULAR))) + if ((networkHasInternet() == false) && (consumerTypes & (1 << NETIF_CELLULAR))) { // If we're in AP only mode (no internet), don't start cellular if (WIFI_SOFT_AP_RUNNING() == false) @@ -1596,7 +1596,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) uint8_t consumerCount = 0; uint16_t consumerId = 0; // Used to debug print who is asking for access - *consumerTypes = NETCONSUMER_NONE; // Clear bitfield + *consumerTypes = NETIF_NONE; // Clear bitfield // If a consumer needs the network or is currently consuming the network (is online) then increment // consumer count @@ -1649,7 +1649,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) // Caster is available over ethernet, WiFi AP, WiFi STA, and cellular // Caster is available in all mode: Rover, and Base if (settings.enableNtripCaster == true || settings.baseCasterOverride == true) - *consumerTypes |= (1 << NETCONSUMER_WIFI_AP); + *consumerTypes |= (1 << NETIF_WIFI_AP); } // Network needed for UDP Server @@ -1682,7 +1682,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) { consumerCount++; consumerId |= (1 << 7); - *consumerTypes = (1 << NETCONSUMER_WIFI_STA); // OTA Pull library only supports WiFi + *consumerTypes = (1 << NETIF_WIFI_STA); // OTA Pull library only supports WiFi } // Network needed for Web Config @@ -1694,14 +1694,14 @@ uint8_t networkConsumers(uint16_t *consumerTypes) *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular if (settings.wifiConfigOverAP == true) - *consumerTypes |= (1 << NETCONSUMER_WIFI_AP); // WebConfig requires both AP and STA (for firmware check) + *consumerTypes |= (1 << NETIF_WIFI_AP); // WebConfig requires both AP and STA (for firmware check) // A good number of RTK products have only WiFi // If WiFi STA has failed or we have no WiFi SSIDs, fall back to WiFi AP, but allow STA to keep hunting if (networkIsPresent(NETWORK_ETHERNET) == false && networkIsPresent(NETWORK_CELLULAR) == false && settings.wifiConfigOverAP == false && (wifiGetStartTimeout() > 0 || wifiNetworkCount() == 0)) { - *consumerTypes |= (1 << NETCONSUMER_WIFI_AP); // Re-allow Webconfig over AP + *consumerTypes |= (1 << NETIF_WIFI_AP); // Re-allow Webconfig over AP } } diff --git a/Firmware/RTK_Everywhere/WiFi.ino b/Firmware/RTK_Everywhere/WiFi.ino index 4853a7498..6e65eed65 100644 --- a/Firmware/RTK_Everywhere/WiFi.ino +++ b/Firmware/RTK_Everywhere/WiFi.ino @@ -752,11 +752,11 @@ bool wifiStart() uint16_t consumerTypes = networkGetConsumerTypes(); // The consumers need station - if (consumerTypes & (1 << NETCONSUMER_WIFI_STA)) + if (consumerTypes & (1 << NETIF_WIFI_STA)) startWiFiStation = true; // The consumers need AP - if (consumerTypes & (1 << NETCONSUMER_WIFI_AP)) + if (consumerTypes & (1 << NETIF_WIFI_AP)) startWiFiAp = true; if (startWiFiStation == false && startWiFiAp == false) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index b930a9615..4625bd6a1 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -555,15 +555,15 @@ const int numRegionalAreas = sizeof(Regional_Information_Table) / sizeof(Regiona //Bitfield for describing the type of network the consumer can use enum { - NETCONSUMER_NONE = 0, // No consumers - NETCONSUMER_WIFI_STA, // The consumer can use STA - NETCONSUMER_WIFI_AP, // The consumer can use AP - NETCONSUMER_CELLULAR, // The consumer can use Cellular - NETCONSUMER_ETHERNET, // The consumer can use Ethernet - NETCONSUMER_UNKNOWN + NETIF_NONE = 0, // No consumers + NETIF_WIFI_STA, // The consumer can use STA + NETIF_WIFI_AP, // The consumer can use AP + NETIF_CELLULAR, // The consumer can use Cellular + NETIF_ETHERNET, // The consumer can use Ethernet + NETIF_UNKNOWN }; -#define NETWORK_EWC ((1 << NETCONSUMER_ETHERNET) | (1 << NETCONSUMER_WIFI_STA) | (1 << NETCONSUMER_CELLULAR)) +#define NETWORK_EWC ((1 << NETIF_ETHERNET) | (1 << NETIF_WIFI_STA) | (1 << NETIF_CELLULAR)) // This is all the settings that can be set on RTK Product. It's recorded to NVM and the config file. // Avoid reordering. The order of these variables is mimicked in NVM/record/parse/create/update/get From 2da158b64473cb496f1ffe6a10d737ed3e265af9 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Mon, 27 Jan 2025 19:57:55 -1000 Subject: [PATCH 190/276] Add NETCONSUMER_* values --- Firmware/RTK_Everywhere/Network.ino | 74 ++++++++++++++--------------- Firmware/RTK_Everywhere/settings.h | 14 ++++++ 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 894b41d02..98d8761c9 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -1605,7 +1605,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) if (ntripClientNeedsNetwork() || online.ntripClient) { consumerCount++; - consumerId |= (1 << 0); + consumerId |= (1 << NETCONSUMER_NTRIP_CLIENT); *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } @@ -1624,7 +1624,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) if (ntripServerNeedsNetwork() || ntripServerOnline) { consumerCount++; - consumerId |= (1 << 1); + consumerId |= (1 << NETCONSUMER_NTRIP_SERVER); *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } @@ -1633,7 +1633,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) if (tcpClientNeedsNetwork() || online.tcpClient) { consumerCount++; - consumerId |= (1 << 2); + consumerId |= (1 << NETCONSUMER_TCP_CLIENT); *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } @@ -1641,7 +1641,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) if (tcpServerNeedsNetwork() || online.tcpServer) { consumerCount++; - consumerId |= (1 << 3); + consumerId |= (1 << NETCONSUMER_TCP_SERVER); *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular @@ -1656,7 +1656,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) if (udpServerNeedsNetwork() || online.udpServer) { consumerCount++; - consumerId |= (1 << 4); + consumerId |= (1 << NETCONSUMER_UDP_SERVER); *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } @@ -1664,7 +1664,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) if (provisioningNeedsNetwork() || online.httpClient) { consumerCount++; - consumerId |= (1 << 5); + consumerId |= (1 << NETCONSUMER_PPL_KEY_UPDATE); *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } @@ -1673,7 +1673,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) { // PointPerfect is enabled, allow MQTT to begin consumerCount++; - consumerId |= (1 << 6); + consumerId |= (1 << NETCONSUMER_PPL_MQTT_CLIENT); *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular } @@ -1681,7 +1681,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) if (otaNeedsNetwork() || online.otaClient) { consumerCount++; - consumerId |= (1 << 7); + consumerId |= (1 << NETCONSUMER_OTA_CLIENT); *consumerTypes = (1 << NETIF_WIFI_STA); // OTA Pull library only supports WiFi } @@ -1689,7 +1689,7 @@ uint8_t networkConsumers(uint16_t *consumerTypes) if (webServerNeedsNetwork() || online.webServer) { consumerCount++; - consumerId |= (1 << 8); + consumerId |= (1 << NETCONSUMER_WEB_CONFIG); *consumerTypes = NETWORK_EWC; // Ask for eth/wifi/cellular @@ -1718,26 +1718,25 @@ uint8_t networkConsumers(uint16_t *consumerTypes) { systemPrintf("- Consumers: ", consumerCount); - if (consumerId & (1 << 0)) + if (consumerId & (1 << NETCONSUMER_NTRIP_CLIENT)) systemPrint("Rover NTRIP Client, "); - if (consumerId & (1 << 1)) + if (consumerId & (1 << NETCONSUMER_NTRIP_SERVER)) systemPrint("Base NTRIP Server, "); - if (consumerId & (1 << 2)) + if (consumerId & (1 << NETCONSUMER_TCP_CLIENT)) systemPrint("TCP Client, "); - if (consumerId & (1 << 3)) + if (consumerId & (1 << NETCONSUMER_TCP_SERVER)) systemPrint("TCP Server, "); - if (consumerId & (1 << 4)) + if (consumerId & (1 << NETCONSUMER_UDP_SERVER)) systemPrint("UDP Server, "); - if (consumerId & (1 << 5)) + if (consumerId & (1 << NETCONSUMER_PPL_KEY_UPDATE)) systemPrint("PPL Key Update Request, "); - if (consumerId & (1 << 6)) + if (consumerId & (1 << NETCONSUMER_PPL_MQTT_CLIENT)) systemPrint("PPL MQTT Client, "); - if (consumerId & (1 << 7)) + if (consumerId & (1 << NETCONSUMER_OTA_CLIENT)) systemPrint("OTA Version Check or Update, "); - if (consumerId & (1 << 8)) + if (consumerId & (1 << NETCONSUMER_WEB_CONFIG)) systemPrint("Web Config, "); } - systemPrintln(); } } @@ -1756,7 +1755,7 @@ uint8_t networkConsumersOnline() if (online.ntripClient) { consumerCountOnline++; - consumerId |= (1 << 0); + consumerId |= (1 << NETCONSUMER_NTRIP_CLIENT); } // Network needed for NTRIP Server @@ -1773,35 +1772,35 @@ uint8_t networkConsumersOnline() if (ntripServerConnected) { consumerCountOnline++; - consumerId |= (1 << 1); + consumerId |= (1 << NETCONSUMER_NTRIP_SERVER); } // Network needed for TCP Client if (online.tcpClient) { consumerCountOnline++; - consumerId |= (1 << 2); + consumerId |= (1 << NETCONSUMER_TCP_CLIENT); } // Network needed for TCP Server - May use WiFi AP or WiFi STA if (online.tcpServer) { consumerCountOnline++; - consumerId |= (1 << 3); + consumerId |= (1 << NETCONSUMER_TCP_SERVER); } // Network needed for UDP Server if (online.udpServer) { consumerCountOnline++; - consumerId |= (1 << 4); + consumerId |= (1 << NETCONSUMER_UDP_SERVER); } // Network needed for PointPerfect ZTP or key update requested by scheduler, from menu, or display menu if (online.httpClient) { consumerCountOnline++; - consumerId |= (1 << 5); + consumerId |= (1 << NETCONSUMER_PPL_KEY_UPDATE); } // Network needed for PointPerfect Corrections MQTT client @@ -1809,21 +1808,21 @@ uint8_t networkConsumersOnline() { // PointPerfect is enabled, allow MQTT to begin consumerCountOnline++; - consumerId |= (1 << 6); + consumerId |= (1 << NETCONSUMER_PPL_MQTT_CLIENT); } // Network needed to obtain the latest firmware version or do update if (online.otaClient) { consumerCountOnline++; - consumerId |= (1 << 7); + consumerId |= (1 << NETCONSUMER_OTA_CLIENT); } // Network needed for Web Config if (online.webServer) { consumerCountOnline++; - consumerId |= (1 << 8); + consumerId |= (1 << NETCONSUMER_WEB_CONFIG); } // Debug @@ -1838,24 +1837,23 @@ uint8_t networkConsumersOnline() if (consumerCountOnline > 0) { systemPrintf("- Consumers: ", consumerCountOnline); - - if (consumerId & (1 << 0)) + if (consumerId & (1 << NETCONSUMER_NTRIP_CLIENT)) systemPrint("Rover NTRIP Client, "); - if (consumerId & (1 << 1)) + if (consumerId & (1 << NETCONSUMER_NTRIP_SERVER)) systemPrint("Base NTRIP Server, "); - if (consumerId & (1 << 2)) + if (consumerId & (1 << NETCONSUMER_TCP_CLIENT)) systemPrint("TCP Client, "); - if (consumerId & (1 << 3)) + if (consumerId & (1 << NETCONSUMER_TCP_SERVER)) systemPrint("TCP Server, "); - if (consumerId & (1 << 4)) + if (consumerId & (1 << NETCONSUMER_UDP_SERVER)) systemPrint("UDP Server, "); - if (consumerId & (1 << 5)) + if (consumerId & (1 << NETCONSUMER_PPL_KEY_UPDATE)) systemPrint("PPL Key Update Request, "); - if (consumerId & (1 << 6)) + if (consumerId & (1 << NETCONSUMER_PPL_MQTT_CLIENT)) systemPrint("PPL MQTT Client, "); - if (consumerId & (1 << 7)) + if (consumerId & (1 << NETCONSUMER_OTA_CLIENT)) systemPrint("OTA Version Check or Update, "); - if (consumerId & (1 << 8)) + if (consumerId & (1 << NETCONSUMER_WEB_CONFIG)) systemPrint("Web Config, "); } diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 4625bd6a1..7aeb20d39 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -565,6 +565,20 @@ enum #define NETWORK_EWC ((1 << NETIF_ETHERNET) | (1 << NETIF_WIFI_STA) | (1 << NETIF_CELLULAR)) +// Bitfield for describing the network consumers +enum +{ + NETCONSUMER_NTRIP_CLIENT = 0, + NETCONSUMER_NTRIP_SERVER, + NETCONSUMER_TCP_CLIENT, + NETCONSUMER_TCP_SERVER, + NETCONSUMER_UDP_SERVER, + NETCONSUMER_PPL_KEY_UPDATE, + NETCONSUMER_PPL_MQTT_CLIENT, + NETCONSUMER_OTA_CLIENT, + NETCONSUMER_WEB_CONFIG, +}; + // This is all the settings that can be set on RTK Product. It's recorded to NVM and the config file. // Avoid reordering. The order of these variables is mimicked in NVM/record/parse/create/update/get struct Settings From bff206e78d1be921bb355cb2b66f1d53eb215c24 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Tue, 28 Jan 2025 08:49:18 -1000 Subject: [PATCH 191/276] WebServer: Add webServerVerifyTables routine --- Firmware/RTK_Everywhere/WebServer.ino | 9 ++++++++- Firmware/RTK_Everywhere/support.ino | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index f4358e801..645137fe3 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------------ -Form.ino +WebServer.ino Start and stop the web-server, provide the form and handle browser input. ------------------------------------------------------------------------------*/ @@ -1465,4 +1465,11 @@ void handleUpload() } } +// Verify the web server tables +void webServerVerifyTables() +{ + if (webServerStateEntries != WEBSERVER_STATE_MAX) + reportFatalError("Fix webServerStateNames to match WebServerState"); +} + #endif // COMPILE_AP diff --git a/Firmware/RTK_Everywhere/support.ino b/Firmware/RTK_Everywhere/support.ino index e5cecb3dc..31686407d 100644 --- a/Firmware/RTK_Everywhere/support.ino +++ b/Firmware/RTK_Everywhere/support.ino @@ -721,6 +721,7 @@ void verifyTables() provisioningVerifyTables(); mosaicVerifyTables(); correctionVerifyTables(); + webServerVerifyTables(); if (correctionsSource::CORR_NUM >= (int)('x' - 'a')) reportFatalError("Too many correction sources"); From fbd5127321a0f8123e952247a12f426ee2ec7c32 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Tue, 28 Jan 2025 09:23:21 -1000 Subject: [PATCH 192/276] WebServer: Dump the HTTP request in hex and ASCII --- Firmware/RTK_Everywhere/WebServer.ino | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index f4358e801..91d79da12 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -150,26 +150,25 @@ static esp_err_t ws_handler(httpd_req_t *req) if (ws_pkt.type == HTTPD_WS_TYPE_TEXT) { - if (currentlyParsingData == false) + if (settings.debugWebServer == true) { - if (settings.debugWebServer == true) - systemPrint("Got packet with message: \r\n"); //We can't %s the payload as it's not string terminated + systemPrintf("Got packet with message: %s\r\n", ws_pkt.payload); + dumpBuffer(ws_pkt.payload, ws_pkt.len); + } + if (currentlyParsingData == false) + { for (int i = 0; i < ws_pkt.len; i++) { incomingSettings[incomingSettingsSpot++] = ws_pkt.payload[i]; incomingSettingsSpot %= AP_CONFIG_SETTING_SIZE; - - //Print payload if needed - if (settings.debugWebServer == true) - systemWrite(ws_pkt.payload[i]); } timeSinceLastIncomingSetting = millis(); } else { if (settings.debugWebServer == true) - systemPrintln("Got packet but ignoring due to parsing block"); + systemPrintln("Ignoring packet due to parsing block"); } } else if (ws_pkt.type == HTTPD_WS_TYPE_CLOSE) From a25f384f513ccb925e11364719c5e153cb99e8e1 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 28 Jan 2025 13:29:46 -0700 Subject: [PATCH 193/276] Revert "Merge pull request #525 from LeeLeahy2/fix-network-failover-detection" This reverts commit ae201aaddf108d64d356bb1daca687b11907fe6e, reversing changes made to a145103af30213c73a801d8e24611484eab2f6dc. --- Firmware/RTK_Everywhere/HTTP_Client.ino | 12 +++++------- Firmware/RTK_Everywhere/MQTT_Client.ino | 8 +++----- Firmware/RTK_Everywhere/NTP.ino | 2 -- Firmware/RTK_Everywhere/Network.ino | 16 ---------------- Firmware/RTK_Everywhere/NtripClient.ino | 12 +++++------- Firmware/RTK_Everywhere/NtripServer.ino | 14 ++++++-------- Firmware/RTK_Everywhere/TcpClient.ino | 8 +++----- Firmware/RTK_Everywhere/TcpServer.ino | 6 ++---- Firmware/RTK_Everywhere/UdpServer.ino | 8 +++----- Firmware/RTK_Everywhere/WebServer.ino | 8 +++----- Firmware/RTK_Everywhere/menuFirmware.ino | 11 +++++++---- Firmware/RTK_Everywhere/menuPP.ino | 3 +-- 12 files changed, 38 insertions(+), 70 deletions(-) diff --git a/Firmware/RTK_Everywhere/HTTP_Client.ino b/Firmware/RTK_Everywhere/HTTP_Client.ino index 837a97b5e..d2e15b9b6 100644 --- a/Firmware/RTK_Everywhere/HTTP_Client.ino +++ b/Firmware/RTK_Everywhere/HTTP_Client.ino @@ -59,7 +59,6 @@ static uint32_t httpClientConnectionAttemptTimeout = 5 * 1000L; // Wait 5s static int httpClientConnectionAttemptsTotal; // Count the number of connection attempts absolutely static volatile uint32_t httpClientLastDataReceived; // Last time data was received via HTTP -static NetPriority_t httpClientPriority = NETWORK_OFFLINE; static NetworkClientSecure *httpSecureClient; @@ -276,7 +275,6 @@ void httpClientUpdate() case HTTP_CLIENT_ON: { if ((millis() - httpClientTimer) > httpClientConnectionAttemptTimeout) { - httpClientPriority = NETWORK_OFFLINE; httpClientSetState(HTTP_CLIENT_NETWORK_STARTED); } break; @@ -288,8 +286,8 @@ void httpClientUpdate() if (!httpClientModeNeeded) httpClientStop(true); - // Wait until the network is connected to the media - else if (networkIsConnected(&httpClientPriority)) + // Wait until the network is connected + else if (networkHasInternet()) httpClientSetState(HTTP_CLIENT_CONNECTING_2_SERVER); break; } @@ -297,7 +295,7 @@ void httpClientUpdate() // Connect to the HTTP server case HTTP_CLIENT_CONNECTING_2_SERVER: { // Determine if the network has failed - if (!networkIsConnected(&httpClientPriority)) + if (networkHasInternet() == false) { // Failed to connect to the network, attempt to restart the network httpClientStop(true); // Was httpClientRestart(); - #StopVsRestart @@ -354,7 +352,7 @@ void httpClientUpdate() case HTTP_CLIENT_CONNECTED: { // Determine if the network has failed - if (!networkIsConnected(&httpClientPriority)) + if (networkHasInternet() == false) { // Failed to connect to the network, attempt to restart the network httpClientStop(true); // Was httpClientRestart(); - #StopVsRestart @@ -558,7 +556,7 @@ void httpClientUpdate() // Hang here until httpClientModeNeeded is set to false by updateProvisioning case HTTP_CLIENT_COMPLETE: { // Determine if the network has failed - if (!networkIsConnected(&httpClientPriority)) + if (networkHasInternet() == false) // Failed to connect to the network, attempt to restart the network httpClientStop(true); // Was httpClientRestart(); - #StopVsRestart break; diff --git a/Firmware/RTK_Everywhere/MQTT_Client.ino b/Firmware/RTK_Everywhere/MQTT_Client.ino index 3bd1cf91c..1b60d4fd9 100644 --- a/Firmware/RTK_Everywhere/MQTT_Client.ino +++ b/Firmware/RTK_Everywhere/MQTT_Client.ino @@ -138,7 +138,6 @@ static uint32_t mqttClientConnectionAttemptTimeout; static int mqttClientConnectionAttemptsTotal; // Count the number of connection attempts absolutely static volatile uint32_t mqttClientLastDataReceived; // Last time data was received via MQTT -static NetPriority_t mqttClientPriority = NETWORK_OFFLINE; static NetworkClientSecure *mqttSecureClient; @@ -723,7 +722,6 @@ void mqttClientUpdate() case MQTT_CLIENT_ON: { if ((millis() - mqttClientTimer) > mqttClientConnectionAttemptTimeout) { - mqttClientPriority = NETWORK_OFFLINE; mqttClientSetState(MQTT_CLIENT_WAIT_FOR_NETWORK); } break; @@ -736,7 +734,7 @@ void mqttClientUpdate() mqttClientStop(true); // Wait until the network is connected to the media - else if (networkIsConnected(&mqttClientPriority)) + else if (networkHasInternet()) mqttClientSetState(MQTT_CLIENT_CONNECTING_2_SERVER); break; } @@ -744,7 +742,7 @@ void mqttClientUpdate() // Connect to the MQTT server case MQTT_CLIENT_CONNECTING_2_SERVER: { // Determine if the network has failed - if (!networkIsConnected(&mqttClientPriority)) + if (networkHasInternet() == false) { // Failed to connect to the network, attempt to restart the network mqttClientStop(true); // Was mqttClientRestart(); - #StopVsRestart @@ -890,7 +888,7 @@ void mqttClientUpdate() case MQTT_CLIENT_SERVICES_CONNECTED: { // Determine if the network has failed - if (!networkIsConnected(&mqttClientPriority)) + if (networkHasInternet() == false) { // Failed to connect to the network, attempt to restart the network mqttClientStop(true); // Was mqttClientRestart(); - #StopVsRestart diff --git a/Firmware/RTK_Everywhere/NTP.ino b/Firmware/RTK_Everywhere/NTP.ino index 75ade00a0..e03d0a217 100644 --- a/Firmware/RTK_Everywhere/NTP.ino +++ b/Firmware/RTK_Everywhere/NTP.ino @@ -75,7 +75,6 @@ const RtkMode_t ntpServerMode = RTK_MODE_NTP; // Locals //---------------------------------------- -static NetPriority_t ntpServerPriority = NETWORK_OFFLINE; static NetworkUDP *ntpServer; // This will be instantiated when we know the NTP port static uint8_t ntpServerState; static uint32_t lastLoggedNTPRequest; @@ -793,7 +792,6 @@ void ntpServerUpdate() // The NTP server only works over Ethernet if (networkInterfaceHasInternet(NETWORK_ETHERNET)) { - ntpServerPriority = NETWORK_OFFLINE; ntpServerSetState(NTP_STATE_NETWORK_CONNECTED); } } diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 339a128e9..98d8761c9 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -586,22 +586,6 @@ const char *networkGetNameByPriority(NetPriority_t priority) return "None"; } -//---------------------------------------- -// Determine if the network is available -//---------------------------------------- -bool networkIsConnected(NetPriority_t *clientPriority) -{ - // If the client is using the highest priority network and that - // network is still available then continue as normal - if (networkHasInternet_bm && (*clientPriority == networkPriority)) - return (networkHasInternet_bm & (1 << networkIndexTable[networkPriority])) - ? true : false; - - // The network has changed, notify the client of the change - *clientPriority = networkPriority; - return false; -} - //---------------------------------------- // Determine if the network interface is online //---------------------------------------- diff --git a/Firmware/RTK_Everywhere/NtripClient.ino b/Firmware/RTK_Everywhere/NtripClient.ino index b6007c8a0..9b54aaaf4 100644 --- a/Firmware/RTK_Everywhere/NtripClient.ino +++ b/Firmware/RTK_Everywhere/NtripClient.ino @@ -187,7 +187,6 @@ static volatile uint8_t ntripClientState = NTRIP_CLIENT_OFF; static int ntripClientConnectionAttempts; // Count the number of connection attempts between restarts static uint32_t ntripClientConnectionAttemptTimeout; static int ntripClientConnectionAttemptsTotal; // Count the number of connection attempts absolutely -static NetPriority_t ntripClientPriority = NETWORK_OFFLINE; // NTRIP client timer usage: // * Reconnection delay @@ -563,7 +562,6 @@ void ntripClientUpdate() // Start the network case NTRIP_CLIENT_ON: - ntripClientPriority = NETWORK_OFFLINE; ntripClientSetState(NTRIP_CLIENT_WAIT_FOR_NETWORK); break; @@ -573,8 +571,8 @@ void ntripClientUpdate() if (ntripClientForcedShutdown || NEQ_RTK_MODE(ntripClientMode) || !settings.enableNtripClient) ntripClientStop(true); - // Wait until the network is connected to the media - else if (networkIsConnected(&ntripClientPriority)) + // Wait until the network is connected + else if (networkHasInternet()) { // Allocate the ntripClient structure ntripClient = new NetworkClient(); @@ -596,7 +594,7 @@ void ntripClientUpdate() case NTRIP_CLIENT_NETWORK_CONNECTED: // Determine if the network has failed - if (!networkIsConnected(&ntripClientPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripClientStop(true); // Was ntripClientRestart(); - #StopVsRestart @@ -629,7 +627,7 @@ void ntripClientUpdate() case NTRIP_CLIENT_WAIT_RESPONSE: // Determine if the network has failed - if (!networkIsConnected(&ntripClientPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripClientStop(true); // Was ntripClientRestart(); - #StopVsRestart @@ -750,7 +748,7 @@ void ntripClientUpdate() case NTRIP_CLIENT_CONNECTED: // Determine if the network has failed - if (!networkIsConnected(&ntripClientPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripClientStop(true); // Was ntripClientRestart(); - #StopVsRestart diff --git a/Firmware/RTK_Everywhere/NtripServer.ino b/Firmware/RTK_Everywhere/NtripServer.ino index c3d45704b..edb72a424 100644 --- a/Firmware/RTK_Everywhere/NtripServer.ino +++ b/Firmware/RTK_Everywhere/NtripServer.ino @@ -175,7 +175,6 @@ const RtkMode_t ntripServerMode = RTK_MODE_BASE_FIXED; // NTRIP Servers static NTRIP_SERVER_DATA ntripServerArray[NTRIP_SERVER_MAX]; -static NetPriority_t ntripServerPriority = NETWORK_OFFLINE; //---------------------------------------- // NTRIP Server Routines @@ -608,7 +607,6 @@ void ntripServerUpdate(int serverIndex) // Start the network case NTRIP_SERVER_ON: - ntripServerPriority = NETWORK_OFFLINE; ntripServerSetState(ntripServer, NTRIP_SERVER_WAIT_FOR_NETWORK); break; @@ -624,7 +622,7 @@ void ntripServerUpdate(int serverIndex) } // Wait until the network is connected - else if (networkIsConnected(&ntripServerPriority)) + else if (networkHasInternet()) { // Allocate the networkClient structure ntripServer->networkClient = new NetworkClient(); @@ -647,7 +645,7 @@ void ntripServerUpdate(int serverIndex) // Network available case NTRIP_SERVER_NETWORK_CONNECTED: // Determine if the network has failed - if (!networkIsConnected(&ntripServerPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -665,7 +663,7 @@ void ntripServerUpdate(int serverIndex) // Wait for GNSS correction data case NTRIP_SERVER_WAIT_GNSS_DATA: // Determine if the network has failed - if (!networkIsConnected(&ntripServerPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -675,7 +673,7 @@ void ntripServerUpdate(int serverIndex) // Initiate the connection to the NTRIP caster case NTRIP_SERVER_CONNECTING: // Determine if the network has failed - if (!networkIsConnected(&ntripServerPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -703,7 +701,7 @@ void ntripServerUpdate(int serverIndex) // Wait for authorization response case NTRIP_SERVER_AUTHORIZATION: // Determine if the network has failed - if (!networkIsConnected(&ntripServerPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart @@ -797,7 +795,7 @@ void ntripServerUpdate(int serverIndex) // NTRIP server authorized to send RTCM correction data to NTRIP caster case NTRIP_SERVER_CASTING: // Determine if the network has failed - if (!networkIsConnected(&ntripServerPriority)) + if (networkHasInternet() == false) // Failed to connect to the network, attempt to restart the network ntripServerStop(serverIndex, true); // Was ntripServerRestart(serverIndex); - #StopVsRestart diff --git a/Firmware/RTK_Everywhere/TcpClient.ino b/Firmware/RTK_Everywhere/TcpClient.ino index 21078879c..d59ff2e3c 100644 --- a/Firmware/RTK_Everywhere/TcpClient.ino +++ b/Firmware/RTK_Everywhere/TcpClient.ino @@ -148,7 +148,6 @@ const RtkMode_t tcpClientMode = RTK_MODE_BASE_FIXED | RTK_MODE_BASE_SURVEY_IN | static NetworkClient *tcpClient; static IPAddress tcpClientIpAddress; -static NetPriority_t tcpClientPriority = NETWORK_OFFLINE; static uint8_t tcpClientState; static volatile RING_BUFFER_OFFSET tcpClientTail; static volatile bool tcpClientWriteError; @@ -417,7 +416,6 @@ void tcpClientUpdate() if (EQ_RTK_MODE(tcpClientMode) && settings.enableTcpClient) { timer = 0; - tcpClientPriority = NETWORK_OFFLINE; tcpClientSetState(TCP_CLIENT_STATE_WAIT_FOR_NETWORK); } break; @@ -429,7 +427,7 @@ void tcpClientUpdate() tcpClientStop(); // Wait until the network is connected - else if (networkIsConnected(&tcpClientPriority)) + else if (networkHasInternet()) { #ifdef COMPILE_WIFI // Determine if WiFi is required @@ -465,7 +463,7 @@ void tcpClientUpdate() // Attempt the connection ot the TCP server case TCP_CLIENT_STATE_CLIENT_STARTING: // Determine if the network has failed - if (!networkIsConnected(&tcpClientPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network tcpClientStop(); @@ -510,7 +508,7 @@ void tcpClientUpdate() // Wait for the TCP client to shutdown or a TCP client link failure case TCP_CLIENT_STATE_CONNECTED: // Determine if the network has failed - if (!networkIsConnected(&tcpClientPriority)) + if (networkHasInternet() == false) // Failed to connect to to the network, attempt to restart the network tcpClientStop(); diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino index 3506abbde..fac038922 100644 --- a/Firmware/RTK_Everywhere/TcpServer.ino +++ b/Firmware/RTK_Everywhere/TcpServer.ino @@ -76,7 +76,6 @@ static volatile uint8_t tcpServerClientWriteError; static NetworkClient *tcpServerClient[TCP_SERVER_MAX_CLIENTS]; static IPAddress tcpServerClientIpAddress[TCP_SERVER_MAX_CLIENTS]; static volatile RING_BUFFER_OFFSET tcpServerClientTails[TCP_SERVER_MAX_CLIENTS]; -static NetPriority_t tcpServerPriority = NETWORK_OFFLINE; //---------------------------------------- // TCP Server handleGnssDataTask Support Routines @@ -381,7 +380,6 @@ void tcpServerUpdate() { if (settings.debugTcpServer && (!inMainMenu)) systemPrintln("TCP server start"); - tcpServerPriority = NETWORK_OFFLINE; tcpServerSetState(TCP_SERVER_STATE_WAIT_FOR_NETWORK); } break; @@ -393,7 +391,7 @@ void tcpServerUpdate() tcpServerStop(); // Wait until the network is connected to the media - else if (networkIsConnected(&tcpServerPriority)) + else if (networkHasInternet() || WIFI_SOFT_AP_RUNNING()) { // Delay before starting the TCP server if ((millis() - tcpServerTimer) >= (1 * 1000)) @@ -411,7 +409,7 @@ void tcpServerUpdate() // Handle client connections and link failures case TCP_SERVER_STATE_RUNNING: // Determine if the network has failed - if ((networkIsConnected(&tcpServerPriority) == false && WIFI_SOFT_AP_RUNNING() == false) || (!settings.enableTcpServer && !settings.baseCasterOverride)) + if ((networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) || (!settings.enableTcpServer && !settings.baseCasterOverride)) { if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu)) { diff --git a/Firmware/RTK_Everywhere/UdpServer.ino b/Firmware/RTK_Everywhere/UdpServer.ino index ce60629f9..3a9a8d27f 100644 --- a/Firmware/RTK_Everywhere/UdpServer.ino +++ b/Firmware/RTK_Everywhere/UdpServer.ino @@ -94,7 +94,6 @@ static NetworkUDP *udpServer = nullptr; static uint8_t udpServerState; static uint32_t udpServerTimer; static volatile RING_BUFFER_OFFSET udpServerTail; -static NetPriority_t udpServerPriority; //---------------------------------------- // UDP Server handleGnssDataTask Support Routines @@ -107,7 +106,7 @@ int32_t udpServerSendDataBroadcast(uint8_t *data, uint16_t length) return 0; // Send the data as broadcast - if (settings.enableUdpServer && online.udpServer && networkIsConnected(&udpServerPriority)) + if (settings.enableUdpServer && online.udpServer && networkHasInternet()) { IPAddress broadcastAddress = networkGetBroadcastIpAddress(); udpServer->beginPacket(broadcastAddress, settings.udpServerPort); @@ -325,7 +324,6 @@ void udpServerUpdate() { if (settings.debugUdpServer && (!inMainMenu)) systemPrintln("UDP server starting the network"); - udpServerPriority = NETWORK_OFFLINE; udpServerSetState(UDP_SERVER_STATE_WAIT_FOR_NETWORK); } break; @@ -337,7 +335,7 @@ void udpServerUpdate() udpServerStop(); // Wait until the network is connected - else if (networkIsConnected(&udpServerPriority) || WIFI_SOFT_AP_RUNNING()) + else if (networkHasInternet() || WIFI_SOFT_AP_RUNNING()) { // Delay before starting the UDP server if ((millis() - udpServerTimer) >= (1 * 1000)) @@ -355,7 +353,7 @@ void udpServerUpdate() // Handle client connections and link failures case UDP_SERVER_STATE_RUNNING: // Determine if the network has failed - if ((networkIsConnected(&udpServerPriority) == false && WIFI_SOFT_AP_RUNNING() == false) || (!settings.enableUdpServer && !settings.baseCasterOverride)) + if ((networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) || (!settings.enableUdpServer && !settings.baseCasterOverride)) { if ((settings.debugUdpServer || PERIODIC_DISPLAY(PD_UDP_SERVER_DATA)) && (!inMainMenu)) { diff --git a/Firmware/RTK_Everywhere/WebServer.ino b/Firmware/RTK_Everywhere/WebServer.ino index 3a20f161d..59dadd7e5 100644 --- a/Firmware/RTK_Everywhere/WebServer.ino +++ b/Firmware/RTK_Everywhere/WebServer.ino @@ -27,8 +27,6 @@ static const char *const webServerStateNames[] = { static const int webServerStateEntries = sizeof(webServerStateNames) / sizeof(webServerStateNames[0]); -static NetPriority_t webServerPriority = NETWORK_OFFLINE; - static uint8_t webServerState; // Once connected to the access point for WiFi Config, the ESP32 sends current setting values in one long string to @@ -780,7 +778,7 @@ void webServerUpdate() // Wait for connection to the network case WEBSERVER_STATE_WAIT_FOR_NETWORK: // Wait until the network is connected to the internet or has WiFi AP - if (networkIsConnected(&webServerPriority) || WIFI_SOFT_AP_RUNNING()) + if (networkHasInternet() || WIFI_SOFT_AP_RUNNING()) { if (settings.debugWebServer) systemPrintln("Web Server connected to network"); @@ -792,7 +790,7 @@ void webServerUpdate() // Start the web server case WEBSERVER_STATE_NETWORK_CONNECTED: { // Determine if the network has failed - if (networkIsConnected(&webServerPriority) == false && WIFI_SOFT_AP_RUNNING() == false) + if (networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) webServerStop(); if (settings.debugWebServer) systemPrintln("Assigning web server resources"); @@ -808,7 +806,7 @@ void webServerUpdate() // Allow web services case WEBSERVER_STATE_RUNNING: // Determine if the network has failed - if (networkIsConnected(&webServerPriority) == false && WIFI_SOFT_AP_RUNNING() == false) + if (networkHasInternet() == false && WIFI_SOFT_AP_RUNNING() == false) webServerStop(); // This state is exited when webServerStop() is called diff --git a/Firmware/RTK_Everywhere/menuFirmware.ino b/Firmware/RTK_Everywhere/menuFirmware.ino index 94aff2dda..25af250c6 100644 --- a/Firmware/RTK_Everywhere/menuFirmware.ino +++ b/Firmware/RTK_Everywhere/menuFirmware.ino @@ -33,7 +33,6 @@ static const int otaStateEntries = sizeof(otaStateNames) / sizeof(otaStateNames[ //---------------------------------------- static uint32_t otaLastUpdateCheck; -static NetPriority_t otaPriority = NETWORK_OFFLINE; static uint8_t otaState; #endif // COMPILE_OTA_AUTO @@ -841,7 +840,9 @@ void otaUpdate() otaUpdateStop(); // Wait until the network is connected to the media - else if (networkIsConnected(&otaPriority)) + // else if (networkHasInternet()) + else if (networkInterfaceHasInternet( + NETWORK_WIFI)) // TODO Remove once OTA works over other network interfaces { if (settings.debugFirmwareUpdate) systemPrintln("Firmware update connected to network"); @@ -854,7 +855,9 @@ void otaUpdate() // Get firmware version from server case OTA_STATE_GET_FIRMWARE_VERSION: // Determine if the network has failed - if (!networkIsConnected(&otaPriority)) + // if (networkHasInternet() == false) + if (networkInterfaceHasInternet(NETWORK_WIFI) == + false) // TODO Remove once OTA works over other network interfaces otaUpdateStop(); if (settings.debugFirmwareUpdate) systemPrintln("Checking for latest firmware version"); @@ -910,7 +913,7 @@ void otaUpdate() // Update the firmware case OTA_STATE_UPDATE_FIRMWARE: // Determine if the network has failed - if (!networkIsConnected(&otaPriority)) + if (networkHasInternet() == false) otaUpdateStop(); else { diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index bd3db6850..6d62f4f54 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -21,7 +21,6 @@ static const uint8_t ppIpToken[16] = {POINTPERFECT_IP_TOKEN}; // Toke static const uint8_t ppLbandIpToken[16] = {POINTPERFECT_LBAND_IP_TOKEN}; // Token in HEX form #ifdef COMPILE_NETWORK -static NetPriority_t pointperfectPriority = NETWORK_OFFLINE; MqttClient *menuppMqttClient; #endif // COMPILE_NETWORK @@ -1309,7 +1308,7 @@ void provisioningUpdate() } // Wait until the network is available #ifdef COMPILE_NETWORK - else if (networkIsConnected(&pointperfectPriority)) + else if (networkHasInternet()) { if (settings.debugPpCertificate) systemPrintln("PointPerfect key update connected to network"); From 68382e1ccdb7fddff72d827c81f1feaccc349396 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 28 Jan 2025 13:52:06 -0700 Subject: [PATCH 194/276] Add compile guard --- Firmware/RTK_Everywhere/Developer.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 6ac3e11a0..edd72d944 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -168,6 +168,7 @@ void stopWebServer() {} bool webServerNeedsNetwork() {return false;} void webServerStop() {} void webServerUpdate() {} +void webServerVerifyTables() {} #endif // COMPILE_AP From f9d15fa76771592abbda93df9dc386b3984746a3 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 31 Jan 2025 09:28:31 -1000 Subject: [PATCH 195/276] Network: Move code --- Firmware/RTK_Everywhere/Network.ino | 140 ++++++++++++++-------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index 98d8761c9..c5b9de435 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -586,30 +586,6 @@ const char *networkGetNameByPriority(NetPriority_t priority) return "None"; } -//---------------------------------------- -// Determine if the network interface is online -//---------------------------------------- -bool networkInterfaceHasInternet(NetIndex_t index) -{ - // Validate the index - networkValidateIndex(index); - - // Return the network interface state - return (networkHasInternet_bm & (1 << index)) ? true : false; -} - -//---------------------------------------- -// Determine if the network interface has completed its start routine -//---------------------------------------- -bool networkIsInterfaceStarted(NetIndex_t index) -{ - // Validate the index - networkValidateIndex(index); - - // Return the network started state - return (networkStarted & (1 << index)) ? true : false; -} - //---------------------------------------- // Determine if any network interface is online //---------------------------------------- @@ -620,23 +596,23 @@ bool networkHasInternet() } //---------------------------------------- -// Determine if the network is present on the platform +// Interface stop event //---------------------------------------- -bool networkIsPresent(NetIndex_t index) +void networkInterfaceEventStop(NetIndex_t index) { - // Validate the index - networkValidateIndex(index); - - // Present if nullptr or bool set to true - return ((!networkInterfaceTable[index].present) || *(networkInterfaceTable[index].present)); + networkEventStop[index] = true; } //---------------------------------------- -// Interface stop event +// Determine if the network interface is online //---------------------------------------- -void networkInterfaceEventStop(NetIndex_t index) +bool networkInterfaceHasInternet(NetIndex_t index) { - networkEventStop[index] = true; + // Validate the index + networkValidateIndex(index); + + // Return the network interface state + return (networkHasInternet_bm & (1 << index)) ? true : false; } //---------------------------------------- @@ -780,6 +756,30 @@ void networkInterfaceEventInternetAvailable(NetIndex_t index) networkMulticastDNSStart(previousIndex); } +//---------------------------------------- +// Determine if the network interface has completed its start routine +//---------------------------------------- +bool networkIsInterfaceStarted(NetIndex_t index) +{ + // Validate the index + networkValidateIndex(index); + + // Return the network started state + return (networkStarted & (1 << index)) ? true : false; +} + +//---------------------------------------- +// Determine if the network is present on the platform +//---------------------------------------- +bool networkIsPresent(NetIndex_t index) +{ + // Validate the index + networkValidateIndex(index); + + // Present if nullptr or bool set to true + return ((!networkInterfaceTable[index].present) || *(networkInterfaceTable[index].present)); +} + //---------------------------------------- // Change multicast DNS to a given network //---------------------------------------- @@ -1326,42 +1326,6 @@ void networkStartDelayed(NetIndex_t index, uintptr_t parameter, bool debug) } } -//---------------------------------------- -// Validate the network index -//---------------------------------------- -void networkValidateIndex(NetIndex_t index) -{ - // Validate the index - if (index >= NETWORK_OFFLINE) - { - systemPrintf("HALTED: Invalid index value %d, valid range (0 - %d)!\r\n", index, NETWORK_OFFLINE - 1); - reportFatalError("Invalid index value!"); - } -} - -//---------------------------------------- -// Validate the network priority -//---------------------------------------- -void networkValidatePriority(NetPriority_t priority) -{ - // Validate the priority - if (priority >= NETWORK_OFFLINE) - { - systemPrintf("HALTED: Invalid priority value %d, valid range (0 - %d)!\r\n", priority, NETWORK_OFFLINE - 1); - reportFatalError("Invalid priority value!"); - } -} - -//---------------------------------------- -// Verify the network layer tables -//---------------------------------------- -void networkVerifyTables() -{ - // Verify the table lengths - if (NETWORK_OFFLINE != NETWORK_MAX) - reportFatalError("Fix networkInterfaceTable to match NetworkType"); -} - //---------------------------------------- // Maintain the network connections //---------------------------------------- @@ -1570,6 +1534,42 @@ void networkUpdate() } } +//---------------------------------------- +// Validate the network index +//---------------------------------------- +void networkValidateIndex(NetIndex_t index) +{ + // Validate the index + if (index >= NETWORK_OFFLINE) + { + systemPrintf("HALTED: Invalid index value %d, valid range (0 - %d)!\r\n", index, NETWORK_OFFLINE - 1); + reportFatalError("Invalid index value!"); + } +} + +//---------------------------------------- +// Validate the network priority +//---------------------------------------- +void networkValidatePriority(NetPriority_t priority) +{ + // Validate the priority + if (priority >= NETWORK_OFFLINE) + { + systemPrintf("HALTED: Invalid priority value %d, valid range (0 - %d)!\r\n", priority, NETWORK_OFFLINE - 1); + reportFatalError("Invalid priority value!"); + } +} + +//---------------------------------------- +// Verify the network layer tables +//---------------------------------------- +void networkVerifyTables() +{ + // Verify the table lengths + if (NETWORK_OFFLINE != NETWORK_MAX) + reportFatalError("Fix networkInterfaceTable to match NetworkType"); +} + // Return the bitfield containing the type of consumers currently using the network uint16_t networkGetConsumerTypes() { From 1bb87f2c68791ed3418ac686c2c2eec2e5581075 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 31 Jan 2025 09:32:40 -1000 Subject: [PATCH 196/276] Network: Fix comments and remove blank lines --- Firmware/RTK_Everywhere/Network.ino | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino index c5b9de435..03f5ffb53 100644 --- a/Firmware/RTK_Everywhere/Network.ino +++ b/Firmware/RTK_Everywhere/Network.ino @@ -587,7 +587,7 @@ const char *networkGetNameByPriority(NetPriority_t priority) } //---------------------------------------- -// Determine if any network interface is online +// Determine if any network interface has access to the internet //---------------------------------------- bool networkHasInternet() { @@ -604,7 +604,7 @@ void networkInterfaceEventStop(NetIndex_t index) } //---------------------------------------- -// Determine if the network interface is online +// Determine the specified network interface access to the internet //---------------------------------------- bool networkInterfaceHasInternet(NetIndex_t index) { @@ -616,7 +616,7 @@ bool networkInterfaceHasInternet(NetIndex_t index) } //---------------------------------------- -// Mark network offline +// Mark network interface as having NO access to the internet //---------------------------------------- void networkInterfaceEventInternetLost(NetIndex_t index) { @@ -685,7 +685,7 @@ void networkInterfaceEventInternetLost(NetIndex_t index) } //---------------------------------------- -// Mark network online +// Mark network interface as having access to the internet //---------------------------------------- void networkInterfaceEventInternetAvailable(NetIndex_t index) { @@ -1124,7 +1124,6 @@ void networkSequenceStop(NetIndex_t index, bool debug) // Start the sequence networkSeqStopping |= bitMask; networkStarted &= ~bitMask; - networkSequence[index] = sequence; } } @@ -1184,7 +1183,6 @@ void networkSequenceStopPolling(NetIndex_t index, bool debug, bool forcedStop) if (forcedStop) { networkStarted &= ~bitMask; - networkSeqRequest &= ~bitMask; networkSeqNext &= ~bitMask; } From dfab621371c9a71f9a3dbe6df091d7aba07f32e0 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 31 Jan 2025 10:11:57 -1000 Subject: [PATCH 197/276] ESP-NOW: Rename peerBroadcast to espnowBroadcastAddr --- Firmware/RTK_Everywhere/ESPNOW.ino | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index e58f5824e..43e9eba52 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -10,7 +10,7 @@ // Constants //**************************************** -const uint8_t peerBroadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +const uint8_t espnowBroadcastAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; //**************************************** // Types @@ -53,16 +53,16 @@ esp_err_t espNowAddPeer(const uint8_t * peerMac) if (result != ESP_OK) { systemPrintf("ERROR: Failed to add ESP-NOW peer %02x:%02x:%02x:%02x:%02x:%02x, result: %d\r\n", - peerBroadcast[0], peerBroadcast[1], - peerBroadcast[2], peerBroadcast[3], - peerBroadcast[4], peerBroadcast[5], + espnowBroadcastAddr[0], espnowBroadcastAddr[1], + espnowBroadcastAddr[2], espnowBroadcastAddr[3], + espnowBroadcastAddr[4], espnowBroadcastAddr[5], result); } else if (espNowDebug) systemPrintf("Added ESP-NOW peer %02x:%02x:%02x:%02x:%02x:%02x\r\n", - peerBroadcast[0], peerBroadcast[1], - peerBroadcast[2], peerBroadcast[3], - peerBroadcast[4], peerBroadcast[5]); + espnowBroadcastAddr[0], espnowBroadcastAddr[1], + espnowBroadcastAddr[2], espnowBroadcastAddr[3], + espnowBroadcastAddr[4], espnowBroadcastAddr[5]); return result; } @@ -369,11 +369,11 @@ bool espNowStop() // 4. Remove all peers by calling espnowRemovePeer if (espNowDebug && espNowVerbose) systemPrintf("Calling esp_now_is_peer_exist\r\n"); - if (esp_now_is_peer_exist(peerBroadcast)) + if (esp_now_is_peer_exist(espnowBroadcastAddr)) { if (espNowDebug && espNowVerbose) systemPrintf("Calling esp_now_del_peer\r\n"); - status = esp_now_del_peer(peerBroadcast); + status = esp_now_del_peer(espnowBroadcastAddr); if (status != ESP_OK) { systemPrintf("ERROR: Failed to delete broadcast peer, status: %d\r\n", status); From f289288753993de7866fa9f45e2defba237dfd67 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 31 Jan 2025 10:16:14 -1000 Subject: [PATCH 198/276] ESP-NOW: Add module comment --- Firmware/RTK_Everywhere/ESPNOW.ino | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index 43e9eba52..c4ff13bc4 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -2,6 +2,18 @@ ESPNOW.ino Handle the ESP-NOW events + Use ESP NOW protocol to transmit RTCM between RTK Products via 2.4GHz + + How pairing works: + 1. Device enters pairing mode + 2. Device adds the broadcast MAC (all 0xFFs) as peer + 3. Device waits for incoming pairing packet from remote + 4. If valid pairing packet received, add peer, immediately transmit a pairing packet to that peer and exit. + + ESP NOW is bare metal, there is no guaranteed packet delivery. For RTCM byte transmissions using ESP NOW: + We don't care about dropped packets or packets out of order. The ZED will check the integrity of the RTCM packet. + We don't care if the ESP NOW packet is corrupt or not. RTCM has its own CRC. RTK needs valid RTCM once every + few seconds so a single dropped frame is not critical. **********************************************************************/ #ifdef COMPILE_ESPNOW From 0790106bfe0cdde60707383c8d75f2d39fe3aa49 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 31 Jan 2025 10:20:10 -1000 Subject: [PATCH 199/276] ESP-NOW: Rename espNowDebug to settings.debugEspNow --- Firmware/RTK_Everywhere/ESPNOW.ino | 41 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index c4ff13bc4..62898830a 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -41,7 +41,6 @@ typedef struct _ESP_NOW_PAIR_MESSAGE // Locals //**************************************** -bool espNowDebug; bool espNowDisplay; ESPNOWState espNowState; bool espNowVerbose; @@ -59,7 +58,7 @@ esp_err_t espNowAddPeer(const uint8_t * peerMac) peerInfo.encrypt = false; // Add the peer - if (espNowDebug) + if (settings.debugEspNow) systemPrintf("Calling esp_now_add_peer\r\n"); esp_err_t result = esp_now_add_peer(&peerInfo); if (result != ESP_OK) @@ -70,7 +69,7 @@ esp_err_t espNowAddPeer(const uint8_t * peerMac) espnowBroadcastAddr[4], espnowBroadcastAddr[5], result); } - else if (espNowDebug) + else if (settings.debugEspNow) systemPrintf("Added ESP-NOW peer %02x:%02x:%02x:%02x:%02x:%02x\r\n", espnowBroadcastAddr[0], espnowBroadcastAddr[1], espnowBroadcastAddr[2], espnowBroadcastAddr[3], @@ -239,7 +238,7 @@ void espNowSetState(ESPNOWState newState) const char * oldName; char oLine[80]; - if (espNowDebug == true) + if (settings.debugEspNow == true) { // Get the old state name if (espNowState < ESPNOW_MAX) @@ -281,7 +280,7 @@ bool espNowStart() started = false; // 5. Call esp_now_init - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("Calling esp_now_init\r\n"); status = esp_now_init(); if (status != ESP_OK) @@ -291,7 +290,7 @@ bool espNowStart() } // 9. Set receive callback [esp_now_register_recv_cb(espnowOnDataReceived)] - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("Calling esp_now_register_recv_cb\r\n"); status = esp_now_register_recv_cb(espNowRxHandler); if (status != ESP_OK) @@ -302,7 +301,7 @@ bool espNowStart() // 10. Add peers from settings // i. Set ESP-NOW state, call espNowSetState(ESPNOW_PAIRED) - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("Calling espNowSetState\r\n"); espNowSetState(ESPNOW_PAIRED); @@ -310,12 +309,12 @@ bool espNowStart() for (index = 0; index < ESPNOW_MAX_PEERS; index++) { // a. Determine if peer exists, call esp_now_is_peer_exist - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("Calling esp_now_is_peer_exist\r\n"); if (esp_now_is_peer_exist(settings.espnowPeers[index]) == false) { // b. Add peer if necessary, call espnowAddPeer - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("Calling espNowAddPeer\r\n"); status = espNowAddPeer(&settings.espnowPeers[index][0]); if (status != ESP_OK) @@ -338,7 +337,7 @@ bool espNowStart() } // ESP-NOW has started successfully - if (espNowDebug) + if (settings.debugEspNow) systemPrintf("ESP-NOW online\r\n"); started = true; @@ -364,7 +363,7 @@ bool espNowStop() stopped = false; // 3. esp_now_unregister_recv_cb() - if (espNowDebug) + if (settings.debugEspNow) systemPrintf("Calling esp_now_unregister_recv_cb\r\n"); status = esp_now_unregister_recv_cb(); if (status != ESP_OK) @@ -372,18 +371,18 @@ bool espNowStop() systemPrintf("ERROR: Failed to clear ESP_NOW RX callback, status: %d\r\n", status); break; } - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("ESP-NOW: RX callback removed\r\n"); if (espNowDisplay) systemPrintf("ESP-NOW offline\r\n"); // 4. Remove all peers by calling espnowRemovePeer - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("Calling esp_now_is_peer_exist\r\n"); if (esp_now_is_peer_exist(espnowBroadcastAddr)) { - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("Calling esp_now_del_peer\r\n"); status = esp_now_del_peer(espnowBroadcastAddr); if (status != ESP_OK) @@ -391,7 +390,7 @@ bool espNowStop() systemPrintf("ERROR: Failed to delete broadcast peer, status: %d\r\n", status); break; } - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("ESP-NOW removed broadcast peer\r\n"); } @@ -401,14 +400,14 @@ bool espNowStop() esp_now_peer_info_t peerInfo; // Get the next unicast peer - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("Calling esp_now_fetch_peer\r\n"); status = esp_now_fetch_peer(true, &peerInfo); if (status != ESP_OK) break; // Remove the unicast peer - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("Calling esp_now_del_peer\r\n"); status = esp_now_del_peer(peerInfo.peer_addr); if (status != ESP_OK) @@ -420,7 +419,7 @@ bool espNowStop() status); break; } - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("ESP-NOW removed peer %02x:%02x:%02x:%02x:%02x:%02x\r\n", peerInfo.peer_addr[0], peerInfo.peer_addr[1], peerInfo.peer_addr[2], peerInfo.peer_addr[3], @@ -433,7 +432,7 @@ bool espNowStop() } // Get the number of peers - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) { systemPrintf("Calling esp_now_get_peer_num\r\n"); status = esp_now_get_peer_num(&peerCount); @@ -449,7 +448,7 @@ bool espNowStop() espNowSetState(ESPNOW_OFF); // 9. Turn off ESP-NOW. call esp_now_deinit - if (espNowDebug && espNowVerbose) + if (settings.debugEspNow && espNowVerbose) systemPrintf("Calling esp_now_deinit\r\n"); status = esp_now_deinit(); if (status != ESP_OK) @@ -461,7 +460,7 @@ bool espNowStop() // 11. Restart WiFi if necessary // ESP-NOW has stopped successfully - if (espNowDebug) + if (settings.debugEspNow) systemPrintf("ESP-NOW stopped\r\n"); stopped = true; } while (0); From 432222cfd88054bced9eb241d0a819a27bffef85 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 31 Jan 2025 10:25:29 -1000 Subject: [PATCH 200/276] ESP-NOW: Remove espNowVerbose --- Firmware/RTK_Everywhere/ESPNOW.ino | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index 62898830a..fb60541bb 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -43,7 +43,6 @@ typedef struct _ESP_NOW_PAIR_MESSAGE bool espNowDisplay; ESPNOWState espNowState; -bool espNowVerbose; //********************************************************************* // Add a peer to the ESP-NOW network @@ -280,7 +279,7 @@ bool espNowStart() started = false; // 5. Call esp_now_init - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("Calling esp_now_init\r\n"); status = esp_now_init(); if (status != ESP_OK) @@ -290,7 +289,7 @@ bool espNowStart() } // 9. Set receive callback [esp_now_register_recv_cb(espnowOnDataReceived)] - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("Calling esp_now_register_recv_cb\r\n"); status = esp_now_register_recv_cb(espNowRxHandler); if (status != ESP_OK) @@ -301,7 +300,7 @@ bool espNowStart() // 10. Add peers from settings // i. Set ESP-NOW state, call espNowSetState(ESPNOW_PAIRED) - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("Calling espNowSetState\r\n"); espNowSetState(ESPNOW_PAIRED); @@ -309,12 +308,12 @@ bool espNowStart() for (index = 0; index < ESPNOW_MAX_PEERS; index++) { // a. Determine if peer exists, call esp_now_is_peer_exist - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("Calling esp_now_is_peer_exist\r\n"); if (esp_now_is_peer_exist(settings.espnowPeers[index]) == false) { // b. Add peer if necessary, call espnowAddPeer - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("Calling espNowAddPeer\r\n"); status = espNowAddPeer(&settings.espnowPeers[index][0]); if (status != ESP_OK) @@ -371,18 +370,18 @@ bool espNowStop() systemPrintf("ERROR: Failed to clear ESP_NOW RX callback, status: %d\r\n", status); break; } - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("ESP-NOW: RX callback removed\r\n"); if (espNowDisplay) systemPrintf("ESP-NOW offline\r\n"); // 4. Remove all peers by calling espnowRemovePeer - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("Calling esp_now_is_peer_exist\r\n"); if (esp_now_is_peer_exist(espnowBroadcastAddr)) { - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("Calling esp_now_del_peer\r\n"); status = esp_now_del_peer(espnowBroadcastAddr); if (status != ESP_OK) @@ -390,7 +389,7 @@ bool espNowStop() systemPrintf("ERROR: Failed to delete broadcast peer, status: %d\r\n", status); break; } - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("ESP-NOW removed broadcast peer\r\n"); } @@ -400,14 +399,14 @@ bool espNowStop() esp_now_peer_info_t peerInfo; // Get the next unicast peer - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("Calling esp_now_fetch_peer\r\n"); status = esp_now_fetch_peer(true, &peerInfo); if (status != ESP_OK) break; // Remove the unicast peer - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("Calling esp_now_del_peer\r\n"); status = esp_now_del_peer(peerInfo.peer_addr); if (status != ESP_OK) @@ -419,7 +418,7 @@ bool espNowStop() status); break; } - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("ESP-NOW removed peer %02x:%02x:%02x:%02x:%02x:%02x\r\n", peerInfo.peer_addr[0], peerInfo.peer_addr[1], peerInfo.peer_addr[2], peerInfo.peer_addr[3], @@ -432,7 +431,7 @@ bool espNowStop() } // Get the number of peers - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) { systemPrintf("Calling esp_now_get_peer_num\r\n"); status = esp_now_get_peer_num(&peerCount); @@ -448,7 +447,7 @@ bool espNowStop() espNowSetState(ESPNOW_OFF); // 9. Turn off ESP-NOW. call esp_now_deinit - if (settings.debugEspNow && espNowVerbose) + if (settings.debugEspNow) systemPrintf("Calling esp_now_deinit\r\n"); status = esp_now_deinit(); if (status != ESP_OK) From c8a1b3b27f2a381d6e2150688499effcd8f08cd7 Mon Sep 17 00:00:00 2001 From: Lee Leahy Date: Fri, 31 Jan 2025 10:28:13 -1000 Subject: [PATCH 201/276] ESP-NOW: Replace espNowDisplay with settings.debugEspNow --- Firmware/RTK_Everywhere/ESPNOW.ino | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/Firmware/RTK_Everywhere/ESPNOW.ino b/Firmware/RTK_Everywhere/ESPNOW.ino index fb60541bb..e09bf0dc0 100644 --- a/Firmware/RTK_Everywhere/ESPNOW.ino +++ b/Firmware/RTK_Everywhere/ESPNOW.ino @@ -41,7 +41,6 @@ typedef struct _ESP_NOW_PAIR_MESSAGE // Locals //**************************************** -bool espNowDisplay; ESPNOWState espNowState; //********************************************************************* @@ -207,16 +206,13 @@ void espNowRxHandler(const esp_now_recv_info *mac, // else Pair CRC failed } } - else - { - if (espNowDisplay == true) - systemPrintf("*** ESP-NOW: RX %02x:%02x:%02x:%02x:%02x:%02x --> %02x:%02x:%02x:%02x:%02x:%02x, %d bytes, rssi: %d\r\n", - mac->src_addr[0], mac->src_addr[1], mac->src_addr[2], - mac->src_addr[3], mac->src_addr[4], mac->src_addr[5], - mac->des_addr[0], mac->des_addr[1], mac->des_addr[2], - mac->des_addr[3], mac->des_addr[4], mac->des_addr[5], - len, packetRSSI); - } + else if (settings.debugEspNow) + systemPrintf("*** ESP-NOW: RX %02x:%02x:%02x:%02x:%02x:%02x --> %02x:%02x:%02x:%02x:%02x:%02x, %d bytes, rssi: %d\r\n", + mac->src_addr[0], mac->src_addr[1], mac->src_addr[2], + mac->src_addr[3], mac->src_addr[4], mac->src_addr[5], + mac->des_addr[0], mac->des_addr[1], mac->des_addr[2], + mac->des_addr[3], mac->des_addr[4], mac->des_addr[5], + len, packetRSSI); } //********************************************************************* @@ -373,7 +369,7 @@ bool espNowStop() if (settings.debugEspNow) systemPrintf("ESP-NOW: RX callback removed\r\n"); - if (espNowDisplay) + if (settings.debugEspNow) systemPrintf("ESP-NOW offline\r\n"); // 4. Remove all peers by calling espnowRemovePeer From 093751abf914d8baf7ae9b9b959c4a6ed9b003fd Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 3 Feb 2025 18:05:50 +0000 Subject: [PATCH 202/276] Add support for mosaic-X5 ChannelStatus SV tracking --- Firmware/RTK_Everywhere/GNSS.h | 2 +- Firmware/RTK_Everywhere/GNSS_Mosaic.h | 12 +++ Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 104 +++++++++++++++++++++++- 3 files changed, 114 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS.h b/Firmware/RTK_Everywhere/GNSS.h index ebb6d3bdb..990ab16d9 100644 --- a/Firmware/RTK_Everywhere/GNSS.h +++ b/Firmware/RTK_Everywhere/GNSS.h @@ -54,7 +54,7 @@ class GNSS public: // Constructor - GNSS() : _leapSeconds(18), _pvtArrivalMillis(0), _pvtUpdated(0) + GNSS() : _leapSeconds(18), _pvtArrivalMillis(0), _pvtUpdated(0), _satellitesInView(0) { } diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.h b/Firmware/RTK_Everywhere/GNSS_Mosaic.h index 216ae7a25..9f24a80d9 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.h +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.h @@ -18,6 +18,7 @@ typedef struct { const mosaicExpectedID mosaicExpectedIDs[] = { { 4007, true, 96, "PVTGeodetic" }, + { 4013, false, 0, "ChannelStatus" }, { 4090, false, 0, "InputLink" }, { 4097, false, 0, "EncapsulatedOutput" }, { 5914, true, 24, "ReceiverTime" }, @@ -46,6 +47,10 @@ const mosaicExpectedID mosaicExpectedIDs[] = { // This indicates if RTCM corrections are being received - on COM2 #define MOSAIC_SBF_INPUTLINK_STREAM (MOSAIC_SBF_EXTEVENT_STREAM + 1) +// Output SBF ChannelStatus messages on this stream - on COM1 only +// These provide the count of satellites being tracked +#define MOSAIC_SBF_CHANNELSTATUS_STREAM (MOSAIC_SBF_INPUTLINK_STREAM + 1) + // TODO: allow the user to define their own SBF stream for logging to DSK1 - through the menu / web config // But, in the interim, the user can define their own SBF stream (>= Stream3) via the X5 web page over USB-C // The updated configuration can be saved by entering and exiting the main menu, or by: @@ -575,6 +580,8 @@ class GNSS_MOSAIC : GNSS float _latStdDev; float _lonStdDev; bool _receiverSetupSeen; + std::vector svInTracking; + //std::vector svInPVT; // Constructor GNSS_MOSAIC() : _determiningFixedPosition(true), _clkBias_ms(0), @@ -582,6 +589,8 @@ class GNSS_MOSAIC : GNSS _radioExtBytesReceived_millis(0), GNSS() { + svInTracking.clear(); + //svInPVT.clear(); } // If we have decryption keys, configure module @@ -1016,6 +1025,9 @@ class GNSS_MOSAIC : GNSS // Save the data from the SBF Block 4007 void storeBlock4007(SEMP_PARSE_STATE *parse); + // Save the data from the SBF Block 4013 + void storeBlock4013(SEMP_PARSE_STATE *parse); + // Save the data from the SBF Block 4090 void storeBlock4090(SEMP_PARSE_STATE *parse); diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 606de3422..de3dc5e02 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -579,6 +579,11 @@ bool GNSS_MOSAIC::configureOnce() setting = String("sso,Stream" + String(MOSAIC_SBF_INPUTLINK_STREAM) + ",COM1,InputLink,sec1\n\r"); response &= sendWithResponse(setting, "SBFOutput"); + // Output SBF ChannelStatus on its own stream - at 0.5Hz - on COM1 only + // OnChange is too often. The message is typically 1000 bytes in size. + setting = String("sso,Stream" + String(MOSAIC_SBF_CHANNELSTATUS_STREAM) + ",COM1,ChannelStatus,sec2\n\r"); + response &= sendWithResponse(setting, "SBFOutput"); + response &= setElevation(settings.minElev); response &= setMinCnoRadio(settings.minCNO); @@ -2367,9 +2372,12 @@ void GNSS_MOSAIC::storeBlock4007(SEMP_PARSE_STATE *parse) _longitude = sempSbfGetF8(parse, 24) * 180.0 / PI; _altitude = (float)sempSbfGetF8(parse, 32); _horizontalAccuracy = ((float)sempSbfGetU2(parse, 90)) / 100.0; // Convert from cm to m - _satellitesInView = sempSbfGetU1(parse, 74); - if (_satellitesInView == 255) // 255 indicates "Do-Not-Use" - _satellitesInView = 0; + + // NrSV is the total number of satellites used in the PVT computation. + //_satellitesInView = sempSbfGetU1(parse, 74); + //if (_satellitesInView == 255) // 255 indicates "Do-Not-Use" + // _satellitesInView = 0; + _fixType = sempSbfGetU1(parse, 14) & 0x0F; _determiningFixedPosition = (sempSbfGetU1(parse, 14) >> 6) & 0x01; _clkBias_ms = sempSbfGetF8(parse, 60); @@ -2377,6 +2385,92 @@ void GNSS_MOSAIC::storeBlock4007(SEMP_PARSE_STATE *parse) _pvtUpdated = true; } +//---------------------------------------- +// Save the data from the SBF Block 4013 +//---------------------------------------- +void GNSS_MOSAIC::storeBlock4013(SEMP_PARSE_STATE *parse) +{ + uint16_t N = (uint16_t)sempSbfGetU1(parse, 14); + uint16_t SB1Length = (uint16_t)sempSbfGetU1(parse, 15); + uint16_t SB2Length = (uint16_t)sempSbfGetU1(parse, 16); + uint16_t ChannelInfoBytes = 0; + for (uint16_t i = 0; i < N; i++) + { + uint8_t SVID = sempSbfGetU1(parse, 20 + ChannelInfoBytes + 0); + + uint16_t N2 = (uint16_t)sempSbfGetU1(parse, 20 + ChannelInfoBytes + 9); + + for (uint16_t j = 0; j < N2; j++) + { + uint16_t TrackingStatus = sempSbfGetU2(parse, 20 + ChannelInfoBytes + SB1Length + (j * SB2Length) + 2); + + bool Tracking = false; + for (uint16_t shift = 0; shift < 16; shift += 2) // Step through each 2-bit status field + { + if ((TrackingStatus & (0x0003 << shift)) == (0x0003 << shift)) // 3 : Tracking + { + Tracking = true; + } + } + + if (Tracking) + { + // SV is being tracked. If it is not in svInTracking, add it + std::vector::iterator pos = + std::find(svInTracking.begin(), svInTracking.end(), SVID); + if (pos == svInTracking.end()) + svInTracking.push_back(SVID); + } + else + { + // SV is not being tracked. If it is in svInTracking, remove it + std::vector::iterator pos = + std::find(svInTracking.begin(), svInTracking.end(), SVID); + if (pos != svInTracking.end()) + svInTracking.erase(pos); + } + + // uint16_t PVTStatus = sempSbfGetU2(parse, 20 + ChannelInfoBytes + SB1Length + (j * SB2Length) + 4); + + // bool Used = false; + // for (uint16_t shift = 0; shift < 16; shift += 2) // Step through each 2-bit status field + // { + // if ((PVTStatus & (0x0003 << shift)) == (0x0002 << shift)) // 2 : Used + // { + // Used = true; + // } + // } + + // if (Used) + // { + // // SV is being used for PVT. If it is not in svInPVT, add it + // std::vector::iterator pos = + // std::find(svInPVT.begin(), svInPVT.end(), SVID); + // if (pos == svInPVT.end()) + // svInPVT.push_back(SVID); + // } + // else + // { + // // SV is not being used for PVT. If it is in svInPVT, remove it + // std::vector::iterator pos = + // std::find(svInPVT.begin(), svInPVT.end(), SVID); + // if (pos != svInPVT.end()) + // svInPVT.erase(pos); + // } + + } + + ChannelInfoBytes += SB1Length + (N2 * SB2Length); + } + + _satellitesInView = (uint8_t)std::distance(svInTracking.begin(), svInTracking.end()); + + //uint8_t _inPVT = (uint8_t)std::distance(svInPVT.begin(), svInPVT.end()); + + //systemPrintf("%d %d %d %d %d %d\r\n", N, SB1Length, SB2Length, ChannelInfoBytes, _satellitesInView, _inPVT); + +} + //---------------------------------------- // Save the data from the SBF Block 4090 //---------------------------------------- @@ -2726,6 +2820,10 @@ void processUart1SBF(SEMP_PARSE_STATE *parse, uint16_t type) if (sempSbfGetBlockNumber(parse) == 4007) mosaic->storeBlock4007(parse); + // If this is ChannelStatus, extract some data + if (sempSbfGetBlockNumber(parse) == 4013) + mosaic->storeBlock4013(parse); + // If this is InputLink, extract some data if (sempSbfGetBlockNumber(parse) == 4090) mosaic->storeBlock4090(parse); From 68bc6587b6bd50e213b558221af73a4c0c966be3 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 3 Feb 2025 18:16:04 +0000 Subject: [PATCH 203/276] Better InPVT diagnostics --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index de3dc5e02..d0ae23200 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2465,9 +2465,11 @@ void GNSS_MOSAIC::storeBlock4013(SEMP_PARSE_STATE *parse) _satellitesInView = (uint8_t)std::distance(svInTracking.begin(), svInTracking.end()); - //uint8_t _inPVT = (uint8_t)std::distance(svInPVT.begin(), svInPVT.end()); - - //systemPrintf("%d %d %d %d %d %d\r\n", N, SB1Length, SB2Length, ChannelInfoBytes, _satellitesInView, _inPVT); + // if (settings.debugCorrections && !inMainMenu) + // { + // uint8_t _inPVT = (uint8_t)std::distance(svInPVT.begin(), svInPVT.end()); + // systemPrintf("ChannelStatus: InTracking %d, InPVT %d\r\n", _satellitesInView, _inPVT); + // } } From 0d72b71daf0fc588ff484dbad6d7c4858592da64 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 3 Feb 2025 18:26:46 +0000 Subject: [PATCH 204/276] Correct debug print (commented) --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index d0ae23200..0eaefb510 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2465,7 +2465,7 @@ void GNSS_MOSAIC::storeBlock4013(SEMP_PARSE_STATE *parse) _satellitesInView = (uint8_t)std::distance(svInTracking.begin(), svInTracking.end()); - // if (settings.debugCorrections && !inMainMenu) + // if (settings.debugGnss && !inMainMenu) // { // uint8_t _inPVT = (uint8_t)std::distance(svInPVT.begin(), svInPVT.end()); // systemPrintf("ChannelStatus: InTracking %d, InPVT %d\r\n", _satellitesInView, _inPVT); From abc0afa4eab305d7e16c34240cf5379bc9a7e548 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 4 Feb 2025 13:24:23 +0000 Subject: [PATCH 205/276] mosaic-X5 SD : Replace ldi,DSK1 with exeSBFOnce,,DiskStatus --- Firmware/RTK_Everywhere/GNSS_Mosaic.h | 5 +- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 112 ++++++++++++++++++++---- 2 files changed, 99 insertions(+), 18 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.h b/Firmware/RTK_Everywhere/GNSS_Mosaic.h index 9f24a80d9..6b13c4222 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.h +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.h @@ -580,13 +580,14 @@ class GNSS_MOSAIC : GNSS float _latStdDev; float _lonStdDev; bool _receiverSetupSeen; + bool _diskStatusSeen; std::vector svInTracking; //std::vector svInPVT; // Constructor GNSS_MOSAIC() : _determiningFixedPosition(true), _clkBias_ms(0), _latStdDev(999.9), _lonStdDev(999.9), _receiverSetupSeen(false), - _radioExtBytesReceived_millis(0), + _radioExtBytesReceived_millis(0), _diskStatusSeen(false), GNSS() { svInTracking.clear(); @@ -1051,6 +1052,8 @@ class GNSS_MOSAIC : GNSS bool updateSD(); void waitSBFReceiverSetup(unsigned long timeout); + + void waitSBFDiskStatus(unsigned long timeout); }; #endif // __GNSS_MOSAIC_H__ diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 0eaefb510..dc2c29fb9 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2648,24 +2648,37 @@ bool GNSS_MOSAIC::updateSD() if (!previousCardPresent) // If the card is not present, skip the list disk info return false; - char diskInfo[200]; - bool response = - sendAndWaitForIdle("ldi,DSK1\n\r", "DiskInfo", 1000, 25, &diskInfo[0], sizeof(diskInfo), false); // No debug - if (response) - { - char *ptr = strstr(diskInfo, " total=\""); - if (ptr == nullptr) - return false; - ptr += strlen(" total=\""); - sscanf(ptr, "%llu\"", &sdCardSize); - ptr = strstr(ptr, " free=\""); - if (ptr == nullptr) - return false; - ptr += strlen(" free=\""); - sscanf(ptr, "%llu\"", &sdFreeSpace); - } + // Use ldi,DSK1 to read the disk information + // This is inefficient as the DiskInfo lists all files on the SD card + // exeSBFOnce DiskStatus is much more efficient + // + // char diskInfo[200]; + // bool response = + // sendAndWaitForIdle("ldi,DSK1\n\r", "DiskInfo", 1000, 25, &diskInfo[0], sizeof(diskInfo), false); // No debug + // if (response) + // { + // char *ptr = strstr(diskInfo, " total=\""); + // if (ptr == nullptr) + // return false; + // ptr += strlen(" total=\""); + // sscanf(ptr, "%llu\"", &sdCardSize); + // ptr = strstr(ptr, " free=\""); + // if (ptr == nullptr) + // return false; + // ptr += strlen(" free=\""); + // sscanf(ptr, "%llu\"", &sdFreeSpace); + // } - return response; + _diskStatusSeen = false; + + // Request the DiskStatus SBF block using a esoc (exeSBFOnce) command on COM4 + String request = "esoc,COM4,DiskStatus\n\r"; + serial2GNSS->write(request.c_str(), request.length()); + + // Wait for up to 1 second for the DiskStatus + waitSBFDiskStatus(1000); + + return _diskStatusSeen; } //---------------------------------------- @@ -2702,6 +2715,40 @@ void GNSS_MOSAIC::waitSBFReceiverSetup(unsigned long timeout) sempStopParser(&sbfParse); } +//---------------------------------------- +void GNSS_MOSAIC::waitSBFDiskStatus(unsigned long timeout) +{ + SEMP_PARSE_ROUTINE const sbfParserTable[] = {sempSbfPreamble}; + const int sbfParserCount = sizeof(sbfParserTable) / sizeof(sbfParserTable[0]); + const char *const sbfParserNames[] = { + "SBF", + }; + const int sbfParserNameCount = sizeof(sbfParserNames) / sizeof(sbfParserNames[0]); + + SEMP_PARSE_STATE *sbfParse; + + // Initialize the SBF parser for the mosaic-X5 + sbfParse = sempBeginParser(sbfParserTable, sbfParserCount, sbfParserNames, sbfParserNameCount, + 0, // Scratchpad bytes + 500, // Buffer length + processSBFDiskStatus, // eom Call Back + "Sbf"); // Parser Name + if (!sbfParse) + reportFatalError("Failed to initialize the SBF parser"); + + unsigned long startTime = millis(); + while ((millis() < (startTime + timeout)) && (_diskStatusSeen == false)) + { + if (serial2GNSS->available()) + { + // Update the parser state based on the incoming byte + sempParseNextByte(sbfParse, serial2GNSS->read()); + } + } + + sempStopParser(&sbfParse); +} + //========================================================================== // Parser support routines //========================================================================== @@ -2798,6 +2845,37 @@ void processSBFReceiverSetup(SEMP_PARSE_STATE *parse, uint16_t type) } } +//---------------------------------------- +void processSBFDiskStatus(SEMP_PARSE_STATE *parse, uint16_t type) +{ + // If this is DiskStatus, extract some data + if (sempSbfGetBlockNumber(parse) == 4059) + { + if (sempSbfGetU1(parse, 14) < 1) // Check N is at least 1 + return; + + uint64_t diskUsageMSB = sempSbfGetU2(parse, 20 + 2); // DiskUsageMSB + uint64_t diskUsageLSB = sempSbfGetU4(parse, 20 + 4); // DiskUsageLSB + + if ((diskUsageMSB == 65535) && (diskUsageLSB == 4294967295)) + return; + + uint64_t diskSizeMB = sempSbfGetU4(parse, 20 + 8); // DiskSize in megabytes + + if (diskSizeMB == 0) + return; + + uint64_t diskUsage = (diskUsageMSB * 4294967296) + diskUsageLSB; + + sdCardSize = diskSizeMB * 1048576; // Convert to bytes + + sdFreeSpace = sdCardSize - diskUsage; + + GNSS_MOSAIC *mosaic = (GNSS_MOSAIC *)gnss; + mosaic->_diskStatusSeen = true; + } +} + //---------------------------------------- // Call back from within the SBF parser, for end of valid message // Process a complete message incoming from parser From 1c4ea7a5c286be83526aa428c75b61a0b7ea54d5 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 4 Feb 2025 13:26:32 +0000 Subject: [PATCH 206/276] Update comment --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index dc2c29fb9..0f35eb3d3 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2668,6 +2668,7 @@ bool GNSS_MOSAIC::updateSD() // ptr += strlen(" free=\""); // sscanf(ptr, "%llu\"", &sdFreeSpace); // } + // return response; _diskStatusSeen = false; From 6368f50581bea18b44c9042eb356dc48c5af423d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 4 Feb 2025 13:35:17 +0000 Subject: [PATCH 207/276] mosaic-X5 : allow more retries when removing SD card --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 0f35eb3d3..cb9061120 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2627,7 +2627,11 @@ bool GNSS_MOSAIC::updateSD() // Allow many retries int retries = 0; - int retryLimit = 20; + int retryLimit = 30; + + // If the card has been removed, the soft reset takes extra time. Allow more retries + if (!previousCardPresent) + retryLimit = 40; // Set COM4 to: CMD input (only), SBF output (only) while (!sendWithResponse("sdio,COM4,CMD,SBF\n\r", "DataInOut")) From 79cfb30fff5eef9c2bbf34042b393413f8a7e11e Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 4 Feb 2025 14:32:55 +0000 Subject: [PATCH 208/276] mosaic-X5 : improve logIncreasing checks If the user inserts a new SD card, we need to be able to recover from sdFreeSpace > previousFreeSpace --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 38 ++++++++++++++++++------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index cb9061120..3ddb64474 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2576,21 +2576,39 @@ void GNSS_MOSAIC::update() static uint64_t previousFreeSpace = 0; if (millis() > (sdCardSizeLastCheck + sdCardSizeCheckInterval)) { - updateSD(); - - if (previousFreeSpace == 0) - previousFreeSpace = sdFreeSpace; - if (sdFreeSpace < previousFreeSpace) + if (updateSD()) // updateSD will only return true if a card is inserted and the card size has been read { - previousFreeSpace = sdFreeSpace; - logIncreasing = true; - sdCardLastFreeChange = millis(); + // If previousFreeSpace hasn't been initialized, initialize it + if (previousFreeSpace == 0) + previousFreeSpace = sdFreeSpace; + + if (sdFreeSpace < previousFreeSpace) + { + // The free space is decreasing, so set logIncreasing to true + previousFreeSpace = sdFreeSpace; + logIncreasing = true; + sdCardLastFreeChange = millis(); + } + else if (sdFreeSpace == previousFreeSpace) + { + // The free space has not changed + // X5 is slow to update free. Seems to be about every ~20s? + // So only set logIncreasing to false after 30s + if (millis() > (sdCardLastFreeChange + 30000)) + logIncreasing = false; + } + else // if (sdFreeSpace > previousFreeSpace) + { + // User must have inserted a new SD card? + previousFreeSpace = sdFreeSpace; + } } else { - if (millis() > (sdCardLastFreeChange + 30000)) // X5 is slow to update free. Seems to be about every ~20s? - logIncreasing = false; + // updateSD failed. So sdFreeSpace can't be trusted and the log cannot be increasing + logIncreasing = false; } + sdCardSizeLastCheck = millis(); } From a4dca6b9a392d0537d0c95f0e29b160860a30c88 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 4 Feb 2025 16:56:15 +0000 Subject: [PATCH 209/276] mosaic-X5 : better disk use reporting using DiskStatus --- Firmware/RTK_Everywhere/GNSS_Mosaic.h | 15 ++- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 158 +++++++----------------- 2 files changed, 54 insertions(+), 119 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.h b/Firmware/RTK_Everywhere/GNSS_Mosaic.h index 6b13c4222..62be6a599 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.h +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.h @@ -19,6 +19,7 @@ typedef struct { const mosaicExpectedID mosaicExpectedIDs[] = { { 4007, true, 96, "PVTGeodetic" }, { 4013, false, 0, "ChannelStatus" }, + { 4059, false, 0, "DiskStatus" }, { 4090, false, 0, "InputLink" }, { 4097, false, 0, "EncapsulatedOutput" }, { 5914, true, 24, "ReceiverTime" }, @@ -47,9 +48,10 @@ const mosaicExpectedID mosaicExpectedIDs[] = { // This indicates if RTCM corrections are being received - on COM2 #define MOSAIC_SBF_INPUTLINK_STREAM (MOSAIC_SBF_EXTEVENT_STREAM + 1) -// Output SBF ChannelStatus messages on this stream - on COM1 only -// These provide the count of satellites being tracked -#define MOSAIC_SBF_CHANNELSTATUS_STREAM (MOSAIC_SBF_INPUTLINK_STREAM + 1) +// Output SBF ChannelStatus and DiskStatus messages on this stream - on COM1 only +// ChannelStatus provides the count of satellites being tracked +// DiskStatus provides the disk usage +#define MOSAIC_SBF_STATUS_STREAM (MOSAIC_SBF_INPUTLINK_STREAM + 1) // TODO: allow the user to define their own SBF stream for logging to DSK1 - through the menu / web config // But, in the interim, the user can define their own SBF stream (>= Stream3) via the X5 web page over USB-C @@ -1029,6 +1031,9 @@ class GNSS_MOSAIC : GNSS // Save the data from the SBF Block 4013 void storeBlock4013(SEMP_PARSE_STATE *parse); + // Save the data from the SBF Block 4059 + void storeBlock4059(SEMP_PARSE_STATE *parse); + // Save the data from the SBF Block 4090 void storeBlock4090(SEMP_PARSE_STATE *parse); @@ -1049,11 +1054,9 @@ class GNSS_MOSAIC : GNSS // Poll routine to update the GNSS state void update(); - bool updateSD(); + void updateSD(); void waitSBFReceiverSetup(unsigned long timeout); - - void waitSBFDiskStatus(unsigned long timeout); }; #endif // __GNSS_MOSAIC_H__ diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 3ddb64474..21ed495a6 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -579,9 +579,10 @@ bool GNSS_MOSAIC::configureOnce() setting = String("sso,Stream" + String(MOSAIC_SBF_INPUTLINK_STREAM) + ",COM1,InputLink,sec1\n\r"); response &= sendWithResponse(setting, "SBFOutput"); - // Output SBF ChannelStatus on its own stream - at 0.5Hz - on COM1 only - // OnChange is too often. The message is typically 1000 bytes in size. - setting = String("sso,Stream" + String(MOSAIC_SBF_CHANNELSTATUS_STREAM) + ",COM1,ChannelStatus,sec2\n\r"); + // Output SBF ChannelStatus and DiskStatus on their own stream - at 0.5Hz - on COM1 only + // For ChannelStatus: OnChange is too often. The message is typically 1000 bytes in size. + // For DiskStatus: DiskUsage is slow to update. 0.5Hz is plenty fast enough. + setting = String("sso,Stream" + String(MOSAIC_SBF_STATUS_STREAM) + ",COM1,ChannelStatus+DiskStatus,sec2\n\r"); response &= sendWithResponse(setting, "SBFOutput"); response &= setElevation(settings.minElev); @@ -2473,6 +2474,37 @@ void GNSS_MOSAIC::storeBlock4013(SEMP_PARSE_STATE *parse) } +//---------------------------------------- +// Save the data from the SBF Block 4059 +//---------------------------------------- +void GNSS_MOSAIC::storeBlock4059(SEMP_PARSE_STATE *parse) +{ + if (sempSbfGetU1(parse, 14) < 1) // Check N is at least 1 + return; + + if (sempSbfGetU1(parse, 20 + 0) != 1) // Check DiskID is 1 + return; + + uint64_t diskUsageMSB = sempSbfGetU2(parse, 20 + 2); // DiskUsageMSB + uint64_t diskUsageLSB = sempSbfGetU4(parse, 20 + 4); // DiskUsageLSB + + if ((diskUsageMSB == 65535) && (diskUsageLSB == 4294967295)) // Do-Not-Use + return; + + uint64_t diskSizeMB = sempSbfGetU4(parse, 20 + 8); // DiskSize in megabytes + + if (diskSizeMB == 0) // Do-Not-Use + return; + + uint64_t diskUsage = (diskUsageMSB * 4294967296) + diskUsageLSB; + + sdCardSize = diskSizeMB * 1048576; // Convert to bytes + + sdFreeSpace = sdCardSize - diskUsage; + + _diskStatusSeen = true; +} + //---------------------------------------- // Save the data from the SBF Block 4090 //---------------------------------------- @@ -2576,7 +2608,9 @@ void GNSS_MOSAIC::update() static uint64_t previousFreeSpace = 0; if (millis() > (sdCardSizeLastCheck + sdCardSizeCheckInterval)) { - if (updateSD()) // updateSD will only return true if a card is inserted and the card size has been read + updateSD(); // Check if the card has been removed / inserted + + if (_diskStatusSeen) // Check if the DiskStatus SBF message has been processed { // If previousFreeSpace hasn't been initialized, initialize it if (previousFreeSpace == 0) @@ -2603,13 +2637,9 @@ void GNSS_MOSAIC::update() previousFreeSpace = sdFreeSpace; } } - else - { - // updateSD failed. So sdFreeSpace can't be trusted and the log cannot be increasing - logIncreasing = false; - } - sdCardSizeLastCheck = millis(); + sdCardSizeLastCheck = millis(); // Update the timer + _diskStatusSeen = false; // Clear the flag } // Update spartnCorrectionsReceived @@ -2624,7 +2654,7 @@ void GNSS_MOSAIC::update() } //---------------------------------------- -bool GNSS_MOSAIC::updateSD() +void GNSS_MOSAIC::updateSD() { // See comments in update() above // updateSD() is probably the best place to check if an SD card has been inserted / removed @@ -2663,45 +2693,8 @@ bool GNSS_MOSAIC::updateSD() if (retries == retryLimit) { systemPrintln("Soft reset failed!"); - return false; } } - - if (!previousCardPresent) // If the card is not present, skip the list disk info - return false; - - // Use ldi,DSK1 to read the disk information - // This is inefficient as the DiskInfo lists all files on the SD card - // exeSBFOnce DiskStatus is much more efficient - // - // char diskInfo[200]; - // bool response = - // sendAndWaitForIdle("ldi,DSK1\n\r", "DiskInfo", 1000, 25, &diskInfo[0], sizeof(diskInfo), false); // No debug - // if (response) - // { - // char *ptr = strstr(diskInfo, " total=\""); - // if (ptr == nullptr) - // return false; - // ptr += strlen(" total=\""); - // sscanf(ptr, "%llu\"", &sdCardSize); - // ptr = strstr(ptr, " free=\""); - // if (ptr == nullptr) - // return false; - // ptr += strlen(" free=\""); - // sscanf(ptr, "%llu\"", &sdFreeSpace); - // } - // return response; - - _diskStatusSeen = false; - - // Request the DiskStatus SBF block using a esoc (exeSBFOnce) command on COM4 - String request = "esoc,COM4,DiskStatus\n\r"; - serial2GNSS->write(request.c_str(), request.length()); - - // Wait for up to 1 second for the DiskStatus - waitSBFDiskStatus(1000); - - return _diskStatusSeen; } //---------------------------------------- @@ -2738,40 +2731,6 @@ void GNSS_MOSAIC::waitSBFReceiverSetup(unsigned long timeout) sempStopParser(&sbfParse); } -//---------------------------------------- -void GNSS_MOSAIC::waitSBFDiskStatus(unsigned long timeout) -{ - SEMP_PARSE_ROUTINE const sbfParserTable[] = {sempSbfPreamble}; - const int sbfParserCount = sizeof(sbfParserTable) / sizeof(sbfParserTable[0]); - const char *const sbfParserNames[] = { - "SBF", - }; - const int sbfParserNameCount = sizeof(sbfParserNames) / sizeof(sbfParserNames[0]); - - SEMP_PARSE_STATE *sbfParse; - - // Initialize the SBF parser for the mosaic-X5 - sbfParse = sempBeginParser(sbfParserTable, sbfParserCount, sbfParserNames, sbfParserNameCount, - 0, // Scratchpad bytes - 500, // Buffer length - processSBFDiskStatus, // eom Call Back - "Sbf"); // Parser Name - if (!sbfParse) - reportFatalError("Failed to initialize the SBF parser"); - - unsigned long startTime = millis(); - while ((millis() < (startTime + timeout)) && (_diskStatusSeen == false)) - { - if (serial2GNSS->available()) - { - // Update the parser state based on the incoming byte - sempParseNextByte(sbfParse, serial2GNSS->read()); - } - } - - sempStopParser(&sbfParse); -} - //========================================================================== // Parser support routines //========================================================================== @@ -2868,37 +2827,6 @@ void processSBFReceiverSetup(SEMP_PARSE_STATE *parse, uint16_t type) } } -//---------------------------------------- -void processSBFDiskStatus(SEMP_PARSE_STATE *parse, uint16_t type) -{ - // If this is DiskStatus, extract some data - if (sempSbfGetBlockNumber(parse) == 4059) - { - if (sempSbfGetU1(parse, 14) < 1) // Check N is at least 1 - return; - - uint64_t diskUsageMSB = sempSbfGetU2(parse, 20 + 2); // DiskUsageMSB - uint64_t diskUsageLSB = sempSbfGetU4(parse, 20 + 4); // DiskUsageLSB - - if ((diskUsageMSB == 65535) && (diskUsageLSB == 4294967295)) - return; - - uint64_t diskSizeMB = sempSbfGetU4(parse, 20 + 8); // DiskSize in megabytes - - if (diskSizeMB == 0) - return; - - uint64_t diskUsage = (diskUsageMSB * 4294967296) + diskUsageLSB; - - sdCardSize = diskSizeMB * 1048576; // Convert to bytes - - sdFreeSpace = sdCardSize - diskUsage; - - GNSS_MOSAIC *mosaic = (GNSS_MOSAIC *)gnss; - mosaic->_diskStatusSeen = true; - } -} - //---------------------------------------- // Call back from within the SBF parser, for end of valid message // Process a complete message incoming from parser @@ -2927,6 +2855,10 @@ void processUart1SBF(SEMP_PARSE_STATE *parse, uint16_t type) if (sempSbfGetBlockNumber(parse) == 4013) mosaic->storeBlock4013(parse); + // If this is DiskStatus, extract some data + if (sempSbfGetBlockNumber(parse) == 4059) + mosaic->storeBlock4059(parse); + // If this is InputLink, extract some data if (sempSbfGetBlockNumber(parse) == 4090) mosaic->storeBlock4090(parse); From ec714f68c776530c4239072235d89f3d89d114d1 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 4 Feb 2025 17:13:25 +0000 Subject: [PATCH 210/276] Add a check for an unmounted (but not removed) SD card --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 21ed495a6..5d0e0b473 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2610,7 +2610,7 @@ void GNSS_MOSAIC::update() { updateSD(); // Check if the card has been removed / inserted - if (_diskStatusSeen) // Check if the DiskStatus SBF message has been processed + if (_diskStatusSeen) // Check if the DiskStatus SBF message has been seen { // If previousFreeSpace hasn't been initialized, initialize it if (previousFreeSpace == 0) @@ -2637,6 +2637,12 @@ void GNSS_MOSAIC::update() previousFreeSpace = sdFreeSpace; } } + else + { + // Disk status not seen + // (Unmounting the SD card will prevent _diskStatusSeen from going true) + logIncreasing = false; + } sdCardSizeLastCheck = millis(); // Update the timer _diskStatusSeen = false; // Clear the flag From 1824402cd5836fc7138a0aa6503633d946f3b8f8 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 4 Feb 2025 16:21:40 -0700 Subject: [PATCH 211/276] Don't check for keys if 28 days remain --- Firmware/RTK_Everywhere/menuPP.ino | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index 6d62f4f54..c01e92f5a 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -1273,7 +1273,10 @@ void provisioningUpdate() if (settings.debugPpCertificate) systemPrintf("Days until keys expire: %d\r\n", daysRemaining); - if (daysRemaining > 28) + // PointPerfect returns keys that expire at midnight so the primary key + // is still available with 0 days left, and a Next Key that has 28 days left + // If there are 28 days remaining, PointPerfect won't have new keys. + if (daysRemaining >= 28) provisioningSetState(PROVISIONING_KEYS_REMAINING); // Don't need new keys else provisioningSetState(PROVISIONING_CHECK_ATTEMPT); // Do need new keys From 8108bd508803a3b1634e2f88f9159033dfb9636d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 6 Feb 2025 17:50:51 +0000 Subject: [PATCH 212/276] Move corrections icon next to logging icon on Facet v2 - WIP --- Firmware/RTK_Everywhere/Display.ino | 88 +++++++++++++++++------------ 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 1c4270177..5dc5b3043 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -692,6 +692,39 @@ void setRadioIcons(std::vector *iconList) // No Rover/Base icons } + + + // On 64x48: squeeze the icon between SIV and logging + static bool correctionsIconPosCalculated = false; + const uint8_t correctionsIconXPos = 39; + static uint8_t correctionsIconYPos = 48; + // Calculate the highest (lowest!) Y position for the corrections icon + // Do it only once... + if (!correctionsIconPosCalculated) + { + for (int i = 0; i < CORR_NUM; i++) + if ((48 - (correctionIconAttributes[i].yOffset + correctionIconAttributes[i].height)) < + correctionsIconYPos) + correctionsIconYPos = + 48 - (correctionIconAttributes[i].yOffset + correctionIconAttributes[i].height); + correctionsIconPosCalculated = true; + } + + if (inRoverMode() == true) + { + CORRECTION_ID_T correctionSource = correctionGetSource(); + if (correctionSource < CORR_NUM) + { + iconPropertyBlinking prop; + prop.duty = 0b11111111; + prop.icon.bitmap = correctionIconAttributes[correctionSource].pointer; + prop.icon.width = correctionIconAttributes[correctionSource].width; + prop.icon.height = correctionIconAttributes[correctionSource].height; + prop.icon.xPos = correctionsIconXPos + correctionIconAttributes[correctionSource].xOffset; + prop.icon.yPos = correctionsIconYPos + correctionIconAttributes[correctionSource].yOffset; + iconList->push_back(prop); + } + } } else if (present.display_type == DISPLAY_128x64) { @@ -901,16 +934,18 @@ void setRadioIcons(std::vector *iconList) break; } - // Put the corrections source icon on the bottom, right of the IP address + // On 128x64: put the corrections source icon on the bottom, right of the IP address static bool correctionsIconPosCalculated = false; - const uint8_t correctionsIconXPos128x64 = 96; - static uint8_t correctionsIconYPos128x64 = 64; + const uint8_t correctionsIconXPos = 96; + static uint8_t correctionsIconYPos = 64; + // Calculate the highest (lowest!) Y position for the corrections icon + // Do it only once... if (!correctionsIconPosCalculated) { for (int i = 0; i < CORR_NUM; i++) if ((64 - (correctionIconAttributes[i].yOffset + correctionIconAttributes[i].height)) < - correctionsIconYPos128x64) - correctionsIconYPos128x64 = + correctionsIconYPos) + correctionsIconYPos = 64 - (correctionIconAttributes[i].yOffset + correctionIconAttributes[i].height); correctionsIconPosCalculated = true; } @@ -925,8 +960,8 @@ void setRadioIcons(std::vector *iconList) prop.icon.bitmap = correctionIconAttributes[correctionSource].pointer; prop.icon.width = correctionIconAttributes[correctionSource].width; prop.icon.height = correctionIconAttributes[correctionSource].height; - prop.icon.xPos = correctionsIconXPos128x64 + correctionIconAttributes[correctionSource].xOffset; - prop.icon.yPos = correctionsIconYPos128x64 + correctionIconAttributes[correctionSource].yOffset; + prop.icon.xPos = correctionsIconXPos + correctionIconAttributes[correctionSource].xOffset; + prop.icon.yPos = correctionsIconYPos + correctionIconAttributes[correctionSource].yOffset; iconList->push_back(prop); } } @@ -1589,36 +1624,11 @@ void displayHorizontalAccuracy(std::vector *iconList, cons void displayRTKAccuracy(std::vector *iconList, const iconProperties *icon, bool fixed) { - CORRECTION_ID_T correctionSource = correctionGetSource(); - iconPropertyBlinking prop; - if ((present.display_type == DISPLAY_128x64) || (correctionSource == CORR_NUM)) - { - prop.icon = icon->iconDisplay[present.display_type]; - prop.duty = fixed ? 0b11111111 : 0b01010101; - iconList->push_back(prop); - } - else - { - // Display the icon (dual crosshair) for 6/8 intervals - prop.icon = icon->iconDisplay[present.display_type]; - prop.duty = fixed ? 0b00111111 : 0b00010101; - iconList->push_back(prop); - - // Display the correction source icon for 2/8 intervals - prop.icon.bitmap = correctionIconAttributes[correctionSource].pointer; - prop.icon.width = correctionIconAttributes[correctionSource].width; - prop.icon.height = correctionIconAttributes[correctionSource].height; - prop.icon.xPos += correctionIconAttributes[correctionSource].xOffset; - prop.icon.yPos += correctionIconAttributes[correctionSource].yOffset; - prop.duty = fixed ? 0b11000000 : 0b01000000; - iconList->push_back(prop); - - // Restore the position for textCoords - prop.icon.xPos -= correctionIconAttributes[correctionSource].xOffset; - prop.icon.yPos -= correctionIconAttributes[correctionSource].yOffset; - } + prop.icon = icon->iconDisplay[present.display_type]; + prop.duty = fixed ? 0b11111111 : 0b01010101; + iconList->push_back(prop); displayCoords textCoords; textCoords.x = prop.icon.xPos + 16; @@ -1704,14 +1714,18 @@ void paintSIVText(displayCoords textCoords) oled->setCursor(textCoords.x, textCoords.y); // x, y oled->print(":"); + uint8_t siv = gnss->getSatellitesInView(); + if (siv > 99) + siv = 99; // Limit SIV to two digits + if (online.gnss) { if (inBaseMode() == true) - oled->print(gnss->getSatellitesInView()); + oled->print(siv); else if (gnss->isFixed() == false) oled->print("0"); else - oled->print(gnss->getSatellitesInView()); + oled->print(siv); paintResets(); } // End gnss online From cfbd696c1517d08742cd138ce6d5d2ab60c158e3 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 6 Feb 2025 17:54:31 +0000 Subject: [PATCH 213/276] Display 100+ SIV as >99 --- Firmware/RTK_Everywhere/Display.ino | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 5dc5b3043..10ec881b7 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -1712,11 +1712,15 @@ void paintSIVText(displayCoords textCoords) { oled->setFont(QW_FONT_8X16); // Set font to type 1: 8x16 oled->setCursor(textCoords.x, textCoords.y); // x, y - oled->print(":"); uint8_t siv = gnss->getSatellitesInView(); if (siv > 99) + { + oled->print(">"); siv = 99; // Limit SIV to two digits + } + else + oled->print(":"); if (online.gnss) { From 383f1453b2a18de16b4d9dfaade65723be55bbe6 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 7 Feb 2025 15:19:12 +0000 Subject: [PATCH 214/276] Nudge SIV to make room for corrections icon --- Firmware/RTK_Everywhere/Display.ino | 15 +++++++++++++-- Firmware/RTK_Everywhere/icons.h | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 10ec881b7..a84e9166c 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -1708,6 +1708,15 @@ displayCoords paintSIVIcon(std::vector *iconList, const ic return textCoords; } + +void nudgeAndPrintSIV(displayCoords textCoords, uint8_t siv) +{ + oled->setCursor(textCoords.x - 1, textCoords.y); // x, y + oled->print(siv / 10); + oled->setCursor(textCoords.x + 7, textCoords.y); // x, y + oled->print(siv % 10); +} + void paintSIVText(displayCoords textCoords) { oled->setFont(QW_FONT_8X16); // Set font to type 1: 8x16 @@ -1722,14 +1731,16 @@ void paintSIVText(displayCoords textCoords) else oled->print(":"); + textCoords.x += 8; + if (online.gnss) { if (inBaseMode() == true) - oled->print(siv); + nudgeAndPrintSIV(textCoords, siv); else if (gnss->isFixed() == false) oled->print("0"); else - oled->print(siv); + nudgeAndPrintSIV(textCoords, siv); paintResets(); } // End gnss online diff --git a/Firmware/RTK_Everywhere/icons.h b/Firmware/RTK_Everywhere/icons.h index 551b24f94..8a77e22d2 100644 --- a/Firmware/RTK_Everywhere/icons.h +++ b/Firmware/RTK_Everywhere/icons.h @@ -1797,7 +1797,7 @@ correctionIconAttribute correctionIconAttributes[CORR_NUM] = { { 4, 0, BT_Symbol_Width, BT_Symbol_Height, BT_Symbol }, { 0, 0, 15, 14, Corr_USB_Icon }, { 0, 0, 15, 14, Corr_TCP_Icon }, - { 1, 0, SIV_Antenna_LBand_Width, SIV_Antenna_LBand_Height, SIV_Antenna_LBand }, + { 1, 1, SIV_Antenna_LBand_Width, SIV_Antenna_LBand_Height, SIV_Antenna_LBand }, { 0, 0, 15, 14, Corr_IP_Icon }, }; From 4e361ebf34c4110856cd7c14b659667635d0c297 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 7 Feb 2025 17:50:49 +0000 Subject: [PATCH 215/276] Remove redundant correctionsSource:: from correctionsSource::CORR_NUM --- Firmware/RTK_Everywhere/menuCorrectionsPriorities.ino | 4 ++-- Firmware/RTK_Everywhere/settings.h | 6 +++--- Firmware/RTK_Everywhere/support.ino | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Firmware/RTK_Everywhere/menuCorrectionsPriorities.ino b/Firmware/RTK_Everywhere/menuCorrectionsPriorities.ino index 7a3205f83..858447079 100644 --- a/Firmware/RTK_Everywhere/menuCorrectionsPriorities.ino +++ b/Firmware/RTK_Everywhere/menuCorrectionsPriorities.ino @@ -299,11 +299,11 @@ void menuCorrectionsPriorities() &settings.correctionsSourcesLifetime_s); // Check for priority decrease - else if ((incoming >= 'a') && (incoming < ('a' + correctionsSource::CORR_NUM))) + else if ((incoming >= 'a') && (incoming < ('a' + CORR_NUM))) correctionPriorityDecrease(settings.correctionsSourcesPriority[incoming - 'a']); // Check for priority increase - else if ((incoming >= 'A') && (incoming < ('A' + correctionsSource::CORR_NUM))) + else if ((incoming >= 'A') && (incoming < ('A' + CORR_NUM))) correctionPriorityIncrease(settings.correctionsSourcesPriority[incoming - 'A']); else if (incoming == 'x') diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 7aeb20d39..3171e5061 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -149,7 +149,7 @@ typedef enum typedef uint8_t CORRECTION_ID_T; // Type holding a correction ID or priority typedef uint8_t CORRECTION_MASK_T; // Type holding a bitmask of correction IDs -const char * const correctionsSourceNames[correctionsSource::CORR_NUM] = +const char * const correctionsSourceNames[CORR_NUM] = { // These must match correctionsSource above "External Radio", @@ -620,7 +620,7 @@ struct Settings // Corrections int correctionsSourcesLifetime_s = 30; // Expire a corrections source if no data is seen for this many seconds - CORRECTION_ID_T correctionsSourcesPriority[correctionsSource::CORR_NUM] = { (CORRECTION_ID_T)-1 }; // -1 indicates array is uninitialized, indexed by correction source ID + CORRECTION_ID_T correctionsSourcesPriority[CORR_NUM] = { (CORRECTION_ID_T)-1 }; // -1 indicates array is uninitialized, indexed by correction source ID bool debugCorrections = false; uint8_t enableExtCorrRadio = 254; // Will be initialized to true or false depending on model uint8_t extCorrRadioSPARTNSource = 0; // This selects IP (0) vs. L-Band (1) for _SPARTN_ corrections on Radio Ext (UART2) @@ -1177,7 +1177,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = // Corrections { 1, 1, 0, 1, 1, 1, 1, 1, 1, _int, 0, & settings.correctionsSourcesLifetime_s, "correctionsSourcesLifetime", }, - { 1, 1, 1, 1, 1, 1, 1, 1, 1, tCorrSPri, correctionsSource::CORR_NUM, & settings.correctionsSourcesPriority, "correctionsPriority_", }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, tCorrSPri, CORR_NUM, & settings.correctionsSourcesPriority, "correctionsPriority_", }, { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugCorrections, "debugCorrections", }, { 1, 1, 0, 1, 1, 1, 0, 1, 1, _bool, 0, & settings.enableExtCorrRadio, "enableExtCorrRadio", }, { 1, 1, 0, 1, 1, 0, 0, 1, 0, _uint8_t, 0, & settings.extCorrRadioSPARTNSource, "extCorrRadioSPARTNSource", }, diff --git a/Firmware/RTK_Everywhere/support.ino b/Firmware/RTK_Everywhere/support.ino index 31686407d..bb6429aa8 100644 --- a/Firmware/RTK_Everywhere/support.ino +++ b/Firmware/RTK_Everywhere/support.ino @@ -723,7 +723,7 @@ void verifyTables() correctionVerifyTables(); webServerVerifyTables(); - if (correctionsSource::CORR_NUM >= (int)('x' - 'a')) + if (CORR_NUM >= (int)('x' - 'a')) reportFatalError("Too many correction sources"); } From 2b629cfdece63e8c95175e2fe0520098be61fa78 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 7 Feb 2025 17:52:59 +0000 Subject: [PATCH 216/276] Better diagnostics: make pointperfectPrintKeyInformation print who it was called by periodic print subscribed topics in MQTT Client --- Firmware/RTK_Everywhere/Developer.ino | 2 +- Firmware/RTK_Everywhere/HTTP_Client.ino | 2 +- Firmware/RTK_Everywhere/MQTT_Client.ino | 21 ++++++++++++++++++- .../RTK_Everywhere/PointPerfectLibrary.ino | 6 ++++-- Firmware/RTK_Everywhere/menuPP.ino | 2 +- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index edd72d944..eee6ca673 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -266,7 +266,7 @@ void updatePPL() {} bool sendGnssToPpl(uint8_t *buffer, int numDataBytes) {return false;} bool sendSpartnToPpl(uint8_t *buffer, int numDataBytes) {return false;} bool sendAuxSpartnToPpl(uint8_t *buffer, int numDataBytes) {return false;} -void pointperfectPrintKeyInformation() {systemPrintln("**PPL Not Compiled**");} +void pointperfectPrintKeyInformation(const char *requestedBy) {systemPrintln("**PPL Not Compiled**");} #endif // COMPILE_POINTPERFECT_LIBRARY diff --git a/Firmware/RTK_Everywhere/HTTP_Client.ino b/Firmware/RTK_Everywhere/HTTP_Client.ino index d2e15b9b6..7e14eb962 100644 --- a/Firmware/RTK_Everywhere/HTTP_Client.ino +++ b/Firmware/RTK_Everywhere/HTTP_Client.ino @@ -540,7 +540,7 @@ void httpClientUpdate() settings.pointPerfectNextKeyStart = (*jsonZtp)["dynamickeys"]["next"]["start"]; if (settings.debugCorrections || settings.debugHttpClientData) - pointperfectPrintKeyInformation(); + pointperfectPrintKeyInformation("HTTP Client"); // displayKeysUpdated(); diff --git a/Firmware/RTK_Everywhere/MQTT_Client.ino b/Firmware/RTK_Everywhere/MQTT_Client.ino index 1b60d4fd9..e08c2a1ea 100644 --- a/Firmware/RTK_Everywhere/MQTT_Client.ino +++ b/Firmware/RTK_Everywhere/MQTT_Client.ino @@ -474,7 +474,7 @@ void mqttClientReceiveMessage(int messageSize) recordSystemSettings(); // Record these settings to unit if (settings.debugCorrections == true) - pointperfectPrintKeyInformation(); + pointperfectPrintKeyInformation("MQTT Topic"); } // Correction data from PP can go direct to GNSS @@ -585,6 +585,23 @@ void mqttClientSetState(uint8_t newState) } else systemPrintln(mqttClientStateName[mqttClientState]); + + systemPrint("MQTT Client subscribe topics: "); + for (auto it = mqttSubscribeTopics.begin(); it != mqttSubscribeTopics.end(); it = std::next(it)) + { + String topic = *it; + systemPrint(topic); + systemPrint(" "); + } + systemPrintln(); + systemPrint("MQTT Client subscribed topics: "); + for (auto it = mqttSubscribedTopics.begin(); it != mqttSubscribedTopics.end(); it = std::next(it)) + { + String topic = *it; + systemPrint(topic); + systemPrint(" "); + } + systemPrintln(); } } @@ -859,8 +876,10 @@ void mqttClientUpdate() { mqttSubscribeTopics.push_back(MQTT_TOPIC_ASSISTNOW); } + // Subscribe to the key distribution topic mqttSubscribeTopics.push_back(String(settings.pointPerfectKeyDistributionTopic)); + // Subscribe to the continental correction topic for our region - if we have one. L-Band-only does not. if (strlen(settings.regionalCorrectionTopics[settings.geographicRegion]) > 0) { diff --git a/Firmware/RTK_Everywhere/PointPerfectLibrary.ino b/Firmware/RTK_Everywhere/PointPerfectLibrary.ino index 08aa41f4d..32131d8de 100644 --- a/Firmware/RTK_Everywhere/PointPerfectLibrary.ino +++ b/Firmware/RTK_Everywhere/PointPerfectLibrary.ino @@ -364,7 +364,7 @@ bool getUsablePplKey(char *keyBuffer, int keyBufferSize) if (settings.debugCorrections == true) { - pointperfectPrintKeyInformation(); + pointperfectPrintKeyInformation("getUsablePplKey"); systemPrintf("Days remaining until current key expires: %d\r\n", daysRemainingCurrent); systemPrintf("Days remaining until next key expires: %d\r\n", daysRemainingNext); } @@ -525,8 +525,10 @@ const char *PPLReturnStatusToStr(ePPL_ReturnStatus status) } } -void pointperfectPrintKeyInformation() +void pointperfectPrintKeyInformation(const char *requestedBy) { + // All calls to pointperfectPrintKeyInformation are guarded by settings.debugCorrections + systemPrintf(" pointPerfect keys print requested by %s\r\n", requestedBy); systemPrintf(" pointPerfectCurrentKey: %s\r\n", settings.pointPerfectCurrentKey); systemPrintf( " pointPerfectCurrentKeyStart: %lld - %s\r\n", settings.pointPerfectCurrentKeyStart, diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index c01e92f5a..4f2100ed9 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -128,7 +128,7 @@ void menuPointPerfectKeys() settings.pointPerfectNextKeyDuration = settings.pointPerfectCurrentKeyDuration; if (settings.debugCorrections == true) - pointperfectPrintKeyInformation(); + pointperfectPrintKeyInformation("Menu PP"); } else if (incoming == 4) { From 0d600274eda76ba09968457f7bf8cb1890ad993b Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 10 Feb 2025 11:28:02 +0000 Subject: [PATCH 217/276] Add mqttClientIsNeeded() and productVariantSupportsAssistNow() --- Firmware/RTK_Everywhere/MQTT_Client.ino | 60 +++++++++++++------------ Firmware/RTK_Everywhere/menuPP.ino | 15 ++++++- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/Firmware/RTK_Everywhere/MQTT_Client.ino b/Firmware/RTK_Everywhere/MQTT_Client.ino index e08c2a1ea..9b246772d 100644 --- a/Firmware/RTK_Everywhere/MQTT_Client.ino +++ b/Firmware/RTK_Everywhere/MQTT_Client.ino @@ -154,6 +154,34 @@ static uint32_t mqttClientTimer; // MQTT Client Routines //---------------------------------------- +bool mqttClientIsNeeded() +{ + // If PointPerfectCorrections are not enabled, return false + if (!settings.enablePointPerfectCorrections) + return false; + + // For the mosaic-X5, settings.enablePointPerfectCorrections will be true if + // we are using the PPL and getting keys via ZTP. BUT the Facet mosaic-X5 + // uses the L-Band (only) plan. It should not and can not subscribe to PP IP + // MQTT corrections. So, return false - even though the L-Band frequencies topic + // and key distribution topic could be beneficial. + // We could use present.gnss_mosaicX5, but let's not. See notes on EVK below. + if (productVariant == RTK_FACET_MOSAIC) + return false; + + // For the Facet v2 L-Band, the same is true. It uses the L-Band (only) plan. + // We get keys during ZTP (HTTP_Client). It should not and can not subscribe + // to PP IP MQTT corrections. So, return true only if AssistNow is enabled - + // even though the L-Band frequencies topic and key distribution topic could + // be beneficial. + // Note: EVK supports both L-Band and IP, so we cannot use present.lband_neo + if (productVariant == RTK_FACET_V2_LBAND) + if (!settings.useAssistNow) + return false; + + return true; +} + // Determine if another connection is possible or if the limit has been reached bool mqttClientConnectLimitReached() { @@ -163,9 +191,7 @@ bool mqttClientConnectLimitReached() // Retry the connection a few times limitReached = (mqttClientConnectionAttempts >= MAX_MQTT_CLIENT_CONNECTION_ATTEMPTS); - bool enableMqttClient = true; - if (!settings.enablePointPerfectCorrections) - enableMqttClient = false; + bool enableMqttClient = mqttClientIsNeeded(); // Restart the MQTT client MQTT_CLIENT_STOP(limitReached || (!enableMqttClient)); @@ -242,18 +268,7 @@ void mqttClientPrintStatus() byte minutes; byte seconds; - bool enableMqttClient = true; - if (!settings.enablePointPerfectCorrections) - enableMqttClient = false; - - // For the mosaic-X5, settings.enablePointPerfectCorrections will be true if - // we are using the PPL and getting keys via ZTP. BUT the Facet mosaic-X5 - // uses the L-Band (only) plan. It should not and can not subscribe to PP IP - // MQTT corrections. So, if present.gnss_mosaicX5 is true, set enableMqttClient - // to false. - // TODO : review this. This feels like a bit of a hack... - if (present.gnss_mosaicX5) - enableMqttClient = false; + bool enableMqttClient = mqttClientIsNeeded(); // Display MQTT Client status and uptime if (enableMqttClient && (EQ_RTK_MODE(mqttClientMode))) @@ -595,7 +610,7 @@ void mqttClientSetState(uint8_t newState) } systemPrintln(); systemPrint("MQTT Client subscribed topics: "); - for (auto it = mqttSubscribedTopics.begin(); it != mqttSubscribedTopics.end(); it = std::next(it)) + for (auto it = mqttClientSubscribedTopics.begin(); it != mqttClientSubscribedTopics.end(); it = std::next(it)) { String topic = *it; systemPrint(topic); @@ -692,18 +707,7 @@ bool mqttClientNeedsNetwork() // MQTT_CLIENT_RECEIVE_DATA_TIMEOUT void mqttClientUpdate() { - bool enableMqttClient = true; - if (!settings.enablePointPerfectCorrections) - enableMqttClient = false; - - // For the mosaic-X5, settings.enablePointPerfectCorrections will be true if - // we are using the PPL and getting keys via ZTP. BUT the Facet mosaic-X5 - // uses the L-Band (only) plan. It should not and can not subscribe to PP IP - // MQTT corrections. So, if present.gnss_mosaicX5 is true, set enableMqttClient - // to false. - // TODO : review this. This feels like a bit of a hack... - if (present.gnss_mosaicX5) - enableMqttClient = false; + bool enableMqttClient = mqttClientIsNeeded(); // Shutdown the MQTT client when the mode or setting changes DMW_st(mqttClientSetState, mqttClientState); diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index 4f2100ed9..bdbeb0368 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -28,6 +28,17 @@ MqttClient *menuppMqttClient; // L-Band Routines - compiled out //---------------------------------------- +bool productVariantSupportsAssistNow() +{ + if (productVariant == RTK_FACET_MOSAIC) + return false; + if (productVariant == RTK_TORCH) + return false; + if (productVariant == RTK_POSTCARD) + return false; + return true; +} + void menuPointPerfectKeys() { while (1) @@ -979,7 +990,7 @@ void menuPointPerfect() systemPrint(localizedDistributionTileLevelNames[settings.localizedDistributionTileLevel]); systemPrintln(")"); } - if (productVariant != RTK_FACET_MOSAIC) + if (productVariantSupportsAssistNow()) { systemPrint("a) Use AssistNow: "); if (settings.useAssistNow == true) @@ -1030,7 +1041,7 @@ void menuPointPerfect() if (settings.localizedDistributionTileLevel >= LOCALIZED_DISTRIBUTION_TILE_LEVELS) settings.localizedDistributionTileLevel = 0; } - else if (incoming == 'a' && pointPerfectIsEnabled() && (productVariant != RTK_FACET_MOSAIC)) + else if (incoming == 'a' && pointPerfectIsEnabled() && productVariantSupportsAssistNow()) { settings.useAssistNow ^= 1; } From 6f62d330f58401ddc5e514485b1a831cc10fde78 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 10 Feb 2025 15:40:24 -0700 Subject: [PATCH 218/276] Add support for PQTM logging. Fix #541. This suppresses passing Quectel proprietary messages to circular buffer unless the user explicitly enables the message. Note: Only PVT and EPE messages have been added because these are explicitly turned on during LG290P library initialization. More work will need to be done to support other messages during the LG290P configureRover() type functions. --- Firmware/RTK_Everywhere/GNSS_LG290P.h | 6 ++ Firmware/RTK_Everywhere/GNSS_LG290P.ino | 94 ++++++++++++++++++++++-- Firmware/RTK_Everywhere/Tasks.ino | 10 +++ Firmware/RTK_Everywhere/menuMessages.ino | 10 +++ Firmware/RTK_Everywhere/settings.h | 2 + 5 files changed, 117 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.h b/Firmware/RTK_Everywhere/GNSS_LG290P.h index 7cbe15a2b..baeb43b1d 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.h +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.h @@ -51,8 +51,14 @@ const lg290pMsg lgMessagesRTCM[] = { {"RTCM3-107X", 1, 0}, {"RTCM3-108X", 1, 0}, {"RTCM3-109X", 1, 0}, {"RTCM3-111X", 1, 0}, {"RTCM3-112X", 1, 0}, {"RTCM3-113X", 1, 0}, }; +// Quectel Proprietary messages +const lg290pMsg lgMessagesPQTM[] = { + {"EPE", 0, 0}, {"PVT", 0, 0}, +}; + #define MAX_LG290P_NMEA_MSG (sizeof(lgMessagesNMEA) / sizeof(lg290pMsg)) #define MAX_LG290P_RTCM_MSG (sizeof(lgMessagesRTCM) / sizeof(lg290pMsg)) +#define MAX_LG290P_PQTM_MSG (sizeof(lgMessagesPQTM) / sizeof(lg290pMsg)) enum lg290p_Models { diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index 3201b7ef1..fdcbde427 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -1574,6 +1574,7 @@ void GNSS_LG290P::menuMessages() systemPrintln("1) Set NMEA Messages"); systemPrintln("2) Set Rover RTCM Messages"); systemPrintln("3) Set Base RTCM Messages"); + systemPrintln("4) Set PQTM Messages"); systemPrintln("10) Reset to Defaults"); @@ -1587,6 +1588,8 @@ void GNSS_LG290P::menuMessages() menuMessagesSubtype(settings.lg290pMessageRatesRTCMRover, "RTCMRover"); else if (incoming == 3) menuMessagesSubtype(settings.lg290pMessageRatesRTCMBase, "RTCMBase"); + else if (incoming == 4) + menuMessagesSubtype(settings.lg290pMessageRatesPQTM, "PQTM"); else if (incoming == 10) { // Reset rates to defaults @@ -1601,6 +1604,10 @@ void GNSS_LG290P::menuMessages() for (int x = 0; x < MAX_LG290P_RTCM_MSG; x++) settings.lg290pMessageRatesRTCMBase[x] = lgMessagesRTCM[x].msgDefaultRate; + // Reset PQTM rates to defaults + for (int x = 0; x < MAX_LG290P_PQTM_MSG; x++) + settings.lg290pMessageRatesPQTM[x] = lgMessagesPQTM[x].msgDefaultRate; + systemPrintln("Reset to Defaults"); } @@ -1638,7 +1645,7 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message { endOfBlock = MAX_LG290P_NMEA_MSG; - for (int x = 0; x < MAX_LG290P_NMEA_MSG; x++) + for (int x = 0; x < endOfBlock; x++) { if (lg290pFirmwareVersion <= lgMessagesNMEA[x].firmwareVersionSupported) systemPrintf("%d) Message %s: %d - Requires firmware update\r\n", x + 1, @@ -1652,7 +1659,7 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message { endOfBlock = MAX_LG290P_RTCM_MSG; - for (int x = 0; x < MAX_LG290P_RTCM_MSG; x++) + for (int x = 0; x < endOfBlock; x++) { if (lg290pFirmwareVersion <= lgMessagesRTCM[x].firmwareVersionSupported) systemPrintf("%d) Message %s: %d - Requires firmware update\r\n", x + 1, @@ -1666,16 +1673,30 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message { endOfBlock = MAX_LG290P_RTCM_MSG; - for (int x = 0; x < MAX_LG290P_RTCM_MSG; x++) + for (int x = 0; x < endOfBlock; x++) { if (lg290pFirmwareVersion <= lgMessagesRTCM[x].firmwareVersionSupported) - systemPrintf("%d) Message %s: %d - Requires firmware update\r\n", x + 1, lgMessagesRTCM[x].msgTextName, - settings.lg290pMessageRatesRTCMBase[x]); + systemPrintf("%d) Message %s: %d - Requires firmware update\r\n", x + 1, + lgMessagesRTCM[x].msgTextName, settings.lg290pMessageRatesRTCMBase[x]); else systemPrintf("%d) Message %s: %d\r\n", x + 1, lgMessagesRTCM[x].msgTextName, settings.lg290pMessageRatesRTCMBase[x]); } } + else if (strcmp(messageType, "PQTM") == 0) + { + endOfBlock = MAX_LG290P_PQTM_MSG; + + for (int x = 0; x < endOfBlock; x++) + { + if (lg290pFirmwareVersion <= lgMessagesPQTM[x].firmwareVersionSupported) + systemPrintf("%d) Message %s: %d - Requires firmware update\r\n", x + 1, + lgMessagesPQTM[x].msgTextName, settings.lg290pMessageRatesPQTM[x]); + else + systemPrintf("%d) Message %s: %d\r\n", x + 1, lgMessagesPQTM[x].msgTextName, + settings.lg290pMessageRatesPQTM[x]); + } + } systemPrintln("x) Exit"); @@ -1698,6 +1719,11 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message sprintf(messageString, "Enter number of fixes required before %s is reported (0 to disable)", lgMessagesRTCM[incoming].msgTextName); } + else if (strcmp(messageType, "PQTM") == 0) + { + sprintf(messageString, "Enter number of fixes required before %s is reported (0 to disable)", + lgMessagesPQTM[incoming].msgTextName); + } int newSetting = 0; @@ -1718,6 +1744,11 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message if (getNewSetting(messageString, 0, 1200, &newSetting) == INPUT_RESPONSE_VALID) settings.lg290pMessageRatesRTCMBase[incoming] = newSetting; } + if (strcmp(messageType, "PQTM") == 0) + { + if (getNewSetting(messageString, 0, 1, &newSetting) == INPUT_RESPONSE_VALID) + settings.lg290pMessageRatesPQTM[incoming] = newSetting; + } } else if (incoming == INPUT_RESPONSE_GETNUMBER_EXIT) break; @@ -2134,3 +2165,56 @@ void lg290pReset() { digitalWrite(pin_GNSS_Reset, LOW); } + +// Given a NMEA or PQTM sentence, determine if it is enabled in settings +// This is used to signal to the processUart1Message() task to remove messages that are needed +// by the library to function (ie, PQTMEPE, PQTMPVT, GNGSV) but should not be logged or passed to other consumers +// If unknown, allow messages through. Filtering and suppression should be selectively added in. +bool lg290pMessageEnabled(char *nmeaSentence, int sentenceLength) +{ + // Identify message type: PQTM or NMEA + char messageType[strlen("PQTM") + 1] = {0}; + strncpy(messageType, &nmeaSentence[1], + 4); // Copy four letters, starting in spot 1. Null terminated from array initializer. + + if (strncmp(messageType, "PQTM", sizeof(messageType)) == 0) + { + // Identify sentence type + char sentenceType[strlen("EPE") + 1] = {0}; + strncpy(sentenceType, &nmeaSentence[5], + 3); // Copy three letters, starting in spot 5. Null terminated from array initializer. + + // Find this sentence type in the settings array + for (int messageNumber = 0; messageNumber < MAX_LG290P_PQTM_MSG; messageNumber++) + { + if (strncmp(lgMessagesPQTM[messageNumber].msgTextName, sentenceType, sizeof(sentenceType)) == 0) + { + if (settings.lg290pMessageRatesPQTM[messageNumber] > 0) + return (true); + return (false); + } + } + } + + else // We have to assume $G???? + { + // Identify sentence type + char sentenceType[strlen("GSV") + 1] = {0}; + strncpy(sentenceType, &nmeaSentence[3], + 3); // Copy three letters, starting in spot 3. Null terminated from array initializer. + + // Find this sentence type in the settings array + for (int messageNumber = 0; messageNumber < MAX_LG290P_NMEA_MSG; messageNumber++) + { + if (strncmp(lgMessagesNMEA[messageNumber].msgTextName, sentenceType, sizeof(sentenceType)) == 0) + { + if (settings.lg290pMessageRatesNMEA[messageNumber] > 0) + return (true); + return (false); + } + } + } + + // If we can't ID this message, allow it by default. The device configuration should control most message flow. + return (true); +} \ No newline at end of file diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index e387bc96d..d372e98d4 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -641,6 +641,16 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type) { // Give this data to the library to update its internal variables lg290pHandler(parse->buffer, parse->length); + + if (type == RTK_NMEA_PARSER_INDEX) + { + // Suppress PQTM/NMEA messages as needed + if (lg290pMessageEnabled((char *)parse->buffer, parse->length) == false) + { + parse->buffer[0] = 0; + parse->length = 0; + } + } } // Handle LLA compensation due to tilt or outputTipAltitude setting diff --git a/Firmware/RTK_Everywhere/menuMessages.ino b/Firmware/RTK_Everywhere/menuMessages.ino index f838fb3e7..98ced1129 100644 --- a/Firmware/RTK_Everywhere/menuMessages.ino +++ b/Firmware/RTK_Everywhere/menuMessages.ino @@ -705,6 +705,16 @@ void checkGNSSArrayDefaults() for (int x = 0; x < MAX_LG290P_RTCM_MSG; x++) settings.lg290pMessageRatesRTCMBase[x] = lgMessagesRTCM[x].msgDefaultRate; } + + if (settings.lg290pMessageRatesPQTM[0] == 254) + { + defaultsApplied = true; + + // Reset rates to defaults + for (int x = 0; x < MAX_LG290P_PQTM_MSG; x++) + settings.lg290pMessageRatesPQTM[x] = lgMessagesPQTM[x].msgDefaultRate; + } + } #endif // COMPILE_LG290P diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 7aeb20d39..0a37ac5de 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -997,6 +997,7 @@ struct Settings int lg290pMessageRatesRTCMRover[MAX_LG290P_RTCM_MSG] = { 254}; // Mark first record with key so defaults will be applied. Int value for each supported message - Report // rates for RTCM Base. Default to Quectel recommended rates. + int lg290pMessageRatesPQTM[MAX_LG290P_PQTM_MSG] = {254}; // Mark first record with key so defaults will be applied. #endif // COMPILE_LG290P bool debugSettings = false; @@ -1606,6 +1607,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 0, 1, 1, 0, 0, 0, 0, 0, 1, tLgMRNmea, MAX_LG290P_NMEA_MSG, & settings.lg290pMessageRatesNMEA, "messageRateNMEA_", }, { 0, 1, 1, 0, 0, 0, 0, 0, 1, tLgMRBaRT, MAX_LG290P_RTCM_MSG, & settings.lg290pMessageRatesRTCMBase, "messageRateRTCMBase_", }, { 0, 1, 1, 0, 0, 0, 0, 0, 1, tLgMRRvRT, MAX_LG290P_RTCM_MSG, & settings.lg290pMessageRatesRTCMRover, "messageRateRTCMRover_", }, + { 0, 1, 1, 0, 0, 0, 0, 0, 1, tLgMRNmea, MAX_LG290P_PQTM_MSG, & settings.lg290pMessageRatesPQTM, "messageRatePQTM_", }, #endif // COMPILE_LG290P { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugSettings, "debugSettings", }, From 449f25a7b86b6b0378c65f5b7ed83f18a4432345 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 10 Feb 2025 20:24:44 -0700 Subject: [PATCH 219/276] Create higher precision GST sentence Work around for issue #513 --- Firmware/RTK_Everywhere/Developer.ino | 1 + Firmware/RTK_Everywhere/GNSS_LG290P.ino | 131 +++++++++++++++++++++++- Firmware/RTK_Everywhere/GNSS_None.h | 4 + Firmware/RTK_Everywhere/Tasks.ino | 3 + 4 files changed, 138 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index edd72d944..4b161b95c 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -277,6 +277,7 @@ void pointperfectPrintKeyInformation() {systemPrintln("**PPL Not Compiled**");} #ifndef COMPILE_LG290P void lg290pHandler(uint8_t * buffer, int length) {} +void lg290pModifyGst(char *nmeaSentence, uint16_t *sentenceLength) {} #endif // COMPILE_LG290P diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index fdcbde427..baac17c51 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -1080,7 +1080,6 @@ uint8_t GNSS_LG290P::getFixType() //---------------------------------------- float GNSS_LG290P::getHorizontalAccuracy() { - // Coming soon from EPE if (online.gnss) return (_lg290p->get2DError()); return 0; @@ -2217,4 +2216,134 @@ bool lg290pMessageEnabled(char *nmeaSentence, int sentenceLength) // If we can't ID this message, allow it by default. The device configuration should control most message flow. return (true); +} + +// Re-create the GST sentence to increase the horizontal and vertical precision number of decimals +// ie, 0.0 becomes 0.009 +// See issue: https://github.com/sparkfun/SparkFun_RTK_Everywhere_Firmware/issues/513 +// $GNGST,223954.500,1.7,1.5,1.0,109.3,1.412,1.055,2.4*7E +// Modifies the sentence length with new length +void lg290pModifyGst(char *nmeaSentence, uint16_t *sentenceLength) +{ + // This issue currently only applies to LG290P firmware version 4 + // Version 3 does not support GST messages. Version 5 should fix the issue. + if (lg290pFirmwareVersion != 4) + return; + + if (online.gnss == false) + return; + + GNSS_LG290P *lg290p = (GNSS_LG290P *)gnss; + + // Identify sentence type + char sentenceType[strlen("GST") + 1] = {0}; + strncpy(sentenceType, &nmeaSentence[3], + 3); // Copy three letters, starting in spot 3. Null terminated from array initializer. + + // We only care about GST sentences + if (strncmp(sentenceType, "GST", sizeof(sentenceType)) != 0) + return; + + const int latitudeErrorComma = 6; + const int longitudeErrorComma = 7; + const int altitudeErrorComma = 8; + + uint8_t latitudeStart = 0; + uint8_t latitudeStop = 0; + uint8_t longitudeStart = 0; + uint8_t longitudeStop = 0; + uint8_t altitudeStart = 0; + uint8_t checksumStart = 0; + + if (settings.enableImuCompensationDebug == true && !inMainMenu) + systemPrintf("Original GNGST:\r\n%s\r\n", nmeaSentence); + + int commaCount = 0; + for (int x = 0; x < strnlen(nmeaSentence, *sentenceLength); x++) // Assumes sentence is null terminated + { + if (nmeaSentence[x] == ',') + { + commaCount++; + if (commaCount == latitudeErrorComma) + latitudeStart = x + 1; + if (commaCount == latitudeErrorComma + 1) + latitudeStop = x; + if (commaCount == longitudeErrorComma) + longitudeStart = x + 1; + if (commaCount == longitudeErrorComma + 1) + longitudeStop = x; + if (commaCount == altitudeErrorComma) + altitudeStart = x + 1; + } + if (nmeaSentence[x] == '*') + { + checksumStart = x; + break; + } + } + + if (latitudeStart == 0 || latitudeStop == 0 || longitudeStart == 0 || longitudeStop == 0 || altitudeStart == 0 || + checksumStart == 0) + { + systemPrintln("Delineator not found"); + return; + } + + char newSentence[150] = {0}; + + if (sizeof(newSentence) < *sentenceLength) + { + systemPrintln("newSentence not big enough!"); + return; + } + + char errorString[strlen("0.000") + 1] = {0}; + + // strncat terminates + + // Add start of message up to latitude + strncat(newSentence, nmeaSentence, latitudeStart); + + // Convert error from EPE message to string. We don't have pure lat error, only 2D and 3D. + snprintf(errorString, sizeof(errorString), "%0.3f", lg290p->getHorizontalAccuracy()); + + // Add latitude error + strncat(newSentence, errorString, sizeof(newSentence) - 1); + + // Add interstitial between end of lat and beginning of lon + strncat(newSentence, nmeaSentence + latitudeStop, longitudeStart - latitudeStop); + + // Add same error for longitude error + strncat(newSentence, errorString, sizeof(newSentence) - 1); + + // Add interstitial between end of lon and beginning of alt + strncat(newSentence, nmeaSentence + longitudeStop, altitudeStart - longitudeStop); + + // Convert error from EPE message to string. We don't have pure altitude error, use double 2D error as stand-in. + snprintf(errorString, sizeof(errorString), "%0.3f", lg290p->getHorizontalAccuracy() * 2); + + // Add altitude error. We don't really have altitude so use 3D error in its place. + strncat(newSentence, errorString, sizeof(newSentence) - 1); + + // From: http://engineeringnotes.blogspot.com/2015/02/generate-crc-for-nmea-strings-arduino.html + byte CRC = 0; // XOR chars between '$' and '*' + for (byte x = 1; x < strlen(newSentence); x++) + CRC = CRC ^ newSentence[x]; + + // Convert CRC to string, add * and CR LF + snprintf(errorString, sizeof(errorString), "*%02X\r\n", CRC); + + // Add CRC + strncat(newSentence, errorString, sizeof(newSentence) - 1); + + // Increase length of sentence + *sentenceLength = strlen(newSentence); + + // Overwrite the original NMEA + strncpy(nmeaSentence, newSentence, *sentenceLength); + + nmeaSentence[*sentenceLength] = '\0'; // Terminate string + + if (settings.enableImuCompensationDebug == true && !inMainMenu) + systemPrintf("Corrected GNGST:\r\n%s\r\n", nmeaSentence); } \ No newline at end of file diff --git a/Firmware/RTK_Everywhere/GNSS_None.h b/Firmware/RTK_Everywhere/GNSS_None.h index 9eeec57b5..8d717286f 100644 --- a/Firmware/RTK_Everywhere/GNSS_None.h +++ b/Firmware/RTK_Everywhere/GNSS_None.h @@ -429,6 +429,10 @@ class GNSS_None : public GNSS { } + void modifyGst(char *nmeaSentence, uint16_t *sentenceLength) + { + } + // Print the module type and firmware version void printModuleInfo() { diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index d372e98d4..f470d8c7a 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -650,6 +650,9 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type) parse->buffer[0] = 0; parse->length = 0; } + + // Gimme three decimals! + lg290pModifyGst((char *)parse->buffer, &parse->length); } } From 50a3fa4244691c9913d93faf70575c0ba4a534ac Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 10 Feb 2025 20:26:39 -0700 Subject: [PATCH 220/276] Update compile-rtk-everywhere.yml --- .github/workflows/compile-rtk-everywhere.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/compile-rtk-everywhere.yml b/.github/workflows/compile-rtk-everywhere.yml index 7d6da8848..bcab58a31 100644 --- a/.github/workflows/compile-rtk-everywhere.yml +++ b/.github/workflows/compile-rtk-everywhere.yml @@ -159,7 +159,7 @@ jobs: mv RTK_Everywhere.ino.bin ${{ env.FILENAME_PREFIX }}${{ env.FILE_ENDING_UNDERSCORE }}.bin - name: Upload binary to action - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ${{ env.FILENAME_PREFIX }}${{ env.FILE_ENDING_UNDERSCORE }} path: ./Firmware/RTK_Everywhere/build/esp32.esp32.esp32/${{ env.FILENAME_PREFIX }}${{ env.FILE_ENDING_UNDERSCORE }}.bin From 05ff499ddb05834555548dc144958da42b797c1d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Feb 2025 03:28:41 +0000 Subject: [PATCH 221/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 1526 ++++++++++++++++---------------- 1 file changed, 763 insertions(+), 763 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index b176825b4..83bdb6aa8 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xCE, 0x8D, 0x8E, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0xE9, 0xC3, 0xAA, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -281,767 +281,767 @@ static const uint8_t main_js[] PROGMEM = { 0xCC, 0xD8, 0xDA, 0x07, 0x39, 0x7B, 0xDA, 0x3E, 0xCF, 0x5B, 0x07, 0xBE, 0x5B, 0x9C, 0x2E, 0x6E, 0x8C, 0xAE, 0x1C, 0x26, 0xC9, 0xC5, 0xFB, 0xC7, 0x60, 0x4C, 0xC3, 0x12, 0xFD, 0xB2, 0xBD, 0x88, 0x7A, 0x9E, 0xFD, 0x81, 0xBA, 0xC3, 0x9B, 0xE8, 0x72, 0x3C, 0x36, 0x1B, 0x66, 0xAD, 0x96, 0xAA, - 0x23, 0x64, 0x15, 0x6F, 0x30, 0xB0, 0x64, 0x79, 0xE6, 0xCE, 0x91, 0x19, 0x66, 0xDE, 0x3E, 0xC8, - 0x8B, 0x86, 0x00, 0xC6, 0xEF, 0xE0, 0x5E, 0x4D, 0xA3, 0x48, 0x0E, 0xCC, 0xAF, 0x96, 0x56, 0x2D, - 0x0A, 0xEE, 0xCD, 0x1D, 0x8E, 0x81, 0x0B, 0x45, 0x7A, 0xF7, 0x00, 0x8E, 0x72, 0x34, 0xB8, 0x21, - 0x8B, 0x14, 0x77, 0x97, 0xCC, 0x9E, 0x93, 0xE4, 0x92, 0xF4, 0xC1, 0x51, 0xBE, 0x00, 0x24, 0xC4, - 0x0D, 0x43, 0xF8, 0xC9, 0xAE, 0x58, 0x1C, 0x1D, 0xC4, 0xE9, 0xED, 0xEA, 0x8C, 0xEB, 0xE2, 0xFC, - 0x73, 0x15, 0xDB, 0x63, 0x50, 0xAD, 0x06, 0x0D, 0x62, 0x37, 0x99, 0x6B, 0xB7, 0x48, 0xEA, 0xC7, - 0xBD, 0xD1, 0x88, 0x04, 0x74, 0x38, 0x1D, 0x61, 0xC2, 0x40, 0xB6, 0x2A, 0xE2, 0x7D, 0x9A, 0xAC, - 0x49, 0xB4, 0xEE, 0xAC, 0xD1, 0xD6, 0x5C, 0xEB, 0x53, 0xB3, 0x9D, 0x47, 0x0D, 0xFA, 0xEB, 0xC1, - 0x94, 0x8B, 0x31, 0xBE, 0x1A, 0x46, 0x30, 0xA4, 0x8B, 0xA6, 0x57, 0xEA, 0x58, 0x30, 0x08, 0x8F, - 0x69, 0x83, 0x91, 0xEC, 0x0D, 0xA9, 0xD8, 0x5F, 0xD0, 0x42, 0x56, 0x16, 0x16, 0x76, 0x5E, 0xA4, - 0x53, 0x11, 0xCC, 0x09, 0x22, 0x0E, 0xEE, 0x24, 0x1C, 0x1A, 0x6A, 0x0A, 0x06, 0x0E, 0x7C, 0x5C, - 0xCB, 0x4D, 0x79, 0x9E, 0x3D, 0x50, 0x1E, 0xBC, 0xAA, 0x03, 0x4B, 0xBC, 0x00, 0x43, 0xFD, 0x60, - 0x79, 0x45, 0xEE, 0x60, 0x19, 0x97, 0xFA, 0x2F, 0xD0, 0x05, 0xD7, 0xFE, 0x8B, 0xD8, 0xFC, 0xEB, - 0x59, 0xFA, 0xF8, 0x20, 0x90, 0xE5, 0x95, 0x9B, 0xFF, 0x36, 0xED, 0xE0, 0x77, 0x3E, 0xF8, 0xDC, - 0xD0, 0x77, 0xFC, 0xBE, 0x0F, 0x67, 0x24, 0xED, 0xD3, 0x61, 0x36, 0x5D, 0xCD, 0x87, 0xBF, 0x41, - 0x6B, 0x1C, 0x37, 0x9C, 0x60, 0x1F, 0xB1, 0x84, 0xDB, 0x18, 0x69, 0x4D, 0xF6, 0xA7, 0x21, 0xCC, - 0x87, 0xFC, 0x6F, 0x58, 0x96, 0xA2, 0x98, 0x16, 0x96, 0xA4, 0x5E, 0x30, 0x60, 0xEA, 0xD3, 0x41, - 0x63, 0x54, 0x78, 0xE1, 0x0A, 0x1D, 0xB9, 0xBE, 0xB8, 0xD6, 0x37, 0x33, 0xA2, 0x77, 0xE8, 0x74, - 0x35, 0xC6, 0xC2, 0x5C, 0xB6, 0xB7, 0xEC, 0xC6, 0xA9, 0x9C, 0x2B, 0x94, 0xC7, 0xF7, 0xCC, 0x17, - 0xE7, 0x7B, 0xEA, 0x37, 0x46, 0xC9, 0x3D, 0x97, 0xD3, 0x28, 0x70, 0x27, 0x7D, 0x0A, 0x82, 0x0B, - 0xE6, 0x81, 0x69, 0x7F, 0xE4, 0xB2, 0x80, 0xE1, 0x86, 0x98, 0xF0, 0xBE, 0x1D, 0x5E, 0x6D, 0xC2, - 0xA1, 0xE5, 0xE1, 0x65, 0x84, 0x99, 0x38, 0x3A, 0xF3, 0x5D, 0x2F, 0x3A, 0xA3, 0xC1, 0x35, 0x2C, - 0x2A, 0xA5, 0xE5, 0xF3, 0x8C, 0x58, 0x0F, 0xE3, 0x5B, 0xB9, 0x53, 0x66, 0xD1, 0xE7, 0x82, 0xEB, - 0x83, 0x08, 0xE4, 0xE7, 0x39, 0xEB, 0xFD, 0xE1, 0x90, 0x05, 0xDD, 0xCF, 0x86, 0x3A, 0x9C, 0x9C, - 0xFA, 0x77, 0x33, 0x22, 0x39, 0xF6, 0x03, 0xBB, 0x31, 0x0A, 0xE1, 0x3F, 0x9C, 0xDD, 0xA0, 0xDA, - 0x52, 0x3C, 0x41, 0x64, 0xAE, 0xC6, 0x8C, 0x0C, 0xCD, 0x43, 0x36, 0x02, 0xCB, 0xF9, 0xD1, 0xE9, - 0xE1, 0x6F, 0x33, 0xA2, 0xDA, 0x3B, 0x3F, 0x9B, 0x0F, 0x4F, 0xB8, 0x84, 0x78, 0x97, 0x04, 0x12, - 0x3B, 0xEC, 0xB0, 0x7D, 0x66, 0x84, 0xF1, 0x62, 0xA6, 0x19, 0x9E, 0xBC, 0xCB, 0xCF, 0xB5, 0x10, - 0x26, 0x18, 0xF9, 0x74, 0x82, 0x56, 0x10, 0x13, 0xD8, 0xCB, 0xBB, 0x15, 0xBC, 0x24, 0x0E, 0x41, - 0xD4, 0x4B, 0xA3, 0x81, 0xB0, 0x2A, 0x6F, 0xD1, 0xD9, 0xD0, 0x4A, 0xB8, 0xE5, 0xCA, 0x94, 0x4C, - 0x9D, 0x49, 0xE6, 0x9B, 0x73, 0x33, 0x98, 0x1C, 0x8A, 0x1B, 0xFC, 0x59, 0xEA, 0xB0, 0x6A, 0xC7, - 0x55, 0x76, 0xB6, 0x60, 0x3F, 0xB3, 0x25, 0xE9, 0xA6, 0x78, 0x1F, 0x94, 0xE7, 0x17, 0x98, 0xAB, - 0x0F, 0xEE, 0x86, 0x98, 0x74, 0x85, 0x6B, 0x13, 0x46, 0xF7, 0xE0, 0x54, 0xA0, 0xC0, 0x46, 0xEC, - 0x6D, 0x8B, 0x96, 0xE7, 0x7B, 0xB4, 0xA5, 0x3E, 0xDC, 0xC0, 0x96, 0x44, 0xE5, 0x90, 0x57, 0xE0, - 0xE3, 0x7F, 0xE3, 0xA0, 0xE0, 0x55, 0x07, 0x14, 0xE7, 0xF1, 0xFD, 0xFE, 0x2F, 0x78, 0xBF, 0x18, - 0x7D, 0x05, 0x71, 0x13, 0x96, 0x25, 0x6B, 0x96, 0x70, 0x8B, 0x44, 0xF6, 0xC9, 0x43, 0x15, 0x3C, - 0xBB, 0x3D, 0xAB, 0x8A, 0xC0, 0xD2, 0x29, 0xC1, 0xEA, 0xEA, 0x51, 0xEA, 0xD6, 0x25, 0x75, 0x07, - 0xA3, 0x50, 0xBC, 0x1C, 0x81, 0xC9, 0xE4, 0x93, 0x7C, 0xC2, 0x7F, 0x9D, 0xD2, 0xE0, 0x9E, 0x3F, - 0x95, 0xE0, 0x07, 0xE0, 0x1A, 0x2E, 0xB6, 0x3A, 0xF2, 0x49, 0x73, 0x9B, 0x74, 0x94, 0x63, 0xB5, - 0x56, 0x41, 0x92, 0x6A, 0x89, 0x82, 0xD8, 0xF3, 0x84, 0xEF, 0xCB, 0xCB, 0xB2, 0xF7, 0x22, 0x31, - 0xBC, 0xBC, 0x2B, 0x03, 0x7C, 0xF9, 0xFE, 0xB5, 0x23, 0x32, 0x4E, 0xB3, 0x6B, 0x07, 0x6A, 0x09, - 0xF7, 0x2B, 0x59, 0x61, 0xDC, 0x63, 0x2F, 0x32, 0x8B, 0x92, 0xB6, 0x61, 0x4D, 0xB2, 0xBA, 0x7A, - 0x4E, 0xC7, 0xFE, 0x2D, 0x65, 0x91, 0x93, 0xB8, 0x3D, 0x89, 0x01, 0x96, 0xEC, 0x0F, 0x5E, 0x5E, - 0x57, 0x28, 0xE9, 0x91, 0xC1, 0x2B, 0xCF, 0x8F, 0x16, 0x3B, 0x7A, 0xD8, 0xE6, 0x52, 0x2C, 0xAF, - 0x40, 0xCE, 0x13, 0xF0, 0xB4, 0xC2, 0x8A, 0x17, 0x1C, 0x59, 0x71, 0x99, 0xF8, 0x90, 0x23, 0x93, - 0x2B, 0xF1, 0xA1, 0x04, 0x3A, 0x03, 0x11, 0x4C, 0x39, 0xBD, 0xD0, 0x5E, 0x80, 0x9F, 0x12, 0x2A, - 0xE0, 0xA3, 0x1E, 0xFD, 0x24, 0x72, 0xB9, 0x16, 0x0F, 0x49, 0x40, 0xB4, 0x89, 0x8F, 0xB8, 0xB0, - 0x3A, 0x2F, 0x85, 0xFB, 0xF7, 0x65, 0x2C, 0x19, 0x0E, 0x3D, 0x58, 0x58, 0xA0, 0x19, 0x29, 0x67, - 0x8A, 0xF3, 0x5B, 0xB0, 0x57, 0x6F, 0xE6, 0x5D, 0x5B, 0xE2, 0x78, 0xE0, 0x49, 0x0E, 0xF9, 0x2A, - 0x29, 0xE5, 0x29, 0xF3, 0x4C, 0x0D, 0x1A, 0x90, 0x45, 0xA5, 0xFC, 0x45, 0x1C, 0xF8, 0x2B, 0x3D, - 0x90, 0x01, 0xC2, 0x48, 0x9F, 0xD0, 0x58, 0x8C, 0x0B, 0xDB, 0xA4, 0x67, 0x59, 0xD6, 0x52, 0xD6, - 0xDA, 0xB1, 0x28, 0x0F, 0xB0, 0x72, 0x6D, 0xC2, 0x16, 0x76, 0x78, 0x4C, 0xA5, 0x58, 0x3F, 0x6C, - 0x23, 0x8F, 0x04, 0xD1, 0x96, 0x4B, 0x18, 0x6A, 0xCF, 0x0A, 0x5E, 0x11, 0x14, 0x41, 0x02, 0x8D, - 0x24, 0x12, 0x0A, 0x83, 0x11, 0xB5, 0x83, 0x98, 0x44, 0x35, 0xBC, 0x0B, 0x59, 0x1E, 0xFB, 0xD3, - 0xC1, 0x00, 0x56, 0x77, 0x8C, 0x4B, 0x29, 0x6B, 0x7F, 0x82, 0x47, 0x94, 0x9B, 0x38, 0x5C, 0xE0, - 0x89, 0xFB, 0xB3, 0x4C, 0xA5, 0x38, 0xAB, 0xA2, 0x33, 0x30, 0x06, 0xAB, 0xC8, 0x98, 0x29, 0x21, - 0xBF, 0x78, 0x39, 0x97, 0xBC, 0x5F, 0x74, 0x2D, 0x56, 0xCC, 0xA6, 0x95, 0x60, 0x76, 0x25, 0x1E, - 0xEF, 0x38, 0xE0, 0x21, 0x27, 0xCE, 0xBF, 0x9D, 0x80, 0x19, 0xBF, 0x45, 0x11, 0x92, 0x93, 0x70, - 0xB6, 0x53, 0x0C, 0x85, 0x37, 0x6D, 0x95, 0x28, 0x1E, 0xE3, 0x79, 0x01, 0x5F, 0xD0, 0xFF, 0x5D, - 0x59, 0x7D, 0x6B, 0xFB, 0x05, 0xB5, 0x39, 0xCC, 0x90, 0x2B, 0xE3, 0xCF, 0xD0, 0xA4, 0x62, 0x0E, - 0x0D, 0xB7, 0x63, 0x72, 0x7B, 0x5A, 0xF4, 0x51, 0xAA, 0xE3, 0x92, 0xF6, 0xC8, 0xFD, 0xD7, 0x12, - 0x8A, 0x2C, 0x9E, 0x79, 0x48, 0x2E, 0xC2, 0xE9, 0x4A, 0x23, 0xF5, 0xB7, 0xE6, 0x22, 0x18, 0x34, - 0x85, 0x3D, 0x89, 0x84, 0x78, 0xD9, 0x2D, 0x1C, 0xBE, 0xC5, 0x29, 0xE1, 0x43, 0x1B, 0x2F, 0xC7, - 0x44, 0x7C, 0x7A, 0xFB, 0x9B, 0xA4, 0x8C, 0xAC, 0x58, 0xCC, 0x09, 0xAC, 0x98, 0xD1, 0xB5, 0x60, - 0x18, 0x6F, 0x6C, 0x00, 0xBF, 0x27, 0xE0, 0xE4, 0x61, 0x1A, 0x92, 0x2B, 0x1A, 0xDD, 0xE1, 0x39, - 0xB2, 0xC5, 0xF6, 0x7E, 0xA0, 0xAC, 0xD5, 0x46, 0x3B, 0x36, 0x1A, 0xD9, 0x93, 0x90, 0x62, 0x46, - 0x47, 0x9E, 0x92, 0x85, 0xED, 0x76, 0xA8, 0xEA, 0x6B, 0xA2, 0x8F, 0xEB, 0xDA, 0xC7, 0xE4, 0x01, - 0xF1, 0x97, 0xF3, 0x81, 0x19, 0xE1, 0xAA, 0x70, 0xB1, 0x99, 0xCF, 0xC4, 0xE6, 0x2C, 0x72, 0x40, - 0xFA, 0x55, 0x25, 0xD1, 0x8C, 0x07, 0xA3, 0x1C, 0x44, 0xC5, 0x3E, 0x9F, 0x47, 0xC0, 0x70, 0x0F, - 0xF8, 0x35, 0xF9, 0x01, 0xAC, 0x43, 0x64, 0x93, 0x2C, 0x0A, 0x4C, 0x43, 0x10, 0x55, 0x3A, 0x1E, - 0x48, 0x50, 0x93, 0x43, 0x9A, 0x86, 0x2A, 0x4C, 0x3F, 0x2B, 0xAC, 0x74, 0x05, 0x3D, 0xC2, 0x9A, - 0x20, 0xD3, 0x49, 0x11, 0x00, 0x1F, 0xDA, 0x59, 0x02, 0x72, 0x5B, 0xC1, 0x19, 0x74, 0xD1, 0xA5, - 0x7F, 0xE7, 0xD2, 0x91, 0x13, 0x2E, 0xA6, 0xAF, 0xB0, 0xEC, 0x0B, 0x21, 0x08, 0x2F, 0x7A, 0x90, - 0xE6, 0x8C, 0xD1, 0xC5, 0x93, 0x08, 0x56, 0xEC, 0xE7, 0x89, 0xD4, 0x43, 0x20, 0xF1, 0x78, 0x53, - 0x10, 0xA9, 0xC7, 0xEE, 0x5B, 0x2E, 0x74, 0xDA, 0x2D, 0x08, 0x8A, 0xB7, 0xF3, 0xEB, 0xC2, 0xA1, - 0x4A, 0x09, 0x50, 0xF8, 0xB5, 0x1A, 0xF4, 0xDB, 0x34, 0x0B, 0x1A, 0x80, 0xB2, 0x9C, 0x68, 0xF5, - 0xA9, 0x32, 0x25, 0x12, 0xE0, 0x95, 0x29, 0x9F, 0x9D, 0x49, 0x82, 0x92, 0x77, 0x65, 0xAA, 0x41, - 0x4B, 0xC9, 0xD2, 0x18, 0x02, 0xFC, 0xB3, 0x12, 0xE4, 0xAF, 0xEE, 0x3B, 0x37, 0x05, 0xBC, 0x73, - 0xAF, 0xDD, 0x6A, 0x70, 0x17, 0xFB, 0x67, 0x9F, 0x0E, 0x24, 0x9E, 0x61, 0xA5, 0xF9, 0xC9, 0x99, - 0x54, 0x83, 0x65, 0x37, 0xA1, 0x53, 0x50, 0xE6, 0xCF, 0x57, 0x83, 0xCC, 0x2E, 0x35, 0xEF, 0x53, - 0x3C, 0x92, 0xAF, 0x57, 0x0D, 0x5B, 0xFF, 0x3E, 0x8C, 0xE8, 0x38, 0x45, 0x10, 0xF2, 0xBF, 0x2B, - 0xC1, 0x1E, 0xAA, 0x99, 0xEE, 0x00, 0x3A, 0xC9, 0x7D, 0x57, 0x09, 0xFE, 0xF4, 0x42, 0x12, 0x1E, - 0xA6, 0xC3, 0xAB, 0x04, 0xF5, 0x4E, 0x7A, 0x2A, 0x07, 0xE0, 0xE4, 0x25, 0x52, 0x0C, 0xCF, 0x9D, - 0x05, 0x7D, 0x76, 0xE3, 0xA3, 0x58, 0x0C, 0x49, 0xC2, 0x29, 0x67, 0x0C, 0x28, 0xCF, 0xDB, 0x91, - 0xDE, 0x82, 0xC7, 0x38, 0x83, 0x36, 0xBE, 0x60, 0xB6, 0xBE, 0x2D, 0x19, 0x53, 0x96, 0x97, 0x76, - 0x7D, 0x1B, 0x20, 0xED, 0xC0, 0x1E, 0xE0, 0x59, 0x9A, 0x6C, 0x4E, 0xD5, 0x51, 0xBF, 0x94, 0x90, - 0x66, 0x49, 0x8C, 0x73, 0xE8, 0x72, 0xC3, 0x6D, 0xD8, 0x39, 0x6F, 0xE3, 0x5B, 0x53, 0x96, 0xD5, - 0xED, 0xB5, 0xD9, 0x63, 0x59, 0x59, 0x7B, 0xCE, 0x4B, 0x99, 0x55, 0xEF, 0x5A, 0x0C, 0xC0, 0x64, - 0x40, 0x62, 0xA9, 0x22, 0xC9, 0x7D, 0x39, 0x8B, 0x1B, 0xDB, 0xA5, 0xC8, 0x65, 0x87, 0xA7, 0x5E, - 0x6B, 0xB1, 0xE9, 0x64, 0xDB, 0xCA, 0x9D, 0x4E, 0xB6, 0xAD, 0x0A, 0x64, 0x33, 0xA8, 0xF7, 0x4F, - 0x3F, 0xCE, 0x84, 0x39, 0xF1, 0x61, 0xF3, 0xB6, 0x97, 0x93, 0xB3, 0xB1, 0xAC, 0x77, 0x6B, 0xEA, - 0x73, 0x2F, 0x05, 0xDE, 0xB7, 0x41, 0x42, 0xC1, 0x07, 0x3F, 0x8C, 0x44, 0xEF, 0x6F, 0x64, 0x7A, - 0x7F, 0x23, 0xA7, 0xF7, 0xB3, 0xAD, 0xCF, 0x91, 0x40, 0x86, 0x1C, 0x5A, 0x30, 0x4E, 0x6E, 0x1B, - 0xFF, 0xE9, 0x14, 0xD9, 0xC7, 0x7A, 0x94, 0x0C, 0x2D, 0x63, 0x2F, 0x65, 0xB1, 0x3D, 0x6F, 0x4E, - 0x6A, 0xCD, 0xD2, 0xE9, 0xAC, 0x59, 0x8D, 0x5B, 0xC6, 0xDB, 0xF1, 0x29, 0xA4, 0x41, 0xBE, 0x34, - 0xB3, 0x05, 0x58, 0x9F, 0x19, 0xC1, 0xE8, 0x5B, 0x6F, 0xE8, 0x77, 0x06, 0xFE, 0x18, 0xFF, 0xC2, - 0xAF, 0x64, 0x8C, 0x8C, 0x61, 0x0A, 0x5D, 0x30, 0x2C, 0x2E, 0x78, 0xAC, 0x63, 0xDB, 0x1D, 0x61, - 0x5C, 0x62, 0x00, 0x3E, 0x51, 0x31, 0x6B, 0xF1, 0x79, 0x1D, 0xE1, 0xE7, 0x65, 0x18, 0x65, 0x7B, - 0x07, 0xB6, 0x52, 0x1C, 0xFB, 0x61, 0xA4, 0xA4, 0xC8, 0xBB, 0x17, 0x12, 0xB0, 0x59, 0xB4, 0x43, - 0x38, 0x3D, 0xFB, 0x9E, 0xDC, 0xD9, 0x60, 0x32, 0x40, 0x0E, 0x8E, 0x1B, 0xB2, 0xD0, 0xD0, 0xD3, - 0x8B, 0xF3, 0xA3, 0x33, 0xDC, 0xF6, 0x61, 0xD1, 0x91, 0x23, 0x9F, 0x73, 0x43, 0xE8, 0x77, 0xF0, - 0x28, 0x70, 0x23, 0x2D, 0x4E, 0x2D, 0xD7, 0x89, 0x29, 0x4A, 0xCB, 0x14, 0xF8, 0x8B, 0xEF, 0x03, - 0xE1, 0x4A, 0x93, 0xCB, 0xA8, 0x40, 0x32, 0x92, 0x00, 0x44, 0x2B, 0xAA, 0xC1, 0x0B, 0xC5, 0xE9, - 0x75, 0xAD, 0x6E, 0x45, 0x38, 0x45, 0x0B, 0x5A, 0x57, 0x23, 0x27, 0xB8, 0xEC, 0x4F, 0xEC, 0xE0, - 0xDB, 0xBB, 0xA9, 0xD7, 0x6D, 0xD5, 0xC6, 0x71, 0xF6, 0x6B, 0x3D, 0x7E, 0xE3, 0x0E, 0x8F, 0x68, - 0x18, 0xFD, 0x1F, 0xFC, 0x51, 0xBF, 0xC9, 0x88, 0x02, 0xC8, 0x02, 0x12, 0x0D, 0x6E, 0xA8, 0x8E, - 0xAC, 0x0B, 0x91, 0xD5, 0xF0, 0xFD, 0xFB, 0xBD, 0x9C, 0xA0, 0x13, 0x80, 0xD3, 0xB6, 0xFB, 0xD0, - 0xBF, 0x83, 0x05, 0x47, 0x92, 0xCA, 0x3D, 0xDD, 0xE8, 0x5C, 0x5D, 0x1D, 0xB3, 0x45, 0x1F, 0xD6, - 0x70, 0x9D, 0x90, 0x84, 0x91, 0x1D, 0x30, 0x1D, 0x60, 0x4A, 0xA5, 0x5D, 0xC7, 0x7C, 0xF1, 0x83, - 0xD2, 0x08, 0xE2, 0xD2, 0x2E, 0x65, 0xA5, 0x78, 0xE3, 0x71, 0x81, 0xE7, 0x68, 0x71, 0x9D, 0x7F, - 0xDB, 0xD5, 0xB8, 0xFF, 0x2A, 0x2F, 0x7A, 0x4D, 0xBB, 0x59, 0x12, 0x89, 0xBC, 0x2D, 0x2C, 0x73, - 0x54, 0xBA, 0x04, 0xC8, 0x77, 0x1A, 0x77, 0xB2, 0xB1, 0x97, 0xFA, 0xDA, 0xD3, 0x1C, 0x53, 0x2C, - 0x27, 0xDC, 0xAA, 0xDE, 0x31, 0x2C, 0x82, 0x7E, 0xBE, 0xD2, 0x62, 0x28, 0x9F, 0x95, 0xC4, 0xD8, - 0x1A, 0xB1, 0x48, 0x6A, 0x26, 0x9D, 0xC7, 0xC5, 0xA5, 0x41, 0xEB, 0xEB, 0x65, 0xAE, 0x97, 0xD8, - 0xAF, 0x2C, 0x4D, 0xFD, 0xDA, 0x67, 0xA9, 0x28, 0xC7, 0x8D, 0xE4, 0x38, 0xAE, 0x25, 0x44, 0xB6, - 0xD4, 0x2F, 0x53, 0xBC, 0x19, 0x5B, 0x9B, 0xDE, 0x00, 0xF9, 0x1F, 0xD5, 0xE4, 0x6A, 0xE3, 0xE5, - 0xA9, 0x5A, 0x5C, 0x77, 0xAC, 0xA8, 0x4F, 0x6C, 0xF1, 0x3C, 0xB9, 0xF1, 0xDD, 0xD7, 0xF2, 0x11, - 0x53, 0xF0, 0x40, 0xD7, 0x0C, 0x92, 0xCD, 0x5C, 0x59, 0xFE, 0x51, 0xD2, 0x55, 0x7C, 0x5C, 0x09, - 0x16, 0xD7, 0x31, 0xE0, 0x6E, 0xE2, 0x63, 0x1E, 0xE6, 0x65, 0x4C, 0x97, 0x6F, 0x4C, 0x61, 0x79, - 0xE1, 0xFE, 0xD8, 0x5C, 0x15, 0x52, 0xBF, 0xB8, 0xFD, 0x4F, 0x29, 0xB5, 0x78, 0x47, 0x2F, 0x47, - 0xA9, 0x59, 0x3E, 0x66, 0x69, 0x59, 0x1A, 0xAF, 0xA8, 0x0C, 0x01, 0x53, 0x15, 0x17, 0x54, 0x62, - 0x81, 0xE3, 0x5F, 0x85, 0x28, 0x5C, 0x96, 0x70, 0x9C, 0x0E, 0x7C, 0xCF, 0x41, 0x97, 0x7D, 0xD3, - 0x62, 0xCD, 0x31, 0x34, 0x66, 0xD3, 0x12, 0xAF, 0xBD, 0xC8, 0x0D, 0x79, 0x6B, 0xCC, 0xC9, 0x5F, - 0x4C, 0xEC, 0xCC, 0x0F, 0x5D, 0xFC, 0xFF, 0xDE, 0x60, 0x30, 0x85, 0x65, 0xCC, 0x3D, 0x5F, 0xE8, - 0x6C, 0xA0, 0x20, 0x33, 0x44, 0xBB, 0x1D, 0x46, 0x75, 0xA3, 0x53, 0x40, 0x35, 0x25, 0xAB, 0xF8, - 0xA4, 0x2C, 0xDA, 0xEA, 0x90, 0xA5, 0x07, 0x6B, 0x93, 0x95, 0x6E, 0x6F, 0xCB, 0xEA, 0x59, 0x9B, - 0x9D, 0x8D, 0xCD, 0x2D, 0x99, 0x51, 0x33, 0xC4, 0x67, 0x84, 0x58, 0x7F, 0xD9, 0xDD, 0xDC, 0xB2, - 0xD6, 0x3B, 0xEB, 0xD6, 0x5A, 0x39, 0xC4, 0xEF, 0x00, 0xB1, 0x6E, 0x6D, 0x6D, 0x6E, 0x6E, 0x6E, - 0x74, 0xD6, 0xB7, 0xD6, 0x8B, 0x01, 0x8E, 0xED, 0x88, 0x25, 0x2A, 0x47, 0x90, 0x8E, 0xB5, 0x6D, - 0xF5, 0xB6, 0xD7, 0x5F, 0x6E, 0x97, 0x80, 0xF8, 0xDE, 0x50, 0xC0, 0xAC, 0x74, 0x2D, 0x90, 0xD5, - 0xD6, 0x86, 0xB5, 0xF1, 0x72, 0xB3, 0x5B, 0x0C, 0xB5, 0x37, 0x8A, 0xDC, 0x68, 0xEA, 0xB0, 0x2D, - 0x92, 0x8D, 0x4D, 0xA0, 0xB5, 0xB5, 0xAD, 0x2C, 0xBF, 0xB4, 0x03, 0x1B, 0x15, 0x43, 0x8E, 0x7A, - 0xE4, 0x52, 0x2C, 0xEE, 0x61, 0xE8, 0x41, 0xB9, 0xAB, 0x62, 0x25, 0x2E, 0x0E, 0xB3, 0x2B, 0xD0, - 0xE7, 0x86, 0xA2, 0x6D, 0x2E, 0xDE, 0x5A, 0x22, 0x2E, 0xB1, 0x20, 0x9A, 0x6E, 0xBE, 0xB4, 0xD8, - 0xBF, 0x36, 0x49, 0x7E, 0x49, 0xC6, 0x41, 0x5C, 0x86, 0x83, 0x40, 0xFC, 0x5A, 0x3E, 0xFC, 0xCA, - 0x88, 0x7E, 0xFE, 0x11, 0x44, 0x7F, 0x7F, 0x0C, 0xA2, 0x0F, 0x45, 0xB1, 0xCA, 0xF5, 0xCD, 0x41, - 0x33, 0x93, 0x50, 0xCB, 0x2C, 0x64, 0xE5, 0x95, 0x06, 0x2D, 0x81, 0xB1, 0xFF, 0x85, 0x06, 0x98, - 0x0E, 0x1F, 0xBE, 0xAD, 0xB2, 0xFB, 0x42, 0x69, 0x46, 0x88, 0x4A, 0x82, 0x96, 0xB4, 0x71, 0xA5, - 0xDB, 0xB5, 0xD6, 0xD6, 0xDB, 0x64, 0x6B, 0x4B, 0xD9, 0x1A, 0xE5, 0x9F, 0x51, 0xC8, 0x58, 0x50, - 0xC1, 0xA8, 0xE6, 0x90, 0xD3, 0xEF, 0x15, 0x20, 0x41, 0x7C, 0x0A, 0x61, 0x43, 0xA1, 0xB5, 0xC1, - 0x1E, 0x17, 0xD8, 0x68, 0xAC, 0x3D, 0xE6, 0xE8, 0x43, 0xA0, 0xD5, 0xE3, 0x33, 0x6E, 0x4F, 0x9B, - 0x78, 0xF9, 0x77, 0xFE, 0x02, 0x82, 0xD5, 0xA9, 0xAC, 0x40, 0x0F, 0xB9, 0x7B, 0x95, 0x49, 0x50, - 0x6D, 0x93, 0xBD, 0x4A, 0x0E, 0x9C, 0xEE, 0x21, 0x5D, 0x5A, 0x95, 0xF7, 0xAA, 0x65, 0x78, 0xC6, - 0xB4, 0x55, 0x65, 0xB7, 0x52, 0x26, 0x88, 0x9B, 0x4E, 0x31, 0xC1, 0xE2, 0xFD, 0xCA, 0xEA, 0xB4, - 0x72, 0x5B, 0x87, 0xDB, 0x3D, 0x8C, 0x98, 0xA5, 0xB5, 0xCE, 0x9A, 0xB1, 0x75, 0x85, 0x14, 0xCF, - 0x7E, 0x7D, 0x2A, 0x9A, 0xE9, 0x5E, 0xDA, 0xA3, 0xF4, 0x61, 0x21, 0xC5, 0xA7, 0x6B, 0xA5, 0xA4, - 0xA9, 0xDD, 0xE6, 0x14, 0xBB, 0x8D, 0x34, 0x55, 0x10, 0xD4, 0x35, 0xD5, 0x2A, 0xD6, 0xD4, 0x6E, - 0x33, 0x4D, 0x7D, 0x8C, 0xD6, 0x95, 0x69, 0xEA, 0x13, 0xD1, 0x94, 0x34, 0xF5, 0xC9, 0x29, 0x3E, - 0x5D, 0x2B, 0x25, 0x4D, 0xED, 0x35, 0xA7, 0xD8, 0x6B, 0xA4, 0xA9, 0xBD, 0x46, 0x9A, 0xDA, 0x6B, - 0xA6, 0xA9, 0x8F, 0xD1, 0xBA, 0x32, 0x4D, 0x7D, 0x22, 0x9A, 0x92, 0xA6, 0x3E, 0x39, 0xC5, 0xA7, - 0x6B, 0xA5, 0xA4, 0xA9, 0x6B, 0xCD, 0x29, 0xAE, 0x35, 0xD2, 0xD4, 0xB5, 0x46, 0x9A, 0xBA, 0xD6, - 0x4C, 0x53, 0x1F, 0xA3, 0x75, 0x65, 0x9A, 0xFA, 0x44, 0x34, 0x25, 0x4D, 0x7D, 0x72, 0x8A, 0x73, - 0x6A, 0xE5, 0x73, 0x3F, 0x6E, 0x35, 0xBA, 0xCA, 0xB5, 0x0E, 0x5C, 0x8D, 0xBE, 0x6F, 0xA5, 0x23, - 0x57, 0xA3, 0x23, 0x5B, 0xF7, 0xF0, 0x33, 0xC7, 0x37, 0x6D, 0x55, 0x85, 0xD4, 0x3C, 0x4C, 0x7E, - 0xE6, 0xEB, 0xDC, 0x79, 0xD1, 0x9D, 0xD7, 0xAB, 0x8F, 0x23, 0xA6, 0xFE, 0xEB, 0xF9, 0xC6, 0xDD, - 0xB9, 0xBF, 0xFE, 0xA1, 0x1E, 0xFF, 0x89, 0x07, 0xD8, 0x6A, 0x20, 0x76, 0xE6, 0x01, 0xD4, 0x97, - 0x79, 0x03, 0x72, 0x92, 0x63, 0xD5, 0x44, 0xCC, 0x0D, 0xE1, 0xEA, 0x52, 0xD4, 0x5C, 0x95, 0x26, - 0x22, 0xED, 0x35, 0x13, 0x69, 0xAF, 0xB1, 0x48, 0x7B, 0x0D, 0x45, 0xDA, 0x6B, 0x2C, 0xD2, 0x5E, - 0x43, 0x91, 0xAE, 0x35, 0x14, 0xE9, 0x5A, 0x33, 0x91, 0xAE, 0x35, 0x16, 0xE9, 0x5A, 0x43, 0x91, - 0xAE, 0x35, 0x16, 0xA9, 0x0E, 0x99, 0x1C, 0x28, 0xC8, 0x37, 0x6A, 0x4D, 0x07, 0x0B, 0x65, 0xF7, - 0x6E, 0x0B, 0xB6, 0x42, 0xE2, 0x0C, 0x00, 0xEC, 0x82, 0xBD, 0x84, 0xE0, 0x80, 0xBD, 0x6E, 0x24, - 0x02, 0xEF, 0x2E, 0xFC, 0x6F, 0xD4, 0x8B, 0x13, 0x51, 0xEC, 0xBC, 0xD0, 0xF2, 0x9F, 0x4C, 0x69, - 0x92, 0x4E, 0x5D, 0x7F, 0x61, 0xC2, 0x18, 0x08, 0x58, 0x4C, 0xA5, 0x4D, 0xD6, 0x36, 0xF9, 0x7F, - 0xC9, 0xD4, 0xB9, 0xB6, 0x99, 0x17, 0x17, 0x78, 0x66, 0x0A, 0x51, 0x2A, 0xDC, 0x23, 0x2F, 0xA5, - 0xDE, 0x6A, 0xE9, 0xF7, 0x69, 0xA7, 0x91, 0xFF, 0x17, 0x7A, 0x7F, 0x4E, 0x3D, 0x7A, 0x67, 0x8F, - 0x72, 0x62, 0x5E, 0xA4, 0xAE, 0x0A, 0x0A, 0xBA, 0x48, 0xBF, 0xC4, 0x5C, 0xEF, 0xF8, 0x87, 0xCA, - 0xD0, 0x78, 0xE5, 0xE7, 0x2D, 0x3F, 0x73, 0xE1, 0xD8, 0xD8, 0x26, 0xC7, 0xA6, 0x95, 0xD9, 0xA6, - 0xED, 0xF2, 0x43, 0xA0, 0x36, 0x7E, 0xD5, 0xB6, 0x68, 0xCF, 0xCC, 0xCF, 0x21, 0x97, 0x91, 0x3E, - 0x66, 0xBD, 0x3D, 0x27, 0x82, 0x89, 0xE4, 0x30, 0x68, 0xB8, 0x2C, 0x88, 0x14, 0x43, 0x89, 0x4F, - 0xA1, 0xD1, 0x7E, 0xF0, 0xED, 0xD2, 0xEA, 0xF7, 0x8F, 0x0E, 0x2A, 0x3B, 0x5A, 0x86, 0xD0, 0x64, - 0x43, 0x28, 0xA5, 0x91, 0xCE, 0x99, 0x1D, 0x86, 0xF0, 0x9B, 0xF3, 0x04, 0xB4, 0xBA, 0x4F, 0xD4, - 0xA6, 0xEE, 0x13, 0xB6, 0xA9, 0xF7, 0x44, 0x6D, 0xEA, 0x3D, 0x61, 0x9B, 0xD6, 0x9E, 0xA8, 0x4D, - 0x6B, 0x73, 0x6A, 0x93, 0x18, 0x62, 0x17, 0xFB, 0x67, 0xAB, 0x9F, 0x0E, 0xCE, 0xF2, 0xED, 0xD3, - 0xC5, 0xA0, 0x76, 0xAC, 0xAF, 0x30, 0x10, 0xC9, 0x75, 0xF1, 0x34, 0xE6, 0x76, 0x73, 0x63, 0x63, - 0x2D, 0x13, 0xE5, 0xCB, 0x3E, 0xCA, 0x8C, 0x2A, 0x31, 0xFF, 0x25, 0xEB, 0xAD, 0x84, 0x88, 0x14, - 0x47, 0x5C, 0x3D, 0x8A, 0xDC, 0x44, 0xE9, 0xC1, 0x2C, 0x84, 0xBA, 0x87, 0x08, 0xA9, 0x10, 0x38, - 0xE4, 0x3C, 0x84, 0x60, 0x62, 0xED, 0x93, 0xD3, 0x94, 0xB5, 0xA9, 0x33, 0x77, 0xD6, 0x56, 0x57, - 0x3F, 0x7A, 0x24, 0xBE, 0xB2, 0xD0, 0x26, 0x50, 0x91, 0xF0, 0xDE, 0x61, 0x11, 0x14, 0x9C, 0x1A, - 0x7B, 0x40, 0x1B, 0x97, 0x9D, 0x80, 0x9F, 0x37, 0xC1, 0xC1, 0x37, 0xBA, 0x71, 0xFD, 0x19, 0x62, - 0x24, 0x47, 0x04, 0xB3, 0x58, 0x1C, 0x35, 0x31, 0x05, 0x24, 0xBE, 0x47, 0x50, 0x73, 0xDB, 0x58, - 0xE3, 0x5E, 0xBC, 0xBE, 0xDD, 0xE9, 0xC4, 0x2B, 0x53, 0x1E, 0x6C, 0x2F, 0xB2, 0x80, 0x9D, 0x4C, - 0x23, 0xFA, 0x3D, 0xAB, 0xB8, 0x78, 0x69, 0x42, 0xEB, 0x46, 0xF8, 0xD4, 0x98, 0xB9, 0x22, 0x51, - 0xC4, 0x37, 0xD6, 0xD9, 0x2D, 0xF6, 0xDC, 0x31, 0x25, 0x92, 0x79, 0xD4, 0xEB, 0xAE, 0x11, 0x00, - 0x25, 0x07, 0xEC, 0xE0, 0xC5, 0xBD, 0x0B, 0xE8, 0x5F, 0xA7, 0xD4, 0x63, 0x07, 0xF3, 0xDB, 0xD6, - 0x1A, 0xFC, 0xE8, 0xBD, 0x94, 0xBA, 0x0E, 0x3E, 0xB1, 0x2D, 0xA2, 0xDE, 0x4B, 0x99, 0x5F, 0xF9, - 0x4A, 0x4C, 0xF1, 0xF4, 0x8E, 0xE4, 0x40, 0x26, 0xAE, 0x3D, 0x62, 0xF1, 0x3B, 0x36, 0xF3, 0x1C, - 0xC5, 0xA5, 0xE2, 0x4B, 0x1C, 0x44, 0xDD, 0x4C, 0x90, 0x49, 0xD7, 0x14, 0x5C, 0x62, 0xA0, 0x98, - 0x86, 0x7A, 0x49, 0x69, 0x46, 0x8B, 0xEF, 0x6C, 0x64, 0xEE, 0x57, 0x87, 0xC7, 0xEE, 0x35, 0x15, - 0xBD, 0x81, 0x47, 0x96, 0x3D, 0x99, 0x11, 0x7E, 0x62, 0xD9, 0x53, 0xF8, 0xC8, 0xBF, 0xD2, 0xB3, - 0x24, 0xE5, 0x5C, 0x08, 0xA1, 0x23, 0x58, 0xCA, 0xA5, 0x62, 0x76, 0xE6, 0x78, 0x70, 0xFA, 0x94, - 0x07, 0xA6, 0xA2, 0x99, 0xFC, 0x3E, 0x52, 0x91, 0x7A, 0xC6, 0x69, 0x54, 0xEA, 0x69, 0xE8, 0xD8, - 0xFE, 0x0E, 0xA0, 0x17, 0x6E, 0x7C, 0x9D, 0xA7, 0x6B, 0x6D, 0x40, 0x27, 0x64, 0xFC, 0xC0, 0x6E, - 0x1B, 0xBE, 0xB7, 0x7B, 0xAA, 0x9A, 0x28, 0x77, 0xA4, 0x8A, 0x35, 0x93, 0x93, 0x91, 0x3D, 0xCE, - 0x59, 0x09, 0x55, 0x58, 0x24, 0x28, 0x6D, 0xDB, 0xB4, 0xC8, 0x9F, 0x49, 0x2F, 0x3F, 0x40, 0x48, - 0xE3, 0x50, 0xAD, 0x6E, 0x3C, 0xA7, 0x56, 0x92, 0xD7, 0xD4, 0x93, 0x7A, 0x0A, 0x1A, 0x07, 0xDA, - 0x25, 0x6E, 0x78, 0xD6, 0x03, 0x9F, 0x87, 0x28, 0xCC, 0x04, 0xAD, 0xC2, 0xE6, 0x99, 0x52, 0xEA, - 0xD4, 0x6B, 0xA6, 0x2D, 0xA1, 0x60, 0xF6, 0x3E, 0xCE, 0x20, 0x99, 0x1E, 0x8E, 0x9B, 0x4F, 0xC7, - 0xB7, 0xE7, 0xD0, 0xE4, 0x02, 0xE2, 0xA5, 0xED, 0xCE, 0xA4, 0x31, 0xAD, 0xD4, 0x5C, 0x35, 0x6B, - 0x2A, 0x77, 0xF5, 0x7A, 0xDB, 0xEB, 0xDB, 0x9B, 0x2F, 0x33, 0xFE, 0x5E, 0x1B, 0xBE, 0xB7, 0xA1, - 0x60, 0x0E, 0xED, 0xCC, 0x50, 0x65, 0xF1, 0x2C, 0xF8, 0xD2, 0x95, 0xD8, 0x39, 0x36, 0x35, 0xB5, - 0x7E, 0x86, 0xCE, 0x4A, 0x12, 0x28, 0x49, 0x1C, 0xCA, 0x6F, 0x5F, 0x5B, 0xEB, 0x5B, 0x8A, 0x9A, - 0x8B, 0x19, 0x68, 0xBD, 0xBD, 0x35, 0x17, 0x55, 0x2F, 0xE7, 0xA1, 0x48, 0x40, 0xAB, 0xAB, 0xB1, - 0x2B, 0x94, 0xC8, 0x2B, 0xF7, 0x96, 0x8A, 0x59, 0x14, 0x47, 0x67, 0x7B, 0xFC, 0x1E, 0xD6, 0x62, - 0x72, 0xED, 0xF3, 0xE8, 0xAC, 0x25, 0xB5, 0xD7, 0xF3, 0xBC, 0x8E, 0xF4, 0x9F, 0xDC, 0x64, 0xED, - 0xE6, 0x68, 0x8E, 0x4D, 0x35, 0x50, 0x38, 0x38, 0xED, 0x3F, 0x36, 0x89, 0xF7, 0x60, 0x01, 0xEE, - 0xEC, 0xFB, 0xC7, 0x26, 0xD3, 0x9F, 0x5E, 0xC1, 0xCF, 0xB9, 0x52, 0x89, 0x37, 0x3F, 0x44, 0xE5, - 0xD3, 0x68, 0x22, 0xBC, 0x67, 0x2B, 0xEB, 0x3D, 0x5B, 0x46, 0xEF, 0xD9, 0x4C, 0x27, 0x51, 0x99, - 0xD3, 0x8B, 0xB3, 0xA6, 0xDA, 0x92, 0x9C, 0x23, 0x02, 0x4F, 0xA3, 0xD1, 0xE1, 0xF7, 0x89, 0xEF, - 0x71, 0xF7, 0x17, 0x9C, 0xC3, 0xAE, 0x6C, 0x37, 0x98, 0x67, 0xD8, 0x55, 0x0C, 0x46, 0x7A, 0x4F, - 0xB8, 0xEC, 0x90, 0x72, 0x02, 0xDC, 0x0C, 0x5C, 0x96, 0x70, 0x1D, 0x5C, 0x12, 0xBC, 0xDA, 0xA8, - 0xF8, 0x22, 0x6B, 0xAC, 0xD5, 0x56, 0x43, 0xDC, 0xE7, 0x60, 0x7E, 0x0E, 0xE8, 0x88, 0xA9, 0x86, - 0xD5, 0x66, 0x89, 0x6D, 0xB5, 0xAD, 0x24, 0x86, 0xBE, 0x6B, 0xDC, 0x4A, 0xAA, 0x4B, 0xC7, 0x0D, - 0x27, 0x22, 0x73, 0xFC, 0x63, 0x10, 0x4B, 0x4F, 0x04, 0x27, 0xE7, 0xF4, 0x9A, 0x06, 0xE0, 0xAA, - 0xD3, 0x23, 0x47, 0x2C, 0x51, 0x33, 0x2B, 0x54, 0xB6, 0x40, 0x0D, 0x0B, 0x09, 0x3C, 0xC4, 0x39, - 0x45, 0x72, 0x9E, 0x07, 0xD7, 0xB2, 0x8B, 0x60, 0xDE, 0x37, 0x51, 0x45, 0x4A, 0x38, 0xA6, 0xE6, - 0x5D, 0x90, 0xEE, 0xF7, 0xCA, 0x57, 0xB9, 0x77, 0x49, 0x57, 0xC9, 0x92, 0x94, 0x64, 0x09, 0x5A, - 0xC0, 0xD7, 0x25, 0xDE, 0x46, 0xDE, 0x02, 0xF0, 0x79, 0x06, 0x96, 0x12, 0x4C, 0x27, 0x33, 0x98, - 0x2C, 0x6F, 0x8A, 0x84, 0x61, 0x19, 0x3E, 0xB0, 0x3F, 0x5B, 0xBA, 0x8F, 0x14, 0x67, 0xDD, 0x49, - 0x30, 0x49, 0x15, 0x1E, 0xF5, 0x39, 0xF3, 0x07, 0xF5, 0xD2, 0x88, 0xC4, 0xEC, 0x9B, 0xB9, 0xB5, - 0x36, 0x7C, 0x96, 0xCD, 0xFD, 0xBB, 0xB2, 0x77, 0x5D, 0x25, 0x65, 0xEE, 0xB1, 0x6F, 0x63, 0x3E, - 0xAA, 0x0E, 0x11, 0xAD, 0xBE, 0xB3, 0xDD, 0x08, 0x96, 0xDC, 0x0B, 0x72, 0x98, 0xBE, 0x59, 0x07, - 0xCD, 0xF7, 0x42, 0xE2, 0x4B, 0x21, 0xD9, 0x86, 0xBE, 0x8A, 0x99, 0x4F, 0x4E, 0x12, 0x5E, 0xC8, - 0xCF, 0xD9, 0xF2, 0x6C, 0x79, 0xBA, 0x9B, 0xAD, 0x76, 0x8E, 0x54, 0x2C, 0xA7, 0x8A, 0x92, 0x3B, - 0xAF, 0x6F, 0xDF, 0x62, 0x73, 0x3A, 0x1D, 0x25, 0x28, 0x56, 0xCB, 0xAB, 0xD5, 0x4A, 0x73, 0x03, - 0xB7, 0x8B, 0x04, 0xDF, 0x56, 0x90, 0x0C, 0x69, 0x5E, 0x26, 0x92, 0x4C, 0x4E, 0x14, 0x39, 0x39, - 0xCB, 0x2C, 0x39, 0x49, 0x66, 0xCF, 0x4B, 0x32, 0x4B, 0x6E, 0x92, 0xF9, 0xE4, 0x27, 0x99, 0x3D, - 0x47, 0xC9, 0x6C, 0x79, 0x4A, 0x66, 0xC9, 0x55, 0x32, 0x6B, 0xBE, 0x92, 0xD9, 0x72, 0x96, 0xCC, - 0x3F, 0x6F, 0x49, 0x21, 0xC6, 0x74, 0x4B, 0x24, 0x45, 0xE4, 0xA6, 0xDF, 0x2A, 0xE3, 0x29, 0xC9, - 0x81, 0x52, 0x8E, 0xA0, 0x62, 0x22, 0x94, 0xE6, 0xC9, 0x50, 0x66, 0x4D, 0x88, 0x92, 0xCD, 0x42, - 0x8A, 0x16, 0x88, 0xD3, 0xFB, 0x07, 0x98, 0x80, 0x9F, 0xD7, 0xFC, 0x68, 0x9C, 0xBE, 0x1E, 0x6B, - 0x46, 0x10, 0xFE, 0x77, 0x26, 0x29, 0x98, 0x9E, 0xC3, 0x45, 0xCA, 0xE8, 0xB7, 0xC8, 0xED, 0xBE, - 0x54, 0x7E, 0xF9, 0xFE, 0xAC, 0xAF, 0xAE, 0x71, 0x79, 0x1A, 0xC0, 0x84, 0x95, 0x3F, 0xFD, 0x89, - 0x98, 0xA0, 0x40, 0x21, 0x46, 0x2C, 0x77, 0x78, 0x5D, 0xC8, 0xB7, 0xD4, 0x3D, 0xF0, 0xA7, 0x4D, - 0x48, 0x1E, 0x7F, 0x3C, 0xDD, 0xEB, 0x1B, 0x99, 0x5D, 0xD2, 0x9C, 0x05, 0x53, 0xEA, 0x8F, 0xB2, - 0x69, 0x4D, 0xD2, 0x0F, 0x36, 0x75, 0x29, 0x42, 0x94, 0x55, 0xE5, 0xC6, 0xC7, 0xB8, 0x33, 0x58, - 0xA3, 0x10, 0x85, 0x3F, 0x59, 0x47, 0x52, 0x25, 0x5A, 0x5E, 0xD6, 0x15, 0xC3, 0xA4, 0x02, 0xAD, - 0x2C, 0x45, 0x63, 0xBA, 0xB7, 0xB7, 0x6E, 0x74, 0x62, 0x4F, 0xD2, 0x44, 0x6E, 0x63, 0xD7, 0x83, - 0x1F, 0xF6, 0xF7, 0x36, 0xB9, 0x62, 0x25, 0x52, 0x2E, 0xCC, 0x76, 0x62, 0x14, 0x8E, 0x0E, 0xA4, - 0x51, 0x1C, 0x47, 0x48, 0x24, 0x4F, 0x26, 0x70, 0xF6, 0xC6, 0x76, 0xF8, 0x8D, 0x17, 0x70, 0x44, - 0x4A, 0x21, 0x53, 0x1C, 0x0E, 0xFB, 0x1A, 0x49, 0xF2, 0xCC, 0x13, 0xFC, 0xC3, 0x1B, 0x24, 0xCF, - 0x3F, 0x2C, 0x32, 0x24, 0xD0, 0x75, 0x5D, 0xF2, 0xFA, 0x35, 0xA7, 0x05, 0x1D, 0x03, 0x7D, 0x64, - 0xE9, 0xFD, 0x53, 0x90, 0x44, 0xD3, 0x9C, 0x98, 0x53, 0x82, 0x95, 0x5A, 0x55, 0xD6, 0xA3, 0x45, - 0xBD, 0x90, 0xD9, 0x3A, 0x89, 0x53, 0x7D, 0x4A, 0x06, 0x31, 0xBE, 0xD3, 0x0D, 0xED, 0x37, 0xDC, - 0x89, 0x0A, 0x09, 0x58, 0x50, 0xE2, 0xC0, 0x9A, 0x72, 0x02, 0xF6, 0x9C, 0xED, 0xA1, 0xA8, 0x9D, - 0x95, 0xDC, 0xAD, 0x92, 0xB2, 0x26, 0xBB, 0x18, 0x6B, 0xA1, 0xDE, 0x16, 0xDC, 0x49, 0xD3, 0x24, - 0x27, 0x4D, 0x23, 0xBB, 0xC6, 0xAD, 0xF0, 0xF4, 0x45, 0x08, 0x87, 0x46, 0x60, 0xEA, 0xA9, 0xF3, - 0x0E, 0x56, 0xD9, 0x02, 0x4F, 0xFA, 0x04, 0x46, 0x92, 0x8D, 0xF9, 0x36, 0x7E, 0x66, 0x03, 0xAF, - 0x35, 0xF2, 0x57, 0xA5, 0x5C, 0x07, 0xA6, 0x3F, 0xF7, 0xFA, 0x3E, 0x79, 0xBB, 0x6A, 0x51, 0x56, - 0x86, 0xA5, 0xA4, 0xBF, 0x55, 0xB0, 0x5D, 0xA2, 0x5E, 0x91, 0x0C, 0x3B, 0xFB, 0x1F, 0x3F, 0x9E, - 0x1F, 0x1C, 0x9D, 0xEE, 0x5D, 0x1C, 0x5E, 0x1E, 0x9D, 0x9E, 0x7D, 0xBA, 0xB8, 0xBC, 0xF8, 0x7C, - 0x86, 0xBF, 0xFE, 0xB2, 0x77, 0x7C, 0x74, 0x70, 0xF9, 0xE9, 0xF4, 0x2F, 0xA7, 0x1F, 0x7F, 0x3D, - 0xD5, 0xEF, 0xAF, 0x27, 0x3D, 0x8A, 0x4C, 0xA6, 0x18, 0xF1, 0x32, 0x35, 0xB4, 0x82, 0x4C, 0xBD, - 0x6F, 0x1E, 0xE6, 0x79, 0xDE, 0x79, 0x6E, 0xBA, 0xC2, 0x06, 0xC0, 0x80, 0x3F, 0x9A, 0x43, 0x1D, - 0x89, 0xF1, 0xD7, 0x64, 0xA5, 0xBB, 0x65, 0x71, 0xF5, 0x37, 0x95, 0xC3, 0x14, 0xB4, 0x65, 0x2D, - 0x15, 0x8A, 0x21, 0x3D, 0x76, 0xD9, 0xE2, 0xAB, 0xF6, 0x2D, 0xEB, 0xD9, 0x09, 0x20, 0x77, 0xA8, - 0x70, 0x75, 0x91, 0x74, 0x3A, 0xBE, 0xCA, 0xBA, 0x63, 0xD0, 0x3F, 0xFE, 0x04, 0x59, 0x7D, 0x05, - 0x64, 0x70, 0x3F, 0x35, 0xF0, 0xA7, 0x06, 0xE6, 0x6B, 0x60, 0x46, 0x5F, 0xFE, 0xB0, 0xAB, 0x18, - 0xBE, 0xC2, 0xF6, 0x73, 0x1B, 0x1A, 0xF2, 0x7C, 0x62, 0x2C, 0x55, 0xD0, 0x33, 0x69, 0x7E, 0xA1, - 0xB1, 0x97, 0xF9, 0x98, 0x04, 0xB0, 0xD8, 0xC4, 0x19, 0x28, 0x1D, 0x54, 0xCD, 0x46, 0x4B, 0xAE, - 0xD8, 0x9B, 0xB2, 0xA1, 0x74, 0x82, 0x78, 0x76, 0x00, 0x27, 0x34, 0x07, 0xC3, 0x23, 0x30, 0x3A, - 0xC1, 0xF0, 0x9A, 0x62, 0x3B, 0x1E, 0x8D, 0x58, 0x0E, 0xDE, 0xD0, 0xEA, 0x08, 0x7B, 0x34, 0xC2, - 0xDE, 0xE2, 0x79, 0x87, 0x92, 0x69, 0x56, 0x7B, 0x78, 0x21, 0x4D, 0x35, 0xAB, 0xCE, 0xB0, 0xE9, - 0xCC, 0x28, 0x46, 0x08, 0x23, 0xB5, 0x18, 0xD7, 0x69, 0x9B, 0x98, 0x48, 0x13, 0xC5, 0x6A, 0x96, - 0xAD, 0x10, 0x19, 0x54, 0x2A, 0xC2, 0x96, 0xBD, 0x72, 0xCD, 0x0F, 0x15, 0x43, 0x71, 0x09, 0x82, - 0xCB, 0x57, 0x34, 0x3F, 0xEB, 0xFD, 0x65, 0xF2, 0xF8, 0xA6, 0xEE, 0x5F, 0x43, 0xB7, 0xAF, 0xA2, - 0x67, 0x27, 0x10, 0xA0, 0x67, 0xF1, 0x83, 0x5C, 0x39, 0xFE, 0xC4, 0x6D, 0xEA, 0x1E, 0xED, 0xE6, - 0x26, 0x81, 0x31, 0x3C, 0x43, 0xD7, 0x64, 0x35, 0xF0, 0x50, 0x9B, 0x34, 0xCF, 0xA4, 0x52, 0x40, - 0x5E, 0x8E, 0x69, 0xA8, 0x4E, 0xBE, 0x91, 0x55, 0xCC, 0x53, 0x1D, 0xB1, 0xB7, 0x3F, 0x67, 0xDD, - 0x49, 0x5F, 0x19, 0x56, 0x55, 0x28, 0x8D, 0xA5, 0x46, 0x4D, 0x9A, 0x97, 0xE2, 0x18, 0xFA, 0xC3, - 0x74, 0xF1, 0x78, 0x4E, 0x1D, 0xA1, 0xA4, 0x0D, 0x94, 0x49, 0xCC, 0x00, 0x6A, 0xD5, 0xEA, 0xFF, - 0x78, 0xFA, 0x2F, 0x6B, 0x73, 0xF7, 0x59, 0xB7, 0xB9, 0xFB, 0x28, 0x6D, 0xEE, 0x3D, 0xEB, 0x36, - 0xF7, 0x1E, 0xA5, 0xCD, 0x6B, 0xCF, 0xBA, 0xCD, 0x6B, 0x75, 0xDB, 0xAC, 0xA3, 0x7C, 0x6C, 0x87, - 0x31, 0xCF, 0x34, 0xA6, 0xC7, 0xF0, 0xCA, 0x93, 0x22, 0xF5, 0x6C, 0x22, 0xFA, 0x96, 0x0E, 0x7F, - 0xF5, 0x9D, 0x5B, 0x40, 0xF1, 0xD8, 0x7B, 0x27, 0x66, 0x9B, 0x19, 0x4D, 0xAC, 0x11, 0xDB, 0x46, - 0x70, 0x54, 0xD7, 0xD3, 0x8D, 0x2F, 0xB6, 0x8D, 0x82, 0xC5, 0x5F, 0xAC, 0xAF, 0x62, 0xBE, 0x65, - 0xDF, 0xDC, 0xF0, 0xD4, 0x3E, 0x5D, 0xE4, 0x67, 0x39, 0x71, 0xF9, 0xD2, 0x12, 0x2F, 0x8B, 0xAB, - 0xBF, 0x26, 0x96, 0xFA, 0xE1, 0x0D, 0x3E, 0x69, 0xB0, 0x64, 0x42, 0xDE, 0x2D, 0x41, 0xDE, 0x55, - 0x91, 0x77, 0x75, 0xE4, 0xDD, 0x22, 0xE4, 0xBD, 0x12, 0xE4, 0x3D, 0x15, 0x79, 0x4F, 0x47, 0xDE, - 0x2B, 0x42, 0xBE, 0x56, 0x82, 0x7C, 0x4D, 0x45, 0xBE, 0xA6, 0x23, 0x5F, 0x4B, 0x90, 0x3F, 0xBF, - 0x2D, 0xA9, 0xDA, 0x2A, 0x2B, 0x65, 0x54, 0xBE, 0xF1, 0x43, 0x50, 0xD5, 0x29, 0xFC, 0x0A, 0x3F, - 0x83, 0x51, 0x89, 0x02, 0x8B, 0x08, 0x28, 0x04, 0x12, 0xEA, 0xDB, 0x89, 0xFC, 0x63, 0xFF, 0x8E, - 0x5D, 0x1B, 0xA3, 0x8B, 0x4B, 0xE9, 0x43, 0xBF, 0x80, 0x6B, 0x29, 0xE7, 0x8E, 0x15, 0x12, 0x33, - 0xDE, 0xA3, 0xD2, 0x9D, 0x82, 0xAE, 0xD1, 0x25, 0x58, 0xDF, 0x36, 0x3D, 0x19, 0x8C, 0x48, 0x1B, - 0x76, 0x44, 0xFD, 0xCE, 0xC8, 0x5F, 0x75, 0x15, 0x98, 0x28, 0xA9, 0x73, 0x98, 0x04, 0xAA, 0xF4, - 0xA2, 0xA8, 0x98, 0xDD, 0xA8, 0x57, 0xE2, 0xBF, 0x5D, 0xA7, 0xDB, 0x26, 0xAE, 0xD3, 0xAB, 0xD0, - 0x79, 0x7C, 0xCF, 0xA4, 0x6B, 0x08, 0x4D, 0x13, 0x5B, 0xE7, 0x80, 0x26, 0x5B, 0x98, 0x51, 0xF9, - 0x6E, 0x73, 0x9D, 0x07, 0x02, 0xCF, 0x76, 0x0F, 0xB7, 0x6B, 0x3E, 0x67, 0x41, 0x99, 0x98, 0x8E, - 0xBB, 0x94, 0xD0, 0x39, 0x34, 0xFE, 0x7C, 0x27, 0x4A, 0x7D, 0x26, 0x47, 0x7A, 0x5E, 0x38, 0xD6, - 0xF7, 0xA2, 0x61, 0xCA, 0x5E, 0xEC, 0xBD, 0xF0, 0xDF, 0xD9, 0x18, 0x46, 0x70, 0x7F, 0x20, 0xAE, - 0xB7, 0xAB, 0x4B, 0x54, 0xB5, 0x2C, 0xFB, 0xAE, 0x6F, 0x2B, 0x2E, 0x22, 0x7B, 0x13, 0x98, 0x46, - 0xA8, 0xA3, 0xC4, 0x35, 0xB0, 0x0C, 0x94, 0x0E, 0xBB, 0xF6, 0xC7, 0xA9, 0xE1, 0xA1, 0x90, 0xF1, - 0xE1, 0x2D, 0x8D, 0x12, 0x8B, 0xEB, 0x6C, 0x77, 0xDB, 0x2D, 0x33, 0xCB, 0x86, 0xA3, 0xD8, 0x0C, - 0xFB, 0x95, 0x1E, 0x30, 0x4B, 0x5F, 0x12, 0xCB, 0xCB, 0x87, 0x59, 0xF2, 0xF8, 0xD8, 0x2E, 0xF9, - 0xAE, 0xC4, 0x98, 0x95, 0xBC, 0xA6, 0x28, 0xB7, 0xE5, 0x6F, 0x34, 0xF0, 0xE3, 0xAC, 0xC8, 0xD2, - 0x2B, 0x2D, 0x52, 0x1E, 0x68, 0xB6, 0x8D, 0x5F, 0x9A, 0xA6, 0x9B, 0x2C, 0xE2, 0x9D, 0x0A, 0x43, - 0x3E, 0xE7, 0xA5, 0x17, 0x8F, 0x90, 0x4D, 0xBB, 0x61, 0x5E, 0xE8, 0x5A, 0x39, 0xA1, 0x87, 0x6A, - 0x36, 0x5B, 0xFD, 0x15, 0xFB, 0x07, 0x45, 0x52, 0x7A, 0xEA, 0xE5, 0x17, 0x73, 0xCF, 0xE1, 0xDC, - 0x24, 0x8D, 0x6A, 0xF5, 0x14, 0xAA, 0xB9, 0x8D, 0xED, 0x58, 0x65, 0xED, 0x4D, 0x93, 0x2F, 0xF3, - 0xF3, 0xB1, 0xB9, 0xA6, 0x71, 0x7E, 0x5E, 0xAD, 0xE6, 0x4F, 0x16, 0x61, 0x33, 0x0C, 0x03, 0x42, - 0x60, 0xEA, 0x47, 0x01, 0xB5, 0xC7, 0xA9, 0x12, 0x54, 0x93, 0x07, 0xC7, 0x2A, 0x0B, 0x44, 0xC2, - 0xF3, 0xA3, 0xA5, 0x51, 0xA0, 0x00, 0x99, 0x84, 0xC9, 0x33, 0x29, 0x41, 0x16, 0xDB, 0x0F, 0x6E, - 0x7A, 0xB7, 0x53, 0xD4, 0xF8, 0x43, 0x7E, 0x7D, 0x6C, 0x3E, 0x6D, 0xCF, 0x20, 0xFB, 0x41, 0x4D, - 0x4F, 0x2F, 0xBA, 0x8B, 0x37, 0xEB, 0xB3, 0x6E, 0x00, 0xCE, 0x19, 0x68, 0xDB, 0x8B, 0xE7, 0x8D, - 0x2A, 0xEF, 0x07, 0x98, 0x66, 0x8D, 0x79, 0xCE, 0x18, 0x6A, 0x86, 0xF4, 0xE7, 0x3C, 0x6B, 0x24, - 0xF9, 0xDC, 0xE7, 0x31, 0x73, 0x64, 0x93, 0xC3, 0x3F, 0xCB, 0xD9, 0x43, 0x4F, 0x1B, 0x3E, 0x37, - 0xDB, 0xF1, 0x1C, 0xDA, 0x5E, 0xD9, 0x74, 0xCC, 0xDC, 0x72, 0x1D, 0xD7, 0xF3, 0x35, 0x1C, 0xC2, - 0x71, 0xE6, 0xA9, 0xD0, 0xC1, 0x2E, 0x64, 0xDC, 0x65, 0xD5, 0x1B, 0xDD, 0xF9, 0x51, 0x6F, 0xBF, - 0xB0, 0x07, 0xD9, 0x55, 0xA3, 0xC4, 0x26, 0x62, 0xFE, 0xFC, 0x4D, 0xD2, 0xC3, 0x3B, 0xE5, 0x00, - 0xFD, 0xDA, 0x00, 0x17, 0x75, 0x01, 0x7E, 0x91, 0x00, 0xD6, 0xCB, 0x01, 0xCE, 0x4F, 0xF6, 0xB3, - 0x14, 0x1E, 0x1A, 0xBC, 0x50, 0x32, 0x64, 0x0F, 0xAD, 0xA9, 0xDE, 0xEA, 0xFB, 0x33, 0x55, 0x44, - 0x56, 0x67, 0x63, 0xA7, 0x0C, 0xA0, 0x5F, 0x1B, 0xE0, 0xA2, 0x2E, 0x80, 0x2C, 0xA2, 0x64, 0x5C, - 0xE6, 0x03, 0xA8, 0x22, 0x4A, 0x28, 0x3C, 0xCC, 0xF2, 0x28, 0x05, 0xBB, 0x46, 0xC7, 0x5C, 0xBA, - 0xD8, 0x50, 0x31, 0x62, 0x96, 0x44, 0x68, 0x13, 0x8F, 0x39, 0xC7, 0x21, 0x1D, 0x6C, 0x58, 0x56, - 0x19, 0x5C, 0x57, 0x82, 0x7B, 0x89, 0x70, 0x00, 0xD6, 0x35, 0x35, 0x4B, 0x72, 0x23, 0x0B, 0xB5, - 0xD7, 0x50, 0xBD, 0x5F, 0xB3, 0xFA, 0x45, 0xBD, 0xEA, 0x72, 0xA7, 0xF4, 0xCA, 0xAA, 0x67, 0xB4, - 0xD6, 0x54, 0x3F, 0xEB, 0x3E, 0xE2, 0x6F, 0x5D, 0x6B, 0x6D, 0x4D, 0x86, 0xB5, 0x52, 0xC3, 0xFC, - 0x90, 0x31, 0x4D, 0xE2, 0xDA, 0xEB, 0x4F, 0xC3, 0xF4, 0x0C, 0x0C, 0x53, 0x11, 0xC4, 0xF9, 0x6F, - 0x27, 0x97, 0xE7, 0x7B, 0xBF, 0xFE, 0x56, 0x99, 0x27, 0x04, 0xE8, 0xBF, 0x3B, 0x7F, 0xFB, 0xDB, - 0x4F, 0xE3, 0x57, 0xDB, 0xF8, 0xE5, 0x41, 0xE8, 0xE3, 0xAC, 0xBB, 0x5D, 0x91, 0x94, 0x0E, 0xD8, - 0xB3, 0x1A, 0x02, 0xAE, 0xF7, 0x9A, 0x02, 0x6E, 0xB6, 0x72, 0x5D, 0xB5, 0x9F, 0x16, 0xFE, 0x9F, - 0xC1, 0xC2, 0x9B, 0xC0, 0x33, 0x6B, 0x6C, 0x49, 0x6F, 0x4D, 0x09, 0xDE, 0xAA, 0x81, 0x33, 0xED, - 0x6D, 0x0E, 0xCE, 0x74, 0x78, 0x06, 0xF0, 0xCD, 0xDC, 0xEC, 0x74, 0x06, 0xD7, 0x1B, 0x61, 0x8C, - 0x93, 0x9B, 0xBA, 0x9E, 0x7F, 0x46, 0x13, 0x1C, 0x5B, 0xD2, 0x20, 0xDB, 0x97, 0x5D, 0xCB, 0xDA, - 0xA8, 0x6A, 0xEF, 0x65, 0xA8, 0x97, 0xEB, 0x8D, 0xA0, 0x5E, 0xB6, 0x32, 0xAB, 0xF7, 0x72, 0xA8, - 0xAD, 0x46, 0xB4, 0xB6, 0x34, 0x5A, 0x15, 0xC1, 0xB6, 0x1B, 0x11, 0xDB, 0x6E, 0xD2, 0xB0, 0x6E, - 0xAF, 0x09, 0xAD, 0x6E, 0xAF, 0x09, 0xAD, 0xDE, 0x9A, 0x32, 0x1D, 0x54, 0x95, 0xC7, 0xBA, 0xF5, - 0xB2, 0xA7, 0x58, 0xDB, 0x8A, 0xF4, 0x18, 0x5C, 0xB7, 0x95, 0xB3, 0x55, 0x33, 0x93, 0x5B, 0x90, - 0x2C, 0xC9, 0xF9, 0x50, 0x55, 0xD5, 0xB7, 0x64, 0xB6, 0x92, 0xE0, 0x72, 0xFC, 0xD7, 0x72, 0x40, - 0x55, 0xF3, 0xAB, 0xC3, 0x6D, 0x35, 0x84, 0xDB, 0x6E, 0x06, 0xA7, 0x29, 0xD7, 0xDC, 0x66, 0xE3, - 0xBC, 0x9D, 0xA1, 0xA6, 0x73, 0x86, 0xDE, 0x95, 0xF5, 0x8C, 0xB6, 0x4E, 0xBA, 0x01, 0xF4, 0x49, - 0xFF, 0x64, 0xBD, 0xAE, 0xB5, 0x3F, 0xF6, 0xEF, 0xD0, 0xCC, 0xDE, 0xB9, 0x4E, 0x74, 0xF3, 0x8F, - 0x6E, 0xF1, 0xAD, 0x46, 0x26, 0xBF, 0xF7, 0x84, 0x26, 0xBF, 0xF7, 0x94, 0x26, 0xBF, 0xF7, 0x84, - 0x26, 0xBF, 0xF7, 0xD3, 0xE4, 0xCF, 0x6C, 0xF2, 0x7B, 0x4F, 0x6D, 0xF2, 0x7B, 0x0D, 0x4D, 0x7E, - 0xAF, 0xA1, 0xC9, 0xEF, 0x35, 0x34, 0xF9, 0xBD, 0x27, 0x32, 0xF9, 0xD6, 0xC6, 0x7F, 0x6E, 0x56, - 0x91, 0x6B, 0xF5, 0x19, 0xA3, 0x0A, 0xB0, 0xB0, 0xDA, 0x4A, 0x63, 0xFF, 0x69, 0x66, 0x9A, 0x69, - 0xC8, 0x5E, 0x81, 0x4C, 0x2F, 0xD1, 0x84, 0xD9, 0xDB, 0x25, 0xFC, 0x39, 0xBF, 0x54, 0x02, 0x14, - 0xFF, 0xDE, 0xC9, 0xD6, 0xF9, 0xAC, 0xD5, 0xF9, 0x6C, 0xA8, 0xF3, 0xBB, 0x56, 0xE7, 0xF7, 0x1D, - 0x79, 0x17, 0x0F, 0xB8, 0x79, 0x4F, 0x7D, 0x87, 0x46, 0xEE, 0xA0, 0x90, 0xA3, 0xEC, 0x7D, 0x97, - 0xA1, 0x00, 0x83, 0x92, 0xF2, 0xFB, 0x2C, 0x49, 0x65, 0xDF, 0xD3, 0x2A, 0x7F, 0xD8, 0x3B, 0xDC, - 0x3B, 0xDB, 0x37, 0x54, 0xDD, 0x1B, 0x45, 0xA2, 0xD7, 0xD5, 0xA4, 0x30, 0x63, 0x3B, 0xF8, 0xA6, - 0x64, 0x84, 0xE9, 0x96, 0xA4, 0x7D, 0x29, 0x01, 0xEF, 0x99, 0xC0, 0xF9, 0xD5, 0x6F, 0x41, 0xDF, - 0x76, 0xFE, 0x63, 0x1A, 0x46, 0xC0, 0xA8, 0x1E, 0x0A, 0xC4, 0x4E, 0x6B, 0x4F, 0xE9, 0xDD, 0xB1, - 0x9F, 0xDE, 0x10, 0xCA, 0x64, 0x50, 0x49, 0xEB, 0x18, 0x02, 0xA3, 0xE8, 0x77, 0x37, 0xD2, 0xD2, - 0x21, 0xDC, 0xB8, 0x0E, 0x4B, 0xE8, 0xE8, 0x7A, 0x67, 0x2C, 0x0D, 0x0D, 0x6F, 0x04, 0xC6, 0xAE, - 0x61, 0x2E, 0x3A, 0xF0, 0x52, 0x8E, 0xBC, 0xB3, 0xC0, 0xC7, 0xDB, 0xFB, 0x49, 0x92, 0x08, 0x9D, - 0x26, 0x62, 0xDD, 0xF3, 0x1C, 0x39, 0x1A, 0x0B, 0xAB, 0x71, 0x1F, 0x87, 0xA7, 0x6B, 0x03, 0x41, - 0xA7, 0x7F, 0x2C, 0xA6, 0x6C, 0xB0, 0x4C, 0x9A, 0x96, 0x29, 0x7C, 0x6B, 0xDF, 0x1F, 0x4F, 0x46, - 0x34, 0x4A, 0x13, 0x27, 0xB1, 0x18, 0xB5, 0x18, 0x83, 0x8C, 0x5B, 0x90, 0x33, 0x37, 0x84, 0x7F, - 0xCD, 0x36, 0x44, 0x6B, 0x64, 0x4C, 0xAD, 0x15, 0xDF, 0xEC, 0xDA, 0xB7, 0x47, 0x98, 0x78, 0xF6, - 0xEE, 0x86, 0xF2, 0xCB, 0x5D, 0x87, 0xFD, 0xB3, 0xB5, 0x1E, 0xB9, 0xB1, 0x43, 0xBC, 0x2B, 0x75, - 0xED, 0x06, 0x63, 0x28, 0x0C, 0x40, 0xBF, 0xDD, 0x49, 0x44, 0xFC, 0x6B, 0x1E, 0x29, 0x8D, 0x8B, - 0xFE, 0x54, 0x38, 0xE4, 0x3A, 0xF0, 0xC7, 0x64, 0xEF, 0x8C, 0x03, 0x0C, 0xC9, 0x04, 0xB8, 0x92, - 0x22, 0xF5, 0x38, 0x16, 0xCC, 0xA5, 0x70, 0xCE, 0xD1, 0x48, 0x87, 0xF4, 0x07, 0xC0, 0x49, 0x30, - 0x76, 0x3D, 0x0A, 0xF4, 0xDD, 0xC1, 0x0D, 0x49, 0x35, 0x00, 0xF3, 0xA2, 0x22, 0x3B, 0x7E, 0xE0, - 0x0E, 0x61, 0xEC, 0x8C, 0x18, 0xE1, 0xC4, 0x33, 0x8C, 0xB3, 0x33, 0xC4, 0x42, 0xFF, 0xC3, 0x2E, - 0xF1, 0xA6, 0xA3, 0xD1, 0x92, 0x1E, 0x5D, 0x18, 0x4B, 0x51, 0xAB, 0x5F, 0x25, 0x69, 0x03, 0xFF, - 0xF6, 0x8A, 0xEC, 0x8D, 0x46, 0xA4, 0x0F, 0xDF, 0x9D, 0xE2, 0x54, 0x7E, 0xBE, 0x17, 0xFA, 0x23, - 0xDA, 0x19, 0x81, 0xC6, 0xB6, 0x3E, 0xF1, 0x1B, 0xA9, 0x04, 0xFE, 0x03, 0x39, 0x81, 0xD0, 0xB2, - 0x32, 0x30, 0x27, 0xF1, 0xB8, 0x4E, 0xD2, 0x56, 0x8E, 0x7C, 0xDB, 0xF9, 0xD5, 0x76, 0x23, 0xE5, - 0x22, 0x3A, 0x66, 0x02, 0x11, 0x6F, 0x25, 0x84, 0xD3, 0xAB, 0xB1, 0x1B, 0xC5, 0x69, 0x22, 0x31, - 0x63, 0x08, 0x0C, 0x36, 0x2C, 0x0F, 0xBF, 0x58, 0x5F, 0xD3, 0xB8, 0x76, 0x9C, 0xB2, 0x44, 0x6C, - 0xBB, 0x47, 0xEF, 0x08, 0xDE, 0x02, 0x94, 0x93, 0x5A, 0xC4, 0xC5, 0x1D, 0x7B, 0x32, 0xE1, 0x83, - 0x2A, 0x8B, 0xB6, 0xCD, 0xC8, 0x2E, 0xA5, 0x38, 0xED, 0xFF, 0xB0, 0xBF, 0x0B, 0x7C, 0xBF, 0x9D, - 0x1C, 0x7F, 0x88, 0x30, 0xE5, 0xD8, 0x5F, 0xA7, 0x34, 0x8C, 0x62, 0xAC, 0x58, 0xA1, 0xE3, 0x03, - 0xC2, 0xC5, 0xD6, 0xD9, 0xC7, 0xFE, 0x05, 0xE6, 0x30, 0x59, 0x9D, 0xB2, 0x16, 0xC5, 0x88, 0x5B, - 0x72, 0x4D, 0x36, 0xB4, 0x62, 0x4E, 0xE2, 0x91, 0xC7, 0xCD, 0x98, 0x2C, 0x0D, 0x43, 0xAC, 0xE5, - 0xEB, 0xAB, 0xE0, 0x0D, 0x2F, 0x74, 0xF1, 0x0E, 0xDF, 0x44, 0x49, 0x20, 0xD5, 0xDA, 0x29, 0x10, - 0x6D, 0x3F, 0xB2, 0xA3, 0x69, 0x88, 0xE1, 0xCD, 0xAA, 0x41, 0x2E, 0x26, 0x08, 0xD5, 0x8B, 0x90, - 0x66, 0x06, 0x32, 0x1F, 0x76, 0xE6, 0x4A, 0xAD, 0xDC, 0xC1, 0xAC, 0x10, 0xF0, 0x83, 0x21, 0x8D, - 0xCE, 0x6C, 0x37, 0x80, 0x19, 0x11, 0x8D, 0xAB, 0x3A, 0x83, 0x5C, 0x45, 0xDE, 0x3B, 0x56, 0x83, - 0x97, 0x19, 0x44, 0x84, 0xDA, 0xCB, 0xF2, 0xFA, 0x84, 0x0C, 0x97, 0x1F, 0x45, 0xD4, 0xEB, 0x48, - 0x39, 0x09, 0x26, 0x94, 0x06, 0x27, 0x7B, 0xFB, 0xA1, 0x0E, 0x77, 0xEA, 0x7B, 0x34, 0x2F, 0x32, - 0x95, 0x51, 0x3C, 0x0C, 0x27, 0xA7, 0xFE, 0xDD, 0x19, 0x80, 0x87, 0x06, 0xF3, 0x0B, 0x8C, 0x31, - 0x23, 0xA9, 0xE7, 0x84, 0x1B, 0xC6, 0x26, 0x4A, 0x14, 0x18, 0x38, 0x66, 0x70, 0x2C, 0x54, 0x47, - 0x24, 0xEF, 0xCA, 0x8B, 0x90, 0x95, 0xF1, 0xA4, 0x2C, 0x24, 0xE1, 0x0A, 0xB6, 0xE3, 0x1C, 0xDE, - 0xC2, 0x2F, 0x18, 0xA6, 0x4C, 0x01, 0xFF, 0x62, 0xEB, 0xE0, 0xE3, 0x09, 0xD8, 0xE2, 0x08, 0xBF, - 0x41, 0x47, 0x50, 0x4C, 0x8F, 0xB7, 0x48, 0xB1, 0xCA, 0x12, 0xD9, 0x7D, 0x03, 0x0C, 0x26, 0x1A, - 0x2E, 0x04, 0x56, 0x21, 0xF6, 0x21, 0x9B, 0x64, 0x4C, 0x89, 0x78, 0x60, 0x77, 0xE9, 0xD1, 0xA9, - 0x67, 0xB7, 0xF6, 0xE0, 0x17, 0x8E, 0x39, 0x89, 0x78, 0x70, 0x31, 0x0C, 0xC2, 0xFE, 0x0E, 0xBF, - 0xA8, 0xA1, 0x0F, 0xBC, 0xDA, 0x17, 0xF7, 0x6B, 0xC7, 0xF7, 0x06, 0x23, 0x77, 0x80, 0x69, 0x3E, - 0x12, 0xD9, 0x2E, 0x66, 0x5E, 0xB5, 0x56, 0xD3, 0xEF, 0xE5, 0xBC, 0x55, 0xCB, 0x5D, 0x2C, 0x3B, - 0x9C, 0x06, 0x2C, 0x68, 0x1A, 0x1D, 0xE1, 0x0F, 0x7F, 0x03, 0xE1, 0x67, 0xE5, 0xC4, 0xF1, 0xE1, - 0xC0, 0x37, 0x92, 0x34, 0x20, 0xEA, 0xD3, 0x81, 0xBA, 0x6D, 0x42, 0x56, 0x73, 0xE9, 0x49, 0xC1, - 0xD8, 0x0F, 0xF2, 0x68, 0x37, 0xA2, 0x9C, 0x07, 0x73, 0x29, 0xD5, 0x22, 0xDE, 0xA4, 0x26, 0x18, - 0x98, 0xC3, 0xB4, 0x62, 0x78, 0x27, 0x98, 0xC7, 0x8B, 0x1C, 0x79, 0x4D, 0x58, 0x8B, 0x53, 0xD8, - 0x1A, 0x70, 0x95, 0x3C, 0x5B, 0xCE, 0xED, 0x48, 0x28, 0xEA, 0x9B, 0xDF, 0x42, 0xE6, 0x76, 0x84, - 0x79, 0x7E, 0xB9, 0x8F, 0x16, 0x9B, 0x5A, 0xF4, 0x0E, 0x21, 0xE6, 0xD1, 0x9C, 0x18, 0x51, 0xA5, - 0xB6, 0xE4, 0xF0, 0x99, 0x36, 0x24, 0xBF, 0xB1, 0x86, 0xB6, 0x14, 0xBF, 0x09, 0xDF, 0xB8, 0x65, - 0x33, 0x3D, 0x35, 0xCF, 0xDB, 0x89, 0xEB, 0x82, 0xA2, 0x66, 0x0E, 0x93, 0x25, 0x42, 0xF3, 0x66, - 0xBE, 0x67, 0x19, 0x9D, 0xE6, 0xDD, 0xCA, 0xF7, 0x7A, 0x9E, 0x28, 0x53, 0x23, 0x79, 0x23, 0xF2, - 0x1B, 0xC9, 0x85, 0x90, 0x6D, 0xA4, 0x52, 0x29, 0x6F, 0xA7, 0x2F, 0xB3, 0xBE, 0x6E, 0xB0, 0xA5, - 0xA7, 0x3C, 0xA4, 0x64, 0xCC, 0x74, 0x2F, 0x1D, 0x89, 0x6E, 0x75, 0x36, 0xF0, 0x74, 0x73, 0x0F, - 0x9C, 0x5B, 0x98, 0x8A, 0xD1, 0x6F, 0x3B, 0xEE, 0xAE, 0x1E, 0xF7, 0x14, 0x64, 0x0F, 0xEA, 0x45, - 0xA4, 0xD2, 0xED, 0x81, 0xDB, 0xEC, 0x6D, 0xD7, 0xCA, 0xFC, 0x6C, 0x77, 0x36, 0xE7, 0xC8, 0x4F, - 0x76, 0xBF, 0xA8, 0x0E, 0x33, 0xDD, 0xEE, 0xE6, 0x5C, 0xA5, 0xA3, 0xA7, 0x16, 0xAE, 0xC3, 0xCB, - 0x3A, 0xEE, 0x5B, 0x34, 0x60, 0xA5, 0x19, 0x35, 0x65, 0x73, 0x45, 0xC5, 0x6C, 0x18, 0xA3, 0xA6, - 0x97, 0xE0, 0x1B, 0x0F, 0xCD, 0x9A, 0xCF, 0xCA, 0xA7, 0x23, 0xCE, 0x70, 0x39, 0x38, 0xF7, 0xFA, - 0xB2, 0x69, 0x44, 0x57, 0x80, 0xCF, 0x6B, 0x75, 0xF2, 0x7E, 0xCF, 0x3C, 0x5A, 0x5D, 0xE5, 0x31, - 0x20, 0xAD, 0xD5, 0x1C, 0xA4, 0x79, 0xAB, 0x8B, 0xE1, 0x0D, 0xAD, 0xD6, 0xAE, 0x8B, 0xCD, 0xDE, - 0xF2, 0x2C, 0xC2, 0x92, 0xD6, 0x1B, 0x2E, 0xA6, 0x01, 0x90, 0xC8, 0x11, 0xAF, 0x45, 0xC1, 0x96, - 0x8A, 0xA2, 0x14, 0x99, 0xBA, 0x71, 0x67, 0x10, 0x0B, 0x2E, 0xE3, 0x30, 0x27, 0x2A, 0x66, 0xFD, - 0xF5, 0xE8, 0x68, 0x16, 0x81, 0x64, 0x51, 0x25, 0x59, 0x4D, 0x2C, 0xB3, 0x0E, 0xC4, 0x10, 0x6F, - 0xED, 0xA9, 0x73, 0x10, 0xF8, 0x13, 0x4C, 0xA8, 0x6F, 0x9E, 0x7A, 0x95, 0x27, 0xE5, 0x4A, 0xF5, - 0xA5, 0x02, 0x47, 0x5D, 0xF3, 0xEC, 0x58, 0x85, 0x23, 0xE1, 0x2C, 0xD4, 0xE2, 0xA8, 0x29, 0xAD, - 0x1A, 0xAD, 0x37, 0x68, 0x7B, 0xFE, 0x23, 0x8F, 0x33, 0x6A, 0x7D, 0xE9, 0xEB, 0x91, 0xE6, 0xFE, - 0x9E, 0x80, 0x99, 0xE2, 0xCF, 0x07, 0x37, 0x12, 0x58, 0x39, 0xB8, 0x22, 0x83, 0x69, 0x48, 0x8F, - 0xFD, 0x81, 0x3D, 0x72, 0xFF, 0x46, 0x9D, 0x03, 0x68, 0x67, 0xE0, 0x5E, 0x4D, 0x79, 0x1A, 0xC9, - 0xE6, 0xCD, 0x2F, 0xC0, 0x59, 0xD8, 0xF2, 0x91, 0x09, 0xE8, 0x02, 0x56, 0x80, 0xC7, 0xB0, 0xA6, - 0x1D, 0x99, 0x7A, 0xBF, 0x82, 0x3C, 0x9A, 0x22, 0x35, 0x68, 0x8A, 0xFE, 0xD6, 0xE4, 0x8C, 0xFA, - 0x51, 0xE3, 0xE9, 0xCA, 0xC2, 0x11, 0x75, 0x40, 0x23, 0xDB, 0x1D, 0x85, 0x35, 0xE5, 0x52, 0x07, - 0x51, 0x81, 0x2C, 0x3E, 0xD8, 0x81, 0x83, 0x5B, 0x41, 0x5C, 0x10, 0xC9, 0x1B, 0x3C, 0x73, 0x12, - 0x4D, 0x0E, 0xF6, 0x5A, 0x92, 0x92, 0x61, 0x67, 0x13, 0x55, 0x25, 0x4C, 0x26, 0x59, 0xB1, 0x8D, - 0xA5, 0x39, 0x48, 0x25, 0xC6, 0x53, 0xA9, 0xFD, 0x6C, 0xC7, 0xA5, 0x59, 0x83, 0x8B, 0x41, 0x4D, - 0x1E, 0x83, 0xB4, 0x65, 0x37, 0x07, 0x77, 0x41, 0xC5, 0x96, 0x63, 0x33, 0x0C, 0xBB, 0x85, 0xB3, - 0xF9, 0x08, 0x85, 0xC8, 0x4A, 0x7D, 0x04, 0xE5, 0x69, 0xBA, 0x19, 0x05, 0x50, 0xFE, 0xC0, 0x9D, - 0x6C, 0x34, 0x03, 0xBB, 0x59, 0x2F, 0x17, 0x42, 0x1A, 0xDB, 0xD6, 0x78, 0x74, 0x23, 0xAB, 0x1F, - 0x80, 0xA8, 0x3A, 0x78, 0xE2, 0x8D, 0xBD, 0x7C, 0x5A, 0xE7, 0x47, 0xA7, 0x87, 0xBF, 0xCD, 0x43, - 0x9E, 0x0A, 0xB6, 0x6A, 0xE6, 0x23, 0x03, 0xD9, 0xD0, 0x78, 0x54, 0xC7, 0x63, 0x90, 0x83, 0xF2, - 0xB0, 0xD9, 0x8C, 0x52, 0xA8, 0xFA, 0x48, 0x9A, 0x2E, 0x83, 0x14, 0x6E, 0x16, 0x09, 0x54, 0xC0, - 0x62, 0x6A, 0xBF, 0xE9, 0xE5, 0xB3, 0x59, 0xE5, 0x50, 0xF3, 0x35, 0xB5, 0x8C, 0x3C, 0x00, 0x7E, - 0x6C, 0x47, 0xEE, 0x40, 0x45, 0x32, 0x93, 0x70, 0x6A, 0xA2, 0xCC, 0x91, 0x54, 0xFC, 0x56, 0xDA, - 0x1C, 0x04, 0x54, 0xE1, 0xD9, 0xB5, 0x5C, 0xB9, 0x30, 0xD8, 0xB9, 0x88, 0xA3, 0x18, 0x93, 0x22, - 0x85, 0xCA, 0xCF, 0xA8, 0x35, 0x16, 0xCE, 0x3C, 0x1E, 0x6A, 0x93, 0xF6, 0xBE, 0x0B, 0xB1, 0x35, - 0x93, 0x5E, 0x43, 0x9C, 0xD9, 0x2D, 0xD9, 0xBD, 0x51, 0xE4, 0x46, 0x53, 0xA7, 0xD1, 0x60, 0x53, - 0x42, 0x20, 0x32, 0xE8, 0xF5, 0xA7, 0x3F, 0x1F, 0x8B, 0x40, 0x66, 0xF3, 0x6B, 0xCE, 0x64, 0xD4, - 0x80, 0x94, 0x39, 0x22, 0x4F, 0xEE, 0x15, 0xDF, 0xF3, 0x7B, 0xC5, 0xF7, 0xE4, 0x35, 0xF1, 0xA6, - 0xE3, 0xFD, 0xCC, 0x0B, 0xAE, 0x50, 0x94, 0xBD, 0x5D, 0x0C, 0xCB, 0x9B, 0xC8, 0xF7, 0xC4, 0xE5, - 0x62, 0xF6, 0x64, 0x09, 0x66, 0xA7, 0x79, 0xCB, 0xBE, 0xE2, 0xB3, 0x12, 0xF7, 0x4A, 0x80, 0x52, - 0x5A, 0xDB, 0xD8, 0x04, 0x3C, 0xA6, 0xCB, 0x6D, 0x41, 0x9C, 0x39, 0x27, 0xC5, 0xBF, 0x8F, 0xF5, - 0x17, 0xEF, 0x65, 0xF5, 0x92, 0x5E, 0x87, 0x58, 0x92, 0x83, 0x61, 0x72, 0xDC, 0x01, 0x29, 0xB5, - 0x54, 0xBD, 0xE8, 0xB4, 0x92, 0x07, 0x58, 0x2B, 0xCC, 0xF0, 0x82, 0x87, 0x13, 0x86, 0x7D, 0x96, - 0x29, 0xBE, 0x04, 0x91, 0x31, 0xD4, 0x62, 0x6E, 0xEC, 0xCF, 0x81, 0x71, 0x13, 0xCB, 0x4A, 0x4C, - 0x5A, 0x51, 0xFA, 0xA3, 0x82, 0xC4, 0x4C, 0x39, 0x3A, 0xAC, 0xDD, 0x90, 0x6F, 0xAE, 0xFD, 0x69, - 0x4E, 0xD6, 0xFC, 0x6C, 0x4E, 0xF7, 0x2C, 0x6D, 0xDF, 0x77, 0xD3, 0x2E, 0x7D, 0x95, 0xC1, 0xF3, - 0x7D, 0xC7, 0xB4, 0xDD, 0x2E, 0x0F, 0x22, 0xCC, 0x0E, 0x2D, 0x0E, 0xE4, 0x59, 0x66, 0x66, 0x8D, - 0x15, 0xAC, 0x84, 0x5C, 0x94, 0xEC, 0xBE, 0xAB, 0x69, 0xC1, 0x0C, 0x63, 0x0C, 0xBF, 0xF1, 0xBF, - 0xD3, 0xB8, 0x23, 0x72, 0xE4, 0x0D, 0x02, 0x16, 0x2D, 0x32, 0x11, 0xF9, 0xB2, 0xC8, 0x0A, 0x09, - 0xEF, 0xEC, 0x09, 0x7F, 0x7D, 0x9B, 0x1D, 0xF4, 0xC3, 0x9C, 0x94, 0xF2, 0x44, 0x42, 0xC6, 0x13, - 0x4F, 0x1F, 0x82, 0x75, 0x3C, 0x4C, 0x6D, 0x7D, 0x03, 0x76, 0x99, 0x86, 0xE9, 0x8B, 0x9B, 0x29, - 0x29, 0xF2, 0x46, 0xDD, 0xA1, 0x64, 0xC9, 0x0C, 0xEC, 0x6F, 0xF4, 0x84, 0x7E, 0x40, 0x98, 0x60, - 0xC7, 0x50, 0xC2, 0x92, 0xF9, 0xED, 0x64, 0x7B, 0xB7, 0xB6, 0x5E, 0x54, 0xE9, 0xDD, 0xEF, 0xAC, - 0x77, 0xB3, 0xB2, 0x91, 0xFF, 0xC9, 0x0C, 0xA7, 0x99, 0xBD, 0xCC, 0x27, 0x2C, 0xD5, 0xE8, 0xC9, - 0x12, 0x5A, 0x21, 0xDD, 0xA5, 0x7C, 0xAA, 0x4C, 0x18, 0x45, 0x44, 0x1F, 0xE6, 0x28, 0x28, 0x66, - 0x32, 0xE5, 0xD6, 0x9A, 0xF8, 0x2A, 0x69, 0xDD, 0x0A, 0x5E, 0x46, 0x92, 0x55, 0xAB, 0x44, 0x58, - 0x12, 0x4D, 0xD6, 0x56, 0x13, 0x49, 0xC0, 0x76, 0xEA, 0x47, 0xF4, 0x15, 0x69, 0x95, 0x10, 0x5F, - 0x06, 0xE2, 0x2D, 0xE2, 0x7B, 0xA3, 0x7B, 0x72, 0xE7, 0x07, 0xDF, 0xC2, 0x98, 0x59, 0xF8, 0xDB, - 0xBD, 0x36, 0xA1, 0x2D, 0xC0, 0xC7, 0x9E, 0x48, 0x71, 0xBD, 0xA8, 0xCD, 0xDE, 0xA6, 0x0F, 0x59, - 0xF6, 0xE9, 0x0E, 0xF9, 0x84, 0x63, 0xC5, 0x0E, 0xF0, 0x91, 0xAE, 0x08, 0xC7, 0x0A, 0xA5, 0xC4, - 0xBE, 0xF2, 0x6F, 0x69, 0x5D, 0x31, 0x2D, 0xC7, 0x62, 0x3A, 0xA0, 0x85, 0x62, 0x7A, 0x50, 0x32, - 0x96, 0x90, 0xA3, 0x6B, 0x62, 0x8F, 0xA0, 0xBE, 0x73, 0xCF, 0x46, 0x9F, 0x18, 0x78, 0xC9, 0xE8, - 0x6D, 0x33, 0x49, 0x12, 0x37, 0x22, 0x23, 0x90, 0xA5, 0x18, 0x91, 0x9A, 0x25, 0x67, 0xC1, 0x38, - 0x7B, 0xE3, 0x0F, 0x1C, 0xF4, 0x69, 0xC7, 0x19, 0xDA, 0x02, 0x6C, 0x86, 0x45, 0xDC, 0x90, 0x7C, - 0x90, 0xAC, 0x86, 0x82, 0x2A, 0x61, 0x2E, 0xAB, 0xF7, 0xF8, 0xEF, 0x0A, 0xDA, 0xFF, 0xED, 0x69, - 0x86, 0x03, 0x3E, 0xC5, 0x90, 0x70, 0xF3, 0xC8, 0x83, 0x21, 0xE7, 0x6C, 0xB6, 0x34, 0xD1, 0xA0, - 0xB1, 0x4D, 0x68, 0x55, 0x18, 0xE1, 0xE3, 0x54, 0x0F, 0xF2, 0x95, 0xAB, 0x6E, 0x8A, 0x42, 0x74, - 0xFB, 0xF6, 0x0F, 0xDF, 0x25, 0x53, 0xB7, 0xFC, 0x8C, 0x5A, 0x72, 0x75, 0xC6, 0x83, 0x49, 0x07, - 0xE3, 0xC2, 0xB0, 0x66, 0x72, 0x8A, 0x1C, 0xD0, 0x31, 0x0C, 0x96, 0xB7, 0xB6, 0x83, 0x6B, 0x8D, - 0x70, 0x31, 0x5B, 0x27, 0xF6, 0x68, 0x8D, 0xAF, 0xBA, 0x4A, 0xB5, 0xC5, 0x9B, 0xAE, 0x99, 0xE7, - 0xC7, 0xD7, 0xB7, 0xD9, 0xAB, 0xAE, 0x36, 0xCC, 0x5B, 0xEA, 0xD3, 0xAE, 0x72, 0x72, 0xE9, 0x9D, - 0x17, 0x39, 0xAF, 0xD4, 0x4A, 0xC1, 0xF1, 0x6D, 0xB2, 0xF2, 0x32, 0x7E, 0x9B, 0xF6, 0x65, 0xE6, - 0x91, 0xDA, 0xB8, 0x0C, 0x49, 0x8A, 0x5F, 0x9B, 0x13, 0xFB, 0xFC, 0x94, 0xC4, 0x7E, 0x9F, 0x27, - 0xB1, 0x9C, 0x87, 0xF4, 0x94, 0x29, 0x3F, 0x7E, 0x89, 0x0A, 0x7B, 0x8E, 0xD8, 0x43, 0x1B, 0x5F, - 0x32, 0xE4, 0xCF, 0x63, 0xB8, 0x92, 0x62, 0xF2, 0xE7, 0x76, 0x1C, 0xFA, 0x5D, 0xBD, 0x33, 0xC4, - 0x06, 0xF1, 0x8E, 0x28, 0x79, 0x8D, 0x01, 0xD8, 0x7E, 0xE0, 0x84, 0x4C, 0x5D, 0xE2, 0xE0, 0xC1, - 0xE5, 0x65, 0x56, 0xAA, 0x8F, 0x4E, 0x44, 0x08, 0x86, 0x3A, 0x0A, 0x99, 0xD6, 0x25, 0x60, 0x5F, - 0x58, 0xE5, 0xAF, 0x71, 0x72, 0x6B, 0xA2, 0xE7, 0xD4, 0x8D, 0xBD, 0x6A, 0x45, 0xD7, 0xA4, 0xD3, - 0x4D, 0x86, 0x12, 0x33, 0x58, 0x1B, 0x86, 0x6A, 0x96, 0x0C, 0x0E, 0xCF, 0xEC, 0x30, 0x58, 0x26, - 0x0B, 0x2C, 0xC1, 0x6C, 0xAA, 0x6D, 0x79, 0x05, 0x9F, 0xF3, 0x0A, 0x7E, 0xD7, 0x93, 0x17, 0xD7, - 0x34, 0x8E, 0xFC, 0xD5, 0x19, 0x26, 0xEE, 0x5D, 0x83, 0x54, 0x97, 0x5E, 0xE4, 0xB4, 0xAB, 0x33, - 0x99, 0x86, 0x37, 0x8B, 0x8F, 0xDA, 0xA6, 0x25, 0x43, 0xE2, 0x54, 0x24, 0x84, 0x6B, 0x4C, 0xDD, - 0x10, 0x39, 0x14, 0x63, 0x88, 0x13, 0x5B, 0x94, 0x44, 0xAE, 0x02, 0x22, 0x11, 0x20, 0x8E, 0x11, - 0xCE, 0x50, 0x53, 0xBA, 0x7B, 0x22, 0xF7, 0x68, 0x7A, 0xC7, 0x12, 0x21, 0xDE, 0xB0, 0xE4, 0xDC, - 0xEA, 0x4C, 0x69, 0x52, 0x21, 0xA8, 0x6B, 0x56, 0x20, 0x04, 0x40, 0xD9, 0x88, 0xD5, 0x40, 0xAC, - 0x2B, 0x52, 0xA0, 0x17, 0x9F, 0x26, 0x59, 0x14, 0xFC, 0x62, 0xEB, 0x80, 0x71, 0x4F, 0xF0, 0xB0, - 0x91, 0xB5, 0x06, 0x97, 0x0B, 0x09, 0xF8, 0x32, 0x69, 0xFD, 0x4B, 0x6B, 0x29, 0x6F, 0x3B, 0x48, - 0xEE, 0x12, 0xE4, 0x64, 0x40, 0xB1, 0x05, 0x60, 0x13, 0x73, 0xD6, 0x8E, 0xC5, 0x62, 0xC4, 0x80, - 0x6C, 0xC5, 0xA0, 0xFF, 0x40, 0x19, 0xE6, 0xDE, 0x51, 0xE2, 0xD2, 0xEC, 0x7E, 0xCD, 0xA9, 0xFA, - 0x39, 0x53, 0xB5, 0x97, 0x57, 0xF5, 0xF7, 0x4C, 0xD5, 0x35, 0xAD, 0xAA, 0x79, 0xF4, 0x4B, 0x1D, - 0x6A, 0x7A, 0x07, 0x51, 0xE6, 0xBA, 0xA4, 0xC6, 0xE7, 0xD2, 0x1A, 0xBF, 0xE7, 0xD5, 0x50, 0x59, - 0x53, 0x5E, 0xFC, 0x4B, 0x1E, 0x27, 0x92, 0x04, 0x0D, 0x5E, 0x6C, 0x60, 0x83, 0x5F, 0xC8, 0x15, - 0x80, 0xD8, 0x9E, 0x43, 0xC6, 0xBE, 0xE7, 0x87, 0x13, 0x1B, 0x56, 0x71, 0x2C, 0xD6, 0x9C, 0x99, - 0x61, 0x6D, 0xA5, 0x9E, 0x2A, 0x8A, 0x14, 0xB0, 0x9E, 0xAB, 0x06, 0x22, 0x2F, 0x7A, 0x3A, 0xF5, - 0xA3, 0x32, 0x64, 0x8D, 0x4A, 0x66, 0x66, 0xE0, 0xFB, 0x09, 0x79, 0x68, 0xD3, 0xE6, 0xCB, 0x4D, - 0xC6, 0x7B, 0x5F, 0x7A, 0x88, 0xBE, 0xF4, 0x6A, 0x11, 0x66, 0xB8, 0xF4, 0x03, 0xEA, 0xB4, 0x8A, - 0x9E, 0x34, 0x65, 0x3B, 0x21, 0x33, 0x93, 0x15, 0xA5, 0xAF, 0xC8, 0x6F, 0xAB, 0x9F, 0x57, 0x7F, - 0x6F, 0xA9, 0x79, 0xE4, 0x0D, 0xAD, 0x7F, 0x4D, 0x36, 0x96, 0x32, 0xC7, 0x87, 0xB9, 0x32, 0x0D, - 0xDD, 0xBF, 0x51, 0x62, 0x32, 0xCD, 0x8A, 0x75, 0x4C, 0x7C, 0xDC, 0x74, 0xEA, 0xAC, 0x3B, 0x57, - 0xE2, 0x00, 0xF5, 0x27, 0xAC, 0xEF, 0xA5, 0x40, 0x7F, 0xF4, 0x56, 0x41, 0x0D, 0x44, 0x62, 0xF1, - 0x05, 0x5E, 0x41, 0x1E, 0xA6, 0xFC, 0x0B, 0xDB, 0xBB, 0x30, 0x4E, 0xB0, 0x99, 0x9A, 0xF1, 0x18, - 0x62, 0xC5, 0xEA, 0x68, 0xCB, 0x15, 0x02, 0x66, 0x55, 0xE7, 0xE0, 0xEA, 0xA4, 0xF0, 0xC7, 0xC5, - 0xD6, 0xFF, 0x32, 0x03, 0x09, 0x6A, 0x00, 0x4B, 0xED, 0xC1, 0xCD, 0xA2, 0x79, 0x17, 0x52, 0xB6, - 0x49, 0x7F, 0x5C, 0x8C, 0x6E, 0xDC, 0x90, 0x6F, 0xC2, 0x2C, 0x2E, 0x15, 0x5A, 0x75, 0x4F, 0xB5, - 0xEA, 0x9D, 0x70, 0x7A, 0xC5, 0x57, 0x85, 0x8B, 0xE0, 0x3F, 0x75, 0x37, 0x94, 0x57, 0xE6, 0x25, - 0xA4, 0x09, 0x28, 0x4C, 0x78, 0x3C, 0xB1, 0x7C, 0x6C, 0xC9, 0x92, 0x29, 0x30, 0xB6, 0x57, 0xDA, - 0x87, 0xB5, 0xAF, 0x1C, 0x45, 0xBA, 0xD9, 0xAB, 0x39, 0xE1, 0xF1, 0xCD, 0xCA, 0x6A, 0x8E, 0x78, - 0x5C, 0xBB, 0xCC, 0x19, 0x57, 0xEB, 0x55, 0x71, 0xC8, 0x63, 0x88, 0x79, 0x39, 0xE5, 0xE9, 0x33, - 0x63, 0x85, 0xEE, 0x6C, 0x72, 0xE0, 0x00, 0x1E, 0x6D, 0xB7, 0x6B, 0xAD, 0xAD, 0xB7, 0xC9, 0xD6, - 0x96, 0x42, 0x9D, 0x7F, 0x46, 0x16, 0xB0, 0xA0, 0xB6, 0xD3, 0xAC, 0x9F, 0x3B, 0x20, 0x9D, 0x0D, - 0xEC, 0x6B, 0x85, 0xC4, 0x06, 0x7B, 0x78, 0x70, 0xA3, 0x29, 0x76, 0xED, 0xD0, 0x01, 0x68, 0xF4, - 0x2C, 0xAB, 0x63, 0xB1, 0x8B, 0x92, 0x1D, 0xC5, 0x33, 0x67, 0x1F, 0x90, 0x18, 0xFB, 0xE5, 0xD9, - 0x79, 0xE5, 0x89, 0xDE, 0xD4, 0xF7, 0xCC, 0x63, 0xD0, 0xBA, 0xDE, 0x79, 0xA2, 0x78, 0xF5, 0x3C, - 0x74, 0x8D, 0x9C, 0xE4, 0xA5, 0x6B, 0x63, 0x44, 0xF1, 0x51, 0xC5, 0x15, 0x65, 0x63, 0x91, 0xB8, - 0x91, 0x6C, 0x2A, 0x8B, 0xB5, 0x54, 0x2B, 0xD3, 0x74, 0xCB, 0x5C, 0xAA, 0xEA, 0xC6, 0x23, 0xF8, - 0xFC, 0x5A, 0x9F, 0x19, 0xFD, 0xFE, 0xA4, 0x8E, 0xE2, 0xFB, 0xFF, 0x03, 0x48, 0xCA, 0xB4, 0x92, - 0x88, 0xD9, 0xCE, 0x5F, 0x4D, 0x64, 0x8C, 0x6A, 0x99, 0x33, 0xAC, 0x2B, 0x61, 0x6D, 0x87, 0x38, - 0x51, 0xC7, 0xE7, 0xB3, 0xB0, 0x48, 0x7A, 0xB7, 0xFA, 0xE2, 0xA2, 0x48, 0xB2, 0xD2, 0xC9, 0xA5, - 0xBC, 0x4C, 0xBB, 0xB1, 0xE9, 0x09, 0x8D, 0x6E, 0x7C, 0x27, 0xF7, 0x8E, 0xA1, 0x72, 0xC1, 0x30, - 0xBD, 0x5A, 0xFF, 0x2A, 0xBE, 0x49, 0x9F, 0x79, 0xC1, 0x0A, 0x50, 0xA6, 0xF2, 0x97, 0xF0, 0x6B, - 0x71, 0xC9, 0xD9, 0xD3, 0xD8, 0xFC, 0x18, 0x30, 0xD3, 0x01, 0x77, 0x6E, 0x90, 0x17, 0x90, 0x84, - 0x6F, 0xE2, 0x59, 0xA7, 0x9C, 0x24, 0x04, 0x4B, 0x64, 0x85, 0x2C, 0x4A, 0x55, 0xB2, 0xC7, 0xDB, - 0xA2, 0xDA, 0x32, 0xC9, 0xD6, 0x32, 0x5F, 0xD0, 0x58, 0x22, 0xAB, 0xA4, 0xCB, 0x2F, 0xD6, 0x17, - 0xB1, 0x1D, 0xCF, 0xFC, 0xC0, 0x65, 0x07, 0xE3, 0x59, 0xA0, 0x74, 0x71, 0xAD, 0xE8, 0x3E, 0x77, - 0xA1, 0x9C, 0xB2, 0xB9, 0x2B, 0x0A, 0xC4, 0xA4, 0x09, 0xD5, 0x2C, 0x27, 0x9D, 0x55, 0x14, 0xC1, - 0x13, 0x4A, 0x2A, 0x93, 0x2B, 0xC2, 0x2C, 0x27, 0x7D, 0xE9, 0xFC, 0x6C, 0x2D, 0xC6, 0x74, 0x7C, - 0x26, 0xE0, 0x18, 0xBC, 0xB2, 0x82, 0x88, 0x29, 0x26, 0x95, 0xDE, 0xEC, 0x92, 0x4D, 0xD3, 0x54, - 0x3D, 0xB2, 0xA3, 0x18, 0x4B, 0x5A, 0x79, 0x85, 0xAC, 0xA3, 0x20, 0x7B, 0x86, 0x57, 0xF5, 0x72, - 0xA7, 0x66, 0xC3, 0xF2, 0xB9, 0x24, 0x05, 0x48, 0x76, 0xC9, 0x1F, 0x73, 0x9D, 0x30, 0xF5, 0x26, - 0x7B, 0xDF, 0x40, 0x59, 0x18, 0x8D, 0x61, 0x35, 0x18, 0xB3, 0xDF, 0xDD, 0x91, 0xFE, 0x7C, 0x9D, - 0x34, 0x4C, 0xFA, 0x9A, 0x3D, 0x07, 0x28, 0xE5, 0x72, 0x79, 0x57, 0xF1, 0xD9, 0x53, 0x02, 0xCB, - 0x44, 0x67, 0x3C, 0xBB, 0xE7, 0xFF, 0x90, 0x23, 0x89, 0x6C, 0x82, 0x13, 0x21, 0x0A, 0xC0, 0x1A, - 0xB3, 0xFD, 0xBC, 0xA4, 0xA2, 0x73, 0x5C, 0x24, 0x96, 0xFC, 0x46, 0x54, 0x96, 0x90, 0xC1, 0xA6, - 0x71, 0x42, 0x92, 0x86, 0xAE, 0x19, 0x14, 0x2D, 0xC7, 0x80, 0x98, 0xC0, 0x7B, 0xF9, 0xE0, 0xB9, - 0x97, 0xE4, 0x32, 0x48, 0xBA, 0x5F, 0xB5, 0x5B, 0x9E, 0x4D, 0x72, 0xCD, 0xC4, 0xC9, 0x62, 0x6A, - 0xE0, 0xE9, 0x15, 0xE4, 0xAC, 0x51, 0xF0, 0x28, 0x31, 0x45, 0x79, 0x8F, 0xC5, 0x19, 0x06, 0xF5, - 0x4E, 0x6E, 0x5D, 0x75, 0x94, 0x94, 0xD5, 0x4B, 0xF4, 0xA6, 0xA4, 0x62, 0xDA, 0xE1, 0xF9, 0x15, - 0x33, 0x9D, 0x5B, 0x5A, 0x55, 0xEF, 0xC8, 0x8A, 0x81, 0x30, 0x4A, 0x96, 0x93, 0x90, 0x9B, 0xF7, - 0x58, 0x34, 0x84, 0x59, 0x63, 0xBE, 0x12, 0xCF, 0x09, 0x8B, 0xC9, 0xEE, 0xD4, 0x25, 0xC0, 0x8D, - 0x76, 0xEB, 0x54, 0xCF, 0xAB, 0x70, 0xC7, 0x4E, 0xB2, 0xCA, 0x45, 0xBB, 0x76, 0xDA, 0xB2, 0xA0, - 0xF2, 0xCE, 0x9D, 0x49, 0x3F, 0x74, 0xDD, 0x79, 0xC4, 0x1D, 0xBC, 0x86, 0xE4, 0x93, 0x9D, 0x3C, - 0xD0, 0xDA, 0x55, 0xD4, 0xC8, 0x55, 0xD0, 0x36, 0xF3, 0x86, 0x9E, 0x2E, 0x98, 0x8A, 0x9B, 0x7A, - 0x92, 0xD8, 0xD5, 0x8D, 0x3D, 0x7D, 0xCD, 0x5C, 0x73, 0x73, 0xAF, 0xCA, 0x92, 0x7B, 0x9E, 0x1B, - 0x7C, 0xDA, 0xC2, 0x79, 0xB6, 0x4D, 0x3E, 0x49, 0x28, 0xF5, 0x36, 0xFA, 0x92, 0xD1, 0xF2, 0x43, - 0x37, 0xFB, 0x14, 0xF5, 0x90, 0xFD, 0x2B, 0xF4, 0xA4, 0x5E, 0xEA, 0x33, 0xE6, 0xDC, 0xB6, 0x04, - 0x33, 0xF3, 0xA5, 0x5A, 0x61, 0x5D, 0x87, 0xD8, 0xD0, 0x3F, 0x6C, 0x96, 0xA1, 0x78, 0xA9, 0x6C, - 0x3B, 0x96, 0x1A, 0xC3, 0x47, 0xD9, 0xEC, 0x94, 0x74, 0xE0, 0x21, 0x93, 0x2C, 0x4C, 0xD9, 0xB5, - 0x94, 0x72, 0x17, 0x71, 0x97, 0x1B, 0x7E, 0x4A, 0x3D, 0xDB, 0xF9, 0x0F, 0xDF, 0xF5, 0x16, 0x17, - 0x16, 0x92, 0xC4, 0x4D, 0x5A, 0x95, 0x76, 0x79, 0x95, 0x7F, 0xFD, 0xD7, 0x4C, 0x9D, 0x80, 0x46, - 0xD3, 0xC0, 0x63, 0xEE, 0xBA, 0xC6, 0xDD, 0x90, 0x46, 0x98, 0x2E, 0x4A, 0x31, 0xC5, 0x2C, 0x53, - 0x17, 0x98, 0x2C, 0xD0, 0x9E, 0xB8, 0x0C, 0x2D, 0x2A, 0x9F, 0xD6, 0x35, 0xB3, 0xA6, 0xD4, 0x11, - 0x2B, 0x2C, 0x69, 0xD3, 0xEE, 0xE8, 0x9A, 0x6D, 0xD2, 0x45, 0xF6, 0x15, 0xB9, 0xB3, 0x43, 0x82, - 0x73, 0x37, 0xC1, 0x14, 0x53, 0xD4, 0x69, 0x13, 0x3E, 0xA4, 0xB1, 0x6C, 0x44, 0x79, 0x2E, 0xB2, - 0x70, 0x10, 0xE0, 0x13, 0x47, 0xDA, 0x42, 0x67, 0x44, 0x4F, 0x6C, 0xCF, 0x1E, 0xD2, 0xE0, 0x02, - 0x6B, 0x66, 0x92, 0x49, 0x31, 0xF8, 0x37, 0xAF, 0xA3, 0x80, 0xD8, 0x23, 0x77, 0xE8, 0xED, 0x2E, - 0x8C, 0xE8, 0x75, 0xB4, 0x00, 0x1F, 0x6E, 0xDE, 0xE0, 0xFE, 0xC1, 0xEB, 0x55, 0xF8, 0x05, 0xFF, - 0xE8, 0x83, 0x21, 0x13, 0x7F, 0x38, 0x6F, 0x5E, 0xF3, 0x47, 0x29, 0xA3, 0xFB, 0x09, 0xDD, 0xE5, - 0x1E, 0xC7, 0x95, 0xFF, 0x7D, 0x81, 0xB8, 0xCE, 0xEE, 0x02, 0x12, 0xE4, 0xCB, 0xF9, 0xBD, 0xD1, - 0x68, 0x81, 0xB0, 0x37, 0x53, 0xE1, 0xAB, 0x1F, 0x8C, 0x57, 0x58, 0xC5, 0x15, 0x0E, 0x2A, 0xF1, - 0xC5, 0x76, 0x26, 0x17, 0x88, 0x08, 0x5C, 0xE4, 0x18, 0x62, 0x96, 0xFD, 0xE1, 0x10, 0x93, 0xFB, - 0x00, 0x3F, 0xAB, 0x48, 0x76, 0x35, 0x0A, 0x92, 0x1F, 0x8C, 0x6F, 0xC9, 0x6C, 0x23, 0x18, 0x6B, - 0xE2, 0x05, 0xB7, 0x61, 0xAD, 0x96, 0x24, 0xCA, 0xEF, 0xE3, 0xD1, 0x4D, 0x14, 0x4D, 0x0A, 0x13, - 0x78, 0x49, 0xF5, 0x44, 0x1E, 0xAF, 0xF7, 0x87, 0x3C, 0x8D, 0x17, 0xCE, 0xC2, 0x2C, 0xCB, 0x58, - 0x2B, 0xEB, 0x9D, 0xC5, 0x10, 0x2C, 0x3B, 0x93, 0x6C, 0x27, 0x44, 0xD8, 0xD8, 0xC0, 0x1F, 0xA3, - 0x19, 0x89, 0xAB, 0x05, 0x34, 0x9C, 0x80, 0x3B, 0xC1, 0x98, 0x5C, 0xC2, 0x90, 0x1D, 0x91, 0xB3, - 0x8E, 0xEC, 0xF7, 0x7F, 0xE1, 0x59, 0xE6, 0x5C, 0x2F, 0xF2, 0xD9, 0xE4, 0xFF, 0xA2, 0x7A, 0x47, - 0x82, 0xFB, 0xAD, 0x34, 0xBF, 0x64, 0x32, 0x55, 0xB5, 0x2E, 0xF7, 0xB5, 0x28, 0x50, 0x6E, 0x91, - 0xBD, 0x35, 0xA3, 0xDF, 0xFE, 0x55, 0x64, 0xBB, 0xA0, 0x86, 0x52, 0xB9, 0x51, 0xC7, 0x8D, 0xF5, - 0x74, 0x3D, 0x97, 0xD2, 0x60, 0x62, 0x05, 0x5D, 0x45, 0xA5, 0x3E, 0x16, 0xB5, 0xA4, 0x1E, 0x4E, - 0x9A, 0x85, 0xB9, 0xEA, 0x4E, 0xD2, 0xE7, 0xB0, 0xD0, 0xFE, 0x7F, 0xF9, 0x6A, 0x2E, 0x67, 0x1B, - 0xF2, 0xC6, 0x0A, 0xF1, 0x05, 0x8D, 0x5C, 0x0C, 0x71, 0x05, 0x05, 0xC5, 0x1C, 0xB5, 0x2C, 0xCE, - 0x07, 0xFD, 0x03, 0x15, 0x2D, 0xAF, 0x27, 0x96, 0x77, 0x65, 0xF1, 0x2B, 0x66, 0x8A, 0x9C, 0xD3, - 0x89, 0xC0, 0x6E, 0x7B, 0xF7, 0x5C, 0x52, 0x71, 0x65, 0x76, 0xE4, 0x10, 0x32, 0xDF, 0xF6, 0x96, - 0x0B, 0x6D, 0x85, 0xB8, 0x1D, 0xDA, 0x61, 0x86, 0x4D, 0x7C, 0x41, 0xD7, 0x07, 0xFF, 0xC4, 0x77, - 0x28, 0x08, 0x7F, 0x8A, 0x83, 0x38, 0xE2, 0xD6, 0x75, 0x58, 0x18, 0xE1, 0x97, 0xE9, 0xF6, 0xBC, - 0x67, 0xD5, 0x44, 0xEB, 0x32, 0xF5, 0xBF, 0x7C, 0xFF, 0x9A, 0xAE, 0xE7, 0xB2, 0x4A, 0xF2, 0x45, - 0xF6, 0x7A, 0x1E, 0x4A, 0xDB, 0x1C, 0x9B, 0xC2, 0x3A, 0x8D, 0xC6, 0x94, 0xAF, 0x84, 0x47, 0xD9, - 0xA7, 0x08, 0x68, 0x85, 0x66, 0x2B, 0xCA, 0x5A, 0xD4, 0x6E, 0x36, 0x21, 0x65, 0xB5, 0x57, 0x04, - 0x69, 0xB6, 0x70, 0x34, 0xE6, 0x65, 0xA5, 0xC9, 0x12, 0x62, 0x02, 0xCB, 0x4B, 0x68, 0x5B, 0x90, - 0x0D, 0xA7, 0x80, 0x01, 0xA6, 0xE9, 0x8D, 0x39, 0xD0, 0x76, 0x1A, 0x6B, 0x44, 0x5A, 0x4A, 0xAB, - 0x3A, 0xD5, 0xD4, 0x91, 0xA3, 0x30, 0x9C, 0x8A, 0xA8, 0xF7, 0xA3, 0x83, 0x57, 0x6C, 0x43, 0xDD, - 0xCC, 0x47, 0x9D, 0x28, 0x7D, 0x95, 0xC6, 0x5B, 0xF6, 0x7C, 0x7D, 0xB1, 0x49, 0xC5, 0x3A, 0x55, - 0xCD, 0x2A, 0xAF, 0x5B, 0x62, 0x5A, 0xB1, 0x52, 0x73, 0xF3, 0xFA, 0x6C, 0xAC, 0x23, 0x6B, 0xC6, - 0xB3, 0xB0, 0x90, 0x19, 0x81, 0xD6, 0xB5, 0x92, 0x3F, 0x2D, 0xC6, 0x3F, 0x85, 0xC5, 0x60, 0xA3, - 0xCF, 0x7D, 0x0C, 0xAB, 0x21, 0xF9, 0x7D, 0x07, 0x30, 0x1D, 0xE2, 0x01, 0x44, 0x9A, 0x69, 0x55, - 0xDC, 0xD8, 0x41, 0x67, 0xAE, 0x7A, 0xE2, 0x4E, 0xC4, 0x78, 0x74, 0x20, 0x1D, 0xAA, 0x71, 0x76, - 0x3C, 0x76, 0xA2, 0xF2, 0xF1, 0x9A, 0x21, 0xEB, 0xC7, 0x77, 0x81, 0x1A, 0x23, 0x55, 0xB6, 0x38, - 0xB0, 0x94, 0x9F, 0xD8, 0xA4, 0x91, 0x05, 0x38, 0x4A, 0xDF, 0xF1, 0xD4, 0x9D, 0x30, 0x38, 0xFA, - 0x98, 0xD7, 0x1A, 0x33, 0xCB, 0x82, 0xF5, 0xC5, 0x12, 0x35, 0x31, 0x76, 0x52, 0x55, 0xB2, 0x97, - 0x32, 0xCE, 0x5D, 0x33, 0xF7, 0x4B, 0x62, 0xE5, 0x96, 0x9E, 0x17, 0x4E, 0x83, 0x51, 0x84, 0xC9, - 0x5E, 0x70, 0xCD, 0xD7, 0x5A, 0x45, 0x14, 0xFF, 0xC2, 0xD8, 0x67, 0x7D, 0x25, 0x4B, 0xF3, 0x4B, - 0x8A, 0x1E, 0x5F, 0x5D, 0xC5, 0x63, 0xD4, 0x3F, 0xD9, 0x8C, 0x9B, 0x5D, 0x47, 0x74, 0x83, 0x30, - 0x8F, 0xB2, 0x56, 0x24, 0xE8, 0x85, 0x4C, 0xC1, 0xD3, 0x86, 0xDA, 0x9D, 0xF8, 0x64, 0xB6, 0x73, - 0x13, 0xD0, 0x6B, 0x7C, 0xBE, 0x38, 0xAE, 0x16, 0xDF, 0xE7, 0x4C, 0x68, 0x2D, 0x2F, 0xEF, 0xE4, - 0xF5, 0x7E, 0xBC, 0x16, 0x92, 0x0E, 0x9D, 0xD2, 0xB1, 0x5F, 0xB7, 0x9F, 0xF2, 0xF2, 0xB5, 0xE2, - 0xA6, 0x51, 0x8A, 0x55, 0xC9, 0xD8, 0xEA, 0x65, 0xF2, 0xB5, 0xA6, 0x15, 0x31, 0x67, 0x6B, 0x3A, - 0xBE, 0xE2, 0xE5, 0x4A, 0xB2, 0x0C, 0x4C, 0xAF, 0x29, 0xEE, 0x94, 0x68, 0x38, 0x55, 0x33, 0x09, - 0xCF, 0x4B, 0xBF, 0x5F, 0xE4, 0x9D, 0x99, 0x67, 0xFA, 0x3D, 0xDE, 0xD4, 0x81, 0xFE, 0x66, 0x8C, - 0x85, 0xE2, 0xF0, 0x3C, 0x33, 0x05, 0xCB, 0x9A, 0xA5, 0xEF, 0xE0, 0xC9, 0x76, 0xD7, 0x80, 0xDC, - 0xF8, 0xE6, 0x6F, 0x75, 0xCD, 0xFC, 0x9E, 0x51, 0x48, 0xD6, 0x96, 0xD6, 0x4E, 0xE5, 0x99, 0xB6, - 0x70, 0xAA, 0x4D, 0x18, 0x29, 0x9F, 0x60, 0xA5, 0xB6, 0xAF, 0xAE, 0x9E, 0xD3, 0x6B, 0x98, 0x51, - 0x6F, 0x78, 0xBA, 0xEE, 0x24, 0xAC, 0xA8, 0x70, 0xB9, 0xA9, 0xEC, 0x9E, 0xEC, 0x68, 0x57, 0x48, - 0x79, 0xE6, 0x6C, 0x4D, 0xE3, 0xA5, 0x5C, 0xE0, 0xF8, 0x6B, 0x77, 0x2E, 0xE9, 0xBF, 0x39, 0xA6, - 0x86, 0x19, 0xBF, 0x39, 0xA3, 0x86, 0xAB, 0xD1, 0x30, 0xD7, 0x0F, 0x03, 0xCC, 0x46, 0xDF, 0x26, - 0xF1, 0xAF, 0x1F, 0x60, 0x7A, 0x1F, 0xD1, 0x40, 0x15, 0x2C, 0xC3, 0x92, 0x05, 0x67, 0x16, 0xA6, - 0x0D, 0xD6, 0x85, 0x27, 0xCE, 0xAE, 0x03, 0xCA, 0x0F, 0x23, 0xDA, 0xFC, 0x50, 0xA2, 0x0E, 0xA0, - 0x7D, 0xE5, 0x07, 0x11, 0x00, 0xB2, 0xFF, 0xE7, 0x03, 0xE6, 0x24, 0x39, 0x1F, 0x15, 0x27, 0x38, - 0x97, 0x5E, 0x89, 0xD0, 0xE4, 0x11, 0xA7, 0xA3, 0x4E, 0xBB, 0x79, 0x42, 0x83, 0x01, 0xBF, 0x1F, - 0xCB, 0xCB, 0x3A, 0x23, 0x96, 0xBA, 0x9A, 0xAC, 0x12, 0xFE, 0x67, 0xE4, 0x47, 0xB8, 0x0F, 0xF8, - 0x67, 0x3C, 0xDA, 0x97, 0xB2, 0x7A, 0x0B, 0xB4, 0x6F, 0xED, 0x40, 0x3A, 0xA4, 0x3B, 0xB1, 0xA3, - 0x9B, 0x4E, 0xE0, 0x4F, 0x81, 0x1B, 0x81, 0x76, 0x29, 0x05, 0x99, 0x4A, 0x79, 0xD1, 0x35, 0xC7, - 0xD8, 0x00, 0x87, 0x83, 0xEE, 0x7F, 0x0B, 0xD5, 0xA4, 0x0E, 0xCF, 0xB6, 0x9E, 0x6C, 0x09, 0x0B, - 0x96, 0xDF, 0xE0, 0xCB, 0x24, 0x56, 0xE6, 0x81, 0xA5, 0x7C, 0x3A, 0xAD, 0xB3, 0x34, 0x81, 0x7B, - 0x9B, 0xDC, 0xE1, 0x15, 0x2C, 0x6F, 0xC8, 0x15, 0x1D, 0xBC, 0x4F, 0xA6, 0xDD, 0xF7, 0xD0, 0x41, - 0xE3, 0x96, 0xE1, 0xD1, 0x5C, 0x4D, 0x3B, 0x54, 0x41, 0x96, 0xD1, 0xE5, 0x99, 0xD9, 0x49, 0x92, - 0x9A, 0xBD, 0x4C, 0x90, 0xF1, 0xC1, 0xD1, 0x3C, 0x86, 0x3A, 0xFB, 0x96, 0x98, 0x73, 0x4C, 0xAC, - 0xCE, 0x8F, 0x26, 0xDE, 0xDE, 0x1F, 0x39, 0x75, 0xB9, 0x96, 0xE4, 0x21, 0x6B, 0x7C, 0x23, 0x61, - 0xBC, 0xB3, 0x81, 0x49, 0x47, 0x45, 0x2A, 0x8F, 0x86, 0x46, 0x48, 0xF7, 0x10, 0x81, 0xC0, 0x9A, - 0xA2, 0x8D, 0x06, 0x22, 0xEB, 0xE6, 0x5B, 0x9C, 0x41, 0x15, 0xD7, 0x26, 0xBD, 0xE7, 0x7F, 0x31, - 0xA8, 0x94, 0x0D, 0x94, 0x9F, 0x90, 0x25, 0x18, 0xD5, 0x58, 0x54, 0xE3, 0x36, 0x20, 0x3F, 0xD2, - 0xCB, 0x81, 0x88, 0xDB, 0x96, 0x14, 0x63, 0x76, 0x45, 0xF9, 0x05, 0x9D, 0xED, 0xF5, 0x2D, 0xD3, - 0x4C, 0x0E, 0xF5, 0x79, 0xFA, 0xD4, 0x92, 0x26, 0x55, 0x49, 0xEB, 0x9A, 0x34, 0xC9, 0x94, 0x90, - 0xB5, 0xB8, 0x49, 0x79, 0x29, 0x5C, 0x87, 0x72, 0x71, 0xC5, 0x26, 0x4D, 0x9D, 0x49, 0x51, 0x63, - 0x3E, 0x39, 0x35, 0x1A, 0x33, 0x75, 0x72, 0xF2, 0x2E, 0x16, 0x34, 0x27, 0x17, 0x26, 0xD1, 0x3F, - 0xC7, 0xDC, 0xA0, 0xAE, 0xD5, 0xED, 0x5A, 0xA6, 0x16, 0x39, 0x37, 0x83, 0xC9, 0x21, 0x2C, 0x23, - 0x03, 0x8F, 0x46, 0xD9, 0x56, 0x89, 0x82, 0x83, 0x0F, 0xFB, 0x67, 0xC5, 0x4D, 0x92, 0x32, 0xAF, - 0x1F, 0x9D, 0xA9, 0x2C, 0xC6, 0xD8, 0x0B, 0x9B, 0x27, 0x65, 0x44, 0x2F, 0x87, 0x97, 0xF9, 0x87, - 0x02, 0xBC, 0xEC, 0xCD, 0xE2, 0x9C, 0x55, 0x6F, 0x58, 0x0B, 0x84, 0xC7, 0x6F, 0x77, 0xEE, 0xB5, - 0x7B, 0xCA, 0x01, 0x2A, 0x39, 0x90, 0xAE, 0xF3, 0x6F, 0xBB, 0x12, 0xCC, 0xD7, 0x05, 0xF2, 0xA7, - 0x3F, 0x91, 0xA4, 0xEC, 0x8F, 0xBB, 0xFD, 0xBE, 0xEE, 0x3C, 0x6B, 0xFE, 0x9E, 0x4C, 0x30, 0xCF, - 0xDD, 0x43, 0x61, 0xCB, 0xF5, 0xD0, 0xA3, 0x63, 0xDD, 0x96, 0x9C, 0x28, 0x12, 0x6B, 0x49, 0x8B, - 0x40, 0x80, 0xA6, 0xE1, 0xDA, 0x40, 0xF2, 0xB8, 0xE2, 0x43, 0x29, 0x56, 0xA6, 0x79, 0x4F, 0xAC, - 0xDF, 0x4E, 0xE9, 0x5D, 0x9C, 0x2A, 0x4A, 0xE9, 0x67, 0x3D, 0x6F, 0xCA, 0x1F, 0x92, 0xC4, 0xD4, - 0xD0, 0xD6, 0x45, 0x4D, 0xBC, 0x2C, 0x14, 0x40, 0x57, 0xE5, 0x93, 0x70, 0xC8, 0x03, 0x2B, 0x16, - 0xE2, 0x57, 0x3E, 0xF6, 0x05, 0x41, 0x28, 0xC1, 0x67, 0x64, 0x7E, 0x75, 0xDF, 0xB9, 0x6C, 0x62, - 0xC0, 0x8B, 0xDF, 0x74, 0x3C, 0x89, 0xEE, 0x65, 0xB5, 0x35, 0xB8, 0xCE, 0x22, 0xB7, 0xDE, 0xBE, - 0xC6, 0x77, 0x5E, 0x00, 0xA2, 0x60, 0x22, 0x97, 0x3E, 0xE8, 0x91, 0x87, 0xD7, 0x9A, 0x61, 0x22, - 0x85, 0x39, 0x54, 0x34, 0xA9, 0xA5, 0xBD, 0xC3, 0x84, 0xFA, 0x21, 0x1E, 0xDD, 0xC0, 0x1D, 0x1F, - 0xE9, 0xC4, 0x08, 0x96, 0xA3, 0xE0, 0xBC, 0x90, 0xC1, 0x34, 0x08, 0x70, 0x4A, 0x67, 0xAD, 0xC1, - 0x9E, 0x67, 0xDB, 0x33, 0x67, 0xBF, 0x86, 0xA9, 0xCA, 0x8D, 0x42, 0x31, 0x71, 0x35, 0xD3, 0xAE, - 0x02, 0x45, 0x92, 0x50, 0xE7, 0xE9, 0x91, 0xC4, 0xFC, 0xF2, 0xAE, 0x0C, 0x90, 0x2E, 0x11, 0xDA, - 0xB8, 0x7C, 0xD0, 0x4A, 0xE2, 0x80, 0x6A, 0x28, 0x54, 0xFA, 0x40, 0xB5, 0x6C, 0xE7, 0xFB, 0x52, - 0x27, 0xE8, 0x76, 0x20, 0x87, 0x85, 0x0C, 0x68, 0x1B, 0x6B, 0xC7, 0x64, 0xD0, 0x00, 0x54, 0x06, - 0x64, 0x3D, 0xD5, 0x8E, 0x3B, 0x44, 0xAB, 0xAD, 0xAB, 0x37, 0xBE, 0x83, 0x12, 0xDF, 0x5B, 0x91, - 0xF7, 0x68, 0xE2, 0x72, 0xB6, 0x81, 0x00, 0xF0, 0x62, 0x4F, 0x26, 0x41, 0xB6, 0x64, 0x7C, 0x62, - 0x45, 0x29, 0x4F, 0x6F, 0x73, 0x48, 0xF4, 0x8C, 0x8F, 0x5E, 0x65, 0x98, 0x32, 0x3D, 0x7D, 0xC5, - 0x2A, 0x01, 0x72, 0xD3, 0xD8, 0x54, 0x9E, 0x6E, 0xCA, 0x21, 0xB9, 0x94, 0xDD, 0x73, 0x68, 0xED, - 0x23, 0x1C, 0x53, 0x75, 0xC1, 0x16, 0xAA, 0x53, 0x0E, 0x7C, 0x72, 0x5F, 0xA4, 0x74, 0x04, 0x09, - 0x46, 0x93, 0xC7, 0x7E, 0x08, 0x4C, 0x31, 0x21, 0x0B, 0xBF, 0xD8, 0xD1, 0xCC, 0x71, 0x42, 0xE3, - 0x17, 0x5E, 0x63, 0xF1, 0x5A, 0xFD, 0x5B, 0x69, 0x5F, 0x2E, 0x4D, 0xE9, 0x01, 0x54, 0x0D, 0x9E, - 0xED, 0xF8, 0x9D, 0x7E, 0xBC, 0x3C, 0x3A, 0xBD, 0x38, 0x3C, 0x3F, 0x85, 0x35, 0x6A, 0x6D, 0x73, - 0x74, 0xEA, 0xE3, 0x56, 0xAE, 0x32, 0xA7, 0x48, 0xD9, 0xA3, 0xDD, 0xDB, 0xF7, 0x34, 0x52, 0x8C, - 0x8E, 0x3A, 0xC3, 0x96, 0xDA, 0x25, 0x6D, 0x3F, 0x51, 0x35, 0x6F, 0xCA, 0x96, 0x66, 0x4E, 0xCB, - 0xFA, 0x87, 0xE7, 0xBF, 0x1C, 0x9E, 0x37, 0x68, 0x17, 0xB7, 0x23, 0x04, 0xFA, 0x9B, 0xFB, 0x00, - 0x2C, 0x77, 0x89, 0x7D, 0x0B, 0x4E, 0x2C, 0x3F, 0x22, 0x7E, 0x6E, 0x6D, 0xDD, 0xFF, 0x74, 0x7E, - 0x7E, 0x78, 0x6A, 0xEC, 0xC1, 0xDC, 0x46, 0x26, 0x83, 0x18, 0xA6, 0x92, 0xE9, 0x04, 0xED, 0x39, - 0x4F, 0xC7, 0xF8, 0xC4, 0x6D, 0x93, 0xA7, 0x29, 0x9D, 0x8E, 0xEE, 0xF5, 0xB3, 0x68, 0x3E, 0x60, - 0xF4, 0xB6, 0xC5, 0xEE, 0xBA, 0x28, 0x72, 0xD8, 0x29, 0x44, 0x64, 0xE6, 0x46, 0x7D, 0xA5, 0x0B, - 0xB1, 0x9F, 0xE5, 0xAD, 0xD0, 0xCC, 0x03, 0x4D, 0x05, 0x92, 0x86, 0x9B, 0x48, 0x1F, 0x6F, 0x12, - 0x9D, 0x76, 0x74, 0xA5, 0x5B, 0xAC, 0xE7, 0xE3, 0x4E, 0xFC, 0xF8, 0xEE, 0x37, 0xFA, 0x28, 0x95, - 0xCC, 0x5D, 0x46, 0xF9, 0xB3, 0x3D, 0x05, 0xED, 0x7F, 0x2F, 0x9E, 0x06, 0xC3, 0xAD, 0xA8, 0x6B, - 0xA9, 0x79, 0x3F, 0xDD, 0x18, 0xD5, 0x8D, 0x31, 0xB8, 0x0A, 0xAA, 0xE6, 0x3E, 0xB6, 0xA3, 0xA0, - 0x52, 0x33, 0xBA, 0x09, 0x1A, 0x43, 0x26, 0x27, 0x61, 0xC8, 0xF1, 0xCA, 0x23, 0x4E, 0x0A, 0x7B, - 0x8B, 0xEF, 0x8D, 0xA0, 0x3D, 0xED, 0xB6, 0x72, 0xDF, 0x7E, 0x34, 0xB2, 0xB2, 0x64, 0xB4, 0xD4, - 0x31, 0xB6, 0xC3, 0xF3, 0xF3, 0x8F, 0xEA, 0x2C, 0xF4, 0x48, 0x43, 0xAB, 0xCC, 0xE4, 0x33, 0x6B, - 0x10, 0x8B, 0x41, 0xD5, 0x7A, 0xE5, 0x29, 0x56, 0x75, 0x61, 0xE8, 0x47, 0x76, 0x4C, 0x5D, 0x3C, - 0x74, 0x28, 0xF6, 0xE4, 0xE2, 0xBD, 0x22, 0xA3, 0xA3, 0x95, 0x27, 0xA7, 0xEA, 0xC3, 0x53, 0xA3, - 0xC2, 0x37, 0x09, 0xF5, 0x07, 0x0F, 0xAB, 0x9A, 0x70, 0x0D, 0x99, 0x74, 0x74, 0xA1, 0x93, 0xD9, - 0xCD, 0x6C, 0x34, 0x6A, 0xEF, 0xAA, 0x2A, 0xC9, 0x22, 0xDE, 0xBB, 0xB7, 0xD4, 0x23, 0x36, 0x3E, - 0xD0, 0x1B, 0x2C, 0x84, 0x22, 0xBF, 0x19, 0x0A, 0xF3, 0x1E, 0x27, 0x2A, 0xE8, 0x66, 0x2F, 0x72, - 0xAF, 0x79, 0x96, 0x31, 0x8C, 0xEA, 0x63, 0x26, 0x42, 0xAC, 0x30, 0xF1, 0x5B, 0x1A, 0xB0, 0x0D, - 0x9E, 0x14, 0x39, 0x38, 0xE8, 0x38, 0xF1, 0x3F, 0xB6, 0x9D, 0x6E, 0x4B, 0x41, 0xEA, 0x31, 0xAE, - 0x23, 0xB4, 0x15, 0xF8, 0xA6, 0xD6, 0x22, 0xD2, 0x3C, 0xF4, 0x80, 0x94, 0xBA, 0x5A, 0x8F, 0x31, - 0x26, 0x15, 0xA1, 0xF9, 0xEA, 0x6B, 0x5C, 0x61, 0x67, 0xFF, 0xE3, 0xC7, 0xF3, 0x83, 0xA3, 0xD3, - 0xBD, 0x8B, 0x43, 0x70, 0xFF, 0xCE, 0x3E, 0x5D, 0x5C, 0x5E, 0x7C, 0x3E, 0xC3, 0x5F, 0x7F, 0xD9, - 0x3B, 0x3E, 0x3A, 0xB8, 0xFC, 0x74, 0xFA, 0x97, 0xD3, 0x8F, 0xBF, 0x9E, 0xA6, 0x5B, 0xF6, 0x8E, - 0x1D, 0xDE, 0x48, 0xF7, 0xE1, 0x13, 0xF3, 0x88, 0x01, 0xF5, 0x86, 0xEF, 0x0E, 0x1D, 0xB8, 0x63, - 0x7B, 0x64, 0x28, 0xE1, 0xA6, 0xEA, 0xE3, 0xF5, 0x31, 0x65, 0xAF, 0x6C, 0xEA, 0x67, 0x97, 0x60, - 0x3C, 0xC0, 0xDB, 0x8A, 0xF0, 0x31, 0xB7, 0x44, 0x2E, 0xFC, 0xCD, 0x24, 0xBC, 0x69, 0x8D, 0xEA, - 0x45, 0xEE, 0x6E, 0x6C, 0x36, 0x5D, 0x0D, 0x99, 0xE0, 0x41, 0xC6, 0xD3, 0x30, 0xB1, 0xCA, 0x03, - 0xDB, 0x23, 0x14, 0x05, 0xC2, 0x4C, 0xA6, 0xEB, 0x41, 0xE7, 0xBB, 0x0E, 0xBB, 0x33, 0x1F, 0x8A, - 0x2A, 0x7B, 0x84, 0x7F, 0xE3, 0xB5, 0xF0, 0x59, 0x5A, 0x96, 0xE5, 0x8E, 0x9F, 0x72, 0x86, 0x6D, - 0xB2, 0xD2, 0xC6, 0x68, 0xDA, 0x36, 0xEB, 0xA6, 0x8E, 0x7A, 0x92, 0x27, 0x19, 0xDF, 0x44, 0xF0, - 0xBA, 0xE9, 0x55, 0x2F, 0x09, 0x87, 0x8E, 0x3B, 0x74, 0xA3, 0xB4, 0x9B, 0xF0, 0x88, 0x3A, 0xEF, - 0xC2, 0x28, 0x02, 0xA8, 0x62, 0x63, 0x77, 0x05, 0x8C, 0xF2, 0x5A, 0x5E, 0x2E, 0x7A, 0x57, 0x46, - 0x26, 0x87, 0x58, 0x16, 0x56, 0x16, 0x96, 0xD2, 0x0E, 0x5C, 0x5E, 0x66, 0x6F, 0x5D, 0x8D, 0x46, - 0x64, 0xE8, 0xFB, 0x4E, 0x05, 0x68, 0x02, 0xD0, 0x69, 0x3F, 0xD7, 0x06, 0xEF, 0x20, 0x71, 0xA9, - 0x5D, 0x45, 0x08, 0xE2, 0x9D, 0x97, 0x46, 0xCA, 0x2A, 0x4E, 0xBB, 0xD9, 0x82, 0x0D, 0xD4, 0x08, - 0xE3, 0x78, 0x42, 0x45, 0x05, 0x58, 0xDA, 0x04, 0xF5, 0x68, 0x0D, 0xBC, 0x7B, 0x54, 0xA2, 0x89, - 0x1F, 0x86, 0x2E, 0x46, 0xFB, 0x72, 0xAD, 0xC0, 0x71, 0x1A, 0xEB, 0x4B, 0x3A, 0x24, 0xD3, 0x0F, - 0x27, 0x27, 0x9D, 0x31, 0xFF, 0x97, 0x7E, 0x23, 0xA6, 0x8F, 0x2B, 0xA6, 0x8F, 0x27, 0x27, 0xFD, - 0x7E, 0x27, 0x64, 0xFF, 0x14, 0x70, 0x62, 0xF8, 0x0C, 0x08, 0x56, 0xD2, 0xCF, 0x2F, 0x8C, 0x7A, - 0xC2, 0xEE, 0xA8, 0xCD, 0x2E, 0xB9, 0xFF, 0x8B, 0x21, 0xD0, 0x9E, 0xDF, 0x21, 0xEB, 0x30, 0xDA, - 0xB6, 0xAD, 0xB5, 0xB5, 0xF5, 0x97, 0x2C, 0xBB, 0x20, 0x93, 0x5F, 0x27, 0x8D, 0xBF, 0x4E, 0x47, - 0xFC, 0x1B, 0xD2, 0x9B, 0x07, 0xE1, 0x8F, 0x38, 0xFE, 0x2C, 0x96, 0xF1, 0x02, 0x46, 0x5A, 0x8F, - 0xD8, 0x23, 0xCC, 0xB9, 0xE8, 0x20, 0x23, 0xC4, 0xDA, 0x20, 0xBD, 0x8D, 0x4E, 0xCF, 0x5A, 0xDF, - 0x36, 0xB0, 0x92, 0xDA, 0xA4, 0x37, 0x64, 0x6D, 0xCE, 0x9C, 0xF4, 0x18, 0x33, 0x6B, 0x29, 0x33, - 0x2B, 0x5D, 0x6B, 0x63, 0xA5, 0xDB, 0x5D, 0xB1, 0x36, 0x3A, 0xDD, 0xCD, 0x9E, 0x89, 0x1D, 0xB3, - 0x65, 0x7B, 0x83, 0x57, 0x18, 0xE6, 0xC4, 0xDA, 0x4B, 0xE4, 0xE9, 0x9A, 0xDE, 0xD1, 0x80, 0xF3, - 0xD3, 0xED, 0x22, 0x37, 0x5B, 0x5B, 0xDB, 0xDB, 0x3D, 0xB2, 0x78, 0xC0, 0x35, 0x0B, 0xAB, 0xF0, - 0xDF, 0x96, 0x12, 0x1E, 0x53, 0x77, 0xD6, 0xA3, 0x43, 0x3B, 0x02, 0xBB, 0xD9, 0x77, 0x87, 0x9E, - 0xEA, 0x3D, 0xA8, 0x63, 0xD7, 0x4A, 0x0D, 0x47, 0x6A, 0xA5, 0x92, 0x62, 0xEE, 0x77, 0xE1, 0xB5, - 0x81, 0x3D, 0xC9, 0xB8, 0xB5, 0x51, 0x74, 0x18, 0xD9, 0xCF, 0xCE, 0xB1, 0xF0, 0x6E, 0x01, 0x18, - 0x2F, 0x26, 0x0A, 0x6E, 0x3E, 0xD2, 0x9B, 0x44, 0x2A, 0x13, 0x6A, 0xD8, 0x52, 0xD2, 0xA9, 0x2B, - 0x2B, 0x88, 0x08, 0xD3, 0x84, 0xA6, 0xFD, 0x0C, 0xD6, 0x1A, 0xE7, 0x4C, 0xBE, 0xE5, 0xC0, 0xDE, - 0xF0, 0x0E, 0x6F, 0x28, 0xB7, 0xE0, 0x3C, 0xBB, 0x28, 0x4B, 0xBC, 0x21, 0x88, 0xC6, 0x64, 0x48, - 0x08, 0x74, 0xF4, 0xED, 0x38, 0x59, 0x8F, 0xB9, 0xA1, 0xC5, 0x35, 0x95, 0x34, 0xCB, 0x25, 0xDF, - 0x72, 0xFA, 0x75, 0x97, 0xDD, 0x4D, 0xC1, 0x27, 0x24, 0x73, 0xCB, 0x37, 0x97, 0x60, 0x41, 0xB6, - 0xBA, 0x9A, 0x1D, 0xF1, 0xF2, 0x33, 0xDF, 0xCD, 0xE7, 0x6A, 0x8E, 0x57, 0x8A, 0x39, 0xE0, 0x49, - 0x46, 0xD8, 0x91, 0x12, 0xBF, 0xA4, 0xC4, 0x0E, 0x5A, 0x41, 0xBC, 0xDE, 0x20, 0xBE, 0xFB, 0x9D, - 0x3A, 0x0C, 0xAC, 0x9B, 0xC0, 0xF9, 0x24, 0x42, 0x6F, 0x14, 0x2C, 0xC2, 0xBE, 0xA8, 0x28, 0x24, - 0xD4, 0xFC, 0xE6, 0xB7, 0x25, 0xE3, 0x48, 0x27, 0xBE, 0xB4, 0xDA, 0xCA, 0x6E, 0x62, 0xAA, 0xF8, - 0x89, 0xB2, 0x72, 0x5B, 0x9C, 0x25, 0x2A, 0xE6, 0xC9, 0xF1, 0x8B, 0x09, 0x25, 0x64, 0x4E, 0x4E, - 0xE4, 0xA8, 0xBF, 0x77, 0x2E, 0x4C, 0xD1, 0x30, 0xBD, 0x28, 0x53, 0x6E, 0x3A, 0x31, 0xB3, 0xAB, - 0x53, 0x1F, 0xAF, 0x17, 0xD9, 0x04, 0x04, 0xBD, 0xB1, 0xD2, 0xD5, 0x77, 0xFE, 0x67, 0x15, 0xFD, - 0xE5, 0xE9, 0xC7, 0xCB, 0x83, 0xC3, 0xFD, 0xA3, 0x93, 0xBD, 0x63, 0xAD, 0x17, 0x42, 0x0A, 0x13, - 0x90, 0x83, 0xCD, 0x4A, 0xF8, 0xD1, 0xC4, 0x2D, 0xAB, 0x03, 0x5F, 0x5C, 0x71, 0x08, 0xA3, 0xC8, - 0xD2, 0x01, 0x25, 0x0B, 0x5A, 0x06, 0x89, 0xE5, 0xF8, 0xE7, 0x44, 0x5E, 0x02, 0x00, 0x44, 0x26, - 0x05, 0xD9, 0x19, 0x5C, 0xAB, 0x98, 0xD8, 0x72, 0x8A, 0x64, 0x95, 0x6C, 0xC2, 0x14, 0xC0, 0x52, - 0x06, 0xC4, 0x34, 0x56, 0xC9, 0xDA, 0x26, 0xE6, 0xCA, 0x59, 0xD2, 0xEE, 0xBC, 0x2B, 0x23, 0xD9, - 0xEC, 0xD7, 0x98, 0xC8, 0xFE, 0x19, 0xBB, 0x43, 0x7E, 0x07, 0xF3, 0xC1, 0xB4, 0x7A, 0xD2, 0x86, - 0x28, 0x8E, 0x46, 0x75, 0x80, 0xB2, 0xF1, 0x99, 0x3B, 0xFC, 0x36, 0x70, 0x74, 0xE6, 0x96, 0xAE, - 0x27, 0x63, 0x53, 0x99, 0xA1, 0xE7, 0x37, 0x34, 0x2B, 0x0E, 0xCC, 0x74, 0x44, 0x2A, 0x1A, 0x92, - 0x33, 0x1C, 0xF5, 0xA1, 0x51, 0x77, 0x00, 0xE6, 0x0E, 0x3F, 0xB3, 0x9E, 0x2A, 0xA2, 0x61, 0x71, - 0xCC, 0x02, 0xC0, 0x80, 0xD8, 0xAC, 0xA4, 0x75, 0x95, 0xEE, 0x91, 0xF5, 0x4B, 0x55, 0x30, 0x45, - 0x9B, 0xBA, 0x5C, 0x1F, 0x56, 0x1E, 0x49, 0x21, 0x2E, 0x4F, 0x4E, 0x2E, 0x0F, 0xF6, 0xFA, 0x1F, - 0x34, 0xB5, 0x10, 0xD1, 0x54, 0xA9, 0xD9, 0x12, 0x77, 0xE5, 0x56, 0xF4, 0xBB, 0x94, 0xA9, 0x0E, - 0x08, 0x53, 0x8E, 0x90, 0x98, 0x9D, 0x29, 0xED, 0xB0, 0x9C, 0xAE, 0x95, 0xEB, 0x77, 0xBF, 0x4A, - 0xC6, 0x34, 0xD3, 0xBB, 0xCF, 0xAC, 0xB3, 0xF2, 0xFB, 0xAA, 0x97, 0xF4, 0x55, 0xEC, 0x1D, 0xCF, - 0xBD, 0xAF, 0xC0, 0xBC, 0x3F, 0xB3, 0xEE, 0x7A, 0x36, 0x73, 0x9F, 0x24, 0x9E, 0x2A, 0x53, 0xA0, - 0xDC, 0xA0, 0x5E, 0xDA, 0xA0, 0xEC, 0x1C, 0xF8, 0x8F, 0x3E, 0x41, 0x71, 0xA5, 0x4C, 0x37, 0x70, - 0xE6, 0xAA, 0x93, 0x3B, 0x25, 0x62, 0x4A, 0x0D, 0xF8, 0x0F, 0x13, 0x80, 0xB0, 0xA0, 0xE4, 0xF1, - 0x2C, 0x68, 0xC5, 0xD1, 0x48, 0x7E, 0x1A, 0xCF, 0xA2, 0x7E, 0xEA, 0x25, 0xFD, 0x44, 0x1E, 0x67, - 0x5D, 0xC2, 0x0D, 0xC4, 0x33, 0xEA, 0xAC, 0xE7, 0x66, 0x3A, 0xFF, 0xA7, 0x59, 0x4D, 0xB1, 0xA1, - 0xA5, 0x9C, 0x0C, 0x19, 0x10, 0xF0, 0xC3, 0x21, 0x43, 0x41, 0x92, 0x3B, 0x6C, 0x7B, 0x49, 0x4B, - 0x1C, 0x60, 0xE8, 0x0E, 0x7E, 0xE6, 0x93, 0x6E, 0xCC, 0x4B, 0x3B, 0xEC, 0xB8, 0xA9, 0x9B, 0x5E, - 0xB0, 0x6F, 0x13, 0x7F, 0x1A, 0xE1, 0x1F, 0xB6, 0xD8, 0xB5, 0x07, 0xA0, 0xBE, 0xAF, 0xEE, 0xC1, - 0xE3, 0x86, 0xF2, 0x15, 0x48, 0x6B, 0x4C, 0xC9, 0x82, 0x36, 0x64, 0x16, 0xDA, 0x84, 0x46, 0x03, - 0x39, 0x64, 0x98, 0xF1, 0xCD, 0xF8, 0x90, 0xF8, 0x6A, 0x9B, 0x54, 0xC6, 0xBC, 0x5F, 0x2F, 0x36, - 0x2F, 0xA5, 0x83, 0x46, 0x7E, 0xB3, 0xC2, 0xA0, 0x71, 0xD5, 0x55, 0x6E, 0xC9, 0x38, 0xAC, 0x53, - 0x0D, 0x4B, 0xBF, 0x2D, 0x49, 0x62, 0xD6, 0x4F, 0x6B, 0x65, 0x36, 0xCC, 0x67, 0x5D, 0x33, 0xB2, - 0x79, 0x29, 0xAD, 0x79, 0x60, 0xDD, 0x36, 0x23, 0xB6, 0xB9, 0x22, 0x8B, 0x5D, 0xF7, 0x39, 0xA3, - 0xEC, 0x7F, 0x3E, 0x79, 0xFB, 0xF1, 0x98, 0x21, 0xD5, 0xAF, 0xAC, 0x8C, 0x7C, 0x6F, 0xC8, 0xB2, - 0x34, 0x1D, 0xD0, 0x61, 0x40, 0xF5, 0xFD, 0x91, 0x4C, 0x4F, 0x68, 0x5D, 0x0B, 0x8B, 0x33, 0x1D, - 0x81, 0xB1, 0x1E, 0x0C, 0xD7, 0x4D, 0x6B, 0x47, 0xCB, 0x7C, 0x99, 0x94, 0xBE, 0x26, 0xB9, 0x96, - 0x8F, 0x0F, 0x74, 0xC9, 0x74, 0x29, 0x7A, 0x35, 0xC8, 0x0E, 0xDB, 0x97, 0x4B, 0x99, 0x0C, 0x9B, - 0x33, 0x76, 0x6F, 0x1E, 0x6B, 0xC9, 0x10, 0xCA, 0x88, 0x70, 0x19, 0x46, 0x15, 0xB3, 0x2E, 0x71, - 0xD5, 0x9D, 0xEC, 0xE1, 0xC5, 0x9C, 0x14, 0xA5, 0x11, 0x73, 0x2B, 0x4F, 0xC1, 0x1D, 0xD7, 0xB9, - 0x46, 0xFC, 0xFD, 0xF7, 0x7F, 0xA9, 0x0C, 0xE2, 0xB7, 0x85, 0x96, 0xCA, 0x66, 0x13, 0xBC, 0xC4, - 0xD4, 0x6E, 0xCD, 0xB6, 0xCC, 0xA5, 0xE9, 0xFD, 0x25, 0x79, 0x00, 0xCF, 0xAE, 0x82, 0x73, 0x46, - 0x28, 0xAD, 0xAA, 0x1E, 0x03, 0xAF, 0xDE, 0xF3, 0x73, 0x12, 0x81, 0xE4, 0xCA, 0x3C, 0x06, 0xD7, - 0x8F, 0x8B, 0x5D, 0x5B, 0xC1, 0x2E, 0xFD, 0xA3, 0x9B, 0x61, 0x85, 0xE7, 0x13, 0xD3, 0xD6, 0x7A, - 0x1D, 0x9E, 0x05, 0x82, 0x22, 0x9E, 0x2B, 0x4F, 0x00, 0x9B, 0x73, 0x9F, 0x00, 0xE4, 0xD1, 0x57, - 0x73, 0x0A, 0xC8, 0x88, 0xE8, 0x89, 0xA6, 0x86, 0xCC, 0xE8, 0xAE, 0x3B, 0x3B, 0x98, 0x18, 0x5F, - 0x79, 0x22, 0xCE, 0x67, 0x9E, 0x39, 0x4C, 0xCC, 0x2F, 0x64, 0xA7, 0x94, 0x7F, 0x6D, 0xB5, 0x1E, - 0xAB, 0x0D, 0x4B, 0x8D, 0xA7, 0x27, 0x13, 0xEF, 0xE4, 0xB1, 0x05, 0x9F, 0x6B, 0x5E, 0xE7, 0xA4, - 0xEE, 0xD2, 0x35, 0x4C, 0xA3, 0x59, 0x98, 0xB3, 0x02, 0xCD, 0xD8, 0x92, 0xE2, 0x7E, 0x78, 0xE2, - 0xB6, 0xE8, 0x13, 0xC7, 0xFC, 0x47, 0x74, 0x51, 0x83, 0x32, 0xD7, 0x94, 0x54, 0x7A, 0x5A, 0xCC, - 0x63, 0x1C, 0x84, 0x34, 0xC0, 0x27, 0x23, 0x05, 0xCC, 0xEA, 0xBF, 0x3A, 0xAB, 0x9D, 0x08, 0x2F, - 0x5C, 0x0F, 0x96, 0x76, 0x88, 0x9A, 0x10, 0x22, 0x3E, 0xD7, 0x87, 0x25, 0x71, 0x9B, 0xE7, 0x9F, - 0x84, 0x15, 0xEC, 0x4D, 0x20, 0x07, 0x49, 0xF2, 0xE4, 0x99, 0x6F, 0x70, 0xD5, 0x1C, 0x5F, 0xAC, - 0x5A, 0x91, 0x82, 0x50, 0xE0, 0xB3, 0xB2, 0x48, 0xC7, 0x6A, 0x4A, 0xDA, 0x47, 0x91, 0x5A, 0x73, - 0x19, 0xF1, 0x62, 0x34, 0xA8, 0x52, 0xCE, 0x91, 0x2F, 0xB3, 0x24, 0xF9, 0xF2, 0x3A, 0xDE, 0x53, - 0x56, 0xEE, 0x02, 0xB5, 0x8D, 0x2F, 0x76, 0x7A, 0x3C, 0x53, 0x9F, 0x58, 0xC3, 0x4B, 0x77, 0xA1, - 0x45, 0x49, 0x1A, 0x2F, 0x57, 0xB0, 0x12, 0x0F, 0xEF, 0xDC, 0x68, 0x70, 0x43, 0x8A, 0xAA, 0xB0, - 0xF0, 0x04, 0x7A, 0x6D, 0x4F, 0x47, 0xD1, 0x2B, 0x2D, 0xD7, 0x3F, 0xEF, 0x89, 0xD6, 0x27, 0xEF, - 0x9B, 0xE7, 0xDF, 0x79, 0x7A, 0xC2, 0x5C, 0xED, 0x5D, 0x89, 0x01, 0x5E, 0x4A, 0x5E, 0xAC, 0xBC, - 0x7E, 0xCF, 0xA1, 0x25, 0x6F, 0x53, 0xCC, 0x95, 0x20, 0x2C, 0xAE, 0x72, 0x49, 0xA6, 0xFB, 0x9E, - 0x73, 0x25, 0x79, 0x59, 0x44, 0x93, 0x3C, 0x1E, 0x51, 0x3E, 0x1F, 0xE7, 0x52, 0x5E, 0x79, 0x24, - 0xCA, 0xCC, 0x7B, 0x29, 0x90, 0x71, 0xB2, 0xC5, 0x34, 0xF7, 0xF6, 0x16, 0xD1, 0x55, 0x36, 0xB7, - 0x1E, 0x81, 0x72, 0xB9, 0xB0, 0x57, 0x1E, 0x87, 0xBC, 0x3E, 0x91, 0x16, 0x4A, 0xFE, 0x31, 0x1A, - 0x5E, 0x85, 0x36, 0x97, 0xFE, 0x63, 0x89, 0xBD, 0x12, 0x0B, 0xBC, 0x07, 0x0A, 0x58, 0x78, 0x78, - 0x91, 0x67, 0xED, 0x1E, 0xFE, 0x3F, 0x1B, 0x62, 0x1E, 0xA2, 0x79, 0x9B, 0x00 + 0x23, 0x64, 0x15, 0x6F, 0x30, 0xB0, 0x64, 0x79, 0x66, 0x26, 0x99, 0x87, 0x0F, 0x32, 0xA2, 0x21, + 0x54, 0xE5, 0xF7, 0x6E, 0xAF, 0xA6, 0x51, 0x24, 0x07, 0xE3, 0x57, 0x4B, 0xA5, 0x16, 0x05, 0xF7, + 0xE6, 0x4E, 0xC6, 0x60, 0x85, 0x22, 0x5D, 0x7B, 0x00, 0xE7, 0x38, 0x1A, 0xDC, 0x90, 0x45, 0x8A, + 0x3B, 0x4A, 0x66, 0x6F, 0x49, 0x72, 0x43, 0xFA, 0xE0, 0x1C, 0x5F, 0x00, 0x12, 0xE2, 0x86, 0x21, + 0xFC, 0x64, 0xD7, 0x2A, 0x8E, 0x0E, 0xE2, 0x94, 0x76, 0x75, 0xC6, 0x72, 0x71, 0xCE, 0xB9, 0x8A, + 0xED, 0x31, 0xA8, 0x53, 0x83, 0x06, 0xB1, 0xDB, 0xCB, 0xB5, 0x5B, 0x24, 0xF5, 0xE3, 0xDE, 0x68, + 0x44, 0x02, 0x3A, 0x9C, 0x8E, 0x30, 0x49, 0x20, 0x5B, 0x09, 0xF1, 0x3E, 0x4D, 0xD6, 0x21, 0x5A, + 0x77, 0xD6, 0x68, 0x6B, 0xAE, 0xC5, 0xA9, 0xD9, 0xCE, 0xA3, 0x06, 0xFD, 0xF5, 0x60, 0xCA, 0xBF, + 0x18, 0x5F, 0x07, 0x23, 0x18, 0xC6, 0x45, 0xD3, 0x6B, 0x74, 0x2C, 0x00, 0x84, 0xC7, 0xB1, 0xC1, + 0xE8, 0xF5, 0x86, 0x54, 0xEC, 0x29, 0x68, 0x61, 0x2A, 0x0B, 0x0B, 0x3B, 0x2F, 0xD2, 0xE9, 0x07, + 0xE6, 0x01, 0x11, 0xFB, 0x76, 0x12, 0x0E, 0x0D, 0x35, 0x05, 0x03, 0x07, 0x3E, 0xAE, 0xDF, 0xA6, + 0x3C, 0xB7, 0x1E, 0x28, 0x0F, 0x5E, 0xCF, 0x81, 0x65, 0x5D, 0x80, 0xE1, 0x7D, 0xB0, 0xA4, 0x22, + 0x77, 0xB0, 0x74, 0x4B, 0x7D, 0x16, 0xE8, 0x82, 0x6B, 0xFF, 0x45, 0x6C, 0xF2, 0xF5, 0xCC, 0x7C, + 0x7C, 0x10, 0xC8, 0xF2, 0xCA, 0xCD, 0x79, 0x9B, 0x76, 0xF0, 0x3B, 0x1F, 0xFC, 0x6C, 0xE8, 0x3B, + 0x7E, 0xC7, 0x87, 0x33, 0x92, 0xF6, 0xE9, 0x30, 0x9B, 0xA2, 0xE6, 0xC3, 0xDF, 0xA0, 0x35, 0x8E, + 0x1B, 0x4E, 0xB0, 0x8F, 0x58, 0x92, 0x6D, 0x8C, 0xAE, 0x26, 0xFB, 0xD3, 0x10, 0xE6, 0x40, 0xFE, + 0x37, 0x2C, 0x45, 0x51, 0x4C, 0x0B, 0x4B, 0x52, 0x2F, 0x18, 0x30, 0xF5, 0xE9, 0xA0, 0x31, 0x2A, + 0xBC, 0x64, 0x85, 0xCE, 0x5B, 0x5F, 0x5C, 0xE5, 0x9B, 0x19, 0xD1, 0x3B, 0x74, 0xB4, 0x1A, 0x63, + 0x61, 0x6E, 0xDA, 0x5B, 0x76, 0xCB, 0x54, 0xCE, 0x0F, 0xCA, 0x63, 0x7A, 0xE6, 0x8B, 0xF3, 0x3D, + 0xF5, 0x1B, 0xA3, 0xE4, 0xDE, 0xCA, 0x69, 0x14, 0xB8, 0x93, 0x3E, 0x05, 0xC1, 0x05, 0xF3, 0xC0, + 0xB4, 0x3F, 0x72, 0x59, 0x90, 0x70, 0x43, 0x4C, 0x78, 0xC7, 0x0E, 0xAF, 0x33, 0xE1, 0xD0, 0xF2, + 0xF0, 0x02, 0xC2, 0x4C, 0x1C, 0x9D, 0xF9, 0xAE, 0x17, 0x9D, 0xD1, 0xE0, 0x1A, 0x16, 0x92, 0xD2, + 0x92, 0x79, 0x46, 0xAC, 0x87, 0xF1, 0x4D, 0xDC, 0x29, 0xB3, 0xE8, 0x73, 0xC1, 0xF5, 0x41, 0x04, + 0xEF, 0xF3, 0x3C, 0xF5, 0xFE, 0x70, 0xC8, 0x02, 0xED, 0x67, 0x43, 0x1D, 0x4E, 0x4E, 0xFD, 0xBB, + 0x19, 0x91, 0x1C, 0xFB, 0x81, 0xDD, 0x18, 0x85, 0xF0, 0x19, 0xCE, 0x6E, 0x50, 0x6D, 0x29, 0x9E, + 0x1A, 0x32, 0xF7, 0x62, 0x46, 0x86, 0xE6, 0x21, 0x1B, 0x81, 0xE5, 0xFC, 0xE8, 0xF4, 0xF0, 0xB7, + 0x19, 0x51, 0xED, 0x9D, 0x9F, 0xCD, 0x87, 0x27, 0x5C, 0x36, 0xBC, 0x4B, 0x82, 0x87, 0x1D, 0x76, + 0xC0, 0x3E, 0x33, 0xC2, 0x78, 0x01, 0xD3, 0x0C, 0x4F, 0xDE, 0x85, 0xE7, 0x5A, 0x08, 0x13, 0x8C, + 0x7C, 0x3A, 0x41, 0x2B, 0x88, 0x49, 0xEB, 0xE5, 0x1D, 0x0A, 0x5E, 0x12, 0x87, 0x1D, 0xEA, 0xA5, + 0xD1, 0x40, 0x58, 0x95, 0xB7, 0xE8, 0x6C, 0x68, 0x25, 0xDC, 0x72, 0x65, 0x4A, 0xA6, 0xCE, 0x24, + 0xF3, 0xCD, 0xB9, 0x19, 0x4C, 0x0E, 0xC5, 0xAD, 0xFD, 0x2C, 0x75, 0x58, 0xA9, 0xE3, 0xCA, 0x3A, + 0x5B, 0xB0, 0x9F, 0xD9, 0x86, 0x74, 0x53, 0xBC, 0x0F, 0xCA, 0x93, 0x0B, 0xCC, 0xBD, 0x07, 0x77, + 0x43, 0x4C, 0xBA, 0xC2, 0xB5, 0x09, 0xA3, 0x7B, 0x70, 0x2A, 0x50, 0x60, 0x23, 0xF6, 0x9E, 0x45, + 0xCB, 0xF3, 0x3D, 0xDA, 0x52, 0x1F, 0x6B, 0x60, 0xCB, 0xA0, 0x72, 0xC8, 0x2B, 0xF0, 0xEB, 0xBF, + 0x71, 0x50, 0xF0, 0xAA, 0x03, 0x8A, 0xF3, 0xF8, 0x7E, 0xFF, 0x17, 0xBC, 0x53, 0x8C, 0xBE, 0x82, + 0xB8, 0xFD, 0xCA, 0x12, 0x34, 0x4B, 0xB8, 0x45, 0xF2, 0xFA, 0xE4, 0x71, 0x0A, 0x9E, 0xD1, 0x9E, + 0x55, 0x45, 0x60, 0xE9, 0x64, 0x60, 0x75, 0xF5, 0x28, 0x75, 0xEB, 0x92, 0xBA, 0x83, 0x51, 0x28, + 0x5E, 0x8B, 0xC0, 0x04, 0xF2, 0x49, 0x0E, 0xE1, 0xBF, 0x4E, 0x69, 0x70, 0xCF, 0x9F, 0x47, 0xF0, + 0x03, 0x70, 0x0D, 0x17, 0x5B, 0x1D, 0xF9, 0x74, 0xB9, 0x4D, 0x3A, 0xCA, 0x51, 0x5A, 0xAB, 0x20, + 0x31, 0xB5, 0x44, 0x41, 0xEC, 0x73, 0xC2, 0xF7, 0xE5, 0x65, 0xD9, 0x7B, 0x91, 0x18, 0x5E, 0xDE, + 0x95, 0x01, 0xBE, 0x7C, 0xFF, 0xDA, 0x11, 0x59, 0xA6, 0xD9, 0x55, 0x03, 0xB5, 0x84, 0xFB, 0x95, + 0xAC, 0x30, 0xEE, 0xB1, 0x17, 0x99, 0x45, 0x49, 0xDB, 0xB0, 0x26, 0x59, 0x5D, 0x3D, 0xA7, 0x63, + 0xFF, 0x96, 0xB2, 0x68, 0x49, 0xDC, 0x92, 0xC4, 0xA0, 0x4A, 0xF6, 0x07, 0x2F, 0xAF, 0x2B, 0x94, + 0xF4, 0x98, 0xE0, 0x95, 0xE7, 0x47, 0x8B, 0x1D, 0x3D, 0x54, 0x73, 0x29, 0x96, 0x57, 0x20, 0xE7, + 0x06, 0x78, 0x5A, 0x61, 0xC5, 0x0B, 0x8E, 0xAC, 0xB8, 0x4C, 0x7C, 0xC8, 0xD1, 0xC8, 0x95, 0xF8, + 0x50, 0x82, 0x9B, 0x81, 0x08, 0xA6, 0x99, 0x5E, 0x68, 0x2F, 0xC0, 0x4F, 0x09, 0x15, 0xF0, 0x51, + 0x8F, 0x7E, 0x12, 0xAD, 0x5C, 0x8B, 0x87, 0x24, 0x08, 0xDA, 0xC4, 0x47, 0x5C, 0x58, 0x9D, 0x97, + 0xC2, 0x3D, 0xFB, 0x32, 0x96, 0x0C, 0x07, 0x1D, 0x2C, 0x14, 0xD0, 0x8C, 0x94, 0x33, 0xC5, 0xF9, + 0x2D, 0xD8, 0x9F, 0x37, 0xF3, 0xAE, 0x2D, 0x71, 0x3C, 0xF0, 0x24, 0x87, 0x7C, 0x95, 0x94, 0xF2, + 0x94, 0x79, 0x9A, 0x06, 0x0D, 0xC8, 0xA2, 0x52, 0xFE, 0x22, 0x0E, 0xF6, 0x95, 0x1E, 0xC5, 0x00, + 0x61, 0xA4, 0xCF, 0x66, 0x2C, 0xC6, 0x85, 0x6D, 0xD2, 0xB3, 0x2C, 0x6B, 0x29, 0x6B, 0xED, 0x58, + 0x64, 0x07, 0x58, 0xB9, 0x36, 0x61, 0x0B, 0x3B, 0x3C, 0x9A, 0x52, 0xAC, 0x1F, 0xB6, 0x91, 0x47, + 0x7F, 0x68, 0xCB, 0x25, 0x0C, 0xAF, 0x67, 0x05, 0xAF, 0x08, 0x8A, 0x20, 0x81, 0x46, 0x12, 0x09, + 0x85, 0xC1, 0x88, 0xDA, 0x41, 0x4C, 0xA2, 0x1A, 0xDE, 0x85, 0x2C, 0x8F, 0xFD, 0xE9, 0x60, 0x00, + 0xAB, 0x3B, 0xC6, 0xA5, 0x94, 0xA9, 0x3F, 0xC1, 0x23, 0xCA, 0x4D, 0x1C, 0x2E, 0xF0, 0x64, 0xFD, + 0x59, 0xA6, 0x52, 0x9C, 0x55, 0xD1, 0x19, 0x18, 0x83, 0x55, 0x64, 0xCC, 0x94, 0x90, 0x5F, 0xBC, + 0x9C, 0x4B, 0xDE, 0x2C, 0xBA, 0x16, 0x2B, 0x66, 0xD3, 0x4A, 0x30, 0xBB, 0x12, 0x8F, 0x77, 0x1C, + 0xF0, 0x60, 0x13, 0xE7, 0xDF, 0x4E, 0xC0, 0x8C, 0xDF, 0xA2, 0x08, 0xC3, 0x49, 0x38, 0xDB, 0x29, + 0x86, 0xC2, 0xDB, 0xB5, 0x4A, 0xE4, 0x8E, 0xF1, 0x8C, 0x80, 0x2F, 0xE8, 0xFF, 0xAE, 0xAC, 0xBE, + 0xB5, 0xFD, 0x82, 0xDA, 0x1C, 0x66, 0xC8, 0x95, 0xF1, 0x67, 0x68, 0x52, 0x31, 0x87, 0x86, 0x1B, + 0x31, 0xB9, 0x3D, 0x2D, 0xFA, 0x28, 0xD5, 0x71, 0x49, 0x7B, 0xE4, 0xFE, 0x6B, 0x09, 0x45, 0x16, + 0x4F, 0x3B, 0x24, 0x97, 0xDF, 0x74, 0xA5, 0x91, 0xFA, 0x5B, 0x73, 0x11, 0x0C, 0x9A, 0xC2, 0x9E, + 0x41, 0x42, 0xBC, 0xEC, 0xE6, 0x0D, 0xDF, 0xD6, 0x94, 0xF0, 0xA1, 0x8D, 0x97, 0xE3, 0x20, 0x3E, + 0xBD, 0xFD, 0x4D, 0x52, 0x46, 0x56, 0x2C, 0xE6, 0x04, 0x56, 0xCC, 0xE8, 0x5A, 0x30, 0x8C, 0x37, + 0x36, 0x80, 0xDF, 0x13, 0x70, 0xF2, 0x30, 0xF5, 0xC8, 0x15, 0x8D, 0xEE, 0xF0, 0xEC, 0xD8, 0x62, + 0x7B, 0x3F, 0x50, 0xD6, 0x6A, 0xA3, 0x1D, 0x1B, 0x8D, 0xEC, 0x49, 0x48, 0x31, 0x8B, 0x23, 0x4F, + 0xC3, 0xC2, 0x76, 0x3B, 0x54, 0xF5, 0x35, 0xD1, 0xC7, 0x75, 0xED, 0x63, 0xF2, 0x80, 0xF8, 0xCB, + 0xF9, 0xC0, 0x2C, 0x70, 0x55, 0xB8, 0xD8, 0xCC, 0x67, 0x62, 0x73, 0x16, 0x39, 0x20, 0xFD, 0xAA, + 0x92, 0x68, 0xC6, 0x83, 0x51, 0x0E, 0xA2, 0x62, 0x9F, 0xCF, 0x23, 0x60, 0xB8, 0x07, 0xFC, 0x6A, + 0xFC, 0x00, 0xD6, 0x21, 0xB2, 0x49, 0x16, 0x05, 0xA6, 0x21, 0x88, 0x2A, 0x1D, 0x0F, 0x24, 0xA8, + 0xC9, 0x21, 0x4D, 0x43, 0x15, 0xA6, 0x9F, 0x15, 0x56, 0xBA, 0x82, 0x1E, 0x61, 0x4D, 0x90, 0xE9, + 0xA4, 0x08, 0x80, 0x0F, 0xED, 0x2C, 0x01, 0xB9, 0xAD, 0xE0, 0x0C, 0xBA, 0xE8, 0xD2, 0xBF, 0x73, + 0xE9, 0xC8, 0x09, 0x17, 0xD3, 0x97, 0x57, 0xF6, 0x85, 0x10, 0x84, 0x17, 0x3D, 0x48, 0xF3, 0xC4, + 0xE8, 0xE2, 0x49, 0x04, 0x2B, 0xF6, 0xF3, 0x44, 0xBA, 0x21, 0x90, 0x78, 0xBC, 0x29, 0x88, 0xD4, + 0x63, 0xF7, 0x2D, 0x17, 0x3A, 0xED, 0x16, 0x04, 0xC5, 0x1B, 0xF9, 0x75, 0xE1, 0x50, 0xA5, 0x04, + 0x28, 0xFC, 0x5A, 0x0D, 0xFA, 0x6D, 0x9A, 0xF9, 0x0C, 0x40, 0x59, 0x1E, 0xB4, 0xFA, 0x54, 0x99, + 0x12, 0x09, 0xF0, 0xCA, 0x94, 0xCF, 0xCE, 0x24, 0x41, 0xC9, 0xBB, 0x32, 0xD5, 0xA0, 0xA5, 0x04, + 0x69, 0x0C, 0x01, 0xFE, 0x59, 0x09, 0xF2, 0x57, 0xF7, 0x9D, 0x9B, 0x02, 0xDE, 0xB9, 0xD7, 0x6E, + 0x35, 0xB8, 0x8B, 0xFD, 0xB3, 0x4F, 0x07, 0x12, 0xCF, 0xB0, 0xD2, 0xFC, 0xE4, 0x4C, 0xAA, 0xC1, + 0xB2, 0xDB, 0xCF, 0x29, 0x28, 0xF3, 0xE7, 0xAB, 0x41, 0x66, 0x97, 0x9A, 0xF7, 0x29, 0x1E, 0xC9, + 0xD7, 0xAB, 0x86, 0xAD, 0x7F, 0x1F, 0x46, 0x74, 0x9C, 0x22, 0x08, 0xF9, 0xDF, 0x95, 0x60, 0x0F, + 0xD5, 0xEC, 0x76, 0x00, 0x9D, 0xE4, 0xBB, 0xAB, 0x04, 0x7F, 0x7A, 0x21, 0x09, 0x0F, 0x53, 0xE0, + 0x55, 0x82, 0x7A, 0x27, 0x3D, 0x8F, 0x03, 0x70, 0xF2, 0x12, 0x29, 0x86, 0xE7, 0xCE, 0x82, 0x3E, + 0xBB, 0xF1, 0x51, 0x2C, 0x86, 0x24, 0xE1, 0x94, 0x33, 0x06, 0x94, 0xE7, 0xEA, 0x48, 0x6F, 0xBE, + 0x63, 0x6C, 0x41, 0x1B, 0x5F, 0x2D, 0x5B, 0xDF, 0x96, 0x8C, 0x29, 0xCB, 0x45, 0xBB, 0xBE, 0x0D, + 0x90, 0x76, 0x60, 0x0F, 0xF0, 0xFC, 0x4C, 0x36, 0xA7, 0xEA, 0xA8, 0x5F, 0x4A, 0x48, 0xB3, 0xC4, + 0xC5, 0x39, 0x74, 0xB9, 0xE1, 0x36, 0xEC, 0x9C, 0xB7, 0xF1, 0x7D, 0x29, 0xCB, 0xEA, 0xF6, 0xDA, + 0xEC, 0x81, 0xAC, 0xAC, 0x3D, 0xE7, 0xA5, 0xCC, 0xAA, 0x77, 0x2D, 0x06, 0x60, 0x32, 0x20, 0xB1, + 0x54, 0x91, 0xE4, 0xBE, 0x9C, 0xB9, 0x8D, 0xED, 0x52, 0xE4, 0xB2, 0xC3, 0xD3, 0xAD, 0xB5, 0xD8, + 0x74, 0xB2, 0x6D, 0xE5, 0x4E, 0x27, 0xDB, 0x56, 0x05, 0xB2, 0x19, 0xD4, 0xFB, 0xA7, 0x1F, 0x67, + 0xC2, 0x9C, 0xF8, 0xB0, 0x79, 0xDB, 0xCB, 0xC9, 0xD9, 0x58, 0xD6, 0xBB, 0x35, 0xF5, 0xB9, 0x97, + 0x02, 0xEF, 0xDB, 0x20, 0xA1, 0xE0, 0x83, 0x1F, 0x46, 0xA2, 0xF7, 0x37, 0x32, 0xBD, 0xBF, 0x91, + 0xD3, 0xFB, 0xD9, 0xD6, 0xE7, 0x48, 0x20, 0x43, 0x0E, 0x2D, 0x18, 0x27, 0xB7, 0x8D, 0xFF, 0x74, + 0x8A, 0xEC, 0x63, 0x3D, 0x4A, 0x86, 0x96, 0xB1, 0xD7, 0xB1, 0xD8, 0x9E, 0x37, 0x27, 0xB5, 0x66, + 0xE9, 0x74, 0xD6, 0xAC, 0xC6, 0x2D, 0xE3, 0xED, 0xF8, 0x14, 0xD2, 0x20, 0x5F, 0x9A, 0xD9, 0x02, + 0xAC, 0xCF, 0x8C, 0x60, 0xF4, 0xAD, 0x37, 0xF4, 0x3B, 0x03, 0x7F, 0x8C, 0x7F, 0xE1, 0x57, 0x32, + 0x46, 0xC6, 0x30, 0x6D, 0x2E, 0x18, 0x16, 0x17, 0x3C, 0xD6, 0xB1, 0xED, 0x8E, 0x30, 0x16, 0x31, + 0x00, 0x9F, 0xA8, 0x98, 0xB5, 0xF8, 0xBC, 0x8E, 0xF0, 0xF3, 0x32, 0x8C, 0xAC, 0xBD, 0x03, 0x5B, + 0x29, 0x8E, 0xFD, 0x30, 0x3A, 0x52, 0xE4, 0xDA, 0x0B, 0x09, 0xD8, 0x2C, 0xDA, 0x21, 0x9C, 0x9E, + 0x7D, 0x4F, 0xEE, 0x6C, 0x30, 0x19, 0x20, 0x07, 0xC7, 0x0D, 0x59, 0x38, 0xE8, 0xE9, 0xC5, 0xF9, + 0xD1, 0x19, 0x6E, 0xFB, 0xB0, 0x88, 0xC8, 0x91, 0xCF, 0xB9, 0x21, 0xF4, 0x3B, 0x78, 0x14, 0xB8, + 0x91, 0x16, 0xA7, 0x93, 0xEB, 0xC4, 0x14, 0xA5, 0x65, 0x0A, 0xFC, 0xC5, 0xF7, 0x81, 0x70, 0xA5, + 0xC9, 0x65, 0x54, 0x20, 0x19, 0x49, 0x00, 0xA2, 0x15, 0xD5, 0xE0, 0x85, 0xE2, 0xF4, 0xBA, 0x56, + 0xB7, 0x22, 0x9C, 0xA2, 0x05, 0xAD, 0xAB, 0x91, 0x13, 0x5C, 0xF6, 0x27, 0x76, 0xF0, 0xED, 0xDD, + 0xD4, 0xEB, 0xB6, 0x6A, 0xE3, 0x38, 0xFB, 0xB5, 0x1E, 0xBF, 0x71, 0x87, 0x47, 0x34, 0x8C, 0xFE, + 0x0F, 0xFE, 0xA8, 0xDF, 0x64, 0x44, 0x01, 0x64, 0x01, 0x89, 0x06, 0x37, 0x54, 0x47, 0xD6, 0x85, + 0xC8, 0x64, 0xF8, 0xFE, 0xFD, 0x5E, 0x4E, 0xA0, 0x09, 0xC0, 0x69, 0xDB, 0x7D, 0xE8, 0xDF, 0xC1, + 0x82, 0x23, 0x49, 0xDF, 0x9E, 0x6E, 0x74, 0xAE, 0xAE, 0x8E, 0xD9, 0xA2, 0x0F, 0x6B, 0xB8, 0x4E, + 0x48, 0xC2, 0xC8, 0x0E, 0x98, 0x0E, 0x30, 0xA5, 0xD2, 0xAE, 0x60, 0xBE, 0xF8, 0x41, 0xA9, 0x03, + 0x71, 0x69, 0x97, 0xB2, 0x52, 0xBC, 0xF1, 0xB8, 0xC0, 0xF3, 0xB2, 0xB8, 0xCE, 0xBF, 0xED, 0x6A, + 0xDC, 0x7F, 0x95, 0x17, 0xBD, 0xA6, 0xDD, 0x2C, 0x89, 0x44, 0xDE, 0x16, 0x96, 0x39, 0x12, 0x5D, + 0x02, 0xE4, 0x3B, 0x8D, 0x3B, 0xD9, 0x78, 0x4B, 0x7D, 0xED, 0x69, 0x8E, 0x23, 0x96, 0x93, 0x6C, + 0x55, 0xEF, 0x18, 0x16, 0x35, 0x3F, 0x5F, 0x69, 0x31, 0x94, 0xCF, 0x4A, 0x62, 0x6C, 0x8D, 0x58, + 0x24, 0x35, 0x93, 0xCE, 0xE3, 0xE2, 0xD2, 0xA0, 0xF5, 0xF5, 0xB2, 0xD5, 0x4B, 0xEC, 0x57, 0x96, + 0xA6, 0x7E, 0xD5, 0xB3, 0x54, 0x94, 0xE3, 0x46, 0x72, 0x1C, 0xD7, 0x12, 0x22, 0x5B, 0xEA, 0x97, + 0x29, 0xDE, 0x8C, 0xAD, 0x4D, 0x6F, 0x7D, 0xFC, 0x8F, 0x6A, 0x72, 0xB5, 0xF1, 0xF2, 0x54, 0x2D, + 0xAE, 0x3B, 0x56, 0xD4, 0x67, 0xB5, 0x78, 0x6E, 0xDC, 0xF8, 0xBE, 0x6B, 0xF9, 0x88, 0x29, 0x78, + 0x94, 0x6B, 0x06, 0xC9, 0x66, 0xAE, 0x29, 0xFF, 0x28, 0xE9, 0x2A, 0x3E, 0xAE, 0x04, 0x8B, 0xEB, + 0x18, 0x70, 0x37, 0xF1, 0x01, 0x0F, 0xF3, 0x32, 0xA6, 0xCB, 0x37, 0xA6, 0xB0, 0xBC, 0x70, 0x7F, + 0x6C, 0xAE, 0x0A, 0xA9, 0x5F, 0xD6, 0xFE, 0xA7, 0x94, 0x5A, 0xBC, 0xA3, 0x97, 0xA3, 0xD4, 0x2C, + 0x07, 0xB3, 0xB4, 0x2C, 0x8D, 0x57, 0x54, 0x86, 0x80, 0xA9, 0x8A, 0x0B, 0x2A, 0xB1, 0xC0, 0xF1, + 0xAF, 0x42, 0x14, 0x2E, 0x4B, 0x32, 0x4E, 0x07, 0xBE, 0xE7, 0xA0, 0xCB, 0xBE, 0x69, 0xB1, 0xE6, + 0x18, 0x1A, 0xB3, 0x69, 0x89, 0x17, 0x5E, 0xE4, 0x86, 0xBC, 0x35, 0xE6, 0xE1, 0x2F, 0x26, 0x76, + 0xE6, 0x87, 0x2E, 0xFE, 0x7F, 0x6F, 0x30, 0x98, 0xC2, 0x32, 0xE6, 0x9E, 0x2F, 0x74, 0x36, 0x50, + 0x90, 0x19, 0xA2, 0xDD, 0x0E, 0xA3, 0xBA, 0xD1, 0x29, 0xA0, 0x9A, 0x92, 0x55, 0x7C, 0x52, 0x16, + 0x6D, 0x75, 0xC8, 0x52, 0x82, 0xB5, 0xC9, 0x4A, 0xB7, 0xB7, 0x65, 0xF5, 0xAC, 0xCD, 0xCE, 0xC6, + 0xE6, 0x96, 0xCC, 0xA8, 0x19, 0xE2, 0x33, 0x42, 0xAC, 0xBF, 0xEC, 0x6E, 0x6E, 0x59, 0xEB, 0x9D, + 0x75, 0x6B, 0xAD, 0x1C, 0xE2, 0x77, 0x80, 0x58, 0xB7, 0xB6, 0x36, 0x37, 0x37, 0x37, 0x3A, 0xEB, + 0x5B, 0xEB, 0xC5, 0x00, 0xC7, 0x76, 0xC4, 0x92, 0x93, 0x23, 0x48, 0xC7, 0xDA, 0xB6, 0x7A, 0xDB, + 0xEB, 0x2F, 0xB7, 0x4B, 0x40, 0x7C, 0x6F, 0x28, 0x60, 0x56, 0xBA, 0x16, 0xC8, 0x6A, 0x6B, 0xC3, + 0xDA, 0x78, 0xB9, 0xD9, 0x2D, 0x86, 0xDA, 0x1B, 0x45, 0x6E, 0x34, 0x75, 0xD8, 0x16, 0xC9, 0xC6, + 0x26, 0xD0, 0xDA, 0xDA, 0x56, 0x96, 0x5F, 0xDA, 0x81, 0x8D, 0x8A, 0x21, 0x47, 0x3D, 0x72, 0x29, + 0x16, 0xF7, 0x30, 0xF4, 0xA0, 0xDC, 0x55, 0xB1, 0x12, 0x17, 0x87, 0xD9, 0x15, 0xE8, 0x73, 0x43, + 0xD1, 0x36, 0x17, 0x6F, 0x2D, 0x11, 0x97, 0x58, 0x10, 0x4D, 0x37, 0x5F, 0x5A, 0xEC, 0x5F, 0x9B, + 0x24, 0xBF, 0x24, 0xE3, 0x20, 0x2E, 0xC3, 0x41, 0x20, 0x7E, 0x2D, 0x1F, 0x7E, 0x65, 0x44, 0x3F, + 0xFF, 0x08, 0xA2, 0xBF, 0x3F, 0x06, 0xD1, 0x87, 0xA2, 0x58, 0xE5, 0xFA, 0xE6, 0xA0, 0x99, 0x49, + 0xA8, 0x65, 0x16, 0xB2, 0xF2, 0x4A, 0x83, 0x96, 0xC0, 0xD8, 0xFF, 0x42, 0x03, 0x4C, 0x81, 0x0F, + 0xDF, 0x56, 0xD9, 0x1D, 0xA1, 0x34, 0x0B, 0x44, 0x25, 0x41, 0x4B, 0xDA, 0xB8, 0xD2, 0xED, 0x5A, + 0x6B, 0xEB, 0x6D, 0xB2, 0xB5, 0xA5, 0x6C, 0x8D, 0xF2, 0xCF, 0x28, 0x64, 0x2C, 0xA8, 0x60, 0x54, + 0x73, 0xC8, 0xE9, 0x77, 0x09, 0x90, 0x20, 0x3E, 0x7F, 0xB0, 0xA1, 0xD0, 0xDA, 0x60, 0x0F, 0x0A, + 0x6C, 0x34, 0xD6, 0x1E, 0x73, 0xF4, 0x21, 0xD0, 0xEA, 0xF1, 0x19, 0xB7, 0xA7, 0x4D, 0xBC, 0xFC, + 0x3B, 0x7F, 0xF5, 0xC0, 0xEA, 0x54, 0x56, 0xA0, 0x87, 0xDC, 0xBD, 0xCA, 0x24, 0xA8, 0xB6, 0xC9, + 0x5E, 0x25, 0x07, 0x4E, 0xF7, 0x90, 0x2E, 0xAD, 0xCA, 0x7B, 0xD5, 0x32, 0x3C, 0x63, 0xDA, 0xAA, + 0xB2, 0x5B, 0x29, 0x13, 0xC4, 0x4D, 0xA7, 0x98, 0x60, 0xF1, 0x7E, 0x65, 0x75, 0x5A, 0xB9, 0xAD, + 0xC3, 0xED, 0x1E, 0x46, 0xCC, 0xD2, 0x5A, 0x67, 0xCD, 0xD8, 0xBA, 0x42, 0x8A, 0x67, 0xBF, 0x3E, + 0x15, 0xCD, 0x74, 0x2F, 0xED, 0x51, 0xFA, 0xB0, 0x90, 0xE2, 0xD3, 0xB5, 0x52, 0xD2, 0xD4, 0x6E, + 0x73, 0x8A, 0xDD, 0x46, 0x9A, 0x2A, 0x08, 0xEA, 0x9A, 0x6A, 0x15, 0x6B, 0x6A, 0xB7, 0x99, 0xA6, + 0x3E, 0x46, 0xEB, 0xCA, 0x34, 0xF5, 0x89, 0x68, 0x4A, 0x9A, 0xFA, 0xE4, 0x14, 0x9F, 0xAE, 0x95, + 0x92, 0xA6, 0xF6, 0x9A, 0x53, 0xEC, 0x35, 0xD2, 0xD4, 0x5E, 0x23, 0x4D, 0xED, 0x35, 0xD3, 0xD4, + 0xC7, 0x68, 0x5D, 0x99, 0xA6, 0x3E, 0x11, 0x4D, 0x49, 0x53, 0x9F, 0x9C, 0xE2, 0xD3, 0xB5, 0x52, + 0xD2, 0xD4, 0xB5, 0xE6, 0x14, 0xD7, 0x1A, 0x69, 0xEA, 0x5A, 0x23, 0x4D, 0x5D, 0x6B, 0xA6, 0xA9, + 0x8F, 0xD1, 0xBA, 0x32, 0x4D, 0x7D, 0x22, 0x9A, 0x92, 0xA6, 0x3E, 0x39, 0xC5, 0x39, 0xB5, 0xF2, + 0xB9, 0x1F, 0xB7, 0x1A, 0x5D, 0xE5, 0x5A, 0x07, 0xAE, 0x46, 0xDF, 0xB7, 0xD2, 0x91, 0xAB, 0xD1, + 0x91, 0xAD, 0x7B, 0xF8, 0x99, 0xE3, 0x9B, 0xB6, 0xAA, 0x42, 0x6A, 0x1E, 0x26, 0x3F, 0xF3, 0x75, + 0xEE, 0xBC, 0xE8, 0xCE, 0xEB, 0xD5, 0xC7, 0x11, 0x53, 0xFF, 0xF5, 0x7C, 0xE3, 0xEE, 0xDC, 0x5F, + 0xFF, 0x50, 0x8F, 0xFF, 0xC4, 0x03, 0x6C, 0x35, 0x10, 0x3B, 0xF3, 0x00, 0xEA, 0xCB, 0xBC, 0x01, + 0x39, 0xC9, 0xB1, 0x6A, 0x22, 0xE6, 0x86, 0x70, 0x75, 0x29, 0x6A, 0xAE, 0x4A, 0x13, 0x91, 0xF6, + 0x9A, 0x89, 0xB4, 0xD7, 0x58, 0xA4, 0xBD, 0x86, 0x22, 0xED, 0x35, 0x16, 0x69, 0xAF, 0xA1, 0x48, + 0xD7, 0x1A, 0x8A, 0x74, 0xAD, 0x99, 0x48, 0xD7, 0x1A, 0x8B, 0x74, 0xAD, 0xA1, 0x48, 0xD7, 0x1A, + 0x8B, 0x54, 0x87, 0x4C, 0x0E, 0x14, 0xE4, 0x1B, 0xB5, 0xA6, 0x83, 0x85, 0xB2, 0x7B, 0xB7, 0x05, + 0x5B, 0x21, 0x71, 0x06, 0x00, 0x76, 0xC1, 0x5E, 0x42, 0x70, 0xC0, 0x5E, 0x34, 0x12, 0x81, 0x77, + 0x17, 0xFE, 0x37, 0xEA, 0xC5, 0xC9, 0x27, 0x76, 0x5E, 0x68, 0x39, 0x4F, 0xA6, 0x34, 0x49, 0xA1, + 0xAE, 0xBF, 0x2A, 0x61, 0x0C, 0x04, 0x2C, 0xA6, 0xD2, 0x26, 0x6B, 0x9B, 0xFC, 0xBF, 0x64, 0xEA, + 0x5C, 0xDB, 0xCC, 0x8B, 0x0B, 0x3C, 0x33, 0x85, 0x28, 0x15, 0xEE, 0x91, 0x97, 0x52, 0x6F, 0xB5, + 0xF4, 0xFB, 0xB4, 0xD3, 0xC8, 0xFF, 0x0B, 0xBD, 0x3F, 0xA7, 0x1E, 0xBD, 0xB3, 0x47, 0x39, 0x31, + 0x2F, 0x52, 0x57, 0x05, 0x05, 0x5D, 0xA4, 0x5F, 0x62, 0xAE, 0x77, 0xFC, 0x43, 0x65, 0x68, 0xBC, + 0xF2, 0xF3, 0x96, 0x9F, 0xB9, 0x70, 0x6C, 0x6C, 0x93, 0x63, 0xD3, 0xCA, 0x6C, 0xD3, 0x76, 0xF9, + 0x21, 0x50, 0x1B, 0xBF, 0x6A, 0x5B, 0xB4, 0x67, 0xE6, 0x27, 0x90, 0xCB, 0x48, 0x1F, 0xB3, 0xDE, + 0x9E, 0x13, 0xC1, 0x44, 0x72, 0x18, 0x34, 0x5C, 0x16, 0x44, 0x8A, 0xA1, 0xC4, 0xA7, 0xD0, 0x68, + 0x3F, 0xF8, 0x76, 0x69, 0xF5, 0xFB, 0x47, 0x07, 0x95, 0x1D, 0x2D, 0x43, 0x68, 0xB2, 0x21, 0x94, + 0xD2, 0x48, 0xE7, 0xCC, 0x0E, 0x43, 0xF8, 0xCD, 0x79, 0x02, 0x5A, 0xDD, 0x27, 0x6A, 0x53, 0xF7, + 0x09, 0xDB, 0xD4, 0x7B, 0xA2, 0x36, 0xF5, 0x9E, 0xB0, 0x4D, 0x6B, 0x4F, 0xD4, 0xA6, 0xB5, 0x39, + 0xB5, 0x49, 0x0C, 0xB1, 0x8B, 0xFD, 0xB3, 0xD5, 0x4F, 0x07, 0x67, 0xF9, 0xF6, 0xE9, 0x62, 0x50, + 0x3B, 0xD6, 0x57, 0x18, 0x88, 0xE4, 0xBA, 0x78, 0x1A, 0x73, 0xBB, 0xB9, 0xB1, 0xB1, 0x96, 0x89, + 0xF2, 0x65, 0x1F, 0x65, 0x46, 0x95, 0x98, 0xFF, 0x92, 0xF5, 0x56, 0x42, 0x44, 0x8A, 0x23, 0xAE, + 0x1E, 0x45, 0x6E, 0xA2, 0xF4, 0x60, 0x16, 0x42, 0xDD, 0x43, 0x84, 0x54, 0x08, 0x1C, 0x72, 0x1E, + 0x42, 0x30, 0xB1, 0xF6, 0xC9, 0x69, 0xCA, 0xDA, 0xD4, 0x99, 0x3B, 0x6B, 0xAB, 0xAB, 0x1F, 0x3D, + 0x12, 0x5F, 0x59, 0x68, 0x13, 0xA8, 0x48, 0x78, 0xEF, 0xB0, 0x08, 0x0A, 0x4E, 0x8D, 0x3D, 0x9A, + 0x8D, 0xCB, 0x4E, 0xC0, 0xCF, 0x9B, 0xE0, 0xE0, 0xBB, 0xDC, 0xB8, 0xFE, 0x0C, 0x31, 0x92, 0x23, + 0x82, 0x59, 0x2C, 0x8E, 0x9A, 0x98, 0x02, 0x12, 0xDF, 0x23, 0xA8, 0xB9, 0x6D, 0xAC, 0x71, 0x2F, + 0x5E, 0xDC, 0xEE, 0x74, 0xE2, 0x95, 0x29, 0x0F, 0xB6, 0x17, 0x99, 0xBF, 0x4E, 0xA6, 0x11, 0xFD, + 0x9E, 0x55, 0x5C, 0xBC, 0x34, 0xA1, 0x75, 0x23, 0x7C, 0x6A, 0xCC, 0x5C, 0x91, 0x28, 0xE2, 0x1B, + 0xEB, 0xEC, 0x16, 0x7B, 0xEE, 0x98, 0x12, 0xC9, 0x3C, 0xEA, 0x75, 0xD7, 0x08, 0x80, 0x92, 0x03, + 0x76, 0xF0, 0xE2, 0xDE, 0x05, 0xF4, 0xAF, 0x53, 0xEA, 0xB1, 0x83, 0xF9, 0x6D, 0x6B, 0x0D, 0x7E, + 0xF4, 0x5E, 0x4A, 0x5D, 0x07, 0x9F, 0xD8, 0x16, 0x51, 0xEF, 0xA5, 0xCC, 0xAF, 0x7C, 0x25, 0xA6, + 0x78, 0x7A, 0x47, 0x72, 0x20, 0x13, 0xD7, 0x1E, 0xB1, 0xF8, 0x1D, 0x9B, 0x79, 0x8E, 0xE2, 0x52, + 0xF1, 0x25, 0x0E, 0xA2, 0x6E, 0x26, 0xC8, 0xA4, 0x6B, 0x0A, 0x2E, 0x31, 0x50, 0x4C, 0x43, 0xBD, + 0xA4, 0xD4, 0xA2, 0xC5, 0x77, 0x36, 0x32, 0xF7, 0xAB, 0xC3, 0x63, 0xF7, 0x9A, 0x8A, 0xDE, 0xC0, + 0x23, 0xCB, 0x9E, 0xCC, 0x08, 0x3F, 0xB1, 0xEC, 0x29, 0x7C, 0xE4, 0x5F, 0xE9, 0x59, 0x92, 0x72, + 0x2E, 0x84, 0xD0, 0x11, 0x2C, 0xE5, 0x52, 0x31, 0x3B, 0x73, 0x3C, 0x38, 0x7D, 0xCA, 0x03, 0x53, + 0xD1, 0x4C, 0x7E, 0x1F, 0xA9, 0x48, 0x3D, 0xE3, 0x34, 0x2A, 0xF5, 0x34, 0x74, 0x6C, 0x7F, 0x07, + 0xD0, 0x0B, 0x37, 0xBE, 0xCE, 0xD3, 0xB5, 0x36, 0xA0, 0x13, 0x32, 0x7E, 0x60, 0xB7, 0x0D, 0xDF, + 0xDB, 0x3D, 0x55, 0x4D, 0x94, 0x3B, 0x52, 0xC5, 0x9A, 0xC9, 0xC9, 0xC8, 0x1E, 0xE7, 0xAC, 0x84, + 0x2A, 0x2C, 0x12, 0x94, 0xB6, 0x6D, 0x5A, 0xE4, 0xCF, 0xA4, 0x97, 0x1F, 0x20, 0xA4, 0x71, 0xA8, + 0x56, 0x37, 0x9E, 0x53, 0x2B, 0xC9, 0x6B, 0xEA, 0x49, 0x3D, 0x05, 0x8D, 0x03, 0xED, 0x12, 0x37, + 0x3C, 0xEB, 0x81, 0xCF, 0x43, 0x14, 0x66, 0x82, 0x56, 0x61, 0xF3, 0x4C, 0x29, 0x75, 0xEA, 0x35, + 0xD3, 0x96, 0x50, 0x30, 0x7B, 0x1F, 0x67, 0x8D, 0x4C, 0x0F, 0xC7, 0xCD, 0xA7, 0xE3, 0xDB, 0x73, + 0x68, 0x72, 0x01, 0xF1, 0xD2, 0x76, 0x67, 0x52, 0x97, 0x56, 0x6A, 0xAE, 0x9A, 0x29, 0x95, 0xBB, + 0x7A, 0xBD, 0xED, 0xF5, 0xED, 0xCD, 0x97, 0x19, 0x7F, 0xAF, 0x0D, 0xDF, 0xDB, 0x50, 0x30, 0x87, + 0x76, 0x66, 0xA8, 0xB2, 0x78, 0x16, 0x7C, 0xDD, 0x4A, 0xEC, 0x1C, 0x9B, 0x9A, 0x5A, 0x3F, 0x2B, + 0x67, 0x25, 0x09, 0x94, 0x24, 0x0B, 0xE5, 0xB7, 0xAF, 0xAD, 0xF5, 0x2D, 0x45, 0xCD, 0xC5, 0x0C, + 0xB4, 0xDE, 0xDE, 0x9A, 0x8B, 0xAA, 0x97, 0xF3, 0x50, 0x24, 0xA0, 0xD5, 0xD5, 0xD8, 0x15, 0x4A, + 0xE4, 0x95, 0x7B, 0x4B, 0xC5, 0x2C, 0x8A, 0xA3, 0xB3, 0x3D, 0x7E, 0x0F, 0x6B, 0x31, 0xB9, 0xF6, + 0x79, 0x74, 0xD6, 0x92, 0xDA, 0xEB, 0x79, 0x5E, 0x47, 0xFA, 0x4F, 0x6E, 0xB2, 0x76, 0x73, 0x34, + 0xC7, 0xA6, 0x1A, 0x28, 0x1C, 0x9C, 0xF6, 0x1F, 0x9B, 0xC4, 0x7B, 0xB0, 0x00, 0x77, 0xF6, 0xFD, + 0x63, 0x93, 0xE9, 0x4F, 0xAF, 0xE0, 0xE7, 0x5C, 0xA9, 0xC4, 0x9B, 0x1F, 0xA2, 0xF2, 0x69, 0x34, + 0x11, 0xDE, 0xB3, 0x95, 0xF5, 0x9E, 0x2D, 0xA3, 0xF7, 0x6C, 0xA6, 0x93, 0xA8, 0xCC, 0xE9, 0xC5, + 0x59, 0x53, 0x6D, 0x49, 0xCE, 0x11, 0x81, 0xA7, 0xD1, 0xE8, 0xF0, 0xFB, 0xC4, 0xF7, 0xB8, 0xFB, + 0x0B, 0xCE, 0x61, 0x57, 0xB6, 0x1B, 0xCC, 0x33, 0xEC, 0x2A, 0x06, 0x23, 0xBD, 0x27, 0x5C, 0x76, + 0x48, 0x39, 0x01, 0x6E, 0x06, 0x2E, 0x4B, 0xB2, 0x0E, 0x2E, 0x09, 0x5E, 0x6D, 0x54, 0x7C, 0x91, + 0x35, 0xD6, 0x6A, 0xAB, 0x21, 0xEE, 0x73, 0x30, 0x3F, 0x07, 0x74, 0xC4, 0x54, 0xC3, 0x6A, 0xB3, + 0x64, 0xB6, 0xDA, 0x56, 0x12, 0x43, 0xDF, 0x35, 0x6E, 0x25, 0xD5, 0xA5, 0xE3, 0x86, 0x13, 0x91, + 0x2D, 0xFE, 0x31, 0x88, 0xA5, 0x27, 0x82, 0x93, 0x73, 0x7A, 0x4D, 0x03, 0x70, 0xD5, 0xE9, 0x91, + 0x23, 0x96, 0xA8, 0x99, 0x15, 0x2A, 0x5B, 0xA0, 0x86, 0x85, 0x04, 0x1E, 0xE2, 0x9C, 0x22, 0x39, + 0x4F, 0x82, 0x6B, 0xD9, 0x45, 0x30, 0xEF, 0x9B, 0xA8, 0x22, 0x25, 0x1C, 0x53, 0xF3, 0x2E, 0x48, + 0xF7, 0x7B, 0xE5, 0xAB, 0xDC, 0xBB, 0xA4, 0xAB, 0x64, 0x49, 0x4A, 0xB2, 0x04, 0x2D, 0xE0, 0x8B, + 0x12, 0x6F, 0x23, 0x6F, 0x01, 0xF8, 0x3C, 0x03, 0x4B, 0x09, 0xA6, 0x93, 0x19, 0x4C, 0x96, 0x37, + 0x45, 0xC2, 0xB0, 0x0C, 0x1F, 0xD8, 0x9F, 0x2D, 0xDD, 0x47, 0x8A, 0xB3, 0xEE, 0x24, 0x98, 0xA4, + 0x0A, 0x8F, 0xFA, 0x84, 0xF9, 0x83, 0x7A, 0x69, 0x44, 0x62, 0xF6, 0xCD, 0xDC, 0x5A, 0x1B, 0x3E, + 0xCB, 0xE6, 0xFE, 0x5D, 0xD9, 0xBB, 0xAE, 0x92, 0x32, 0xF7, 0xD8, 0xB7, 0x31, 0x1F, 0x55, 0x87, + 0x88, 0x56, 0xDF, 0xD9, 0x6E, 0x04, 0x4B, 0xEE, 0x05, 0x39, 0x4C, 0xDF, 0xAC, 0x83, 0xE6, 0x7B, + 0x21, 0xF1, 0xA5, 0x90, 0x6C, 0x43, 0x5F, 0xC5, 0xCC, 0x27, 0x27, 0x09, 0x2F, 0xE4, 0x27, 0x6C, + 0x79, 0xB6, 0x3C, 0xDD, 0xCD, 0x56, 0x3B, 0x47, 0x2A, 0x96, 0x53, 0x45, 0xC9, 0x9D, 0xD7, 0xB7, + 0x6F, 0xB1, 0x39, 0x9D, 0x8E, 0x12, 0x14, 0xAB, 0xE5, 0xD5, 0x6A, 0xA5, 0xB9, 0x81, 0xDB, 0x45, + 0x82, 0x6F, 0x2B, 0x48, 0x86, 0x34, 0x2F, 0x13, 0x49, 0x26, 0x27, 0x8A, 0x9C, 0x9C, 0x65, 0x96, + 0x9C, 0x24, 0xB3, 0xE7, 0x25, 0x99, 0x25, 0x37, 0xC9, 0x7C, 0xF2, 0x93, 0xCC, 0x9E, 0xA3, 0x64, + 0xB6, 0x3C, 0x25, 0xB3, 0xE4, 0x2A, 0x99, 0x35, 0x5F, 0xC9, 0x6C, 0x39, 0x4B, 0xE6, 0x9F, 0xB7, + 0xA4, 0x10, 0x63, 0xBA, 0x25, 0x92, 0x22, 0x72, 0xD3, 0x6F, 0x95, 0xF1, 0x94, 0xE4, 0x40, 0x29, + 0x47, 0x50, 0x31, 0x11, 0x4A, 0xF3, 0x64, 0x28, 0xB3, 0x26, 0x44, 0xC9, 0x66, 0x21, 0x45, 0x0B, + 0xC4, 0xE9, 0xFD, 0x03, 0x4C, 0xC0, 0xCF, 0x6B, 0x7E, 0x34, 0x4E, 0x5F, 0x8F, 0x35, 0x23, 0x08, + 0xFF, 0x3B, 0x93, 0x14, 0x4C, 0xCF, 0xE1, 0x22, 0x65, 0xF4, 0x5B, 0xE4, 0x76, 0x5F, 0x2A, 0xBF, + 0x7C, 0x7F, 0xD6, 0x57, 0xD7, 0xB8, 0x3C, 0x0D, 0x60, 0xC2, 0xCA, 0x9F, 0xFE, 0x44, 0x4C, 0x50, + 0xA0, 0x10, 0x23, 0x96, 0x3B, 0xBC, 0x2E, 0xE4, 0x5B, 0xEA, 0x1E, 0xF8, 0xD3, 0x26, 0x24, 0x8F, + 0x3F, 0x9E, 0xEE, 0xF5, 0x8D, 0xCC, 0x2E, 0x69, 0xCE, 0x82, 0x29, 0xF5, 0x47, 0xD9, 0xB4, 0x26, + 0xE9, 0x07, 0x9B, 0xBA, 0x14, 0x21, 0xCA, 0xAA, 0x72, 0xE3, 0x63, 0xDC, 0x19, 0xAC, 0x51, 0x88, + 0xC2, 0x9F, 0xAC, 0x23, 0xA9, 0x12, 0x2D, 0x2F, 0xEB, 0x8A, 0x61, 0x52, 0x81, 0x56, 0x96, 0xA2, + 0x31, 0xDD, 0xDB, 0x5B, 0x37, 0x3A, 0xB1, 0x27, 0x69, 0x22, 0xB7, 0xB1, 0xEB, 0xC1, 0x0F, 0xFB, + 0x7B, 0x9B, 0x5C, 0xB1, 0x12, 0x29, 0x17, 0x66, 0x3B, 0x31, 0x0A, 0x47, 0x07, 0xD2, 0x28, 0x8E, + 0x23, 0x24, 0x92, 0x27, 0x13, 0x38, 0x7B, 0x63, 0x3B, 0xFC, 0xC6, 0x0B, 0x38, 0x22, 0xA5, 0x90, + 0x29, 0x0E, 0x87, 0x7D, 0x8D, 0x24, 0x79, 0xE6, 0x09, 0xFE, 0xE1, 0x0D, 0x92, 0xE7, 0x1F, 0x16, + 0x19, 0x12, 0xE8, 0xBA, 0x2E, 0x79, 0xFD, 0x9A, 0xD3, 0x82, 0x8E, 0x81, 0x3E, 0xB2, 0xF4, 0xFE, + 0x29, 0x48, 0xA2, 0x69, 0x4E, 0xCC, 0x29, 0xC1, 0x4A, 0xAD, 0x2A, 0xEB, 0xD1, 0xA2, 0x5E, 0xC8, + 0x6C, 0x9D, 0xC4, 0xA9, 0x3E, 0x25, 0x83, 0x18, 0xDF, 0xE9, 0x86, 0xF6, 0x1B, 0xEE, 0x44, 0x85, + 0x04, 0x2C, 0x28, 0x71, 0x60, 0x4D, 0x39, 0x01, 0x7B, 0xCE, 0xF6, 0x50, 0xD4, 0xCE, 0x4A, 0xEE, + 0x56, 0x49, 0x59, 0x93, 0x5D, 0x8C, 0xB5, 0x50, 0x6F, 0x0B, 0xEE, 0xA4, 0x69, 0x92, 0x93, 0xA6, + 0x91, 0x5D, 0xE3, 0x56, 0x78, 0xFA, 0x22, 0x84, 0x43, 0x23, 0x30, 0xF5, 0xD4, 0x79, 0x07, 0xAB, + 0x6C, 0x81, 0x27, 0x7D, 0x02, 0x23, 0xC9, 0xC6, 0x7C, 0x1B, 0x3F, 0xB3, 0x81, 0xD7, 0x1A, 0xF9, + 0x4B, 0x52, 0xAE, 0x03, 0xD3, 0x9F, 0x7B, 0x7D, 0x9F, 0xBC, 0x57, 0xB5, 0x28, 0x2B, 0xC3, 0x52, + 0xD2, 0xDF, 0x2A, 0xD8, 0x2E, 0x51, 0xAF, 0x48, 0x86, 0x9D, 0xFD, 0x8F, 0x1F, 0xCF, 0x0F, 0x8E, + 0x4E, 0xF7, 0x2E, 0x0E, 0x2F, 0x8F, 0x4E, 0xCF, 0x3E, 0x5D, 0x5C, 0x5E, 0x7C, 0x3E, 0xC3, 0x5F, + 0x7F, 0xD9, 0x3B, 0x3E, 0x3A, 0xB8, 0xFC, 0x74, 0xFA, 0x97, 0xD3, 0x8F, 0xBF, 0x9E, 0xEA, 0xF7, + 0xD7, 0x93, 0x1E, 0x45, 0x26, 0x53, 0x8C, 0x78, 0x99, 0x1A, 0x5A, 0x41, 0xA6, 0xDE, 0x37, 0x0F, + 0xF3, 0x3C, 0xEF, 0x3C, 0x37, 0x5D, 0x61, 0x03, 0x60, 0xC0, 0x1F, 0xCA, 0xA1, 0x8E, 0xC4, 0xF8, + 0x6B, 0xB2, 0xD2, 0xDD, 0xB2, 0xB8, 0xFA, 0x9B, 0xCA, 0x61, 0x0A, 0xDA, 0xB2, 0x96, 0x0A, 0xC5, + 0x90, 0x1E, 0xBB, 0x6C, 0xF1, 0x55, 0xFB, 0x96, 0xF5, 0xEC, 0x04, 0x90, 0x3B, 0x54, 0xB8, 0xBA, + 0x48, 0x3A, 0x1D, 0x5F, 0x65, 0xDD, 0x31, 0xE8, 0x1F, 0x7F, 0x76, 0xAC, 0xBE, 0x02, 0x32, 0xB8, + 0x9F, 0x1A, 0xF8, 0x53, 0x03, 0xF3, 0x35, 0x30, 0xA3, 0x2F, 0x7F, 0xD8, 0x55, 0x0C, 0x5F, 0x61, + 0xFB, 0xB9, 0x0D, 0x0D, 0x79, 0x3E, 0x31, 0x96, 0x2A, 0xE8, 0x99, 0x34, 0xBF, 0xD0, 0xD8, 0xCB, + 0x7C, 0x4C, 0x02, 0x58, 0x6C, 0xE2, 0x0C, 0x94, 0x0E, 0xAA, 0x66, 0xA3, 0x25, 0x57, 0xEC, 0x4D, + 0xD9, 0x50, 0x3A, 0x41, 0x3C, 0x3B, 0x80, 0x13, 0x9A, 0x83, 0xE1, 0x11, 0x18, 0x9D, 0x60, 0x78, + 0x41, 0xB1, 0x1D, 0x8F, 0x46, 0x2C, 0x07, 0x6F, 0x68, 0x75, 0x84, 0x3D, 0x1A, 0x61, 0x6F, 0xF1, + 0xBC, 0x43, 0xC9, 0x34, 0xAB, 0x3D, 0xBC, 0x90, 0xA6, 0x9A, 0x55, 0x67, 0xD8, 0x74, 0x66, 0x14, + 0x23, 0x84, 0x91, 0x5A, 0x8C, 0xEB, 0xB4, 0x4D, 0x4C, 0xA4, 0x89, 0x62, 0x35, 0xCB, 0x56, 0x88, + 0x0C, 0x2A, 0x15, 0x61, 0xCB, 0x5E, 0xB9, 0xE6, 0x87, 0x8A, 0xA1, 0xB8, 0x04, 0xC1, 0xE5, 0x2B, + 0x9A, 0x9F, 0xF5, 0xFE, 0x32, 0x79, 0x7C, 0x53, 0xF7, 0xAF, 0xA1, 0xDB, 0x57, 0xD1, 0xB3, 0x13, + 0x08, 0xD0, 0xB3, 0xF8, 0x41, 0xAE, 0x1C, 0x7F, 0xD6, 0x36, 0x75, 0x8F, 0x76, 0x73, 0x93, 0xC0, + 0x18, 0x9E, 0x9E, 0x6B, 0xB2, 0x1A, 0x78, 0xA8, 0x4D, 0x9A, 0x67, 0x52, 0x29, 0x20, 0x2F, 0xC7, + 0x34, 0x54, 0x27, 0xDF, 0xC8, 0x2A, 0xE6, 0xA9, 0x8E, 0xD8, 0xDB, 0x9F, 0xB3, 0xEE, 0xA4, 0x2F, + 0x0B, 0xAB, 0x2A, 0x94, 0xC6, 0x52, 0xA3, 0x26, 0xCD, 0x4B, 0x71, 0x0C, 0xFD, 0x61, 0xBA, 0x78, + 0x3C, 0xA7, 0x8E, 0x50, 0xD2, 0x06, 0xCA, 0x24, 0x66, 0x00, 0xB5, 0x6A, 0xF5, 0x7F, 0x3C, 0xFD, + 0x97, 0xB5, 0xB9, 0xFB, 0xAC, 0xDB, 0xDC, 0x7D, 0x94, 0x36, 0xF7, 0x9E, 0x75, 0x9B, 0x7B, 0x8F, + 0xD2, 0xE6, 0xB5, 0x67, 0xDD, 0xE6, 0xB5, 0xBA, 0x6D, 0xD6, 0x51, 0x3E, 0xB6, 0xC3, 0x98, 0x67, + 0x1A, 0xD3, 0x63, 0x78, 0xE5, 0x49, 0x91, 0x7A, 0x36, 0x11, 0x7D, 0x4B, 0x87, 0xBF, 0xF4, 0xCE, + 0x2D, 0xA0, 0x78, 0xE0, 0xBD, 0x13, 0xB3, 0xCD, 0x8C, 0x26, 0xD6, 0x88, 0x6D, 0x23, 0x38, 0xAA, + 0xEB, 0xE9, 0xC6, 0x17, 0xDB, 0x46, 0xC1, 0xE2, 0x2F, 0xD6, 0x57, 0x31, 0xDF, 0xB2, 0x6F, 0x6E, + 0x78, 0x6A, 0x9F, 0x2E, 0xF2, 0xB3, 0x9C, 0xB8, 0x7C, 0x69, 0x89, 0x97, 0xC5, 0xD5, 0x5F, 0x13, + 0x4B, 0xFD, 0xF0, 0x06, 0x9F, 0x34, 0x58, 0x32, 0x21, 0xEF, 0x96, 0x20, 0xEF, 0xAA, 0xC8, 0xBB, + 0x3A, 0xF2, 0x6E, 0x11, 0xF2, 0x5E, 0x09, 0xF2, 0x9E, 0x8A, 0xBC, 0xA7, 0x23, 0xEF, 0x15, 0x21, + 0x5F, 0x2B, 0x41, 0xBE, 0xA6, 0x22, 0x5F, 0xD3, 0x91, 0xAF, 0x25, 0xC8, 0x9F, 0xDF, 0x96, 0x54, + 0x6D, 0x95, 0x95, 0x32, 0x2A, 0xDF, 0xF8, 0x21, 0xA8, 0xEA, 0x14, 0x7E, 0x85, 0x9F, 0xC1, 0xA8, + 0x44, 0x81, 0x45, 0x04, 0x14, 0x02, 0x09, 0xF5, 0xED, 0x44, 0xFE, 0xB1, 0x7F, 0xC7, 0xAE, 0x8D, + 0xD1, 0xC5, 0xA5, 0xF4, 0x71, 0x5F, 0xC0, 0xB5, 0x94, 0x73, 0xC7, 0x0A, 0x89, 0x19, 0xEF, 0x51, + 0xE9, 0x4E, 0x41, 0xD7, 0xE8, 0x12, 0xAC, 0x6F, 0x9B, 0x9E, 0x09, 0x46, 0xA4, 0x0D, 0x3B, 0xA2, + 0x7E, 0x67, 0xE4, 0xAF, 0xBA, 0x0A, 0x4C, 0x94, 0xD4, 0x39, 0x4C, 0x02, 0x55, 0x7A, 0x51, 0x54, + 0xCC, 0x6E, 0xD4, 0x2B, 0xF1, 0xDF, 0xAE, 0xD3, 0x6D, 0x13, 0xD7, 0xE9, 0x55, 0xE8, 0x3C, 0xBE, + 0x67, 0xD2, 0x35, 0x84, 0xA6, 0x89, 0xAD, 0x73, 0x40, 0x93, 0x2D, 0xCC, 0xA8, 0x7C, 0xB7, 0xB9, + 0xCE, 0x03, 0x81, 0x67, 0xBB, 0x87, 0xDB, 0x35, 0x9F, 0xB3, 0xA0, 0x4C, 0x4C, 0xC7, 0x5D, 0x4A, + 0xE8, 0x1C, 0x1A, 0x7F, 0xBE, 0x13, 0xA5, 0x3E, 0x93, 0x23, 0x3D, 0x2F, 0x1C, 0xEB, 0x7B, 0xD1, + 0x30, 0x65, 0x2F, 0xF6, 0x5E, 0xF8, 0xEF, 0x6C, 0x0C, 0x23, 0xB8, 0x3F, 0x10, 0xD7, 0xDB, 0xD5, + 0x25, 0xAA, 0x5A, 0x96, 0x7D, 0xD7, 0xB7, 0x15, 0x17, 0x91, 0xBD, 0x09, 0x4C, 0x23, 0xD4, 0x51, + 0xE2, 0x1A, 0x58, 0x06, 0x4A, 0x87, 0x5D, 0xFB, 0xE3, 0xD4, 0xF0, 0x50, 0xC8, 0xF8, 0xF0, 0x96, + 0x46, 0x89, 0xC5, 0x75, 0xB6, 0xBB, 0xED, 0x96, 0x99, 0x65, 0xC3, 0x51, 0x6C, 0x86, 0xFD, 0x4A, + 0x0F, 0x98, 0xA5, 0x2F, 0x89, 0xE5, 0xE5, 0xC3, 0x2C, 0x79, 0x7C, 0x6C, 0x97, 0x7C, 0x57, 0x62, + 0xCC, 0x4A, 0x5E, 0x53, 0x94, 0xDB, 0xF2, 0x37, 0x1A, 0xF8, 0x71, 0x56, 0x64, 0xE9, 0x95, 0x16, + 0x29, 0x0F, 0x34, 0xDB, 0xC6, 0x2F, 0x4D, 0xD3, 0x4D, 0x16, 0xF1, 0x4E, 0x85, 0x21, 0x9F, 0xF3, + 0xD2, 0x8B, 0x47, 0xC8, 0xA6, 0xDD, 0x30, 0x2F, 0x74, 0xAD, 0x9C, 0xD0, 0x43, 0x35, 0x9B, 0xAD, + 0xFE, 0x72, 0xFD, 0x83, 0x22, 0x29, 0x3D, 0xF5, 0xF2, 0x8B, 0xB9, 0xE7, 0x70, 0x6E, 0x92, 0x46, + 0xB5, 0x7A, 0x0A, 0xD5, 0xDC, 0xC6, 0x76, 0xAC, 0xB2, 0xF6, 0xA6, 0xC9, 0x97, 0xF9, 0xF9, 0xD8, + 0x5C, 0xD3, 0x38, 0x3F, 0xAF, 0x56, 0xF3, 0x27, 0x8B, 0xB0, 0x19, 0x86, 0x01, 0x21, 0x30, 0xF5, + 0xA3, 0x80, 0xDA, 0xE3, 0x54, 0x09, 0xAA, 0xC9, 0x83, 0x63, 0x95, 0x05, 0x22, 0xE1, 0xF9, 0xD1, + 0xD2, 0x28, 0x50, 0x80, 0x4C, 0xC2, 0xE4, 0x99, 0x94, 0x20, 0x8B, 0xED, 0x07, 0x37, 0xBD, 0xDB, + 0x29, 0x6A, 0xFC, 0x21, 0xBF, 0x3E, 0x36, 0x9F, 0xB6, 0x67, 0x90, 0xFD, 0xA0, 0xA6, 0xA7, 0x17, + 0xDD, 0xC5, 0x9B, 0xF5, 0x59, 0x37, 0x00, 0xE7, 0x0C, 0xB4, 0xED, 0xC5, 0xF3, 0x46, 0x95, 0xF7, + 0x03, 0x4C, 0xB3, 0xC6, 0x3C, 0x67, 0x0C, 0x35, 0x43, 0xFA, 0x73, 0x9E, 0x35, 0x92, 0x7C, 0xEE, + 0xF3, 0x98, 0x39, 0xB2, 0xC9, 0xE1, 0x9F, 0xE5, 0xEC, 0xA1, 0xA7, 0x0D, 0x9F, 0x9B, 0xED, 0x78, + 0x0E, 0x6D, 0xAF, 0x6C, 0x3A, 0x66, 0x6E, 0xB9, 0x8E, 0xEB, 0xF9, 0x1A, 0x0E, 0xE1, 0x38, 0xF3, + 0x54, 0xE8, 0x60, 0x17, 0x32, 0xEE, 0xB2, 0xEA, 0x8D, 0xEE, 0xFC, 0xA8, 0xB7, 0x5F, 0xD8, 0x83, + 0xEC, 0xAA, 0x51, 0x62, 0x13, 0x31, 0x7F, 0xFE, 0x26, 0xE9, 0xE1, 0x9D, 0x72, 0x80, 0x7E, 0x6D, + 0x80, 0x8B, 0xBA, 0x00, 0xBF, 0x48, 0x00, 0xEB, 0xE5, 0x00, 0xE7, 0x27, 0xFB, 0x59, 0x0A, 0x0F, + 0x0D, 0x5E, 0x28, 0x19, 0xB2, 0x87, 0xD6, 0x54, 0x6F, 0xF5, 0xFD, 0x99, 0x2A, 0x22, 0xAB, 0xB3, + 0xB1, 0x53, 0x06, 0xD0, 0xAF, 0x0D, 0x70, 0x51, 0x17, 0x40, 0x16, 0x51, 0x32, 0x2E, 0xF3, 0x01, + 0x54, 0x11, 0x25, 0x14, 0x1E, 0x66, 0x79, 0x94, 0x82, 0x5D, 0xA3, 0x63, 0x2E, 0x5D, 0x6C, 0xA8, + 0x18, 0x31, 0x4B, 0x22, 0xB4, 0x89, 0xC7, 0x9C, 0xE3, 0x90, 0x0E, 0x36, 0x2C, 0xAB, 0x0C, 0xAE, + 0x2B, 0xC1, 0xBD, 0x44, 0x38, 0x00, 0xEB, 0x9A, 0x9A, 0x25, 0xB9, 0x91, 0x85, 0xDA, 0x6B, 0xA8, + 0xDE, 0xAF, 0x59, 0xFD, 0xA2, 0x5E, 0x75, 0xB9, 0x53, 0x7A, 0x65, 0xD5, 0x33, 0x5A, 0x6B, 0xAA, + 0x9F, 0x75, 0x1F, 0xF1, 0xB7, 0xAE, 0xB5, 0xB6, 0x26, 0xC3, 0x5A, 0xA9, 0x61, 0x7E, 0xC8, 0x98, + 0x26, 0x71, 0xED, 0xF5, 0xA7, 0x61, 0x7A, 0x06, 0x86, 0xA9, 0x08, 0xE2, 0xFC, 0xB7, 0x93, 0xCB, + 0xF3, 0xBD, 0x5F, 0x7F, 0xAB, 0xCC, 0x13, 0x02, 0xF4, 0xDF, 0x9D, 0xBF, 0xFD, 0xED, 0xA7, 0xF1, + 0xAB, 0x6D, 0xFC, 0xF2, 0x20, 0xF4, 0x71, 0xD6, 0xDD, 0xAE, 0x48, 0x4A, 0x07, 0xEC, 0x59, 0x0D, + 0x01, 0xD7, 0x7B, 0x4D, 0x01, 0x37, 0x5B, 0xB9, 0xAE, 0xDA, 0x4F, 0x0B, 0xFF, 0xCF, 0x60, 0xE1, + 0x4D, 0xE0, 0x99, 0x35, 0xB6, 0xA4, 0xB7, 0xA6, 0x04, 0x6F, 0xD5, 0xC0, 0x99, 0xF6, 0x36, 0x07, + 0x67, 0x3A, 0x3C, 0x03, 0xF8, 0x66, 0x6E, 0x76, 0x3A, 0x83, 0xEB, 0x8D, 0x30, 0xC6, 0xC9, 0x4D, + 0x5D, 0xCF, 0x3F, 0xA3, 0x09, 0x8E, 0x2D, 0x69, 0x90, 0xED, 0xCB, 0xAE, 0x65, 0x6D, 0x54, 0xB5, + 0xF7, 0x32, 0xD4, 0xCB, 0xF5, 0x46, 0x50, 0x2F, 0x5B, 0x99, 0xD5, 0x7B, 0x39, 0xD4, 0x56, 0x23, + 0x5A, 0x5B, 0x1A, 0xAD, 0x8A, 0x60, 0xDB, 0x8D, 0x88, 0x6D, 0x37, 0x69, 0x58, 0xB7, 0xD7, 0x84, + 0x56, 0xB7, 0xD7, 0x84, 0x56, 0x6F, 0x4D, 0x99, 0x0E, 0xAA, 0xCA, 0x63, 0xDD, 0x7A, 0xD9, 0x53, + 0xAC, 0x6D, 0x45, 0x7A, 0x0C, 0xAE, 0xDB, 0xCA, 0xD9, 0xAA, 0x99, 0xC9, 0x2D, 0x48, 0x96, 0xE4, + 0x7C, 0xA8, 0xAA, 0xEA, 0x5B, 0x32, 0x5B, 0x49, 0x70, 0x39, 0xFE, 0x6B, 0x39, 0xA0, 0xAA, 0xF9, + 0xD5, 0xE1, 0xB6, 0x1A, 0xC2, 0x6D, 0x37, 0x83, 0xD3, 0x94, 0x6B, 0x6E, 0xB3, 0x71, 0xDE, 0xCE, + 0x50, 0xD3, 0x39, 0x43, 0xEF, 0xCA, 0x7A, 0x46, 0x5B, 0x27, 0xDD, 0x00, 0xFA, 0xA4, 0x7F, 0xB2, + 0x5E, 0xD7, 0xDA, 0x1F, 0xFB, 0x77, 0x68, 0x66, 0xEF, 0x5C, 0x27, 0xBA, 0xF9, 0x47, 0xB7, 0xF8, + 0x56, 0x23, 0x93, 0xDF, 0x7B, 0x42, 0x93, 0xDF, 0x7B, 0x4A, 0x93, 0xDF, 0x7B, 0x42, 0x93, 0xDF, + 0xFB, 0x69, 0xF2, 0x67, 0x36, 0xF9, 0xBD, 0xA7, 0x36, 0xF9, 0xBD, 0x86, 0x26, 0xBF, 0xD7, 0xD0, + 0xE4, 0xF7, 0x1A, 0x9A, 0xFC, 0xDE, 0x13, 0x99, 0x7C, 0x6B, 0xE3, 0x3F, 0x37, 0xAB, 0xC8, 0xB5, + 0xFA, 0x8C, 0x51, 0x05, 0x58, 0x58, 0x6D, 0xA5, 0xB1, 0xFF, 0x34, 0x33, 0xCD, 0x34, 0x64, 0xAF, + 0x40, 0xA6, 0x97, 0x68, 0xC2, 0xEC, 0xED, 0x12, 0xFE, 0x9C, 0x5F, 0x2A, 0x01, 0x8A, 0x7F, 0xEF, + 0x64, 0xEB, 0x7C, 0xD6, 0xEA, 0x7C, 0x36, 0xD4, 0xF9, 0x5D, 0xAB, 0xF3, 0xFB, 0x8E, 0xBC, 0x8B, + 0x07, 0xDC, 0xBC, 0xA7, 0xBE, 0x43, 0x23, 0x77, 0x50, 0xC8, 0x51, 0xF6, 0xBE, 0xCB, 0x50, 0x80, + 0x41, 0x49, 0xF9, 0x7D, 0x96, 0xA4, 0xB2, 0xEF, 0x69, 0x95, 0x3F, 0xEC, 0x1D, 0xEE, 0x9D, 0xED, + 0x1B, 0xAA, 0xEE, 0x8D, 0x22, 0xD1, 0xEB, 0x6A, 0x52, 0x98, 0xB1, 0x1D, 0x7C, 0x53, 0x32, 0xC2, + 0x74, 0x4B, 0xD2, 0xBE, 0x94, 0x80, 0xF7, 0x4C, 0xE0, 0xFC, 0xEA, 0xB7, 0xA0, 0x6F, 0x3B, 0xFF, + 0x31, 0x0D, 0x23, 0x60, 0x54, 0x0F, 0x05, 0x62, 0xA7, 0xB5, 0xA7, 0xF4, 0xEE, 0xD8, 0x4F, 0x6F, + 0x08, 0x65, 0x32, 0xA8, 0xA4, 0x75, 0x0C, 0x81, 0x51, 0xF4, 0xBB, 0x1B, 0x69, 0xE9, 0x10, 0x6E, + 0x5C, 0x87, 0x25, 0x74, 0x74, 0xBD, 0x33, 0x96, 0x86, 0x86, 0x37, 0x02, 0x63, 0xD7, 0x30, 0x17, + 0x1D, 0x78, 0x29, 0x47, 0xDE, 0x59, 0xE0, 0xE3, 0xED, 0xFD, 0x24, 0x49, 0x84, 0x4E, 0x13, 0xB1, + 0xEE, 0x79, 0x8E, 0x1C, 0x8D, 0x85, 0xD5, 0xB8, 0x8F, 0xC3, 0xD3, 0xB5, 0x81, 0xA0, 0xD3, 0x3F, + 0x16, 0x53, 0x36, 0x58, 0x26, 0x4D, 0xCB, 0x14, 0xBE, 0xB5, 0xEF, 0x8F, 0x27, 0x23, 0x1A, 0xA5, + 0x89, 0x93, 0x58, 0x8C, 0x5A, 0x8C, 0x41, 0xC6, 0x2D, 0xC8, 0x99, 0x1B, 0xC2, 0xBF, 0x66, 0x1B, + 0xA2, 0x35, 0x32, 0xA6, 0xD6, 0x8A, 0x6F, 0x76, 0xED, 0xDB, 0x23, 0x4C, 0x3C, 0x7B, 0x77, 0x43, + 0xF9, 0xE5, 0xAE, 0xC3, 0xFE, 0xD9, 0x5A, 0x8F, 0xDC, 0xD8, 0x21, 0xDE, 0x95, 0xBA, 0x76, 0x83, + 0x31, 0x14, 0x06, 0xA0, 0xDF, 0xEE, 0x24, 0x22, 0xFE, 0x35, 0x8F, 0x94, 0xC6, 0x45, 0x7F, 0x2A, + 0x1C, 0x72, 0x1D, 0xF8, 0x63, 0xB2, 0x77, 0xC6, 0x01, 0x86, 0x64, 0x02, 0x5C, 0x49, 0x91, 0x7A, + 0x1C, 0x0B, 0xE6, 0x52, 0x38, 0xE7, 0x68, 0xA4, 0x43, 0xFA, 0x03, 0xE0, 0x24, 0x18, 0xBB, 0x1E, + 0x05, 0xFA, 0xEE, 0xE0, 0x86, 0xA4, 0x1A, 0x80, 0x79, 0x51, 0x91, 0x1D, 0x3F, 0x70, 0x87, 0x30, + 0x76, 0x46, 0x8C, 0x70, 0xE2, 0x19, 0xC6, 0xD9, 0x19, 0x62, 0xA1, 0xFF, 0x61, 0x97, 0x78, 0xD3, + 0xD1, 0x68, 0x49, 0x8F, 0x2E, 0x8C, 0xA5, 0xA8, 0xD5, 0xAF, 0x92, 0xB4, 0x81, 0x7F, 0x7B, 0x45, + 0xF6, 0x46, 0x23, 0xD2, 0x87, 0xEF, 0x4E, 0x71, 0x2A, 0x3F, 0xDF, 0x0B, 0xFD, 0x11, 0xED, 0x8C, + 0x40, 0x63, 0x5B, 0x9F, 0xF8, 0x8D, 0x54, 0x02, 0xFF, 0x81, 0x9C, 0x40, 0x68, 0x59, 0x19, 0x98, + 0x93, 0x78, 0x5C, 0x27, 0x69, 0x2B, 0x47, 0xBE, 0xED, 0xFC, 0x6A, 0xBB, 0x91, 0x72, 0x11, 0x1D, + 0x33, 0x81, 0x88, 0xB7, 0x12, 0xC2, 0xE9, 0xD5, 0xD8, 0x8D, 0xE2, 0x34, 0x91, 0x98, 0x31, 0x04, + 0x06, 0x1B, 0x96, 0x87, 0x5F, 0xAC, 0xAF, 0x69, 0x5C, 0x3B, 0x4E, 0x59, 0x22, 0xB6, 0xDD, 0xA3, + 0x77, 0x04, 0x6F, 0x01, 0xCA, 0x49, 0x2D, 0xE2, 0xE2, 0x8E, 0x3D, 0x99, 0xF0, 0x41, 0x95, 0x45, + 0xDB, 0x66, 0x64, 0x97, 0x52, 0x9C, 0xF6, 0x7F, 0xD8, 0xDF, 0x05, 0xBE, 0xDF, 0x4E, 0x8E, 0x3F, + 0x44, 0x98, 0x72, 0xEC, 0xAF, 0x53, 0x1A, 0x46, 0x31, 0x56, 0xAC, 0xD0, 0xF1, 0x01, 0xE1, 0x62, + 0xEB, 0xEC, 0x63, 0xFF, 0x02, 0x73, 0x98, 0xAC, 0x4E, 0x59, 0x8B, 0x62, 0xC4, 0x2D, 0xB9, 0x26, + 0x1B, 0x5A, 0x31, 0x27, 0xF1, 0xC8, 0xE3, 0x66, 0x4C, 0x96, 0x86, 0x21, 0xD6, 0xF2, 0xF5, 0x55, + 0xF0, 0x86, 0x17, 0xBA, 0x78, 0x87, 0x6F, 0xA2, 0x24, 0x90, 0x6A, 0xED, 0x14, 0x88, 0xB6, 0x1F, + 0xD9, 0xD1, 0x34, 0xC4, 0xF0, 0x66, 0xD5, 0x20, 0x17, 0x13, 0x84, 0xEA, 0x45, 0x48, 0x33, 0x03, + 0x99, 0x0F, 0x3B, 0x73, 0xA5, 0x56, 0xEE, 0x60, 0x56, 0x08, 0xF8, 0xC1, 0x90, 0x46, 0x67, 0xB6, + 0x1B, 0xC0, 0x8C, 0x88, 0xC6, 0x55, 0x9D, 0x41, 0xAE, 0x22, 0xEF, 0x1D, 0xAB, 0xC1, 0xCB, 0x0C, + 0x22, 0x42, 0xED, 0x65, 0x79, 0x7D, 0x42, 0x86, 0xCB, 0x8F, 0x22, 0xEA, 0x75, 0xA4, 0x9C, 0x04, + 0x13, 0x4A, 0x83, 0x93, 0xBD, 0xFD, 0x50, 0x87, 0x3B, 0xF5, 0x3D, 0x9A, 0x17, 0x99, 0xCA, 0x28, + 0x1E, 0x86, 0x93, 0x53, 0xFF, 0xEE, 0x0C, 0xC0, 0x43, 0x83, 0xF9, 0x05, 0xC6, 0x98, 0x91, 0xD4, + 0x73, 0xC2, 0x0D, 0x63, 0x13, 0x25, 0x0A, 0x0C, 0x1C, 0x33, 0x38, 0x16, 0xAA, 0x23, 0x92, 0x77, + 0xE5, 0x45, 0xC8, 0xCA, 0x78, 0x52, 0x16, 0x92, 0x70, 0x05, 0xDB, 0x71, 0x0E, 0x6F, 0xE1, 0x17, + 0x0C, 0x53, 0xA6, 0x80, 0x7F, 0xB1, 0x75, 0xF0, 0xF1, 0x04, 0x6C, 0x71, 0x84, 0xDF, 0xA0, 0x23, + 0x28, 0xA6, 0xC7, 0x5B, 0xA4, 0x58, 0x65, 0x89, 0xEC, 0xBE, 0x01, 0x06, 0x13, 0x0D, 0x17, 0x02, + 0xAB, 0x10, 0xFB, 0x90, 0x4D, 0x32, 0xA6, 0x44, 0x3C, 0xB0, 0xBB, 0xF4, 0xE8, 0xD4, 0xB3, 0x5B, + 0x7B, 0xF0, 0x0B, 0xC7, 0x9C, 0x44, 0x3C, 0xB8, 0x18, 0x06, 0x61, 0x7F, 0x87, 0x5F, 0xD4, 0xD0, + 0x07, 0x5E, 0xED, 0x8B, 0xFB, 0xB5, 0xE3, 0x7B, 0x83, 0x91, 0x3B, 0xC0, 0x34, 0x1F, 0x89, 0x6C, + 0x17, 0x33, 0xAF, 0x5A, 0xAB, 0xE9, 0xF7, 0x72, 0xDE, 0xAA, 0xE5, 0x2E, 0x96, 0x1D, 0x4E, 0x03, + 0x16, 0x34, 0x8D, 0x8E, 0xF0, 0x87, 0xBF, 0x81, 0xF0, 0xB3, 0x72, 0xE2, 0xF8, 0x70, 0xE0, 0x1B, + 0x49, 0x1A, 0x10, 0xF5, 0xE9, 0x40, 0xDD, 0x36, 0x21, 0xAB, 0xB9, 0xF4, 0xA4, 0x60, 0xEC, 0x07, + 0x79, 0xB4, 0x1B, 0x51, 0xCE, 0x83, 0xB9, 0x94, 0x6A, 0x11, 0x6F, 0x52, 0x13, 0x0C, 0xCC, 0x61, + 0x5A, 0x31, 0xBC, 0x13, 0xCC, 0xE3, 0x45, 0x8E, 0xBC, 0x26, 0xAC, 0xC5, 0x29, 0x6C, 0x0D, 0xB8, + 0x4A, 0x9E, 0x2D, 0xE7, 0x76, 0x24, 0x14, 0xF5, 0xCD, 0x6F, 0x21, 0x73, 0x3B, 0xC2, 0x3C, 0xBF, + 0xDC, 0x47, 0x8B, 0x4D, 0x2D, 0x7A, 0x87, 0x10, 0xF3, 0x68, 0x4E, 0x8C, 0xA8, 0x52, 0x5B, 0x72, + 0xF8, 0x4C, 0x1B, 0x92, 0xDF, 0x58, 0x43, 0x5B, 0x8A, 0xDF, 0x84, 0x6F, 0xDC, 0xB2, 0x99, 0x9E, + 0x9A, 0xE7, 0xED, 0xC4, 0x75, 0x41, 0x51, 0x33, 0x87, 0xC9, 0x12, 0xA1, 0x79, 0x33, 0xDF, 0xB3, + 0x8C, 0x4E, 0xF3, 0x6E, 0xE5, 0x7B, 0x3D, 0x4F, 0x94, 0xA9, 0x91, 0xBC, 0x11, 0xF9, 0x8D, 0xE4, + 0x42, 0xC8, 0x36, 0x52, 0xA9, 0x94, 0xB7, 0xD3, 0x97, 0x59, 0x5F, 0x37, 0xD8, 0xD2, 0x53, 0x1E, + 0x52, 0x32, 0x66, 0xBA, 0x97, 0x8E, 0x44, 0xB7, 0x3A, 0x1B, 0x78, 0xBA, 0xB9, 0x07, 0xCE, 0x2D, + 0x4C, 0xC5, 0xE8, 0xB7, 0x1D, 0x77, 0x57, 0x8F, 0x7B, 0x0A, 0xB2, 0x07, 0xF5, 0x22, 0x52, 0xE9, + 0xF6, 0xC0, 0x6D, 0xF6, 0xB6, 0x6B, 0x65, 0x7E, 0xB6, 0x3B, 0x9B, 0x73, 0xE4, 0x27, 0xBB, 0x5F, + 0x54, 0x87, 0x99, 0x6E, 0x77, 0x73, 0xAE, 0xD2, 0xD1, 0x53, 0x0B, 0xD7, 0xE1, 0x65, 0x1D, 0xF7, + 0x2D, 0x1A, 0xB0, 0xD2, 0x8C, 0x9A, 0xB2, 0xB9, 0xA2, 0x62, 0x36, 0x8C, 0x51, 0xD3, 0x4B, 0xF0, + 0x8D, 0x87, 0x66, 0xCD, 0x67, 0xE5, 0xD3, 0x11, 0x67, 0xB8, 0x1C, 0x9C, 0x7B, 0x7D, 0xD9, 0x34, + 0xA2, 0x2B, 0xC0, 0xE7, 0xB5, 0x3A, 0x79, 0xBF, 0x67, 0x1E, 0xAD, 0xAE, 0xF2, 0x18, 0x90, 0xD6, + 0x6A, 0x0E, 0xD2, 0xBC, 0xD5, 0xC5, 0xF0, 0x86, 0x56, 0x6B, 0xD7, 0xC5, 0x66, 0x6F, 0x79, 0x16, + 0x61, 0x49, 0xEB, 0x0D, 0x17, 0xD3, 0x00, 0x48, 0xE4, 0x88, 0xD7, 0xA2, 0x60, 0x4B, 0x45, 0x51, + 0x8A, 0x4C, 0xDD, 0xB8, 0x33, 0x88, 0x05, 0x97, 0x71, 0x98, 0x13, 0x15, 0xB3, 0xFE, 0x7A, 0x74, + 0x34, 0x8B, 0x40, 0xB2, 0xA8, 0x92, 0xAC, 0x26, 0x96, 0x59, 0x07, 0x62, 0x88, 0xB7, 0xF6, 0xD4, + 0x39, 0x08, 0xFC, 0x09, 0x26, 0xD4, 0x37, 0x4F, 0xBD, 0xCA, 0x93, 0x72, 0xA5, 0xFA, 0x52, 0x81, + 0xA3, 0xAE, 0x79, 0x76, 0xAC, 0xC2, 0x91, 0x70, 0x16, 0x6A, 0x71, 0xD4, 0x94, 0x56, 0x8D, 0xD6, + 0x1B, 0xB4, 0x3D, 0xFF, 0x91, 0xC7, 0x19, 0xB5, 0xBE, 0xF4, 0xF5, 0x48, 0x73, 0x7F, 0x4F, 0xC0, + 0x4C, 0xF1, 0xE7, 0x83, 0x1B, 0x09, 0xAC, 0x1C, 0x5C, 0x91, 0xC1, 0x34, 0xA4, 0xC7, 0xFE, 0xC0, + 0x1E, 0xB9, 0x7F, 0xA3, 0xCE, 0x01, 0xB4, 0x33, 0x70, 0xAF, 0xA6, 0x3C, 0x8D, 0x64, 0xF3, 0xE6, + 0x17, 0xE0, 0x2C, 0x6C, 0xF9, 0xC8, 0x04, 0x74, 0x01, 0x2B, 0xC0, 0x63, 0x58, 0xD3, 0x8E, 0x4C, + 0xBD, 0x5F, 0x41, 0x1E, 0x4D, 0x91, 0x1A, 0x34, 0x45, 0x7F, 0x6B, 0x72, 0x46, 0xFD, 0xA8, 0xF1, + 0x74, 0x65, 0xE1, 0x88, 0x3A, 0xA0, 0x91, 0xED, 0x8E, 0xC2, 0x9A, 0x72, 0xA9, 0x83, 0xA8, 0x40, + 0x16, 0x1F, 0xEC, 0xC0, 0xC1, 0xAD, 0x20, 0x2E, 0x88, 0xE4, 0x0D, 0x9E, 0x39, 0x89, 0x26, 0x07, + 0x7B, 0x2D, 0x49, 0xC9, 0xB0, 0xB3, 0x89, 0xAA, 0x12, 0x26, 0x93, 0xAC, 0xD8, 0xC6, 0xD2, 0x1C, + 0xA4, 0x12, 0xE3, 0xA9, 0xD4, 0x7E, 0xB6, 0xE3, 0xD2, 0xAC, 0xC1, 0xC5, 0xA0, 0x26, 0x8F, 0x41, + 0xDA, 0xB2, 0x9B, 0x83, 0xBB, 0xA0, 0x62, 0xCB, 0xB1, 0x19, 0x86, 0xDD, 0xC2, 0xD9, 0x7C, 0x84, + 0x42, 0x64, 0xA5, 0x3E, 0x82, 0xF2, 0x34, 0xDD, 0x8C, 0x02, 0x28, 0x7F, 0xE0, 0x4E, 0x36, 0x9A, + 0x81, 0xDD, 0xAC, 0x97, 0x0B, 0x21, 0x8D, 0x6D, 0x6B, 0x3C, 0xBA, 0x91, 0xD5, 0x0F, 0x40, 0x54, + 0x1D, 0x3C, 0xF1, 0xC6, 0x5E, 0x3E, 0xAD, 0xF3, 0xA3, 0xD3, 0xC3, 0xDF, 0xE6, 0x21, 0x4F, 0x05, + 0x5B, 0x35, 0xF3, 0x91, 0x81, 0x6C, 0x68, 0x3C, 0xAA, 0xE3, 0x31, 0xC8, 0x41, 0x79, 0xD8, 0x6C, + 0x46, 0x29, 0x54, 0x7D, 0x24, 0x4D, 0x97, 0x41, 0x0A, 0x37, 0x8B, 0x04, 0x2A, 0x60, 0x31, 0xB5, + 0xDF, 0xF4, 0xF2, 0xD9, 0xAC, 0x72, 0xA8, 0xF9, 0x9A, 0x5A, 0x46, 0x1E, 0x00, 0x3F, 0xB6, 0x23, + 0x77, 0xA0, 0x22, 0x99, 0x49, 0x38, 0x35, 0x51, 0xE6, 0x48, 0x2A, 0x7E, 0x2B, 0x6D, 0x0E, 0x02, + 0xAA, 0xF0, 0xEC, 0x5A, 0xAE, 0x5C, 0x18, 0xEC, 0x5C, 0xC4, 0x51, 0x8C, 0x49, 0x91, 0x42, 0xE5, + 0x67, 0xD4, 0x1A, 0x0B, 0x67, 0x1E, 0x0F, 0xB5, 0x49, 0x7B, 0xDF, 0x85, 0xD8, 0x9A, 0x49, 0xAF, + 0x21, 0xCE, 0xEC, 0x96, 0xEC, 0xDE, 0x28, 0x72, 0xA3, 0xA9, 0xD3, 0x68, 0xB0, 0x29, 0x21, 0x10, + 0x19, 0xF4, 0xFA, 0xD3, 0x9F, 0x8F, 0x45, 0x20, 0xB3, 0xF9, 0x35, 0x67, 0x32, 0x6A, 0x40, 0xCA, + 0x1C, 0x91, 0x27, 0xF7, 0x8A, 0xEF, 0xF9, 0xBD, 0xE2, 0x7B, 0xF2, 0x9A, 0x78, 0xD3, 0xF1, 0x7E, + 0xE6, 0x05, 0x57, 0x28, 0xCA, 0xDE, 0x2E, 0x86, 0xE5, 0x4D, 0xE4, 0x7B, 0xE2, 0x72, 0x31, 0x7B, + 0xB2, 0x04, 0xB3, 0xD3, 0xBC, 0x65, 0x5F, 0xF1, 0x59, 0x89, 0x7B, 0x25, 0x40, 0x29, 0xAD, 0x6D, + 0x6C, 0x02, 0x1E, 0xD3, 0xE5, 0xB6, 0x20, 0xCE, 0x9C, 0x93, 0xE2, 0xDF, 0xC7, 0xFA, 0x8B, 0xF7, + 0xB2, 0x7A, 0x49, 0xAF, 0x43, 0x2C, 0xC9, 0xC1, 0x30, 0x39, 0xEE, 0x80, 0x94, 0x5A, 0xAA, 0x5E, + 0x74, 0x5A, 0xC9, 0x03, 0xAC, 0x15, 0x66, 0x78, 0xC1, 0xC3, 0x09, 0xC3, 0x3E, 0xCB, 0x14, 0x5F, + 0x82, 0xC8, 0x18, 0x6A, 0x31, 0x37, 0xF6, 0xE7, 0xC0, 0xB8, 0x89, 0x65, 0x25, 0x26, 0xAD, 0x28, + 0xFD, 0x51, 0x41, 0x62, 0xA6, 0x1C, 0x1D, 0xD6, 0x6E, 0xC8, 0x37, 0xD7, 0xFE, 0x34, 0x27, 0x6B, + 0x7E, 0x36, 0xA7, 0x7B, 0x96, 0xB6, 0xEF, 0xBB, 0x69, 0x97, 0xBE, 0xCA, 0xE0, 0xF9, 0xBE, 0x63, + 0xDA, 0x6E, 0x97, 0x07, 0x11, 0x66, 0x87, 0x16, 0x07, 0xF2, 0x2C, 0x33, 0xB3, 0xC6, 0x0A, 0x56, + 0x42, 0x2E, 0x4A, 0x76, 0xDF, 0xD5, 0xB4, 0x60, 0x86, 0x31, 0x86, 0xDF, 0xF8, 0xDF, 0x69, 0xDC, + 0x11, 0x39, 0xF2, 0x06, 0x01, 0x8B, 0x16, 0x99, 0x88, 0x7C, 0x59, 0x64, 0x85, 0x84, 0x77, 0xF6, + 0x84, 0xBF, 0xBE, 0xCD, 0x0E, 0xFA, 0x61, 0x4E, 0x4A, 0x79, 0x22, 0x21, 0xE3, 0x89, 0xA7, 0x0F, + 0xC1, 0x3A, 0x1E, 0xA6, 0xB6, 0xBE, 0x01, 0xBB, 0x4C, 0xC3, 0xF4, 0xC5, 0xCD, 0x94, 0x14, 0x79, + 0xA3, 0xEE, 0x50, 0xB2, 0x64, 0x06, 0xF6, 0x37, 0x7A, 0x42, 0x3F, 0x20, 0x4C, 0xB0, 0x63, 0x28, + 0x61, 0xC9, 0xFC, 0x76, 0xB2, 0xBD, 0x5B, 0x5B, 0x2F, 0xAA, 0xF4, 0xEE, 0x77, 0xD6, 0xBB, 0x59, + 0xD9, 0xC8, 0xFF, 0x64, 0x86, 0xD3, 0xCC, 0x5E, 0xE6, 0x13, 0x96, 0x6A, 0xF4, 0x64, 0x09, 0xAD, + 0x90, 0xEE, 0x52, 0x3E, 0x55, 0x26, 0x8C, 0x22, 0xA2, 0x0F, 0x73, 0x14, 0x14, 0x33, 0x99, 0x72, + 0x6B, 0x4D, 0x7C, 0x95, 0xB4, 0x6E, 0x05, 0x2F, 0x23, 0xC9, 0xAA, 0x55, 0x22, 0x2C, 0x89, 0x26, + 0x6B, 0xAB, 0x89, 0x24, 0x60, 0x3B, 0xF5, 0x23, 0xFA, 0x8A, 0xB4, 0x4A, 0x88, 0x2F, 0x03, 0xF1, + 0x16, 0xF1, 0xBD, 0xD1, 0x3D, 0xB9, 0xF3, 0x83, 0x6F, 0x61, 0xCC, 0x2C, 0xFC, 0xED, 0x5E, 0x9B, + 0xD0, 0x16, 0xE0, 0x63, 0x4F, 0xA4, 0xB8, 0x5E, 0xD4, 0x66, 0x6F, 0xD3, 0x87, 0x2C, 0xFB, 0x74, + 0x87, 0x7C, 0xC2, 0xB1, 0x62, 0x07, 0xF8, 0x48, 0x57, 0x84, 0x63, 0x85, 0x52, 0x62, 0x5F, 0xF9, + 0xB7, 0xB4, 0xAE, 0x98, 0x96, 0x63, 0x31, 0x1D, 0xD0, 0x42, 0x31, 0x3D, 0x28, 0x19, 0x4B, 0xC8, + 0xD1, 0x35, 0xB1, 0x47, 0x50, 0xDF, 0xB9, 0x67, 0xA3, 0x4F, 0x0C, 0xBC, 0x64, 0xF4, 0xB6, 0x99, + 0x24, 0x89, 0x1B, 0x91, 0x11, 0xC8, 0x52, 0x8C, 0x48, 0xCD, 0x92, 0xB3, 0x60, 0x9C, 0xBD, 0xF1, + 0x07, 0x0E, 0xFA, 0xB4, 0xE3, 0x0C, 0x6D, 0x01, 0x36, 0xC3, 0x22, 0x6E, 0x48, 0x3E, 0x48, 0x56, + 0x43, 0x41, 0x95, 0x30, 0x97, 0xD5, 0x7B, 0xFC, 0x77, 0x05, 0xED, 0xFF, 0xF6, 0x34, 0xC3, 0x01, + 0x9F, 0x62, 0x48, 0xB8, 0x79, 0xE4, 0xC1, 0x90, 0x73, 0x36, 0x5B, 0x9A, 0x68, 0xD0, 0xD8, 0x26, + 0xB4, 0x2A, 0x8C, 0xF0, 0x71, 0xAA, 0x07, 0xF9, 0xCA, 0x55, 0x37, 0x45, 0x21, 0xBA, 0x7D, 0xFB, + 0x87, 0xEF, 0x92, 0xA9, 0x5B, 0x7E, 0x46, 0x2D, 0xB9, 0x3A, 0xE3, 0xC1, 0xA4, 0x83, 0x71, 0x61, + 0x58, 0x33, 0x39, 0x45, 0x0E, 0xE8, 0x18, 0x06, 0xCB, 0x5B, 0xDB, 0xC1, 0xB5, 0x46, 0xB8, 0x98, + 0xAD, 0x13, 0x7B, 0xB4, 0xC6, 0x57, 0x5D, 0xA5, 0xDA, 0xE2, 0x4D, 0xD7, 0xCC, 0xF3, 0xE3, 0xEB, + 0xDB, 0xEC, 0x55, 0x57, 0x1B, 0xE6, 0x2D, 0xF5, 0x69, 0x57, 0x39, 0xB9, 0xF4, 0xCE, 0x8B, 0x9C, + 0x57, 0x6A, 0xA5, 0xE0, 0xF8, 0x36, 0x59, 0x79, 0x19, 0xBF, 0x4D, 0xFB, 0x32, 0xF3, 0x48, 0x6D, + 0x5C, 0x86, 0x24, 0xC5, 0xAF, 0xCD, 0x89, 0x7D, 0x7E, 0x4A, 0x62, 0xBF, 0xCF, 0x93, 0x58, 0xCE, + 0x43, 0x7A, 0xCA, 0x94, 0x1F, 0xBF, 0x44, 0x85, 0x3D, 0x47, 0xEC, 0xA1, 0x8D, 0x2F, 0x19, 0xF2, + 0xE7, 0x31, 0x5C, 0x49, 0x31, 0xF9, 0x73, 0x3B, 0x0E, 0xFD, 0xAE, 0xDE, 0x19, 0x62, 0x83, 0x78, + 0x47, 0x94, 0xBC, 0xC6, 0x00, 0x6C, 0x3F, 0x70, 0x42, 0xA6, 0x2E, 0x71, 0xF0, 0xE0, 0xF2, 0x32, + 0x2B, 0xD5, 0x47, 0x27, 0x22, 0x04, 0x43, 0x1D, 0x85, 0x4C, 0xEB, 0x12, 0xB0, 0x2F, 0xAC, 0xF2, + 0xD7, 0x38, 0xB9, 0x35, 0xD1, 0x73, 0xEA, 0xC6, 0x5E, 0xB5, 0xA2, 0x6B, 0xD2, 0xE9, 0x26, 0x43, + 0x89, 0x19, 0xAC, 0x0D, 0x43, 0x35, 0x4B, 0x06, 0x87, 0x67, 0x76, 0x18, 0x2C, 0x93, 0x05, 0x96, + 0x60, 0x36, 0xD5, 0xB6, 0xBC, 0x82, 0xCF, 0x79, 0x05, 0xBF, 0xEB, 0xC9, 0x8B, 0x6B, 0x1A, 0x47, + 0xFE, 0xEA, 0x0C, 0x13, 0xF7, 0xAE, 0x41, 0xAA, 0x4B, 0x2F, 0x72, 0xDA, 0xD5, 0x99, 0x4C, 0xC3, + 0x9B, 0xC5, 0x47, 0x6D, 0xD3, 0x92, 0x21, 0x71, 0x2A, 0x12, 0xC2, 0x35, 0xA6, 0x6E, 0x88, 0x1C, + 0x8A, 0x31, 0xC4, 0x89, 0x2D, 0x4A, 0x22, 0x57, 0x01, 0x91, 0x08, 0x10, 0xC7, 0x08, 0x67, 0xA8, + 0x29, 0xDD, 0x3D, 0x91, 0x7B, 0x34, 0xBD, 0x63, 0x89, 0x10, 0x6F, 0x58, 0x72, 0x6E, 0x75, 0xA6, + 0x34, 0xA9, 0x10, 0xD4, 0x35, 0x2B, 0x10, 0x02, 0xA0, 0x6C, 0xC4, 0x6A, 0x20, 0xD6, 0x15, 0x29, + 0xD0, 0x8B, 0x4F, 0x93, 0x2C, 0x0A, 0x7E, 0xB1, 0x75, 0xC0, 0xB8, 0x27, 0x78, 0xD8, 0xC8, 0x5A, + 0x83, 0xCB, 0x85, 0x04, 0x7C, 0x99, 0xB4, 0xFE, 0xA5, 0xB5, 0x94, 0xB7, 0x1D, 0x24, 0x77, 0x09, + 0x72, 0x32, 0xA0, 0xD8, 0x02, 0xB0, 0x89, 0x39, 0x6B, 0xC7, 0x62, 0x31, 0x62, 0x40, 0xB6, 0x62, + 0xD0, 0x7F, 0xA0, 0x0C, 0x73, 0xEF, 0x28, 0x71, 0x69, 0x76, 0xBF, 0xE6, 0x54, 0xFD, 0x9C, 0xA9, + 0xDA, 0xCB, 0xAB, 0xFA, 0x7B, 0xA6, 0xEA, 0x9A, 0x56, 0xD5, 0x3C, 0xFA, 0xA5, 0x0E, 0x35, 0xBD, + 0x83, 0x28, 0x73, 0x5D, 0x52, 0xE3, 0x73, 0x69, 0x8D, 0xDF, 0xF3, 0x6A, 0xA8, 0xAC, 0x29, 0x2F, + 0xFE, 0x25, 0x8F, 0x13, 0x49, 0x82, 0x06, 0x2F, 0x36, 0xB0, 0xC1, 0x2F, 0xE4, 0x0A, 0x40, 0x6C, + 0xCF, 0x21, 0x63, 0xDF, 0xF3, 0xC3, 0x89, 0x0D, 0xAB, 0x38, 0x16, 0x6B, 0xCE, 0xCC, 0xB0, 0xB6, + 0x52, 0x4F, 0x15, 0x45, 0x0A, 0x58, 0xCF, 0x55, 0x03, 0x91, 0x17, 0x3D, 0x9D, 0xFA, 0x51, 0x19, + 0xB2, 0x46, 0x25, 0x33, 0x33, 0xF0, 0xFD, 0x84, 0x3C, 0xB4, 0x69, 0xF3, 0xE5, 0x26, 0xE3, 0xBD, + 0x2F, 0x3D, 0x44, 0x5F, 0x7A, 0xB5, 0x08, 0x33, 0x5C, 0xFA, 0x01, 0x75, 0x5A, 0x45, 0x4F, 0x9A, + 0xB2, 0x9D, 0x90, 0x99, 0xC9, 0x8A, 0xD2, 0x57, 0xE4, 0xB7, 0xD5, 0xCF, 0xAB, 0xBF, 0xB7, 0xD4, + 0x3C, 0xF2, 0x86, 0xD6, 0xBF, 0x26, 0x1B, 0x4B, 0x99, 0xE3, 0xC3, 0x5C, 0x99, 0x86, 0xEE, 0xDF, + 0x28, 0x31, 0x99, 0x66, 0xC5, 0x3A, 0x26, 0x3E, 0x6E, 0x3A, 0x75, 0xD6, 0x9D, 0x2B, 0x71, 0x80, + 0xFA, 0x13, 0xD6, 0xF7, 0x52, 0xA0, 0x3F, 0x7A, 0xAB, 0xA0, 0x06, 0x22, 0xB1, 0xF8, 0x02, 0xAF, + 0x20, 0x0F, 0x53, 0xFE, 0x85, 0xED, 0x5D, 0x18, 0x27, 0xD8, 0x4C, 0xCD, 0x78, 0x0C, 0xB1, 0x62, + 0x75, 0xB4, 0xE5, 0x0A, 0x01, 0xB3, 0xAA, 0x73, 0x70, 0x75, 0x52, 0xF8, 0xE3, 0x62, 0xEB, 0x7F, + 0x99, 0x81, 0x04, 0x35, 0x80, 0xA5, 0xF6, 0xE0, 0x66, 0xD1, 0xBC, 0x0B, 0x29, 0xDB, 0xA4, 0x3F, + 0x2E, 0x46, 0x37, 0x6E, 0xC8, 0x37, 0x61, 0x16, 0x97, 0x0A, 0xAD, 0xBA, 0xA7, 0x5A, 0xF5, 0x4E, + 0x38, 0xBD, 0xE2, 0xAB, 0xC2, 0x45, 0xF0, 0x9F, 0xBA, 0x1B, 0xCA, 0x2B, 0xF3, 0x12, 0xD2, 0x04, + 0x14, 0x26, 0x3C, 0x9E, 0x58, 0x3E, 0xB6, 0x64, 0xC9, 0x14, 0x18, 0xDB, 0x2B, 0xED, 0xC3, 0xDA, + 0x57, 0x8E, 0x22, 0xDD, 0xEC, 0xD5, 0x9C, 0xF0, 0xF8, 0x66, 0x65, 0x35, 0x47, 0x3C, 0xAE, 0x5D, + 0xE6, 0x8C, 0xAB, 0xF5, 0xAA, 0x38, 0xE4, 0x31, 0xC4, 0xBC, 0x9C, 0xF2, 0xF4, 0x99, 0xB1, 0x42, + 0x77, 0x36, 0x39, 0x70, 0x00, 0x8F, 0xB6, 0xDB, 0xB5, 0xD6, 0xD6, 0xDB, 0x64, 0x6B, 0x4B, 0xA1, + 0xCE, 0x3F, 0x23, 0x0B, 0x58, 0x50, 0xDB, 0x69, 0xD6, 0xCF, 0x1D, 0x90, 0xCE, 0x06, 0xF6, 0xB5, + 0x42, 0x62, 0x83, 0x3D, 0x3C, 0xB8, 0xD1, 0x14, 0xBB, 0x76, 0xE8, 0x00, 0x34, 0x7A, 0x96, 0xD5, + 0xB1, 0xD8, 0x45, 0xC9, 0x8E, 0xE2, 0x99, 0xB3, 0x0F, 0x48, 0x8C, 0xFD, 0xF2, 0xEC, 0xBC, 0xF2, + 0x44, 0x6F, 0xEA, 0x7B, 0xE6, 0x31, 0x68, 0x5D, 0xEF, 0x3C, 0x51, 0xBC, 0x7A, 0x1E, 0xBA, 0x46, + 0x4E, 0xF2, 0xD2, 0xB5, 0x31, 0xA2, 0xF8, 0xA8, 0xE2, 0x8A, 0xB2, 0xB1, 0x48, 0xDC, 0x48, 0x36, + 0x95, 0xC5, 0x5A, 0xAA, 0x95, 0x69, 0xBA, 0x65, 0x2E, 0x55, 0x75, 0xE3, 0x11, 0x7C, 0x7E, 0xAD, + 0xCF, 0x8C, 0x7E, 0x7F, 0x52, 0x47, 0xF1, 0xFD, 0xFF, 0x01, 0x24, 0x65, 0x5A, 0x49, 0xC4, 0x6C, + 0xE7, 0xAF, 0x26, 0x32, 0x46, 0xB5, 0xCC, 0x19, 0xD6, 0x95, 0xB0, 0xB6, 0x43, 0x9C, 0xA8, 0xE3, + 0xF3, 0x59, 0x58, 0x24, 0xBD, 0x5B, 0x7D, 0x71, 0x51, 0x24, 0x59, 0xE9, 0xE4, 0x52, 0x5E, 0xA6, + 0xDD, 0xD8, 0xF4, 0x84, 0x46, 0x37, 0xBE, 0x93, 0x7B, 0xC7, 0x50, 0xB9, 0x60, 0x98, 0x5E, 0xAD, + 0x7F, 0x15, 0xDF, 0xA4, 0xCF, 0xBC, 0x60, 0x05, 0x28, 0x53, 0xF9, 0x4B, 0xF8, 0xB5, 0xB8, 0xE4, + 0xEC, 0x69, 0x6C, 0x7E, 0x0C, 0x98, 0xE9, 0x80, 0x3B, 0x37, 0xC8, 0x0B, 0x48, 0xC2, 0x37, 0xF1, + 0xAC, 0x53, 0x4E, 0x12, 0x82, 0x25, 0xB2, 0x42, 0x16, 0xA5, 0x2A, 0xD9, 0xE3, 0x6D, 0x51, 0x6D, + 0x99, 0x64, 0x6B, 0x99, 0x2F, 0x68, 0x2C, 0x91, 0x55, 0xD2, 0xE5, 0x17, 0xEB, 0x8B, 0xD8, 0x8E, + 0x67, 0x7E, 0xE0, 0xB2, 0x83, 0xF1, 0x2C, 0x50, 0xBA, 0xB8, 0x56, 0x74, 0x9F, 0xBB, 0x50, 0x4E, + 0xD9, 0xDC, 0x15, 0x05, 0x62, 0xD2, 0x84, 0x6A, 0x96, 0x93, 0xCE, 0x2A, 0x8A, 0xE0, 0x09, 0x25, + 0x95, 0xC9, 0x15, 0x61, 0x96, 0x93, 0xBE, 0x74, 0x7E, 0xB6, 0x16, 0x63, 0x3A, 0x3E, 0x13, 0x70, + 0x0C, 0x5E, 0x59, 0x41, 0xC4, 0x14, 0x93, 0x4A, 0x6F, 0x76, 0xC9, 0xA6, 0x69, 0xAA, 0x1E, 0xD9, + 0x51, 0x8C, 0x25, 0xAD, 0xBC, 0x42, 0xD6, 0x51, 0x90, 0x3D, 0xC3, 0xAB, 0x7A, 0xB9, 0x53, 0xB3, + 0x61, 0xF9, 0x5C, 0x92, 0x02, 0x24, 0xBB, 0xE4, 0x8F, 0xB9, 0x4E, 0x98, 0x7A, 0x93, 0xBD, 0x6F, + 0xA0, 0x2C, 0x8C, 0xC6, 0xB0, 0x1A, 0x8C, 0xD9, 0xEF, 0xEE, 0x48, 0x7F, 0xBE, 0x4E, 0x1A, 0x26, + 0x7D, 0xCD, 0x9E, 0x03, 0x94, 0x72, 0xB9, 0xBC, 0xAB, 0xF8, 0xEC, 0x29, 0x81, 0x65, 0xA2, 0x33, + 0x9E, 0xDD, 0xF3, 0x7F, 0xC8, 0x91, 0x44, 0x36, 0xC1, 0x89, 0x10, 0x05, 0x60, 0x8D, 0xD9, 0x7E, + 0x5E, 0x52, 0xD1, 0x39, 0x2E, 0x12, 0x4B, 0x7E, 0x23, 0x2A, 0x4B, 0xC8, 0x60, 0xD3, 0x38, 0x21, + 0x49, 0x43, 0xD7, 0x0C, 0x8A, 0x96, 0x63, 0x40, 0x4C, 0xE0, 0xBD, 0x7C, 0xF0, 0xDC, 0x4B, 0x72, + 0x19, 0x24, 0xDD, 0xAF, 0xDA, 0x2D, 0xCF, 0x26, 0xB9, 0x66, 0xE2, 0x64, 0x31, 0x35, 0xF0, 0xF4, + 0x0A, 0x72, 0xD6, 0x28, 0x78, 0x94, 0x98, 0xA2, 0xBC, 0xC7, 0xE2, 0x0C, 0x83, 0x7A, 0x27, 0xB7, + 0xAE, 0x3A, 0x4A, 0xCA, 0xEA, 0x25, 0x7A, 0x53, 0x52, 0x31, 0xED, 0xF0, 0xFC, 0x8A, 0x99, 0xCE, + 0x2D, 0xAD, 0xAA, 0x77, 0x64, 0xC5, 0x40, 0x18, 0x25, 0xCB, 0x49, 0xC8, 0xCD, 0x7B, 0x2C, 0x1A, + 0xC2, 0xAC, 0x31, 0x5F, 0x89, 0xE7, 0x84, 0xC5, 0x64, 0x77, 0xEA, 0x12, 0xE0, 0x46, 0xBB, 0x75, + 0xAA, 0xE7, 0x55, 0xB8, 0x63, 0x27, 0x59, 0xE5, 0xA2, 0x5D, 0x3B, 0x6D, 0x59, 0x50, 0x79, 0xE7, + 0xCE, 0xA4, 0x1F, 0xBA, 0xEE, 0x3C, 0xE2, 0x0E, 0x5E, 0x43, 0xF2, 0xC9, 0x4E, 0x1E, 0x68, 0xED, + 0x2A, 0x6A, 0xE4, 0x2A, 0x68, 0x9B, 0x79, 0x43, 0x4F, 0x17, 0x4C, 0xC5, 0x4D, 0x3D, 0x49, 0xEC, + 0xEA, 0xC6, 0x9E, 0xBE, 0x66, 0xAE, 0xB9, 0xB9, 0x57, 0x65, 0xC9, 0x3D, 0xCF, 0x0D, 0x3E, 0x6D, + 0xE1, 0x3C, 0xDB, 0x26, 0x9F, 0x24, 0x94, 0x7A, 0x1B, 0x7D, 0xC9, 0x68, 0xF9, 0xA1, 0x9B, 0x7D, + 0x8A, 0x7A, 0xC8, 0xFE, 0x15, 0x7A, 0x52, 0x2F, 0xF5, 0x19, 0x73, 0x6E, 0x5B, 0x82, 0x99, 0xF9, + 0x52, 0xAD, 0xB0, 0xAE, 0x43, 0x6C, 0xE8, 0x1F, 0x36, 0xCB, 0x50, 0xBC, 0x54, 0xB6, 0x1D, 0x4B, + 0x8D, 0xE1, 0xA3, 0x6C, 0x76, 0x4A, 0x3A, 0xF0, 0x90, 0x49, 0x16, 0xA6, 0xEC, 0x5A, 0x4A, 0xB9, + 0x8B, 0xB8, 0xCB, 0x0D, 0x3F, 0xA5, 0x9E, 0xED, 0xFC, 0x87, 0xEF, 0x7A, 0x8B, 0x0B, 0x0B, 0x49, + 0xE2, 0x26, 0xAD, 0x4A, 0xBB, 0xBC, 0xCA, 0xBF, 0xFE, 0x6B, 0xA6, 0x4E, 0x40, 0xA3, 0x69, 0xE0, + 0x31, 0x77, 0x5D, 0xE3, 0x6E, 0x48, 0x23, 0x4C, 0x17, 0xA5, 0x98, 0x62, 0x96, 0xA9, 0x0B, 0x4C, + 0x16, 0x68, 0x4F, 0x5C, 0x86, 0x16, 0x95, 0x4F, 0xEB, 0x9A, 0x59, 0x53, 0xEA, 0x88, 0x15, 0x96, + 0xB4, 0x69, 0x77, 0x74, 0xCD, 0x36, 0xE9, 0x22, 0xFB, 0x8A, 0xDC, 0xD9, 0x21, 0xC1, 0xB9, 0x9B, + 0x60, 0x8A, 0x29, 0xEA, 0xB4, 0x09, 0x1F, 0xD2, 0x58, 0x36, 0xA2, 0x3C, 0x17, 0x59, 0x38, 0x08, + 0xF0, 0x89, 0x23, 0x6D, 0xA1, 0x33, 0xA2, 0x27, 0xB6, 0x67, 0x0F, 0x69, 0x70, 0x81, 0x35, 0x33, + 0xC9, 0xA4, 0x18, 0xFC, 0x9B, 0xD7, 0x51, 0x40, 0xEC, 0x91, 0x3B, 0xF4, 0x76, 0x17, 0x46, 0xF4, + 0x3A, 0x5A, 0x80, 0x0F, 0x37, 0x6F, 0x70, 0xFF, 0xE0, 0xF5, 0x2A, 0xFC, 0x82, 0x7F, 0xF4, 0xC1, + 0x90, 0x89, 0x3F, 0x9C, 0x37, 0xAF, 0xF9, 0xA3, 0x94, 0xD1, 0xFD, 0x84, 0xEE, 0x72, 0x8F, 0xE3, + 0xCA, 0xFF, 0xBE, 0x40, 0x5C, 0x67, 0x77, 0x01, 0x09, 0xF2, 0xE5, 0xFC, 0xDE, 0x68, 0xB4, 0x40, + 0xD8, 0x9B, 0xA9, 0xF0, 0xD5, 0x0F, 0xC6, 0x2B, 0xAC, 0xE2, 0x0A, 0x07, 0x95, 0xF8, 0x62, 0x3B, + 0x93, 0x0B, 0x44, 0x04, 0x2E, 0x72, 0x0C, 0x31, 0xCB, 0xFE, 0x70, 0x88, 0xC9, 0x7D, 0x80, 0x9F, + 0x55, 0x24, 0xBB, 0x1A, 0x05, 0xC9, 0x0F, 0xC6, 0xB7, 0x64, 0xB6, 0x11, 0x8C, 0x35, 0xF1, 0x82, + 0xDB, 0xB0, 0x56, 0x4B, 0x12, 0xE5, 0xF7, 0xF1, 0xE8, 0x26, 0x8A, 0x26, 0x85, 0x09, 0xBC, 0xA4, + 0x7A, 0x22, 0x8F, 0xD7, 0xFB, 0x43, 0x9E, 0xC6, 0x0B, 0x67, 0x61, 0x96, 0x65, 0xAC, 0x95, 0xF5, + 0xCE, 0x62, 0x08, 0x96, 0x9D, 0x49, 0xB6, 0x13, 0x22, 0x6C, 0x6C, 0xE0, 0x8F, 0xD1, 0x8C, 0xC4, + 0xD5, 0x02, 0x1A, 0x4E, 0xC0, 0x9D, 0x60, 0x4C, 0x2E, 0x61, 0xC8, 0x8E, 0xC8, 0x59, 0x47, 0xF6, + 0xFB, 0xBF, 0xF0, 0x2C, 0x73, 0xAE, 0x17, 0xF9, 0x6C, 0xF2, 0x7F, 0x51, 0xBD, 0x23, 0xC1, 0xFD, + 0x56, 0x9A, 0x5F, 0x32, 0x99, 0xAA, 0x5A, 0x97, 0xFB, 0x5A, 0x14, 0x28, 0xB7, 0xC8, 0xDE, 0x9A, + 0xD1, 0x6F, 0xFF, 0x2A, 0xB2, 0x5D, 0x50, 0x43, 0xA9, 0xDC, 0xA8, 0xE3, 0xC6, 0x7A, 0xBA, 0x9E, + 0x4B, 0x69, 0x30, 0xB1, 0x82, 0xAE, 0xA2, 0x52, 0x1F, 0x8B, 0x5A, 0x52, 0x0F, 0x27, 0xCD, 0xC2, + 0x5C, 0x75, 0x27, 0xE9, 0x73, 0x58, 0x68, 0xFF, 0xBF, 0x7C, 0x35, 0x97, 0xB3, 0x0D, 0x79, 0x63, + 0x85, 0xF8, 0x82, 0x46, 0x2E, 0x86, 0xB8, 0x82, 0x82, 0x62, 0x8E, 0x5A, 0x16, 0xE7, 0x83, 0xFE, + 0x81, 0x8A, 0x96, 0xD7, 0x13, 0xCB, 0xBB, 0xB2, 0xF8, 0x15, 0x33, 0x45, 0xCE, 0xE9, 0x44, 0x60, + 0xB7, 0xBD, 0x7B, 0x2E, 0xA9, 0xB8, 0x32, 0x3B, 0x72, 0x08, 0x99, 0x6F, 0x7B, 0xCB, 0x85, 0xB6, + 0x42, 0xDC, 0x0E, 0xED, 0x30, 0xC3, 0x26, 0xBE, 0xA0, 0xEB, 0x83, 0x7F, 0xE2, 0x3B, 0x14, 0x84, + 0x3F, 0xC5, 0x41, 0x1C, 0x71, 0xEB, 0x3A, 0x2C, 0x8C, 0xF0, 0xCB, 0x74, 0x7B, 0xDE, 0xB3, 0x6A, + 0xA2, 0x75, 0x99, 0xFA, 0x5F, 0xBE, 0x7F, 0x4D, 0xD7, 0x73, 0x59, 0x25, 0xF9, 0x22, 0x7B, 0x3D, + 0x0F, 0xA5, 0x6D, 0x8E, 0x4D, 0x61, 0x9D, 0x46, 0x63, 0xCA, 0x57, 0xC2, 0xA3, 0xEC, 0x53, 0x04, + 0xB4, 0x42, 0xB3, 0x15, 0x65, 0x2D, 0x6A, 0x37, 0x9B, 0x90, 0xB2, 0xDA, 0x2B, 0x82, 0x34, 0x5B, + 0x38, 0x1A, 0xF3, 0xB2, 0xD2, 0x64, 0x09, 0x31, 0x81, 0xE5, 0x25, 0xB4, 0x2D, 0xC8, 0x86, 0x53, + 0xC0, 0x00, 0xD3, 0xF4, 0xC6, 0x1C, 0x68, 0x3B, 0x8D, 0x35, 0x22, 0x2D, 0xA5, 0x55, 0x9D, 0x6A, + 0xEA, 0xC8, 0x51, 0x18, 0x4E, 0x45, 0xD4, 0xFB, 0xD1, 0xC1, 0x2B, 0xB6, 0xA1, 0x6E, 0xE6, 0xA3, + 0x4E, 0x94, 0xBE, 0x4A, 0xE3, 0x2D, 0x7B, 0xBE, 0xBE, 0xD8, 0xA4, 0x62, 0x9D, 0xAA, 0x66, 0x95, + 0xD7, 0x2D, 0x31, 0xAD, 0x58, 0xA9, 0xB9, 0x79, 0x7D, 0x36, 0xD6, 0x91, 0x35, 0xE3, 0x59, 0x58, + 0xC8, 0x8C, 0x40, 0xEB, 0x5A, 0xC9, 0x9F, 0x16, 0xE3, 0x9F, 0xC2, 0x62, 0xB0, 0xD1, 0xE7, 0x3E, + 0x86, 0xD5, 0x90, 0xFC, 0xBE, 0x03, 0x98, 0x0E, 0xF1, 0x00, 0x22, 0xCD, 0xB4, 0x2A, 0x6E, 0xEC, + 0xA0, 0x33, 0x57, 0x3D, 0x71, 0x27, 0x62, 0x3C, 0x3A, 0x90, 0x0E, 0xD5, 0x38, 0x3B, 0x1E, 0x3B, + 0x51, 0xF9, 0x78, 0xCD, 0x90, 0xF5, 0xE3, 0xBB, 0x40, 0x8D, 0x91, 0x2A, 0x5B, 0x1C, 0x58, 0xCA, + 0x4F, 0x6C, 0xD2, 0xC8, 0x02, 0x1C, 0xA5, 0xEF, 0x78, 0xEA, 0x4E, 0x18, 0x1C, 0x7D, 0xCC, 0x6B, + 0x8D, 0x99, 0x65, 0xC1, 0xFA, 0x62, 0x89, 0x9A, 0x18, 0x3B, 0xA9, 0x2A, 0xD9, 0x4B, 0x19, 0xE7, + 0xAE, 0x99, 0xFB, 0x25, 0xB1, 0x72, 0x4B, 0xCF, 0x0B, 0xA7, 0xC1, 0x28, 0xC2, 0x64, 0x2F, 0xB8, + 0xE6, 0x6B, 0xAD, 0x22, 0x8A, 0x7F, 0x61, 0xEC, 0xB3, 0xBE, 0x92, 0xA5, 0xF9, 0x25, 0x45, 0x8F, + 0xAF, 0xAE, 0xE2, 0x31, 0xEA, 0x9F, 0x6C, 0xC6, 0xCD, 0xAE, 0x23, 0xBA, 0x41, 0x98, 0x47, 0x59, + 0x2B, 0x12, 0xF4, 0x42, 0xA6, 0xE0, 0x69, 0x43, 0xED, 0x4E, 0x7C, 0x32, 0xDB, 0xB9, 0x09, 0xE8, + 0x35, 0x3E, 0x5F, 0x1C, 0x57, 0x8B, 0xEF, 0x73, 0x26, 0xB4, 0x96, 0x97, 0x77, 0xF2, 0x7A, 0x3F, + 0x5E, 0x0B, 0x49, 0x87, 0x4E, 0xE9, 0xD8, 0xAF, 0xDB, 0x4F, 0x79, 0xF9, 0x5A, 0x71, 0xD3, 0x28, + 0xC5, 0xAA, 0x64, 0x6C, 0xF5, 0x32, 0xF9, 0x5A, 0xD3, 0x8A, 0x98, 0xB3, 0x35, 0x1D, 0x5F, 0xF1, + 0x72, 0x25, 0x59, 0x06, 0xA6, 0xD7, 0x14, 0x77, 0x4A, 0x34, 0x9C, 0xAA, 0x99, 0x84, 0xE7, 0xA5, + 0xDF, 0x2F, 0xF2, 0xCE, 0xCC, 0x33, 0xFD, 0x1E, 0x6F, 0xEA, 0x40, 0x7F, 0x33, 0xC6, 0x42, 0x71, + 0x78, 0x9E, 0x99, 0x82, 0x65, 0xCD, 0xD2, 0x77, 0xF0, 0x64, 0xBB, 0x6B, 0x40, 0x6E, 0x7C, 0xF3, + 0xB7, 0xBA, 0x66, 0x7E, 0xCF, 0x28, 0x24, 0x6B, 0x4B, 0x6B, 0xA7, 0xF2, 0x4C, 0x5B, 0x38, 0xD5, + 0x26, 0x8C, 0x94, 0x4F, 0xB0, 0x52, 0xDB, 0x57, 0x57, 0xCF, 0xE9, 0x35, 0xCC, 0xA8, 0x37, 0x3C, + 0x5D, 0x77, 0x12, 0x56, 0x54, 0xB8, 0xDC, 0x54, 0x76, 0x4F, 0x76, 0xB4, 0x2B, 0xA4, 0x3C, 0x73, + 0xB6, 0xA6, 0xF1, 0x52, 0x2E, 0x70, 0xFC, 0xB5, 0x3B, 0x97, 0xF4, 0xDF, 0x1C, 0x53, 0xC3, 0x8C, + 0xDF, 0x9C, 0x51, 0xC3, 0xD5, 0x68, 0x98, 0xEB, 0x87, 0x01, 0x66, 0xA3, 0x6F, 0x93, 0xF8, 0xD7, + 0x0F, 0x30, 0xBD, 0x8F, 0x68, 0xA0, 0x0A, 0x96, 0x61, 0xC9, 0x82, 0x33, 0x0B, 0xD3, 0x06, 0xEB, + 0xC2, 0x13, 0x67, 0xD7, 0x01, 0xE5, 0x87, 0x11, 0x6D, 0x7E, 0x28, 0x51, 0x07, 0xD0, 0xBE, 0xF2, + 0x83, 0x08, 0x00, 0xD9, 0xFF, 0xF3, 0x01, 0x73, 0x92, 0x9C, 0x8F, 0x8A, 0x13, 0x9C, 0x4B, 0xAF, + 0x44, 0x68, 0xF2, 0x88, 0xD3, 0x51, 0xA7, 0xDD, 0x3C, 0xA1, 0xC1, 0x80, 0xDF, 0x8F, 0xE5, 0x65, + 0x9D, 0x11, 0x4B, 0x5D, 0x4D, 0x56, 0x09, 0xFF, 0x33, 0xF2, 0x23, 0xDC, 0x07, 0xFC, 0x33, 0x1E, + 0xED, 0x4B, 0x59, 0xBD, 0x05, 0xDA, 0xB7, 0x76, 0x20, 0x1D, 0xD2, 0x9D, 0xD8, 0xD1, 0x4D, 0x27, + 0xF0, 0xA7, 0xC0, 0x8D, 0x40, 0xBB, 0x94, 0x82, 0x4C, 0xA5, 0xBC, 0xE8, 0x9A, 0x63, 0x6C, 0x80, + 0xC3, 0x41, 0xF7, 0xBF, 0x85, 0x6A, 0x52, 0x87, 0x67, 0x5B, 0x4F, 0xB6, 0x84, 0x05, 0xCB, 0x6F, + 0xF0, 0x65, 0x12, 0x2B, 0xF3, 0xC0, 0x52, 0x3E, 0x9D, 0xD6, 0x59, 0x9A, 0xC0, 0xBD, 0x4D, 0xEE, + 0xF0, 0x0A, 0x96, 0x37, 0xE4, 0x8A, 0x0E, 0xDE, 0x27, 0xD3, 0xEE, 0x7B, 0xE8, 0xA0, 0x71, 0xCB, + 0xF0, 0x68, 0xAE, 0xA6, 0x1D, 0xAA, 0x20, 0xCB, 0xE8, 0xF2, 0xCC, 0xEC, 0x24, 0x49, 0xCD, 0x5E, + 0x26, 0xC8, 0xF8, 0xE0, 0x68, 0x1E, 0x43, 0x9D, 0x7D, 0x4B, 0xCC, 0x39, 0x26, 0x56, 0xE7, 0x47, + 0x13, 0x6F, 0xEF, 0x8F, 0x9C, 0xBA, 0x5C, 0x4B, 0xF2, 0x90, 0x35, 0xBE, 0x91, 0x30, 0xDE, 0xD9, + 0xC0, 0xA4, 0xA3, 0x22, 0x95, 0x47, 0x43, 0x23, 0xA4, 0x7B, 0x88, 0x40, 0x60, 0x4D, 0xD1, 0x46, + 0x03, 0x91, 0x75, 0xF3, 0x2D, 0xCE, 0xA0, 0x8A, 0x6B, 0x93, 0xDE, 0xF3, 0xBF, 0x18, 0x54, 0xCA, + 0x06, 0xCA, 0x4F, 0xC8, 0x12, 0x8C, 0x6A, 0x2C, 0xAA, 0x71, 0x1B, 0x90, 0x1F, 0xE9, 0xE5, 0x40, + 0xC4, 0x6D, 0x4B, 0x8A, 0x31, 0xBB, 0xA2, 0xFC, 0x82, 0xCE, 0xF6, 0xFA, 0x96, 0x69, 0x26, 0x87, + 0xFA, 0x3C, 0x7D, 0x6A, 0x49, 0x93, 0xAA, 0xA4, 0x75, 0x4D, 0x9A, 0x64, 0x4A, 0xC8, 0x5A, 0xDC, + 0xA4, 0xBC, 0x14, 0xAE, 0x43, 0xB9, 0xB8, 0x62, 0x93, 0xA6, 0xCE, 0xA4, 0xA8, 0x31, 0x9F, 0x9C, + 0x1A, 0x8D, 0x99, 0x3A, 0x39, 0x79, 0x17, 0x0B, 0x9A, 0x93, 0x0B, 0x93, 0xE8, 0x9F, 0x63, 0x6E, + 0x50, 0xD7, 0xEA, 0x76, 0x2D, 0x53, 0x8B, 0x9C, 0x9B, 0xC1, 0xE4, 0x10, 0x96, 0x91, 0x81, 0x47, + 0xA3, 0x6C, 0xAB, 0x44, 0xC1, 0xC1, 0x87, 0xFD, 0xB3, 0xE2, 0x26, 0x49, 0x99, 0xD7, 0x8F, 0xCE, + 0x54, 0x16, 0x63, 0xEC, 0x85, 0xCD, 0x93, 0x32, 0xA2, 0x97, 0xC3, 0xCB, 0xFC, 0x43, 0x01, 0x5E, + 0xF6, 0x66, 0x71, 0xCE, 0xAA, 0x37, 0xAC, 0x05, 0xC2, 0xE3, 0xB7, 0x3B, 0xF7, 0xDA, 0x3D, 0xE5, + 0x00, 0x95, 0x1C, 0x48, 0xD7, 0xF9, 0xB7, 0x5D, 0x09, 0xE6, 0xEB, 0x02, 0xF9, 0xD3, 0x9F, 0x48, + 0x52, 0xF6, 0xC7, 0xDD, 0x7E, 0x5F, 0x77, 0x9E, 0x35, 0x7F, 0x4F, 0x26, 0x98, 0xE7, 0xEE, 0xA1, + 0xB0, 0xE5, 0x7A, 0xE8, 0xD1, 0xB1, 0x6E, 0x4B, 0x4E, 0x14, 0x89, 0xB5, 0xA4, 0x45, 0x20, 0x40, + 0xD3, 0x70, 0x6D, 0x20, 0x79, 0x5C, 0xF1, 0xA1, 0x14, 0x2B, 0xD3, 0xBC, 0x27, 0xD6, 0x6F, 0xA7, + 0xF4, 0x2E, 0x4E, 0x15, 0xA5, 0xF4, 0xB3, 0x9E, 0x37, 0xE5, 0x0F, 0x49, 0x62, 0x6A, 0x68, 0xEB, + 0xA2, 0x26, 0x5E, 0x16, 0x0A, 0xA0, 0xAB, 0xF2, 0x49, 0x38, 0xE4, 0x81, 0x15, 0x0B, 0xF1, 0x2B, + 0x1F, 0xFB, 0x82, 0x20, 0x94, 0xE0, 0x33, 0x32, 0xBF, 0xBA, 0xEF, 0x5C, 0x36, 0x31, 0xE0, 0xC5, + 0x6F, 0x3A, 0x9E, 0x44, 0xF7, 0xB2, 0xDA, 0x1A, 0x5C, 0x67, 0x91, 0x5B, 0x6F, 0x5F, 0xE3, 0x3B, + 0x2F, 0x00, 0x51, 0x30, 0x91, 0x4B, 0x1F, 0xF4, 0xC8, 0xC3, 0x6B, 0xCD, 0x30, 0x91, 0xC2, 0x1C, + 0x2A, 0x9A, 0xD4, 0xD2, 0xDE, 0x61, 0x42, 0xFD, 0x10, 0x8F, 0x6E, 0xE0, 0x8E, 0x8F, 0x74, 0x62, + 0x04, 0xCB, 0x51, 0x70, 0x5E, 0xC8, 0x60, 0x1A, 0x04, 0x38, 0xA5, 0xB3, 0xD6, 0x60, 0xCF, 0xB3, + 0xED, 0x99, 0xB3, 0x5F, 0xC3, 0x54, 0xE5, 0x46, 0xA1, 0x98, 0xB8, 0x9A, 0x69, 0x57, 0x81, 0x22, + 0x49, 0xA8, 0xF3, 0xF4, 0x48, 0x62, 0x7E, 0x79, 0x57, 0x06, 0x48, 0x97, 0x08, 0x6D, 0x5C, 0x3E, + 0x68, 0x25, 0x71, 0x40, 0x35, 0x14, 0x2A, 0x7D, 0xA0, 0x5A, 0xB6, 0xF3, 0x7D, 0xA9, 0x13, 0x74, + 0x3B, 0x90, 0xC3, 0x42, 0x06, 0xB4, 0x8D, 0xB5, 0x63, 0x32, 0x68, 0x00, 0x2A, 0x03, 0xB2, 0x9E, + 0x6A, 0xC7, 0x1D, 0xA2, 0xD5, 0xD6, 0xD5, 0x1B, 0xDF, 0x41, 0x89, 0xEF, 0xAD, 0xC8, 0x7B, 0x34, + 0x71, 0x39, 0xDB, 0x40, 0x00, 0x78, 0xB1, 0x27, 0x93, 0x20, 0x5B, 0x32, 0x3E, 0xB1, 0xA2, 0x94, + 0xA7, 0xB7, 0x39, 0x24, 0x7A, 0xC6, 0x47, 0xAF, 0x32, 0x4C, 0x99, 0x9E, 0xBE, 0x62, 0x95, 0x00, + 0xB9, 0x69, 0x6C, 0x2A, 0x4F, 0x37, 0xE5, 0x90, 0x5C, 0xCA, 0xEE, 0x39, 0xB4, 0xF6, 0x11, 0x8E, + 0xA9, 0xBA, 0x60, 0x0B, 0xD5, 0x29, 0x07, 0x3E, 0xB9, 0x2F, 0x52, 0x3A, 0x82, 0x04, 0xA3, 0xC9, + 0x63, 0x3F, 0x04, 0xA6, 0x98, 0x90, 0x85, 0x5F, 0xEC, 0x68, 0xE6, 0x38, 0xA1, 0xF1, 0x0B, 0xAF, + 0xB1, 0x78, 0xAD, 0xFE, 0xAD, 0xB4, 0x2F, 0x97, 0xA6, 0xF4, 0x00, 0xAA, 0x06, 0xCF, 0x76, 0xFC, + 0x4E, 0x3F, 0x5E, 0x1E, 0x9D, 0x5E, 0x1C, 0x9E, 0x9F, 0xC2, 0x1A, 0xB5, 0xB6, 0x39, 0x3A, 0xF5, + 0x71, 0x2B, 0x57, 0x99, 0x53, 0xA4, 0xEC, 0xD1, 0xEE, 0xED, 0x7B, 0x1A, 0x29, 0x46, 0x47, 0x9D, + 0x61, 0x4B, 0xED, 0x92, 0xB6, 0x9F, 0xA8, 0x9A, 0x37, 0x65, 0x4B, 0x33, 0xA7, 0x65, 0xFD, 0xC3, + 0xF3, 0x5F, 0x0E, 0xCF, 0x1B, 0xB4, 0x8B, 0xDB, 0x11, 0x02, 0xFD, 0xCD, 0x7D, 0x00, 0x96, 0xBB, + 0xC4, 0xBE, 0x05, 0x27, 0x96, 0x1F, 0x11, 0x3F, 0xB7, 0xB6, 0xEE, 0x7F, 0x3A, 0x3F, 0x3F, 0x3C, + 0x35, 0xF6, 0x60, 0x6E, 0x23, 0x93, 0x41, 0x0C, 0x53, 0xC9, 0x74, 0x82, 0xF6, 0x9C, 0xA7, 0x63, + 0x7C, 0xE2, 0xB6, 0xC9, 0xD3, 0x94, 0x4E, 0x47, 0xF7, 0xFA, 0x59, 0x34, 0x1F, 0x30, 0x7A, 0xDB, + 0x62, 0x77, 0x5D, 0x14, 0x39, 0xEC, 0x14, 0x22, 0x32, 0x73, 0xA3, 0xBE, 0xD2, 0x85, 0xD8, 0xCF, + 0xF2, 0x56, 0x68, 0xE6, 0x81, 0xA6, 0x02, 0x49, 0xC3, 0x4D, 0xA4, 0x8F, 0x37, 0x89, 0x4E, 0x3B, + 0xBA, 0xD2, 0x2D, 0xD6, 0xF3, 0x71, 0x27, 0x7E, 0x7C, 0xF7, 0x1B, 0x7D, 0x94, 0x4A, 0xE6, 0x2E, + 0xA3, 0xFC, 0xD9, 0x9E, 0x82, 0xF6, 0xBF, 0x17, 0x4F, 0x83, 0xE1, 0x56, 0xD4, 0xB5, 0xD4, 0xBC, + 0x9F, 0x6E, 0x8C, 0xEA, 0xC6, 0x18, 0x5C, 0x05, 0x55, 0x73, 0x1F, 0xDB, 0x51, 0x50, 0xA9, 0x19, + 0xDD, 0x04, 0x8D, 0x21, 0x93, 0x93, 0x30, 0xE4, 0x78, 0xE5, 0x11, 0x27, 0x85, 0xBD, 0xC5, 0xF7, + 0x46, 0xD0, 0x9E, 0x76, 0x5B, 0xB9, 0x6F, 0x3F, 0x1A, 0x59, 0x59, 0x32, 0x5A, 0xEA, 0x18, 0xDB, + 0xE1, 0xF9, 0xF9, 0x47, 0x75, 0x16, 0x7A, 0xA4, 0xA1, 0x55, 0x66, 0xF2, 0x99, 0x35, 0x88, 0xC5, + 0xA0, 0x6A, 0xBD, 0xF2, 0x14, 0xAB, 0xBA, 0x30, 0xF4, 0x23, 0x3B, 0xA6, 0x2E, 0x1E, 0x3A, 0x14, + 0x7B, 0x72, 0xF1, 0x5E, 0x91, 0xD1, 0xD1, 0xCA, 0x93, 0x53, 0xF5, 0xE1, 0xA9, 0x51, 0xE1, 0x9B, + 0x84, 0xFA, 0x83, 0x87, 0x55, 0x4D, 0xB8, 0x86, 0x4C, 0x3A, 0xBA, 0xD0, 0xC9, 0xEC, 0x66, 0x36, + 0x1A, 0xB5, 0x77, 0x55, 0x95, 0x64, 0x11, 0xEF, 0xDD, 0x5B, 0xEA, 0x11, 0x1B, 0x1F, 0xE8, 0x0D, + 0x16, 0x42, 0x91, 0xDF, 0x0C, 0x85, 0x79, 0x8F, 0x13, 0x15, 0x74, 0xB3, 0x17, 0xB9, 0xD7, 0x3C, + 0xCB, 0x18, 0x46, 0xF5, 0x31, 0x13, 0x21, 0x56, 0x98, 0xF8, 0x2D, 0x0D, 0xD8, 0x06, 0x4F, 0x8A, + 0x1C, 0x1C, 0x74, 0x9C, 0xF8, 0x1F, 0xDB, 0x4E, 0xB7, 0xA5, 0x20, 0xF5, 0x18, 0xD7, 0x11, 0xDA, + 0x0A, 0x7C, 0x53, 0x6B, 0x11, 0x69, 0x1E, 0x7A, 0x40, 0x4A, 0x5D, 0xAD, 0xC7, 0x18, 0x93, 0x8A, + 0xD0, 0x7C, 0xF5, 0x35, 0xAE, 0xB0, 0xB3, 0xFF, 0xF1, 0xE3, 0xF9, 0xC1, 0xD1, 0xE9, 0xDE, 0xC5, + 0x21, 0xB8, 0x7F, 0x67, 0x9F, 0x2E, 0x2E, 0x2F, 0x3E, 0x9F, 0xE1, 0xAF, 0xBF, 0xEC, 0x1D, 0x1F, + 0x1D, 0x5C, 0x7E, 0x3A, 0xFD, 0xCB, 0xE9, 0xC7, 0x5F, 0x4F, 0xD3, 0x2D, 0x7B, 0xC7, 0x0E, 0x6F, + 0xA4, 0xFB, 0xF0, 0x89, 0x79, 0xC4, 0x80, 0x7A, 0xC3, 0x77, 0x87, 0x0E, 0xDC, 0xB1, 0x3D, 0x32, + 0x94, 0x70, 0x53, 0xF5, 0xF1, 0xFA, 0x98, 0xB2, 0x57, 0x36, 0xF5, 0xB3, 0x4B, 0x30, 0x1E, 0xE0, + 0x6D, 0x45, 0xF8, 0x98, 0x5B, 0x22, 0x17, 0xFE, 0x66, 0x12, 0xDE, 0xB4, 0x46, 0xF5, 0x22, 0x77, + 0x37, 0x36, 0x9B, 0xAE, 0x86, 0x4C, 0xF0, 0x20, 0xE3, 0x69, 0x98, 0x58, 0xE5, 0x81, 0xED, 0x11, + 0x8A, 0x02, 0x61, 0x26, 0xD3, 0xF5, 0xA0, 0xF3, 0x5D, 0x87, 0xDD, 0x99, 0x0F, 0x45, 0x95, 0x3D, + 0xC2, 0xBF, 0xF1, 0x5A, 0xF8, 0x2C, 0x2D, 0xCB, 0x72, 0xC7, 0x4F, 0x39, 0xC3, 0x36, 0x59, 0x69, + 0x63, 0x34, 0x6D, 0x9B, 0x75, 0x53, 0x47, 0x3D, 0xC9, 0x93, 0x8C, 0x6F, 0x22, 0x78, 0xDD, 0xF4, + 0xAA, 0x97, 0x84, 0x43, 0xC7, 0x1D, 0xBA, 0x51, 0xDA, 0x4D, 0x78, 0x44, 0x9D, 0x77, 0x61, 0x14, + 0x01, 0x54, 0xB1, 0xB1, 0xBB, 0x02, 0x46, 0x79, 0x2D, 0x2F, 0x17, 0xBD, 0x2B, 0x23, 0x93, 0x43, + 0x2C, 0x0B, 0x2B, 0x0B, 0x4B, 0x69, 0x07, 0x2E, 0x2F, 0xB3, 0xB7, 0xAE, 0x46, 0x23, 0x32, 0xF4, + 0x7D, 0xA7, 0x02, 0x34, 0x01, 0xE8, 0xB4, 0x9F, 0x6B, 0x83, 0x77, 0x90, 0xB8, 0xD4, 0xAE, 0x22, + 0x04, 0xF1, 0xCE, 0x4B, 0x23, 0x65, 0x15, 0xA7, 0xDD, 0x6C, 0xC1, 0x06, 0x6A, 0x84, 0x71, 0x3C, + 0xA1, 0xA2, 0x02, 0x2C, 0x6D, 0x82, 0x7A, 0xB4, 0x06, 0xDE, 0x3D, 0x2A, 0xD1, 0xC4, 0x0F, 0x43, + 0x17, 0xA3, 0x7D, 0xB9, 0x56, 0xE0, 0x38, 0x8D, 0xF5, 0x25, 0x1D, 0x92, 0xE9, 0x87, 0x93, 0x93, + 0xCE, 0x98, 0xFF, 0x4B, 0xBF, 0x11, 0xD3, 0xC7, 0x15, 0xD3, 0xC7, 0x93, 0x93, 0x7E, 0xBF, 0x13, + 0xB2, 0x7F, 0x0A, 0x38, 0x31, 0x7C, 0x06, 0x04, 0x2B, 0xE9, 0xE7, 0x17, 0x46, 0x3D, 0x61, 0x77, + 0xD4, 0x66, 0x97, 0xDC, 0xFF, 0xC5, 0x10, 0x68, 0xCF, 0xEF, 0x90, 0x75, 0x18, 0x6D, 0xDB, 0xD6, + 0xDA, 0xDA, 0xFA, 0x4B, 0x96, 0x5D, 0x90, 0xC9, 0xAF, 0x93, 0xC6, 0x5F, 0xA7, 0x23, 0xFE, 0x0D, + 0xE9, 0xCD, 0x83, 0xF0, 0x47, 0x1C, 0x7F, 0x16, 0xCB, 0x78, 0x01, 0x23, 0xAD, 0x47, 0xEC, 0x11, + 0xE6, 0x5C, 0x74, 0x90, 0x11, 0x62, 0x6D, 0x90, 0xDE, 0x46, 0xA7, 0x67, 0xAD, 0x6F, 0x1B, 0x58, + 0x49, 0x6D, 0xD2, 0x1B, 0xB2, 0x36, 0x67, 0x4E, 0x7A, 0x8C, 0x99, 0xB5, 0x94, 0x99, 0x95, 0xAE, + 0xB5, 0xB1, 0xD2, 0xED, 0xAE, 0x58, 0x1B, 0x9D, 0xEE, 0x66, 0xCF, 0xC4, 0x8E, 0xD9, 0xB2, 0xBD, + 0xC1, 0x2B, 0x0C, 0x73, 0x62, 0xED, 0x25, 0xF2, 0x74, 0x4D, 0xEF, 0x68, 0xC0, 0xF9, 0xE9, 0x76, + 0x91, 0x9B, 0xAD, 0xAD, 0xED, 0xED, 0x1E, 0x59, 0x3C, 0xE0, 0x9A, 0x85, 0x55, 0xF8, 0x6F, 0x4B, + 0x09, 0x8F, 0xA9, 0x3B, 0xEB, 0xD1, 0xA1, 0x1D, 0x81, 0xDD, 0xEC, 0xBB, 0x43, 0x4F, 0xF5, 0x1E, + 0xD4, 0xB1, 0x6B, 0xA5, 0x86, 0x23, 0xB5, 0x52, 0x49, 0x31, 0xF7, 0xBB, 0xF0, 0xDA, 0xC0, 0x9E, + 0x64, 0xDC, 0xDA, 0x28, 0x3A, 0x8C, 0xEC, 0x67, 0xE7, 0x58, 0x78, 0xB7, 0x00, 0x8C, 0x17, 0x13, + 0x05, 0x37, 0x1F, 0xE9, 0x4D, 0x22, 0x95, 0x09, 0x35, 0x6C, 0x29, 0xE9, 0xD4, 0x95, 0x15, 0x44, + 0x84, 0x69, 0x42, 0xD3, 0x7E, 0x06, 0x6B, 0x8D, 0x73, 0x26, 0xDF, 0x72, 0x60, 0x6F, 0x78, 0x87, + 0x37, 0x94, 0x5B, 0x70, 0x9E, 0x5D, 0x94, 0x25, 0xDE, 0x10, 0x44, 0x63, 0x32, 0x24, 0x04, 0x3A, + 0xFA, 0x76, 0x9C, 0xAC, 0xC7, 0xDC, 0xD0, 0xE2, 0x9A, 0x4A, 0x9A, 0xE5, 0x92, 0x6F, 0x39, 0xFD, + 0xBA, 0xCB, 0xEE, 0xA6, 0xE0, 0x13, 0x92, 0xB9, 0xE5, 0x9B, 0x4B, 0xB0, 0x20, 0x5B, 0x5D, 0xCD, + 0x8E, 0x78, 0xF9, 0x99, 0xEF, 0xE6, 0x73, 0x35, 0xC7, 0x2B, 0xC5, 0x1C, 0xF0, 0x24, 0x23, 0xEC, + 0x48, 0x89, 0x5F, 0x52, 0x62, 0x07, 0xAD, 0x20, 0x5E, 0x6F, 0x10, 0xDF, 0xFD, 0x4E, 0x1D, 0x06, + 0xD6, 0x4D, 0xE0, 0x7C, 0x12, 0xA1, 0x37, 0x0A, 0x16, 0x61, 0x5F, 0x54, 0x14, 0x12, 0x6A, 0x7E, + 0xF3, 0xDB, 0x92, 0x71, 0xA4, 0x13, 0x5F, 0x5A, 0x6D, 0x65, 0x37, 0x31, 0x55, 0xFC, 0x44, 0x59, + 0xB9, 0x2D, 0xCE, 0x12, 0x15, 0xF3, 0xE4, 0xF8, 0xC5, 0x84, 0x12, 0x32, 0x27, 0x27, 0x72, 0xD4, + 0xDF, 0x3B, 0x17, 0xA6, 0x68, 0x98, 0x5E, 0x94, 0x29, 0x37, 0x9D, 0x98, 0xD9, 0xD5, 0xA9, 0x8F, + 0xD7, 0x8B, 0x6C, 0x02, 0x82, 0xDE, 0x58, 0xE9, 0xEA, 0x3B, 0xFF, 0xB3, 0x8A, 0xFE, 0xF2, 0xF4, + 0xE3, 0xE5, 0xC1, 0xE1, 0xFE, 0xD1, 0xC9, 0xDE, 0xB1, 0xD6, 0x0B, 0x21, 0x85, 0x09, 0xC8, 0xC1, + 0x66, 0x25, 0xFC, 0x68, 0xE2, 0x96, 0xD5, 0x81, 0x2F, 0xAE, 0x38, 0x84, 0x51, 0x64, 0xE9, 0x80, + 0x92, 0x05, 0x2D, 0x83, 0xC4, 0x72, 0xFC, 0x73, 0x22, 0x2F, 0x01, 0x00, 0x22, 0x93, 0x82, 0xEC, + 0x0C, 0xAE, 0x55, 0x4C, 0x6C, 0x39, 0x45, 0xB2, 0x4A, 0x36, 0x61, 0x0A, 0x60, 0x29, 0x03, 0x62, + 0x1A, 0xAB, 0x64, 0x6D, 0x13, 0x73, 0xE5, 0x2C, 0x69, 0x77, 0xDE, 0x95, 0x91, 0x6C, 0xF6, 0x6B, + 0x4C, 0x64, 0xFF, 0x8C, 0xDD, 0x21, 0xBF, 0x83, 0xF9, 0x60, 0x5A, 0x3D, 0x69, 0x43, 0x14, 0x47, + 0xA3, 0x3A, 0x40, 0xD9, 0xF8, 0xCC, 0x1D, 0x7E, 0x1B, 0x38, 0x3A, 0x73, 0x4B, 0xD7, 0x93, 0xB1, + 0xA9, 0xCC, 0xD0, 0xF3, 0x1B, 0x9A, 0x15, 0x07, 0x66, 0x3A, 0x22, 0x15, 0x0D, 0xC9, 0x19, 0x8E, + 0xFA, 0xD0, 0xA8, 0x3B, 0x00, 0x73, 0x87, 0x9F, 0x59, 0x4F, 0x15, 0xD1, 0xB0, 0x38, 0x66, 0x01, + 0x60, 0x40, 0x6C, 0x56, 0xD2, 0xBA, 0x4A, 0xF7, 0xC8, 0xFA, 0xA5, 0x2A, 0x98, 0xA2, 0x4D, 0x5D, + 0xAE, 0x0F, 0x2B, 0x8F, 0xA4, 0x10, 0x97, 0x27, 0x27, 0x97, 0x07, 0x7B, 0xFD, 0x0F, 0x9A, 0x5A, + 0x88, 0x68, 0xAA, 0xD4, 0x6C, 0x89, 0xBB, 0x72, 0x2B, 0xFA, 0x5D, 0xCA, 0x54, 0x07, 0x84, 0x29, + 0x47, 0x48, 0xCC, 0xCE, 0x94, 0x76, 0x58, 0x4E, 0xD7, 0xCA, 0xF5, 0xBB, 0x5F, 0x25, 0x63, 0x9A, + 0xE9, 0xDD, 0x67, 0xD6, 0x59, 0xF9, 0x7D, 0xD5, 0x4B, 0xFA, 0x2A, 0xF6, 0x8E, 0xE7, 0xDE, 0x57, + 0x60, 0xDE, 0x9F, 0x59, 0x77, 0x3D, 0x9B, 0xB9, 0x4F, 0x12, 0x4F, 0x95, 0x29, 0x50, 0x6E, 0x50, + 0x2F, 0x6D, 0x50, 0x76, 0x0E, 0xFC, 0x47, 0x9F, 0xA0, 0xB8, 0x52, 0xA6, 0x1B, 0x38, 0x73, 0xD5, + 0xC9, 0x9D, 0x12, 0x31, 0xA5, 0x06, 0xFC, 0x87, 0x09, 0x40, 0x58, 0x50, 0xF2, 0x78, 0x16, 0xB4, + 0xE2, 0x68, 0x24, 0x3F, 0x8D, 0x67, 0x51, 0x3F, 0xF5, 0x92, 0x7E, 0x22, 0x8F, 0xB3, 0x2E, 0xE1, + 0x06, 0xE2, 0x19, 0x75, 0xD6, 0x73, 0x33, 0x9D, 0xFF, 0xD3, 0xAC, 0xA6, 0xD8, 0xD0, 0x52, 0x4E, + 0x86, 0x0C, 0x08, 0xF8, 0xE1, 0x90, 0xA1, 0x20, 0xC9, 0x1D, 0xB6, 0xBD, 0xA4, 0x25, 0x0E, 0x30, + 0x74, 0x07, 0x3F, 0xF3, 0x49, 0x37, 0xE6, 0xA5, 0x1D, 0x76, 0xDC, 0xD4, 0x4D, 0x2F, 0xD8, 0xB7, + 0x89, 0x3F, 0x8D, 0xF0, 0x0F, 0x5B, 0xEC, 0xDA, 0x03, 0x50, 0xDF, 0x57, 0xF7, 0xE0, 0x71, 0x43, + 0xF9, 0x0A, 0xA4, 0x35, 0xA6, 0x64, 0x41, 0x1B, 0x32, 0x0B, 0x6D, 0x42, 0xA3, 0x81, 0x1C, 0x32, + 0xCC, 0xF8, 0x66, 0x7C, 0x48, 0x7C, 0xB5, 0x4D, 0x2A, 0x63, 0xDE, 0xAF, 0x17, 0x9B, 0x97, 0xD2, + 0x41, 0x23, 0xBF, 0x59, 0x61, 0xD0, 0xB8, 0xEA, 0x2A, 0xB7, 0x64, 0x1C, 0xD6, 0xA9, 0x86, 0xA5, + 0xDF, 0x96, 0x24, 0x31, 0xEB, 0xA7, 0xB5, 0x32, 0x1B, 0xE6, 0xB3, 0xAE, 0x19, 0xD9, 0xBC, 0x94, + 0xD6, 0x3C, 0xB0, 0x6E, 0x9B, 0x11, 0xDB, 0x5C, 0x91, 0xC5, 0xAE, 0xFB, 0x9C, 0x51, 0xF6, 0x3F, + 0x9F, 0xBC, 0xFD, 0x78, 0xCC, 0x90, 0xEA, 0x57, 0x56, 0x46, 0xBE, 0x37, 0x64, 0x59, 0x9A, 0x0E, + 0xE8, 0x30, 0xA0, 0xFA, 0xFE, 0x48, 0xA6, 0x27, 0xB4, 0xAE, 0x85, 0xC5, 0x99, 0x8E, 0xC0, 0x58, + 0x0F, 0x86, 0xEB, 0xA6, 0xB5, 0xA3, 0x65, 0xBE, 0x4C, 0x4A, 0x5F, 0x93, 0x5C, 0xCB, 0xC7, 0x07, + 0xBA, 0x64, 0xBA, 0x14, 0xBD, 0x1A, 0x64, 0x87, 0xED, 0xCB, 0xA5, 0x4C, 0x86, 0xCD, 0x19, 0xBB, + 0x37, 0x8F, 0xB5, 0x64, 0x08, 0x65, 0x44, 0xB8, 0x0C, 0xA3, 0x8A, 0x59, 0x97, 0xB8, 0xEA, 0x4E, + 0xF6, 0xF0, 0x62, 0x4E, 0x8A, 0xD2, 0x88, 0xB9, 0x95, 0xA7, 0xE0, 0x8E, 0xEB, 0x5C, 0x23, 0xFE, + 0xFE, 0xFB, 0xBF, 0x54, 0x06, 0xF1, 0xDB, 0x42, 0x4B, 0x65, 0xB3, 0x09, 0x5E, 0x62, 0x6A, 0xB7, + 0x66, 0x5B, 0xE6, 0xD2, 0xF4, 0xFE, 0x92, 0x3C, 0x80, 0x67, 0x57, 0xC1, 0x39, 0x23, 0x94, 0x56, + 0x55, 0x8F, 0x81, 0x57, 0xEF, 0xF9, 0x39, 0x89, 0x40, 0x72, 0x65, 0x1E, 0x83, 0xEB, 0xC7, 0xC5, + 0xAE, 0xAD, 0x60, 0x97, 0xFE, 0xD1, 0xCD, 0xB0, 0xC2, 0xF3, 0x89, 0x69, 0x6B, 0xBD, 0x0E, 0xCF, + 0x02, 0x41, 0x11, 0xCF, 0x95, 0x27, 0x80, 0xCD, 0xB9, 0x4F, 0x00, 0xF2, 0xE8, 0xAB, 0x39, 0x05, + 0x64, 0x44, 0xF4, 0x44, 0x53, 0x43, 0x66, 0x74, 0xD7, 0x9D, 0x1D, 0x4C, 0x8C, 0xAF, 0x3C, 0x11, + 0xE7, 0x33, 0xCF, 0x1C, 0x26, 0xE6, 0x17, 0xB2, 0x53, 0xCA, 0xBF, 0xB6, 0x5A, 0x8F, 0xD5, 0x86, + 0xA5, 0xC6, 0xD3, 0x93, 0x89, 0x77, 0xF2, 0xD8, 0x82, 0xCF, 0x35, 0xAF, 0x73, 0x52, 0x77, 0xE9, + 0x1A, 0xA6, 0xD1, 0x2C, 0xCC, 0x59, 0x81, 0x66, 0x6C, 0x49, 0x71, 0x3F, 0x3C, 0x71, 0x5B, 0xF4, + 0x89, 0x63, 0xFE, 0x23, 0xBA, 0xA8, 0x41, 0x99, 0x6B, 0x4A, 0x2A, 0x3D, 0x2D, 0xE6, 0x31, 0x0E, + 0x42, 0x1A, 0xE0, 0x93, 0x91, 0x02, 0x66, 0xF5, 0x5F, 0x9D, 0xD5, 0x4E, 0x84, 0x17, 0xAE, 0x07, + 0x4B, 0x3B, 0x44, 0x4D, 0x08, 0x11, 0x9F, 0xEB, 0xC3, 0x92, 0xB8, 0xCD, 0xF3, 0x4F, 0xC2, 0x0A, + 0xF6, 0x26, 0x90, 0x83, 0x24, 0x79, 0xF2, 0xCC, 0x37, 0xB8, 0x6A, 0x8E, 0x2F, 0x56, 0xAD, 0x48, + 0x41, 0x28, 0xF0, 0x59, 0x59, 0xA4, 0x63, 0x35, 0x25, 0xED, 0xA3, 0x48, 0xAD, 0xB9, 0x8C, 0x78, + 0x31, 0x1A, 0x54, 0x29, 0xE7, 0xC8, 0x97, 0x59, 0x92, 0x7C, 0x79, 0x1D, 0xEF, 0x29, 0x2B, 0x77, + 0x81, 0xDA, 0xC6, 0x17, 0x3B, 0x3D, 0x9E, 0xA9, 0x4F, 0xAC, 0xE1, 0xA5, 0xBB, 0xD0, 0xA2, 0x24, + 0x8D, 0x97, 0x2B, 0x58, 0x89, 0x87, 0x77, 0x6E, 0x34, 0xB8, 0x21, 0x45, 0x55, 0x58, 0x78, 0x02, + 0xBD, 0xB6, 0xA7, 0xA3, 0xE8, 0x95, 0x96, 0xEB, 0x9F, 0xF7, 0x44, 0xEB, 0x93, 0xF7, 0xCD, 0xF3, + 0xEF, 0x3C, 0x3D, 0x61, 0xAE, 0xF6, 0xAE, 0xC4, 0x00, 0x2F, 0x25, 0x2F, 0x56, 0x5E, 0xBF, 0xE7, + 0xD0, 0x92, 0xB7, 0x29, 0xE6, 0x4A, 0x10, 0x16, 0x57, 0xB9, 0x24, 0xD3, 0x7D, 0xCF, 0xB9, 0x92, + 0xBC, 0x2C, 0xA2, 0x49, 0x1E, 0x8F, 0x28, 0x9F, 0x8F, 0x73, 0x29, 0xAF, 0x3C, 0x12, 0x65, 0xE6, + 0xBD, 0x14, 0xC8, 0x38, 0xD9, 0x62, 0x9A, 0x7B, 0x7B, 0x8B, 0xE8, 0x2A, 0x9B, 0x5B, 0x8F, 0x40, + 0xB9, 0x5C, 0xD8, 0x2B, 0x8F, 0x43, 0x5E, 0x9F, 0x48, 0x0B, 0x25, 0xFF, 0x18, 0x0D, 0xAF, 0x42, + 0x9B, 0x4B, 0xFF, 0xB1, 0xC4, 0x5E, 0x89, 0x05, 0xDE, 0x03, 0x05, 0x2C, 0x3C, 0xBC, 0xC8, 0xB3, + 0x76, 0x0F, 0x2F, 0xFE, 0x3F, 0x53, 0xDF, 0xB5, 0xEA, 0x6E, 0x9B, 0x00 }; ///main_js //To convert AP-Config\index.html to index_html[], run the Python index_html_zipper.py script in the Tools folder: @@ -1049,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xCE, 0x8D, 0x8E, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0xE9, 0xC3, 0xAA, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From 0271c3d4c81010eef829da257ae803b4df472f6c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Feb 2025 10:25:23 +0000 Subject: [PATCH 222/276] Change fileSize to logFileSize. Use uint64_t throughout --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 19 ++++++++++--------- Firmware/RTK_Everywhere/Tasks.ino | 4 ++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 7c5efed00..6522867e8 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -492,7 +492,7 @@ TaskHandle_t pinBluetoothTaskHandle; // Dummy task to start hardware on an assig volatile bool bluetoothPinned; // This variable is touched by core 0 but checked by core 1. Must be volatile. volatile static int combinedSpaceRemaining; // Overrun indicator -volatile static long fileSize; // Updated with each write +volatile static uint64_t logFileSize; // Updated with each write int bufferOverruns; // Running count of possible data losses since power-on bool zedUartPassed; // Goes true during testing if ESP can communicate with ZED over UART @@ -721,7 +721,7 @@ bool forceSystemStateUpdate; // Set true to avoid update wait uint32_t lastPrintRoverAccuracy; uint32_t lastBaseLEDupdate; // Controls the blinking of the Base LED -uint32_t lastFileReport; // When logging, print file record stats every few seconds +uint32_t lastFileReport = 0; // When logging, print file record stats every few seconds long lastStackReport; // Controls the report rate of stack highwater mark within a task uint32_t lastHeapReport; // Report heap every 1s if option enabled uint32_t lastTaskHeapReport; // Report task heap every 1s if option enabled @@ -731,7 +731,7 @@ uint32_t lastRTCSync; // Time in millis when the RTC was last sync'd bool rtcSyncd; // Set to true when the RTC has been sync'd via TP pulse uint32_t lastPrintPosition; // For periodic display of the position -uint64_t lastLogSize; +uint64_t lastLogSize = 0; bool logIncreasing; // Goes true when log file is greater than lastLogSize or logPosition changes bool reuseLastLog; // Goes true if we have a reset due to software (rather than POR) @@ -1398,18 +1398,19 @@ void logUpdate() // Report file sizes to show recording is working if ((millis() - lastFileReport) > 5000) { - if (fileSize > 0) + if (logFileSize > 0) { lastFileReport = millis(); + if (settings.enablePrintLogFileStatus) { - systemPrintf("Log file size: %ld", fileSize); + systemPrintf("Log file size: %lld", logFileSize); if ((systemTime_minutes - startLogTime_minutes) < settings.maxLogTime_minutes) { // Calculate generation and write speeds every 5 seconds - uint32_t fileSizeDelta = fileSize - lastLogSize; - systemPrintf(" - Generation rate: %0.1fkB/s", fileSizeDelta / 5.0 / 1000.0); + uint64_t fileSizeDelta = logFileSize - lastLogSize; + systemPrintf(" - Generation rate: %0.1fkB/s", ((float)fileSizeDelta) / 5.0 / 1000.0); } else { @@ -1419,9 +1420,9 @@ void logUpdate() systemPrintln(); } - if (fileSize > lastLogSize) + if (logFileSize > lastLogSize) { - lastLogSize = fileSize; + lastLogSize = logFileSize; logIncreasing = true; } else diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index e387bc96d..8a958b169 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -1282,7 +1282,7 @@ void handleGnssDataTask(void *e) systemPrintf("SD %d bytes written to log file\r\n", bytesToSend); } - fileSize = logFile->fileSize(); // Update file size + logFileSize = logFile->fileSize(); // Update file size sdFreeSpace -= bytesToSend; // Update remaining space on SD @@ -1310,7 +1310,7 @@ void handleGnssDataTask(void *e) if (endTime - startTime > 150) systemPrintf("Long Write! Time: %ld ms / Location: %ld / Recorded %d bytes / " "spaceRemaining %d bytes\r\n", - endTime - startTime, fileSize, bytesToSend, combinedSpaceRemaining); + endTime - startTime, logFileSize, bytesToSend, combinedSpaceRemaining); } xSemaphoreGive(sdCardSemaphore); From 412e6afa8c30b27f6a2a69a0d8d52bb819ff76d2 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Feb 2025 10:26:20 +0000 Subject: [PATCH 223/276] Change fileSize to fileSizeStr in printFileList (only) --- Firmware/RTK_Everywhere/menuSystem.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/menuSystem.ino b/Firmware/RTK_Everywhere/menuSystem.ino index 2627e52eb..870bb0337 100644 --- a/Firmware/RTK_Everywhere/menuSystem.ino +++ b/Firmware/RTK_Everywhere/menuSystem.ino @@ -1552,9 +1552,9 @@ void printFileList() ); char fileSizeChar[20]; - String fileSize; - stringHumanReadableSize(fileSize, tempFile.fileSize()); - fileSize.toCharArray(fileSizeChar, sizeof(fileSizeChar)); + String fileSizeStr; + stringHumanReadableSize(fileSizeStr, tempFile.fileSize()); + fileSizeStr.toCharArray(fileSizeChar, sizeof(fileSizeChar)); char fileName[50]; // Handle long file names tempFile.getName(fileName, sizeof(fileName)); From a16d1c9511d3a678ecb1cb5b9c3f748988f0ace4 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Feb 2025 10:29:10 +0000 Subject: [PATCH 224/276] Initialize lastFileReport to avoid possible immediate timeout --- Firmware/RTK_Everywhere/menuMessages.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/menuMessages.ino b/Firmware/RTK_Everywhere/menuMessages.ino index f838fb3e7..ae8a0e2ae 100644 --- a/Firmware/RTK_Everywhere/menuMessages.ino +++ b/Firmware/RTK_Everywhere/menuMessages.ino @@ -281,8 +281,9 @@ bool beginLogging(const char *customFileName) return(false); } - fileSize = 0; + logFileSize = 0; lastLogSize = 0; // Reset counter - used for displaying active logging icon + lastFileReport = millis(); // Fake last file report to avoid an immediate timeout bufferOverruns = 0; // Reset counter From 4bd762137720078c4b56217028ff518c9575bc01 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Feb 2025 10:45:48 +0000 Subject: [PATCH 225/276] Allow more time for ZED factoryDefault (and saveConfiguration) --- Firmware/RTK_Everywhere/GNSS_ZED.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.ino b/Firmware/RTK_Everywhere/GNSS_ZED.ino index 604d454bc..06cc83ea7 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.ino +++ b/Firmware/RTK_Everywhere/GNSS_ZED.ino @@ -893,7 +893,8 @@ void GNSS_ZED::factoryReset() if (online.gnss) { _zed->factoryDefault(); // Reset everything: baud rate, I2C address, update rate, everything. And save to BBR. - _zed->saveConfiguration(); + delay(3000); // Allow time for CFG-CFG to be applied + _zed->saveConfiguration(); // Save to Flash and BBR _zed->hardReset(); // Perform a reset leading to a cold start (zero info start-up) } } From 3b72457e172b3f36e745b3b67b6ba743146d7788 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Feb 2025 14:23:28 +0000 Subject: [PATCH 226/276] Add DEBUG_NEARLY_EVERYTHING --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 58 +++++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 6522867e8..adf965f53 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -866,7 +866,6 @@ volatile bool deadManWalking; deadManWalking = true; \ \ /* Output as much as possible to identify the location of the failure */ \ - settings.debugGnss = true; \ settings.enableHeapReport = true; \ settings.enableTaskReports = true; \ settings.enablePrintPosition = true; \ @@ -883,16 +882,26 @@ volatile bool deadManWalking; settings.enablePrintSDBuffers = true; \ settings.periodicDisplay = (PeriodicDisplay_t) - 1; \ settings.enablePrintEthernetDiag = true; \ - settings.debugWifiState = true; \ + settings.debugCorrections = true; \ + settings.debugGnss = true; \ + settings.debugHttpClientData = true; \ + settings.debugHttpClientState = true; \ + settings.debugLora = true; \ + settings.debugMqttClientData = true; \ + settings.debugMqttClientState = true; \ settings.debugNetworkLayer = true; \ settings.printNetworkStatus = true; \ settings.debugNtripClientRtcm = true; \ settings.debugNtripClientState = true; \ settings.debugNtripServerRtcm = true; \ settings.debugNtripServerState = true; \ + settings.debugPpCertificate = true; \ + settings.debugSettings = true; \ settings.debugTcpClient = true; \ settings.debugTcpServer = true; \ settings.debugUdpServer = true; \ + settings.debugWebServer = true; \ + settings.debugWifiState = true; \ settings.printBootTimes = true; \ } @@ -919,6 +928,49 @@ volatile bool deadManWalking; #endif // 0 +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// Debug nearly everything. Include DEBUG_NEARLY_EVERYTHING in the setup after loadSettings to print many things. +// Similar but less verbose than DEAD_MAN_WALKING +// If the updated settings are saved to NVM, you will need to do a factory reset to clear them +#define DEBUG_NEARLY_EVERYTHING \ + { \ + \ + /* Turn on nearly all the debug prints */ \ + settings.enableHeapReport = true; \ + settings.enablePrintPosition = true; \ + settings.enablePrintIdleTime = true; \ + settings.enablePrintBatteryMessages = true; \ + settings.enablePrintRoverAccuracy = true; \ + settings.enablePrintLogFileMessages = false; \ + settings.enablePrintLogFileStatus = true; \ + settings.enablePrintStates = true; \ + settings.enablePrintDuplicateStates = true; \ + settings.enablePrintRtcSync = true; \ + settings.enablePrintBufferOverrun = true; \ + settings.enablePrintEthernetDiag = true; \ + settings.debugCorrections = true; \ + settings.debugGnss = false; \ + settings.debugHttpClientData = true; \ + settings.debugHttpClientState = true; \ + settings.debugLora = true; \ + settings.debugMqttClientData = true; \ + settings.debugMqttClientState = true; \ + settings.debugNetworkLayer = true; \ + settings.printNetworkStatus = true; \ + settings.debugNtripClientRtcm = true; \ + settings.debugNtripClientState = true; \ + settings.debugNtripServerRtcm = true; \ + settings.debugNtripServerState = true; \ + settings.debugPpCertificate = true; \ + settings.debugSettings = true; \ + settings.debugTcpClient = true; \ + settings.debugTcpServer = true; \ + settings.debugUdpServer = true; \ + settings.debugWebServer = true; \ + settings.debugWifiState = true; \ + settings.printBootTimes = true; \ + } + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- /* +---------------------------------------+ +----------+ @@ -1081,6 +1133,8 @@ void setup() DMW_b("loadSettings"); loadSettings(); // Attempt to load settings after SD is started so we can read the settings file if available + //DEBUG_NEARLY_EVERYTHING // Debug nearly all the things + DMW_b("checkArrayDefaults"); checkArrayDefaults(); // Check for uninitialized arrays that won't be initialized by gnssConfigure // (checkGNSSArrayDefaults) From eed5bcf410576e6ccc7369be79d857d61e34bbc5 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Feb 2025 14:24:16 +0000 Subject: [PATCH 227/276] Better debug prints during factory reset --- Firmware/RTK_Everywhere/menuMain.ino | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 14b659935..88f083dbb 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -505,9 +505,13 @@ void factoryReset(bool alreadyHasSemaphore) // An error occurs when a settings file is on the microSD card and it is not // deleted, as such the settings on the microSD card will be loaded when the // RTK reboots, resulting in failure to achieve the factory reset condition - log_d("sdCardSemaphore failed to yield, held by %s, menuMain.ino line %d\r\n", semaphoreHolder, __LINE__); + systemPrintf("sdCardSemaphore failed to yield, held by %s, menuMain.ino line %d\r\n", semaphoreHolder, __LINE__); } } + else + { + systemPrintln("microSD not online. Unable to delete settings files..."); + } tiltSensorFactoryReset(); @@ -515,8 +519,13 @@ void factoryReset(bool alreadyHasSemaphore) LittleFS.format(); if (online.gnss == true) + { + systemPrintln("Resetting the GNSS to factory defaults. This could take a few seconds..."); gnss->factoryReset(); - + } + else + systemPrintln("GNSS not online. Unable to factoryReset..."); + systemPrintln("Settings erased successfully. Rebooting. Goodbye!"); delay(2000); ESP.restart(); From 00da22cd5aa39b93c36b46daf5abe74e25cc8352 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 11 Feb 2025 14:41:52 +0000 Subject: [PATCH 228/276] ZED : use the 13-byte cfgCfg to perform factoryDefault The 12-byte version --- Firmware/RTK_Everywhere/GNSS_ZED.ino | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.ino b/Firmware/RTK_Everywhere/GNSS_ZED.ino index 06cc83ea7..ef5b767f9 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.ino +++ b/Firmware/RTK_Everywhere/GNSS_ZED.ino @@ -892,9 +892,16 @@ void GNSS_ZED::factoryReset() { if (online.gnss) { - _zed->factoryDefault(); // Reset everything: baud rate, I2C address, update rate, everything. And save to BBR. - delay(3000); // Allow time for CFG-CFG to be applied - _zed->saveConfiguration(); // Save to Flash and BBR + // Set the clearMask and loadMask to 0xFFFF. Set deviceMask to devBBR | devFlash + uint8_t clearAndLoadMask[] = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0x03 }; + _zed->cfgCfg(clearAndLoadMask, 13); + + delay(2000); + + // Set the saveMask to 0xFFFF. Set deviceMask to devBBR | devFlash + uint8_t saveMask[] = { 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0x03 }; + _zed->cfgCfg(saveMask, 13); + _zed->hardReset(); // Perform a reset leading to a cold start (zero info start-up) } } From 5c51a599db5d30c76925cad51ab9786c64299851 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 11 Feb 2025 08:21:47 -0700 Subject: [PATCH 229/276] Suppress GST patch unless we are in RTK Fix/Float. --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index baac17c51..21873b40d 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -2233,6 +2233,10 @@ void lg290pModifyGst(char *nmeaSentence, uint16_t *sentenceLength) if (online.gnss == false) return; + // Only apply the GST patch if our HPA is very small (<0.1m), ie RTK Float or Fix. + if (gnss->isRTKFix() == false && gnss->isRTKFloat() == false) + return; + GNSS_LG290P *lg290p = (GNSS_LG290P *)gnss; // Identify sentence type From 76a6d585c945659c849acce85d6bb1daa4c03ce8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 11 Feb 2025 15:23:57 +0000 Subject: [PATCH 230/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index 83bdb6aa8..82b363187 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xE9, 0xC3, 0xAA, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0x8C, 0x6B, 0xAB, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -1049,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xE9, 0xC3, 0xAA, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0x8C, 0x6B, 0xAB, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From ac9554d9b543a2d146bf3a745b9c0445f489623b Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 12 Feb 2025 14:09:32 +0000 Subject: [PATCH 231/276] Remove settings.updateGNSSSettings. Also: Remove firstPowerOn (on ZED) Add missing ZED saveConfiguration --- Firmware/RTK_Everywhere/Display.ino | 2 - Firmware/RTK_Everywhere/GNSS_LG290P.ino | 24 +------- Firmware/RTK_Everywhere/GNSS_Mosaic.h | 8 +++ Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 40 +------------ Firmware/RTK_Everywhere/GNSS_UM980.ino | 24 +------- Firmware/RTK_Everywhere/GNSS_ZED.h | 2 +- Firmware/RTK_Everywhere/GNSS_ZED.ino | 67 +++++++--------------- Firmware/RTK_Everywhere/NTP.ino | 10 ---- Firmware/RTK_Everywhere/NVM.ino | 3 - Firmware/RTK_Everywhere/RTK_Everywhere.ino | 30 +++++----- Firmware/RTK_Everywhere/States.ino | 7 --- Firmware/RTK_Everywhere/menuMain.ino | 15 +++-- Firmware/RTK_Everywhere/menuPorts.ino | 1 - Firmware/RTK_Everywhere/settings.h | 2 - 14 files changed, 62 insertions(+), 173 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index a84e9166c..de535c6a9 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -2366,8 +2366,6 @@ void paintProfile(uint8_t profileUnit) if (profileNumber >= 0) { - settings.updateGNSSSettings = - true; // When this profile is loaded next, force system to update GNSS settings. recordSystemSettings(); // Before switching, we need to record the current settings to LittleFS and SD recordProfileNumber( diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index 21873b40d..8170d660c 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -165,13 +165,6 @@ bool GNSS_LG290P::checkPPPRates() //---------------------------------------- bool GNSS_LG290P::configureGNSS() { - // Skip configuring the GNSS receiver if no new changes are necessary - if (settings.updateGNSSSettings == false) - { - systemPrintln("LG290P configuration maintained"); - return (true); - } - for (int x = 0; x < 3; x++) { // Wait up to 5 seconds for device to come online @@ -255,10 +248,7 @@ bool GNSS_LG290P::configureOnce() systemPrintln("LG290P configuration updated"); // Save the current configuration into non-volatile memory (NVM) - // We don't need to re-configure the LG290P at next boot - bool settingsWereSaved = saveConfiguration(); - if (settingsWereSaved) - settings.updateGNSSSettings = false; + saveConfiguration(); } else online.gnss = false; // Take it offline @@ -324,10 +314,7 @@ bool GNSS_LG290P::configureRover() else { // Save the current configuration into non-volatile memory (NVM) - // We don't need to re-configure the LG290P at next boot - bool settingsWereSaved = saveConfiguration(); - if (settingsWereSaved) - settings.updateGNSSSettings = false; + saveConfiguration(); // For RTCM and MSM messages to take effect (ie, PointPerfect is active) we must save/reset softwareReset(); @@ -414,10 +401,7 @@ bool GNSS_LG290P::configureBase() else { // Save the current configuration into non-volatile memory (NVM) - // We don't need to re-configure the LG290P at next boot - bool settingsWereSaved = saveConfiguration(); - if (settingsWereSaved) - settings.updateGNSSSettings = false; + saveConfiguration(); softwareReset(); @@ -1757,8 +1741,6 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message printUnknown(incoming); } - settings.updateGNSSSettings = true; // Update the GNSS config at the next boot - clearBuffer(); // Empty buffer of any newline chars } diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.h b/Firmware/RTK_Everywhere/GNSS_Mosaic.h index 62be6a599..95bffeb7b 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.h +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.h @@ -549,6 +549,14 @@ bool mosaicX5waitCR(unsigned long timeout = 25); // Header class GNSS_MOSAIC : GNSS { + // The mosaic-X5 does not have self-contained interface library. + // But the ZED-F9P, UM980 and LG290P all do. + // On the X5, we communicate manually over serial2GNSS using functions like + // sendWithResponse and sendAndWaitForIdle. + // In essence, the interface library is wholly contained in this class. + // TODO: consider breaking the mosaic comms functions out into their own library + // and add a private library class instance here. + protected: // These globals are updated regularly via the SBF parser diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 5d0e0b473..8439708dc 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -314,13 +314,6 @@ bool GNSS_MOSAIC::beginExternalEvent() if (online.gnss == false) return (false); - // If our settings haven't changed, trust GNSS's settings - if (settings.updateGNSSSettings == false) - { - systemPrintln("Skipping mosaic-X5 event configuration"); - return (true); - } - if (settings.dataPortChannel != MUX_PPS_EVENTTRIGGER) return (true); // No need to configure PPS if port is not selected @@ -344,13 +337,6 @@ bool GNSS_MOSAIC::beginPPS() if (online.gnss == false) return (false); - // If our settings haven't changed, trust GNSS's settings - if (settings.updateGNSSSettings == false) - { - systemPrintln("Skipping mosaicX5BeginPPS"); - return (true); - } - if (settings.dataPortChannel != MUX_PPS_EVENTTRIGGER) return (true); // No need to configure PPS if port is not selected @@ -435,10 +421,7 @@ bool GNSS_MOSAIC::configureBase() setLoggingType(); // Update Standard, PPP, or custom for icon selection // Save the current configuration into non-volatile memory (NVM) - // We don't need to re-configure the MOSAICX5 at next boot - bool settingsWereSaved = saveConfiguration(); - if (settingsWereSaved) - settings.updateGNSSSettings = false; + saveConfiguration(); if (response == false) { @@ -606,10 +589,7 @@ bool GNSS_MOSAIC::configureOnce() systemPrintln("mosaic-X5 configuration updated"); // Save the current configuration into non-volatile memory (NVM) - // We don't need to re-configure the MOSAICX5 at next boot - bool settingsWereSaved = saveConfiguration(); - if (settingsWereSaved) - settings.updateGNSSSettings = false; + saveConfiguration(); } else online.gnss = false; // Take it offline @@ -625,13 +605,6 @@ bool GNSS_MOSAIC::configureOnce() //---------------------------------------- bool GNSS_MOSAIC::configureGNSS() { - // Skip configuring the MOSAICX5 if no new changes are necessary - if (settings.updateGNSSSettings == false) - { - systemPrintln("mosaic-X5 configuration maintained"); - return (true); - } - // Attempt 3 tries on MOSAICX5 config for (int x = 0; x < 3; x++) { @@ -679,10 +652,7 @@ bool GNSS_MOSAIC::configureRover() setLoggingType(); // Update Standard, PPP, or custom for icon selection // Save the current configuration into non-volatile memory (NVM) - // We don't need to re-configure the MOSAICX5 at next boot - bool settingsWereSaved = saveConfiguration(); - if (settingsWereSaved) - settings.updateGNSSSettings = false; + saveConfiguration(); if (response == false) { @@ -1727,8 +1697,6 @@ void GNSS_MOSAIC::menuMessagesNMEA() printUnknown(incoming); } - settings.updateGNSSSettings = true; // Update the GNSS config at the next boot - clearBuffer(); // Empty buffer of any newline chars } @@ -1798,8 +1766,6 @@ void GNSS_MOSAIC::menuMessagesRTCM(bool rover) printUnknown(incoming); } - settings.updateGNSSSettings = true; // Update the GNSS config at the next boot - clearBuffer(); // Empty buffer of any newline chars } diff --git a/Firmware/RTK_Everywhere/GNSS_UM980.ino b/Firmware/RTK_Everywhere/GNSS_UM980.ino index 724a4029b..4f274700d 100644 --- a/Firmware/RTK_Everywhere/GNSS_UM980.ino +++ b/Firmware/RTK_Everywhere/GNSS_UM980.ino @@ -186,10 +186,7 @@ bool GNSS_UM980::configureBase() response &= enableNMEA(); // Save the current configuration into non-volatile memory (NVM) - // We don't need to re-configure the UM980 at next boot - bool settingsWereSaved = _um980->saveConfiguration(); - if (settingsWereSaved) - settings.updateGNSSSettings = false; + _um980->saveConfiguration(); if (response == false) { @@ -269,10 +266,7 @@ bool GNSS_UM980::configureOnce() systemPrintln("UM980 configuration updated"); // Save the current configuration into non-volatile memory (NVM) - // We don't need to re-configure the UM980 at next boot - bool settingsWereSaved = _um980->saveConfiguration(); - if (settingsWereSaved) - settings.updateGNSSSettings = false; + _um980->saveConfiguration(); } else online.gnss = false; // Take it offline @@ -294,13 +288,6 @@ bool GNSS_UM980::configureNtpMode() //---------------------------------------- bool GNSS_UM980::configureGNSS() { - // Skip configuring the UM980 if no new changes are necessary - if (settings.updateGNSSSettings == false) - { - systemPrintln("UM980 configuration maintained"); - return (true); - } - for (int x = 0; x < 3; x++) { if (configureOnce()) @@ -368,10 +355,7 @@ bool GNSS_UM980::configureRover() response &= enableNMEA(); // Save the current configuration into non-volatile memory (NVM) - // We don't need to re-configure the UM980 at next boot - bool settingsWereSaved = _um980->saveConfiguration(); - if (settingsWereSaved) - settings.updateGNSSSettings = false; + _um980->saveConfiguration(); if (response == false) { @@ -1423,8 +1407,6 @@ void GNSS_UM980::menuMessagesSubtype(float *localMessageRate, const char *messag printUnknown(incoming); } - settings.updateGNSSSettings = true; // Update the GNSS config at the next boot - clearBuffer(); // Empty buffer of any newline chars } diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.h b/Firmware/RTK_Everywhere/GNSS_ZED.h index 53090bbe5..584469238 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.h +++ b/Firmware/RTK_Everywhere/GNSS_ZED.h @@ -365,7 +365,7 @@ class GNSS_ZED : GNSS // one core? bool iAmLocked = false; - SFE_UBLOX_GNSS_SUPER *_zed = nullptr; // Don't instantiate until we know what gnssPlatform we're on + SFE_UBLOX_GNSS_SUPER *_zed = nullptr; // Library class instance // Record rxBytes so we can tell if Radio Ext (COM2) is receiving correction data. // On the mosaic, we know that InputLink will arrive at 1Hz. But on the ZED, UBX-MON-COMMS diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.ino b/Firmware/RTK_Everywhere/GNSS_ZED.ino index ef5b767f9..f4a8601b2 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.ino +++ b/Firmware/RTK_Everywhere/GNSS_ZED.ino @@ -229,13 +229,6 @@ bool GNSS_ZED::beginExternalEvent() if (online.gnss == false) return (false); - // If our settings haven't changed, trust ZED's settings - if (settings.updateGNSSSettings == false) - { - log_d("Skipping ZED Trigger configuration"); - return (true); - } - if (settings.dataPortChannel != MUX_PPS_EVENTTRIGGER) return (true); // No need to configure PPS if port is not selected @@ -260,13 +253,6 @@ bool GNSS_ZED::beginPPS() if (online.gnss == false) return (false); - // If our settings haven't changed, trust ZED's settings - if (settings.updateGNSSSettings == false) - { - systemPrintln("Skipping ZED Trigger configuration"); - return (true); - } - if (settings.dataPortChannel != MUX_PPS_EVENTTRIGGER) return (true); // No need to configure PPS if port is not selected @@ -327,16 +313,6 @@ bool GNSS_ZED::configureBase() if (online.gnss == false) return (false); - // If our settings haven't changed, and this is first config since power on, trust ZED's settings - if (settings.updateGNSSSettings == false && firstPowerOn) - { - firstPowerOn = false; // Next time user switches modes, new settings will be applied - log_d("Skipping ZED Base configuration"); - return (true); - } - - firstPowerOn = false; // If we switch between rover/base in the future, force config of module. - update(); // Regularly poll to get latest data _zed->setNMEAGPGGAcallbackPtr( @@ -418,6 +394,9 @@ bool GNSS_ZED::configureBase() if (!success) systemPrintln("Base config fail"); + else + // Save the current configuration into non-volatile memory (NVM) + saveConfiguration(); return (success); } @@ -499,6 +478,9 @@ bool GNSS_ZED::configureNtpMode() if (!success) systemPrintln("NTP config fail"); + else + // Save the current configuration into non-volatile memory (NVM) + saveConfiguration(); return (success); } @@ -514,6 +496,7 @@ bool GNSS_ZED::configureGNSS() return (false); bool response = true; + bool success = true; // Turn on/off debug messages if (settings.debugGnss) @@ -525,7 +508,7 @@ bool GNSS_ZED::configureGNSS() // Redundant - also done by gnssConfigure // checkGNSSArrayDefaults(); - // Always configure the callbacks - even if settings.updateGNSSSettings is false + // Configure the callbacks response &= _zed->setAutoPVTcallbackPtr(&storePVTdata); // Enable automatic NAV PVT messages with callback to storePVTdata @@ -562,17 +545,9 @@ bool GNSS_ZED::configureGNSS() { systemPrintln("GNSS initial configuration (callbacks, short detection, radio port) failed"); } + success &= response; response = true; // Reset - // Configuring the ZED can take more than 2000ms. We save configuration to - // ZED so there is no need to update settings unless user has modified - // the settings file or internal settings. - if (settings.updateGNSSSettings == false) - { - systemPrintln("ZED-F9x configuration maintained"); - return (true); - } - // Wait for initial report from module int maxWait = 2000; startTime = millis(); @@ -691,18 +666,21 @@ bool GNSS_ZED::configureGNSS() if (response == false) systemPrintln("Module failed config block 0"); + success &= response; response = true; // Reset // Enable the constellations the user has set response &= setConstellations(); // 19 messages. Send newCfg or sendCfg with value set if (response == false) systemPrintln("Module failed config block 1"); + success &= response; response = true; // Reset // Make sure the appropriate messages are enabled response &= setMessages(MAX_SET_MESSAGES_RETRIES); // Does a complete open/closed val set if (response == false) systemPrintln("Module failed config block 2"); + success &= response; response = true; // Reset // Disable NMEA messages on all but UART1 @@ -737,10 +715,14 @@ bool GNSS_ZED::configureGNSS() if (response == false) systemPrintln("Module failed config block 3"); - if (response) + if (success) + { systemPrintln("ZED-F9x configuration update"); + // Save the current configuration into non-volatile memory (NVM) + saveConfiguration(); + } - return (response); + return (success); } //---------------------------------------- @@ -754,16 +736,6 @@ bool GNSS_ZED::configureRover() return (false); } - // If our settings haven't changed, and this is first config since power on, trust GNSS's settings - if (settings.updateGNSSSettings == false && firstPowerOn) - { - firstPowerOn = false; // Next time user switches modes, new settings will be applied - log_d("Skipping ZED Rover configuration"); - return (true); - } - - firstPowerOn = false; // If we switch between rover/base in the future, force config of module. - update(); // Regularly poll to get latest data bool success = false; @@ -831,6 +803,9 @@ bool GNSS_ZED::configureRover() if (!success) systemPrintln("Rover config fail"); + else + // Save the current configuration into non-volatile memory (NVM) + saveConfiguration(); return (success); } diff --git a/Firmware/RTK_Everywhere/NTP.ino b/Firmware/RTK_Everywhere/NTP.ino index e03d0a217..e35da17dd 100644 --- a/Firmware/RTK_Everywhere/NTP.ino +++ b/Firmware/RTK_Everywhere/NTP.ino @@ -700,16 +700,6 @@ bool configureUbloxModuleNTP() if (online.gnss == false) return (false); - // If our settings haven't changed, and this is first config since power on, trust GNSS's settings - // Unless this is an EVK - where the GNSS has no battery-backed RAM - if ((productVariant != RTK_EVK) && (settings.updateGNSSSettings == false) && (firstPowerOn == true)) - { - firstPowerOn = false; // Next time user switches modes, new settings will be applied - log_d("Skipping ZED NTP configuration"); - return (true); - } - firstPowerOn = false; // If we switch between rover/base in the future, force config of module. - gnss->update(); // Regularly poll to get latest data return gnss->configureNtpMode(); } diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index 9ec2b9d01..0532a9e85 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -1574,14 +1574,12 @@ void loadProfileNumber() else { log_d("profileNumber.txt not found"); - settings.updateGNSSSettings = true; // Force module update recordProfileNumber(0); // Record profile } } else { log_d("profileNumber.txt not found"); - settings.updateGNSSSettings = true; // Force module update recordProfileNumber(0); // Record profile } @@ -1589,7 +1587,6 @@ void loadProfileNumber() if (profileNumber >= MAX_PROFILE_COUNT) { log_d("ProfileNumber invalid. Going to zero."); - settings.updateGNSSSettings = true; // Force module update recordProfileNumber(0); // Record profile } diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index adf965f53..0d1364ac5 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -754,7 +754,6 @@ uint32_t triggerTowMsR; // Global copy - Time Of Week of rising edge (ms) uint32_t triggerTowSubMsR; // Global copy - Millisecond fraction of Time Of Week of rising edge in nanoseconds uint32_t triggerAccEst; // Global copy - Accuracy estimate in nanoseconds -bool firstPowerOn = true; // After boot, apply new settings to GNSS if the user switches between base or rover unsigned long splashStart; // Controls how long the splash is displayed for. Currently min of 2s. bool restartBase; // If the user modifies any NTRIP Server settings, we need to restart the base bool restartRover; // If the user modifies any NTRIP Client or PointPerfect settings, we need to restart the rover @@ -936,18 +935,6 @@ volatile bool deadManWalking; { \ \ /* Turn on nearly all the debug prints */ \ - settings.enableHeapReport = true; \ - settings.enablePrintPosition = true; \ - settings.enablePrintIdleTime = true; \ - settings.enablePrintBatteryMessages = true; \ - settings.enablePrintRoverAccuracy = true; \ - settings.enablePrintLogFileMessages = false; \ - settings.enablePrintLogFileStatus = true; \ - settings.enablePrintStates = true; \ - settings.enablePrintDuplicateStates = true; \ - settings.enablePrintRtcSync = true; \ - settings.enablePrintBufferOverrun = true; \ - settings.enablePrintEthernetDiag = true; \ settings.debugCorrections = true; \ settings.debugGnss = false; \ settings.debugHttpClientData = true; \ @@ -956,7 +943,6 @@ volatile bool deadManWalking; settings.debugMqttClientData = true; \ settings.debugMqttClientState = true; \ settings.debugNetworkLayer = true; \ - settings.printNetworkStatus = true; \ settings.debugNtripClientRtcm = true; \ settings.debugNtripClientState = true; \ settings.debugNtripServerRtcm = true; \ @@ -968,7 +954,23 @@ volatile bool deadManWalking; settings.debugUdpServer = true; \ settings.debugWebServer = true; \ settings.debugWifiState = true; \ + settings.enableHeapReport = true; \ + settings.enablePrintBatteryMessages = true; \ + settings.enablePrintBufferOverrun = true; \ + settings.enablePrintDuplicateStates = true; \ + settings.enablePrintEthernetDiag = true; \ + settings.enablePrintIdleTime = true; \ + settings.enablePrintLogFileMessages = false; \ + settings.enablePrintLogFileStatus = true; \ + settings.enablePrintPosition = true; \ + settings.enablePrintRingBufferOffsets = false; \ + settings.enablePrintRoverAccuracy = true; \ + settings.enablePrintRtcSync = true; \ + settings.enablePrintSDBuffers = true; \ + settings.enablePrintStates = true; \ settings.printBootTimes = true; \ + settings.printNetworkStatus = true; \ + settings.printTaskStartStop = true; \ } //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 11a624c6e..6de1e8bb2 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -102,7 +102,6 @@ void stateUpdate() displayRoverStart(0); if (gnss->configureRover() == false) { - settings.updateGNSSSettings = true; // On the next boot, update the GNSS receiver recordSystemSettings(); // Record this state for next POR systemPrintln("Rover config failed"); @@ -123,7 +122,6 @@ void stateUpdate() displayRoverFail(1000); else { - settings.updateGNSSSettings = false; // On the next boot, no need to update the GNSS receiver settings.lastState = STATE_ROVER_NOT_STARTED; recordSystemSettings(); // Record this state for next POR @@ -246,9 +244,7 @@ void stateUpdate() // Start the UART connected to the GNSS receiver for NMEA and UBX data (enables logging) if (tasksStartGnssUart() && gnss->configureBase()) { - settings.updateGNSSSettings = false; // On the next boot, no need to update the GNSS on this profile settings.lastState = STATE_BASE_NOT_STARTED; // Record this state for next POR - recordSystemSettings(); // Record this state for next POR displayBaseSuccess(500); // Show 'Base Started' @@ -260,7 +256,6 @@ void stateUpdate() } else { - settings.updateGNSSSettings = true; // On the next boot, update the GNSS receiver recordSystemSettings(); // Record this state for next POR displayBaseFail(1000); @@ -485,7 +480,6 @@ void stateUpdate() systemPrintln(); parseIncomingSettings(); - settings.updateGNSSSettings = true; // New settings; update GNSS receiver on next boot recordSystemSettings(); // Record these settings to unit // Clear buffer @@ -605,7 +599,6 @@ void stateUpdate() // Start UART connected to the GNSS receiver for NMEA and UBX data (enables logging) if (tasksStartGnssUart() && configureUbloxModuleNTP()) { - settings.updateGNSSSettings = false; // On the next boot, no need to update the GNSS on this profile settings.lastState = STATE_NTPSERVER_NOT_STARTED; // Record this state for next POR recordSystemSettings(); diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 88f083dbb..3251405ce 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -315,13 +315,13 @@ void menuMain() } // Change system wide settings based on current user profile -// Ways to change the ZED settings: -// Menus - we apply ZED changes at the exit of each sub menu -// Settings file - we detect differences between NVM and settings txt file and updateGNSSSettings = true -// Profile - Before profile is changed, set updateGNSSSettings = true -// AP - once new settings are parsed, set updateGNSSSettings = true +// Ways to change the GNSS settings: +// Menus - we apply changes at the exit of each sub menu +// Settings file - we detect differences between NVM and settings txt file +// Profile - +// AP - // Setup button - -// Factory reset - updatesZEDSettings = true by default +// Factory reset - void menuUserProfiles() { uint8_t originalProfileNumber = profileNumber; @@ -456,8 +456,7 @@ void menuUserProfiles() // Change the active profile number, without unit reset void changeProfileNumber(byte newProfileNumber) { - settings.updateGNSSSettings = true; // When this profile is loaded next, force system to update GNSS settings. - recordSystemSettings(); // Before switching, we need to record the current settings to LittleFS and SD + recordSystemSettings(); // Before switching, we need to record the current settings to LittleFS and SD recordProfileNumber(newProfileNumber); profileNumber = newProfileNumber; diff --git a/Firmware/RTK_Everywhere/menuPorts.ino b/Firmware/RTK_Everywhere/menuPorts.ino index 68a93a088..a4d970284 100644 --- a/Firmware/RTK_Everywhere/menuPorts.ino +++ b/Firmware/RTK_Everywhere/menuPorts.ino @@ -457,7 +457,6 @@ void menuPortHardwareTriggers() if (updateSettings) { - settings.updateGNSSSettings = true; // Force update gnss->beginExternalEvent(); // Update with new settings gnss->beginPPS(); } diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 9a5c60e48..74e15105a 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -654,7 +654,6 @@ struct Settings uint16_t measurementRateMs = 250; // Elapsed ms between GNSS measurements. 25ms to 65535ms. Default 4Hz. uint16_t navigationRate = 1; // Ratio between number of measurements and navigation solutions. Default 1 for 4Hz (with measurementRate). - bool updateGNSSSettings = true; // When in doubt, update the GNSS with current settings // GNSS UART uint16_t serialGNSSRxFullThreshold = 50; // RX FIFO full interrupt. Max of ~128. See pinUART2Task(). @@ -1247,7 +1246,6 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enablePrintPosition, "enablePrintPosition", }, { 0, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.measurementRateMs, "measurementRateMs", }, { 0, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.navigationRate, "navigationRate", }, - { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.updateGNSSSettings, "updateGNSSSettings", }, // Hardware { 1, 1, 0, 1, 1, 1, 0, 1, 0, _bool, 0, & settings.enableExternalHardwareEventLogging, "enableExternalHardwareEventLogging", }, From 428ac7cffadb19aea706813230cd0cd6da5bd458 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Wed, 12 Feb 2025 14:24:16 +0000 Subject: [PATCH 232/276] Only nudge SIV on 64x48 display --- Firmware/RTK_Everywhere/Display.ino | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index de535c6a9..1e2ec3456 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -1711,10 +1711,28 @@ displayCoords paintSIVIcon(std::vector *iconList, const ic void nudgeAndPrintSIV(displayCoords textCoords, uint8_t siv) { - oled->setCursor(textCoords.x - 1, textCoords.y); // x, y - oled->print(siv / 10); - oled->setCursor(textCoords.x + 7, textCoords.y); // x, y - oled->print(siv % 10); + if (present.display_type == DISPLAY_64x48) + { + // Always nudge, even if 1 digit, to avoid small jump when + // siv goes into 2 digits + oled->setCursor(textCoords.x - 1, textCoords.y); // x, y + if (siv >= 10) + { + oled->print(siv / 10); + oled->setCursor(textCoords.x + 7, textCoords.y); // x, y + oled->print(siv % 10); + } + else + { + oled->print(siv); // Left-justify 1 digit + } + } + else + { + // On 128x64, there's no need to nudge + oled->setCursor(textCoords.x, textCoords.y); // x, y + oled->print(siv); // 1 or 2 digits + } } void paintSIVText(displayCoords textCoords) @@ -1738,7 +1756,7 @@ void paintSIVText(displayCoords textCoords) if (inBaseMode() == true) nudgeAndPrintSIV(textCoords, siv); else if (gnss->isFixed() == false) - oled->print("0"); + nudgeAndPrintSIV(textCoords, 0); else nudgeAndPrintSIV(textCoords, siv); From 5dfe93adfcfb5634d3d1656694addec15f465386 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 12 Feb 2025 14:26:26 -0700 Subject: [PATCH 233/276] Pretty print the LG290P version number --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index 21873b40d..ba3b11eba 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -101,8 +101,6 @@ void GNSS_LG290P::begin() online.gnss = true; // Check firmware version and print info - printModuleInfo(); - std::string version, buildDate, buildTime; if (_lg290p->getVersionInfo(version, buildDate, buildTime)) snprintf(gnssFirmwareVersion, sizeof(gnssFirmwareVersion), "%s", version.c_str()); @@ -125,6 +123,8 @@ void GNSS_LG290P::begin() lg290pFirmwareVersion, gnssFirmwareVersion); } + printModuleInfo(); + snprintf(gnssUniqueId, sizeof(gnssUniqueId), "%s", getId()); } @@ -1772,7 +1772,7 @@ void GNSS_LG290P::printModuleInfo() std::string version, buildDate, buildTime; if (_lg290p->getVersionInfo(version, buildDate, buildTime)) { - systemPrintf("LG290P version: %s %s %s\r\n", version.c_str(), buildDate.c_str(), buildTime.c_str()); + systemPrintf("LG290P version: v%02d - %s %s %s - v%d\r\n", lg290pFirmwareVersion, version.c_str(), buildDate.c_str(), buildTime.c_str()); } else { From b983e2c8de3941ae1848ce4b81dd1c4e90a0ef67 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 13 Feb 2025 13:37:59 +0000 Subject: [PATCH 234/276] Replace beginLBand with updateLBand Rename updateLBand to updateLBandCorrections --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 1 + Firmware/RTK_Everywhere/RTK_Everywhere.ino | 10 +- Firmware/RTK_Everywhere/menuPP.ino | 271 ++++++++++++--------- 3 files changed, 166 insertions(+), 116 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 8439708dc..29ed408d9 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -2615,6 +2615,7 @@ void GNSS_MOSAIC::update() } // Update spartnCorrectionsReceived + // Does this need if(online.lband_gnss) ? Not sure... TODO if (millis() > (lastSpartnReception + (settings.correctionsSourcesLifetime_s * 1000))) // Timeout { if (spartnCorrectionsReceived) // If corrections were being received diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 0d1364ac5..541c96b65 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -966,7 +966,7 @@ volatile bool deadManWalking; settings.enablePrintRingBufferOffsets = false; \ settings.enablePrintRoverAccuracy = true; \ settings.enablePrintRtcSync = true; \ - settings.enablePrintSDBuffers = true; \ + settings.enablePrintSDBuffers = false; \ settings.enablePrintStates = true; \ settings.printBootTimes = true; \ settings.printNetworkStatus = true; \ @@ -1160,9 +1160,6 @@ void setup() DMW_b("gnss->configure"); gnss->configure(); // Requires settings. Configure GNSS module - DMW_b("beginLBand"); - beginLBand(); // Begin L-Band - DMW_b("beginExternalEvent"); gnss->beginExternalEvent(); // Configure the event input @@ -1290,7 +1287,10 @@ void loop() networkUpdate(); // Maintain the network connections DMW_c("updateLBand"); - updateLBand(); // Check if we've recently received PointPerfect corrections or not + updateLBand(); // Update L-Band + + DMW_c("updateLBandCorrections"); + updateLBandCorrections(); // Check if we've recently received PointPerfect corrections or not DMW_c("tiltUpdate"); tiltUpdate(); // Check if new lat/lon/alt have been calculated diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index bdbeb0368..a4bae6b1e 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -729,161 +729,210 @@ long gpsToMjd(long GpsCycle, long GpsWeek, long GpsSeconds) // Global L-Band Routines //---------------------------------------- -// Begin any L-Band hardware +// Update any L-Band hardware // Check if NEO-D9S is connected. Configure if available. // If GNSS is mosaic-X5, configure LBandBeam1 -void beginLBand() +void updateLBand() { #ifdef COMPILE_L_BAND if (present.lband_neo) { - if (i2cLBand.begin(*i2c_0, 0x43) == - false) // Connect to the u-blox NEO-D9S using Wire port. The D9S default I2C address is 0x43 (not 0x42) + if (!online.lband_neo && settings.enablePointPerfectCorrections) { - if (settings.debugCorrections == true) + static bool lband_neo_can_not_begin = false; + + if (lband_neo_can_not_begin) + return; + + // NEO-D9S is present but is not yet online. Try to begin the hardware + if (i2cLBand.begin(*i2c_0, 0x43) == + false) // Connect to the u-blox NEO-D9S using Wire port. The D9S default I2C address is 0x43 (not 0x42) + { systemPrintln("L-Band not detected"); - return; - } + lband_neo_can_not_begin = true; + return; + } - // Check the firmware version of the NEO-D9S. Based on Example21_ModuleInfo. - if (i2cLBand.getModuleInfo(1100) == true) // Try to get the module info - { - // Reconstruct the firmware version - snprintf(neoFirmwareVersion, sizeof(neoFirmwareVersion), "%s %d.%02d", i2cLBand.getFirmwareType(), - i2cLBand.getFirmwareVersionHigh(), i2cLBand.getFirmwareVersionLow()); + // Check the firmware version of the NEO-D9S. Based on Example21_ModuleInfo. + if (i2cLBand.getModuleInfo(1100) == true) // Try to get the module info + { + // Reconstruct the firmware version + snprintf(neoFirmwareVersion, sizeof(neoFirmwareVersion), "%s %d.%02d", i2cLBand.getFirmwareType(), + i2cLBand.getFirmwareVersionHigh(), i2cLBand.getFirmwareVersionLow()); - printNEOInfo(); // Print module firmware version - } + printNEOInfo(); // Print module firmware version + } + else + { + systemPrintln("L-Band not detected"); + lband_neo_can_not_begin = true; + return; + } - gnss->update(); + // Update the GNSS position. Use the position to set the frequency if available + gnss->update(); - uint32_t LBandFreq; - uint8_t fixType = gnss->getFixType(); - double latitude = gnss->getLatitude(); - double longitude = gnss->getLongitude(); - // If we have a fix, check which frequency to use - if (fixType >= 2 && fixType <= 5) // 2D, 3D, 3D+DR, or Time - { - int r = 0; // Step through each geographic region - for (; r < numRegionalAreas; r++) + uint32_t LBandFreq; + uint8_t fixType = gnss->getFixType(); + double latitude = gnss->getLatitude(); + double longitude = gnss->getLongitude(); + + // If we have a fix, check which frequency to use + if (fixType >= 2 && fixType <= 5) // 2D, 3D, 3D+DR, or Time { - if ((longitude >= Regional_Information_Table[r].area.lonWest) && - (longitude <= Regional_Information_Table[r].area.lonEast) && - (latitude >= Regional_Information_Table[r].area.latSouth) && - (latitude <= Regional_Information_Table[r].area.latNorth)) + int r = 0; // Step through each geographic region + for (; r < numRegionalAreas; r++) + { + if ((longitude >= Regional_Information_Table[r].area.lonWest) && + (longitude <= Regional_Information_Table[r].area.lonEast) && + (latitude >= Regional_Information_Table[r].area.latSouth) && + (latitude <= Regional_Information_Table[r].area.latNorth)) + { + LBandFreq = Regional_Information_Table[r].frequency; + if (settings.debugCorrections == true) + systemPrintf("Setting L-Band frequency to %s (%dHz)\r\n", Regional_Information_Table[r].name, + LBandFreq); + break; + } + } + if (r == numRegionalAreas) // Geographic region not found { - LBandFreq = Regional_Information_Table[r].frequency; + LBandFreq = Regional_Information_Table[settings.geographicRegion].frequency; if (settings.debugCorrections == true) - systemPrintf("Setting L-Band frequency to %s (%dHz)\r\n", Regional_Information_Table[r].name, - LBandFreq); - break; + systemPrintf("Error: Unknown L-Band geographic region. Using %s (%dHz)\r\n", + Regional_Information_Table[settings.geographicRegion].name, LBandFreq); } } - if (r == numRegionalAreas) // Geographic region not found + else { LBandFreq = Regional_Information_Table[settings.geographicRegion].frequency; if (settings.debugCorrections == true) - systemPrintf("Error: Unknown L-Band geographic region. Using %s (%dHz)\r\n", - Regional_Information_Table[settings.geographicRegion].name, LBandFreq); + systemPrintf("No fix available for L-Band geographic region determination. Using %s (%dHz)\r\n", + Regional_Information_Table[settings.geographicRegion].name, LBandFreq); } - } - else - { - LBandFreq = Regional_Information_Table[settings.geographicRegion].frequency; - if (settings.debugCorrections == true) - systemPrintf("No fix available for L-Band geographic region determination. Using %s (%dHz)\r\n", - Regional_Information_Table[settings.geographicRegion].name, LBandFreq); - } - - bool response = true; - response &= i2cLBand.newCfgValset(); - response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_CENTER_FREQUENCY, LBandFreq); // Default 1539812500 Hz - response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_SEARCH_WINDOW, 2200); // Default 2200 Hz - response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_USE_SERVICE_ID, 0); // Default 1 - response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_SERVICE_ID, 21845); // Default 50821 - response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_DATA_RATE, 2400); // Default 2400 bps - response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_USE_DESCRAMBLER, 1); // Default 1 - response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_DESCRAMBLER_INIT, 26969); // Default 23560 - response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_USE_PRESCRAMBLING, 0); // Default 0 - response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_UNIQUE_WORD, 16238547128276412563ull); - response &= - i2cLBand.addCfgValset(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART1, 0); // Diasable UBX-RXM-PMP on UART1. Not used. - - response &= i2cLBand.sendCfgValset(); - GNSS_ZED *zed = (GNSS_ZED *)gnss; - response &= zed->lBandCommunicationEnable(); - - if (response == false) - systemPrintln("L-Band failed to configure"); - - i2cLBand.softwareResetGNSSOnly(); // Do a restart + bool response = true; + response &= i2cLBand.newCfgValset(); + response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_CENTER_FREQUENCY, LBandFreq); // Default 1539812500 Hz + response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_SEARCH_WINDOW, 2200); // Default 2200 Hz + response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_USE_SERVICE_ID, 0); // Default 1 + response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_SERVICE_ID, 21845); // Default 50821 + response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_DATA_RATE, 2400); // Default 2400 bps + response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_USE_DESCRAMBLER, 1); // Default 1 + response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_DESCRAMBLER_INIT, 26969); // Default 23560 + response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_USE_PRESCRAMBLING, 0); // Default 0 + response &= i2cLBand.addCfgValset(UBLOX_CFG_PMP_UNIQUE_WORD, 16238547128276412563ull); + response &= + i2cLBand.addCfgValset(UBLOX_CFG_MSGOUT_UBX_RXM_PMP_UART1, 0); // Disable UBX-RXM-PMP on UART1. Not used. + + response &= i2cLBand.sendCfgValset(); + + GNSS_ZED *zed = (GNSS_ZED *)gnss; + response &= zed->lBandCommunicationEnable(); + + if (response == false) + { + systemPrintln("L-Band failed to configure"); + lband_neo_can_not_begin = true; + return; + } - if (settings.debugCorrections == true) - systemPrintln("L-Band online"); + i2cLBand.softwareResetGNSSOnly(); // Do a restart - gnss->applyPointPerfectKeys(); // Apply keys now, if we have them. This sets online.lbandCorrections + if (settings.debugCorrections == true) + systemPrintln("L-Band online"); - online.lband_neo = true; + online.lband_neo = true; + } + else if (online.lband_neo && settings.enablePointPerfectCorrections) + { + // L-Band is online. Apply the keys if they have changed + // This may be redundant as PROVISIONING_KEYS_REMAINING also applies the keys + static char previousKey[33] = ""; + if (strncmp(previousKey, settings.pointPerfectCurrentKey, 33) != 0) + { + strncpy(previousKey, settings.pointPerfectCurrentKey, 33); + gnss->applyPointPerfectKeys(); // Apply keys now. This sets online.lbandCorrections + if (settings.debugCorrections == true) + systemPrintln("ZED-F9P PointPerfect keys applied"); + } + } } #endif // COMPILE_L_BAND #ifdef COMPILE_MOSAICX5 - if (present.gnss_mosaicX5 && settings.enablePointPerfectCorrections) + if (present.gnss_mosaicX5) { - uint32_t LBandFreq; - uint8_t fixType = gnss->getFixType(); - double latitude = gnss->getLatitude(); - double longitude = gnss->getLongitude(); - // If we have a fix, check which frequency to use - if (fixType >= 1) // Stand-Alone PVT or better + if (!online.lband_gnss && settings.enablePointPerfectCorrections) { - int r = 0; // Step through each geographic region - for (; r < numRegionalAreas; r++) + static bool lband_gnss_can_not_begin = false; + + if (lband_gnss_can_not_begin) + return; + + uint32_t LBandFreq; + uint8_t fixType = gnss->getFixType(); + double latitude = gnss->getLatitude(); + double longitude = gnss->getLongitude(); + // If we have a fix, check which frequency to use + if (fixType >= 1) // Stand-Alone PVT or better { - if ((longitude >= Regional_Information_Table[r].area.lonWest) && - (longitude <= Regional_Information_Table[r].area.lonEast) && - (latitude >= Regional_Information_Table[r].area.latSouth) && - (latitude <= Regional_Information_Table[r].area.latNorth)) + int r = 0; // Step through each geographic region + for (; r < numRegionalAreas; r++) { - LBandFreq = Regional_Information_Table[r].frequency; + if ((longitude >= Regional_Information_Table[r].area.lonWest) && + (longitude <= Regional_Information_Table[r].area.lonEast) && + (latitude >= Regional_Information_Table[r].area.latSouth) && + (latitude <= Regional_Information_Table[r].area.latNorth)) + { + LBandFreq = Regional_Information_Table[r].frequency; + if (settings.debugCorrections == true) + systemPrintf("Setting L-Band frequency to %s (%dHz)\r\n", Regional_Information_Table[r].name, + LBandFreq); + break; + } + } + if (r == numRegionalAreas) // Geographic region not found + { + LBandFreq = Regional_Information_Table[settings.geographicRegion].frequency; if (settings.debugCorrections == true) - systemPrintf("Setting L-Band frequency to %s (%dHz)\r\n", Regional_Information_Table[r].name, - LBandFreq); - break; + systemPrintf("Error: Unknown L-Band geographic region. Using %s (%dHz)\r\n", + Regional_Information_Table[settings.geographicRegion].name, LBandFreq); } } - if (r == numRegionalAreas) // Geographic region not found + else { LBandFreq = Regional_Information_Table[settings.geographicRegion].frequency; if (settings.debugCorrections == true) - systemPrintf("Error: Unknown L-Band geographic region. Using %s (%dHz)\r\n", - Regional_Information_Table[settings.geographicRegion].name, LBandFreq); + systemPrintf("No fix available for L-Band geographic region determination. Using %s (%dHz)\r\n", + Regional_Information_Table[settings.geographicRegion].name, LBandFreq); } - } - else - { - LBandFreq = Regional_Information_Table[settings.geographicRegion].frequency; - if (settings.debugCorrections == true) - systemPrintf("No fix available for L-Band geographic region determination. Using %s (%dHz)\r\n", - Regional_Information_Table[settings.geographicRegion].name, LBandFreq); - } - bool result = true; + bool result = true; - // If no SPARTN data is received, the L-Band may need a 'kick'. Turn L-Band off and back on again! - GNSS_MOSAIC *mosaic = (GNSS_MOSAIC *)gnss; + GNSS_MOSAIC *mosaic = (GNSS_MOSAIC *)gnss; - result &= mosaic->configureGNSSCOM(true); // Ensure LBandBeam1 is enabled on COM1 + result &= mosaic->configureGNSSCOM(true); // Ensure LBandBeam1 is enabled on COM1 - result &= mosaic->configureLBand(true, LBandFreq); // Start L-Band + result &= mosaic->configureLBand(true, LBandFreq); // Start L-Band - if (result == false) - systemPrintln("mosaic-X5 L-Band failed to configure"); - else if (settings.debugCorrections == true) - systemPrintln("mosaic-X5 L-Band online"); - - online.lband_gnss = result; + if (result == false) + { + systemPrintln("mosaic-X5 L-Band failed to configure"); + lband_gnss_can_not_begin = true; + } + else + { + if (settings.debugCorrections == true) + systemPrintln("mosaic-X5 L-Band online"); + online.lband_gnss = true; + } + } + //else if (online.lband_gnss && settings.enablePointPerfectCorrections) + { + // If no SPARTN data is received, the L-Band may need a 'kick'. Turn L-Band off and back on again! + // But gnss->update will do this. No need to do it here + } } #endif // /COMPILE_MOSAICX5 } @@ -1092,7 +1141,7 @@ bool pointPerfectIsEnabled() } // Process any new L-Band from I2C -void updateLBand() +void updateLBandCorrections() { static unsigned long lbandLastReport; static unsigned long lbandTimeFloatStarted; // Monitors the ZED during L-Band reception if a fix takes too long From 7c4a5ae457dff3a752c2a4718bb897cec6579978 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 13 Feb 2025 18:25:24 +0000 Subject: [PATCH 235/276] Read analog pins as digital to try and avoid SD detection badness --- Firmware/RTK_Everywhere/Display.ino | 4 ++-- Firmware/RTK_Everywhere/GNSS_UM980.ino | 4 ++-- Firmware/RTK_Everywhere/LoRa.ino | 4 ++-- Firmware/RTK_Everywhere/SD.ino | 4 ++-- Firmware/RTK_Everywhere/System.ino | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 1e2ec3456..669e7319b 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -2499,10 +2499,10 @@ void paintSystemTest() pinMode(pin_muxADC, INPUT_PULLUP); digitalWrite(pin_muxDAC, HIGH); - if (digitalRead(pin_muxADC) == HIGH) + if (readAnalogPinAsDigital(pin_muxADC) == HIGH) { digitalWrite(pin_muxDAC, LOW); - if (digitalRead(pin_muxADC) == LOW) + if (readAnalogPinAsDigital(pin_muxADC) == LOW) oled->print("OK"); else oled->print("FAIL"); diff --git a/Firmware/RTK_Everywhere/GNSS_UM980.ino b/Firmware/RTK_Everywhere/GNSS_UM980.ino index 4f274700d..a2dc112fb 100644 --- a/Firmware/RTK_Everywhere/GNSS_UM980.ino +++ b/Firmware/RTK_Everywhere/GNSS_UM980.ino @@ -1947,9 +1947,9 @@ void um980FirmwareBeginUpdate() } } - if (digitalRead(pin_powerButton) == HIGH) + if (readAnalogPinAsDigital(pin_powerButton) == HIGH) { - while (digitalRead(pin_powerButton) == HIGH) + while (readAnalogPinAsDigital(pin_powerButton) == HIGH) delay(100); // Remove file and reset to exit pass-through mode diff --git a/Firmware/RTK_Everywhere/LoRa.ino b/Firmware/RTK_Everywhere/LoRa.ino index 6e6e4ab34..7901fc3a7 100644 --- a/Firmware/RTK_Everywhere/LoRa.ino +++ b/Firmware/RTK_Everywhere/LoRa.ino @@ -482,9 +482,9 @@ void beginLoraFirmwareUpdate() while (serialGNSS->available()) Serial.write(serialGNSS->read()); - if (digitalRead(pin_powerButton) == HIGH) + if (readAnalogPinAsDigital(pin_powerButton) == HIGH) { - while (digitalRead(pin_powerButton) == HIGH) + while (readAnalogPinAsDigital(pin_powerButton) == HIGH) delay(100); // Remove file and reset to exit LoRa update pass-through mode diff --git a/Firmware/RTK_Everywhere/SD.ino b/Firmware/RTK_Everywhere/SD.ino index 7e5112981..2cf8e48c7 100644 --- a/Firmware/RTK_Everywhere/SD.ino +++ b/Firmware/RTK_Everywhere/SD.ino @@ -84,13 +84,13 @@ bool sdCardPresent(void) { if (present.microSdCardDetectLow == true) { - if (digitalRead(pin_microSD_CardDetect) == LOW) + if (readAnalogPinAsDigital(pin_microSD_CardDetect) == LOW) return (true); // Card detect low = SD in place return (false); // Card detect high = No SD } else if (present.microSdCardDetectHigh == true) { - if (digitalRead(pin_microSD_CardDetect) == HIGH) + if (readAnalogPinAsDigital(pin_microSD_CardDetect) == HIGH) return (true); // Card detect high = SD in place return (false); // Card detect low = No SD } diff --git a/Firmware/RTK_Everywhere/System.ino b/Firmware/RTK_Everywhere/System.ino index cd5fbb940..99c9dc290 100644 --- a/Firmware/RTK_Everywhere/System.ino +++ b/Firmware/RTK_Everywhere/System.ino @@ -770,7 +770,7 @@ bool isUsbAttached() { if (pin_powerAdapterDetect != PIN_UNDEFINED) // Pin goes low when wall adapter is detected - if (digitalRead(pin_powerAdapterDetect) == HIGH) + if (readAnalogPinAsDigital(pin_powerAdapterDetect) == HIGH) return false; return true; } From 0b694289fff70f2723d75ced53be11c4322c4482 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 13 Feb 2025 18:28:02 +0000 Subject: [PATCH 236/276] Starting to reinstate settings.updateGNSSSettings as settings.gnssConfiguredOnce/Base/Rover --- Firmware/RTK_Everywhere/GNSS_ZED.ino | 104 ++++++++++++++++----------- Firmware/RTK_Everywhere/settings.h | 6 ++ 2 files changed, 69 insertions(+), 41 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.ino b/Firmware/RTK_Everywhere/GNSS_ZED.ino index f4a8601b2..02262d45c 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.ino +++ b/Firmware/RTK_Everywhere/GNSS_ZED.ino @@ -207,80 +207,94 @@ void GNSS_ZED::begin() } printModuleInfo(); // Print module type and firmware version - } - UBX_SEC_UNIQID_data_t chipID; - if (_zed->getUniqueChipId(&chipID)) - { - snprintf(gnssUniqueId, sizeof(gnssUniqueId), "%s", _zed->getUniqueChipIdStr(&chipID)); - } + UBX_SEC_UNIQID_data_t chipID; + if (_zed->getUniqueChipId(&chipID)) + { + snprintf(gnssUniqueId, sizeof(gnssUniqueId), "%s", _zed->getUniqueChipIdStr(&chipID)); - systemPrintln("GNSS ZED online"); + systemPrintln("GNSS ZED online"); + online.gnss = true; + return; + } + } - online.gnss = true; + systemPrintln("GNSS ZED offline"); + displayGNSSFail(1000); } //---------------------------------------- -// Setup the timepulse output on the PPS pin for external triggering -// Setup TM2 time stamp input as need +// Setup the timepulse output on the PPS pin for external triggering. +// Setup TM2 time stamp input as need. +// Allow this to be called multiple times so that the callback can be +// set or cleared as needed. +// This will be called once by setup and possibly multiple times by +// menuPortsMultiplexed. //---------------------------------------- bool GNSS_ZED::beginExternalEvent() { if (online.gnss == false) return (false); - if (settings.dataPortChannel != MUX_PPS_EVENTTRIGGER) - return (true); // No need to configure PPS if port is not selected - bool response = true; - if (settings.enableExternalHardwareEventLogging) + // Assumes EXTINT is always routed through the multiplexer... + if (settings.enableExternalHardwareEventLogging && (settings.dataPortChannel == MUX_PPS_EVENTTRIGGER)) { - _zed->setAutoTIMTM2callbackPtr( + response &= _zed->setAutoTIMTM2callbackPtr( &eventTriggerReceived); // Enable automatic TIM TM2 messages with callback to eventTriggerReceived } else - _zed->setAutoTIMTM2callbackPtr(nullptr); + { + response &= _zed->setAutoTIMTM2callbackPtr(nullptr); + } + + if (response == false) + systemPrintln("beginExternalEvent failed"); return (response); } //---------------------------------------- // Setup the timepulse output on the PPS pin for external triggering +// Allow this to be called multiple times. +// This will be called once by setup and possibly multiple times by +// menuPortsMultiplexed. //---------------------------------------- bool GNSS_ZED::beginPPS() { if (online.gnss == false) return (false); - if (settings.dataPortChannel != MUX_PPS_EVENTTRIGGER) - return (true); // No need to configure PPS if port is not selected - bool response = true; - response &= _zed->newCfgValset(); - response &= _zed->addCfgValset(UBLOX_CFG_TP_PULSE_DEF, 0); // Time pulse definition is a period (in us) - response &= _zed->addCfgValset(UBLOX_CFG_TP_PULSE_LENGTH_DEF, 1); // Define timepulse by length (not ratio) - response &= - _zed->addCfgValset(UBLOX_CFG_TP_USE_LOCKED_TP1, - 1); // Use CFG-TP-PERIOD_LOCK_TP1 and CFG-TP-LEN_LOCK_TP1 as soon as GNSS time is valid - response &= _zed->addCfgValset(UBLOX_CFG_TP_TP1_ENA, settings.enableExternalPulse); // Enable/disable timepulse - response &= - _zed->addCfgValset(UBLOX_CFG_TP_POL_TP1, settings.externalPulsePolarity); // 0 = falling, 1 = rising edge + // Assumes PPS is always routed through the multiplexer... + if (settings.dataPortChannel == MUX_PPS_EVENTTRIGGER) + { + response &= _zed->newCfgValset(); + response &= _zed->addCfgValset(UBLOX_CFG_TP_PULSE_DEF, 0); // Time pulse definition is a period (in us) + response &= _zed->addCfgValset(UBLOX_CFG_TP_PULSE_LENGTH_DEF, 1); // Define timepulse by length (not ratio) + response &= + _zed->addCfgValset(UBLOX_CFG_TP_USE_LOCKED_TP1, + 1); // Use CFG-TP-PERIOD_LOCK_TP1 and CFG-TP-LEN_LOCK_TP1 as soon as GNSS time is valid + response &= _zed->addCfgValset(UBLOX_CFG_TP_TP1_ENA, settings.enableExternalPulse); // Enable/disable timepulse + response &= + _zed->addCfgValset(UBLOX_CFG_TP_POL_TP1, settings.externalPulsePolarity); // 0 = falling, 1 = rising edge - // While the module is _locking_ to GNSS time, turn off pulse - response &= _zed->addCfgValset(UBLOX_CFG_TP_PERIOD_TP1, 1000000); // Set the period between pulses in us - response &= _zed->addCfgValset(UBLOX_CFG_TP_LEN_TP1, 0); // Set the pulse length in us + // While the module is _locking_ to GNSS time, turn off pulse + response &= _zed->addCfgValset(UBLOX_CFG_TP_PERIOD_TP1, 1000000); // Set the period between pulses in us + response &= _zed->addCfgValset(UBLOX_CFG_TP_LEN_TP1, 0); // Set the pulse length in us - // When the module is _locked_ to GNSS time, make it generate 1Hz (Default is 100ms high, 900ms low) - response &= _zed->addCfgValset(UBLOX_CFG_TP_PERIOD_LOCK_TP1, - settings.externalPulseTimeBetweenPulse_us); // Set the period between pulses is us - response &= - _zed->addCfgValset(UBLOX_CFG_TP_LEN_LOCK_TP1, settings.externalPulseLength_us); // Set the pulse length in us - response &= _zed->sendCfgValset(); + // When the module is _locked_ to GNSS time, make it generate 1Hz (Default is 100ms high, 900ms low) + response &= _zed->addCfgValset(UBLOX_CFG_TP_PERIOD_LOCK_TP1, + settings.externalPulseTimeBetweenPulse_us); // Set the period between pulses is us + response &= + _zed->addCfgValset(UBLOX_CFG_TP_LEN_LOCK_TP1, settings.externalPulseLength_us); // Set the pulse length in us + response &= _zed->sendCfgValset(); + } if (response == false) - systemPrintln("beginExternalTriggers config failed"); + systemPrintln("beginPPS failed"); return (response); } @@ -313,6 +327,13 @@ bool GNSS_ZED::configureBase() if (online.gnss == false) return (false); + if (settings.gnssConfiguredBase) + { + if (settings.debugGnss) + systemPrintln("Skipping ZED Base configuration"); + return true; + } + update(); // Regularly poll to get latest data _zed->setNMEAGPGGAcallbackPtr( @@ -394,9 +415,10 @@ bool GNSS_ZED::configureBase() if (!success) systemPrintln("Base config fail"); - else - // Save the current configuration into non-volatile memory (NVM) - saveConfiguration(); + + // The configuration should be saved to RAM and BBR. No need to saveConfiguration here. + + settings.gnssConfiguredBase = success; return (success); } diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 74e15105a..077e8e4e7 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -654,6 +654,9 @@ struct Settings uint16_t measurementRateMs = 250; // Elapsed ms between GNSS measurements. 25ms to 65535ms. Default 4Hz. uint16_t navigationRate = 1; // Ratio between number of measurements and navigation solutions. Default 1 for 4Hz (with measurementRate). + bool gnssConfiguredOnce = false; // Flags to indicate how the GNSS is configured (Once, Base, Rover, etc.) + bool gnssConfiguredBase = false; + bool gnssConfiguredRover = false; // GNSS UART uint16_t serialGNSSRxFullThreshold = 50; // RX FIFO full interrupt. Max of ~128. See pinUART2Task(). @@ -1246,6 +1249,9 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enablePrintPosition, "enablePrintPosition", }, { 0, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.measurementRateMs, "measurementRateMs", }, { 0, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.navigationRate, "navigationRate", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.gnssConfiguredOnce, "gnssConfiguredOnce", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.gnssConfiguredBase, "gnssConfiguredBase", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.gnssConfiguredRover, "gnssConfiguredRover", }, // Hardware { 1, 1, 0, 1, 1, 1, 0, 1, 0, _bool, 0, & settings.enableExternalHardwareEventLogging, "enableExternalHardwareEventLogging", }, From 860ce679b4d014c2d276cda7594d357ffda85691 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 13 Feb 2025 18:28:29 +0000 Subject: [PATCH 237/276] Delete obsolete stateFromLFS --- Firmware/RTK_Everywhere/NVM.ino | 1 - 1 file changed, 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index 0532a9e85..b3252bf15 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -60,7 +60,6 @@ void loadSettings() // Temp store any variables from LFS that should override SD int resetCount = settings.resetCount; - SystemState stateFromLFS = settings.lastState; loadSystemSettingsFromFileSD(settingsFileName); From c8dd670d6d63e7a7b36af924503907e4c61f0b95 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 13 Feb 2025 18:29:10 +0000 Subject: [PATCH 238/276] Move beginExternalEvent and beginPPS into menuPortsMultiplexed --- Firmware/RTK_Everywhere/menuPorts.ino | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/Firmware/RTK_Everywhere/menuPorts.ino b/Firmware/RTK_Everywhere/menuPorts.ino index a4d970284..fc415bbcb 100644 --- a/Firmware/RTK_Everywhere/menuPorts.ino +++ b/Firmware/RTK_Everywhere/menuPorts.ino @@ -306,13 +306,18 @@ void menuPortsMultiplexed() restartBase = true; } #endif // COMPILE_MOSAICX5 + + gnss->beginExternalEvent(); // Update with new settings + gnss->beginPPS(); } -// Configure the behavior of the PPS and INT pins on the ZED-F9P -// Most often used for logging events (inputs) and when external triggers (outputs) occur +// Configure the behavior of the PPS and INT pins. +// Most often used for logging events (inputs) and when external triggers (outputs) occur. +// menuPortHardwareTriggers is only called by menuPortsMultiplexed. +// Call gnss->beginExternalEvent() and gnss->beginPPS() in menuPortsMultiplexed, not here +// since menuPortsMultiplexed has control of the multiplexer void menuPortHardwareTriggers() { - bool updateSettings = false; while (1) { systemPrintln(); @@ -364,7 +369,6 @@ void menuPortHardwareTriggers() if (incoming == 1) { settings.enableExternalPulse ^= 1; - updateSettings = true; } else if (incoming == 2 && settings.enableExternalPulse == true) { @@ -382,7 +386,6 @@ void menuPortHardwareTriggers() if (interval >= 1 && interval <= MAX_MOSAIC_PPS_INTERVALS) { settings.externalPulseTimeBetweenPulse_us = mosaicPPSIntervals[interval - 1].interval_us; - updateSettings = true; } } else @@ -402,8 +405,6 @@ void menuPortHardwareTriggers() (settings.externalPulseLength_us / 1000)) // pulseTime must be longer than pulseLength settings.externalPulseLength_us = settings.externalPulseTimeBetweenPulse_us / 2; // Force pulse length to be 1/2 time between pulses - - updateSettings = true; } } } @@ -421,7 +422,6 @@ void menuPortHardwareTriggers() else { settings.externalPulseLength_us = pulseLength * 1000; - updateSettings = true; } } } @@ -431,17 +431,14 @@ void menuPortHardwareTriggers() settings.externalPulsePolarity = PULSE_FALLING_EDGE; else settings.externalPulsePolarity = PULSE_RISING_EDGE; - updateSettings = true; } else if (incoming == 5) { settings.enableExternalHardwareEventLogging ^= 1; - updateSettings = true; } else if ((incoming == 6) && (settings.enableExternalHardwareEventLogging == true) && present.gnss_mosaicX5) { settings.externalEventPolarity ^= 1; - updateSettings = true; } else if (incoming == 'x') break; @@ -454,10 +451,4 @@ void menuPortHardwareTriggers() } clearBuffer(); // Empty buffer of any newline chars - - if (updateSettings) - { - gnss->beginExternalEvent(); // Update with new settings - gnss->beginPPS(); - } } From e5a70fae8a1f5770a260f61920b88e854960b356 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Feb 2025 13:11:32 +0000 Subject: [PATCH 239/276] Add gnssConfiguredOnce/Base/Rover setting/clearing --- Firmware/RTK_Everywhere/Display.ino | 2 ++ Firmware/RTK_Everywhere/NVM.ino | 17 +++++++++++++---- Firmware/RTK_Everywhere/States.ino | 11 +++++++++++ Firmware/RTK_Everywhere/menuMain.ino | 4 ++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 669e7319b..f1dae8a94 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -2384,6 +2384,8 @@ void paintProfile(uint8_t profileUnit) if (profileNumber >= 0) { + settings.gnssConfiguredBase = false; // On the next boot, reapply all settings + settings.gnssConfiguredRover = false; recordSystemSettings(); // Before switching, we need to record the current settings to LittleFS and SD recordProfileNumber( diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index b3252bf15..2fc8bc853 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -1572,24 +1572,33 @@ void loadProfileNumber() } else { - log_d("profileNumber.txt not found"); + systemPrintln("profileNumber.txt not found"); + settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings + settings.gnssConfiguredBase = false; + settings.gnssConfiguredRover = false; recordProfileNumber(0); // Record profile } } else { - log_d("profileNumber.txt not found"); + systemPrintln("profileNumber.txt not found"); + settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings + settings.gnssConfiguredBase = false; + settings.gnssConfiguredRover = false; recordProfileNumber(0); // Record profile } // We have arbitrary limit of user profiles if (profileNumber >= MAX_PROFILE_COUNT) { - log_d("ProfileNumber invalid. Going to zero."); + systemPrintln("ProfileNumber invalid. Going to zero."); + settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings + settings.gnssConfiguredBase = false; + settings.gnssConfiguredRover = false; recordProfileNumber(0); // Record profile } - log_d("Using profile #%d", profileNumber); + systemPrintf("Using profile #%d\r\n", profileNumber); } // Record the given profile number as well as a config bool diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 6de1e8bb2..f35288e05 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -102,6 +102,7 @@ void stateUpdate() displayRoverStart(0); if (gnss->configureRover() == false) { + settings.gnssConfiguredRover = false; // On the next boot, reapply all settings recordSystemSettings(); // Record this state for next POR systemPrintln("Rover config failed"); @@ -122,6 +123,8 @@ void stateUpdate() displayRoverFail(1000); else { + //settings.gnssConfiguredRover is set true by gnss->configureRover() + settings.gnssConfiguredBase = false; // When the mode changes, reapply all settings settings.lastState = STATE_ROVER_NOT_STARTED; recordSystemSettings(); // Record this state for next POR @@ -244,6 +247,8 @@ void stateUpdate() // Start the UART connected to the GNSS receiver for NMEA and UBX data (enables logging) if (tasksStartGnssUart() && gnss->configureBase()) { + // settings.gnssConfiguredBase is set true by gnss->configureBase() + settings.gnssConfiguredRover = false; // When the mode changes, reapply all settings settings.lastState = STATE_BASE_NOT_STARTED; // Record this state for next POR recordSystemSettings(); // Record this state for next POR @@ -256,6 +261,7 @@ void stateUpdate() } else { + settings.gnssConfiguredBase = false; // On the next boot, reapply all settings recordSystemSettings(); // Record this state for next POR displayBaseFail(1000); @@ -480,6 +486,9 @@ void stateUpdate() systemPrintln(); parseIncomingSettings(); + settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings + settings.gnssConfiguredBase = false; + settings.gnssConfiguredRover = false; recordSystemSettings(); // Record these settings to unit // Clear buffer @@ -600,6 +609,8 @@ void stateUpdate() if (tasksStartGnssUart() && configureUbloxModuleNTP()) { settings.lastState = STATE_NTPSERVER_NOT_STARTED; // Record this state for next POR + settings.gnssConfiguredBase = false; // On the next boot, reapply all settings + settings.gnssConfiguredRover = false; recordSystemSettings(); if (online.ethernetNTPServer) diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 3251405ce..41e700228 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -456,6 +456,8 @@ void menuUserProfiles() // Change the active profile number, without unit reset void changeProfileNumber(byte newProfileNumber) { + settings.gnssConfiguredBase = false; // On the next boot, reapply all settings + settings.gnssConfiguredRover = false; recordSystemSettings(); // Before switching, we need to record the current settings to LittleFS and SD recordProfileNumber(newProfileNumber); @@ -495,6 +497,8 @@ void factoryReset(bool alreadyHasSemaphore) sd->remove(stationCoordinateGeodeticFileName); xSemaphoreGive(sdCardSemaphore); + + systemPrintln("Settings files deleted..."); } // End sdCardSemaphore else { From 623e9b7c543e926507e2b5f847c5cd4b88ef3b0d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Feb 2025 13:12:24 +0000 Subject: [PATCH 240/276] ZED: add gnssConfiguredOnce/Base/Rover. Apply config to RAM+BBR+FLASH --- Firmware/RTK_Everywhere/GNSS_ZED.ino | 131 ++++++++++++++++----------- 1 file changed, 79 insertions(+), 52 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.ino b/Firmware/RTK_Everywhere/GNSS_ZED.ino index 02262d45c..43c2dbdc4 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.ino +++ b/Firmware/RTK_Everywhere/GNSS_ZED.ino @@ -56,10 +56,10 @@ void GNSS_ZED::applyPointPerfectKeys() updateCorrectionsSource(0); // Set SOURCE to 0 (IP) if needed } - _zed->setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_COR_I2C, 1); // Enable UBX-RXM-COR messages on I2C + _zed->setVal8(UBLOX_CFG_MSGOUT_UBX_RXM_COR_I2C, 1, VAL_LAYER_ALL); // Enable UBX-RXM-COR messages on I2C _zed->setVal8(UBLOX_CFG_NAVHPG_DGNSSMODE, - 3); // Set the differential mode - ambiguities are fixed whenever possible + 3, VAL_LAYER_ALL); // Set the differential mode - ambiguities are fixed whenever possible bool response = _zed->setDynamicSPARTNKeys(currentKeyLengthBytes, currentKeyGPSWeek, currentKeyGPSToW, settings.pointPerfectCurrentKey, nextKeyLengthBytes, nextKeyGPSWeek, @@ -242,11 +242,11 @@ bool GNSS_ZED::beginExternalEvent() if (settings.enableExternalHardwareEventLogging && (settings.dataPortChannel == MUX_PPS_EVENTTRIGGER)) { response &= _zed->setAutoTIMTM2callbackPtr( - &eventTriggerReceived); // Enable automatic TIM TM2 messages with callback to eventTriggerReceived + &eventTriggerReceived, VAL_LAYER_ALL); // Enable automatic TIM TM2 messages with callback to eventTriggerReceived } else { - response &= _zed->setAutoTIMTM2callbackPtr(nullptr); + response &= _zed->setAutoTIMTM2callbackPtr(nullptr, VAL_LAYER_ALL); } if (response == false) @@ -271,7 +271,7 @@ bool GNSS_ZED::beginPPS() // Assumes PPS is always routed through the multiplexer... if (settings.dataPortChannel == MUX_PPS_EVENTTRIGGER) { - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); response &= _zed->addCfgValset(UBLOX_CFG_TP_PULSE_DEF, 0); // Time pulse definition is a period (in us) response &= _zed->addCfgValset(UBLOX_CFG_TP_PULSE_LENGTH_DEF, 1); // Define timepulse by length (not ratio) response &= @@ -351,7 +351,7 @@ bool GNSS_ZED::configureBase() bool response = true; // In Base mode we force 1Hz - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); response &= _zed->addCfgValset(UBLOX_CFG_RATE_MEAS, 1000); response &= _zed->addCfgValset(UBLOX_CFG_RATE_NAV, 1); @@ -416,7 +416,7 @@ bool GNSS_ZED::configureBase() if (!success) systemPrintln("Base config fail"); - // The configuration should be saved to RAM and BBR. No need to saveConfiguration here. + // The configuration should be saved to RAM+BBR+FLASH. No need to saveConfiguration here. settings.gnssConfiguredBase = success; @@ -433,7 +433,12 @@ bool GNSS_ZED::configureNtpMode() if (online.gnss == false) return (false); - gnss->update(); // Regularly poll to get latest data + // This is only called by STATE_NTPSERVER_NOT_STARTED + // I guess it is OK to always do the configuration? + // stateUpdate clear the Base and Rover configuration flags + // to ensure the configuration is re-applied when we exit this mode + + update(); // Regularly poll to get latest data // Disable GPGGA call back that may have been set during Rover NTRIP Client mode _zed->setNMEAGPGGAcallbackPtr(nullptr); @@ -449,7 +454,7 @@ bool GNSS_ZED::configureNtpMode() bool response = true; // In NTP mode we force 1Hz - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); response &= _zed->addCfgValset(UBLOX_CFG_RATE_MEAS, 1000); response &= _zed->addCfgValset(UBLOX_CFG_RATE_NAV, 1); @@ -500,15 +505,15 @@ bool GNSS_ZED::configureNtpMode() if (!success) systemPrintln("NTP config fail"); - else - // Save the current configuration into non-volatile memory (NVM) - saveConfiguration(); + + // The configuration should be saved to RAM+BBR+FLASH. No need to saveConfiguration here. return (success); } //---------------------------------------- // Setup the u-blox module for any setup (base or rover) +// This is the equivalent of configureOnce on the other platforms // In general we check if the setting is incorrect before writing it. Otherwise, the set commands have, on rare // occasion, become corrupt. The worst is when the I2C port gets turned off or the I2C address gets borked. //---------------------------------------- @@ -533,9 +538,9 @@ bool GNSS_ZED::configureGNSS() // Configure the callbacks response &= - _zed->setAutoPVTcallbackPtr(&storePVTdata); // Enable automatic NAV PVT messages with callback to storePVTdata + _zed->setAutoPVTcallbackPtr(&storePVTdata, VAL_LAYER_ALL); // Enable automatic NAV PVT messages with callback to storePVTdata response &= _zed->setAutoHPPOSLLHcallbackPtr( - &storeHPdata); // Enable automatic NAV HPPOSLLH messages with callback to storeHPdata + &storeHPdata, VAL_LAYER_ALL); // Enable automatic NAV HPPOSLLH messages with callback to storeHPdata _zed->setRTCM1005InputcallbackPtr( &storeRTCM1005data); // Configure a callback for RTCM 1005 - parsed from pushRawData _zed->setRTCM1006InputcallbackPtr( @@ -543,22 +548,22 @@ bool GNSS_ZED::configureGNSS() if (present.timePulseInterrupt) response &= _zed->setAutoTIMTPcallbackPtr( - &storeTIMTPdata); // Enable automatic TIM TP messages with callback to storeTIMTPdata + &storeTIMTPdata, VAL_LAYER_ALL); // Enable automatic TIM TP messages with callback to storeTIMTPdata if (present.antennaShortOpen) { - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); response &= _zed->addCfgValset(UBLOX_CFG_HW_ANT_CFG_SHORTDET, 1); // Enable antenna short detection response &= _zed->addCfgValset(UBLOX_CFG_HW_ANT_CFG_OPENDET, 1); // Enable antenna open detection response &= _zed->sendCfgValset(); response &= _zed->setAutoMONHWcallbackPtr( - &storeMONHWdata); // Enable automatic MON HW messages with callback to storeMONHWdata + &storeMONHWdata, VAL_LAYER_ALL); // Enable automatic MON HW messages with callback to storeMONHWdata } // Add a callback for UBX-MON-COMMS - response &= _zed->setAutoMONCOMMScallbackPtr(&storeMONCOMMSdata); + response &= _zed->setAutoMONCOMMScallbackPtr(&storeMONCOMMSdata, VAL_LAYER_ALL); // Enable RTCM3 if needed - if not enable NMEA IN to keep skipped updated response &= setCorrRadioExtPort(settings.enableExtCorrRadio, true); // Force the setting @@ -570,6 +575,15 @@ bool GNSS_ZED::configureGNSS() success &= response; response = true; // Reset + // Configuring the ZED can take more than 2000ms. Configuration is saved to + // ZED RAM+BBR so there is no need to update settings unless user has modified + // the settings file or internal settings. + if (settings.gnssConfiguredOnce) + { + systemPrintln("ZED-F9x configuration maintained"); + return (true); + } + // Wait for initial report from module int maxWait = 2000; startTime = millis(); @@ -586,7 +600,7 @@ bool GNSS_ZED::configureGNSS() } // The first thing we do is go to 1Hz to lighten any I2C traffic from a previous configuration - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); response &= _zed->addCfgValset(UBLOX_CFG_RATE_MEAS, 1000); response &= _zed->addCfgValset(UBLOX_CFG_RATE_NAV, 1); @@ -706,7 +720,7 @@ bool GNSS_ZED::configureGNSS() response = true; // Reset // Disable NMEA messages on all but UART1 - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); response &= _zed->addCfgValset(UBLOX_CFG_MSGOUT_NMEA_ID_GGA_I2C, 0); response &= _zed->addCfgValset(UBLOX_CFG_MSGOUT_NMEA_ID_GSA_I2C, 0); @@ -737,13 +751,17 @@ bool GNSS_ZED::configureGNSS() if (response == false) systemPrintln("Module failed config block 3"); + success &= response; + if (success) { systemPrintln("ZED-F9x configuration update"); - // Save the current configuration into non-volatile memory (NVM) - saveConfiguration(); } + // The configuration should be saved to RAM+BBR+FLASH. No need to saveConfiguration here. + + settings.gnssConfiguredOnce = success; + return (success); } @@ -758,6 +776,13 @@ bool GNSS_ZED::configureRover() return (false); } + // If our settings haven't changed, and this is first config since power on, trust GNSS's settings + if (settings.gnssConfiguredRover) + { + systemPrintln("Skipping ZED Rover configuration"); + return (true); + } + update(); // Regularly poll to get latest data bool success = false; @@ -772,7 +797,7 @@ bool GNSS_ZED::configureRover() bool response = true; // Set output rate - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); response &= _zed->addCfgValset(UBLOX_CFG_RATE_MEAS, settings.measurementRateMs); response &= _zed->addCfgValset(UBLOX_CFG_RATE_NAV, settings.navigationRate); @@ -825,10 +850,11 @@ bool GNSS_ZED::configureRover() if (!success) systemPrintln("Rover config fail"); - else - // Save the current configuration into non-volatile memory (NVM) - saveConfiguration(); + // The configuration should be saved to RAM+BBR+FLASH. No need to saveConfiguration here. + + settings.gnssConfiguredRover = success; + return (success); } @@ -853,15 +879,16 @@ void GNSS_ZED::enableGgaForNtrip() if (online.gnss) { // Set the Main Talker ID to "GP". The NMEA GGA messages will be GPGGA instead of GNGGA - _zed->setVal8(UBLOX_CFG_NMEA_MAINTALKERID, 1); + _zed->setVal8(UBLOX_CFG_NMEA_MAINTALKERID, 1, VAL_LAYER_ALL); _zed->setNMEAGPGGAcallbackPtr(&zedPushGPGGA); // Set up the callback for GPGGA float measurementFrequency = (1000.0 / settings.measurementRateMs) / settings.navigationRate; if (measurementFrequency < 0.2) measurementFrequency = 0.2; // 0.2Hz * 5 = 1 measurement every 5 seconds - log_d("Adjusting GGA setting to %f", measurementFrequency); + if (settings.debugGnss) + systemPrintf("Adjusting GGA setting to %f\r\n", measurementFrequency); _zed->setVal8(UBLOX_CFG_MSGOUT_NMEA_ID_GGA_I2C, - measurementFrequency); // Enable GGA over I2C. Tell the module to output GGA every second + measurementFrequency, VAL_LAYER_ALL); // Enable GGA over I2C. Tell the module to output GGA every second } } @@ -874,7 +901,7 @@ bool GNSS_ZED::enableRTCMTest() { if (online.gnss) { - _zed->newCfgValset(); // Create a new Configuration Item VALSET message + _zed->newCfgValset(VAL_LAYER_RAM); // Create a new Configuration Item VALSET message _zed->addCfgValset(UBLOX_CFG_MSGOUT_RTCM_3X_TYPE1230_UART2, 1); // Enable message 1230 every second _zed->sendCfgValset(); // Send the VALSET return true; @@ -954,7 +981,7 @@ bool GNSS_ZED::fixedBaseStart() // Units are cm with a high precision extension so -1234.5678 should be called: (-123456, -78) //-1280208.308,-4716803.847,4086665.811 is SparkFun HQ so... - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); response &= _zed->addCfgValset(UBLOX_CFG_TMODE_MODE, 2); // Fixed response &= _zed->addCfgValset(UBLOX_CFG_TMODE_POS_TYPE, 0); // Position in ECEF response &= _zed->addCfgValset(UBLOX_CFG_TMODE_ECEF_X, majorEcefX); @@ -994,7 +1021,7 @@ bool GNSS_ZED::fixedBaseStart() // systemPrintf("major (should be 156022): %ld\r\n", majorAlt); // systemPrintf("minor (should be 84): %ld\r\n", minorAlt); - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); response &= _zed->addCfgValset(UBLOX_CFG_TMODE_MODE, 2); // Fixed response &= _zed->addCfgValset(UBLOX_CFG_TMODE_POS_TYPE, 1); // Position in LLH response &= _zed->addCfgValset(UBLOX_CFG_TMODE_LAT, majorLat); @@ -1941,7 +1968,7 @@ bool GNSS_ZED::setBaudrate(uint32_t baudRate) { if (online.gnss) return _zed->setVal32(UBLOX_CFG_UART1_BAUDRATE, - (115200 * 2)); // Defaults to 230400 to maximize message output support + (115200 * 2), VAL_LAYER_ALL); // Defaults to 230400 to maximize message output support return false; } @@ -1957,7 +1984,7 @@ bool GNSS_ZED::setConstellations() bool response = true; - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); // GPS int gnssIndex = ubxConstellationIDToIndex(SFE_UBLOX_GNSS_ID_GPS); @@ -2029,7 +2056,7 @@ bool GNSS_ZED::setCorrRadioExtPort(bool enable, bool force) if (force || (enable != _corrRadioExtPortEnabled)) { - bool response = _zed->newCfgValset(); + bool response = _zed->newCfgValset(VAL_LAYER_ALL); // Leave NMEA IN (poll requests) enabled so MON-COMMS skipped keeps updating response &= _zed->addCfgValset(UBLOX_CFG_UART2INPROT_NMEA, enable ? 0 : 1); @@ -2067,7 +2094,7 @@ bool GNSS_ZED::setCorrRadioExtPort(bool enable, bool force) bool GNSS_ZED::setDataBaudRate(uint32_t baud) { if (online.gnss) - return _zed->setVal32(UBLOX_CFG_UART1_BAUDRATE, baud); + return _zed->setVal32(UBLOX_CFG_UART1_BAUDRATE, baud, VAL_LAYER_ALL); return false; } @@ -2078,7 +2105,7 @@ bool GNSS_ZED::setElevation(uint8_t elevationDegrees) { if (online.gnss) { - _zed->setVal8(UBLOX_CFG_NAVSPG_INFIL_MINELEV, elevationDegrees); // Set minimum elevation + _zed->setVal8(UBLOX_CFG_NAVSPG_INFIL_MINELEV, elevationDegrees, VAL_LAYER_ALL); // Set minimum elevation return true; } return false; @@ -2156,7 +2183,7 @@ bool GNSS_ZED::setMessages(int maxRetries) while (messageNumber < MAX_UBX_MSG) { - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); do { @@ -2210,7 +2237,7 @@ bool GNSS_ZED::setMessagesUsb(int maxRetries) while (messageNumber < MAX_UBX_MSG) { - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); do { @@ -2239,7 +2266,7 @@ bool GNSS_ZED::setMinCnoRadio(uint8_t cnoValue) { if (online.gnss) { - _zed->setVal8(UBLOX_CFG_NAVSPG_INFIL_MINCNO, cnoValue); + _zed->setVal8(UBLOX_CFG_NAVSPG_INFIL_MINCNO, cnoValue, VAL_LAYER_ALL); return true; } return false; @@ -2252,7 +2279,7 @@ bool GNSS_ZED::setModel(uint8_t modelNumber) { if (online.gnss) { - _zed->setVal8(UBLOX_CFG_NAVSPG_DYNMODEL, (dynModel)modelNumber); // Set dynamic model + _zed->setVal8(UBLOX_CFG_NAVSPG_DYNMODEL, (dynModel)modelNumber, VAL_LAYER_ALL); // Set dynamic model return true; } return false; @@ -2262,7 +2289,7 @@ bool GNSS_ZED::setModel(uint8_t modelNumber) bool GNSS_ZED::setRadioBaudRate(uint32_t baud) { if (online.gnss) - return _zed->setVal32(UBLOX_CFG_UART2_BAUDRATE, baud); + return _zed->setVal32(UBLOX_CFG_UART2_BAUDRATE, baud, VAL_LAYER_ALL); return false; } @@ -2305,7 +2332,7 @@ bool GNSS_ZED::setRate(double secondsBetweenSolutions) // systemPrintf("measurementRate / navRate: %d / %d\r\n", measRate, navRate); bool response = true; - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); response &= _zed->addCfgValset(UBLOX_CFG_RATE_MEAS, measRate); response &= _zed->addCfgValset(UBLOX_CFG_RATE_NAV, navRate); @@ -2349,7 +2376,7 @@ bool GNSS_ZED::setTalkerGNGGA() { bool success = true; success &= - _zed->setVal8(UBLOX_CFG_NMEA_MAINTALKERID, 3); // Return talker ID to GNGGA after NTRIP Client set to GPGGA + _zed->setVal8(UBLOX_CFG_NMEA_MAINTALKERID, 3, VAL_LAYER_ALL); // Return talker ID to GNGGA after NTRIP Client set to GPGGA success &= _zed->setNMEAGPGGAcallbackPtr(nullptr); // Remove callback return success; } @@ -2564,11 +2591,11 @@ bool GNSS_ZED::surveyInReset() return (false); // Disable survey-in mode - response &= _zed->setVal8(UBLOX_CFG_TMODE_MODE, 0); + response &= _zed->setVal8(UBLOX_CFG_TMODE_MODE, 0, VAL_LAYER_ALL); delay(1000); // Enable Survey in with bogus values - response &= _zed->newCfgValset(); + response &= _zed->newCfgValset(VAL_LAYER_ALL); response &= _zed->addCfgValset(UBLOX_CFG_TMODE_MODE, 1); // Survey-in enable response &= _zed->addCfgValset(UBLOX_CFG_TMODE_SVIN_ACC_LIMIT, 40 * 10000); // 40.0m response &= _zed->addCfgValset(UBLOX_CFG_TMODE_SVIN_MIN_DUR, 1000); // 1000s @@ -2576,7 +2603,7 @@ bool GNSS_ZED::surveyInReset() delay(1000); // Disable survey-in mode - response &= _zed->setVal8(UBLOX_CFG_TMODE_MODE, 0); + response &= _zed->setVal8(UBLOX_CFG_TMODE_MODE, 0, VAL_LAYER_ALL); if (response == false) return (response); @@ -2603,7 +2630,7 @@ bool GNSS_ZED::surveyInStart() if (online.gnss == false) return (false); - _zed->setVal8(UBLOX_CFG_TMODE_MODE, 0); // Disable survey-in mode + _zed->setVal8(UBLOX_CFG_TMODE_MODE, 0, VAL_LAYER_ALL); // Disable survey-in mode delay(100); bool needSurveyReset = false; @@ -2631,9 +2658,9 @@ bool GNSS_ZED::surveyInStart() } bool response = true; - response &= _zed->setVal8(UBLOX_CFG_TMODE_MODE, 1); // Survey-in enable - response &= _zed->setVal32(UBLOX_CFG_TMODE_SVIN_ACC_LIMIT, settings.observationPositionAccuracy * 10000); - response &= _zed->setVal32(UBLOX_CFG_TMODE_SVIN_MIN_DUR, settings.observationSeconds); + response &= _zed->setVal8(UBLOX_CFG_TMODE_MODE, 1, VAL_LAYER_ALL); // Survey-in enable + response &= _zed->setVal32(UBLOX_CFG_TMODE_SVIN_ACC_LIMIT, settings.observationPositionAccuracy * 10000, VAL_LAYER_ALL); + response &= _zed->setVal32(UBLOX_CFG_TMODE_SVIN_MIN_DUR, settings.observationSeconds, VAL_LAYER_ALL); if (response == false) { @@ -2699,7 +2726,7 @@ void GNSS_ZED::updateCorrectionsSource(uint8_t source) // This is important. Retry if needed int retries = 0; - while ((!_zed->setVal8(UBLOX_CFG_SPARTN_USE_SOURCE, source)) && (retries < 3)) + while ((!_zed->setVal8(UBLOX_CFG_SPARTN_USE_SOURCE, source, VAL_LAYER_ALL)) && (retries < 3)) retries++; if (retries < 3) { From 56c24d6fc30a652519bd63adc5f01d66516aa025 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Feb 2025 13:30:23 +0000 Subject: [PATCH 241/276] Correct comment --- Firmware/RTK_Everywhere/GNSS_ZED.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.ino b/Firmware/RTK_Everywhere/GNSS_ZED.ino index 43c2dbdc4..294fdc60b 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.ino +++ b/Firmware/RTK_Everywhere/GNSS_ZED.ino @@ -776,7 +776,7 @@ bool GNSS_ZED::configureRover() return (false); } - // If our settings haven't changed, and this is first config since power on, trust GNSS's settings + // If our settings haven't changed, trust GNSS's settings if (settings.gnssConfiguredRover) { systemPrintln("Skipping ZED Rover configuration"); From cc8e3cf3dcb5b8bb08cbb0ec5525ba23a9f307e7 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Feb 2025 13:38:13 +0000 Subject: [PATCH 242/276] LG290P: add gnssConfiguredOnce/Base/Rover --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 42 +++++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index dcc1ceba1..ab09e22c9 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -211,6 +211,12 @@ bool GNSS_LG290P::configureOnce() Enable selected RTCM messages on COM2 */ + if (settings.gnssConfiguredOnce) + { + systemPrintln("LG290P configuration maintained"); + return (true); + } + if (settings.debugGnss) debuggingEnable(); // Print all debug to Serial @@ -248,11 +254,13 @@ bool GNSS_LG290P::configureOnce() systemPrintln("LG290P configuration updated"); // Save the current configuration into non-volatile memory (NVM) - saveConfiguration(); + response &= saveConfiguration(); } else online.gnss = false; // Take it offline + settings.gnssConfiguredOnce = response; + return (response); } @@ -272,6 +280,13 @@ bool GNSS_LG290P::configureRover() return (false); } + // If our settings haven't changed, and this is first config since power on, trust GNSS's settings + if (settings.gnssConfiguredRover) + { + systemPrintln("Skipping LG290P Rover configuration"); + return (true); + } + bool response = true; serialGNSS->flush(); // Remove any incoming characters @@ -314,15 +329,17 @@ bool GNSS_LG290P::configureRover() else { // Save the current configuration into non-volatile memory (NVM) - saveConfiguration(); + response &= saveConfiguration(); // For RTCM and MSM messages to take effect (ie, PointPerfect is active) we must save/reset softwareReset(); - if (settings.debugGnss) + if (settings.debugGnss && response) systemPrintln("LG290P Rover configured"); } + settings.gnssConfiguredRover = response; + return (response); } @@ -343,6 +360,13 @@ bool GNSS_LG290P::configureBase() return (false); } + if (settings.gnssConfiguredBase) + { + if (settings.debugGnss) + systemPrintln("Skipping LG290P Base configuration"); + return true; + } + bool response = true; serialGNSS->flush(); // Remove any incoming characters @@ -401,18 +425,20 @@ bool GNSS_LG290P::configureBase() else { // Save the current configuration into non-volatile memory (NVM) - saveConfiguration(); + response &= saveConfiguration(); softwareReset(); // When a device is changed from Rover to Base, NMEA messages settings do not survive PQTMSAVEPAR // Re-enable NMEA post reset - enableNMEA(); // Set NMEA messages + response &= enableNMEA(); // Set NMEA messages - if (settings.debugGnss) + if (settings.debugGnss && response) systemPrintln("LG290P Base configured"); } + settings.gnssConfiguredBase = response; + return (response); } @@ -1741,6 +1767,10 @@ void GNSS_LG290P::menuMessagesSubtype(int *localMessageRate, const char *message printUnknown(incoming); } + settings.gnssConfiguredOnce = false; // Update the GNSS config at the next boot + settings.gnssConfiguredBase = false; + settings.gnssConfiguredRover = false; + clearBuffer(); // Empty buffer of any newline chars } From e311c542de5d62b723a3fd00f6bdca8cfb4d055b Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Feb 2025 13:52:36 +0000 Subject: [PATCH 243/276] Correct comment --- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index ab09e22c9..90fcb0303 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -280,7 +280,7 @@ bool GNSS_LG290P::configureRover() return (false); } - // If our settings haven't changed, and this is first config since power on, trust GNSS's settings + // If our settings haven't changed, trust GNSS's settings if (settings.gnssConfiguredRover) { systemPrintln("Skipping LG290P Rover configuration"); From 1c4dd1febb2a39fcd6ea7db58b38f11869e5831a Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Feb 2025 13:58:36 +0000 Subject: [PATCH 244/276] mosaic: add gnssConfiguredOnce/Base/Rover --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 38 +++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 29ed408d9..d47fcc8b4 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -406,6 +406,13 @@ bool GNSS_MOSAIC::configureBase() return (false); } + if (settings.gnssConfiguredBase) + { + if (settings.debugGnss) + systemPrintln("Skipping mosaic Base configuration"); + return true; + } + bool response = true; response &= setModel(MOSAIC_DYN_MODEL_STATIC); @@ -421,13 +428,15 @@ bool GNSS_MOSAIC::configureBase() setLoggingType(); // Update Standard, PPP, or custom for icon selection // Save the current configuration into non-volatile memory (NVM) - saveConfiguration(); + response &= saveConfiguration(); if (response == false) { systemPrintln("mosaic-X5 Base failed to configure"); } + settings.gnssConfiguredBase = response; + return (response); } @@ -542,6 +551,12 @@ bool GNSS_MOSAIC::configureOnce() RTCMv3 messages are enabled by enableRTCMRover / enableRTCMBase */ + if (settings.gnssConfiguredOnce) + { + systemPrintln("mosaic configuration maintained"); + return (true); + } + bool response = true; // Configure COM1. NMEA and RTCMv3 will be encapsulated in SBF format @@ -589,11 +604,13 @@ bool GNSS_MOSAIC::configureOnce() systemPrintln("mosaic-X5 configuration updated"); // Save the current configuration into non-volatile memory (NVM) - saveConfiguration(); + response &= saveConfiguration(); } else online.gnss = false; // Take it offline + settings.gnssConfiguredOnce = response; + return (response); } @@ -635,6 +652,13 @@ bool GNSS_MOSAIC::configureRover() return (false); } + // If our settings haven't changed, trust GNSS's settings + if (settings.gnssConfiguredRover) + { + systemPrintln("Skipping mosaic Rover configuration"); + return (true); + } + bool response = true; response &= sendWithResponse("spm,Rover,all,auto\n\r", "PVTMode"); @@ -652,13 +676,15 @@ bool GNSS_MOSAIC::configureRover() setLoggingType(); // Update Standard, PPP, or custom for icon selection // Save the current configuration into non-volatile memory (NVM) - saveConfiguration(); + response &= saveConfiguration(); if (response == false) { systemPrintln("mosaic-X5 Rover failed to configure"); } + settings.gnssConfiguredRover = response; + return (response); } @@ -1697,6 +1723,9 @@ void GNSS_MOSAIC::menuMessagesNMEA() printUnknown(incoming); } + settings.gnssConfiguredBase = false; // Update the GNSS config at the next boot + settings.gnssConfiguredRover = false; + clearBuffer(); // Empty buffer of any newline chars } @@ -1766,6 +1795,9 @@ void GNSS_MOSAIC::menuMessagesRTCM(bool rover) printUnknown(incoming); } + settings.gnssConfiguredBase = false; // Update the GNSS config at the next boot + settings.gnssConfiguredRover = false; + clearBuffer(); // Empty buffer of any newline chars } From 9abe3306ac9e1bec086dd7827bf28e1431e154ea Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Feb 2025 14:20:51 +0000 Subject: [PATCH 245/276] UM980: add gnssConfiguredOnce/Base/Rover --- Firmware/RTK_Everywhere/GNSS_UM980.ino | 36 +++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_UM980.ino b/Firmware/RTK_Everywhere/GNSS_UM980.ino index a2dc112fb..4c59ecb58 100644 --- a/Firmware/RTK_Everywhere/GNSS_UM980.ino +++ b/Firmware/RTK_Everywhere/GNSS_UM980.ino @@ -166,6 +166,13 @@ bool GNSS_UM980::configureBase() return (false); } + if (settings.gnssConfiguredBase) + { + if (settings.debugGnss) + systemPrintln("Skipping UM980 Base configuration"); + return true; + } + disableAllOutput(); bool response = true; @@ -186,7 +193,7 @@ bool GNSS_UM980::configureBase() response &= enableNMEA(); // Save the current configuration into non-volatile memory (NVM) - _um980->saveConfiguration(); + response &= _um980->saveConfiguration(); if (response == false) { @@ -196,6 +203,8 @@ bool GNSS_UM980::configureBase() if (settings.debugGnss) systemPrintln("UM980 Base configured"); + settings.gnssConfiguredBase = response; + return (response); } @@ -216,6 +225,12 @@ bool GNSS_UM980::configureOnce() Enable selected RTCM messages on COM3 */ + if (settings.gnssConfiguredOnce) + { + systemPrintln("UM980 configuration maintained"); + return (true); + } + if (settings.debugGnss) debuggingEnable(); // Print all debug to Serial @@ -266,11 +281,13 @@ bool GNSS_UM980::configureOnce() systemPrintln("UM980 configuration updated"); // Save the current configuration into non-volatile memory (NVM) - _um980->saveConfiguration(); + response &= _um980->saveConfiguration(); } else online.gnss = false; // Take it offline + settings.gnssConfiguredOnce = response; + return (response); } @@ -325,6 +342,13 @@ bool GNSS_UM980::configureRover() return (false); } + // If our settings haven't changed, trust GNSS's settings + if (settings.gnssConfiguredRover) + { + systemPrintln("Skipping UM980 Rover configuration"); + return (true); + } + disableAllOutput(); bool response = true; @@ -355,13 +379,15 @@ bool GNSS_UM980::configureRover() response &= enableNMEA(); // Save the current configuration into non-volatile memory (NVM) - _um980->saveConfiguration(); + response &= _um980->saveConfiguration(); if (response == false) { systemPrintln("UM980 Rover failed to configure"); } + settings.gnssConfiguredRover = response; + return (response); } @@ -1407,6 +1433,10 @@ void GNSS_UM980::menuMessagesSubtype(float *localMessageRate, const char *messag printUnknown(incoming); } + settings.gnssConfiguredOnce = false; // Update the GNSS config at the next boot + settings.gnssConfiguredBase = false; + settings.gnssConfiguredRover = false; + clearBuffer(); // Empty buffer of any newline chars } From 2bc7f7087c9dd541abbde0c920c451b9d1cda1ac Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 14 Feb 2025 14:56:22 +0000 Subject: [PATCH 246/276] Add DEBUG_THE_ESSENTIALS --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 541c96b65..d418fcc00 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -973,6 +973,51 @@ volatile bool deadManWalking; settings.printTaskStartStop = true; \ } +//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +// Debug the essentials. Include DEBUG_THE_ESSENTIALS in the setup after loadSettings to print the essentials. +// If the updated settings are saved to NVM, you will need to do a factory reset to clear them +#define DEBUG_THE_ESSENTIALS \ + { \ + \ + /* Turn on nearly all the debug prints */ \ + settings.debugCorrections = true; \ + settings.debugGnss = false; \ + settings.debugHttpClientData = false; \ + settings.debugHttpClientState = true; \ + settings.debugLora = false; \ + settings.debugMqttClientData = false; \ + settings.debugMqttClientState = true; \ + settings.debugNetworkLayer = true; \ + settings.debugNtripClientRtcm = false; \ + settings.debugNtripClientState = true; \ + settings.debugNtripServerRtcm = false; \ + settings.debugNtripServerState = true; \ + settings.debugPpCertificate = false; \ + settings.debugSettings = false; \ + settings.debugTcpClient = true; \ + settings.debugTcpServer = true; \ + settings.debugUdpServer = true; \ + settings.debugWebServer = true; \ + settings.debugWifiState = true; \ + settings.enableHeapReport = false; \ + settings.enablePrintBatteryMessages = false; \ + settings.enablePrintBufferOverrun = true; \ + settings.enablePrintDuplicateStates = false; \ + settings.enablePrintEthernetDiag = true; \ + settings.enablePrintIdleTime = false; \ + settings.enablePrintLogFileMessages = false; \ + settings.enablePrintLogFileStatus = true; \ + settings.enablePrintPosition = false; \ + settings.enablePrintRingBufferOffsets = false; \ + settings.enablePrintRoverAccuracy = true; \ + settings.enablePrintRtcSync = true; \ + settings.enablePrintSDBuffers = false; \ + settings.enablePrintStates = true; \ + settings.printBootTimes = true; \ + settings.printNetworkStatus = true; \ + settings.printTaskStartStop = true; \ + } + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- /* +---------------------------------------+ +----------+ @@ -1136,6 +1181,7 @@ void setup() loadSettings(); // Attempt to load settings after SD is started so we can read the settings file if available //DEBUG_NEARLY_EVERYTHING // Debug nearly all the things + DEBUG_THE_ESSENTIALS // Debug the essentials - handy for measuring the boot time after a factory reset DMW_b("checkArrayDefaults"); checkArrayDefaults(); // Check for uninitialized arrays that won't be initialized by gnssConfigure From 3c8e480b52c95e2c9079f6bc7a686036718aacf6 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 14 Feb 2025 13:05:25 -0700 Subject: [PATCH 247/276] Remove GST modification New "v04 beta" firmware fixes the GST issue so this is no longer needed. --- Firmware/RTK_Everywhere/Developer.ino | 1 - Firmware/RTK_Everywhere/GNSS_LG290P.ino | 134 ------------------------ Firmware/RTK_Everywhere/Tasks.ino | 3 - 3 files changed, 138 deletions(-) diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino index 4b161b95c..edd72d944 100644 --- a/Firmware/RTK_Everywhere/Developer.ino +++ b/Firmware/RTK_Everywhere/Developer.ino @@ -277,7 +277,6 @@ void pointperfectPrintKeyInformation() {systemPrintln("**PPL Not Compiled**");} #ifndef COMPILE_LG290P void lg290pHandler(uint8_t * buffer, int length) {} -void lg290pModifyGst(char *nmeaSentence, uint16_t *sentenceLength) {} #endif // COMPILE_LG290P diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index ba3b11eba..86b98d63e 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -2217,137 +2217,3 @@ bool lg290pMessageEnabled(char *nmeaSentence, int sentenceLength) // If we can't ID this message, allow it by default. The device configuration should control most message flow. return (true); } - -// Re-create the GST sentence to increase the horizontal and vertical precision number of decimals -// ie, 0.0 becomes 0.009 -// See issue: https://github.com/sparkfun/SparkFun_RTK_Everywhere_Firmware/issues/513 -// $GNGST,223954.500,1.7,1.5,1.0,109.3,1.412,1.055,2.4*7E -// Modifies the sentence length with new length -void lg290pModifyGst(char *nmeaSentence, uint16_t *sentenceLength) -{ - // This issue currently only applies to LG290P firmware version 4 - // Version 3 does not support GST messages. Version 5 should fix the issue. - if (lg290pFirmwareVersion != 4) - return; - - if (online.gnss == false) - return; - - // Only apply the GST patch if our HPA is very small (<0.1m), ie RTK Float or Fix. - if (gnss->isRTKFix() == false && gnss->isRTKFloat() == false) - return; - - GNSS_LG290P *lg290p = (GNSS_LG290P *)gnss; - - // Identify sentence type - char sentenceType[strlen("GST") + 1] = {0}; - strncpy(sentenceType, &nmeaSentence[3], - 3); // Copy three letters, starting in spot 3. Null terminated from array initializer. - - // We only care about GST sentences - if (strncmp(sentenceType, "GST", sizeof(sentenceType)) != 0) - return; - - const int latitudeErrorComma = 6; - const int longitudeErrorComma = 7; - const int altitudeErrorComma = 8; - - uint8_t latitudeStart = 0; - uint8_t latitudeStop = 0; - uint8_t longitudeStart = 0; - uint8_t longitudeStop = 0; - uint8_t altitudeStart = 0; - uint8_t checksumStart = 0; - - if (settings.enableImuCompensationDebug == true && !inMainMenu) - systemPrintf("Original GNGST:\r\n%s\r\n", nmeaSentence); - - int commaCount = 0; - for (int x = 0; x < strnlen(nmeaSentence, *sentenceLength); x++) // Assumes sentence is null terminated - { - if (nmeaSentence[x] == ',') - { - commaCount++; - if (commaCount == latitudeErrorComma) - latitudeStart = x + 1; - if (commaCount == latitudeErrorComma + 1) - latitudeStop = x; - if (commaCount == longitudeErrorComma) - longitudeStart = x + 1; - if (commaCount == longitudeErrorComma + 1) - longitudeStop = x; - if (commaCount == altitudeErrorComma) - altitudeStart = x + 1; - } - if (nmeaSentence[x] == '*') - { - checksumStart = x; - break; - } - } - - if (latitudeStart == 0 || latitudeStop == 0 || longitudeStart == 0 || longitudeStop == 0 || altitudeStart == 0 || - checksumStart == 0) - { - systemPrintln("Delineator not found"); - return; - } - - char newSentence[150] = {0}; - - if (sizeof(newSentence) < *sentenceLength) - { - systemPrintln("newSentence not big enough!"); - return; - } - - char errorString[strlen("0.000") + 1] = {0}; - - // strncat terminates - - // Add start of message up to latitude - strncat(newSentence, nmeaSentence, latitudeStart); - - // Convert error from EPE message to string. We don't have pure lat error, only 2D and 3D. - snprintf(errorString, sizeof(errorString), "%0.3f", lg290p->getHorizontalAccuracy()); - - // Add latitude error - strncat(newSentence, errorString, sizeof(newSentence) - 1); - - // Add interstitial between end of lat and beginning of lon - strncat(newSentence, nmeaSentence + latitudeStop, longitudeStart - latitudeStop); - - // Add same error for longitude error - strncat(newSentence, errorString, sizeof(newSentence) - 1); - - // Add interstitial between end of lon and beginning of alt - strncat(newSentence, nmeaSentence + longitudeStop, altitudeStart - longitudeStop); - - // Convert error from EPE message to string. We don't have pure altitude error, use double 2D error as stand-in. - snprintf(errorString, sizeof(errorString), "%0.3f", lg290p->getHorizontalAccuracy() * 2); - - // Add altitude error. We don't really have altitude so use 3D error in its place. - strncat(newSentence, errorString, sizeof(newSentence) - 1); - - // From: http://engineeringnotes.blogspot.com/2015/02/generate-crc-for-nmea-strings-arduino.html - byte CRC = 0; // XOR chars between '$' and '*' - for (byte x = 1; x < strlen(newSentence); x++) - CRC = CRC ^ newSentence[x]; - - // Convert CRC to string, add * and CR LF - snprintf(errorString, sizeof(errorString), "*%02X\r\n", CRC); - - // Add CRC - strncat(newSentence, errorString, sizeof(newSentence) - 1); - - // Increase length of sentence - *sentenceLength = strlen(newSentence); - - // Overwrite the original NMEA - strncpy(nmeaSentence, newSentence, *sentenceLength); - - nmeaSentence[*sentenceLength] = '\0'; // Terminate string - - if (settings.enableImuCompensationDebug == true && !inMainMenu) - systemPrintf("Corrected GNGST:\r\n%s\r\n", nmeaSentence); -} \ No newline at end of file diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino index f470d8c7a..d372e98d4 100644 --- a/Firmware/RTK_Everywhere/Tasks.ino +++ b/Firmware/RTK_Everywhere/Tasks.ino @@ -650,9 +650,6 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type) parse->buffer[0] = 0; parse->length = 0; } - - // Gimme three decimals! - lg290pModifyGst((char *)parse->buffer, &parse->length); } } From d6891502367d4150a0f98f286f5b919922f780b2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 14 Feb 2025 20:16:00 +0000 Subject: [PATCH 248/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index 82b363187..8b7fb9f46 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x8C, 0x6B, 0xAB, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0x80, 0xA4, 0xAF, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -1049,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x8C, 0x6B, 0xAB, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0x80, 0xA4, 0xAF, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From fd3965ed3c7456e9547b16ec17decca42b7edc5b Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Fri, 14 Feb 2025 15:49:31 -0700 Subject: [PATCH 249/276] Add PQTM variable. A previous commit added the ability to set the PQTM messages but leveraged the NMEA variable type. Upon startup, the PQTM settings weren't loading, which lead to default settings being applied (ie, GNSS output was reset to 2Hz regardless of user settings). Now the settings work as expected. --- Firmware/RTK_Everywhere/NVM.ino | 24 ++++++++++++ Firmware/RTK_Everywhere/menuCommands.ino | 49 ++++++++++++++++++++++++ Firmware/RTK_Everywhere/settings.h | 3 +- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index 9ec2b9d01..746a7f9f4 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -616,6 +616,17 @@ void recordSystemSettingsToFile(File *settingsFile) } } break; + case tLgMRPqtm: { + // Record LG290P PQTM rates + for (int x = 0; x < rtkSettingsEntries[i].qualifier; x++) + { + char tempString[50]; // lg290pMessageRatesPQTM_EPE=1 + snprintf(tempString, sizeof(tempString), "%s%s=%d", rtkSettingsEntries[i].name, + lgMessagesPQTM[x].msgTextName, settings.lg290pMessageRatesPQTM[x]); + settingsFile->println(tempString); + } + } + break; case tLgConst: { // Record LG290P Constellations for (int x = 0; x < rtkSettingsEntries[i].qualifier; x++) @@ -1481,6 +1492,19 @@ bool parseLine(char *str) } } break; + case tLgMRPqtm: { + for (int x = 0; x < qualifier; x++) + { + if ((suffix[0] == lgMessagesPQTM[x].msgTextName[0]) && + (strcmp(suffix, lgMessagesPQTM[x].msgTextName) == 0)) + { + settings.lg290pMessageRatesPQTM[x] = d; + knownSetting = true; + break; + } + } + } + break; case tLgConst: { for (int x = 0; x < qualifier; x++) { diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino index 4e004d265..01bc362c6 100644 --- a/Firmware/RTK_Everywhere/menuCommands.ino +++ b/Firmware/RTK_Everywhere/menuCommands.ino @@ -1076,6 +1076,19 @@ SettingValueResponse updateSettingWithValue(bool inCommands, const char *setting } } break; + case tLgMRPqtm: { + for (int x = 0; x < qualifier; x++) + { + if ((suffix[0] == lgMessagesPQTM[x].msgTextName[0]) && + (strcmp(suffix, lgMessagesPQTM[x].msgTextName) == 0)) + { + settings.lg290pMessageRatesPQTM[x] = settingValue; + knownSetting = true; + break; + } + } + } + break; case tLgConst: { for (int x = 0; x < qualifier; x++) { @@ -1868,6 +1881,17 @@ void createSettingsString(char *newSettings) } } break; + case tLgMRPqtm: { + // Record LG290P PQTM rates + for (int x = 0; x < rtkSettingsEntries[i].qualifier; x++) + { + char tempString[50]; // lg290pMessageRatesPQTM_EPE=1 Not a float + snprintf(tempString, sizeof(tempString), "%s%s,%d,", rtkSettingsEntries[i].name, + lgMessagesPQTM[x].msgTextName, settings.lg290pMessageRatesPQTM[x]); + stringRecord(newSettings, tempString); + } + } + break; case tLgConst: { // Record LG290P Constellations // lg290pConstellations are uint8_t, but here we have to convert to bool (true / false) so the web page @@ -2732,6 +2756,19 @@ SettingValueResponse getSettingValue(bool inCommands, const char *settingName, c } } break; + case tLgMRPqtm: { + for (int x = 0; x < qualifier; x++) + { + if ((suffix[0] == lgMessagesPQTM[x].msgTextName[0]) && + (strcmp(suffix, lgMessagesPQTM[x].msgTextName) == 0)) + { + writeToString(settingValueStr, settings.lg290pMessageRatesPQTM[x]); + knownSetting = true; + break; + } + } + } + break; case tLgConst: { for (int x = 0; x < qualifier; x++) { @@ -3278,6 +3315,18 @@ void commandList(bool inCommands, int i) } } break; + case tLgMRPqtm: { + // Record LG290P PQTM rates + for (int x = 0; x < rtkSettingsEntries[i].qualifier; x++) + { + snprintf(settingName, sizeof(settingName), "%s%s", rtkSettingsEntries[i].name, + lgMessagesPQTM[x].msgTextName); + + getSettingValue(inCommands, settingName, settingValue); + commandSendExecuteListResponse(settingName, "uint8_t", settingValue); + } + } + break; case tLgConst: { // Record LG290P Constellations for (int x = 0; x < rtkSettingsEntries[i].qualifier; x++) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 0a37ac5de..5e8529117 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -1066,6 +1066,7 @@ typedef enum { tLgMRNmea, tLgMRRvRT, tLgMRBaRT, + tLgMRPqtm, tLgConst, // Add new settings types above <----------------> // (Maintain the enum of existing settings types!) @@ -1607,7 +1608,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 0, 1, 1, 0, 0, 0, 0, 0, 1, tLgMRNmea, MAX_LG290P_NMEA_MSG, & settings.lg290pMessageRatesNMEA, "messageRateNMEA_", }, { 0, 1, 1, 0, 0, 0, 0, 0, 1, tLgMRBaRT, MAX_LG290P_RTCM_MSG, & settings.lg290pMessageRatesRTCMBase, "messageRateRTCMBase_", }, { 0, 1, 1, 0, 0, 0, 0, 0, 1, tLgMRRvRT, MAX_LG290P_RTCM_MSG, & settings.lg290pMessageRatesRTCMRover, "messageRateRTCMRover_", }, - { 0, 1, 1, 0, 0, 0, 0, 0, 1, tLgMRNmea, MAX_LG290P_PQTM_MSG, & settings.lg290pMessageRatesPQTM, "messageRatePQTM_", }, + { 0, 1, 1, 0, 0, 0, 0, 0, 1, tLgMRPqtm, MAX_LG290P_PQTM_MSG, & settings.lg290pMessageRatesPQTM, "messageRatePQTM_", }, #endif // COMPILE_LG290P { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugSettings, "debugSettings", }, From 14161b66e8709b9aa8d52b22decc34ecd165733a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 14 Feb 2025 22:51:09 +0000 Subject: [PATCH 250/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index 8b7fb9f46..d316e55a8 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x80, 0xA4, 0xAF, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0xDC, 0xC8, 0xAF, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -1049,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0x80, 0xA4, 0xAF, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0xDC, 0xC8, 0xAF, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From bd263e299bf896f39b16de80748a920dc26917c0 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 17 Feb 2025 10:31:55 +0000 Subject: [PATCH 251/276] Correct use of pplNewSpartnLBand --- Firmware/RTK_Everywhere/PointPerfectLibrary.ino | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Firmware/RTK_Everywhere/PointPerfectLibrary.ino b/Firmware/RTK_Everywhere/PointPerfectLibrary.ino index 32131d8de..0dad72627 100644 --- a/Firmware/RTK_Everywhere/PointPerfectLibrary.ino +++ b/Firmware/RTK_Everywhere/PointPerfectLibrary.ino @@ -19,14 +19,11 @@ void updatePplTask(void *e) systemPrintln("UpdatePplTask running"); } - if (pplNewRtcmNmea || pplNewSpartnMqtt || pplNewSpartnMqtt) // Decide when to call PPL_GetRTCMOutput + if (pplNewRtcmNmea || pplNewSpartnMqtt || pplNewSpartnLBand) // Decide when to call PPL_GetRTCMOutput { - if (pplNewRtcmNmea) - pplNewRtcmNmea = false; - if (pplNewSpartnMqtt) - pplNewSpartnMqtt = false; - if (pplNewSpartnLBand) - pplNewSpartnLBand = false; + pplNewRtcmNmea = false; + pplNewSpartnMqtt = false; + pplNewSpartnLBand = false; uint32_t rtcmLength; From 1711c446deaa4137261fad38cb9e4f266e93d27a Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 17 Feb 2025 10:32:42 +0000 Subject: [PATCH 252/276] Add dynamic model icons for um980 and mosaicX5 --- Firmware/RTK_Everywhere/Display.ino | 142 +++++++++++++++++++--------- 1 file changed, 99 insertions(+), 43 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index f1dae8a94..69f9107a1 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -1507,58 +1507,114 @@ void paintClockAccuracy(displayCoords textCoords) // Draw the rover icon depending on screen void paintDynamicModel(std::vector *iconList) { - if (online.gnss == true) + if (present.dynamicModel && online.gnss) { iconPropertyBlinking prop; + prop.icon.bitmap = nullptr; // Use this as the test a valid icon prop.duty = 0b11111111; - // Display icon associated with current Dynamic Model - switch (settings.dynamicModel) + if (present.gnss_zedf9p) { - default: - break; - #ifdef COMPILE_ZED - case (DYN_MODEL_PORTABLE): - prop.icon = DynamicModel_1_Properties.iconDisplay[present.display_type]; - break; - case (DYN_MODEL_STATIONARY): - prop.icon = DynamicModel_2_Properties.iconDisplay[present.display_type]; - break; - case (DYN_MODEL_PEDESTRIAN): - prop.icon = DynamicModel_3_Properties.iconDisplay[present.display_type]; - break; - case (DYN_MODEL_AUTOMOTIVE): - prop.icon = DynamicModel_4_Properties.iconDisplay[present.display_type]; - break; - case (DYN_MODEL_SEA): - prop.icon = DynamicModel_5_Properties.iconDisplay[present.display_type]; - break; - case (DYN_MODEL_AIRBORNE1g): - prop.icon = DynamicModel_6_Properties.iconDisplay[present.display_type]; - break; - case (DYN_MODEL_AIRBORNE2g): - prop.icon = DynamicModel_7_Properties.iconDisplay[present.display_type]; - break; - case (DYN_MODEL_AIRBORNE4g): - prop.icon = DynamicModel_8_Properties.iconDisplay[present.display_type]; - break; - case (DYN_MODEL_WRIST): - prop.icon = DynamicModel_9_Properties.iconDisplay[present.display_type]; - break; - case (DYN_MODEL_BIKE): - prop.icon = DynamicModel_10_Properties.iconDisplay[present.display_type]; - break; - case (DYN_MODEL_MOWER): - prop.icon = DynamicModel_11_Properties.iconDisplay[present.display_type]; - break; - case (DYN_MODEL_ESCOOTER): - prop.icon = DynamicModel_12_Properties.iconDisplay[present.display_type]; - break; + // Display icon associated with current Dynamic Model + switch (settings.dynamicModel) + { + default: + break; + + case (DYN_MODEL_PORTABLE): // 0 + prop.icon = DynamicModel_1_Properties.iconDisplay[present.display_type]; + break; + case (DYN_MODEL_STATIONARY): // 2 + prop.icon = DynamicModel_2_Properties.iconDisplay[present.display_type]; + break; + case (DYN_MODEL_PEDESTRIAN): + prop.icon = DynamicModel_3_Properties.iconDisplay[present.display_type]; + break; + case (DYN_MODEL_AUTOMOTIVE): + prop.icon = DynamicModel_4_Properties.iconDisplay[present.display_type]; + break; + case (DYN_MODEL_SEA): + prop.icon = DynamicModel_5_Properties.iconDisplay[present.display_type]; + break; + case (DYN_MODEL_AIRBORNE1g): + prop.icon = DynamicModel_6_Properties.iconDisplay[present.display_type]; + break; + case (DYN_MODEL_AIRBORNE2g): + prop.icon = DynamicModel_7_Properties.iconDisplay[present.display_type]; + break; + case (DYN_MODEL_AIRBORNE4g): + prop.icon = DynamicModel_8_Properties.iconDisplay[present.display_type]; + break; + case (DYN_MODEL_WRIST): + prop.icon = DynamicModel_9_Properties.iconDisplay[present.display_type]; + break; + case (DYN_MODEL_BIKE): + prop.icon = DynamicModel_10_Properties.iconDisplay[present.display_type]; + break; + case (DYN_MODEL_MOWER): + prop.icon = DynamicModel_11_Properties.iconDisplay[present.display_type]; + break; + case (DYN_MODEL_ESCOOTER): + prop.icon = DynamicModel_12_Properties.iconDisplay[present.display_type]; + break; + } #endif // COMPILE_ZED } + else if (present.gnss_um980) + { +#ifdef COMPILE_UM980 + // Display icon associated with current Dynamic Model + switch (settings.dynamicModel) + { + default: + break; - iconList->push_back(prop); + case UM980_DYN_MODEL_SURVEY: + prop.icon = DynamicModel_2_Properties.iconDisplay[present.display_type]; // Stationary + break; + case UM980_DYN_MODEL_UAV: + prop.icon = DynamicModel_6_Properties.iconDisplay[present.display_type]; // Airborne1g + break; + case UM980_DYN_MODEL_AUTOMOTIVE: + prop.icon = DynamicModel_4_Properties.iconDisplay[present.display_type]; // Automotive + break; + } +#endif // COMPILE_UM980 + } + else if (present.gnss_mosaicX5) + { +#ifdef COMPILE_MOSAICX5 + // Display icon associated with current Dynamic Model + switch (settings.dynamicModel) + { + default: + break; + + case MOSAIC_DYN_MODEL_STATIC: + case MOSAIC_DYN_MODEL_QUASISTATIC: + prop.icon = DynamicModel_2_Properties.iconDisplay[present.display_type]; // Stationary + break; + case MOSAIC_DYN_MODEL_PEDESTRIAN: + prop.icon = DynamicModel_3_Properties.iconDisplay[present.display_type]; // Pedestrian + break; + case MOSAIC_DYN_MODEL_AUTOMOTIVE: + case MOSAIC_DYN_MODEL_RACECAR: + case MOSAIC_DYN_MODEL_HEAVYMACHINERY: + prop.icon = DynamicModel_4_Properties.iconDisplay[present.display_type]; // Automotive + break; + case MOSAIC_DYN_MODEL_UAV: + prop.icon = DynamicModel_6_Properties.iconDisplay[present.display_type]; // Airborne1g + break; + case MOSAIC_DYN_MODEL_UNLIMITED: + prop.icon = DynamicModel_8_Properties.iconDisplay[present.display_type]; // Airborne4g + break; + } +#endif // COMPILE_MOSAICX5 + } + + if (prop.icon.bitmap) + iconList->push_back(prop); } } From 43a5665510750696a8f910f59437a376dcc15935 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 17 Feb 2025 11:08:58 +0000 Subject: [PATCH 253/276] paintLogging: default to LOGGING_STANDARD --- Firmware/RTK_Everywhere/Display.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 69f9107a1..992fedaea 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -1861,10 +1861,6 @@ void paintLogging(std::vector *iconList, bool pulse, bool { prop.icon = LoggingNTPIconProperties.iconDisplay[loggingIconDisplayed][present.display_type]; } - else if (loggingType == LOGGING_STANDARD) - { - prop.icon = LoggingIconProperties.iconDisplay[loggingIconDisplayed][present.display_type]; - } else if (loggingType == LOGGING_PPP) { prop.icon = LoggingPPPIconProperties.iconDisplay[loggingIconDisplayed][present.display_type]; @@ -1873,6 +1869,10 @@ void paintLogging(std::vector *iconList, bool pulse, bool { prop.icon = LoggingCustomIconProperties.iconDisplay[loggingIconDisplayed][present.display_type]; } + else // if (loggingType == LOGGING_STANDARD) + { + prop.icon = LoggingIconProperties.iconDisplay[loggingIconDisplayed][present.display_type]; + } iconList->push_back(prop); } From c71fbda7fcd38c57f5df222f3931ce64a2d31853 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 17 Feb 2025 11:28:05 +0000 Subject: [PATCH 254/276] Initialize loggingType. Improve paintLogging --- Firmware/RTK_Everywhere/Display.ino | 16 +++++++++------- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 992fedaea..385d64aad 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -1853,6 +1853,7 @@ void paintLogging(std::vector *iconList, bool pulse, bool loggingIconDisplayed %= LOGGING_ICON_STATES; // Wrap iconPropertyBlinking prop; + prop.icon.bitmap = nullptr; prop.duty = 0b11111111; if (((online.logging == true) && (logIncreasing || ntpLogIncreasing)) || (present.gnss_mosaicX5 && logIncreasing)) @@ -1861,6 +1862,10 @@ void paintLogging(std::vector *iconList, bool pulse, bool { prop.icon = LoggingNTPIconProperties.iconDisplay[loggingIconDisplayed][present.display_type]; } + else if (loggingType == LOGGING_STANDARD) + { + prop.icon = LoggingIconProperties.iconDisplay[loggingIconDisplayed][present.display_type]; + } else if (loggingType == LOGGING_PPP) { prop.icon = LoggingPPPIconProperties.iconDisplay[loggingIconDisplayed][present.display_type]; @@ -1869,18 +1874,15 @@ void paintLogging(std::vector *iconList, bool pulse, bool { prop.icon = LoggingCustomIconProperties.iconDisplay[loggingIconDisplayed][present.display_type]; } - else // if (loggingType == LOGGING_STANDARD) - { - prop.icon = LoggingIconProperties.iconDisplay[loggingIconDisplayed][present.display_type]; - } - - iconList->push_back(prop); + // Could be LOGGING_UNKNOWN } else if (pulse) { prop.icon = PulseIconProperties.iconDisplay[loggingIconDisplayed][present.display_type]; - iconList->push_back(prop); } + + if (prop.icon.bitmap) + iconList->push_back(prop); } // Survey in is running. Show 3D Mean and elapsed time. diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index d418fcc00..7509dae23 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -280,7 +280,7 @@ typedef enum LoggingType LOGGING_PPP, LOGGING_CUSTOM } LoggingType; -LoggingType loggingType; +LoggingType loggingType = LOGGING_UNKNOWN; SdFile *managerTempFile = nullptr; // File used for uploading or downloading in the file manager section of AP config bool managerFileOpen = false; @@ -936,7 +936,7 @@ volatile bool deadManWalking; \ /* Turn on nearly all the debug prints */ \ settings.debugCorrections = true; \ - settings.debugGnss = false; \ + settings.debugGnss = true; \ settings.debugHttpClientData = true; \ settings.debugHttpClientState = true; \ settings.debugLora = true; \ @@ -981,7 +981,7 @@ volatile bool deadManWalking; \ /* Turn on nearly all the debug prints */ \ settings.debugCorrections = true; \ - settings.debugGnss = false; \ + settings.debugGnss = true; \ settings.debugHttpClientData = false; \ settings.debugHttpClientState = true; \ settings.debugLora = false; \ From bffb223cb81632d6afd43dd8b612f221340ed1b3 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 17 Feb 2025 11:52:59 +0000 Subject: [PATCH 255/276] mosaicX5 : call setLoggingType when skipping configuration --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index d47fcc8b4..38d3cc9c0 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -408,8 +408,8 @@ bool GNSS_MOSAIC::configureBase() if (settings.gnssConfiguredBase) { - if (settings.debugGnss) - systemPrintln("Skipping mosaic Base configuration"); + systemPrintln("Skipping mosaic Base configuration"); + setLoggingType(); // Needed because logUpdate exits early and never calls setLoggingType return true; } @@ -656,6 +656,7 @@ bool GNSS_MOSAIC::configureRover() if (settings.gnssConfiguredRover) { systemPrintln("Skipping mosaic Rover configuration"); + setLoggingType(); // Needed because logUpdate exits early and never calls setLoggingType return (true); } From 3af1a848414f734cf44393d5985ffb598eca6f2b Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 17 Feb 2025 16:07:29 +0000 Subject: [PATCH 256/276] Change gnssConfiguredOnce/Base/Rover to signatures E.g. on the mosaic, the Rover settings must be reapplied when settings.enablePointPerfectCorrections becomes true... Otherwise the required RTCM messages are never enabled... --- Firmware/RTK_Everywhere/Display.ino | 4 +-- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 48 +++++++++++++++++++++---- Firmware/RTK_Everywhere/GNSS_ZED.ino | 43 +++++++++++++++++----- Firmware/RTK_Everywhere/NVM.ino | 24 ++++++------- Firmware/RTK_Everywhere/States.ino | 28 +++++++-------- Firmware/RTK_Everywhere/menuMain.ino | 4 +-- Firmware/RTK_Everywhere/settings.h | 17 +++++---- 7 files changed, 117 insertions(+), 51 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 385d64aad..8942cb00c 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -2442,8 +2442,8 @@ void paintProfile(uint8_t profileUnit) if (profileNumber >= 0) { - settings.gnssConfiguredBase = false; // On the next boot, reapply all settings - settings.gnssConfiguredRover = false; + settings.gnssConfiguredBase = 0; // On the next boot, reapply all settings + settings.gnssConfiguredRover = 0; recordSystemSettings(); // Before switching, we need to record the current settings to LittleFS and SD recordProfileNumber( diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 38d3cc9c0..c6b5b394e 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -389,6 +389,18 @@ bool GNSS_MOSAIC::checkPPPRates() // Outputs: // Returns true if successfully configured and false upon failure //---------------------------------------- +// If any of the settings in the signature have changed, reapply the Base configuration +// See GNSS_MOSAIC_ROVER_SIGNATURE as an example +#define GNSS_MOSAIC_BASE_SIGNATURE \ + ( \ + ((settings.minElev & 0x01) << 1) \ + | ((settings.enableGnssToUsbSerial & 0x01) << 2) \ + | ((settings.enablePointPerfectCorrections & 0x01) << 3) \ + | ((settings.ntripClient_TransmitGGA & 0x01) << 4) \ + | ((settings.enableLogging & 0x01) << 5) \ + | ((settings.enableLoggingRINEX & 0x01) << 6) \ + | ((settings.enableExternalHardwareEventLogging & 0x01) << 7) \ + ) bool GNSS_MOSAIC::configureBase() { /* @@ -406,7 +418,7 @@ bool GNSS_MOSAIC::configureBase() return (false); } - if (settings.gnssConfiguredBase) + if (settings.gnssConfiguredBase == 0x01 | GNSS_MOSAIC_BASE_SIGNATURE) { systemPrintln("Skipping mosaic Base configuration"); setLoggingType(); // Needed because logUpdate exits early and never calls setLoggingType @@ -435,7 +447,10 @@ bool GNSS_MOSAIC::configureBase() systemPrintln("mosaic-X5 Base failed to configure"); } - settings.gnssConfiguredBase = response; + if (response) + settings.gnssConfiguredBase = 0x01 | GNSS_MOSAIC_BASE_SIGNATURE; + else + settings.gnssConfiguredBase = 0; return (response); } @@ -539,6 +554,12 @@ bool GNSS_MOSAIC::configureLBand(bool enableLBand, uint32_t LBandFreq) // Outputs: // Returns true if successfully configured and false upon failure //---------------------------------------- +// If any of the settings in the signature have changed, reapply the configuration +// See GNSS_MOSAIC_ROVER_SIGNATURE as an example +#define GNSS_MOSAIC_ONCE_SIGNATURE \ + ( \ + 0 \ + ) bool GNSS_MOSAIC::configureOnce() { /* @@ -551,7 +572,7 @@ bool GNSS_MOSAIC::configureOnce() RTCMv3 messages are enabled by enableRTCMRover / enableRTCMBase */ - if (settings.gnssConfiguredOnce) + if (settings.gnssConfiguredOnce == 0x01 | GNSS_MOSAIC_ONCE_SIGNATURE) { systemPrintln("mosaic configuration maintained"); return (true); @@ -609,7 +630,10 @@ bool GNSS_MOSAIC::configureOnce() else online.gnss = false; // Take it offline - settings.gnssConfiguredOnce = response; + if (response) + settings.gnssConfiguredOnce = 0x01 | GNSS_MOSAIC_ONCE_SIGNATURE; + else + settings.gnssConfiguredOnce = 0; return (response); } @@ -638,6 +662,15 @@ bool GNSS_MOSAIC::configureGNSS() // Outputs: // Returns true if successfully configured and false upon failure //---------------------------------------- +// If any of the settings in the signature have changed, reapply the Rover configuration +#define GNSS_MOSAIC_ROVER_SIGNATURE \ + ( \ + ((settings.enablePointPerfectCorrections & 0x01) << 1) \ + | ((settings.enableGnssToUsbSerial & 0x01) << 2) \ + | ((settings.ntripClient_TransmitGGA & 0x01) << 3) \ + | ((settings.enableLogging & 0x01) << 4) \ + | ((settings.enableExternalHardwareEventLogging & 0x01) << 5) \ + ) bool GNSS_MOSAIC::configureRover() { /* @@ -653,7 +686,7 @@ bool GNSS_MOSAIC::configureRover() } // If our settings haven't changed, trust GNSS's settings - if (settings.gnssConfiguredRover) + if (settings.gnssConfiguredRover == 0x01 | GNSS_MOSAIC_ROVER_SIGNATURE) { systemPrintln("Skipping mosaic Rover configuration"); setLoggingType(); // Needed because logUpdate exits early and never calls setLoggingType @@ -684,7 +717,10 @@ bool GNSS_MOSAIC::configureRover() systemPrintln("mosaic-X5 Rover failed to configure"); } - settings.gnssConfiguredRover = response; + if (response) + settings.gnssConfiguredRover = 0x01 | GNSS_MOSAIC_ROVER_SIGNATURE; + else + settings.gnssConfiguredRover = 0; return (response); } diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.ino b/Firmware/RTK_Everywhere/GNSS_ZED.ino index 294fdc60b..6bdf7fcda 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.ino +++ b/Firmware/RTK_Everywhere/GNSS_ZED.ino @@ -322,12 +322,18 @@ bool GNSS_ZED::checkPPPRates() //---------------------------------------- // Configure specific aspects of the receiver for base mode //---------------------------------------- +// If any of the settings in the signature have changed, reapply the Base configuration +// See GNSS_MOSAIC_ROVER_SIGNATURE as an example +#define GNSS_ZED_BASE_SIGNATURE \ + ( \ + 0 \ + ) bool GNSS_ZED::configureBase() { if (online.gnss == false) return (false); - if (settings.gnssConfiguredBase) + if (settings.gnssConfiguredBase == 0x01 | GNSS_ZED_BASE_SIGNATURE) { if (settings.debugGnss) systemPrintln("Skipping ZED Base configuration"); @@ -418,7 +424,10 @@ bool GNSS_ZED::configureBase() // The configuration should be saved to RAM+BBR+FLASH. No need to saveConfiguration here. - settings.gnssConfiguredBase = success; + if (success) + settings.gnssConfiguredBase = 0x01 | GNSS_ZED_BASE_SIGNATURE; + else + settings.gnssConfiguredBase = 0; return (success); } @@ -517,6 +526,12 @@ bool GNSS_ZED::configureNtpMode() // In general we check if the setting is incorrect before writing it. Otherwise, the set commands have, on rare // occasion, become corrupt. The worst is when the I2C port gets turned off or the I2C address gets borked. //---------------------------------------- +// If any of the settings in the signature have changed, reapply the configuration +// See GNSS_MOSAIC_ROVER_SIGNATURE as an example +#define GNSS_ZED_ONCE_SIGNATURE \ + ( \ + 0 \ + ) bool GNSS_ZED::configureGNSS() { if (online.gnss == false) @@ -578,7 +593,7 @@ bool GNSS_ZED::configureGNSS() // Configuring the ZED can take more than 2000ms. Configuration is saved to // ZED RAM+BBR so there is no need to update settings unless user has modified // the settings file or internal settings. - if (settings.gnssConfiguredOnce) + if (settings.gnssConfiguredOnce == 0x01 | GNSS_ZED_ONCE_SIGNATURE) { systemPrintln("ZED-F9x configuration maintained"); return (true); @@ -755,19 +770,26 @@ bool GNSS_ZED::configureGNSS() if (success) { - systemPrintln("ZED-F9x configuration update"); + systemPrintln("ZED-F9x configuration updated"); + settings.gnssConfiguredOnce = 0x01 | GNSS_ZED_ONCE_SIGNATURE; } + else + settings.gnssConfiguredOnce = 0; // The configuration should be saved to RAM+BBR+FLASH. No need to saveConfiguration here. - settings.gnssConfiguredOnce = success; - return (success); } //---------------------------------------- // Configure specific aspects of the receiver for rover mode //---------------------------------------- +// If any of the settings in the signature have changed, reapply the Base configuration +// See GNSS_MOSAIC_ROVER_SIGNATURE as an example +#define GNSS_ZED_ROVER_SIGNATURE \ + ( \ + 0 \ + ) bool GNSS_ZED::configureRover() { if (online.gnss == false) @@ -777,7 +799,7 @@ bool GNSS_ZED::configureRover() } // If our settings haven't changed, trust GNSS's settings - if (settings.gnssConfiguredRover) + if (settings.gnssConfiguredRover == 0x01 | GNSS_ZED_ROVER_SIGNATURE) { systemPrintln("Skipping ZED Rover configuration"); return (true); @@ -850,11 +872,14 @@ bool GNSS_ZED::configureRover() if (!success) systemPrintln("Rover config fail"); + + if (success) + settings.gnssConfiguredRover = 0x01 | GNSS_ZED_ROVER_SIGNATURE; + else + settings.gnssConfiguredRover = 0; // The configuration should be saved to RAM+BBR+FLASH. No need to saveConfiguration here. - settings.gnssConfiguredRover = success; - return (success); } diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index 2fc8bc853..719afae04 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -1573,29 +1573,29 @@ void loadProfileNumber() else { systemPrintln("profileNumber.txt not found"); - settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings - settings.gnssConfiguredBase = false; - settings.gnssConfiguredRover = false; - recordProfileNumber(0); // Record profile + settings.gnssConfiguredOnce = 0; // On the next boot, reapply all settings + settings.gnssConfiguredBase = 0; + settings.gnssConfiguredRover = 0; + recordProfileNumber(0); // Record profile } } else { systemPrintln("profileNumber.txt not found"); - settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings - settings.gnssConfiguredBase = false; - settings.gnssConfiguredRover = false; - recordProfileNumber(0); // Record profile + settings.gnssConfiguredOnce = 0; // On the next boot, reapply all settings + settings.gnssConfiguredBase = 0; + settings.gnssConfiguredRover = 0; + recordProfileNumber(0); // Record profile } // We have arbitrary limit of user profiles if (profileNumber >= MAX_PROFILE_COUNT) { systemPrintln("ProfileNumber invalid. Going to zero."); - settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings - settings.gnssConfiguredBase = false; - settings.gnssConfiguredRover = false; - recordProfileNumber(0); // Record profile + settings.gnssConfiguredOnce = 0; // On the next boot, reapply all settings + settings.gnssConfiguredBase = 0; + settings.gnssConfiguredRover = 0; + recordProfileNumber(0); // Record profile } systemPrintf("Using profile #%d\r\n", profileNumber); diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index f35288e05..0edcf907b 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -102,8 +102,8 @@ void stateUpdate() displayRoverStart(0); if (gnss->configureRover() == false) { - settings.gnssConfiguredRover = false; // On the next boot, reapply all settings - recordSystemSettings(); // Record this state for next POR + settings.gnssConfiguredRover = 0; // On the next boot, reapply all settings + recordSystemSettings(); // Record this state for next POR systemPrintln("Rover config failed"); displayRoverFail(1000); @@ -123,8 +123,8 @@ void stateUpdate() displayRoverFail(1000); else { - //settings.gnssConfiguredRover is set true by gnss->configureRover() - settings.gnssConfiguredBase = false; // When the mode changes, reapply all settings + //settings.gnssConfiguredRover is set by gnss->configureRover() + settings.gnssConfiguredBase = 0; // When the mode changes, reapply all settings settings.lastState = STATE_ROVER_NOT_STARTED; recordSystemSettings(); // Record this state for next POR @@ -247,8 +247,8 @@ void stateUpdate() // Start the UART connected to the GNSS receiver for NMEA and UBX data (enables logging) if (tasksStartGnssUart() && gnss->configureBase()) { - // settings.gnssConfiguredBase is set true by gnss->configureBase() - settings.gnssConfiguredRover = false; // When the mode changes, reapply all settings + // settings.gnssConfiguredBase is set by gnss->configureBase() + settings.gnssConfiguredRover = 0; // When the mode changes, reapply all settings settings.lastState = STATE_BASE_NOT_STARTED; // Record this state for next POR recordSystemSettings(); // Record this state for next POR @@ -261,8 +261,8 @@ void stateUpdate() } else { - settings.gnssConfiguredBase = false; // On the next boot, reapply all settings - recordSystemSettings(); // Record this state for next POR + settings.gnssConfiguredBase = 0; // On the next boot, reapply all settings + recordSystemSettings(); // Record this state for next POR displayBaseFail(1000); } @@ -486,10 +486,10 @@ void stateUpdate() systemPrintln(); parseIncomingSettings(); - settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings - settings.gnssConfiguredBase = false; - settings.gnssConfiguredRover = false; - recordSystemSettings(); // Record these settings to unit + settings.gnssConfiguredOnce = 0; // On the next boot, reapply all settings + settings.gnssConfiguredBase = 0; + settings.gnssConfiguredRover = 0; + recordSystemSettings(); // Record these settings to unit // Clear buffer incomingSettingsSpot = 0; @@ -609,8 +609,8 @@ void stateUpdate() if (tasksStartGnssUart() && configureUbloxModuleNTP()) { settings.lastState = STATE_NTPSERVER_NOT_STARTED; // Record this state for next POR - settings.gnssConfiguredBase = false; // On the next boot, reapply all settings - settings.gnssConfiguredRover = false; + settings.gnssConfiguredBase = 0; // On the next boot, reapply all settings + settings.gnssConfiguredRover = 0; recordSystemSettings(); if (online.ethernetNTPServer) diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 41e700228..9ef638287 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -456,8 +456,8 @@ void menuUserProfiles() // Change the active profile number, without unit reset void changeProfileNumber(byte newProfileNumber) { - settings.gnssConfiguredBase = false; // On the next boot, reapply all settings - settings.gnssConfiguredRover = false; + settings.gnssConfiguredBase = 0; // On the next boot, reapply all settings + settings.gnssConfiguredRover = 0; recordSystemSettings(); // Before switching, we need to record the current settings to LittleFS and SD recordProfileNumber(newProfileNumber); diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index 077e8e4e7..de7472eb9 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -654,9 +654,14 @@ struct Settings uint16_t measurementRateMs = 250; // Elapsed ms between GNSS measurements. 25ms to 65535ms. Default 4Hz. uint16_t navigationRate = 1; // Ratio between number of measurements and navigation solutions. Default 1 for 4Hz (with measurementRate). - bool gnssConfiguredOnce = false; // Flags to indicate how the GNSS is configured (Once, Base, Rover, etc.) - bool gnssConfiguredBase = false; - bool gnssConfiguredRover = false; + + // Signatures to indicate how the GNSS is configured (Once, Base, Rover, etc.) + // Bit 0 indicates if the GNSS has been configured previously. + // Bits 1 onwards record the state of critical settings. E.g. settings.enable + // If those critical settings have changed + uint8_t gnssConfiguredOnce = 0; + uint8_t gnssConfiguredBase = 0; + uint8_t gnssConfiguredRover = 0; // GNSS UART uint16_t serialGNSSRxFullThreshold = 50; // RX FIFO full interrupt. Max of ~128. See pinUART2Task(). @@ -1249,9 +1254,9 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enablePrintPosition, "enablePrintPosition", }, { 0, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.measurementRateMs, "measurementRateMs", }, { 0, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.navigationRate, "navigationRate", }, - { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.gnssConfiguredOnce, "gnssConfiguredOnce", }, - { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.gnssConfiguredBase, "gnssConfiguredBase", }, - { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.gnssConfiguredRover, "gnssConfiguredRover", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint8_t, 0, & settings.gnssConfiguredOnce, "gnssConfiguredOnce", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint8_t, 0, & settings.gnssConfiguredBase, "gnssConfiguredBase", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint8_t, 0, & settings.gnssConfiguredRover, "gnssConfiguredRover", }, // Hardware { 1, 1, 0, 1, 1, 1, 0, 1, 0, _bool, 0, & settings.enableExternalHardwareEventLogging, "enableExternalHardwareEventLogging", }, From c6be11a96767cff8b5ae1c3933af64b405fb6f2f Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 17 Feb 2025 16:40:30 +0000 Subject: [PATCH 257/276] Correct bracketing --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 7 +++---- Firmware/RTK_Everywhere/GNSS_ZED.ino | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index c6b5b394e..c6c075935 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -390,7 +390,6 @@ bool GNSS_MOSAIC::checkPPPRates() // Returns true if successfully configured and false upon failure //---------------------------------------- // If any of the settings in the signature have changed, reapply the Base configuration -// See GNSS_MOSAIC_ROVER_SIGNATURE as an example #define GNSS_MOSAIC_BASE_SIGNATURE \ ( \ ((settings.minElev & 0x01) << 1) \ @@ -418,7 +417,7 @@ bool GNSS_MOSAIC::configureBase() return (false); } - if (settings.gnssConfiguredBase == 0x01 | GNSS_MOSAIC_BASE_SIGNATURE) + if (settings.gnssConfiguredBase == (0x01 | GNSS_MOSAIC_BASE_SIGNATURE)) { systemPrintln("Skipping mosaic Base configuration"); setLoggingType(); // Needed because logUpdate exits early and never calls setLoggingType @@ -572,7 +571,7 @@ bool GNSS_MOSAIC::configureOnce() RTCMv3 messages are enabled by enableRTCMRover / enableRTCMBase */ - if (settings.gnssConfiguredOnce == 0x01 | GNSS_MOSAIC_ONCE_SIGNATURE) + if (settings.gnssConfiguredOnce == (0x01 | GNSS_MOSAIC_ONCE_SIGNATURE)) { systemPrintln("mosaic configuration maintained"); return (true); @@ -686,7 +685,7 @@ bool GNSS_MOSAIC::configureRover() } // If our settings haven't changed, trust GNSS's settings - if (settings.gnssConfiguredRover == 0x01 | GNSS_MOSAIC_ROVER_SIGNATURE) + if (settings.gnssConfiguredRover == (0x01 | GNSS_MOSAIC_ROVER_SIGNATURE)) { systemPrintln("Skipping mosaic Rover configuration"); setLoggingType(); // Needed because logUpdate exits early and never calls setLoggingType diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.ino b/Firmware/RTK_Everywhere/GNSS_ZED.ino index 6bdf7fcda..db969bb22 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.ino +++ b/Firmware/RTK_Everywhere/GNSS_ZED.ino @@ -333,7 +333,7 @@ bool GNSS_ZED::configureBase() if (online.gnss == false) return (false); - if (settings.gnssConfiguredBase == 0x01 | GNSS_ZED_BASE_SIGNATURE) + if (settings.gnssConfiguredBase == (0x01 | GNSS_ZED_BASE_SIGNATURE)) { if (settings.debugGnss) systemPrintln("Skipping ZED Base configuration"); @@ -593,7 +593,7 @@ bool GNSS_ZED::configureGNSS() // Configuring the ZED can take more than 2000ms. Configuration is saved to // ZED RAM+BBR so there is no need to update settings unless user has modified // the settings file or internal settings. - if (settings.gnssConfiguredOnce == 0x01 | GNSS_ZED_ONCE_SIGNATURE) + if (settings.gnssConfiguredOnce == (0x01 | GNSS_ZED_ONCE_SIGNATURE)) { systemPrintln("ZED-F9x configuration maintained"); return (true); @@ -799,7 +799,7 @@ bool GNSS_ZED::configureRover() } // If our settings haven't changed, trust GNSS's settings - if (settings.gnssConfiguredRover == 0x01 | GNSS_ZED_ROVER_SIGNATURE) + if (settings.gnssConfiguredRover == (0x01 | GNSS_ZED_ROVER_SIGNATURE)) { systemPrintln("Skipping ZED Rover configuration"); return (true); From c5286f533fe98d2411e248d78366e43a51c92a7c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 17 Feb 2025 17:36:02 +0000 Subject: [PATCH 258/276] Update mosaic menuMessagesNMEA and menuMessagesRTCM --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index c6c075935..05504fcc2 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -1759,8 +1759,8 @@ void GNSS_MOSAIC::menuMessagesNMEA() printUnknown(incoming); } - settings.gnssConfiguredBase = false; // Update the GNSS config at the next boot - settings.gnssConfiguredRover = false; + settings.gnssConfiguredBase = 0; // Update the GNSS config at the next boot + settings.gnssConfiguredRover = 0; clearBuffer(); // Empty buffer of any newline chars } @@ -1831,8 +1831,8 @@ void GNSS_MOSAIC::menuMessagesRTCM(bool rover) printUnknown(incoming); } - settings.gnssConfiguredBase = false; // Update the GNSS config at the next boot - settings.gnssConfiguredRover = false; + settings.gnssConfiguredBase = 0; // Update the GNSS config at the next boot + settings.gnssConfiguredRover = 0; clearBuffer(); // Empty buffer of any newline chars } From 36410ba09aa1ad057f8a78afc7353f40f7f124c4 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 18 Feb 2025 09:13:09 +0000 Subject: [PATCH 259/276] Update gnssConfigureBase/Rover from restartBase/Rover --- Firmware/RTK_Everywhere/menuMain.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 9ef638287..576cb200a 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -280,12 +280,14 @@ void menuMain() if (restartBase == true && inBaseMode() == true) { restartBase = false; + settings.gnssConfiguredBase = 0; // Reapply configuration requestChangeState(STATE_BASE_NOT_STARTED); // Restart base upon exit for latest changes to take effect } if (restartRover == true && inRoverMode() == true) { restartRover = false; + settings.gnssConfiguredRover = 0; // Reapply configuration requestChangeState(STATE_ROVER_NOT_STARTED); // Restart rover upon exit for latest changes to take effect } From a93b8710c6c6d4dccc746dd4199cca0164ecf3be Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 18 Feb 2025 09:19:59 +0000 Subject: [PATCH 260/276] Allow 16 bits for gnssConfigured signatures (probably redundant) --- Firmware/RTK_Everywhere/settings.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index de7472eb9..aa7938ec8 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -657,11 +657,11 @@ struct Settings // Signatures to indicate how the GNSS is configured (Once, Base, Rover, etc.) // Bit 0 indicates if the GNSS has been configured previously. - // Bits 1 onwards record the state of critical settings. E.g. settings.enable - // If those critical settings have changed - uint8_t gnssConfiguredOnce = 0; - uint8_t gnssConfiguredBase = 0; - uint8_t gnssConfiguredRover = 0; + // Bits 1 onwards record the state of critical settings. E.g. settings.enablePointPerfectCorrections + // Configuration is reapplied if any of those critical settings have changed + uint16_t gnssConfiguredOnce = 0; + uint16_t gnssConfiguredBase = 0; + uint16_t gnssConfiguredRover = 0; // GNSS UART uint16_t serialGNSSRxFullThreshold = 50; // RX FIFO full interrupt. Max of ~128. See pinUART2Task(). @@ -1254,9 +1254,9 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enablePrintPosition, "enablePrintPosition", }, { 0, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.measurementRateMs, "measurementRateMs", }, { 0, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.navigationRate, "navigationRate", }, - { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint8_t, 0, & settings.gnssConfiguredOnce, "gnssConfiguredOnce", }, - { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint8_t, 0, & settings.gnssConfiguredBase, "gnssConfiguredBase", }, - { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint8_t, 0, & settings.gnssConfiguredRover, "gnssConfiguredRover", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.gnssConfiguredOnce, "gnssConfiguredOnce", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.gnssConfiguredBase, "gnssConfiguredBase", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.gnssConfiguredRover, "gnssConfiguredRover", }, // Hardware { 1, 1, 0, 1, 1, 1, 0, 1, 0, _bool, 0, & settings.enableExternalHardwareEventLogging, "enableExternalHardwareEventLogging", }, From f91451343bcc8f873c48b9a18542b334df8a898d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 18 Feb 2025 09:21:26 +0000 Subject: [PATCH 261/276] Update mosaic signatures. Correct use of restartRover/Base makes the signatures largely redundant --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 37 +++++++++++-------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 05504fcc2..b20808e47 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -390,15 +390,10 @@ bool GNSS_MOSAIC::checkPPPRates() // Returns true if successfully configured and false upon failure //---------------------------------------- // If any of the settings in the signature have changed, reapply the Base configuration -#define GNSS_MOSAIC_BASE_SIGNATURE \ - ( \ - ((settings.minElev & 0x01) << 1) \ - | ((settings.enableGnssToUsbSerial & 0x01) << 2) \ - | ((settings.enablePointPerfectCorrections & 0x01) << 3) \ - | ((settings.ntripClient_TransmitGGA & 0x01) << 4) \ - | ((settings.enableLogging & 0x01) << 5) \ - | ((settings.enableLoggingRINEX & 0x01) << 6) \ - | ((settings.enableExternalHardwareEventLogging & 0x01) << 7) \ +// See GNSS_MOSAIC_ROVER_SIGNATURE as an example +#define GNSS_MOSAIC_BASE_SIGNATURE \ + ( \ + 0 \ ) bool GNSS_MOSAIC::configureBase() { @@ -555,9 +550,9 @@ bool GNSS_MOSAIC::configureLBand(bool enableLBand, uint32_t LBandFreq) //---------------------------------------- // If any of the settings in the signature have changed, reapply the configuration // See GNSS_MOSAIC_ROVER_SIGNATURE as an example -#define GNSS_MOSAIC_ONCE_SIGNATURE \ - ( \ - 0 \ +#define GNSS_MOSAIC_ONCE_SIGNATURE \ + ( \ + 0 \ ) bool GNSS_MOSAIC::configureOnce() { @@ -662,13 +657,13 @@ bool GNSS_MOSAIC::configureGNSS() // Returns true if successfully configured and false upon failure //---------------------------------------- // If any of the settings in the signature have changed, reapply the Rover configuration -#define GNSS_MOSAIC_ROVER_SIGNATURE \ - ( \ - ((settings.enablePointPerfectCorrections & 0x01) << 1) \ - | ((settings.enableGnssToUsbSerial & 0x01) << 2) \ - | ((settings.ntripClient_TransmitGGA & 0x01) << 3) \ - | ((settings.enableLogging & 0x01) << 4) \ - | ((settings.enableExternalHardwareEventLogging & 0x01) << 5) \ +// E.g. ((settings.enablePointPerfectCorrections & 0x01) << 1) +// | ((settings.enableGnssToUsbSerial & 0x01) << 2) +// But most of this is taken care of by restartRover and restartBase +// You should only use the signature to trap any exceptions not covered by restartRover/Base +#define GNSS_MOSAIC_ROVER_SIGNATURE \ + ( \ + 0 \ ) bool GNSS_MOSAIC::configureRover() { @@ -696,9 +691,9 @@ bool GNSS_MOSAIC::configureRover() response &= sendWithResponse("spm,Rover,all,auto\n\r", "PVTMode"); - response &= setModel(settings.dynamicModel); + response &= setModel(settings.dynamicModel); // Set by menuGNSS which calls gnss->setModel - response &= setElevation(settings.minElev); + response &= setElevation(settings.minElev); // Set by menuGNSS which calls gnss->setElevation response &= enableRTCMRover(); From d5edc78a6db52f66df51dcadf2c63305fb4046a0 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 18 Feb 2025 10:31:31 +0000 Subject: [PATCH 262/276] Remove signatures. Change gnssConfiguredOnce/Base/Rover back to bool --- Firmware/RTK_Everywhere/Display.ino | 4 +- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 50 +++++-------------------- Firmware/RTK_Everywhere/GNSS_ZED.ino | 39 ++++--------------- Firmware/RTK_Everywhere/NVM.ino | 18 ++++----- Firmware/RTK_Everywhere/States.ino | 18 ++++----- Firmware/RTK_Everywhere/menuMain.ino | 8 ++-- Firmware/RTK_Everywhere/settings.h | 12 +++--- 7 files changed, 47 insertions(+), 102 deletions(-) diff --git a/Firmware/RTK_Everywhere/Display.ino b/Firmware/RTK_Everywhere/Display.ino index 8942cb00c..385d64aad 100644 --- a/Firmware/RTK_Everywhere/Display.ino +++ b/Firmware/RTK_Everywhere/Display.ino @@ -2442,8 +2442,8 @@ void paintProfile(uint8_t profileUnit) if (profileNumber >= 0) { - settings.gnssConfiguredBase = 0; // On the next boot, reapply all settings - settings.gnssConfiguredRover = 0; + settings.gnssConfiguredBase = false; // On the next boot, reapply all settings + settings.gnssConfiguredRover = false; recordSystemSettings(); // Before switching, we need to record the current settings to LittleFS and SD recordProfileNumber( diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index b20808e47..ebe141c59 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -389,12 +389,6 @@ bool GNSS_MOSAIC::checkPPPRates() // Outputs: // Returns true if successfully configured and false upon failure //---------------------------------------- -// If any of the settings in the signature have changed, reapply the Base configuration -// See GNSS_MOSAIC_ROVER_SIGNATURE as an example -#define GNSS_MOSAIC_BASE_SIGNATURE \ - ( \ - 0 \ - ) bool GNSS_MOSAIC::configureBase() { /* @@ -412,7 +406,7 @@ bool GNSS_MOSAIC::configureBase() return (false); } - if (settings.gnssConfiguredBase == (0x01 | GNSS_MOSAIC_BASE_SIGNATURE)) + if (settings.gnssConfiguredBase) { systemPrintln("Skipping mosaic Base configuration"); setLoggingType(); // Needed because logUpdate exits early and never calls setLoggingType @@ -441,10 +435,7 @@ bool GNSS_MOSAIC::configureBase() systemPrintln("mosaic-X5 Base failed to configure"); } - if (response) - settings.gnssConfiguredBase = 0x01 | GNSS_MOSAIC_BASE_SIGNATURE; - else - settings.gnssConfiguredBase = 0; + settings.gnssConfiguredBase = response; return (response); } @@ -548,12 +539,6 @@ bool GNSS_MOSAIC::configureLBand(bool enableLBand, uint32_t LBandFreq) // Outputs: // Returns true if successfully configured and false upon failure //---------------------------------------- -// If any of the settings in the signature have changed, reapply the configuration -// See GNSS_MOSAIC_ROVER_SIGNATURE as an example -#define GNSS_MOSAIC_ONCE_SIGNATURE \ - ( \ - 0 \ - ) bool GNSS_MOSAIC::configureOnce() { /* @@ -566,7 +551,7 @@ bool GNSS_MOSAIC::configureOnce() RTCMv3 messages are enabled by enableRTCMRover / enableRTCMBase */ - if (settings.gnssConfiguredOnce == (0x01 | GNSS_MOSAIC_ONCE_SIGNATURE)) + if (settings.gnssConfiguredOnce) { systemPrintln("mosaic configuration maintained"); return (true); @@ -624,10 +609,7 @@ bool GNSS_MOSAIC::configureOnce() else online.gnss = false; // Take it offline - if (response) - settings.gnssConfiguredOnce = 0x01 | GNSS_MOSAIC_ONCE_SIGNATURE; - else - settings.gnssConfiguredOnce = 0; + settings.gnssConfiguredOnce = response; return (response); } @@ -656,15 +638,6 @@ bool GNSS_MOSAIC::configureGNSS() // Outputs: // Returns true if successfully configured and false upon failure //---------------------------------------- -// If any of the settings in the signature have changed, reapply the Rover configuration -// E.g. ((settings.enablePointPerfectCorrections & 0x01) << 1) -// | ((settings.enableGnssToUsbSerial & 0x01) << 2) -// But most of this is taken care of by restartRover and restartBase -// You should only use the signature to trap any exceptions not covered by restartRover/Base -#define GNSS_MOSAIC_ROVER_SIGNATURE \ - ( \ - 0 \ - ) bool GNSS_MOSAIC::configureRover() { /* @@ -680,7 +653,7 @@ bool GNSS_MOSAIC::configureRover() } // If our settings haven't changed, trust GNSS's settings - if (settings.gnssConfiguredRover == (0x01 | GNSS_MOSAIC_ROVER_SIGNATURE)) + if (settings.gnssConfiguredRover) { systemPrintln("Skipping mosaic Rover configuration"); setLoggingType(); // Needed because logUpdate exits early and never calls setLoggingType @@ -711,10 +684,7 @@ bool GNSS_MOSAIC::configureRover() systemPrintln("mosaic-X5 Rover failed to configure"); } - if (response) - settings.gnssConfiguredRover = 0x01 | GNSS_MOSAIC_ROVER_SIGNATURE; - else - settings.gnssConfiguredRover = 0; + settings.gnssConfiguredRover = response; return (response); } @@ -1754,8 +1724,8 @@ void GNSS_MOSAIC::menuMessagesNMEA() printUnknown(incoming); } - settings.gnssConfiguredBase = 0; // Update the GNSS config at the next boot - settings.gnssConfiguredRover = 0; + settings.gnssConfiguredBase = false; // Update the GNSS config at the next boot + settings.gnssConfiguredRover = false; clearBuffer(); // Empty buffer of any newline chars } @@ -1826,8 +1796,8 @@ void GNSS_MOSAIC::menuMessagesRTCM(bool rover) printUnknown(incoming); } - settings.gnssConfiguredBase = 0; // Update the GNSS config at the next boot - settings.gnssConfiguredRover = 0; + settings.gnssConfiguredBase = false; // Update the GNSS config at the next boot + settings.gnssConfiguredRover = false; clearBuffer(); // Empty buffer of any newline chars } diff --git a/Firmware/RTK_Everywhere/GNSS_ZED.ino b/Firmware/RTK_Everywhere/GNSS_ZED.ino index db969bb22..dc7b2e1ce 100644 --- a/Firmware/RTK_Everywhere/GNSS_ZED.ino +++ b/Firmware/RTK_Everywhere/GNSS_ZED.ino @@ -322,18 +322,12 @@ bool GNSS_ZED::checkPPPRates() //---------------------------------------- // Configure specific aspects of the receiver for base mode //---------------------------------------- -// If any of the settings in the signature have changed, reapply the Base configuration -// See GNSS_MOSAIC_ROVER_SIGNATURE as an example -#define GNSS_ZED_BASE_SIGNATURE \ - ( \ - 0 \ - ) bool GNSS_ZED::configureBase() { if (online.gnss == false) return (false); - if (settings.gnssConfiguredBase == (0x01 | GNSS_ZED_BASE_SIGNATURE)) + if (settings.gnssConfiguredBase) { if (settings.debugGnss) systemPrintln("Skipping ZED Base configuration"); @@ -424,10 +418,7 @@ bool GNSS_ZED::configureBase() // The configuration should be saved to RAM+BBR+FLASH. No need to saveConfiguration here. - if (success) - settings.gnssConfiguredBase = 0x01 | GNSS_ZED_BASE_SIGNATURE; - else - settings.gnssConfiguredBase = 0; + settings.gnssConfiguredBase = success; return (success); } @@ -526,12 +517,6 @@ bool GNSS_ZED::configureNtpMode() // In general we check if the setting is incorrect before writing it. Otherwise, the set commands have, on rare // occasion, become corrupt. The worst is when the I2C port gets turned off or the I2C address gets borked. //---------------------------------------- -// If any of the settings in the signature have changed, reapply the configuration -// See GNSS_MOSAIC_ROVER_SIGNATURE as an example -#define GNSS_ZED_ONCE_SIGNATURE \ - ( \ - 0 \ - ) bool GNSS_ZED::configureGNSS() { if (online.gnss == false) @@ -593,7 +578,7 @@ bool GNSS_ZED::configureGNSS() // Configuring the ZED can take more than 2000ms. Configuration is saved to // ZED RAM+BBR so there is no need to update settings unless user has modified // the settings file or internal settings. - if (settings.gnssConfiguredOnce == (0x01 | GNSS_ZED_ONCE_SIGNATURE)) + if (settings.gnssConfiguredOnce) { systemPrintln("ZED-F9x configuration maintained"); return (true); @@ -771,10 +756,9 @@ bool GNSS_ZED::configureGNSS() if (success) { systemPrintln("ZED-F9x configuration updated"); - settings.gnssConfiguredOnce = 0x01 | GNSS_ZED_ONCE_SIGNATURE; } - else - settings.gnssConfiguredOnce = 0; + + settings.gnssConfiguredOnce = success; // The configuration should be saved to RAM+BBR+FLASH. No need to saveConfiguration here. @@ -784,12 +768,6 @@ bool GNSS_ZED::configureGNSS() //---------------------------------------- // Configure specific aspects of the receiver for rover mode //---------------------------------------- -// If any of the settings in the signature have changed, reapply the Base configuration -// See GNSS_MOSAIC_ROVER_SIGNATURE as an example -#define GNSS_ZED_ROVER_SIGNATURE \ - ( \ - 0 \ - ) bool GNSS_ZED::configureRover() { if (online.gnss == false) @@ -799,7 +777,7 @@ bool GNSS_ZED::configureRover() } // If our settings haven't changed, trust GNSS's settings - if (settings.gnssConfiguredRover == (0x01 | GNSS_ZED_ROVER_SIGNATURE)) + if (settings.gnssConfiguredRover) { systemPrintln("Skipping ZED Rover configuration"); return (true); @@ -873,10 +851,7 @@ bool GNSS_ZED::configureRover() if (!success) systemPrintln("Rover config fail"); - if (success) - settings.gnssConfiguredRover = 0x01 | GNSS_ZED_ROVER_SIGNATURE; - else - settings.gnssConfiguredRover = 0; + settings.gnssConfiguredRover = success; // The configuration should be saved to RAM+BBR+FLASH. No need to saveConfiguration here. diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index 719afae04..b05cb025a 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -1573,18 +1573,18 @@ void loadProfileNumber() else { systemPrintln("profileNumber.txt not found"); - settings.gnssConfiguredOnce = 0; // On the next boot, reapply all settings - settings.gnssConfiguredBase = 0; - settings.gnssConfiguredRover = 0; + settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings + settings.gnssConfiguredBase = false; + settings.gnssConfiguredRover = false; recordProfileNumber(0); // Record profile } } else { systemPrintln("profileNumber.txt not found"); - settings.gnssConfiguredOnce = 0; // On the next boot, reapply all settings - settings.gnssConfiguredBase = 0; - settings.gnssConfiguredRover = 0; + settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings + settings.gnssConfiguredBase = false; + settings.gnssConfiguredRover = false; recordProfileNumber(0); // Record profile } @@ -1592,9 +1592,9 @@ void loadProfileNumber() if (profileNumber >= MAX_PROFILE_COUNT) { systemPrintln("ProfileNumber invalid. Going to zero."); - settings.gnssConfiguredOnce = 0; // On the next boot, reapply all settings - settings.gnssConfiguredBase = 0; - settings.gnssConfiguredRover = 0; + settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings + settings.gnssConfiguredBase = false; + settings.gnssConfiguredRover = false; recordProfileNumber(0); // Record profile } diff --git a/Firmware/RTK_Everywhere/States.ino b/Firmware/RTK_Everywhere/States.ino index 0edcf907b..094817eae 100644 --- a/Firmware/RTK_Everywhere/States.ino +++ b/Firmware/RTK_Everywhere/States.ino @@ -102,7 +102,7 @@ void stateUpdate() displayRoverStart(0); if (gnss->configureRover() == false) { - settings.gnssConfiguredRover = 0; // On the next boot, reapply all settings + settings.gnssConfiguredRover = false; // On the next boot, reapply all settings recordSystemSettings(); // Record this state for next POR systemPrintln("Rover config failed"); @@ -124,7 +124,7 @@ void stateUpdate() else { //settings.gnssConfiguredRover is set by gnss->configureRover() - settings.gnssConfiguredBase = 0; // When the mode changes, reapply all settings + settings.gnssConfiguredBase = false; // When the mode changes, reapply all settings settings.lastState = STATE_ROVER_NOT_STARTED; recordSystemSettings(); // Record this state for next POR @@ -248,7 +248,7 @@ void stateUpdate() if (tasksStartGnssUart() && gnss->configureBase()) { // settings.gnssConfiguredBase is set by gnss->configureBase() - settings.gnssConfiguredRover = 0; // When the mode changes, reapply all settings + settings.gnssConfiguredRover = false; // When the mode changes, reapply all settings settings.lastState = STATE_BASE_NOT_STARTED; // Record this state for next POR recordSystemSettings(); // Record this state for next POR @@ -261,7 +261,7 @@ void stateUpdate() } else { - settings.gnssConfiguredBase = 0; // On the next boot, reapply all settings + settings.gnssConfiguredBase = false; // On the next boot, reapply all settings recordSystemSettings(); // Record this state for next POR displayBaseFail(1000); @@ -486,9 +486,9 @@ void stateUpdate() systemPrintln(); parseIncomingSettings(); - settings.gnssConfiguredOnce = 0; // On the next boot, reapply all settings - settings.gnssConfiguredBase = 0; - settings.gnssConfiguredRover = 0; + settings.gnssConfiguredOnce = false; // On the next boot, reapply all settings + settings.gnssConfiguredBase = false; + settings.gnssConfiguredRover = false; recordSystemSettings(); // Record these settings to unit // Clear buffer @@ -609,8 +609,8 @@ void stateUpdate() if (tasksStartGnssUart() && configureUbloxModuleNTP()) { settings.lastState = STATE_NTPSERVER_NOT_STARTED; // Record this state for next POR - settings.gnssConfiguredBase = 0; // On the next boot, reapply all settings - settings.gnssConfiguredRover = 0; + settings.gnssConfiguredBase = false; // On the next boot, reapply all settings + settings.gnssConfiguredRover = false; recordSystemSettings(); if (online.ethernetNTPServer) diff --git a/Firmware/RTK_Everywhere/menuMain.ino b/Firmware/RTK_Everywhere/menuMain.ino index 576cb200a..cb000000b 100644 --- a/Firmware/RTK_Everywhere/menuMain.ino +++ b/Firmware/RTK_Everywhere/menuMain.ino @@ -280,14 +280,14 @@ void menuMain() if (restartBase == true && inBaseMode() == true) { restartBase = false; - settings.gnssConfiguredBase = 0; // Reapply configuration + settings.gnssConfiguredBase = false; // Reapply configuration requestChangeState(STATE_BASE_NOT_STARTED); // Restart base upon exit for latest changes to take effect } if (restartRover == true && inRoverMode() == true) { restartRover = false; - settings.gnssConfiguredRover = 0; // Reapply configuration + settings.gnssConfiguredRover = false; // Reapply configuration requestChangeState(STATE_ROVER_NOT_STARTED); // Restart rover upon exit for latest changes to take effect } @@ -458,8 +458,8 @@ void menuUserProfiles() // Change the active profile number, without unit reset void changeProfileNumber(byte newProfileNumber) { - settings.gnssConfiguredBase = 0; // On the next boot, reapply all settings - settings.gnssConfiguredRover = 0; + settings.gnssConfiguredBase = false; // On the next boot, reapply all settings + settings.gnssConfiguredRover = false; recordSystemSettings(); // Before switching, we need to record the current settings to LittleFS and SD recordProfileNumber(newProfileNumber); diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index aa7938ec8..ee741b8c6 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -659,9 +659,9 @@ struct Settings // Bit 0 indicates if the GNSS has been configured previously. // Bits 1 onwards record the state of critical settings. E.g. settings.enablePointPerfectCorrections // Configuration is reapplied if any of those critical settings have changed - uint16_t gnssConfiguredOnce = 0; - uint16_t gnssConfiguredBase = 0; - uint16_t gnssConfiguredRover = 0; + bool gnssConfiguredOnce = false; + bool gnssConfiguredBase = false; + bool gnssConfiguredRover = false; // GNSS UART uint16_t serialGNSSRxFullThreshold = 50; // RX FIFO full interrupt. Max of ~128. See pinUART2Task(). @@ -1254,9 +1254,9 @@ const RTK_Settings_Entry rtkSettingsEntries[] = { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enablePrintPosition, "enablePrintPosition", }, { 0, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.measurementRateMs, "measurementRateMs", }, { 0, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.navigationRate, "navigationRate", }, - { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.gnssConfiguredOnce, "gnssConfiguredOnce", }, - { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.gnssConfiguredBase, "gnssConfiguredBase", }, - { 0, 0, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.gnssConfiguredRover, "gnssConfiguredRover", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.gnssConfiguredOnce, "gnssConfiguredOnce", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.gnssConfiguredBase, "gnssConfiguredBase", }, + { 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.gnssConfiguredRover, "gnssConfiguredRover", }, // Hardware { 1, 1, 0, 1, 1, 1, 0, 1, 0, _bool, 0, & settings.enableExternalHardwareEventLogging, "enableExternalHardwareEventLogging", }, From 9a4bfe8c6ca71175ab77fd9e51d0b1779b802bb9 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 18 Feb 2025 10:49:19 +0000 Subject: [PATCH 263/276] Disable DEBUG_THE_ESSENTIALS --- Firmware/RTK_Everywhere/RTK_Everywhere.ino | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino index 7509dae23..9a487e5b2 100644 --- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino +++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino @@ -936,7 +936,7 @@ volatile bool deadManWalking; \ /* Turn on nearly all the debug prints */ \ settings.debugCorrections = true; \ - settings.debugGnss = true; \ + settings.debugGnss = false; \ settings.debugHttpClientData = true; \ settings.debugHttpClientState = true; \ settings.debugLora = true; \ @@ -981,7 +981,7 @@ volatile bool deadManWalking; \ /* Turn on nearly all the debug prints */ \ settings.debugCorrections = true; \ - settings.debugGnss = true; \ + settings.debugGnss = false; \ settings.debugHttpClientData = false; \ settings.debugHttpClientState = true; \ settings.debugLora = false; \ @@ -1181,7 +1181,7 @@ void setup() loadSettings(); // Attempt to load settings after SD is started so we can read the settings file if available //DEBUG_NEARLY_EVERYTHING // Debug nearly all the things - DEBUG_THE_ESSENTIALS // Debug the essentials - handy for measuring the boot time after a factory reset + //DEBUG_THE_ESSENTIALS // Debug the essentials - handy for measuring the boot time after a factory reset DMW_b("checkArrayDefaults"); checkArrayDefaults(); // Check for uninitialized arrays that won't be initialized by gnssConfigure From d397f886364d17f6f6231ee87e5b4b46b99e3d6c Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 18 Feb 2025 14:31:46 +0000 Subject: [PATCH 264/276] LG290P : add isBlocking checks and retries for enterConfigMode --- Firmware/RTK_Everywhere/GNSS_LG290P.h | 2 +- Firmware/RTK_Everywhere/GNSS_LG290P.ino | 69 ++++++++++++++++++------- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.h b/Firmware/RTK_Everywhere/GNSS_LG290P.h index baeb43b1d..efbd13e1e 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.h +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.h @@ -176,7 +176,7 @@ class GNSS_LG290P : GNSS // Returns true if successfully started and false upon failure bool enableRTCMTest(); - bool enterConfigMode(); + bool enterConfigMode(unsigned long waitForSemaphoreTimeout_millis); bool exitConfigMode(); diff --git a/Firmware/RTK_Everywhere/GNSS_LG290P.ino b/Firmware/RTK_Everywhere/GNSS_LG290P.ino index b7267a3f4..6f45871d0 100644 --- a/Firmware/RTK_Everywhere/GNSS_LG290P.ino +++ b/Firmware/RTK_Everywhere/GNSS_LG290P.ino @@ -224,24 +224,32 @@ bool GNSS_LG290P::configureOnce() bool response = true; - response &= enterConfigMode(); + uint8_t retries = 4; + + while ((retries > 0) && (!enterConfigMode(500))) + { + retries--; + systemPrintf("configureOnce: Enter config mode failed. %d retries remaining\r\n", retries); + } + + response &= (retries > 0); if (settings.debugGnss && response == false) - systemPrintln("ConfigureOnce: Enter config mode failed"); + systemPrintln("configureOnce: Enter config mode failed"); response &= setDataBaudRate(settings.dataPortBaud); // LG290P UART1 is connected to CH342 (Port B) response &= _lg290p->setPortBaudrate(2, 115200 * 4); // LG290P UART2 is connected to the ESP32 UART1 response &= setRadioBaudRate(settings.radioPortBaud); // LG290P UART3 is connected to the locking JST connector if (settings.debugGnss && response == false) - systemPrintln("ConfigureOnce: setBauds failed"); + systemPrintln("configureOnce: setBauds failed"); // Enable PPS signal with a width of 200ms response &= _lg290p->setPPS(200, false, true); // duration time ms, alwaysOutput, polarity if (settings.debugGnss && response == false) - systemPrintln("ConfigureOnce: setPPS failed"); + systemPrintln("configureOnce: setPPS failed"); response &= setConstellations(); if (settings.debugGnss && response == false) - systemPrintln("ConfigureOnce: setConstellations failed"); + systemPrintln("configureOnce: setConstellations failed"); // We do not set Rover or fix rate here because fix rate only applies in rover mode. @@ -291,9 +299,17 @@ bool GNSS_LG290P::configureRover() serialGNSS->flush(); // Remove any incoming characters - response &= enterConfigMode(); + uint8_t retries = 4; + + while ((retries > 0) && (!enterConfigMode(500))) + { + retries--; + systemPrintf("configureRover: Enter config mode failed. %d retries remaining\r\n", retries); + } + + response &= (retries > 0); if (settings.debugGnss && response == false) - systemPrintln("Rover: Enter config mode failed"); + systemPrintln("configureRover: Enter config mode failed"); // We must force receiver into Rover mode so that we can set fix rate int currentMode = getMode(); @@ -304,21 +320,21 @@ bool GNSS_LG290P::configureRover() // fail because NMEA is not present. _lg290p->setModeRover(); // Wait for save and reset if (settings.debugGnss && response == false) - systemPrintln("Rover: Set mode rover failed"); + systemPrintln("configureRover: Set mode rover failed"); } // Set the fix rate. Default on LG290P is 10Hz so set accordingly. response &= setRate(settings.measurementRateMs / 1000.0); // May require save/reset if (settings.debugGnss && response == false) - systemPrintln("Rover: Set rate failed"); + systemPrintln("configureRover: Set rate failed"); response &= enableRTCMRover(); if (settings.debugGnss && response == false) - systemPrintln("Rover: Enable RTCM failed"); + systemPrintln("configureRover: Enable RTCM failed"); response &= enableNMEA(); if (settings.debugGnss && response == false) - systemPrintln("Rover: Enable NMEA failed"); + systemPrintln("configureRover: Enable NMEA failed"); response &= exitConfigMode(); // We must exit config before we save otherwise we will save with NMEA/RTCM off @@ -371,9 +387,17 @@ bool GNSS_LG290P::configureBase() serialGNSS->flush(); // Remove any incoming characters - response &= enterConfigMode(); + uint8_t retries = 4; + + while ((retries > 0) && (!enterConfigMode(500))) + { + retries--; + systemPrintf("configureBase: Enter config mode failed. %d retries remaining\r\n", retries); + } + + response &= (retries > 0); if (settings.debugGnss && response == false) - systemPrintln("Base: Enter config mode failed"); + systemPrintln("configureBase: Enter config mode failed"); // "When set to Base Station mode, the receiver will automatically disable NMEA message output and enable RTCM MSM4 // and RTCM3-1005 message output." @@ -391,7 +415,7 @@ bool GNSS_LG290P::configureBase() // fail because NMEA is not present. _lg290p->setModeBase(false); // Don't save and reset if (settings.debugGnss && response == false) - systemPrintln("Base: Set mode base failed"); + systemPrintln("configureBase: Set mode base failed"); // Device should now have survey mode disabled } @@ -405,16 +429,16 @@ bool GNSS_LG290P::configureBase() // fail because NMEA is not present. disableSurveyIn(false); // Don't save and reset if (settings.debugGnss && response == false) - systemPrintln("Base: disable survey in failed"); + systemPrintln("configureBase: disable survey in failed"); } response &= enableRTCMBase(); // Set RTCM messages if (settings.debugGnss && response == false) - systemPrintln("Base: Enable RTCM failed"); + systemPrintln("configureBase: Enable RTCM failed"); response &= enableNMEA(); // Set NMEA messages if (settings.debugGnss && response == false) - systemPrintln("Base: Enable NMEA failed"); + systemPrintln("configureBase: Enable NMEA failed"); response &= exitConfigMode(); // We must exit config before we save otherwise we will save with NMEA/RTCM off @@ -464,11 +488,20 @@ bool GNSS_LG290P::configureNtpMode() //---------------------------------------- // Disable NMEA and RTCM on UART2 to reduce the serial traffic //---------------------------------------- -bool GNSS_LG290P::enterConfigMode() +bool GNSS_LG290P::enterConfigMode(unsigned long waitForSemaphoreTimeout_millis) { if (online.gnss) + { + unsigned long start = millis(); + bool isBlocking; + do { // Wait for up to waitForSemaphoreTimeout for library to stop blocking + isBlocking = _lg290p->isBlocking(); + } while (isBlocking && (millis() < (start + waitForSemaphoreTimeout_millis))); + + // This will fail if the library is still blocking, but it is worth a punt... return (_lg290p->sendOkCommand("$PQTMCFGPROT", ",W,1,2,00000000,00000000")); // Disable NMEA and RTCM on the LG290P UART2 + } return (false); } From 457cd6ab20ee968a46498fcd80d96d9167339794 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 18 Feb 2025 14:56:07 +0000 Subject: [PATCH 265/276] Tag arrival of MQTT corrections on UM980 / LG280P --- Firmware/RTK_Everywhere/MQTT_Client.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Firmware/RTK_Everywhere/MQTT_Client.ino b/Firmware/RTK_Everywhere/MQTT_Client.ino index 9b246772d..bc3acfd8d 100644 --- a/Firmware/RTK_Everywhere/MQTT_Client.ino +++ b/Firmware/RTK_Everywhere/MQTT_Client.ino @@ -557,6 +557,8 @@ void mqttClientReceiveMessage(int messageSize) sendSpartnToPpl(mqttData, mqttCount); bytesPushed += mqttCount; + + mqttClientDataReceived = true; } // Record the arrival of data over MQTT From ca63b778bb0b0ee2f8ba489fe391b0bd6e4ee0b4 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 18 Feb 2025 16:23:06 +0000 Subject: [PATCH 266/276] On Torch (UM980) don't trust the saved Base/Rover configuration --- Firmware/RTK_Everywhere/GNSS_UM980.ino | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_UM980.ino b/Firmware/RTK_Everywhere/GNSS_UM980.ino index 4c59ecb58..90edfc060 100644 --- a/Firmware/RTK_Everywhere/GNSS_UM980.ino +++ b/Firmware/RTK_Everywhere/GNSS_UM980.ino @@ -166,12 +166,13 @@ bool GNSS_UM980::configureBase() return (false); } - if (settings.gnssConfiguredBase) - { - if (settings.debugGnss) - systemPrintln("Skipping UM980 Base configuration"); - return true; - } + // // If our settings haven't changed, trust GNSS's settings + // if (settings.gnssConfiguredBase) + // { + // if (settings.debugGnss) + // systemPrintln("Skipping UM980 Base configuration"); + // return true; + // } disableAllOutput(); @@ -225,6 +226,7 @@ bool GNSS_UM980::configureOnce() Enable selected RTCM messages on COM3 */ + // // If our settings haven't changed, trust GNSS's settings if (settings.gnssConfiguredOnce) { systemPrintln("UM980 configuration maintained"); @@ -342,12 +344,12 @@ bool GNSS_UM980::configureRover() return (false); } - // If our settings haven't changed, trust GNSS's settings - if (settings.gnssConfiguredRover) - { - systemPrintln("Skipping UM980 Rover configuration"); - return (true); - } + // // If our settings haven't changed, trust GNSS's settings + // if (settings.gnssConfiguredRover) + // { + // systemPrintln("Skipping UM980 Rover configuration"); + // return (true); + // } disableAllOutput(); From cd0c7c3f5eea1f68b419553119ba9d238c5e7dd3 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Tue, 18 Feb 2025 16:46:55 +0000 Subject: [PATCH 267/276] Add better comments about the UM980 saved configuration --- Firmware/RTK_Everywhere/GNSS_UM980.ino | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_UM980.ino b/Firmware/RTK_Everywhere/GNSS_UM980.ino index 90edfc060..07e035801 100644 --- a/Firmware/RTK_Everywhere/GNSS_UM980.ino +++ b/Firmware/RTK_Everywhere/GNSS_UM980.ino @@ -166,7 +166,10 @@ bool GNSS_UM980::configureBase() return (false); } - // // If our settings haven't changed, trust GNSS's settings + // Trusting the saved configuration does not seem to work on the UM980. + // It looks like the GPGGA NMEA output does not restart...? + // (Re)configuration is quick. Doing this every time is not much of an overhead. + // // if (settings.gnssConfiguredBase) // { // if (settings.debugGnss) @@ -344,7 +347,10 @@ bool GNSS_UM980::configureRover() return (false); } - // // If our settings haven't changed, trust GNSS's settings + // Trusting the saved configuration does not seem to work on the UM980. + // It looks like the GPGGA NMEA output does not restart...? + // (Re)configuration is quick. Doing this every time is not much of an overhead. + // // if (settings.gnssConfiguredRover) // { // systemPrintln("Skipping UM980 Rover configuration"); From 871dce6e2d5f29113534c6d27b7e45ee468c9999 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 19 Feb 2025 16:42:34 +0000 Subject: [PATCH 268/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index d316e55a8..09243530c 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xDC, 0xC8, 0xAF, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0xF9, 0x09, 0xB6, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -1049,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xDC, 0xC8, 0xAF, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0xF9, 0x09, 0xB6, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, From cbf937f4c0d3a64e9249b61e8497268ae93f1905 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 20 Feb 2025 09:50:51 +0000 Subject: [PATCH 269/276] mosaic-X5 : allow extra time for eccf (saveConfiguration) --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 29 +++++++++++++++++-------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index ebe141c59..bf0339210 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -1014,8 +1014,15 @@ bool GNSS_MOSAIC::enableRTCMTest() //---------------------------------------- void GNSS_MOSAIC::factoryReset() { - sendWithResponse("eccf,RxDefault,Boot\n\r", "CopyConfigFile"); - sendWithResponse("eccf,RxDefault,Current\n\r", "CopyConfigFile"); + unsigned long start = millis(); + bool result = sendWithResponse("eccf,RxDefault,Boot\n\r", "CopyConfigFile", 5000); + if (settings.debugGnss) + systemPrintf("saveConfiguration: sendWithResponse eccf,RxDefault,Boot returned %s after %d ms\r\n", result ? "true" : "false", millis() - start); + + start = millis(); + result = sendWithResponse("eccf,RxDefault,Current\n\r", "CopyConfigFile", 5000); + if (settings.debugGnss) + systemPrintf("saveConfiguration: sendWithResponse eccf,RxDefault,Current returned %s after %d ms\r\n", result ? "true" : "false", millis() - start); } //---------------------------------------- @@ -1935,7 +1942,11 @@ uint16_t GNSS_MOSAIC::rtcmRead(uint8_t *rtcmBuffer, int rtcmBytesToRead) //---------------------------------------- bool GNSS_MOSAIC::saveConfiguration() { - return sendWithResponse("eccf,Current,Boot\n\r", "CopyConfigFile"); + unsigned long start = millis(); + bool result = sendWithResponse("eccf,Current,Boot\n\r", "CopyConfigFile", 5000); + if (settings.debugGnss) + systemPrintf("saveConfiguration: sendWithResponse returned %s after %d ms\r\n", result ? "true" : "false", millis() - start); + return result; } //---------------------------------------- @@ -2846,12 +2857,12 @@ void processUart1SBF(SEMP_PARSE_STATE *parse, uint16_t type) { GNSS_MOSAIC *mosaic = (GNSS_MOSAIC *)gnss; - if (((settings.debugGnss == true) || PERIODIC_DISPLAY(PD_GNSS_DATA_RX)) && !inMainMenu) - { - // Don't call PERIODIC_CLEAR(PD_GNSS_DATA_RX); here. Let processUart1Message do it via rtkParse - systemPrintf("Processing SBF Block %d (%d bytes) from mosaic-X5\r\n", sempSbfGetBlockNumber(parse), - parse->length); - } + // if (((settings.debugGnss == true) || PERIODIC_DISPLAY(PD_GNSS_DATA_RX)) && !inMainMenu) + // { + // // Don't call PERIODIC_CLEAR(PD_GNSS_DATA_RX); here. Let processUart1Message do it via rtkParse + // systemPrintf("Processing SBF Block %d (%d bytes) from mosaic-X5\r\n", sempSbfGetBlockNumber(parse), + // parse->length); + // } // If this is PVTGeodetic, extract some data if (sempSbfGetBlockNumber(parse) == 4007) From fc0d68fc979f990e6cba94cc1325de775f447cad Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 20 Feb 2025 12:57:33 +0000 Subject: [PATCH 270/276] Update debug --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index bf0339210..58f39b1e9 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -1017,12 +1017,12 @@ void GNSS_MOSAIC::factoryReset() unsigned long start = millis(); bool result = sendWithResponse("eccf,RxDefault,Boot\n\r", "CopyConfigFile", 5000); if (settings.debugGnss) - systemPrintf("saveConfiguration: sendWithResponse eccf,RxDefault,Boot returned %s after %d ms\r\n", result ? "true" : "false", millis() - start); + systemPrintf("factoryReset: sendWithResponse eccf,RxDefault,Boot returned %s after %d ms\r\n", result ? "true" : "false", millis() - start); start = millis(); result = sendWithResponse("eccf,RxDefault,Current\n\r", "CopyConfigFile", 5000); if (settings.debugGnss) - systemPrintf("saveConfiguration: sendWithResponse eccf,RxDefault,Current returned %s after %d ms\r\n", result ? "true" : "false", millis() - start); + systemPrintf("factoryReset: sendWithResponse eccf,RxDefault,Current returned %s after %d ms\r\n", result ? "true" : "false", millis() - start); } //---------------------------------------- From e8122644ce6675356e45e9edba802715b1657863 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 20 Feb 2025 12:58:44 +0000 Subject: [PATCH 271/276] Only trust settings.gnssConfigured from LittleFS --- Firmware/RTK_Everywhere/NVM.ino | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Firmware/RTK_Everywhere/NVM.ino b/Firmware/RTK_Everywhere/NVM.ino index aef52517e..4ed0e052e 100644 --- a/Firmware/RTK_Everywhere/NVM.ino +++ b/Firmware/RTK_Everywhere/NVM.ino @@ -60,11 +60,20 @@ void loadSettings() // Temp store any variables from LFS that should override SD int resetCount = settings.resetCount; + bool gnssConfiguredOnce = settings.gnssConfiguredOnce; + bool gnssConfiguredRover = settings.gnssConfiguredRover; + bool gnssConfiguredBase = settings.gnssConfiguredBase; loadSystemSettingsFromFileSD(settingsFileName); settings.resetCount = resetCount; // resetCount from LFS should override SD + // Trust gnssConfigured from LittleFS over SD. + // LittleFS may have been erased, SD could be stale. + settings.gnssConfiguredOnce = gnssConfiguredOnce; + settings.gnssConfiguredRover = gnssConfiguredRover; + settings.gnssConfiguredBase = gnssConfiguredBase; + // Change empty profile name to 'Profile1' etc if (strlen(settings.profileName) == 0) { From 0597137fdf7c427379ed027e28f09234ff43cec0 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 20 Feb 2025 13:29:37 +0000 Subject: [PATCH 272/276] mosaic : extra saveConfiguration --- Firmware/RTK_Everywhere/GNSS_Mosaic.ino | 23 ++++++++++++++--------- Firmware/RTK_Everywhere/menuPP.ino | 2 ++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino index 58f39b1e9..40e8701ef 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.ino +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.ino @@ -135,9 +135,10 @@ void menuLogMosaic() { GNSS_MOSAIC *mosaic = (GNSS_MOSAIC *)gnss; - mosaic->configureLogging(); // This will enable / disable RINEX logging - mosaic->enableNMEA(); // Enable NMEA messages - this will enable/disable the DSK1 streams - setLoggingType(); // Update Standard, PPP, or custom for icon selection + mosaic->configureLogging(); // This will enable / disable RINEX logging + mosaic->enableNMEA(); // Enable NMEA messages - this will enable/disable the DSK1 streams + mosaic->saveConfiguration(); // Save the configuration + setLoggingType(); // Update Standard, PPP, or custom for icon selection } clearBuffer(); // Empty buffer of any newline chars @@ -419,6 +420,10 @@ bool GNSS_MOSAIC::configureBase() response &= setElevation(settings.minElev); + response &= setMinCnoRadio(settings.minCNO); + + response &= setConstellations(); + response &= enableRTCMBase(); response &= enableNMEA(); @@ -583,12 +588,6 @@ bool GNSS_MOSAIC::configureOnce() setting = String("sso,Stream" + String(MOSAIC_SBF_STATUS_STREAM) + ",COM1,ChannelStatus+DiskStatus,sec2\n\r"); response &= sendWithResponse(setting, "SBFOutput"); - response &= setElevation(settings.minElev); - - response &= setMinCnoRadio(settings.minCNO); - - response &= setConstellations(); - // Mark L5 as healthy response &= sendWithResponse("shm,Tracking,off\n\r", "HealthMask"); response &= sendWithResponse("shm,PVT,off\n\r", "HealthMask"); @@ -668,6 +667,10 @@ bool GNSS_MOSAIC::configureRover() response &= setElevation(settings.minElev); // Set by menuGNSS which calls gnss->setElevation + response &= setMinCnoRadio(settings.minCNO); + + response &= setConstellations(); + response &= enableRTCMRover(); response &= enableNMEA(); @@ -1657,6 +1660,8 @@ void GNSS_MOSAIC::menuConstellations() // Apply current settings to module setConstellations(); + saveConfiguration(); // Save the updated constellations + clearBuffer(); // Empty buffer of any newline chars } diff --git a/Firmware/RTK_Everywhere/menuPP.ino b/Firmware/RTK_Everywhere/menuPP.ino index a4bae6b1e..23fd38add 100644 --- a/Firmware/RTK_Everywhere/menuPP.ino +++ b/Firmware/RTK_Everywhere/menuPP.ino @@ -916,6 +916,8 @@ void updateLBand() result &= mosaic->configureLBand(true, LBandFreq); // Start L-Band + result &= mosaic->saveConfiguration(); // Save the updated configuration. Probably redundant? + if (result == false) { systemPrintln("mosaic-X5 L-Band failed to configure"); From ed3f5a08976633ef4ed9343e3e312b55d3f93857 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 20 Feb 2025 14:44:07 +0000 Subject: [PATCH 273/276] Correct NavIC constellation name for config --- Firmware/RTK_Everywhere/GNSS_Mosaic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/RTK_Everywhere/GNSS_Mosaic.h b/Firmware/RTK_Everywhere/GNSS_Mosaic.h index 95bffeb7b..a2e41310c 100644 --- a/Firmware/RTK_Everywhere/GNSS_Mosaic.h +++ b/Firmware/RTK_Everywhere/GNSS_Mosaic.h @@ -229,7 +229,7 @@ const mosaicSignalConstellation mosaicSignalConstellations[] = { {"SBAS","SBAS"}, {"BEIDOU","BeiDou"}, {"QZSS","QZSS"}, - {"NAVIC","NAVIC"}, + {"NAVIC","NavIC"}, }; #define MAX_MOSAIC_CONSTELLATIONS (sizeof(mosaicSignalConstellations) / sizeof(mosaicSignalConstellation)) From df225a3e41c99f01feae6ba480efbbd12afbacf0 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 20 Feb 2025 14:44:33 +0000 Subject: [PATCH 274/276] Update form.h --- Firmware/RTK_Everywhere/form.h | 4212 ++++++++++++++++---------------- 1 file changed, 2112 insertions(+), 2100 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index d316e55a8..dd78ebb95 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,1022 +26,1029 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xDC, 0xC8, 0xAF, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, - 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, - 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, - 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, - 0x6D, 0xF7, 0xD8, 0x6E, 0x08, 0x33, 0xCB, 0x3B, 0xED, 0x33, 0xEC, 0x93, 0xDD, 0x2A, 0x49, 0xB6, - 0x25, 0x59, 0xFE, 0xEC, 0x86, 0x30, 0xB3, 0xC9, 0xEF, 0x77, 0x38, 0x60, 0xA9, 0x3E, 0x54, 0x2A, - 0x95, 0x4A, 0x52, 0xA9, 0x74, 0x6B, 0x07, 0x64, 0x68, 0x47, 0xF4, 0xCE, 0xBE, 0x27, 0xBB, 0xE4, - 0xDF, 0xEF, 0xC2, 0x57, 0xAB, 0xAB, 0x7F, 0xFC, 0xFB, 0x9D, 0xEB, 0x39, 0xFE, 0x5D, 0x67, 0xE4, - 0x0F, 0xEC, 0xC8, 0xF5, 0xBD, 0xCE, 0x8D, 0x1F, 0x46, 0x9E, 0x3D, 0xA6, 0x0F, 0xAF, 0xB6, 0xBA, - 0xAB, 0x77, 0xE1, 0xBF, 0xEF, 0xBC, 0xB8, 0x05, 0xB8, 0x3B, 0x7A, 0x15, 0xFA, 0x83, 0x6F, 0x34, - 0xDA, 0x79, 0xF1, 0x42, 0x40, 0xD8, 0x8E, 0x73, 0x78, 0x4B, 0xBD, 0xE8, 0xD8, 0x0D, 0x23, 0xEA, - 0xD1, 0x60, 0x71, 0x61, 0xE4, 0xDB, 0xCE, 0x42, 0x9B, 0xF8, 0xDE, 0x31, 0xFC, 0xB2, 0x04, 0x35, - 0xAF, 0xA7, 0xDE, 0x00, 0x91, 0x8A, 0x4F, 0x8B, 0x14, 0xEB, 0x2F, 0x91, 0xBF, 0xBF, 0x20, 0xF0, - 0xCF, 0xF5, 0xDC, 0xE8, 0x57, 0x7A, 0xD5, 0x67, 0x68, 0x17, 0xA1, 0xFA, 0x83, 0x04, 0xA0, 0x15, - 0x0A, 0x90, 0x84, 0x0B, 0xE0, 0xDF, 0xA3, 0x77, 0x24, 0xAD, 0x21, 0xDA, 0x05, 0x58, 0x94, 0x7A, - 0x1D, 0xDF, 0x1B, 0xD3, 0x30, 0xB4, 0x87, 0x14, 0x20, 0x12, 0xE4, 0x8B, 0xE3, 0x70, 0x18, 0xA3, - 0xC4, 0x7F, 0x13, 0x3B, 0x08, 0xE9, 0x91, 0x37, 0xF0, 0xC7, 0xAE, 0x37, 0xC4, 0xC2, 0x8E, 0x63, - 0x47, 0xB6, 0xC0, 0xF5, 0xA0, 0x32, 0x36, 0xA4, 0x8B, 0x34, 0x86, 0x0D, 0x68, 0x34, 0x0D, 0x3C, - 0xE2, 0xF8, 0x83, 0xE9, 0x18, 0x1A, 0xD6, 0x19, 0xD2, 0xE8, 0x70, 0x44, 0xF1, 0xD7, 0xB7, 0xF7, - 0x47, 0xD0, 0x5A, 0xDE, 0x26, 0x14, 0xDF, 0xB5, 0xFB, 0x9D, 0x3A, 0xC7, 0x36, 0xF2, 0x6D, 0xED, - 0x48, 0x5F, 0x7C, 0x6F, 0x98, 0x7E, 0x9A, 0x8C, 0xEC, 0xE8, 0xDA, 0x0F, 0xC6, 0x67, 0x01, 0x85, - 0x52, 0xF8, 0xDE, 0x6A, 0xF1, 0x82, 0x21, 0xF5, 0x1D, 0x1A, 0xB9, 0x03, 0x8E, 0x60, 0xDD, 0xEA, - 0x58, 0x5D, 0xAD, 0x00, 0x18, 0xDB, 0x25, 0x2B, 0x5D, 0x6B, 0xA3, 0xD3, 0xDD, 0x56, 0x8B, 0xF6, - 0x46, 0x08, 0xD3, 0xDD, 0xB0, 0xAC, 0x8E, 0x00, 0xA2, 0x03, 0x7A, 0xFD, 0x1B, 0xAB, 0xDE, 0xDB, - 0xB2, 0x7A, 0xD6, 0x66, 0x67, 0x63, 0x73, 0x2B, 0x2D, 0xF9, 0x8C, 0x25, 0xEB, 0x2F, 0xBB, 0x9B, - 0x5B, 0xD6, 0x7A, 0x67, 0xDD, 0x5A, 0x4B, 0x4B, 0x7E, 0x67, 0xB4, 0xB7, 0x36, 0x37, 0x37, 0x37, - 0x3A, 0xEB, 0x5B, 0xEB, 0xBC, 0x60, 0x64, 0x87, 0xD1, 0x3B, 0x77, 0x44, 0x4F, 0x41, 0x63, 0x24, - 0x8E, 0xAF, 0xF1, 0xD3, 0x74, 0x7C, 0x45, 0x83, 0xB4, 0x79, 0x1E, 0xFB, 0xFB, 0xE3, 0x35, 0x56, - 0x0F, 0xFB, 0x74, 0x44, 0x07, 0x11, 0x75, 0xD2, 0xE2, 0x50, 0x7C, 0x61, 0xC5, 0x12, 0xAA, 0xF0, - 0xC6, 0x07, 0x85, 0x1B, 0xE2, 0x67, 0xD4, 0x34, 0xEC, 0x47, 0x7B, 0x14, 0x52, 0x5E, 0xE8, 0x5F, - 0x45, 0xB6, 0xEB, 0x51, 0xE7, 0x84, 0x77, 0x72, 0xA5, 0x0A, 0x6F, 0xED, 0x90, 0xAA, 0x95, 0x04, - 0x09, 0x51, 0xE7, 0xFC, 0x62, 0xFF, 0x24, 0x8B, 0x08, 0x5B, 0x74, 0x61, 0x5F, 0xC1, 0x0F, 0xFA, - 0x3D, 0x92, 0xD8, 0x1B, 0xF8, 0x41, 0x40, 0x99, 0x6A, 0x68, 0x05, 0x42, 0xEF, 0xB4, 0xAF, 0x28, - 0x2F, 0x41, 0xE7, 0xE2, 0x7E, 0x42, 0xF3, 0x4B, 0x04, 0x97, 0x58, 0xCA, 0x79, 0xB4, 0x6F, 0x93, - 0x56, 0xA0, 0xB0, 0x51, 0x44, 0x5F, 0xBE, 0xEE, 0x64, 0xCA, 0x7E, 0xB1, 0x47, 0xD3, 0x6C, 0xE1, - 0xFE, 0x0D, 0x1D, 0x7C, 0xBB, 0xF2, 0xBF, 0x1B, 0x21, 0xE3, 0x42, 0x05, 0x94, 0x15, 0x43, 0xCB, - 0xFC, 0xC0, 0x09, 0x0F, 0xF7, 0x0F, 0xDF, 0x49, 0x40, 0xE2, 0xEB, 0x7B, 0xA1, 0x61, 0x52, 0xC9, - 0xF5, 0x74, 0x34, 0x3A, 0x03, 0x26, 0x3E, 0x4D, 0x60, 0x00, 0x49, 0x42, 0x16, 0x60, 0x21, 0x8D, - 0x2E, 0xDC, 0x31, 0xF5, 0xA7, 0x51, 0xDC, 0xE5, 0x9E, 0x73, 0x00, 0x23, 0x4D, 0xF9, 0x38, 0x40, - 0x6E, 0x4E, 0xE9, 0xDD, 0x3B, 0x37, 0x18, 0xDF, 0xD9, 0x01, 0x55, 0x0A, 0x61, 0x84, 0x99, 0x8A, - 0x5E, 0x0C, 0x7C, 0x0F, 0x3A, 0x0C, 0x34, 0x6C, 0x3F, 0xE9, 0x8E, 0xB0, 0xEF, 0x4F, 0x83, 0x01, - 0x6B, 0xCF, 0x96, 0xDE, 0x55, 0xA2, 0x4C, 0x97, 0x46, 0xA6, 0xC2, 0x59, 0xE0, 0xFA, 0x81, 0x1B, - 0xB9, 0xA9, 0x54, 0x38, 0xA1, 0x7D, 0x1F, 0x04, 0xE0, 0x7A, 0xD0, 0x46, 0xEC, 0x2A, 0x2C, 0xE4, - 0x06, 0x61, 0xFF, 0xE3, 0xC7, 0xF3, 0x83, 0xA3, 0xD3, 0xBD, 0x8B, 0xC3, 0xCB, 0xA3, 0xD3, 0xB3, - 0x4F, 0x17, 0x97, 0x17, 0x9F, 0xCF, 0x0E, 0x2F, 0x0F, 0x0E, 0x5E, 0x11, 0xAB, 0x4D, 0x56, 0x57, - 0x0F, 0xE8, 0xB5, 0x3D, 0x85, 0xF1, 0x78, 0x70, 0xD0, 0x71, 0xE2, 0x7F, 0x85, 0x70, 0x27, 0x27, - 0xAF, 0x48, 0x97, 0x41, 0xC2, 0xAF, 0x9D, 0x31, 0xFE, 0x2B, 0xAC, 0x7F, 0x89, 0x00, 0x3D, 0x0E, - 0x40, 0xAA, 0x42, 0x5C, 0x1E, 0xEC, 0xF5, 0x3F, 0xBC, 0x22, 0x6B, 0x1C, 0x6C, 0xA5, 0x32, 0x58, - 0xFF, 0xF3, 0xC9, 0xDB, 0x8F, 0xC7, 0xAF, 0xC8, 0x3A, 0x07, 0xFC, 0xEF, 0xFF, 0x8A, 0x21, 0xC7, - 0xE3, 0x85, 0x92, 0x56, 0xF5, 0xFB, 0xAF, 0xC8, 0x46, 0xC2, 0x26, 0xE9, 0xF7, 0x3B, 0x21, 0xFB, - 0x57, 0x4E, 0x13, 0x00, 0x37, 0x9B, 0x01, 0x8A, 0x66, 0xBE, 0x4C, 0x9A, 0xB9, 0x52, 0x0B, 0x3A, - 0x6E, 0xED, 0x56, 0xDA, 0xDA, 0x85, 0x04, 0x41, 0xAB, 0xB4, 0xBD, 0x97, 0xA7, 0x1F, 0x2F, 0x0F, - 0x0E, 0xF7, 0x8F, 0x4E, 0xF6, 0x00, 0xC7, 0x76, 0xDC, 0xA5, 0xFD, 0x3E, 0x59, 0x21, 0xA7, 0x3E, - 0x71, 0xE8, 0xC0, 0x1D, 0xDB, 0xA3, 0x2A, 0x7C, 0xC8, 0x78, 0xBA, 0x96, 0x2C, 0x8A, 0xDA, 0xA8, - 0x50, 0x20, 0x2A, 0xBE, 0xAE, 0x2C, 0x9C, 0xAA, 0xF8, 0x8E, 0x4E, 0x7F, 0xD9, 0x3B, 0x3E, 0x3A, - 0xB8, 0xFC, 0x74, 0xFA, 0x97, 0xD3, 0x8F, 0xBF, 0x9E, 0x02, 0x9A, 0x5E, 0x3B, 0x9E, 0xF7, 0x60, - 0xB8, 0xDC, 0xD2, 0x00, 0xAC, 0x7A, 0x3A, 0x62, 0xD0, 0xE2, 0x77, 0xAC, 0x78, 0xC0, 0xC5, 0x5F, - 0x8F, 0xBC, 0xC9, 0x34, 0x12, 0x16, 0x51, 0x1B, 0x5D, 0x9D, 0xBC, 0x66, 0xC8, 0x0E, 0x46, 0x66, - 0x0A, 0x8F, 0xE7, 0xE8, 0xD5, 0x55, 0x1C, 0xB2, 0xFE, 0x88, 0x82, 0x87, 0x33, 0x5C, 0x6C, 0xC5, - 0x55, 0x62, 0xF3, 0xFC, 0x8A, 0xB4, 0xC8, 0x32, 0xC1, 0xFA, 0x80, 0x0D, 0xEB, 0x23, 0x5B, 0x38, - 0xFB, 0x03, 0x1F, 0xE8, 0x08, 0x84, 0x93, 0x91, 0x1B, 0x2D, 0x2E, 0xB4, 0x17, 0x84, 0x37, 0x00, - 0xF3, 0x33, 0x59, 0x1C, 0x81, 0x03, 0xF2, 0x9D, 0xCD, 0x5C, 0xF0, 0xBF, 0xD7, 0xAC, 0x7A, 0x67, - 0x44, 0xBD, 0x61, 0x74, 0x03, 0x32, 0xEB, 0xE2, 0xC7, 0xE5, 0x5D, 0xD2, 0x93, 0x3D, 0x0C, 0xC4, - 0xEA, 0xE2, 0x64, 0x87, 0x75, 0xBF, 0x7C, 0xFF, 0xBA, 0xA3, 0x94, 0xDC, 0xDA, 0xA3, 0xA4, 0x08, - 0xB8, 0xE9, 0x4A, 0xC5, 0x1A, 0xFB, 0xAE, 0xC3, 0x19, 0x06, 0x5C, 0xCB, 0xA4, 0xD5, 0x46, 0x48, - 0xFE, 0x01, 0x7E, 0x89, 0x5B, 0xC0, 0xC1, 0xFA, 0x13, 0xE8, 0x38, 0xC0, 0x0B, 0xCD, 0x1D, 0xDB, - 0x9E, 0x13, 0x26, 0x45, 0xEE, 0x35, 0x59, 0x74, 0x9D, 0x8E, 0xEB, 0x0D, 0x46, 0x53, 0x87, 0x86, - 0x8B, 0xAD, 0xD0, 0x39, 0xF1, 0xA7, 0x1E, 0xF4, 0x51, 0x6B, 0x49, 0x66, 0x99, 0xA3, 0xB9, 0x40, - 0x07, 0xC7, 0xF7, 0x56, 0xFD, 0xEB, 0x6B, 0xD2, 0x3F, 0x20, 0x60, 0x74, 0x6D, 0xA5, 0x06, 0x62, - 0x63, 0xEC, 0xC3, 0x54, 0xC5, 0x8C, 0x7D, 0x4B, 0xC7, 0x81, 0xFF, 0x6E, 0x5C, 0x87, 0x2E, 0xB6, - 0x70, 0x0A, 0x3D, 0xB1, 0x3D, 0x90, 0x7A, 0xD0, 0x5A, 0xDA, 0x51, 0x2A, 0x3D, 0x28, 0x7F, 0x51, - 0xC0, 0xA3, 0x60, 0x8E, 0x82, 0xA9, 0x19, 0x31, 0xCE, 0xDC, 0x15, 0x11, 0xA7, 0xBF, 0x25, 0xE8, - 0xB1, 0x47, 0x00, 0xBB, 0xEA, 0x77, 0x65, 0xE8, 0x64, 0xDC, 0x32, 0xE0, 0x4A, 0x25, 0x92, 0x38, - 0x80, 0x91, 0x1B, 0x8D, 0xD8, 0xAC, 0x7D, 0x7E, 0xF1, 0x17, 0xD6, 0x2D, 0x1A, 0x2C, 0xF4, 0x19, - 0xE9, 0x83, 0xD3, 0x38, 0x69, 0xA9, 0x08, 0x32, 0xF3, 0x26, 0x36, 0x58, 0xAD, 0x62, 0xF4, 0x33, - 0x32, 0x5D, 0xA1, 0xF3, 0x0A, 0xD5, 0x0E, 0x7F, 0xF9, 0x4B, 0x81, 0xE8, 0xAE, 0xC0, 0xCD, 0xD8, - 0xF7, 0xBD, 0x6B, 0x77, 0xA8, 0x4B, 0x2E, 0xAD, 0x33, 0x99, 0x94, 0xD5, 0xA0, 0xD1, 0x0D, 0x0D, - 0x3C, 0x1A, 0x95, 0xD5, 0xF3, 0xA2, 0x52, 0x54, 0x13, 0x3F, 0x88, 0xC2, 0xFC, 0x4A, 0x5C, 0x93, - 0x40, 0x02, 0x40, 0xCF, 0x1E, 0x9D, 0x41, 0xE5, 0x8F, 0x13, 0x36, 0x61, 0xE7, 0x63, 0x84, 0x81, - 0x73, 0xE1, 0xF7, 0x0F, 0xF6, 0xED, 0xC0, 0xC9, 0xC7, 0x38, 0xB4, 0x47, 0xA0, 0x44, 0xFE, 0x07, - 0x1B, 0x3C, 0xD3, 0x28, 0x02, 0x03, 0x91, 0x5F, 0x35, 0x72, 0x47, 0x51, 0x19, 0x83, 0x57, 0x94, - 0x4E, 0x68, 0x00, 0xB5, 0xA2, 0xC0, 0x1F, 0xE5, 0xB3, 0x36, 0x0D, 0xE9, 0x5E, 0x18, 0x82, 0xAF, - 0x79, 0xEA, 0xDF, 0xC5, 0x5E, 0x58, 0x7E, 0xED, 0x31, 0xB5, 0xC3, 0x69, 0xC0, 0xD6, 0x17, 0xE7, - 0xB1, 0xC9, 0xCC, 0x67, 0x61, 0xEC, 0x87, 0xB6, 0x3B, 0x38, 0x3D, 0x39, 0xDC, 0xEB, 0x47, 0x30, - 0x6A, 0xC7, 0x07, 0x81, 0x3F, 0x81, 0x65, 0x5B, 0x91, 0xA4, 0x00, 0xFB, 0x2D, 0xBD, 0x3F, 0xF2, - 0x84, 0x08, 0xC2, 0x42, 0xC6, 0x8F, 0x61, 0xC1, 0x38, 0x72, 0xFF, 0x46, 0x9D, 0x03, 0xE0, 0x3F, - 0x70, 0xAF, 0xA6, 0xD8, 0x0D, 0xE5, 0x8D, 0x00, 0xC8, 0x43, 0x0F, 0xFD, 0xE8, 0xC3, 0xEF, 0x11, - 0x3A, 0x6B, 0xE7, 0xB6, 0xE3, 0xFA, 0x05, 0x9A, 0x25, 0xD5, 0xEA, 0x9F, 0xED, 0x9D, 0x5F, 0x9C, - 0x72, 0xCF, 0x2C, 0x6E, 0x4D, 0x7E, 0xFB, 0xC3, 0x9B, 0x69, 0x84, 0x35, 0x4E, 0xFD, 0xFD, 0x1B, - 0x3B, 0x18, 0xC6, 0xCE, 0xE2, 0x89, 0xEB, 0x4D, 0x23, 0x1A, 0xC6, 0x8C, 0x1E, 0x50, 0x58, 0x1F, - 0xB0, 0x1E, 0xCA, 0x41, 0xC3, 0x1C, 0x3E, 0x3A, 0x1A, 0xB1, 0xC5, 0xF1, 0xA9, 0x7D, 0xEB, 0x0E, - 0xA0, 0x32, 0x18, 0xC6, 0x53, 0x3F, 0x22, 0xE1, 0x74, 0x82, 0xEA, 0x0A, 0xAB, 0x18, 0x98, 0x81, - 0x7E, 0x3F, 0x3C, 0xA8, 0x62, 0xD2, 0x4C, 0x43, 0xF4, 0x9D, 0x3D, 0x80, 0x19, 0xE5, 0xB6, 0x07, - 0xE3, 0xF4, 0x3F, 0xFF, 0x93, 0x14, 0xD5, 0x20, 0xC7, 0x6F, 0xC1, 0x98, 0x67, 0x0D, 0xF5, 0xFC, - 0x06, 0xB4, 0x18, 0x60, 0xA5, 0x03, 0x9A, 0xD7, 0x9B, 0x7D, 0x40, 0x27, 0xDD, 0xFC, 0x73, 0x40, - 0xFF, 0x1C, 0xD0, 0x62, 0x40, 0x3F, 0xD1, 0x50, 0xCC, 0x1D, 0x67, 0x5C, 0xD2, 0xBF, 0x6D, 0xB4, - 0x7E, 0x0E, 0xB3, 0xE7, 0x36, 0xCC, 0x78, 0xB5, 0xAA, 0xC3, 0x4C, 0x0C, 0x9C, 0x8A, 0xC3, 0x4C, - 0x0C, 0xCA, 0x3A, 0xC3, 0x4C, 0x4C, 0x35, 0x15, 0x86, 0x59, 0xC2, 0xF8, 0x63, 0x0F, 0xB3, 0xC4, - 0x43, 0xAA, 0x3F, 0xCC, 0xF8, 0x16, 0x1C, 0xF8, 0x96, 0x43, 0xC0, 0xE0, 0xDC, 0x7B, 0xF6, 0xD8, - 0x1D, 0x9C, 0xF8, 0x0E, 0x35, 0xF6, 0x04, 0x2E, 0x82, 0x3C, 0x7A, 0xC7, 0xD5, 0x48, 0xEC, 0xC7, - 0xF2, 0x3F, 0x16, 0x17, 0xFA, 0x11, 0x8C, 0xD1, 0xC1, 0x42, 0x9B, 0x2C, 0x58, 0x0B, 0xA6, 0x16, - 0x31, 0x3A, 0xB8, 0x81, 0xBC, 0x98, 0x60, 0x68, 0x93, 0xA9, 0xE7, 0xC0, 0x38, 0xF4, 0xA8, 0x63, - 0x80, 0xC8, 0x23, 0xF4, 0xFF, 0xA6, 0x36, 0xAA, 0x41, 0x4C, 0xAD, 0xFB, 0xB8, 0xD4, 0xCE, 0x28, - 0x2C, 0x98, 0xA0, 0xCF, 0x6C, 0x0F, 0x89, 0xF5, 0x1E, 0x97, 0xD8, 0xDE, 0x34, 0xF2, 0xC7, 0x7E, - 0xE4, 0xDE, 0x52, 0x24, 0xB6, 0xF6, 0xB8, 0xC4, 0xCE, 0xC1, 0xEE, 0x11, 0x18, 0xE9, 0x48, 0x6A, - 0xFD, 0x71, 0x49, 0x7D, 0xA0, 0xF6, 0xED, 0x3D, 0x39, 0xB1, 0x07, 0x37, 0x00, 0x18, 0xDC, 0x23, - 0xC5, 0x8D, 0xC7, 0xA5, 0xF8, 0x69, 0xEF, 0x17, 0xA4, 0xB2, 0xF9, 0xC8, 0x54, 0xBC, 0x91, 0x3B, - 0x76, 0x61, 0x06, 0x42, 0x5A, 0x2F, 0x9B, 0xD1, 0xCA, 0x80, 0x0C, 0x99, 0xF9, 0xE2, 0xDB, 0xD2, - 0xCC, 0x74, 0x5D, 0xFB, 0xB8, 0xFC, 0x6B, 0x2D, 0x75, 0x42, 0x1A, 0xED, 0x45, 0xDC, 0x7E, 0xD0, - 0xC5, 0x05, 0xDC, 0x3B, 0x58, 0xB9, 0x0A, 0x57, 0xFC, 0xC0, 0x1D, 0xBA, 0x60, 0xE0, 0x57, 0xD8, - 0x4A, 0x14, 0x39, 0xB9, 0xB8, 0xA1, 0xE4, 0xFD, 0x69, 0xBF, 0x4F, 0x06, 0x36, 0x2C, 0xE4, 0xA7, - 0x11, 0xD8, 0x3E, 0x82, 0xC6, 0x8D, 0x80, 0x1F, 0x49, 0x70, 0xAB, 0xFB, 0x76, 0x8D, 0xD8, 0x11, - 0x71, 0xDC, 0xEB, 0x6B, 0x1A, 0x80, 0x85, 0x24, 0x01, 0xD0, 0x09, 0x3B, 0xE4, 0x9D, 0x1F, 0xB0, - 0x7A, 0xAF, 0x62, 0xAB, 0x60, 0x93, 0x90, 0xD9, 0x43, 0xB6, 0x05, 0x42, 0xA1, 0xFB, 0xE2, 0x2D, - 0x94, 0x36, 0x43, 0x05, 0xFC, 0xC0, 0xFF, 0x89, 0xEB, 0xC1, 0x0C, 0x83, 0xCB, 0xF6, 0xA4, 0x16, - 0x87, 0xE2, 0x08, 0x39, 0xBD, 0x57, 0xF9, 0x95, 0xE3, 0xC3, 0x9A, 0x61, 0xE0, 0x4F, 0x27, 0x1C, - 0x31, 0x65, 0x56, 0x0F, 0xEA, 0x3A, 0xEE, 0xAD, 0xEB, 0x4C, 0xA1, 0xB6, 0xA8, 0x14, 0x76, 0x4C, - 0x42, 0x46, 0x89, 0x05, 0xD1, 0x60, 0xDC, 0x50, 0x5C, 0xC8, 0x21, 0x71, 0x43, 0x58, 0x80, 0xDB, - 0x5E, 0x08, 0xDD, 0x89, 0x1E, 0xC5, 0xD5, 0x3D, 0x81, 0x79, 0x9A, 0xE0, 0x94, 0x8F, 0xA2, 0xB2, - 0x89, 0x23, 0xF6, 0x71, 0xFD, 0x6B, 0xD2, 0xFD, 0xF0, 0x37, 0xC6, 0x7D, 0xCC, 0x13, 0xE9, 0x5A, - 0xD6, 0x46, 0x9B, 0x9C, 0xF4, 0x4F, 0xD6, 0x39, 0xFB, 0x56, 0x27, 0xAE, 0xD2, 0xB5, 0xD6, 0xD6, - 0x3A, 0xE4, 0xE2, 0x06, 0xB0, 0x63, 0x5F, 0x5C, 0x51, 0x32, 0xF2, 0xEF, 0x40, 0xE6, 0x0E, 0x2B, - 0x0D, 0xD0, 0x52, 0x87, 0xE4, 0xCE, 0x8D, 0x6E, 0xF0, 0x3B, 0x50, 0xF3, 0x9C, 0x3B, 0xD7, 0x81, - 0xBF, 0xA0, 0x10, 0xD7, 0x28, 0x3E, 0xD6, 0x8C, 0xFC, 0x84, 0x33, 0xC0, 0x7E, 0xBF, 0x6A, 0x8F, - 0x46, 0x4C, 0xA8, 0xA9, 0x4C, 0xC8, 0x31, 0x6A, 0x61, 0xF8, 0x0A, 0x09, 0x63, 0xF5, 0x4D, 0xCB, - 0xCA, 0x95, 0x13, 0xCD, 0x4C, 0x28, 0x0D, 0x24, 0xC6, 0x67, 0x25, 0x12, 0xBB, 0x16, 0xBC, 0x21, - 0xF2, 0x56, 0xFA, 0xAB, 0x58, 0xCD, 0x60, 0xC8, 0xF0, 0xC9, 0x95, 0xEC, 0x7F, 0x3C, 0xE9, 0x75, - 0x88, 0xD8, 0x0E, 0x7F, 0x45, 0xDE, 0xE1, 0xC6, 0xD1, 0x42, 0xB5, 0x2D, 0x21, 0x83, 0xD3, 0x76, - 0xE1, 0x07, 0x83, 0x9B, 0x7F, 0x22, 0x5F, 0xAD, 0x70, 0x8F, 0x23, 0xA7, 0xB6, 0xE6, 0xAC, 0x55, - 0xF1, 0xA0, 0xFB, 0x20, 0x97, 0x1C, 0x07, 0xFA, 0xD3, 0xC9, 0xF6, 0x96, 0x35, 0xAB, 0x17, 0xCE, - 0x91, 0xD4, 0x5B, 0x28, 0xE1, 0xF6, 0xB3, 0x0F, 0xA3, 0x08, 0xC7, 0xDB, 0xD9, 0xD9, 0x31, 0x81, - 0x6A, 0xE4, 0xE4, 0xFD, 0xDE, 0xBF, 0x10, 0x8E, 0x3D, 0xA0, 0x9D, 0x4E, 0xA7, 0xE6, 0x62, 0x2A, - 0xD7, 0xBB, 0x0D, 0xEC, 0xB4, 0x0B, 0x1E, 0xD1, 0x15, 0x62, 0xBE, 0xE1, 0x13, 0xB8, 0x42, 0x62, - 0x96, 0xEB, 0x3E, 0xA5, 0x57, 0xD2, 0x9B, 0xE3, 0x34, 0xF7, 0xE3, 0x8D, 0x76, 0xD7, 0x7A, 0xB9, - 0x8E, 0x3F, 0xB7, 0xD8, 0xCF, 0x6D, 0xFC, 0xD9, 0xED, 0xFD, 0x70, 0x33, 0x8E, 0x95, 0x7B, 0x56, - 0x07, 0x47, 0x00, 0x7D, 0x45, 0x70, 0x3A, 0x97, 0x34, 0x9D, 0xCD, 0xD6, 0xD8, 0x74, 0xFF, 0x96, - 0x06, 0x81, 0xEB, 0x38, 0xD4, 0xC3, 0xFA, 0xC8, 0xEB, 0xDD, 0x0D, 0xC5, 0x19, 0x96, 0xB0, 0x83, - 0xE4, 0x31, 0xA8, 0x2E, 0x9B, 0x06, 0x1A, 0x9A, 0xD8, 0x33, 0x3F, 0x8C, 0x06, 0xCC, 0xB6, 0xFC, - 0x5C, 0x11, 0x97, 0x19, 0xD9, 0xC7, 0x5E, 0x12, 0xFF, 0xDC, 0x7A, 0xFA, 0xC1, 0x5B, 0x4F, 0x05, - 0x13, 0xE7, 0xF1, 0xFB, 0xDE, 0xB6, 0x75, 0x96, 0x43, 0xDF, 0x38, 0x73, 0xE6, 0x51, 0x94, 0xE7, - 0x1C, 0x89, 0xC1, 0x1A, 0x44, 0x45, 0xD7, 0xB9, 0xDE, 0xE1, 0x88, 0xDE, 0x26, 0x5A, 0xD6, 0x04, - 0xC1, 0xFE, 0xE9, 0xC7, 0x2A, 0xF0, 0xFF, 0x40, 0x66, 0xBD, 0x9B, 0x18, 0xF7, 0x6E, 0x77, 0x6D, - 0xFD, 0x1F, 0xD7, 0x9C, 0xD7, 0x38, 0xEA, 0x94, 0x4E, 0x7C, 0x87, 0x5E, 0x18, 0xC6, 0x31, 0x34, - 0xBF, 0xD0, 0x20, 0x04, 0x75, 0x3C, 0xF2, 0x22, 0xD3, 0xF1, 0x2F, 0xA8, 0x9F, 0x7B, 0x7D, 0x8F, - 0xEB, 0x35, 0x36, 0x88, 0x89, 0x33, 0xA5, 0xC8, 0xD0, 0xB5, 0x00, 0x26, 0x6C, 0xC9, 0xCB, 0xF4, - 0x39, 0xCC, 0x9C, 0x45, 0xE6, 0x1F, 0x46, 0x96, 0x1C, 0x72, 0xCC, 0x78, 0x0C, 0x32, 0x2F, 0xCF, - 0x0D, 0xA7, 0x04, 0x34, 0x2E, 0x4F, 0xE0, 0xBB, 0xF5, 0xB9, 0x0C, 0x6D, 0xBE, 0x1D, 0xD2, 0x7B, - 0xCA, 0x5D, 0xAC, 0xB5, 0xA7, 0xF4, 0x17, 0x1F, 0x79, 0x6B, 0xA9, 0x4F, 0xED, 0x27, 0xD8, 0x4E, - 0xDA, 0x73, 0x83, 0x2B, 0x1F, 0x7C, 0x14, 0xD2, 0x1D, 0x3E, 0xC1, 0xB6, 0x52, 0x42, 0xAD, 0x37, - 0x9C, 0x61, 0x63, 0xA9, 0x36, 0xB5, 0x75, 0x46, 0x6D, 0xEB, 0x71, 0xA9, 0xFD, 0x1A, 0xC0, 0x74, - 0x8F, 0x74, 0xB6, 0x1F, 0x97, 0xCE, 0x5B, 0xF7, 0x1B, 0x53, 0xBF, 0xEE, 0x9C, 0x86, 0x71, 0x1C, - 0x9A, 0xF2, 0x66, 0x97, 0x74, 0x7B, 0x5D, 0x93, 0x11, 0xAA, 0x6D, 0x88, 0xCA, 0x8C, 0xD1, 0x09, - 0x4E, 0x4A, 0xAC, 0x0D, 0xC6, 0x05, 0x5E, 0xB3, 0x76, 0x14, 0xC9, 0xEC, 0x70, 0xA5, 0x3F, 0xF0, - 0x61, 0x8E, 0xE2, 0x44, 0x7B, 0xF3, 0x23, 0xFA, 0x50, 0x3A, 0x69, 0xAD, 0xAE, 0x82, 0x97, 0xC9, - 0xA6, 0x9B, 0x21, 0xC6, 0x95, 0xDB, 0x62, 0xDE, 0xC7, 0x98, 0x9A, 0xA9, 0xE7, 0x46, 0x25, 0x93, - 0x5B, 0xE8, 0xBC, 0x0B, 0x28, 0xED, 0x4F, 0x60, 0xAA, 0x68, 0x2D, 0x29, 0xB4, 0x60, 0x52, 0xD1, - 0x6A, 0xF6, 0xC1, 0xE7, 0x2C, 0xA9, 0x74, 0x03, 0xCE, 0x3E, 0x4E, 0x75, 0x47, 0x07, 0x25, 0x15, - 0x0D, 0x93, 0x6A, 0x09, 0x84, 0x63, 0xDF, 0x87, 0xE7, 0x74, 0x6C, 0xBB, 0x1E, 0x5B, 0x24, 0x14, - 0xD6, 0x9D, 0x04, 0x3E, 0x46, 0x39, 0x59, 0x18, 0xB2, 0x5A, 0xAD, 0x6A, 0xB7, 0x7A, 0xD5, 0x5E, - 0xF5, 0xAA, 0x6B, 0xD5, 0xAB, 0xAE, 0x57, 0xAF, 0xBA, 0x51, 0xBD, 0xEA, 0x66, 0xF5, 0xAA, 0x2F, - 0x2B, 0x54, 0x65, 0x0E, 0xDE, 0xC9, 0xDE, 0x7E, 0x59, 0x57, 0x51, 0xF0, 0xD6, 0xE9, 0xDB, 0x8B, - 0x52, 0x2D, 0x80, 0x25, 0x62, 0x1C, 0x0E, 0x5F, 0x52, 0xF3, 0xCA, 0x06, 0x87, 0x36, 0xB8, 0x3F, - 0xA3, 0xB0, 0x02, 0x41, 0xE7, 0x2B, 0xA9, 0xAC, 0xDB, 0x13, 0x30, 0x1F, 0xAE, 0xB3, 0x04, 0x90, - 0x30, 0x16, 0x3E, 0x5C, 0x9C, 0x1C, 0xEB, 0x11, 0x68, 0x65, 0xDE, 0x5E, 0x10, 0x7D, 0xCB, 0xE8, - 0xA5, 0x81, 0x86, 0xB1, 0x5E, 0x3E, 0xD5, 0x7C, 0xA8, 0x4F, 0x93, 0x21, 0x48, 0x95, 0xB6, 0x66, - 0x60, 0x79, 0x80, 0xAB, 0x8D, 0x60, 0x7C, 0x8E, 0x11, 0xE3, 0x59, 0x66, 0x59, 0x20, 0xF9, 0xBE, - 0x3F, 0x9E, 0x80, 0xC1, 0xA4, 0x8B, 0x4B, 0xB5, 0xD1, 0x62, 0xC8, 0xF9, 0x39, 0x1D, 0x50, 0x77, - 0x62, 0x40, 0x9E, 0xAD, 0xA3, 0x52, 0x28, 0x21, 0x21, 0x54, 0x8F, 0xDF, 0x7D, 0x30, 0x60, 0x9F, - 0x06, 0x78, 0xC8, 0x72, 0x26, 0xD7, 0x32, 0x49, 0xF6, 0x8F, 0x8B, 0x2D, 0x17, 0x97, 0xE4, 0x5F, - 0xF0, 0x26, 0xCE, 0xAE, 0x40, 0xCA, 0x16, 0xAE, 0x5F, 0xBF, 0xDC, 0x62, 0x98, 0xFE, 0x2E, 0x46, - 0x17, 0x1A, 0xB1, 0x2D, 0x93, 0xD6, 0x57, 0x90, 0x3D, 0xC0, 0x4C, 0x16, 0x17, 0x58, 0x30, 0x3D, - 0x3B, 0x92, 0xC2, 0x88, 0xC2, 0x1A, 0xA2, 0x8A, 0x3D, 0xFC, 0x4F, 0x13, 0xBC, 0xD4, 0x13, 0x0B, - 0x3B, 0xDB, 0x20, 0x73, 0xBD, 0xC5, 0xC6, 0x94, 0xD0, 0x13, 0x9E, 0x86, 0x65, 0x74, 0x78, 0xAD, - 0x45, 0x1E, 0xF4, 0x5A, 0x79, 0xD5, 0x93, 0xDE, 0xA2, 0x31, 0x0D, 0x00, 0xF9, 0x8A, 0x8D, 0x49, - 0xD3, 0x67, 0x1A, 0x83, 0xD2, 0x45, 0x9D, 0x02, 0xDA, 0x6C, 0x12, 0x7E, 0x34, 0xDA, 0x7B, 0xA3, - 0x82, 0x76, 0xF3, 0x6B, 0x42, 0x73, 0xA7, 0xCD, 0xEE, 0x1A, 0x65, 0xA9, 0xC6, 0x57, 0x90, 0x1E, - 0x85, 0xDE, 0x67, 0x33, 0xBD, 0xCF, 0x8F, 0x45, 0xEF, 0x77, 0x33, 0xBD, 0xDF, 0x1F, 0x85, 0x5E, - 0x38, 0xF1, 0xFC, 0xBB, 0x33, 0x8A, 0x1B, 0x82, 0x53, 0xD3, 0x92, 0x3D, 0x71, 0x4D, 0x89, 0xB5, - 0x64, 0xDC, 0x8F, 0x99, 0x00, 0x2C, 0xCC, 0x77, 0xA1, 0x66, 0x9E, 0x5B, 0xAD, 0x26, 0x4C, 0x5C, - 0xE6, 0x32, 0xF0, 0xC5, 0xFA, 0x4A, 0xFE, 0x00, 0x68, 0xAD, 0x16, 0xF9, 0xD3, 0x9F, 0xB0, 0x8D, - 0x5F, 0xBA, 0xF1, 0x07, 0x93, 0xBF, 0x9C, 0xCB, 0xD9, 0x32, 0x13, 0x10, 0x1A, 0xB5, 0xD7, 0x57, - 0xC1, 0x9B, 0x56, 0xD3, 0x1D, 0x8F, 0x90, 0x2F, 0xB0, 0xF1, 0x22, 0x93, 0x69, 0x3E, 0x49, 0x6E, - 0x39, 0x75, 0x26, 0xD3, 0xF0, 0xA6, 0xA6, 0x5D, 0x11, 0xB8, 0xE3, 0xEB, 0x50, 0xB9, 0xF8, 0xE3, - 0x0A, 0x4D, 0x68, 0x5C, 0x8F, 0xB9, 0x47, 0xA1, 0xA3, 0xD6, 0xAE, 0xDF, 0xD5, 0xD2, 0xA5, 0xEB, - 0x31, 0x77, 0x7F, 0xB3, 0xA6, 0x56, 0xBE, 0xE9, 0x06, 0x1D, 0xD0, 0x7A, 0x1D, 0x05, 0xC4, 0x1E, - 0xB9, 0x43, 0x6F, 0x77, 0x61, 0x44, 0xAF, 0xA3, 0x05, 0xBD, 0x1F, 0x4C, 0x10, 0xCE, 0x1B, 0x9C, - 0xA1, 0x14, 0xFE, 0xB0, 0x13, 0x57, 0xB1, 0xA0, 0x2A, 0x74, 0xDC, 0xF3, 0x95, 0x81, 0x5E, 0xB3, - 0x49, 0x93, 0x44, 0xF7, 0x13, 0xBA, 0xCB, 0xE7, 0xBE, 0x2B, 0xFF, 0xFB, 0x02, 0xF8, 0x5D, 0xBB, - 0x0B, 0x26, 0x6E, 0x16, 0x08, 0x9B, 0x5E, 0x17, 0x10, 0xD9, 0xD1, 0xC1, 0x02, 0x19, 0x40, 0x85, - 0x10, 0xFE, 0xF4, 0x83, 0xF1, 0x0A, 0x83, 0x5E, 0xE1, 0xF8, 0xA4, 0xFB, 0x05, 0x6C, 0x53, 0x7A, - 0xE1, 0x4D, 0x45, 0x96, 0x56, 0x23, 0x45, 0x67, 0x2B, 0xF4, 0x32, 0xDB, 0x21, 0xD5, 0x7B, 0x04, - 0xEF, 0xC9, 0x21, 0xDF, 0x75, 0xA6, 0xD5, 0xE9, 0xD5, 0xF7, 0x93, 0x34, 0x70, 0x84, 0xE1, 0x84, - 0x85, 0x15, 0x51, 0x3F, 0x5F, 0xE2, 0x96, 0xFE, 0xE5, 0xC1, 0xC5, 0x89, 0xF6, 0x1D, 0x37, 0x19, - 0x2F, 0x71, 0x07, 0xF3, 0x12, 0xB7, 0x50, 0x15, 0x5E, 0xA4, 0xAB, 0x8D, 0x42, 0xE9, 0x5C, 0x67, - 0x27, 0xAF, 0xC6, 0x39, 0xBF, 0xCD, 0x90, 0x31, 0x83, 0x1A, 0x92, 0x63, 0xFB, 0x8A, 0x8E, 0x4C, - 0x57, 0x1A, 0xA4, 0x7A, 0x07, 0xE2, 0x4E, 0x4E, 0x0A, 0x15, 0xDF, 0xCD, 0xB9, 0xD4, 0xD7, 0xA6, - 0x28, 0x0B, 0x09, 0x2A, 0xBE, 0x9A, 0x03, 0xAB, 0xF5, 0x35, 0x93, 0xED, 0x91, 0x2F, 0x6B, 0xF2, - 0x0B, 0x48, 0x12, 0x30, 0x98, 0xAD, 0x9D, 0x22, 0xB9, 0xED, 0xB2, 0x20, 0x19, 0xE3, 0x0E, 0x81, - 0x7E, 0xD5, 0xF3, 0x0F, 0xBB, 0x32, 0x99, 0xBC, 0x5D, 0x83, 0xEC, 0x05, 0x51, 0x09, 0xC8, 0xBC, - 0x06, 0x97, 0x6F, 0x9A, 0x32, 0xB5, 0xBB, 0xC9, 0x58, 0x4A, 0xCD, 0x77, 0xD5, 0x20, 0xE5, 0x3E, - 0x50, 0xDB, 0x8E, 0xA3, 0xE4, 0x92, 0xDD, 0x90, 0x92, 0x3E, 0xF7, 0x4C, 0x22, 0x51, 0x55, 0x06, - 0x10, 0x99, 0xD5, 0xA7, 0xA0, 0x7F, 0x76, 0x77, 0xC9, 0x7A, 0x9E, 0x54, 0x9A, 0x32, 0x6A, 0xFC, - 0xBC, 0x66, 0xEC, 0x52, 0xC6, 0xEF, 0xBA, 0xF5, 0xB2, 0x77, 0x69, 0xC5, 0xDC, 0xF3, 0xBF, 0x4A, - 0x77, 0x30, 0x5E, 0x14, 0x76, 0x86, 0xE3, 0xDE, 0x2A, 0x86, 0x85, 0x85, 0x36, 0x91, 0xC0, 0xBF, - 0xE3, 0x76, 0x69, 0x1C, 0x0E, 0x25, 0xFE, 0x12, 0xCB, 0xA4, 0x77, 0x60, 0x06, 0xED, 0x88, 0x89, - 0x01, 0x30, 0x72, 0xD3, 0xA6, 0xC3, 0xC7, 0x24, 0x07, 0xFE, 0x68, 0x25, 0x1C, 0xAF, 0xAC, 0x13, - 0xFC, 0x65, 0x93, 0xFD, 0x64, 0x5C, 0x30, 0xF0, 0x85, 0x37, 0x1A, 0x28, 0x97, 0x2D, 0xC0, 0xBF, - 0x7A, 0xBD, 0xCA, 0x6A, 0x94, 0xB2, 0x21, 0xB5, 0x4E, 0x21, 0xB5, 0xBE, 0xA0, 0x1A, 0x63, 0x7E, - 0xF9, 0x5B, 0x33, 0xB1, 0xFC, 0x4C, 0x73, 0xA1, 0x84, 0x46, 0x62, 0xBE, 0x33, 0x6D, 0xE4, 0x2B, - 0x21, 0xB9, 0x8C, 0x19, 0x9C, 0x4A, 0xF2, 0x9B, 0xE4, 0xA1, 0x3D, 0x0C, 0x02, 0x3F, 0x65, 0xD4, - 0xF5, 0x46, 0xAE, 0x47, 0xF9, 0x37, 0xB0, 0xFA, 0x93, 0x52, 0xBC, 0xAB, 0x20, 0x91, 0x37, 0xFC, - 0x67, 0x0D, 0xCB, 0x3F, 0x96, 0x4D, 0x75, 0x66, 0xAB, 0x40, 0x94, 0x1E, 0x89, 0x70, 0x39, 0xD4, - 0x4D, 0xD3, 0x61, 0x8D, 0x2C, 0x04, 0x66, 0xA0, 0xDE, 0x9F, 0x81, 0x89, 0x2A, 0xA8, 0x84, 0x88, - 0xCE, 0xF1, 0xA8, 0x89, 0x29, 0x3F, 0x8C, 0xD5, 0x6E, 0x41, 0xE5, 0x10, 0xEB, 0x24, 0xA3, 0xBC, - 0xA0, 0xB2, 0xCC, 0xA6, 0x84, 0xBD, 0xB7, 0x66, 0x55, 0x00, 0x48, 0x09, 0xE8, 0xF5, 0x9B, 0x4C, - 0x3C, 0xEC, 0x56, 0xE8, 0x3B, 0x58, 0x31, 0x46, 0x9A, 0xBF, 0x55, 0x32, 0x09, 0xE9, 0xD5, 0xFE, - 0x3A, 0x05, 0xF7, 0xE7, 0xDA, 0x65, 0x6B, 0x75, 0xBD, 0x3C, 0xAF, 0x2F, 0x8B, 0x7B, 0x0B, 0xFF, - 0x29, 0x58, 0x93, 0x60, 0xC8, 0x56, 0x91, 0x75, 0x69, 0x36, 0x21, 0x96, 0x5A, 0xCF, 0x9D, 0x7F, - 0x42, 0x1B, 0x96, 0x4A, 0xF7, 0xA7, 0x3D, 0xFB, 0x51, 0xF6, 0x8C, 0x47, 0x8B, 0xA0, 0x2D, 0x2A, - 0xB2, 0x57, 0x69, 0xAD, 0xCB, 0xF7, 0xEF, 0xF7, 0x9A, 0x0F, 0xFA, 0x47, 0x70, 0x25, 0xE7, 0x32, - 0x72, 0xFE, 0x09, 0xA6, 0x79, 0x71, 0x96, 0xC5, 0x97, 0x4B, 0x46, 0x46, 0x72, 0x95, 0x5A, 0x1E, - 0x21, 0x8E, 0x08, 0x64, 0x21, 0xE3, 0xAB, 0x95, 0x5E, 0x79, 0xE3, 0x7D, 0x7E, 0x30, 0x25, 0x86, - 0x85, 0xB5, 0xF0, 0xE6, 0xE3, 0xF5, 0xF5, 0xEB, 0x55, 0xFE, 0xB5, 0x26, 0x70, 0x77, 0xE1, 0x0D, - 0x57, 0xB3, 0x6E, 0x43, 0x04, 0xBD, 0x18, 0x41, 0xAF, 0x32, 0x82, 0x55, 0x2E, 0xB5, 0x6A, 0x43, - 0x4C, 0xD7, 0x57, 0x18, 0x1E, 0x7D, 0xFB, 0x96, 0xB2, 0x68, 0x17, 0x14, 0x3B, 0x8B, 0x42, 0x64, - 0xBC, 0x10, 0x3B, 0x24, 0x77, 0x14, 0xA3, 0x55, 0x16, 0x22, 0x16, 0x49, 0x8F, 0x55, 0x78, 0xC9, - 0x3D, 0x8D, 0x3A, 0x0A, 0xFE, 0x1B, 0xA8, 0xEB, 0xF9, 0x11, 0x16, 0x90, 0x2B, 0x4A, 0x3D, 0x62, - 0x3B, 0x0E, 0x0F, 0x58, 0x49, 0xB6, 0x58, 0xD4, 0x95, 0xA6, 0x9E, 0x65, 0x86, 0x6F, 0x56, 0x48, - 0x9D, 0xAA, 0x0D, 0x90, 0x6C, 0xEA, 0x99, 0x26, 0xDB, 0x1B, 0x02, 0x3F, 0x0F, 0xE6, 0x72, 0xCA, - 0xFC, 0x1B, 0xA9, 0x5A, 0x25, 0xFF, 0x42, 0xAA, 0x3F, 0x27, 0xF7, 0xE2, 0xB9, 0x5A, 0x9A, 0xCC, - 0x06, 0x06, 0x19, 0x47, 0x2B, 0x6B, 0x55, 0xAD, 0x4C, 0x76, 0xFB, 0x83, 0x9B, 0x8F, 0x7C, 0xF3, - 0xF3, 0x46, 0x04, 0xFF, 0xE7, 0xD9, 0x97, 0xAA, 0xE6, 0x85, 0xCF, 0xAC, 0x39, 0xDB, 0x2F, 0x0B, - 0xB9, 0xFB, 0x39, 0xB5, 0xAD, 0xE9, 0xAC, 0x23, 0x2D, 0x39, 0x4F, 0x99, 0xD3, 0x48, 0x53, 0xD2, - 0x32, 0x55, 0x1A, 0x6A, 0x6A, 0xAE, 0xA6, 0x26, 0x63, 0x4D, 0xBA, 0x99, 0x21, 0xD2, 0x1B, 0xDD, - 0x67, 0x07, 0x9B, 0x9A, 0x0D, 0xA9, 0x60, 0x40, 0xA4, 0x95, 0x62, 0x64, 0xB1, 0xDB, 0x0D, 0xFE, - 0x6F, 0x8E, 0xD3, 0x9D, 0xC2, 0x88, 0xF1, 0xA1, 0x52, 0xCA, 0x1D, 0x22, 0x59, 0xA6, 0xE2, 0x91, - 0xA2, 0x62, 0xCC, 0x0E, 0x16, 0x14, 0x82, 0x39, 0xFB, 0x53, 0xBC, 0xF9, 0xF0, 0xDA, 0x9C, 0x3C, - 0xCA, 0xE4, 0xB6, 0xE7, 0x20, 0x62, 0x5D, 0x61, 0x60, 0xCF, 0x10, 0x02, 0x51, 0x90, 0x67, 0x4A, - 0x47, 0x13, 0x4B, 0xB5, 0xF4, 0x72, 0x8C, 0x81, 0x88, 0x94, 0x37, 0xE6, 0xC2, 0xF7, 0xC9, 0xD8, - 0xF6, 0xEE, 0x65, 0xD2, 0x24, 0xE4, 0x6D, 0x6C, 0xD5, 0x51, 0x1E, 0x54, 0x3F, 0xD7, 0x1B, 0x4A, - 0x49, 0xB8, 0x0C, 0x87, 0x9C, 0xD9, 0x4A, 0x75, 0x76, 0x2E, 0xBD, 0x14, 0x2C, 0xF7, 0xBC, 0x3A, - 0x5B, 0xA7, 0xF6, 0x61, 0x20, 0x8B, 0x68, 0x2C, 0x6C, 0x47, 0xB6, 0x4E, 0x9D, 0x66, 0xF8, 0x91, - 0x1D, 0x83, 0xE5, 0x1D, 0x6A, 0x66, 0xAA, 0xD4, 0x6C, 0x84, 0x08, 0x21, 0x38, 0x82, 0xAE, 0x4E, - 0x83, 0x0E, 0x4C, 0x47, 0xFB, 0xC6, 0x8A, 0x9D, 0x30, 0x18, 0xD4, 0x3F, 0x98, 0xCF, 0x24, 0x6C, - 0x32, 0x1D, 0xA1, 0x9B, 0xB2, 0x3A, 0xD5, 0x3B, 0x9B, 0x10, 0xF9, 0x12, 0x4D, 0xA7, 0x13, 0x49, - 0x26, 0xC5, 0x06, 0x18, 0x7D, 0x0C, 0xB4, 0x31, 0xA3, 0xE4, 0xA9, 0x18, 0xEB, 0x45, 0x56, 0xD0, - 0x2B, 0xDF, 0x8F, 0x33, 0x8A, 0x14, 0x9F, 0xC5, 0xE5, 0x9C, 0x79, 0x69, 0x18, 0x3A, 0x7C, 0xDA, - 0x31, 0xEC, 0x98, 0xAB, 0x57, 0xF6, 0x30, 0xAA, 0x52, 0x04, 0x47, 0x74, 0xC4, 0x94, 0x64, 0x4C, - 0x1A, 0x24, 0xC5, 0xBE, 0x27, 0x70, 0x63, 0xBC, 0x2C, 0xCD, 0x80, 0x79, 0xEE, 0x93, 0xB0, 0x42, - 0x2E, 0xA6, 0x7A, 0xCC, 0x5B, 0xF5, 0x59, 0x17, 0x79, 0x02, 0x73, 0xEE, 0x84, 0x34, 0xE1, 0xBD, - 0xF4, 0xD4, 0xAE, 0x30, 0x3D, 0x4C, 0xA3, 0xCE, 0x2C, 0x43, 0x59, 0xDE, 0xBB, 0xD5, 0x72, 0xD6, - 0x54, 0xEE, 0xF4, 0x62, 0x74, 0xB3, 0x76, 0x7F, 0xE5, 0xE6, 0x5A, 0x73, 0x6B, 0x6C, 0xA1, 0x9A, - 0xCC, 0xD8, 0xDA, 0x07, 0x39, 0x7B, 0xDA, 0x3E, 0xCF, 0x5B, 0x07, 0xBE, 0x5B, 0x9C, 0x2E, 0x6E, - 0x8C, 0xAE, 0x1C, 0x26, 0xC9, 0xC5, 0xFB, 0xC7, 0x60, 0x4C, 0xC3, 0x12, 0xFD, 0xB2, 0xBD, 0x88, - 0x7A, 0x9E, 0xFD, 0x81, 0xBA, 0xC3, 0x9B, 0xE8, 0x72, 0x3C, 0x36, 0x1B, 0x66, 0xAD, 0x96, 0xAA, - 0x23, 0x64, 0x15, 0x6F, 0x30, 0xB0, 0x64, 0x79, 0x66, 0x26, 0x99, 0x87, 0x0F, 0x32, 0xA2, 0x21, - 0x54, 0xE5, 0xF7, 0x6E, 0xAF, 0xA6, 0x51, 0x24, 0x07, 0xE3, 0x57, 0x4B, 0xA5, 0x16, 0x05, 0xF7, - 0xE6, 0x4E, 0xC6, 0x60, 0x85, 0x22, 0x5D, 0x7B, 0x00, 0xE7, 0x38, 0x1A, 0xDC, 0x90, 0x45, 0x8A, - 0x3B, 0x4A, 0x66, 0x6F, 0x49, 0x72, 0x43, 0xFA, 0xE0, 0x1C, 0x5F, 0x00, 0x12, 0xE2, 0x86, 0x21, - 0xFC, 0x64, 0xD7, 0x2A, 0x8E, 0x0E, 0xE2, 0x94, 0x76, 0x75, 0xC6, 0x72, 0x71, 0xCE, 0xB9, 0x8A, - 0xED, 0x31, 0xA8, 0x53, 0x83, 0x06, 0xB1, 0xDB, 0xCB, 0xB5, 0x5B, 0x24, 0xF5, 0xE3, 0xDE, 0x68, - 0x44, 0x02, 0x3A, 0x9C, 0x8E, 0x30, 0x49, 0x20, 0x5B, 0x09, 0xF1, 0x3E, 0x4D, 0xD6, 0x21, 0x5A, - 0x77, 0xD6, 0x68, 0x6B, 0xAE, 0xC5, 0xA9, 0xD9, 0xCE, 0xA3, 0x06, 0xFD, 0xF5, 0x60, 0xCA, 0xBF, - 0x18, 0x5F, 0x07, 0x23, 0x18, 0xC6, 0x45, 0xD3, 0x6B, 0x74, 0x2C, 0x00, 0x84, 0xC7, 0xB1, 0xC1, - 0xE8, 0xF5, 0x86, 0x54, 0xEC, 0x29, 0x68, 0x61, 0x2A, 0x0B, 0x0B, 0x3B, 0x2F, 0xD2, 0xE9, 0x07, - 0xE6, 0x01, 0x11, 0xFB, 0x76, 0x12, 0x0E, 0x0D, 0x35, 0x05, 0x03, 0x07, 0x3E, 0xAE, 0xDF, 0xA6, - 0x3C, 0xB7, 0x1E, 0x28, 0x0F, 0x5E, 0xCF, 0x81, 0x65, 0x5D, 0x80, 0xE1, 0x7D, 0xB0, 0xA4, 0x22, - 0x77, 0xB0, 0x74, 0x4B, 0x7D, 0x16, 0xE8, 0x82, 0x6B, 0xFF, 0x45, 0x6C, 0xF2, 0xF5, 0xCC, 0x7C, - 0x7C, 0x10, 0xC8, 0xF2, 0xCA, 0xCD, 0x79, 0x9B, 0x76, 0xF0, 0x3B, 0x1F, 0xFC, 0x6C, 0xE8, 0x3B, - 0x7E, 0xC7, 0x87, 0x33, 0x92, 0xF6, 0xE9, 0x30, 0x9B, 0xA2, 0xE6, 0xC3, 0xDF, 0xA0, 0x35, 0x8E, - 0x1B, 0x4E, 0xB0, 0x8F, 0x58, 0x92, 0x6D, 0x8C, 0xAE, 0x26, 0xFB, 0xD3, 0x10, 0xE6, 0x40, 0xFE, - 0x37, 0x2C, 0x45, 0x51, 0x4C, 0x0B, 0x4B, 0x52, 0x2F, 0x18, 0x30, 0xF5, 0xE9, 0xA0, 0x31, 0x2A, - 0xBC, 0x64, 0x85, 0xCE, 0x5B, 0x5F, 0x5C, 0xE5, 0x9B, 0x19, 0xD1, 0x3B, 0x74, 0xB4, 0x1A, 0x63, - 0x61, 0x6E, 0xDA, 0x5B, 0x76, 0xCB, 0x54, 0xCE, 0x0F, 0xCA, 0x63, 0x7A, 0xE6, 0x8B, 0xF3, 0x3D, - 0xF5, 0x1B, 0xA3, 0xE4, 0xDE, 0xCA, 0x69, 0x14, 0xB8, 0x93, 0x3E, 0x05, 0xC1, 0x05, 0xF3, 0xC0, - 0xB4, 0x3F, 0x72, 0x59, 0x90, 0x70, 0x43, 0x4C, 0x78, 0xC7, 0x0E, 0xAF, 0x33, 0xE1, 0xD0, 0xF2, - 0xF0, 0x02, 0xC2, 0x4C, 0x1C, 0x9D, 0xF9, 0xAE, 0x17, 0x9D, 0xD1, 0xE0, 0x1A, 0x16, 0x92, 0xD2, - 0x92, 0x79, 0x46, 0xAC, 0x87, 0xF1, 0x4D, 0xDC, 0x29, 0xB3, 0xE8, 0x73, 0xC1, 0xF5, 0x41, 0x04, - 0xEF, 0xF3, 0x3C, 0xF5, 0xFE, 0x70, 0xC8, 0x02, 0xED, 0x67, 0x43, 0x1D, 0x4E, 0x4E, 0xFD, 0xBB, - 0x19, 0x91, 0x1C, 0xFB, 0x81, 0xDD, 0x18, 0x85, 0xF0, 0x19, 0xCE, 0x6E, 0x50, 0x6D, 0x29, 0x9E, - 0x1A, 0x32, 0xF7, 0x62, 0x46, 0x86, 0xE6, 0x21, 0x1B, 0x81, 0xE5, 0xFC, 0xE8, 0xF4, 0xF0, 0xB7, - 0x19, 0x51, 0xED, 0x9D, 0x9F, 0xCD, 0x87, 0x27, 0x5C, 0x36, 0xBC, 0x4B, 0x82, 0x87, 0x1D, 0x76, - 0xC0, 0x3E, 0x33, 0xC2, 0x78, 0x01, 0xD3, 0x0C, 0x4F, 0xDE, 0x85, 0xE7, 0x5A, 0x08, 0x13, 0x8C, - 0x7C, 0x3A, 0x41, 0x2B, 0x88, 0x49, 0xEB, 0xE5, 0x1D, 0x0A, 0x5E, 0x12, 0x87, 0x1D, 0xEA, 0xA5, - 0xD1, 0x40, 0x58, 0x95, 0xB7, 0xE8, 0x6C, 0x68, 0x25, 0xDC, 0x72, 0x65, 0x4A, 0xA6, 0xCE, 0x24, - 0xF3, 0xCD, 0xB9, 0x19, 0x4C, 0x0E, 0xC5, 0xAD, 0xFD, 0x2C, 0x75, 0x58, 0xA9, 0xE3, 0xCA, 0x3A, - 0x5B, 0xB0, 0x9F, 0xD9, 0x86, 0x74, 0x53, 0xBC, 0x0F, 0xCA, 0x93, 0x0B, 0xCC, 0xBD, 0x07, 0x77, - 0x43, 0x4C, 0xBA, 0xC2, 0xB5, 0x09, 0xA3, 0x7B, 0x70, 0x2A, 0x50, 0x60, 0x23, 0xF6, 0x9E, 0x45, - 0xCB, 0xF3, 0x3D, 0xDA, 0x52, 0x1F, 0x6B, 0x60, 0xCB, 0xA0, 0x72, 0xC8, 0x2B, 0xF0, 0xEB, 0xBF, - 0x71, 0x50, 0xF0, 0xAA, 0x03, 0x8A, 0xF3, 0xF8, 0x7E, 0xFF, 0x17, 0xBC, 0x53, 0x8C, 0xBE, 0x82, - 0xB8, 0xFD, 0xCA, 0x12, 0x34, 0x4B, 0xB8, 0x45, 0xF2, 0xFA, 0xE4, 0x71, 0x0A, 0x9E, 0xD1, 0x9E, - 0x55, 0x45, 0x60, 0xE9, 0x64, 0x60, 0x75, 0xF5, 0x28, 0x75, 0xEB, 0x92, 0xBA, 0x83, 0x51, 0x28, - 0x5E, 0x8B, 0xC0, 0x04, 0xF2, 0x49, 0x0E, 0xE1, 0xBF, 0x4E, 0x69, 0x70, 0xCF, 0x9F, 0x47, 0xF0, - 0x03, 0x70, 0x0D, 0x17, 0x5B, 0x1D, 0xF9, 0x74, 0xB9, 0x4D, 0x3A, 0xCA, 0x51, 0x5A, 0xAB, 0x20, - 0x31, 0xB5, 0x44, 0x41, 0xEC, 0x73, 0xC2, 0xF7, 0xE5, 0x65, 0xD9, 0x7B, 0x91, 0x18, 0x5E, 0xDE, - 0x95, 0x01, 0xBE, 0x7C, 0xFF, 0xDA, 0x11, 0x59, 0xA6, 0xD9, 0x55, 0x03, 0xB5, 0x84, 0xFB, 0x95, - 0xAC, 0x30, 0xEE, 0xB1, 0x17, 0x99, 0x45, 0x49, 0xDB, 0xB0, 0x26, 0x59, 0x5D, 0x3D, 0xA7, 0x63, - 0xFF, 0x96, 0xB2, 0x68, 0x49, 0xDC, 0x92, 0xC4, 0xA0, 0x4A, 0xF6, 0x07, 0x2F, 0xAF, 0x2B, 0x94, - 0xF4, 0x98, 0xE0, 0x95, 0xE7, 0x47, 0x8B, 0x1D, 0x3D, 0x54, 0x73, 0x29, 0x96, 0x57, 0x20, 0xE7, - 0x06, 0x78, 0x5A, 0x61, 0xC5, 0x0B, 0x8E, 0xAC, 0xB8, 0x4C, 0x7C, 0xC8, 0xD1, 0xC8, 0x95, 0xF8, - 0x50, 0x82, 0x9B, 0x81, 0x08, 0xA6, 0x99, 0x5E, 0x68, 0x2F, 0xC0, 0x4F, 0x09, 0x15, 0xF0, 0x51, - 0x8F, 0x7E, 0x12, 0xAD, 0x5C, 0x8B, 0x87, 0x24, 0x08, 0xDA, 0xC4, 0x47, 0x5C, 0x58, 0x9D, 0x97, - 0xC2, 0x3D, 0xFB, 0x32, 0x96, 0x0C, 0x07, 0x1D, 0x2C, 0x14, 0xD0, 0x8C, 0x94, 0x33, 0xC5, 0xF9, - 0x2D, 0xD8, 0x9F, 0x37, 0xF3, 0xAE, 0x2D, 0x71, 0x3C, 0xF0, 0x24, 0x87, 0x7C, 0x95, 0x94, 0xF2, - 0x94, 0x79, 0x9A, 0x06, 0x0D, 0xC8, 0xA2, 0x52, 0xFE, 0x22, 0x0E, 0xF6, 0x95, 0x1E, 0xC5, 0x00, - 0x61, 0xA4, 0xCF, 0x66, 0x2C, 0xC6, 0x85, 0x6D, 0xD2, 0xB3, 0x2C, 0x6B, 0x29, 0x6B, 0xED, 0x58, - 0x64, 0x07, 0x58, 0xB9, 0x36, 0x61, 0x0B, 0x3B, 0x3C, 0x9A, 0x52, 0xAC, 0x1F, 0xB6, 0x91, 0x47, - 0x7F, 0x68, 0xCB, 0x25, 0x0C, 0xAF, 0x67, 0x05, 0xAF, 0x08, 0x8A, 0x20, 0x81, 0x46, 0x12, 0x09, - 0x85, 0xC1, 0x88, 0xDA, 0x41, 0x4C, 0xA2, 0x1A, 0xDE, 0x85, 0x2C, 0x8F, 0xFD, 0xE9, 0x60, 0x00, - 0xAB, 0x3B, 0xC6, 0xA5, 0x94, 0xA9, 0x3F, 0xC1, 0x23, 0xCA, 0x4D, 0x1C, 0x2E, 0xF0, 0x64, 0xFD, - 0x59, 0xA6, 0x52, 0x9C, 0x55, 0xD1, 0x19, 0x18, 0x83, 0x55, 0x64, 0xCC, 0x94, 0x90, 0x5F, 0xBC, - 0x9C, 0x4B, 0xDE, 0x2C, 0xBA, 0x16, 0x2B, 0x66, 0xD3, 0x4A, 0x30, 0xBB, 0x12, 0x8F, 0x77, 0x1C, - 0xF0, 0x60, 0x13, 0xE7, 0xDF, 0x4E, 0xC0, 0x8C, 0xDF, 0xA2, 0x08, 0xC3, 0x49, 0x38, 0xDB, 0x29, - 0x86, 0xC2, 0xDB, 0xB5, 0x4A, 0xE4, 0x8E, 0xF1, 0x8C, 0x80, 0x2F, 0xE8, 0xFF, 0xAE, 0xAC, 0xBE, - 0xB5, 0xFD, 0x82, 0xDA, 0x1C, 0x66, 0xC8, 0x95, 0xF1, 0x67, 0x68, 0x52, 0x31, 0x87, 0x86, 0x1B, - 0x31, 0xB9, 0x3D, 0x2D, 0xFA, 0x28, 0xD5, 0x71, 0x49, 0x7B, 0xE4, 0xFE, 0x6B, 0x09, 0x45, 0x16, - 0x4F, 0x3B, 0x24, 0x97, 0xDF, 0x74, 0xA5, 0x91, 0xFA, 0x5B, 0x73, 0x11, 0x0C, 0x9A, 0xC2, 0x9E, - 0x41, 0x42, 0xBC, 0xEC, 0xE6, 0x0D, 0xDF, 0xD6, 0x94, 0xF0, 0xA1, 0x8D, 0x97, 0xE3, 0x20, 0x3E, - 0xBD, 0xFD, 0x4D, 0x52, 0x46, 0x56, 0x2C, 0xE6, 0x04, 0x56, 0xCC, 0xE8, 0x5A, 0x30, 0x8C, 0x37, - 0x36, 0x80, 0xDF, 0x13, 0x70, 0xF2, 0x30, 0xF5, 0xC8, 0x15, 0x8D, 0xEE, 0xF0, 0xEC, 0xD8, 0x62, - 0x7B, 0x3F, 0x50, 0xD6, 0x6A, 0xA3, 0x1D, 0x1B, 0x8D, 0xEC, 0x49, 0x48, 0x31, 0x8B, 0x23, 0x4F, - 0xC3, 0xC2, 0x76, 0x3B, 0x54, 0xF5, 0x35, 0xD1, 0xC7, 0x75, 0xED, 0x63, 0xF2, 0x80, 0xF8, 0xCB, - 0xF9, 0xC0, 0x2C, 0x70, 0x55, 0xB8, 0xD8, 0xCC, 0x67, 0x62, 0x73, 0x16, 0x39, 0x20, 0xFD, 0xAA, - 0x92, 0x68, 0xC6, 0x83, 0x51, 0x0E, 0xA2, 0x62, 0x9F, 0xCF, 0x23, 0x60, 0xB8, 0x07, 0xFC, 0x6A, - 0xFC, 0x00, 0xD6, 0x21, 0xB2, 0x49, 0x16, 0x05, 0xA6, 0x21, 0x88, 0x2A, 0x1D, 0x0F, 0x24, 0xA8, - 0xC9, 0x21, 0x4D, 0x43, 0x15, 0xA6, 0x9F, 0x15, 0x56, 0xBA, 0x82, 0x1E, 0x61, 0x4D, 0x90, 0xE9, - 0xA4, 0x08, 0x80, 0x0F, 0xED, 0x2C, 0x01, 0xB9, 0xAD, 0xE0, 0x0C, 0xBA, 0xE8, 0xD2, 0xBF, 0x73, - 0xE9, 0xC8, 0x09, 0x17, 0xD3, 0x97, 0x57, 0xF6, 0x85, 0x10, 0x84, 0x17, 0x3D, 0x48, 0xF3, 0xC4, - 0xE8, 0xE2, 0x49, 0x04, 0x2B, 0xF6, 0xF3, 0x44, 0xBA, 0x21, 0x90, 0x78, 0xBC, 0x29, 0x88, 0xD4, - 0x63, 0xF7, 0x2D, 0x17, 0x3A, 0xED, 0x16, 0x04, 0xC5, 0x1B, 0xF9, 0x75, 0xE1, 0x50, 0xA5, 0x04, - 0x28, 0xFC, 0x5A, 0x0D, 0xFA, 0x6D, 0x9A, 0xF9, 0x0C, 0x40, 0x59, 0x1E, 0xB4, 0xFA, 0x54, 0x99, - 0x12, 0x09, 0xF0, 0xCA, 0x94, 0xCF, 0xCE, 0x24, 0x41, 0xC9, 0xBB, 0x32, 0xD5, 0xA0, 0xA5, 0x04, - 0x69, 0x0C, 0x01, 0xFE, 0x59, 0x09, 0xF2, 0x57, 0xF7, 0x9D, 0x9B, 0x02, 0xDE, 0xB9, 0xD7, 0x6E, - 0x35, 0xB8, 0x8B, 0xFD, 0xB3, 0x4F, 0x07, 0x12, 0xCF, 0xB0, 0xD2, 0xFC, 0xE4, 0x4C, 0xAA, 0xC1, - 0xB2, 0xDB, 0xCF, 0x29, 0x28, 0xF3, 0xE7, 0xAB, 0x41, 0x66, 0x97, 0x9A, 0xF7, 0x29, 0x1E, 0xC9, - 0xD7, 0xAB, 0x86, 0xAD, 0x7F, 0x1F, 0x46, 0x74, 0x9C, 0x22, 0x08, 0xF9, 0xDF, 0x95, 0x60, 0x0F, - 0xD5, 0xEC, 0x76, 0x00, 0x9D, 0xE4, 0xBB, 0xAB, 0x04, 0x7F, 0x7A, 0x21, 0x09, 0x0F, 0x53, 0xE0, - 0x55, 0x82, 0x7A, 0x27, 0x3D, 0x8F, 0x03, 0x70, 0xF2, 0x12, 0x29, 0x86, 0xE7, 0xCE, 0x82, 0x3E, - 0xBB, 0xF1, 0x51, 0x2C, 0x86, 0x24, 0xE1, 0x94, 0x33, 0x06, 0x94, 0xE7, 0xEA, 0x48, 0x6F, 0xBE, - 0x63, 0x6C, 0x41, 0x1B, 0x5F, 0x2D, 0x5B, 0xDF, 0x96, 0x8C, 0x29, 0xCB, 0x45, 0xBB, 0xBE, 0x0D, - 0x90, 0x76, 0x60, 0x0F, 0xF0, 0xFC, 0x4C, 0x36, 0xA7, 0xEA, 0xA8, 0x5F, 0x4A, 0x48, 0xB3, 0xC4, - 0xC5, 0x39, 0x74, 0xB9, 0xE1, 0x36, 0xEC, 0x9C, 0xB7, 0xF1, 0x7D, 0x29, 0xCB, 0xEA, 0xF6, 0xDA, - 0xEC, 0x81, 0xAC, 0xAC, 0x3D, 0xE7, 0xA5, 0xCC, 0xAA, 0x77, 0x2D, 0x06, 0x60, 0x32, 0x20, 0xB1, - 0x54, 0x91, 0xE4, 0xBE, 0x9C, 0xB9, 0x8D, 0xED, 0x52, 0xE4, 0xB2, 0xC3, 0xD3, 0xAD, 0xB5, 0xD8, - 0x74, 0xB2, 0x6D, 0xE5, 0x4E, 0x27, 0xDB, 0x56, 0x05, 0xB2, 0x19, 0xD4, 0xFB, 0xA7, 0x1F, 0x67, - 0xC2, 0x9C, 0xF8, 0xB0, 0x79, 0xDB, 0xCB, 0xC9, 0xD9, 0x58, 0xD6, 0xBB, 0x35, 0xF5, 0xB9, 0x97, - 0x02, 0xEF, 0xDB, 0x20, 0xA1, 0xE0, 0x83, 0x1F, 0x46, 0xA2, 0xF7, 0x37, 0x32, 0xBD, 0xBF, 0x91, - 0xD3, 0xFB, 0xD9, 0xD6, 0xE7, 0x48, 0x20, 0x43, 0x0E, 0x2D, 0x18, 0x27, 0xB7, 0x8D, 0xFF, 0x74, - 0x8A, 0xEC, 0x63, 0x3D, 0x4A, 0x86, 0x96, 0xB1, 0xD7, 0xB1, 0xD8, 0x9E, 0x37, 0x27, 0xB5, 0x66, - 0xE9, 0x74, 0xD6, 0xAC, 0xC6, 0x2D, 0xE3, 0xED, 0xF8, 0x14, 0xD2, 0x20, 0x5F, 0x9A, 0xD9, 0x02, - 0xAC, 0xCF, 0x8C, 0x60, 0xF4, 0xAD, 0x37, 0xF4, 0x3B, 0x03, 0x7F, 0x8C, 0x7F, 0xE1, 0x57, 0x32, - 0x46, 0xC6, 0x30, 0x6D, 0x2E, 0x18, 0x16, 0x17, 0x3C, 0xD6, 0xB1, 0xED, 0x8E, 0x30, 0x16, 0x31, - 0x00, 0x9F, 0xA8, 0x98, 0xB5, 0xF8, 0xBC, 0x8E, 0xF0, 0xF3, 0x32, 0x8C, 0xAC, 0xBD, 0x03, 0x5B, - 0x29, 0x8E, 0xFD, 0x30, 0x3A, 0x52, 0xE4, 0xDA, 0x0B, 0x09, 0xD8, 0x2C, 0xDA, 0x21, 0x9C, 0x9E, - 0x7D, 0x4F, 0xEE, 0x6C, 0x30, 0x19, 0x20, 0x07, 0xC7, 0x0D, 0x59, 0x38, 0xE8, 0xE9, 0xC5, 0xF9, - 0xD1, 0x19, 0x6E, 0xFB, 0xB0, 0x88, 0xC8, 0x91, 0xCF, 0xB9, 0x21, 0xF4, 0x3B, 0x78, 0x14, 0xB8, - 0x91, 0x16, 0xA7, 0x93, 0xEB, 0xC4, 0x14, 0xA5, 0x65, 0x0A, 0xFC, 0xC5, 0xF7, 0x81, 0x70, 0xA5, - 0xC9, 0x65, 0x54, 0x20, 0x19, 0x49, 0x00, 0xA2, 0x15, 0xD5, 0xE0, 0x85, 0xE2, 0xF4, 0xBA, 0x56, - 0xB7, 0x22, 0x9C, 0xA2, 0x05, 0xAD, 0xAB, 0x91, 0x13, 0x5C, 0xF6, 0x27, 0x76, 0xF0, 0xED, 0xDD, - 0xD4, 0xEB, 0xB6, 0x6A, 0xE3, 0x38, 0xFB, 0xB5, 0x1E, 0xBF, 0x71, 0x87, 0x47, 0x34, 0x8C, 0xFE, - 0x0F, 0xFE, 0xA8, 0xDF, 0x64, 0x44, 0x01, 0x64, 0x01, 0x89, 0x06, 0x37, 0x54, 0x47, 0xD6, 0x85, - 0xC8, 0x64, 0xF8, 0xFE, 0xFD, 0x5E, 0x4E, 0xA0, 0x09, 0xC0, 0x69, 0xDB, 0x7D, 0xE8, 0xDF, 0xC1, - 0x82, 0x23, 0x49, 0xDF, 0x9E, 0x6E, 0x74, 0xAE, 0xAE, 0x8E, 0xD9, 0xA2, 0x0F, 0x6B, 0xB8, 0x4E, - 0x48, 0xC2, 0xC8, 0x0E, 0x98, 0x0E, 0x30, 0xA5, 0xD2, 0xAE, 0x60, 0xBE, 0xF8, 0x41, 0xA9, 0x03, - 0x71, 0x69, 0x97, 0xB2, 0x52, 0xBC, 0xF1, 0xB8, 0xC0, 0xF3, 0xB2, 0xB8, 0xCE, 0xBF, 0xED, 0x6A, - 0xDC, 0x7F, 0x95, 0x17, 0xBD, 0xA6, 0xDD, 0x2C, 0x89, 0x44, 0xDE, 0x16, 0x96, 0x39, 0x12, 0x5D, - 0x02, 0xE4, 0x3B, 0x8D, 0x3B, 0xD9, 0x78, 0x4B, 0x7D, 0xED, 0x69, 0x8E, 0x23, 0x96, 0x93, 0x6C, - 0x55, 0xEF, 0x18, 0x16, 0x35, 0x3F, 0x5F, 0x69, 0x31, 0x94, 0xCF, 0x4A, 0x62, 0x6C, 0x8D, 0x58, - 0x24, 0x35, 0x93, 0xCE, 0xE3, 0xE2, 0xD2, 0xA0, 0xF5, 0xF5, 0xB2, 0xD5, 0x4B, 0xEC, 0x57, 0x96, - 0xA6, 0x7E, 0xD5, 0xB3, 0x54, 0x94, 0xE3, 0x46, 0x72, 0x1C, 0xD7, 0x12, 0x22, 0x5B, 0xEA, 0x97, - 0x29, 0xDE, 0x8C, 0xAD, 0x4D, 0x6F, 0x7D, 0xFC, 0x8F, 0x6A, 0x72, 0xB5, 0xF1, 0xF2, 0x54, 0x2D, - 0xAE, 0x3B, 0x56, 0xD4, 0x67, 0xB5, 0x78, 0x6E, 0xDC, 0xF8, 0xBE, 0x6B, 0xF9, 0x88, 0x29, 0x78, - 0x94, 0x6B, 0x06, 0xC9, 0x66, 0xAE, 0x29, 0xFF, 0x28, 0xE9, 0x2A, 0x3E, 0xAE, 0x04, 0x8B, 0xEB, - 0x18, 0x70, 0x37, 0xF1, 0x01, 0x0F, 0xF3, 0x32, 0xA6, 0xCB, 0x37, 0xA6, 0xB0, 0xBC, 0x70, 0x7F, - 0x6C, 0xAE, 0x0A, 0xA9, 0x5F, 0xD6, 0xFE, 0xA7, 0x94, 0x5A, 0xBC, 0xA3, 0x97, 0xA3, 0xD4, 0x2C, - 0x07, 0xB3, 0xB4, 0x2C, 0x8D, 0x57, 0x54, 0x86, 0x80, 0xA9, 0x8A, 0x0B, 0x2A, 0xB1, 0xC0, 0xF1, - 0xAF, 0x42, 0x14, 0x2E, 0x4B, 0x32, 0x4E, 0x07, 0xBE, 0xE7, 0xA0, 0xCB, 0xBE, 0x69, 0xB1, 0xE6, - 0x18, 0x1A, 0xB3, 0x69, 0x89, 0x17, 0x5E, 0xE4, 0x86, 0xBC, 0x35, 0xE6, 0xE1, 0x2F, 0x26, 0x76, - 0xE6, 0x87, 0x2E, 0xFE, 0x7F, 0x6F, 0x30, 0x98, 0xC2, 0x32, 0xE6, 0x9E, 0x2F, 0x74, 0x36, 0x50, - 0x90, 0x19, 0xA2, 0xDD, 0x0E, 0xA3, 0xBA, 0xD1, 0x29, 0xA0, 0x9A, 0x92, 0x55, 0x7C, 0x52, 0x16, - 0x6D, 0x75, 0xC8, 0x52, 0x82, 0xB5, 0xC9, 0x4A, 0xB7, 0xB7, 0x65, 0xF5, 0xAC, 0xCD, 0xCE, 0xC6, - 0xE6, 0x96, 0xCC, 0xA8, 0x19, 0xE2, 0x33, 0x42, 0xAC, 0xBF, 0xEC, 0x6E, 0x6E, 0x59, 0xEB, 0x9D, - 0x75, 0x6B, 0xAD, 0x1C, 0xE2, 0x77, 0x80, 0x58, 0xB7, 0xB6, 0x36, 0x37, 0x37, 0x37, 0x3A, 0xEB, - 0x5B, 0xEB, 0xC5, 0x00, 0xC7, 0x76, 0xC4, 0x92, 0x93, 0x23, 0x48, 0xC7, 0xDA, 0xB6, 0x7A, 0xDB, - 0xEB, 0x2F, 0xB7, 0x4B, 0x40, 0x7C, 0x6F, 0x28, 0x60, 0x56, 0xBA, 0x16, 0xC8, 0x6A, 0x6B, 0xC3, - 0xDA, 0x78, 0xB9, 0xD9, 0x2D, 0x86, 0xDA, 0x1B, 0x45, 0x6E, 0x34, 0x75, 0xD8, 0x16, 0xC9, 0xC6, - 0x26, 0xD0, 0xDA, 0xDA, 0x56, 0x96, 0x5F, 0xDA, 0x81, 0x8D, 0x8A, 0x21, 0x47, 0x3D, 0x72, 0x29, - 0x16, 0xF7, 0x30, 0xF4, 0xA0, 0xDC, 0x55, 0xB1, 0x12, 0x17, 0x87, 0xD9, 0x15, 0xE8, 0x73, 0x43, - 0xD1, 0x36, 0x17, 0x6F, 0x2D, 0x11, 0x97, 0x58, 0x10, 0x4D, 0x37, 0x5F, 0x5A, 0xEC, 0x5F, 0x9B, - 0x24, 0xBF, 0x24, 0xE3, 0x20, 0x2E, 0xC3, 0x41, 0x20, 0x7E, 0x2D, 0x1F, 0x7E, 0x65, 0x44, 0x3F, - 0xFF, 0x08, 0xA2, 0xBF, 0x3F, 0x06, 0xD1, 0x87, 0xA2, 0x58, 0xE5, 0xFA, 0xE6, 0xA0, 0x99, 0x49, - 0xA8, 0x65, 0x16, 0xB2, 0xF2, 0x4A, 0x83, 0x96, 0xC0, 0xD8, 0xFF, 0x42, 0x03, 0x4C, 0x81, 0x0F, - 0xDF, 0x56, 0xD9, 0x1D, 0xA1, 0x34, 0x0B, 0x44, 0x25, 0x41, 0x4B, 0xDA, 0xB8, 0xD2, 0xED, 0x5A, - 0x6B, 0xEB, 0x6D, 0xB2, 0xB5, 0xA5, 0x6C, 0x8D, 0xF2, 0xCF, 0x28, 0x64, 0x2C, 0xA8, 0x60, 0x54, - 0x73, 0xC8, 0xE9, 0x77, 0x09, 0x90, 0x20, 0x3E, 0x7F, 0xB0, 0xA1, 0xD0, 0xDA, 0x60, 0x0F, 0x0A, - 0x6C, 0x34, 0xD6, 0x1E, 0x73, 0xF4, 0x21, 0xD0, 0xEA, 0xF1, 0x19, 0xB7, 0xA7, 0x4D, 0xBC, 0xFC, - 0x3B, 0x7F, 0xF5, 0xC0, 0xEA, 0x54, 0x56, 0xA0, 0x87, 0xDC, 0xBD, 0xCA, 0x24, 0xA8, 0xB6, 0xC9, - 0x5E, 0x25, 0x07, 0x4E, 0xF7, 0x90, 0x2E, 0xAD, 0xCA, 0x7B, 0xD5, 0x32, 0x3C, 0x63, 0xDA, 0xAA, - 0xB2, 0x5B, 0x29, 0x13, 0xC4, 0x4D, 0xA7, 0x98, 0x60, 0xF1, 0x7E, 0x65, 0x75, 0x5A, 0xB9, 0xAD, - 0xC3, 0xED, 0x1E, 0x46, 0xCC, 0xD2, 0x5A, 0x67, 0xCD, 0xD8, 0xBA, 0x42, 0x8A, 0x67, 0xBF, 0x3E, - 0x15, 0xCD, 0x74, 0x2F, 0xED, 0x51, 0xFA, 0xB0, 0x90, 0xE2, 0xD3, 0xB5, 0x52, 0xD2, 0xD4, 0x6E, - 0x73, 0x8A, 0xDD, 0x46, 0x9A, 0x2A, 0x08, 0xEA, 0x9A, 0x6A, 0x15, 0x6B, 0x6A, 0xB7, 0x99, 0xA6, - 0x3E, 0x46, 0xEB, 0xCA, 0x34, 0xF5, 0x89, 0x68, 0x4A, 0x9A, 0xFA, 0xE4, 0x14, 0x9F, 0xAE, 0x95, - 0x92, 0xA6, 0xF6, 0x9A, 0x53, 0xEC, 0x35, 0xD2, 0xD4, 0x5E, 0x23, 0x4D, 0xED, 0x35, 0xD3, 0xD4, - 0xC7, 0x68, 0x5D, 0x99, 0xA6, 0x3E, 0x11, 0x4D, 0x49, 0x53, 0x9F, 0x9C, 0xE2, 0xD3, 0xB5, 0x52, - 0xD2, 0xD4, 0xB5, 0xE6, 0x14, 0xD7, 0x1A, 0x69, 0xEA, 0x5A, 0x23, 0x4D, 0x5D, 0x6B, 0xA6, 0xA9, - 0x8F, 0xD1, 0xBA, 0x32, 0x4D, 0x7D, 0x22, 0x9A, 0x92, 0xA6, 0x3E, 0x39, 0xC5, 0x39, 0xB5, 0xF2, - 0xB9, 0x1F, 0xB7, 0x1A, 0x5D, 0xE5, 0x5A, 0x07, 0xAE, 0x46, 0xDF, 0xB7, 0xD2, 0x91, 0xAB, 0xD1, - 0x91, 0xAD, 0x7B, 0xF8, 0x99, 0xE3, 0x9B, 0xB6, 0xAA, 0x42, 0x6A, 0x1E, 0x26, 0x3F, 0xF3, 0x75, - 0xEE, 0xBC, 0xE8, 0xCE, 0xEB, 0xD5, 0xC7, 0x11, 0x53, 0xFF, 0xF5, 0x7C, 0xE3, 0xEE, 0xDC, 0x5F, - 0xFF, 0x50, 0x8F, 0xFF, 0xC4, 0x03, 0x6C, 0x35, 0x10, 0x3B, 0xF3, 0x00, 0xEA, 0xCB, 0xBC, 0x01, - 0x39, 0xC9, 0xB1, 0x6A, 0x22, 0xE6, 0x86, 0x70, 0x75, 0x29, 0x6A, 0xAE, 0x4A, 0x13, 0x91, 0xF6, - 0x9A, 0x89, 0xB4, 0xD7, 0x58, 0xA4, 0xBD, 0x86, 0x22, 0xED, 0x35, 0x16, 0x69, 0xAF, 0xA1, 0x48, - 0xD7, 0x1A, 0x8A, 0x74, 0xAD, 0x99, 0x48, 0xD7, 0x1A, 0x8B, 0x74, 0xAD, 0xA1, 0x48, 0xD7, 0x1A, - 0x8B, 0x54, 0x87, 0x4C, 0x0E, 0x14, 0xE4, 0x1B, 0xB5, 0xA6, 0x83, 0x85, 0xB2, 0x7B, 0xB7, 0x05, - 0x5B, 0x21, 0x71, 0x06, 0x00, 0x76, 0xC1, 0x5E, 0x42, 0x70, 0xC0, 0x5E, 0x34, 0x12, 0x81, 0x77, - 0x17, 0xFE, 0x37, 0xEA, 0xC5, 0xC9, 0x27, 0x76, 0x5E, 0x68, 0x39, 0x4F, 0xA6, 0x34, 0x49, 0xA1, - 0xAE, 0xBF, 0x2A, 0x61, 0x0C, 0x04, 0x2C, 0xA6, 0xD2, 0x26, 0x6B, 0x9B, 0xFC, 0xBF, 0x64, 0xEA, - 0x5C, 0xDB, 0xCC, 0x8B, 0x0B, 0x3C, 0x33, 0x85, 0x28, 0x15, 0xEE, 0x91, 0x97, 0x52, 0x6F, 0xB5, - 0xF4, 0xFB, 0xB4, 0xD3, 0xC8, 0xFF, 0x0B, 0xBD, 0x3F, 0xA7, 0x1E, 0xBD, 0xB3, 0x47, 0x39, 0x31, - 0x2F, 0x52, 0x57, 0x05, 0x05, 0x5D, 0xA4, 0x5F, 0x62, 0xAE, 0x77, 0xFC, 0x43, 0x65, 0x68, 0xBC, - 0xF2, 0xF3, 0x96, 0x9F, 0xB9, 0x70, 0x6C, 0x6C, 0x93, 0x63, 0xD3, 0xCA, 0x6C, 0xD3, 0x76, 0xF9, - 0x21, 0x50, 0x1B, 0xBF, 0x6A, 0x5B, 0xB4, 0x67, 0xE6, 0x27, 0x90, 0xCB, 0x48, 0x1F, 0xB3, 0xDE, - 0x9E, 0x13, 0xC1, 0x44, 0x72, 0x18, 0x34, 0x5C, 0x16, 0x44, 0x8A, 0xA1, 0xC4, 0xA7, 0xD0, 0x68, - 0x3F, 0xF8, 0x76, 0x69, 0xF5, 0xFB, 0x47, 0x07, 0x95, 0x1D, 0x2D, 0x43, 0x68, 0xB2, 0x21, 0x94, - 0xD2, 0x48, 0xE7, 0xCC, 0x0E, 0x43, 0xF8, 0xCD, 0x79, 0x02, 0x5A, 0xDD, 0x27, 0x6A, 0x53, 0xF7, - 0x09, 0xDB, 0xD4, 0x7B, 0xA2, 0x36, 0xF5, 0x9E, 0xB0, 0x4D, 0x6B, 0x4F, 0xD4, 0xA6, 0xB5, 0x39, - 0xB5, 0x49, 0x0C, 0xB1, 0x8B, 0xFD, 0xB3, 0xD5, 0x4F, 0x07, 0x67, 0xF9, 0xF6, 0xE9, 0x62, 0x50, - 0x3B, 0xD6, 0x57, 0x18, 0x88, 0xE4, 0xBA, 0x78, 0x1A, 0x73, 0xBB, 0xB9, 0xB1, 0xB1, 0x96, 0x89, - 0xF2, 0x65, 0x1F, 0x65, 0x46, 0x95, 0x98, 0xFF, 0x92, 0xF5, 0x56, 0x42, 0x44, 0x8A, 0x23, 0xAE, - 0x1E, 0x45, 0x6E, 0xA2, 0xF4, 0x60, 0x16, 0x42, 0xDD, 0x43, 0x84, 0x54, 0x08, 0x1C, 0x72, 0x1E, - 0x42, 0x30, 0xB1, 0xF6, 0xC9, 0x69, 0xCA, 0xDA, 0xD4, 0x99, 0x3B, 0x6B, 0xAB, 0xAB, 0x1F, 0x3D, - 0x12, 0x5F, 0x59, 0x68, 0x13, 0xA8, 0x48, 0x78, 0xEF, 0xB0, 0x08, 0x0A, 0x4E, 0x8D, 0x3D, 0x9A, - 0x8D, 0xCB, 0x4E, 0xC0, 0xCF, 0x9B, 0xE0, 0xE0, 0xBB, 0xDC, 0xB8, 0xFE, 0x0C, 0x31, 0x92, 0x23, - 0x82, 0x59, 0x2C, 0x8E, 0x9A, 0x98, 0x02, 0x12, 0xDF, 0x23, 0xA8, 0xB9, 0x6D, 0xAC, 0x71, 0x2F, - 0x5E, 0xDC, 0xEE, 0x74, 0xE2, 0x95, 0x29, 0x0F, 0xB6, 0x17, 0x99, 0xBF, 0x4E, 0xA6, 0x11, 0xFD, - 0x9E, 0x55, 0x5C, 0xBC, 0x34, 0xA1, 0x75, 0x23, 0x7C, 0x6A, 0xCC, 0x5C, 0x91, 0x28, 0xE2, 0x1B, - 0xEB, 0xEC, 0x16, 0x7B, 0xEE, 0x98, 0x12, 0xC9, 0x3C, 0xEA, 0x75, 0xD7, 0x08, 0x80, 0x92, 0x03, - 0x76, 0xF0, 0xE2, 0xDE, 0x05, 0xF4, 0xAF, 0x53, 0xEA, 0xB1, 0x83, 0xF9, 0x6D, 0x6B, 0x0D, 0x7E, - 0xF4, 0x5E, 0x4A, 0x5D, 0x07, 0x9F, 0xD8, 0x16, 0x51, 0xEF, 0xA5, 0xCC, 0xAF, 0x7C, 0x25, 0xA6, - 0x78, 0x7A, 0x47, 0x72, 0x20, 0x13, 0xD7, 0x1E, 0xB1, 0xF8, 0x1D, 0x9B, 0x79, 0x8E, 0xE2, 0x52, - 0xF1, 0x25, 0x0E, 0xA2, 0x6E, 0x26, 0xC8, 0xA4, 0x6B, 0x0A, 0x2E, 0x31, 0x50, 0x4C, 0x43, 0xBD, - 0xA4, 0xD4, 0xA2, 0xC5, 0x77, 0x36, 0x32, 0xF7, 0xAB, 0xC3, 0x63, 0xF7, 0x9A, 0x8A, 0xDE, 0xC0, - 0x23, 0xCB, 0x9E, 0xCC, 0x08, 0x3F, 0xB1, 0xEC, 0x29, 0x7C, 0xE4, 0x5F, 0xE9, 0x59, 0x92, 0x72, - 0x2E, 0x84, 0xD0, 0x11, 0x2C, 0xE5, 0x52, 0x31, 0x3B, 0x73, 0x3C, 0x38, 0x7D, 0xCA, 0x03, 0x53, - 0xD1, 0x4C, 0x7E, 0x1F, 0xA9, 0x48, 0x3D, 0xE3, 0x34, 0x2A, 0xF5, 0x34, 0x74, 0x6C, 0x7F, 0x07, - 0xD0, 0x0B, 0x37, 0xBE, 0xCE, 0xD3, 0xB5, 0x36, 0xA0, 0x13, 0x32, 0x7E, 0x60, 0xB7, 0x0D, 0xDF, - 0xDB, 0x3D, 0x55, 0x4D, 0x94, 0x3B, 0x52, 0xC5, 0x9A, 0xC9, 0xC9, 0xC8, 0x1E, 0xE7, 0xAC, 0x84, - 0x2A, 0x2C, 0x12, 0x94, 0xB6, 0x6D, 0x5A, 0xE4, 0xCF, 0xA4, 0x97, 0x1F, 0x20, 0xA4, 0x71, 0xA8, - 0x56, 0x37, 0x9E, 0x53, 0x2B, 0xC9, 0x6B, 0xEA, 0x49, 0x3D, 0x05, 0x8D, 0x03, 0xED, 0x12, 0x37, - 0x3C, 0xEB, 0x81, 0xCF, 0x43, 0x14, 0x66, 0x82, 0x56, 0x61, 0xF3, 0x4C, 0x29, 0x75, 0xEA, 0x35, - 0xD3, 0x96, 0x50, 0x30, 0x7B, 0x1F, 0x67, 0x8D, 0x4C, 0x0F, 0xC7, 0xCD, 0xA7, 0xE3, 0xDB, 0x73, - 0x68, 0x72, 0x01, 0xF1, 0xD2, 0x76, 0x67, 0x52, 0x97, 0x56, 0x6A, 0xAE, 0x9A, 0x29, 0x95, 0xBB, - 0x7A, 0xBD, 0xED, 0xF5, 0xED, 0xCD, 0x97, 0x19, 0x7F, 0xAF, 0x0D, 0xDF, 0xDB, 0x50, 0x30, 0x87, - 0x76, 0x66, 0xA8, 0xB2, 0x78, 0x16, 0x7C, 0xDD, 0x4A, 0xEC, 0x1C, 0x9B, 0x9A, 0x5A, 0x3F, 0x2B, - 0x67, 0x25, 0x09, 0x94, 0x24, 0x0B, 0xE5, 0xB7, 0xAF, 0xAD, 0xF5, 0x2D, 0x45, 0xCD, 0xC5, 0x0C, - 0xB4, 0xDE, 0xDE, 0x9A, 0x8B, 0xAA, 0x97, 0xF3, 0x50, 0x24, 0xA0, 0xD5, 0xD5, 0xD8, 0x15, 0x4A, - 0xE4, 0x95, 0x7B, 0x4B, 0xC5, 0x2C, 0x8A, 0xA3, 0xB3, 0x3D, 0x7E, 0x0F, 0x6B, 0x31, 0xB9, 0xF6, - 0x79, 0x74, 0xD6, 0x92, 0xDA, 0xEB, 0x79, 0x5E, 0x47, 0xFA, 0x4F, 0x6E, 0xB2, 0x76, 0x73, 0x34, - 0xC7, 0xA6, 0x1A, 0x28, 0x1C, 0x9C, 0xF6, 0x1F, 0x9B, 0xC4, 0x7B, 0xB0, 0x00, 0x77, 0xF6, 0xFD, - 0x63, 0x93, 0xE9, 0x4F, 0xAF, 0xE0, 0xE7, 0x5C, 0xA9, 0xC4, 0x9B, 0x1F, 0xA2, 0xF2, 0x69, 0x34, - 0x11, 0xDE, 0xB3, 0x95, 0xF5, 0x9E, 0x2D, 0xA3, 0xF7, 0x6C, 0xA6, 0x93, 0xA8, 0xCC, 0xE9, 0xC5, - 0x59, 0x53, 0x6D, 0x49, 0xCE, 0x11, 0x81, 0xA7, 0xD1, 0xE8, 0xF0, 0xFB, 0xC4, 0xF7, 0xB8, 0xFB, - 0x0B, 0xCE, 0x61, 0x57, 0xB6, 0x1B, 0xCC, 0x33, 0xEC, 0x2A, 0x06, 0x23, 0xBD, 0x27, 0x5C, 0x76, - 0x48, 0x39, 0x01, 0x6E, 0x06, 0x2E, 0x4B, 0xB2, 0x0E, 0x2E, 0x09, 0x5E, 0x6D, 0x54, 0x7C, 0x91, - 0x35, 0xD6, 0x6A, 0xAB, 0x21, 0xEE, 0x73, 0x30, 0x3F, 0x07, 0x74, 0xC4, 0x54, 0xC3, 0x6A, 0xB3, - 0x64, 0xB6, 0xDA, 0x56, 0x12, 0x43, 0xDF, 0x35, 0x6E, 0x25, 0xD5, 0xA5, 0xE3, 0x86, 0x13, 0x91, - 0x2D, 0xFE, 0x31, 0x88, 0xA5, 0x27, 0x82, 0x93, 0x73, 0x7A, 0x4D, 0x03, 0x70, 0xD5, 0xE9, 0x91, - 0x23, 0x96, 0xA8, 0x99, 0x15, 0x2A, 0x5B, 0xA0, 0x86, 0x85, 0x04, 0x1E, 0xE2, 0x9C, 0x22, 0x39, - 0x4F, 0x82, 0x6B, 0xD9, 0x45, 0x30, 0xEF, 0x9B, 0xA8, 0x22, 0x25, 0x1C, 0x53, 0xF3, 0x2E, 0x48, - 0xF7, 0x7B, 0xE5, 0xAB, 0xDC, 0xBB, 0xA4, 0xAB, 0x64, 0x49, 0x4A, 0xB2, 0x04, 0x2D, 0xE0, 0x8B, - 0x12, 0x6F, 0x23, 0x6F, 0x01, 0xF8, 0x3C, 0x03, 0x4B, 0x09, 0xA6, 0x93, 0x19, 0x4C, 0x96, 0x37, - 0x45, 0xC2, 0xB0, 0x0C, 0x1F, 0xD8, 0x9F, 0x2D, 0xDD, 0x47, 0x8A, 0xB3, 0xEE, 0x24, 0x98, 0xA4, - 0x0A, 0x8F, 0xFA, 0x84, 0xF9, 0x83, 0x7A, 0x69, 0x44, 0x62, 0xF6, 0xCD, 0xDC, 0x5A, 0x1B, 0x3E, - 0xCB, 0xE6, 0xFE, 0x5D, 0xD9, 0xBB, 0xAE, 0x92, 0x32, 0xF7, 0xD8, 0xB7, 0x31, 0x1F, 0x55, 0x87, - 0x88, 0x56, 0xDF, 0xD9, 0x6E, 0x04, 0x4B, 0xEE, 0x05, 0x39, 0x4C, 0xDF, 0xAC, 0x83, 0xE6, 0x7B, - 0x21, 0xF1, 0xA5, 0x90, 0x6C, 0x43, 0x5F, 0xC5, 0xCC, 0x27, 0x27, 0x09, 0x2F, 0xE4, 0x27, 0x6C, - 0x79, 0xB6, 0x3C, 0xDD, 0xCD, 0x56, 0x3B, 0x47, 0x2A, 0x96, 0x53, 0x45, 0xC9, 0x9D, 0xD7, 0xB7, - 0x6F, 0xB1, 0x39, 0x9D, 0x8E, 0x12, 0x14, 0xAB, 0xE5, 0xD5, 0x6A, 0xA5, 0xB9, 0x81, 0xDB, 0x45, - 0x82, 0x6F, 0x2B, 0x48, 0x86, 0x34, 0x2F, 0x13, 0x49, 0x26, 0x27, 0x8A, 0x9C, 0x9C, 0x65, 0x96, - 0x9C, 0x24, 0xB3, 0xE7, 0x25, 0x99, 0x25, 0x37, 0xC9, 0x7C, 0xF2, 0x93, 0xCC, 0x9E, 0xA3, 0x64, - 0xB6, 0x3C, 0x25, 0xB3, 0xE4, 0x2A, 0x99, 0x35, 0x5F, 0xC9, 0x6C, 0x39, 0x4B, 0xE6, 0x9F, 0xB7, - 0xA4, 0x10, 0x63, 0xBA, 0x25, 0x92, 0x22, 0x72, 0xD3, 0x6F, 0x95, 0xF1, 0x94, 0xE4, 0x40, 0x29, - 0x47, 0x50, 0x31, 0x11, 0x4A, 0xF3, 0x64, 0x28, 0xB3, 0x26, 0x44, 0xC9, 0x66, 0x21, 0x45, 0x0B, - 0xC4, 0xE9, 0xFD, 0x03, 0x4C, 0xC0, 0xCF, 0x6B, 0x7E, 0x34, 0x4E, 0x5F, 0x8F, 0x35, 0x23, 0x08, - 0xFF, 0x3B, 0x93, 0x14, 0x4C, 0xCF, 0xE1, 0x22, 0x65, 0xF4, 0x5B, 0xE4, 0x76, 0x5F, 0x2A, 0xBF, - 0x7C, 0x7F, 0xD6, 0x57, 0xD7, 0xB8, 0x3C, 0x0D, 0x60, 0xC2, 0xCA, 0x9F, 0xFE, 0x44, 0x4C, 0x50, - 0xA0, 0x10, 0x23, 0x96, 0x3B, 0xBC, 0x2E, 0xE4, 0x5B, 0xEA, 0x1E, 0xF8, 0xD3, 0x26, 0x24, 0x8F, - 0x3F, 0x9E, 0xEE, 0xF5, 0x8D, 0xCC, 0x2E, 0x69, 0xCE, 0x82, 0x29, 0xF5, 0x47, 0xD9, 0xB4, 0x26, - 0xE9, 0x07, 0x9B, 0xBA, 0x14, 0x21, 0xCA, 0xAA, 0x72, 0xE3, 0x63, 0xDC, 0x19, 0xAC, 0x51, 0x88, - 0xC2, 0x9F, 0xAC, 0x23, 0xA9, 0x12, 0x2D, 0x2F, 0xEB, 0x8A, 0x61, 0x52, 0x81, 0x56, 0x96, 0xA2, - 0x31, 0xDD, 0xDB, 0x5B, 0x37, 0x3A, 0xB1, 0x27, 0x69, 0x22, 0xB7, 0xB1, 0xEB, 0xC1, 0x0F, 0xFB, - 0x7B, 0x9B, 0x5C, 0xB1, 0x12, 0x29, 0x17, 0x66, 0x3B, 0x31, 0x0A, 0x47, 0x07, 0xD2, 0x28, 0x8E, - 0x23, 0x24, 0x92, 0x27, 0x13, 0x38, 0x7B, 0x63, 0x3B, 0xFC, 0xC6, 0x0B, 0x38, 0x22, 0xA5, 0x90, - 0x29, 0x0E, 0x87, 0x7D, 0x8D, 0x24, 0x79, 0xE6, 0x09, 0xFE, 0xE1, 0x0D, 0x92, 0xE7, 0x1F, 0x16, - 0x19, 0x12, 0xE8, 0xBA, 0x2E, 0x79, 0xFD, 0x9A, 0xD3, 0x82, 0x8E, 0x81, 0x3E, 0xB2, 0xF4, 0xFE, - 0x29, 0x48, 0xA2, 0x69, 0x4E, 0xCC, 0x29, 0xC1, 0x4A, 0xAD, 0x2A, 0xEB, 0xD1, 0xA2, 0x5E, 0xC8, - 0x6C, 0x9D, 0xC4, 0xA9, 0x3E, 0x25, 0x83, 0x18, 0xDF, 0xE9, 0x86, 0xF6, 0x1B, 0xEE, 0x44, 0x85, - 0x04, 0x2C, 0x28, 0x71, 0x60, 0x4D, 0x39, 0x01, 0x7B, 0xCE, 0xF6, 0x50, 0xD4, 0xCE, 0x4A, 0xEE, - 0x56, 0x49, 0x59, 0x93, 0x5D, 0x8C, 0xB5, 0x50, 0x6F, 0x0B, 0xEE, 0xA4, 0x69, 0x92, 0x93, 0xA6, - 0x91, 0x5D, 0xE3, 0x56, 0x78, 0xFA, 0x22, 0x84, 0x43, 0x23, 0x30, 0xF5, 0xD4, 0x79, 0x07, 0xAB, - 0x6C, 0x81, 0x27, 0x7D, 0x02, 0x23, 0xC9, 0xC6, 0x7C, 0x1B, 0x3F, 0xB3, 0x81, 0xD7, 0x1A, 0xF9, - 0x4B, 0x52, 0xAE, 0x03, 0xD3, 0x9F, 0x7B, 0x7D, 0x9F, 0xBC, 0x57, 0xB5, 0x28, 0x2B, 0xC3, 0x52, - 0xD2, 0xDF, 0x2A, 0xD8, 0x2E, 0x51, 0xAF, 0x48, 0x86, 0x9D, 0xFD, 0x8F, 0x1F, 0xCF, 0x0F, 0x8E, - 0x4E, 0xF7, 0x2E, 0x0E, 0x2F, 0x8F, 0x4E, 0xCF, 0x3E, 0x5D, 0x5C, 0x5E, 0x7C, 0x3E, 0xC3, 0x5F, - 0x7F, 0xD9, 0x3B, 0x3E, 0x3A, 0xB8, 0xFC, 0x74, 0xFA, 0x97, 0xD3, 0x8F, 0xBF, 0x9E, 0xEA, 0xF7, - 0xD7, 0x93, 0x1E, 0x45, 0x26, 0x53, 0x8C, 0x78, 0x99, 0x1A, 0x5A, 0x41, 0xA6, 0xDE, 0x37, 0x0F, - 0xF3, 0x3C, 0xEF, 0x3C, 0x37, 0x5D, 0x61, 0x03, 0x60, 0xC0, 0x1F, 0xCA, 0xA1, 0x8E, 0xC4, 0xF8, - 0x6B, 0xB2, 0xD2, 0xDD, 0xB2, 0xB8, 0xFA, 0x9B, 0xCA, 0x61, 0x0A, 0xDA, 0xB2, 0x96, 0x0A, 0xC5, - 0x90, 0x1E, 0xBB, 0x6C, 0xF1, 0x55, 0xFB, 0x96, 0xF5, 0xEC, 0x04, 0x90, 0x3B, 0x54, 0xB8, 0xBA, - 0x48, 0x3A, 0x1D, 0x5F, 0x65, 0xDD, 0x31, 0xE8, 0x1F, 0x7F, 0x76, 0xAC, 0xBE, 0x02, 0x32, 0xB8, - 0x9F, 0x1A, 0xF8, 0x53, 0x03, 0xF3, 0x35, 0x30, 0xA3, 0x2F, 0x7F, 0xD8, 0x55, 0x0C, 0x5F, 0x61, - 0xFB, 0xB9, 0x0D, 0x0D, 0x79, 0x3E, 0x31, 0x96, 0x2A, 0xE8, 0x99, 0x34, 0xBF, 0xD0, 0xD8, 0xCB, - 0x7C, 0x4C, 0x02, 0x58, 0x6C, 0xE2, 0x0C, 0x94, 0x0E, 0xAA, 0x66, 0xA3, 0x25, 0x57, 0xEC, 0x4D, - 0xD9, 0x50, 0x3A, 0x41, 0x3C, 0x3B, 0x80, 0x13, 0x9A, 0x83, 0xE1, 0x11, 0x18, 0x9D, 0x60, 0x78, - 0x41, 0xB1, 0x1D, 0x8F, 0x46, 0x2C, 0x07, 0x6F, 0x68, 0x75, 0x84, 0x3D, 0x1A, 0x61, 0x6F, 0xF1, - 0xBC, 0x43, 0xC9, 0x34, 0xAB, 0x3D, 0xBC, 0x90, 0xA6, 0x9A, 0x55, 0x67, 0xD8, 0x74, 0x66, 0x14, - 0x23, 0x84, 0x91, 0x5A, 0x8C, 0xEB, 0xB4, 0x4D, 0x4C, 0xA4, 0x89, 0x62, 0x35, 0xCB, 0x56, 0x88, - 0x0C, 0x2A, 0x15, 0x61, 0xCB, 0x5E, 0xB9, 0xE6, 0x87, 0x8A, 0xA1, 0xB8, 0x04, 0xC1, 0xE5, 0x2B, - 0x9A, 0x9F, 0xF5, 0xFE, 0x32, 0x79, 0x7C, 0x53, 0xF7, 0xAF, 0xA1, 0xDB, 0x57, 0xD1, 0xB3, 0x13, - 0x08, 0xD0, 0xB3, 0xF8, 0x41, 0xAE, 0x1C, 0x7F, 0xD6, 0x36, 0x75, 0x8F, 0x76, 0x73, 0x93, 0xC0, - 0x18, 0x9E, 0x9E, 0x6B, 0xB2, 0x1A, 0x78, 0xA8, 0x4D, 0x9A, 0x67, 0x52, 0x29, 0x20, 0x2F, 0xC7, - 0x34, 0x54, 0x27, 0xDF, 0xC8, 0x2A, 0xE6, 0xA9, 0x8E, 0xD8, 0xDB, 0x9F, 0xB3, 0xEE, 0xA4, 0x2F, - 0x0B, 0xAB, 0x2A, 0x94, 0xC6, 0x52, 0xA3, 0x26, 0xCD, 0x4B, 0x71, 0x0C, 0xFD, 0x61, 0xBA, 0x78, - 0x3C, 0xA7, 0x8E, 0x50, 0xD2, 0x06, 0xCA, 0x24, 0x66, 0x00, 0xB5, 0x6A, 0xF5, 0x7F, 0x3C, 0xFD, - 0x97, 0xB5, 0xB9, 0xFB, 0xAC, 0xDB, 0xDC, 0x7D, 0x94, 0x36, 0xF7, 0x9E, 0x75, 0x9B, 0x7B, 0x8F, - 0xD2, 0xE6, 0xB5, 0x67, 0xDD, 0xE6, 0xB5, 0xBA, 0x6D, 0xD6, 0x51, 0x3E, 0xB6, 0xC3, 0x98, 0x67, - 0x1A, 0xD3, 0x63, 0x78, 0xE5, 0x49, 0x91, 0x7A, 0x36, 0x11, 0x7D, 0x4B, 0x87, 0xBF, 0xF4, 0xCE, - 0x2D, 0xA0, 0x78, 0xE0, 0xBD, 0x13, 0xB3, 0xCD, 0x8C, 0x26, 0xD6, 0x88, 0x6D, 0x23, 0x38, 0xAA, - 0xEB, 0xE9, 0xC6, 0x17, 0xDB, 0x46, 0xC1, 0xE2, 0x2F, 0xD6, 0x57, 0x31, 0xDF, 0xB2, 0x6F, 0x6E, - 0x78, 0x6A, 0x9F, 0x2E, 0xF2, 0xB3, 0x9C, 0xB8, 0x7C, 0x69, 0x89, 0x97, 0xC5, 0xD5, 0x5F, 0x13, - 0x4B, 0xFD, 0xF0, 0x06, 0x9F, 0x34, 0x58, 0x32, 0x21, 0xEF, 0x96, 0x20, 0xEF, 0xAA, 0xC8, 0xBB, - 0x3A, 0xF2, 0x6E, 0x11, 0xF2, 0x5E, 0x09, 0xF2, 0x9E, 0x8A, 0xBC, 0xA7, 0x23, 0xEF, 0x15, 0x21, - 0x5F, 0x2B, 0x41, 0xBE, 0xA6, 0x22, 0x5F, 0xD3, 0x91, 0xAF, 0x25, 0xC8, 0x9F, 0xDF, 0x96, 0x54, - 0x6D, 0x95, 0x95, 0x32, 0x2A, 0xDF, 0xF8, 0x21, 0xA8, 0xEA, 0x14, 0x7E, 0x85, 0x9F, 0xC1, 0xA8, - 0x44, 0x81, 0x45, 0x04, 0x14, 0x02, 0x09, 0xF5, 0xED, 0x44, 0xFE, 0xB1, 0x7F, 0xC7, 0xAE, 0x8D, - 0xD1, 0xC5, 0xA5, 0xF4, 0x71, 0x5F, 0xC0, 0xB5, 0x94, 0x73, 0xC7, 0x0A, 0x89, 0x19, 0xEF, 0x51, - 0xE9, 0x4E, 0x41, 0xD7, 0xE8, 0x12, 0xAC, 0x6F, 0x9B, 0x9E, 0x09, 0x46, 0xA4, 0x0D, 0x3B, 0xA2, - 0x7E, 0x67, 0xE4, 0xAF, 0xBA, 0x0A, 0x4C, 0x94, 0xD4, 0x39, 0x4C, 0x02, 0x55, 0x7A, 0x51, 0x54, - 0xCC, 0x6E, 0xD4, 0x2B, 0xF1, 0xDF, 0xAE, 0xD3, 0x6D, 0x13, 0xD7, 0xE9, 0x55, 0xE8, 0x3C, 0xBE, - 0x67, 0xD2, 0x35, 0x84, 0xA6, 0x89, 0xAD, 0x73, 0x40, 0x93, 0x2D, 0xCC, 0xA8, 0x7C, 0xB7, 0xB9, - 0xCE, 0x03, 0x81, 0x67, 0xBB, 0x87, 0xDB, 0x35, 0x9F, 0xB3, 0xA0, 0x4C, 0x4C, 0xC7, 0x5D, 0x4A, - 0xE8, 0x1C, 0x1A, 0x7F, 0xBE, 0x13, 0xA5, 0x3E, 0x93, 0x23, 0x3D, 0x2F, 0x1C, 0xEB, 0x7B, 0xD1, - 0x30, 0x65, 0x2F, 0xF6, 0x5E, 0xF8, 0xEF, 0x6C, 0x0C, 0x23, 0xB8, 0x3F, 0x10, 0xD7, 0xDB, 0xD5, - 0x25, 0xAA, 0x5A, 0x96, 0x7D, 0xD7, 0xB7, 0x15, 0x17, 0x91, 0xBD, 0x09, 0x4C, 0x23, 0xD4, 0x51, - 0xE2, 0x1A, 0x58, 0x06, 0x4A, 0x87, 0x5D, 0xFB, 0xE3, 0xD4, 0xF0, 0x50, 0xC8, 0xF8, 0xF0, 0x96, - 0x46, 0x89, 0xC5, 0x75, 0xB6, 0xBB, 0xED, 0x96, 0x99, 0x65, 0xC3, 0x51, 0x6C, 0x86, 0xFD, 0x4A, - 0x0F, 0x98, 0xA5, 0x2F, 0x89, 0xE5, 0xE5, 0xC3, 0x2C, 0x79, 0x7C, 0x6C, 0x97, 0x7C, 0x57, 0x62, - 0xCC, 0x4A, 0x5E, 0x53, 0x94, 0xDB, 0xF2, 0x37, 0x1A, 0xF8, 0x71, 0x56, 0x64, 0xE9, 0x95, 0x16, - 0x29, 0x0F, 0x34, 0xDB, 0xC6, 0x2F, 0x4D, 0xD3, 0x4D, 0x16, 0xF1, 0x4E, 0x85, 0x21, 0x9F, 0xF3, - 0xD2, 0x8B, 0x47, 0xC8, 0xA6, 0xDD, 0x30, 0x2F, 0x74, 0xAD, 0x9C, 0xD0, 0x43, 0x35, 0x9B, 0xAD, - 0xFE, 0x72, 0xFD, 0x83, 0x22, 0x29, 0x3D, 0xF5, 0xF2, 0x8B, 0xB9, 0xE7, 0x70, 0x6E, 0x92, 0x46, - 0xB5, 0x7A, 0x0A, 0xD5, 0xDC, 0xC6, 0x76, 0xAC, 0xB2, 0xF6, 0xA6, 0xC9, 0x97, 0xF9, 0xF9, 0xD8, - 0x5C, 0xD3, 0x38, 0x3F, 0xAF, 0x56, 0xF3, 0x27, 0x8B, 0xB0, 0x19, 0x86, 0x01, 0x21, 0x30, 0xF5, - 0xA3, 0x80, 0xDA, 0xE3, 0x54, 0x09, 0xAA, 0xC9, 0x83, 0x63, 0x95, 0x05, 0x22, 0xE1, 0xF9, 0xD1, - 0xD2, 0x28, 0x50, 0x80, 0x4C, 0xC2, 0xE4, 0x99, 0x94, 0x20, 0x8B, 0xED, 0x07, 0x37, 0xBD, 0xDB, - 0x29, 0x6A, 0xFC, 0x21, 0xBF, 0x3E, 0x36, 0x9F, 0xB6, 0x67, 0x90, 0xFD, 0xA0, 0xA6, 0xA7, 0x17, - 0xDD, 0xC5, 0x9B, 0xF5, 0x59, 0x37, 0x00, 0xE7, 0x0C, 0xB4, 0xED, 0xC5, 0xF3, 0x46, 0x95, 0xF7, - 0x03, 0x4C, 0xB3, 0xC6, 0x3C, 0x67, 0x0C, 0x35, 0x43, 0xFA, 0x73, 0x9E, 0x35, 0x92, 0x7C, 0xEE, - 0xF3, 0x98, 0x39, 0xB2, 0xC9, 0xE1, 0x9F, 0xE5, 0xEC, 0xA1, 0xA7, 0x0D, 0x9F, 0x9B, 0xED, 0x78, - 0x0E, 0x6D, 0xAF, 0x6C, 0x3A, 0x66, 0x6E, 0xB9, 0x8E, 0xEB, 0xF9, 0x1A, 0x0E, 0xE1, 0x38, 0xF3, - 0x54, 0xE8, 0x60, 0x17, 0x32, 0xEE, 0xB2, 0xEA, 0x8D, 0xEE, 0xFC, 0xA8, 0xB7, 0x5F, 0xD8, 0x83, - 0xEC, 0xAA, 0x51, 0x62, 0x13, 0x31, 0x7F, 0xFE, 0x26, 0xE9, 0xE1, 0x9D, 0x72, 0x80, 0x7E, 0x6D, - 0x80, 0x8B, 0xBA, 0x00, 0xBF, 0x48, 0x00, 0xEB, 0xE5, 0x00, 0xE7, 0x27, 0xFB, 0x59, 0x0A, 0x0F, - 0x0D, 0x5E, 0x28, 0x19, 0xB2, 0x87, 0xD6, 0x54, 0x6F, 0xF5, 0xFD, 0x99, 0x2A, 0x22, 0xAB, 0xB3, - 0xB1, 0x53, 0x06, 0xD0, 0xAF, 0x0D, 0x70, 0x51, 0x17, 0x40, 0x16, 0x51, 0x32, 0x2E, 0xF3, 0x01, - 0x54, 0x11, 0x25, 0x14, 0x1E, 0x66, 0x79, 0x94, 0x82, 0x5D, 0xA3, 0x63, 0x2E, 0x5D, 0x6C, 0xA8, - 0x18, 0x31, 0x4B, 0x22, 0xB4, 0x89, 0xC7, 0x9C, 0xE3, 0x90, 0x0E, 0x36, 0x2C, 0xAB, 0x0C, 0xAE, - 0x2B, 0xC1, 0xBD, 0x44, 0x38, 0x00, 0xEB, 0x9A, 0x9A, 0x25, 0xB9, 0x91, 0x85, 0xDA, 0x6B, 0xA8, - 0xDE, 0xAF, 0x59, 0xFD, 0xA2, 0x5E, 0x75, 0xB9, 0x53, 0x7A, 0x65, 0xD5, 0x33, 0x5A, 0x6B, 0xAA, - 0x9F, 0x75, 0x1F, 0xF1, 0xB7, 0xAE, 0xB5, 0xB6, 0x26, 0xC3, 0x5A, 0xA9, 0x61, 0x7E, 0xC8, 0x98, - 0x26, 0x71, 0xED, 0xF5, 0xA7, 0x61, 0x7A, 0x06, 0x86, 0xA9, 0x08, 0xE2, 0xFC, 0xB7, 0x93, 0xCB, - 0xF3, 0xBD, 0x5F, 0x7F, 0xAB, 0xCC, 0x13, 0x02, 0xF4, 0xDF, 0x9D, 0xBF, 0xFD, 0xED, 0xA7, 0xF1, - 0xAB, 0x6D, 0xFC, 0xF2, 0x20, 0xF4, 0x71, 0xD6, 0xDD, 0xAE, 0x48, 0x4A, 0x07, 0xEC, 0x59, 0x0D, - 0x01, 0xD7, 0x7B, 0x4D, 0x01, 0x37, 0x5B, 0xB9, 0xAE, 0xDA, 0x4F, 0x0B, 0xFF, 0xCF, 0x60, 0xE1, - 0x4D, 0xE0, 0x99, 0x35, 0xB6, 0xA4, 0xB7, 0xA6, 0x04, 0x6F, 0xD5, 0xC0, 0x99, 0xF6, 0x36, 0x07, - 0x67, 0x3A, 0x3C, 0x03, 0xF8, 0x66, 0x6E, 0x76, 0x3A, 0x83, 0xEB, 0x8D, 0x30, 0xC6, 0xC9, 0x4D, - 0x5D, 0xCF, 0x3F, 0xA3, 0x09, 0x8E, 0x2D, 0x69, 0x90, 0xED, 0xCB, 0xAE, 0x65, 0x6D, 0x54, 0xB5, - 0xF7, 0x32, 0xD4, 0xCB, 0xF5, 0x46, 0x50, 0x2F, 0x5B, 0x99, 0xD5, 0x7B, 0x39, 0xD4, 0x56, 0x23, - 0x5A, 0x5B, 0x1A, 0xAD, 0x8A, 0x60, 0xDB, 0x8D, 0x88, 0x6D, 0x37, 0x69, 0x58, 0xB7, 0xD7, 0x84, - 0x56, 0xB7, 0xD7, 0x84, 0x56, 0x6F, 0x4D, 0x99, 0x0E, 0xAA, 0xCA, 0x63, 0xDD, 0x7A, 0xD9, 0x53, - 0xAC, 0x6D, 0x45, 0x7A, 0x0C, 0xAE, 0xDB, 0xCA, 0xD9, 0xAA, 0x99, 0xC9, 0x2D, 0x48, 0x96, 0xE4, - 0x7C, 0xA8, 0xAA, 0xEA, 0x5B, 0x32, 0x5B, 0x49, 0x70, 0x39, 0xFE, 0x6B, 0x39, 0xA0, 0xAA, 0xF9, - 0xD5, 0xE1, 0xB6, 0x1A, 0xC2, 0x6D, 0x37, 0x83, 0xD3, 0x94, 0x6B, 0x6E, 0xB3, 0x71, 0xDE, 0xCE, - 0x50, 0xD3, 0x39, 0x43, 0xEF, 0xCA, 0x7A, 0x46, 0x5B, 0x27, 0xDD, 0x00, 0xFA, 0xA4, 0x7F, 0xB2, - 0x5E, 0xD7, 0xDA, 0x1F, 0xFB, 0x77, 0x68, 0x66, 0xEF, 0x5C, 0x27, 0xBA, 0xF9, 0x47, 0xB7, 0xF8, - 0x56, 0x23, 0x93, 0xDF, 0x7B, 0x42, 0x93, 0xDF, 0x7B, 0x4A, 0x93, 0xDF, 0x7B, 0x42, 0x93, 0xDF, - 0xFB, 0x69, 0xF2, 0x67, 0x36, 0xF9, 0xBD, 0xA7, 0x36, 0xF9, 0xBD, 0x86, 0x26, 0xBF, 0xD7, 0xD0, - 0xE4, 0xF7, 0x1A, 0x9A, 0xFC, 0xDE, 0x13, 0x99, 0x7C, 0x6B, 0xE3, 0x3F, 0x37, 0xAB, 0xC8, 0xB5, - 0xFA, 0x8C, 0x51, 0x05, 0x58, 0x58, 0x6D, 0xA5, 0xB1, 0xFF, 0x34, 0x33, 0xCD, 0x34, 0x64, 0xAF, - 0x40, 0xA6, 0x97, 0x68, 0xC2, 0xEC, 0xED, 0x12, 0xFE, 0x9C, 0x5F, 0x2A, 0x01, 0x8A, 0x7F, 0xEF, - 0x64, 0xEB, 0x7C, 0xD6, 0xEA, 0x7C, 0x36, 0xD4, 0xF9, 0x5D, 0xAB, 0xF3, 0xFB, 0x8E, 0xBC, 0x8B, - 0x07, 0xDC, 0xBC, 0xA7, 0xBE, 0x43, 0x23, 0x77, 0x50, 0xC8, 0x51, 0xF6, 0xBE, 0xCB, 0x50, 0x80, - 0x41, 0x49, 0xF9, 0x7D, 0x96, 0xA4, 0xB2, 0xEF, 0x69, 0x95, 0x3F, 0xEC, 0x1D, 0xEE, 0x9D, 0xED, - 0x1B, 0xAA, 0xEE, 0x8D, 0x22, 0xD1, 0xEB, 0x6A, 0x52, 0x98, 0xB1, 0x1D, 0x7C, 0x53, 0x32, 0xC2, - 0x74, 0x4B, 0xD2, 0xBE, 0x94, 0x80, 0xF7, 0x4C, 0xE0, 0xFC, 0xEA, 0xB7, 0xA0, 0x6F, 0x3B, 0xFF, - 0x31, 0x0D, 0x23, 0x60, 0x54, 0x0F, 0x05, 0x62, 0xA7, 0xB5, 0xA7, 0xF4, 0xEE, 0xD8, 0x4F, 0x6F, - 0x08, 0x65, 0x32, 0xA8, 0xA4, 0x75, 0x0C, 0x81, 0x51, 0xF4, 0xBB, 0x1B, 0x69, 0xE9, 0x10, 0x6E, - 0x5C, 0x87, 0x25, 0x74, 0x74, 0xBD, 0x33, 0x96, 0x86, 0x86, 0x37, 0x02, 0x63, 0xD7, 0x30, 0x17, - 0x1D, 0x78, 0x29, 0x47, 0xDE, 0x59, 0xE0, 0xE3, 0xED, 0xFD, 0x24, 0x49, 0x84, 0x4E, 0x13, 0xB1, - 0xEE, 0x79, 0x8E, 0x1C, 0x8D, 0x85, 0xD5, 0xB8, 0x8F, 0xC3, 0xD3, 0xB5, 0x81, 0xA0, 0xD3, 0x3F, - 0x16, 0x53, 0x36, 0x58, 0x26, 0x4D, 0xCB, 0x14, 0xBE, 0xB5, 0xEF, 0x8F, 0x27, 0x23, 0x1A, 0xA5, - 0x89, 0x93, 0x58, 0x8C, 0x5A, 0x8C, 0x41, 0xC6, 0x2D, 0xC8, 0x99, 0x1B, 0xC2, 0xBF, 0x66, 0x1B, - 0xA2, 0x35, 0x32, 0xA6, 0xD6, 0x8A, 0x6F, 0x76, 0xED, 0xDB, 0x23, 0x4C, 0x3C, 0x7B, 0x77, 0x43, - 0xF9, 0xE5, 0xAE, 0xC3, 0xFE, 0xD9, 0x5A, 0x8F, 0xDC, 0xD8, 0x21, 0xDE, 0x95, 0xBA, 0x76, 0x83, - 0x31, 0x14, 0x06, 0xA0, 0xDF, 0xEE, 0x24, 0x22, 0xFE, 0x35, 0x8F, 0x94, 0xC6, 0x45, 0x7F, 0x2A, - 0x1C, 0x72, 0x1D, 0xF8, 0x63, 0xB2, 0x77, 0xC6, 0x01, 0x86, 0x64, 0x02, 0x5C, 0x49, 0x91, 0x7A, - 0x1C, 0x0B, 0xE6, 0x52, 0x38, 0xE7, 0x68, 0xA4, 0x43, 0xFA, 0x03, 0xE0, 0x24, 0x18, 0xBB, 0x1E, - 0x05, 0xFA, 0xEE, 0xE0, 0x86, 0xA4, 0x1A, 0x80, 0x79, 0x51, 0x91, 0x1D, 0x3F, 0x70, 0x87, 0x30, - 0x76, 0x46, 0x8C, 0x70, 0xE2, 0x19, 0xC6, 0xD9, 0x19, 0x62, 0xA1, 0xFF, 0x61, 0x97, 0x78, 0xD3, - 0xD1, 0x68, 0x49, 0x8F, 0x2E, 0x8C, 0xA5, 0xA8, 0xD5, 0xAF, 0x92, 0xB4, 0x81, 0x7F, 0x7B, 0x45, - 0xF6, 0x46, 0x23, 0xD2, 0x87, 0xEF, 0x4E, 0x71, 0x2A, 0x3F, 0xDF, 0x0B, 0xFD, 0x11, 0xED, 0x8C, - 0x40, 0x63, 0x5B, 0x9F, 0xF8, 0x8D, 0x54, 0x02, 0xFF, 0x81, 0x9C, 0x40, 0x68, 0x59, 0x19, 0x98, - 0x93, 0x78, 0x5C, 0x27, 0x69, 0x2B, 0x47, 0xBE, 0xED, 0xFC, 0x6A, 0xBB, 0x91, 0x72, 0x11, 0x1D, - 0x33, 0x81, 0x88, 0xB7, 0x12, 0xC2, 0xE9, 0xD5, 0xD8, 0x8D, 0xE2, 0x34, 0x91, 0x98, 0x31, 0x04, - 0x06, 0x1B, 0x96, 0x87, 0x5F, 0xAC, 0xAF, 0x69, 0x5C, 0x3B, 0x4E, 0x59, 0x22, 0xB6, 0xDD, 0xA3, - 0x77, 0x04, 0x6F, 0x01, 0xCA, 0x49, 0x2D, 0xE2, 0xE2, 0x8E, 0x3D, 0x99, 0xF0, 0x41, 0x95, 0x45, - 0xDB, 0x66, 0x64, 0x97, 0x52, 0x9C, 0xF6, 0x7F, 0xD8, 0xDF, 0x05, 0xBE, 0xDF, 0x4E, 0x8E, 0x3F, - 0x44, 0x98, 0x72, 0xEC, 0xAF, 0x53, 0x1A, 0x46, 0x31, 0x56, 0xAC, 0xD0, 0xF1, 0x01, 0xE1, 0x62, - 0xEB, 0xEC, 0x63, 0xFF, 0x02, 0x73, 0x98, 0xAC, 0x4E, 0x59, 0x8B, 0x62, 0xC4, 0x2D, 0xB9, 0x26, - 0x1B, 0x5A, 0x31, 0x27, 0xF1, 0xC8, 0xE3, 0x66, 0x4C, 0x96, 0x86, 0x21, 0xD6, 0xF2, 0xF5, 0x55, - 0xF0, 0x86, 0x17, 0xBA, 0x78, 0x87, 0x6F, 0xA2, 0x24, 0x90, 0x6A, 0xED, 0x14, 0x88, 0xB6, 0x1F, - 0xD9, 0xD1, 0x34, 0xC4, 0xF0, 0x66, 0xD5, 0x20, 0x17, 0x13, 0x84, 0xEA, 0x45, 0x48, 0x33, 0x03, - 0x99, 0x0F, 0x3B, 0x73, 0xA5, 0x56, 0xEE, 0x60, 0x56, 0x08, 0xF8, 0xC1, 0x90, 0x46, 0x67, 0xB6, - 0x1B, 0xC0, 0x8C, 0x88, 0xC6, 0x55, 0x9D, 0x41, 0xAE, 0x22, 0xEF, 0x1D, 0xAB, 0xC1, 0xCB, 0x0C, - 0x22, 0x42, 0xED, 0x65, 0x79, 0x7D, 0x42, 0x86, 0xCB, 0x8F, 0x22, 0xEA, 0x75, 0xA4, 0x9C, 0x04, - 0x13, 0x4A, 0x83, 0x93, 0xBD, 0xFD, 0x50, 0x87, 0x3B, 0xF5, 0x3D, 0x9A, 0x17, 0x99, 0xCA, 0x28, - 0x1E, 0x86, 0x93, 0x53, 0xFF, 0xEE, 0x0C, 0xC0, 0x43, 0x83, 0xF9, 0x05, 0xC6, 0x98, 0x91, 0xD4, - 0x73, 0xC2, 0x0D, 0x63, 0x13, 0x25, 0x0A, 0x0C, 0x1C, 0x33, 0x38, 0x16, 0xAA, 0x23, 0x92, 0x77, - 0xE5, 0x45, 0xC8, 0xCA, 0x78, 0x52, 0x16, 0x92, 0x70, 0x05, 0xDB, 0x71, 0x0E, 0x6F, 0xE1, 0x17, - 0x0C, 0x53, 0xA6, 0x80, 0x7F, 0xB1, 0x75, 0xF0, 0xF1, 0x04, 0x6C, 0x71, 0x84, 0xDF, 0xA0, 0x23, - 0x28, 0xA6, 0xC7, 0x5B, 0xA4, 0x58, 0x65, 0x89, 0xEC, 0xBE, 0x01, 0x06, 0x13, 0x0D, 0x17, 0x02, - 0xAB, 0x10, 0xFB, 0x90, 0x4D, 0x32, 0xA6, 0x44, 0x3C, 0xB0, 0xBB, 0xF4, 0xE8, 0xD4, 0xB3, 0x5B, - 0x7B, 0xF0, 0x0B, 0xC7, 0x9C, 0x44, 0x3C, 0xB8, 0x18, 0x06, 0x61, 0x7F, 0x87, 0x5F, 0xD4, 0xD0, - 0x07, 0x5E, 0xED, 0x8B, 0xFB, 0xB5, 0xE3, 0x7B, 0x83, 0x91, 0x3B, 0xC0, 0x34, 0x1F, 0x89, 0x6C, - 0x17, 0x33, 0xAF, 0x5A, 0xAB, 0xE9, 0xF7, 0x72, 0xDE, 0xAA, 0xE5, 0x2E, 0x96, 0x1D, 0x4E, 0x03, - 0x16, 0x34, 0x8D, 0x8E, 0xF0, 0x87, 0xBF, 0x81, 0xF0, 0xB3, 0x72, 0xE2, 0xF8, 0x70, 0xE0, 0x1B, - 0x49, 0x1A, 0x10, 0xF5, 0xE9, 0x40, 0xDD, 0x36, 0x21, 0xAB, 0xB9, 0xF4, 0xA4, 0x60, 0xEC, 0x07, - 0x79, 0xB4, 0x1B, 0x51, 0xCE, 0x83, 0xB9, 0x94, 0x6A, 0x11, 0x6F, 0x52, 0x13, 0x0C, 0xCC, 0x61, - 0x5A, 0x31, 0xBC, 0x13, 0xCC, 0xE3, 0x45, 0x8E, 0xBC, 0x26, 0xAC, 0xC5, 0x29, 0x6C, 0x0D, 0xB8, - 0x4A, 0x9E, 0x2D, 0xE7, 0x76, 0x24, 0x14, 0xF5, 0xCD, 0x6F, 0x21, 0x73, 0x3B, 0xC2, 0x3C, 0xBF, - 0xDC, 0x47, 0x8B, 0x4D, 0x2D, 0x7A, 0x87, 0x10, 0xF3, 0x68, 0x4E, 0x8C, 0xA8, 0x52, 0x5B, 0x72, - 0xF8, 0x4C, 0x1B, 0x92, 0xDF, 0x58, 0x43, 0x5B, 0x8A, 0xDF, 0x84, 0x6F, 0xDC, 0xB2, 0x99, 0x9E, - 0x9A, 0xE7, 0xED, 0xC4, 0x75, 0x41, 0x51, 0x33, 0x87, 0xC9, 0x12, 0xA1, 0x79, 0x33, 0xDF, 0xB3, - 0x8C, 0x4E, 0xF3, 0x6E, 0xE5, 0x7B, 0x3D, 0x4F, 0x94, 0xA9, 0x91, 0xBC, 0x11, 0xF9, 0x8D, 0xE4, - 0x42, 0xC8, 0x36, 0x52, 0xA9, 0x94, 0xB7, 0xD3, 0x97, 0x59, 0x5F, 0x37, 0xD8, 0xD2, 0x53, 0x1E, - 0x52, 0x32, 0x66, 0xBA, 0x97, 0x8E, 0x44, 0xB7, 0x3A, 0x1B, 0x78, 0xBA, 0xB9, 0x07, 0xCE, 0x2D, - 0x4C, 0xC5, 0xE8, 0xB7, 0x1D, 0x77, 0x57, 0x8F, 0x7B, 0x0A, 0xB2, 0x07, 0xF5, 0x22, 0x52, 0xE9, - 0xF6, 0xC0, 0x6D, 0xF6, 0xB6, 0x6B, 0x65, 0x7E, 0xB6, 0x3B, 0x9B, 0x73, 0xE4, 0x27, 0xBB, 0x5F, - 0x54, 0x87, 0x99, 0x6E, 0x77, 0x73, 0xAE, 0xD2, 0xD1, 0x53, 0x0B, 0xD7, 0xE1, 0x65, 0x1D, 0xF7, - 0x2D, 0x1A, 0xB0, 0xD2, 0x8C, 0x9A, 0xB2, 0xB9, 0xA2, 0x62, 0x36, 0x8C, 0x51, 0xD3, 0x4B, 0xF0, - 0x8D, 0x87, 0x66, 0xCD, 0x67, 0xE5, 0xD3, 0x11, 0x67, 0xB8, 0x1C, 0x9C, 0x7B, 0x7D, 0xD9, 0x34, - 0xA2, 0x2B, 0xC0, 0xE7, 0xB5, 0x3A, 0x79, 0xBF, 0x67, 0x1E, 0xAD, 0xAE, 0xF2, 0x18, 0x90, 0xD6, - 0x6A, 0x0E, 0xD2, 0xBC, 0xD5, 0xC5, 0xF0, 0x86, 0x56, 0x6B, 0xD7, 0xC5, 0x66, 0x6F, 0x79, 0x16, - 0x61, 0x49, 0xEB, 0x0D, 0x17, 0xD3, 0x00, 0x48, 0xE4, 0x88, 0xD7, 0xA2, 0x60, 0x4B, 0x45, 0x51, - 0x8A, 0x4C, 0xDD, 0xB8, 0x33, 0x88, 0x05, 0x97, 0x71, 0x98, 0x13, 0x15, 0xB3, 0xFE, 0x7A, 0x74, - 0x34, 0x8B, 0x40, 0xB2, 0xA8, 0x92, 0xAC, 0x26, 0x96, 0x59, 0x07, 0x62, 0x88, 0xB7, 0xF6, 0xD4, - 0x39, 0x08, 0xFC, 0x09, 0x26, 0xD4, 0x37, 0x4F, 0xBD, 0xCA, 0x93, 0x72, 0xA5, 0xFA, 0x52, 0x81, - 0xA3, 0xAE, 0x79, 0x76, 0xAC, 0xC2, 0x91, 0x70, 0x16, 0x6A, 0x71, 0xD4, 0x94, 0x56, 0x8D, 0xD6, - 0x1B, 0xB4, 0x3D, 0xFF, 0x91, 0xC7, 0x19, 0xB5, 0xBE, 0xF4, 0xF5, 0x48, 0x73, 0x7F, 0x4F, 0xC0, - 0x4C, 0xF1, 0xE7, 0x83, 0x1B, 0x09, 0xAC, 0x1C, 0x5C, 0x91, 0xC1, 0x34, 0xA4, 0xC7, 0xFE, 0xC0, - 0x1E, 0xB9, 0x7F, 0xA3, 0xCE, 0x01, 0xB4, 0x33, 0x70, 0xAF, 0xA6, 0x3C, 0x8D, 0x64, 0xF3, 0xE6, - 0x17, 0xE0, 0x2C, 0x6C, 0xF9, 0xC8, 0x04, 0x74, 0x01, 0x2B, 0xC0, 0x63, 0x58, 0xD3, 0x8E, 0x4C, - 0xBD, 0x5F, 0x41, 0x1E, 0x4D, 0x91, 0x1A, 0x34, 0x45, 0x7F, 0x6B, 0x72, 0x46, 0xFD, 0xA8, 0xF1, - 0x74, 0x65, 0xE1, 0x88, 0x3A, 0xA0, 0x91, 0xED, 0x8E, 0xC2, 0x9A, 0x72, 0xA9, 0x83, 0xA8, 0x40, - 0x16, 0x1F, 0xEC, 0xC0, 0xC1, 0xAD, 0x20, 0x2E, 0x88, 0xE4, 0x0D, 0x9E, 0x39, 0x89, 0x26, 0x07, - 0x7B, 0x2D, 0x49, 0xC9, 0xB0, 0xB3, 0x89, 0xAA, 0x12, 0x26, 0x93, 0xAC, 0xD8, 0xC6, 0xD2, 0x1C, - 0xA4, 0x12, 0xE3, 0xA9, 0xD4, 0x7E, 0xB6, 0xE3, 0xD2, 0xAC, 0xC1, 0xC5, 0xA0, 0x26, 0x8F, 0x41, - 0xDA, 0xB2, 0x9B, 0x83, 0xBB, 0xA0, 0x62, 0xCB, 0xB1, 0x19, 0x86, 0xDD, 0xC2, 0xD9, 0x7C, 0x84, - 0x42, 0x64, 0xA5, 0x3E, 0x82, 0xF2, 0x34, 0xDD, 0x8C, 0x02, 0x28, 0x7F, 0xE0, 0x4E, 0x36, 0x9A, - 0x81, 0xDD, 0xAC, 0x97, 0x0B, 0x21, 0x8D, 0x6D, 0x6B, 0x3C, 0xBA, 0x91, 0xD5, 0x0F, 0x40, 0x54, - 0x1D, 0x3C, 0xF1, 0xC6, 0x5E, 0x3E, 0xAD, 0xF3, 0xA3, 0xD3, 0xC3, 0xDF, 0xE6, 0x21, 0x4F, 0x05, - 0x5B, 0x35, 0xF3, 0x91, 0x81, 0x6C, 0x68, 0x3C, 0xAA, 0xE3, 0x31, 0xC8, 0x41, 0x79, 0xD8, 0x6C, - 0x46, 0x29, 0x54, 0x7D, 0x24, 0x4D, 0x97, 0x41, 0x0A, 0x37, 0x8B, 0x04, 0x2A, 0x60, 0x31, 0xB5, - 0xDF, 0xF4, 0xF2, 0xD9, 0xAC, 0x72, 0xA8, 0xF9, 0x9A, 0x5A, 0x46, 0x1E, 0x00, 0x3F, 0xB6, 0x23, - 0x77, 0xA0, 0x22, 0x99, 0x49, 0x38, 0x35, 0x51, 0xE6, 0x48, 0x2A, 0x7E, 0x2B, 0x6D, 0x0E, 0x02, - 0xAA, 0xF0, 0xEC, 0x5A, 0xAE, 0x5C, 0x18, 0xEC, 0x5C, 0xC4, 0x51, 0x8C, 0x49, 0x91, 0x42, 0xE5, - 0x67, 0xD4, 0x1A, 0x0B, 0x67, 0x1E, 0x0F, 0xB5, 0x49, 0x7B, 0xDF, 0x85, 0xD8, 0x9A, 0x49, 0xAF, - 0x21, 0xCE, 0xEC, 0x96, 0xEC, 0xDE, 0x28, 0x72, 0xA3, 0xA9, 0xD3, 0x68, 0xB0, 0x29, 0x21, 0x10, - 0x19, 0xF4, 0xFA, 0xD3, 0x9F, 0x8F, 0x45, 0x20, 0xB3, 0xF9, 0x35, 0x67, 0x32, 0x6A, 0x40, 0xCA, - 0x1C, 0x91, 0x27, 0xF7, 0x8A, 0xEF, 0xF9, 0xBD, 0xE2, 0x7B, 0xF2, 0x9A, 0x78, 0xD3, 0xF1, 0x7E, - 0xE6, 0x05, 0x57, 0x28, 0xCA, 0xDE, 0x2E, 0x86, 0xE5, 0x4D, 0xE4, 0x7B, 0xE2, 0x72, 0x31, 0x7B, - 0xB2, 0x04, 0xB3, 0xD3, 0xBC, 0x65, 0x5F, 0xF1, 0x59, 0x89, 0x7B, 0x25, 0x40, 0x29, 0xAD, 0x6D, - 0x6C, 0x02, 0x1E, 0xD3, 0xE5, 0xB6, 0x20, 0xCE, 0x9C, 0x93, 0xE2, 0xDF, 0xC7, 0xFA, 0x8B, 0xF7, - 0xB2, 0x7A, 0x49, 0xAF, 0x43, 0x2C, 0xC9, 0xC1, 0x30, 0x39, 0xEE, 0x80, 0x94, 0x5A, 0xAA, 0x5E, - 0x74, 0x5A, 0xC9, 0x03, 0xAC, 0x15, 0x66, 0x78, 0xC1, 0xC3, 0x09, 0xC3, 0x3E, 0xCB, 0x14, 0x5F, - 0x82, 0xC8, 0x18, 0x6A, 0x31, 0x37, 0xF6, 0xE7, 0xC0, 0xB8, 0x89, 0x65, 0x25, 0x26, 0xAD, 0x28, - 0xFD, 0x51, 0x41, 0x62, 0xA6, 0x1C, 0x1D, 0xD6, 0x6E, 0xC8, 0x37, 0xD7, 0xFE, 0x34, 0x27, 0x6B, - 0x7E, 0x36, 0xA7, 0x7B, 0x96, 0xB6, 0xEF, 0xBB, 0x69, 0x97, 0xBE, 0xCA, 0xE0, 0xF9, 0xBE, 0x63, - 0xDA, 0x6E, 0x97, 0x07, 0x11, 0x66, 0x87, 0x16, 0x07, 0xF2, 0x2C, 0x33, 0xB3, 0xC6, 0x0A, 0x56, - 0x42, 0x2E, 0x4A, 0x76, 0xDF, 0xD5, 0xB4, 0x60, 0x86, 0x31, 0x86, 0xDF, 0xF8, 0xDF, 0x69, 0xDC, - 0x11, 0x39, 0xF2, 0x06, 0x01, 0x8B, 0x16, 0x99, 0x88, 0x7C, 0x59, 0x64, 0x85, 0x84, 0x77, 0xF6, - 0x84, 0xBF, 0xBE, 0xCD, 0x0E, 0xFA, 0x61, 0x4E, 0x4A, 0x79, 0x22, 0x21, 0xE3, 0x89, 0xA7, 0x0F, - 0xC1, 0x3A, 0x1E, 0xA6, 0xB6, 0xBE, 0x01, 0xBB, 0x4C, 0xC3, 0xF4, 0xC5, 0xCD, 0x94, 0x14, 0x79, - 0xA3, 0xEE, 0x50, 0xB2, 0x64, 0x06, 0xF6, 0x37, 0x7A, 0x42, 0x3F, 0x20, 0x4C, 0xB0, 0x63, 0x28, - 0x61, 0xC9, 0xFC, 0x76, 0xB2, 0xBD, 0x5B, 0x5B, 0x2F, 0xAA, 0xF4, 0xEE, 0x77, 0xD6, 0xBB, 0x59, - 0xD9, 0xC8, 0xFF, 0x64, 0x86, 0xD3, 0xCC, 0x5E, 0xE6, 0x13, 0x96, 0x6A, 0xF4, 0x64, 0x09, 0xAD, - 0x90, 0xEE, 0x52, 0x3E, 0x55, 0x26, 0x8C, 0x22, 0xA2, 0x0F, 0x73, 0x14, 0x14, 0x33, 0x99, 0x72, - 0x6B, 0x4D, 0x7C, 0x95, 0xB4, 0x6E, 0x05, 0x2F, 0x23, 0xC9, 0xAA, 0x55, 0x22, 0x2C, 0x89, 0x26, - 0x6B, 0xAB, 0x89, 0x24, 0x60, 0x3B, 0xF5, 0x23, 0xFA, 0x8A, 0xB4, 0x4A, 0x88, 0x2F, 0x03, 0xF1, - 0x16, 0xF1, 0xBD, 0xD1, 0x3D, 0xB9, 0xF3, 0x83, 0x6F, 0x61, 0xCC, 0x2C, 0xFC, 0xED, 0x5E, 0x9B, - 0xD0, 0x16, 0xE0, 0x63, 0x4F, 0xA4, 0xB8, 0x5E, 0xD4, 0x66, 0x6F, 0xD3, 0x87, 0x2C, 0xFB, 0x74, - 0x87, 0x7C, 0xC2, 0xB1, 0x62, 0x07, 0xF8, 0x48, 0x57, 0x84, 0x63, 0x85, 0x52, 0x62, 0x5F, 0xF9, - 0xB7, 0xB4, 0xAE, 0x98, 0x96, 0x63, 0x31, 0x1D, 0xD0, 0x42, 0x31, 0x3D, 0x28, 0x19, 0x4B, 0xC8, - 0xD1, 0x35, 0xB1, 0x47, 0x50, 0xDF, 0xB9, 0x67, 0xA3, 0x4F, 0x0C, 0xBC, 0x64, 0xF4, 0xB6, 0x99, - 0x24, 0x89, 0x1B, 0x91, 0x11, 0xC8, 0x52, 0x8C, 0x48, 0xCD, 0x92, 0xB3, 0x60, 0x9C, 0xBD, 0xF1, - 0x07, 0x0E, 0xFA, 0xB4, 0xE3, 0x0C, 0x6D, 0x01, 0x36, 0xC3, 0x22, 0x6E, 0x48, 0x3E, 0x48, 0x56, - 0x43, 0x41, 0x95, 0x30, 0x97, 0xD5, 0x7B, 0xFC, 0x77, 0x05, 0xED, 0xFF, 0xF6, 0x34, 0xC3, 0x01, - 0x9F, 0x62, 0x48, 0xB8, 0x79, 0xE4, 0xC1, 0x90, 0x73, 0x36, 0x5B, 0x9A, 0x68, 0xD0, 0xD8, 0x26, - 0xB4, 0x2A, 0x8C, 0xF0, 0x71, 0xAA, 0x07, 0xF9, 0xCA, 0x55, 0x37, 0x45, 0x21, 0xBA, 0x7D, 0xFB, - 0x87, 0xEF, 0x92, 0xA9, 0x5B, 0x7E, 0x46, 0x2D, 0xB9, 0x3A, 0xE3, 0xC1, 0xA4, 0x83, 0x71, 0x61, - 0x58, 0x33, 0x39, 0x45, 0x0E, 0xE8, 0x18, 0x06, 0xCB, 0x5B, 0xDB, 0xC1, 0xB5, 0x46, 0xB8, 0x98, - 0xAD, 0x13, 0x7B, 0xB4, 0xC6, 0x57, 0x5D, 0xA5, 0xDA, 0xE2, 0x4D, 0xD7, 0xCC, 0xF3, 0xE3, 0xEB, - 0xDB, 0xEC, 0x55, 0x57, 0x1B, 0xE6, 0x2D, 0xF5, 0x69, 0x57, 0x39, 0xB9, 0xF4, 0xCE, 0x8B, 0x9C, - 0x57, 0x6A, 0xA5, 0xE0, 0xF8, 0x36, 0x59, 0x79, 0x19, 0xBF, 0x4D, 0xFB, 0x32, 0xF3, 0x48, 0x6D, - 0x5C, 0x86, 0x24, 0xC5, 0xAF, 0xCD, 0x89, 0x7D, 0x7E, 0x4A, 0x62, 0xBF, 0xCF, 0x93, 0x58, 0xCE, - 0x43, 0x7A, 0xCA, 0x94, 0x1F, 0xBF, 0x44, 0x85, 0x3D, 0x47, 0xEC, 0xA1, 0x8D, 0x2F, 0x19, 0xF2, - 0xE7, 0x31, 0x5C, 0x49, 0x31, 0xF9, 0x73, 0x3B, 0x0E, 0xFD, 0xAE, 0xDE, 0x19, 0x62, 0x83, 0x78, - 0x47, 0x94, 0xBC, 0xC6, 0x00, 0x6C, 0x3F, 0x70, 0x42, 0xA6, 0x2E, 0x71, 0xF0, 0xE0, 0xF2, 0x32, - 0x2B, 0xD5, 0x47, 0x27, 0x22, 0x04, 0x43, 0x1D, 0x85, 0x4C, 0xEB, 0x12, 0xB0, 0x2F, 0xAC, 0xF2, - 0xD7, 0x38, 0xB9, 0x35, 0xD1, 0x73, 0xEA, 0xC6, 0x5E, 0xB5, 0xA2, 0x6B, 0xD2, 0xE9, 0x26, 0x43, - 0x89, 0x19, 0xAC, 0x0D, 0x43, 0x35, 0x4B, 0x06, 0x87, 0x67, 0x76, 0x18, 0x2C, 0x93, 0x05, 0x96, - 0x60, 0x36, 0xD5, 0xB6, 0xBC, 0x82, 0xCF, 0x79, 0x05, 0xBF, 0xEB, 0xC9, 0x8B, 0x6B, 0x1A, 0x47, - 0xFE, 0xEA, 0x0C, 0x13, 0xF7, 0xAE, 0x41, 0xAA, 0x4B, 0x2F, 0x72, 0xDA, 0xD5, 0x99, 0x4C, 0xC3, - 0x9B, 0xC5, 0x47, 0x6D, 0xD3, 0x92, 0x21, 0x71, 0x2A, 0x12, 0xC2, 0x35, 0xA6, 0x6E, 0x88, 0x1C, - 0x8A, 0x31, 0xC4, 0x89, 0x2D, 0x4A, 0x22, 0x57, 0x01, 0x91, 0x08, 0x10, 0xC7, 0x08, 0x67, 0xA8, - 0x29, 0xDD, 0x3D, 0x91, 0x7B, 0x34, 0xBD, 0x63, 0x89, 0x10, 0x6F, 0x58, 0x72, 0x6E, 0x75, 0xA6, - 0x34, 0xA9, 0x10, 0xD4, 0x35, 0x2B, 0x10, 0x02, 0xA0, 0x6C, 0xC4, 0x6A, 0x20, 0xD6, 0x15, 0x29, - 0xD0, 0x8B, 0x4F, 0x93, 0x2C, 0x0A, 0x7E, 0xB1, 0x75, 0xC0, 0xB8, 0x27, 0x78, 0xD8, 0xC8, 0x5A, - 0x83, 0xCB, 0x85, 0x04, 0x7C, 0x99, 0xB4, 0xFE, 0xA5, 0xB5, 0x94, 0xB7, 0x1D, 0x24, 0x77, 0x09, - 0x72, 0x32, 0xA0, 0xD8, 0x02, 0xB0, 0x89, 0x39, 0x6B, 0xC7, 0x62, 0x31, 0x62, 0x40, 0xB6, 0x62, - 0xD0, 0x7F, 0xA0, 0x0C, 0x73, 0xEF, 0x28, 0x71, 0x69, 0x76, 0xBF, 0xE6, 0x54, 0xFD, 0x9C, 0xA9, - 0xDA, 0xCB, 0xAB, 0xFA, 0x7B, 0xA6, 0xEA, 0x9A, 0x56, 0xD5, 0x3C, 0xFA, 0xA5, 0x0E, 0x35, 0xBD, - 0x83, 0x28, 0x73, 0x5D, 0x52, 0xE3, 0x73, 0x69, 0x8D, 0xDF, 0xF3, 0x6A, 0xA8, 0xAC, 0x29, 0x2F, - 0xFE, 0x25, 0x8F, 0x13, 0x49, 0x82, 0x06, 0x2F, 0x36, 0xB0, 0xC1, 0x2F, 0xE4, 0x0A, 0x40, 0x6C, - 0xCF, 0x21, 0x63, 0xDF, 0xF3, 0xC3, 0x89, 0x0D, 0xAB, 0x38, 0x16, 0x6B, 0xCE, 0xCC, 0xB0, 0xB6, - 0x52, 0x4F, 0x15, 0x45, 0x0A, 0x58, 0xCF, 0x55, 0x03, 0x91, 0x17, 0x3D, 0x9D, 0xFA, 0x51, 0x19, - 0xB2, 0x46, 0x25, 0x33, 0x33, 0xF0, 0xFD, 0x84, 0x3C, 0xB4, 0x69, 0xF3, 0xE5, 0x26, 0xE3, 0xBD, - 0x2F, 0x3D, 0x44, 0x5F, 0x7A, 0xB5, 0x08, 0x33, 0x5C, 0xFA, 0x01, 0x75, 0x5A, 0x45, 0x4F, 0x9A, - 0xB2, 0x9D, 0x90, 0x99, 0xC9, 0x8A, 0xD2, 0x57, 0xE4, 0xB7, 0xD5, 0xCF, 0xAB, 0xBF, 0xB7, 0xD4, - 0x3C, 0xF2, 0x86, 0xD6, 0xBF, 0x26, 0x1B, 0x4B, 0x99, 0xE3, 0xC3, 0x5C, 0x99, 0x86, 0xEE, 0xDF, - 0x28, 0x31, 0x99, 0x66, 0xC5, 0x3A, 0x26, 0x3E, 0x6E, 0x3A, 0x75, 0xD6, 0x9D, 0x2B, 0x71, 0x80, - 0xFA, 0x13, 0xD6, 0xF7, 0x52, 0xA0, 0x3F, 0x7A, 0xAB, 0xA0, 0x06, 0x22, 0xB1, 0xF8, 0x02, 0xAF, - 0x20, 0x0F, 0x53, 0xFE, 0x85, 0xED, 0x5D, 0x18, 0x27, 0xD8, 0x4C, 0xCD, 0x78, 0x0C, 0xB1, 0x62, - 0x75, 0xB4, 0xE5, 0x0A, 0x01, 0xB3, 0xAA, 0x73, 0x70, 0x75, 0x52, 0xF8, 0xE3, 0x62, 0xEB, 0x7F, - 0x99, 0x81, 0x04, 0x35, 0x80, 0xA5, 0xF6, 0xE0, 0x66, 0xD1, 0xBC, 0x0B, 0x29, 0xDB, 0xA4, 0x3F, - 0x2E, 0x46, 0x37, 0x6E, 0xC8, 0x37, 0x61, 0x16, 0x97, 0x0A, 0xAD, 0xBA, 0xA7, 0x5A, 0xF5, 0x4E, - 0x38, 0xBD, 0xE2, 0xAB, 0xC2, 0x45, 0xF0, 0x9F, 0xBA, 0x1B, 0xCA, 0x2B, 0xF3, 0x12, 0xD2, 0x04, - 0x14, 0x26, 0x3C, 0x9E, 0x58, 0x3E, 0xB6, 0x64, 0xC9, 0x14, 0x18, 0xDB, 0x2B, 0xED, 0xC3, 0xDA, - 0x57, 0x8E, 0x22, 0xDD, 0xEC, 0xD5, 0x9C, 0xF0, 0xF8, 0x66, 0x65, 0x35, 0x47, 0x3C, 0xAE, 0x5D, - 0xE6, 0x8C, 0xAB, 0xF5, 0xAA, 0x38, 0xE4, 0x31, 0xC4, 0xBC, 0x9C, 0xF2, 0xF4, 0x99, 0xB1, 0x42, - 0x77, 0x36, 0x39, 0x70, 0x00, 0x8F, 0xB6, 0xDB, 0xB5, 0xD6, 0xD6, 0xDB, 0x64, 0x6B, 0x4B, 0xA1, - 0xCE, 0x3F, 0x23, 0x0B, 0x58, 0x50, 0xDB, 0x69, 0xD6, 0xCF, 0x1D, 0x90, 0xCE, 0x06, 0xF6, 0xB5, - 0x42, 0x62, 0x83, 0x3D, 0x3C, 0xB8, 0xD1, 0x14, 0xBB, 0x76, 0xE8, 0x00, 0x34, 0x7A, 0x96, 0xD5, - 0xB1, 0xD8, 0x45, 0xC9, 0x8E, 0xE2, 0x99, 0xB3, 0x0F, 0x48, 0x8C, 0xFD, 0xF2, 0xEC, 0xBC, 0xF2, - 0x44, 0x6F, 0xEA, 0x7B, 0xE6, 0x31, 0x68, 0x5D, 0xEF, 0x3C, 0x51, 0xBC, 0x7A, 0x1E, 0xBA, 0x46, - 0x4E, 0xF2, 0xD2, 0xB5, 0x31, 0xA2, 0xF8, 0xA8, 0xE2, 0x8A, 0xB2, 0xB1, 0x48, 0xDC, 0x48, 0x36, - 0x95, 0xC5, 0x5A, 0xAA, 0x95, 0x69, 0xBA, 0x65, 0x2E, 0x55, 0x75, 0xE3, 0x11, 0x7C, 0x7E, 0xAD, - 0xCF, 0x8C, 0x7E, 0x7F, 0x52, 0x47, 0xF1, 0xFD, 0xFF, 0x01, 0x24, 0x65, 0x5A, 0x49, 0xC4, 0x6C, - 0xE7, 0xAF, 0x26, 0x32, 0x46, 0xB5, 0xCC, 0x19, 0xD6, 0x95, 0xB0, 0xB6, 0x43, 0x9C, 0xA8, 0xE3, - 0xF3, 0x59, 0x58, 0x24, 0xBD, 0x5B, 0x7D, 0x71, 0x51, 0x24, 0x59, 0xE9, 0xE4, 0x52, 0x5E, 0xA6, - 0xDD, 0xD8, 0xF4, 0x84, 0x46, 0x37, 0xBE, 0x93, 0x7B, 0xC7, 0x50, 0xB9, 0x60, 0x98, 0x5E, 0xAD, - 0x7F, 0x15, 0xDF, 0xA4, 0xCF, 0xBC, 0x60, 0x05, 0x28, 0x53, 0xF9, 0x4B, 0xF8, 0xB5, 0xB8, 0xE4, - 0xEC, 0x69, 0x6C, 0x7E, 0x0C, 0x98, 0xE9, 0x80, 0x3B, 0x37, 0xC8, 0x0B, 0x48, 0xC2, 0x37, 0xF1, - 0xAC, 0x53, 0x4E, 0x12, 0x82, 0x25, 0xB2, 0x42, 0x16, 0xA5, 0x2A, 0xD9, 0xE3, 0x6D, 0x51, 0x6D, - 0x99, 0x64, 0x6B, 0x99, 0x2F, 0x68, 0x2C, 0x91, 0x55, 0xD2, 0xE5, 0x17, 0xEB, 0x8B, 0xD8, 0x8E, - 0x67, 0x7E, 0xE0, 0xB2, 0x83, 0xF1, 0x2C, 0x50, 0xBA, 0xB8, 0x56, 0x74, 0x9F, 0xBB, 0x50, 0x4E, - 0xD9, 0xDC, 0x15, 0x05, 0x62, 0xD2, 0x84, 0x6A, 0x96, 0x93, 0xCE, 0x2A, 0x8A, 0xE0, 0x09, 0x25, - 0x95, 0xC9, 0x15, 0x61, 0x96, 0x93, 0xBE, 0x74, 0x7E, 0xB6, 0x16, 0x63, 0x3A, 0x3E, 0x13, 0x70, - 0x0C, 0x5E, 0x59, 0x41, 0xC4, 0x14, 0x93, 0x4A, 0x6F, 0x76, 0xC9, 0xA6, 0x69, 0xAA, 0x1E, 0xD9, - 0x51, 0x8C, 0x25, 0xAD, 0xBC, 0x42, 0xD6, 0x51, 0x90, 0x3D, 0xC3, 0xAB, 0x7A, 0xB9, 0x53, 0xB3, - 0x61, 0xF9, 0x5C, 0x92, 0x02, 0x24, 0xBB, 0xE4, 0x8F, 0xB9, 0x4E, 0x98, 0x7A, 0x93, 0xBD, 0x6F, - 0xA0, 0x2C, 0x8C, 0xC6, 0xB0, 0x1A, 0x8C, 0xD9, 0xEF, 0xEE, 0x48, 0x7F, 0xBE, 0x4E, 0x1A, 0x26, - 0x7D, 0xCD, 0x9E, 0x03, 0x94, 0x72, 0xB9, 0xBC, 0xAB, 0xF8, 0xEC, 0x29, 0x81, 0x65, 0xA2, 0x33, - 0x9E, 0xDD, 0xF3, 0x7F, 0xC8, 0x91, 0x44, 0x36, 0xC1, 0x89, 0x10, 0x05, 0x60, 0x8D, 0xD9, 0x7E, - 0x5E, 0x52, 0xD1, 0x39, 0x2E, 0x12, 0x4B, 0x7E, 0x23, 0x2A, 0x4B, 0xC8, 0x60, 0xD3, 0x38, 0x21, - 0x49, 0x43, 0xD7, 0x0C, 0x8A, 0x96, 0x63, 0x40, 0x4C, 0xE0, 0xBD, 0x7C, 0xF0, 0xDC, 0x4B, 0x72, - 0x19, 0x24, 0xDD, 0xAF, 0xDA, 0x2D, 0xCF, 0x26, 0xB9, 0x66, 0xE2, 0x64, 0x31, 0x35, 0xF0, 0xF4, - 0x0A, 0x72, 0xD6, 0x28, 0x78, 0x94, 0x98, 0xA2, 0xBC, 0xC7, 0xE2, 0x0C, 0x83, 0x7A, 0x27, 0xB7, - 0xAE, 0x3A, 0x4A, 0xCA, 0xEA, 0x25, 0x7A, 0x53, 0x52, 0x31, 0xED, 0xF0, 0xFC, 0x8A, 0x99, 0xCE, - 0x2D, 0xAD, 0xAA, 0x77, 0x64, 0xC5, 0x40, 0x18, 0x25, 0xCB, 0x49, 0xC8, 0xCD, 0x7B, 0x2C, 0x1A, - 0xC2, 0xAC, 0x31, 0x5F, 0x89, 0xE7, 0x84, 0xC5, 0x64, 0x77, 0xEA, 0x12, 0xE0, 0x46, 0xBB, 0x75, - 0xAA, 0xE7, 0x55, 0xB8, 0x63, 0x27, 0x59, 0xE5, 0xA2, 0x5D, 0x3B, 0x6D, 0x59, 0x50, 0x79, 0xE7, - 0xCE, 0xA4, 0x1F, 0xBA, 0xEE, 0x3C, 0xE2, 0x0E, 0x5E, 0x43, 0xF2, 0xC9, 0x4E, 0x1E, 0x68, 0xED, - 0x2A, 0x6A, 0xE4, 0x2A, 0x68, 0x9B, 0x79, 0x43, 0x4F, 0x17, 0x4C, 0xC5, 0x4D, 0x3D, 0x49, 0xEC, - 0xEA, 0xC6, 0x9E, 0xBE, 0x66, 0xAE, 0xB9, 0xB9, 0x57, 0x65, 0xC9, 0x3D, 0xCF, 0x0D, 0x3E, 0x6D, - 0xE1, 0x3C, 0xDB, 0x26, 0x9F, 0x24, 0x94, 0x7A, 0x1B, 0x7D, 0xC9, 0x68, 0xF9, 0xA1, 0x9B, 0x7D, - 0x8A, 0x7A, 0xC8, 0xFE, 0x15, 0x7A, 0x52, 0x2F, 0xF5, 0x19, 0x73, 0x6E, 0x5B, 0x82, 0x99, 0xF9, - 0x52, 0xAD, 0xB0, 0xAE, 0x43, 0x6C, 0xE8, 0x1F, 0x36, 0xCB, 0x50, 0xBC, 0x54, 0xB6, 0x1D, 0x4B, - 0x8D, 0xE1, 0xA3, 0x6C, 0x76, 0x4A, 0x3A, 0xF0, 0x90, 0x49, 0x16, 0xA6, 0xEC, 0x5A, 0x4A, 0xB9, - 0x8B, 0xB8, 0xCB, 0x0D, 0x3F, 0xA5, 0x9E, 0xED, 0xFC, 0x87, 0xEF, 0x7A, 0x8B, 0x0B, 0x0B, 0x49, - 0xE2, 0x26, 0xAD, 0x4A, 0xBB, 0xBC, 0xCA, 0xBF, 0xFE, 0x6B, 0xA6, 0x4E, 0x40, 0xA3, 0x69, 0xE0, - 0x31, 0x77, 0x5D, 0xE3, 0x6E, 0x48, 0x23, 0x4C, 0x17, 0xA5, 0x98, 0x62, 0x96, 0xA9, 0x0B, 0x4C, - 0x16, 0x68, 0x4F, 0x5C, 0x86, 0x16, 0x95, 0x4F, 0xEB, 0x9A, 0x59, 0x53, 0xEA, 0x88, 0x15, 0x96, - 0xB4, 0x69, 0x77, 0x74, 0xCD, 0x36, 0xE9, 0x22, 0xFB, 0x8A, 0xDC, 0xD9, 0x21, 0xC1, 0xB9, 0x9B, - 0x60, 0x8A, 0x29, 0xEA, 0xB4, 0x09, 0x1F, 0xD2, 0x58, 0x36, 0xA2, 0x3C, 0x17, 0x59, 0x38, 0x08, - 0xF0, 0x89, 0x23, 0x6D, 0xA1, 0x33, 0xA2, 0x27, 0xB6, 0x67, 0x0F, 0x69, 0x70, 0x81, 0x35, 0x33, - 0xC9, 0xA4, 0x18, 0xFC, 0x9B, 0xD7, 0x51, 0x40, 0xEC, 0x91, 0x3B, 0xF4, 0x76, 0x17, 0x46, 0xF4, - 0x3A, 0x5A, 0x80, 0x0F, 0x37, 0x6F, 0x70, 0xFF, 0xE0, 0xF5, 0x2A, 0xFC, 0x82, 0x7F, 0xF4, 0xC1, - 0x90, 0x89, 0x3F, 0x9C, 0x37, 0xAF, 0xF9, 0xA3, 0x94, 0xD1, 0xFD, 0x84, 0xEE, 0x72, 0x8F, 0xE3, - 0xCA, 0xFF, 0xBE, 0x40, 0x5C, 0x67, 0x77, 0x01, 0x09, 0xF2, 0xE5, 0xFC, 0xDE, 0x68, 0xB4, 0x40, - 0xD8, 0x9B, 0xA9, 0xF0, 0xD5, 0x0F, 0xC6, 0x2B, 0xAC, 0xE2, 0x0A, 0x07, 0x95, 0xF8, 0x62, 0x3B, - 0x93, 0x0B, 0x44, 0x04, 0x2E, 0x72, 0x0C, 0x31, 0xCB, 0xFE, 0x70, 0x88, 0xC9, 0x7D, 0x80, 0x9F, - 0x55, 0x24, 0xBB, 0x1A, 0x05, 0xC9, 0x0F, 0xC6, 0xB7, 0x64, 0xB6, 0x11, 0x8C, 0x35, 0xF1, 0x82, - 0xDB, 0xB0, 0x56, 0x4B, 0x12, 0xE5, 0xF7, 0xF1, 0xE8, 0x26, 0x8A, 0x26, 0x85, 0x09, 0xBC, 0xA4, - 0x7A, 0x22, 0x8F, 0xD7, 0xFB, 0x43, 0x9E, 0xC6, 0x0B, 0x67, 0x61, 0x96, 0x65, 0xAC, 0x95, 0xF5, - 0xCE, 0x62, 0x08, 0x96, 0x9D, 0x49, 0xB6, 0x13, 0x22, 0x6C, 0x6C, 0xE0, 0x8F, 0xD1, 0x8C, 0xC4, - 0xD5, 0x02, 0x1A, 0x4E, 0xC0, 0x9D, 0x60, 0x4C, 0x2E, 0x61, 0xC8, 0x8E, 0xC8, 0x59, 0x47, 0xF6, - 0xFB, 0xBF, 0xF0, 0x2C, 0x73, 0xAE, 0x17, 0xF9, 0x6C, 0xF2, 0x7F, 0x51, 0xBD, 0x23, 0xC1, 0xFD, - 0x56, 0x9A, 0x5F, 0x32, 0x99, 0xAA, 0x5A, 0x97, 0xFB, 0x5A, 0x14, 0x28, 0xB7, 0xC8, 0xDE, 0x9A, - 0xD1, 0x6F, 0xFF, 0x2A, 0xB2, 0x5D, 0x50, 0x43, 0xA9, 0xDC, 0xA8, 0xE3, 0xC6, 0x7A, 0xBA, 0x9E, - 0x4B, 0x69, 0x30, 0xB1, 0x82, 0xAE, 0xA2, 0x52, 0x1F, 0x8B, 0x5A, 0x52, 0x0F, 0x27, 0xCD, 0xC2, - 0x5C, 0x75, 0x27, 0xE9, 0x73, 0x58, 0x68, 0xFF, 0xBF, 0x7C, 0x35, 0x97, 0xB3, 0x0D, 0x79, 0x63, - 0x85, 0xF8, 0x82, 0x46, 0x2E, 0x86, 0xB8, 0x82, 0x82, 0x62, 0x8E, 0x5A, 0x16, 0xE7, 0x83, 0xFE, - 0x81, 0x8A, 0x96, 0xD7, 0x13, 0xCB, 0xBB, 0xB2, 0xF8, 0x15, 0x33, 0x45, 0xCE, 0xE9, 0x44, 0x60, - 0xB7, 0xBD, 0x7B, 0x2E, 0xA9, 0xB8, 0x32, 0x3B, 0x72, 0x08, 0x99, 0x6F, 0x7B, 0xCB, 0x85, 0xB6, - 0x42, 0xDC, 0x0E, 0xED, 0x30, 0xC3, 0x26, 0xBE, 0xA0, 0xEB, 0x83, 0x7F, 0xE2, 0x3B, 0x14, 0x84, - 0x3F, 0xC5, 0x41, 0x1C, 0x71, 0xEB, 0x3A, 0x2C, 0x8C, 0xF0, 0xCB, 0x74, 0x7B, 0xDE, 0xB3, 0x6A, - 0xA2, 0x75, 0x99, 0xFA, 0x5F, 0xBE, 0x7F, 0x4D, 0xD7, 0x73, 0x59, 0x25, 0xF9, 0x22, 0x7B, 0x3D, - 0x0F, 0xA5, 0x6D, 0x8E, 0x4D, 0x61, 0x9D, 0x46, 0x63, 0xCA, 0x57, 0xC2, 0xA3, 0xEC, 0x53, 0x04, - 0xB4, 0x42, 0xB3, 0x15, 0x65, 0x2D, 0x6A, 0x37, 0x9B, 0x90, 0xB2, 0xDA, 0x2B, 0x82, 0x34, 0x5B, - 0x38, 0x1A, 0xF3, 0xB2, 0xD2, 0x64, 0x09, 0x31, 0x81, 0xE5, 0x25, 0xB4, 0x2D, 0xC8, 0x86, 0x53, - 0xC0, 0x00, 0xD3, 0xF4, 0xC6, 0x1C, 0x68, 0x3B, 0x8D, 0x35, 0x22, 0x2D, 0xA5, 0x55, 0x9D, 0x6A, - 0xEA, 0xC8, 0x51, 0x18, 0x4E, 0x45, 0xD4, 0xFB, 0xD1, 0xC1, 0x2B, 0xB6, 0xA1, 0x6E, 0xE6, 0xA3, - 0x4E, 0x94, 0xBE, 0x4A, 0xE3, 0x2D, 0x7B, 0xBE, 0xBE, 0xD8, 0xA4, 0x62, 0x9D, 0xAA, 0x66, 0x95, - 0xD7, 0x2D, 0x31, 0xAD, 0x58, 0xA9, 0xB9, 0x79, 0x7D, 0x36, 0xD6, 0x91, 0x35, 0xE3, 0x59, 0x58, - 0xC8, 0x8C, 0x40, 0xEB, 0x5A, 0xC9, 0x9F, 0x16, 0xE3, 0x9F, 0xC2, 0x62, 0xB0, 0xD1, 0xE7, 0x3E, - 0x86, 0xD5, 0x90, 0xFC, 0xBE, 0x03, 0x98, 0x0E, 0xF1, 0x00, 0x22, 0xCD, 0xB4, 0x2A, 0x6E, 0xEC, - 0xA0, 0x33, 0x57, 0x3D, 0x71, 0x27, 0x62, 0x3C, 0x3A, 0x90, 0x0E, 0xD5, 0x38, 0x3B, 0x1E, 0x3B, - 0x51, 0xF9, 0x78, 0xCD, 0x90, 0xF5, 0xE3, 0xBB, 0x40, 0x8D, 0x91, 0x2A, 0x5B, 0x1C, 0x58, 0xCA, - 0x4F, 0x6C, 0xD2, 0xC8, 0x02, 0x1C, 0xA5, 0xEF, 0x78, 0xEA, 0x4E, 0x18, 0x1C, 0x7D, 0xCC, 0x6B, - 0x8D, 0x99, 0x65, 0xC1, 0xFA, 0x62, 0x89, 0x9A, 0x18, 0x3B, 0xA9, 0x2A, 0xD9, 0x4B, 0x19, 0xE7, - 0xAE, 0x99, 0xFB, 0x25, 0xB1, 0x72, 0x4B, 0xCF, 0x0B, 0xA7, 0xC1, 0x28, 0xC2, 0x64, 0x2F, 0xB8, - 0xE6, 0x6B, 0xAD, 0x22, 0x8A, 0x7F, 0x61, 0xEC, 0xB3, 0xBE, 0x92, 0xA5, 0xF9, 0x25, 0x45, 0x8F, - 0xAF, 0xAE, 0xE2, 0x31, 0xEA, 0x9F, 0x6C, 0xC6, 0xCD, 0xAE, 0x23, 0xBA, 0x41, 0x98, 0x47, 0x59, - 0x2B, 0x12, 0xF4, 0x42, 0xA6, 0xE0, 0x69, 0x43, 0xED, 0x4E, 0x7C, 0x32, 0xDB, 0xB9, 0x09, 0xE8, - 0x35, 0x3E, 0x5F, 0x1C, 0x57, 0x8B, 0xEF, 0x73, 0x26, 0xB4, 0x96, 0x97, 0x77, 0xF2, 0x7A, 0x3F, - 0x5E, 0x0B, 0x49, 0x87, 0x4E, 0xE9, 0xD8, 0xAF, 0xDB, 0x4F, 0x79, 0xF9, 0x5A, 0x71, 0xD3, 0x28, - 0xC5, 0xAA, 0x64, 0x6C, 0xF5, 0x32, 0xF9, 0x5A, 0xD3, 0x8A, 0x98, 0xB3, 0x35, 0x1D, 0x5F, 0xF1, - 0x72, 0x25, 0x59, 0x06, 0xA6, 0xD7, 0x14, 0x77, 0x4A, 0x34, 0x9C, 0xAA, 0x99, 0x84, 0xE7, 0xA5, - 0xDF, 0x2F, 0xF2, 0xCE, 0xCC, 0x33, 0xFD, 0x1E, 0x6F, 0xEA, 0x40, 0x7F, 0x33, 0xC6, 0x42, 0x71, - 0x78, 0x9E, 0x99, 0x82, 0x65, 0xCD, 0xD2, 0x77, 0xF0, 0x64, 0xBB, 0x6B, 0x40, 0x6E, 0x7C, 0xF3, - 0xB7, 0xBA, 0x66, 0x7E, 0xCF, 0x28, 0x24, 0x6B, 0x4B, 0x6B, 0xA7, 0xF2, 0x4C, 0x5B, 0x38, 0xD5, - 0x26, 0x8C, 0x94, 0x4F, 0xB0, 0x52, 0xDB, 0x57, 0x57, 0xCF, 0xE9, 0x35, 0xCC, 0xA8, 0x37, 0x3C, - 0x5D, 0x77, 0x12, 0x56, 0x54, 0xB8, 0xDC, 0x54, 0x76, 0x4F, 0x76, 0xB4, 0x2B, 0xA4, 0x3C, 0x73, - 0xB6, 0xA6, 0xF1, 0x52, 0x2E, 0x70, 0xFC, 0xB5, 0x3B, 0x97, 0xF4, 0xDF, 0x1C, 0x53, 0xC3, 0x8C, - 0xDF, 0x9C, 0x51, 0xC3, 0xD5, 0x68, 0x98, 0xEB, 0x87, 0x01, 0x66, 0xA3, 0x6F, 0x93, 0xF8, 0xD7, - 0x0F, 0x30, 0xBD, 0x8F, 0x68, 0xA0, 0x0A, 0x96, 0x61, 0xC9, 0x82, 0x33, 0x0B, 0xD3, 0x06, 0xEB, - 0xC2, 0x13, 0x67, 0xD7, 0x01, 0xE5, 0x87, 0x11, 0x6D, 0x7E, 0x28, 0x51, 0x07, 0xD0, 0xBE, 0xF2, - 0x83, 0x08, 0x00, 0xD9, 0xFF, 0xF3, 0x01, 0x73, 0x92, 0x9C, 0x8F, 0x8A, 0x13, 0x9C, 0x4B, 0xAF, - 0x44, 0x68, 0xF2, 0x88, 0xD3, 0x51, 0xA7, 0xDD, 0x3C, 0xA1, 0xC1, 0x80, 0xDF, 0x8F, 0xE5, 0x65, - 0x9D, 0x11, 0x4B, 0x5D, 0x4D, 0x56, 0x09, 0xFF, 0x33, 0xF2, 0x23, 0xDC, 0x07, 0xFC, 0x33, 0x1E, - 0xED, 0x4B, 0x59, 0xBD, 0x05, 0xDA, 0xB7, 0x76, 0x20, 0x1D, 0xD2, 0x9D, 0xD8, 0xD1, 0x4D, 0x27, - 0xF0, 0xA7, 0xC0, 0x8D, 0x40, 0xBB, 0x94, 0x82, 0x4C, 0xA5, 0xBC, 0xE8, 0x9A, 0x63, 0x6C, 0x80, - 0xC3, 0x41, 0xF7, 0xBF, 0x85, 0x6A, 0x52, 0x87, 0x67, 0x5B, 0x4F, 0xB6, 0x84, 0x05, 0xCB, 0x6F, - 0xF0, 0x65, 0x12, 0x2B, 0xF3, 0xC0, 0x52, 0x3E, 0x9D, 0xD6, 0x59, 0x9A, 0xC0, 0xBD, 0x4D, 0xEE, - 0xF0, 0x0A, 0x96, 0x37, 0xE4, 0x8A, 0x0E, 0xDE, 0x27, 0xD3, 0xEE, 0x7B, 0xE8, 0xA0, 0x71, 0xCB, - 0xF0, 0x68, 0xAE, 0xA6, 0x1D, 0xAA, 0x20, 0xCB, 0xE8, 0xF2, 0xCC, 0xEC, 0x24, 0x49, 0xCD, 0x5E, - 0x26, 0xC8, 0xF8, 0xE0, 0x68, 0x1E, 0x43, 0x9D, 0x7D, 0x4B, 0xCC, 0x39, 0x26, 0x56, 0xE7, 0x47, - 0x13, 0x6F, 0xEF, 0x8F, 0x9C, 0xBA, 0x5C, 0x4B, 0xF2, 0x90, 0x35, 0xBE, 0x91, 0x30, 0xDE, 0xD9, - 0xC0, 0xA4, 0xA3, 0x22, 0x95, 0x47, 0x43, 0x23, 0xA4, 0x7B, 0x88, 0x40, 0x60, 0x4D, 0xD1, 0x46, - 0x03, 0x91, 0x75, 0xF3, 0x2D, 0xCE, 0xA0, 0x8A, 0x6B, 0x93, 0xDE, 0xF3, 0xBF, 0x18, 0x54, 0xCA, - 0x06, 0xCA, 0x4F, 0xC8, 0x12, 0x8C, 0x6A, 0x2C, 0xAA, 0x71, 0x1B, 0x90, 0x1F, 0xE9, 0xE5, 0x40, - 0xC4, 0x6D, 0x4B, 0x8A, 0x31, 0xBB, 0xA2, 0xFC, 0x82, 0xCE, 0xF6, 0xFA, 0x96, 0x69, 0x26, 0x87, - 0xFA, 0x3C, 0x7D, 0x6A, 0x49, 0x93, 0xAA, 0xA4, 0x75, 0x4D, 0x9A, 0x64, 0x4A, 0xC8, 0x5A, 0xDC, - 0xA4, 0xBC, 0x14, 0xAE, 0x43, 0xB9, 0xB8, 0x62, 0x93, 0xA6, 0xCE, 0xA4, 0xA8, 0x31, 0x9F, 0x9C, - 0x1A, 0x8D, 0x99, 0x3A, 0x39, 0x79, 0x17, 0x0B, 0x9A, 0x93, 0x0B, 0x93, 0xE8, 0x9F, 0x63, 0x6E, - 0x50, 0xD7, 0xEA, 0x76, 0x2D, 0x53, 0x8B, 0x9C, 0x9B, 0xC1, 0xE4, 0x10, 0x96, 0x91, 0x81, 0x47, - 0xA3, 0x6C, 0xAB, 0x44, 0xC1, 0xC1, 0x87, 0xFD, 0xB3, 0xE2, 0x26, 0x49, 0x99, 0xD7, 0x8F, 0xCE, - 0x54, 0x16, 0x63, 0xEC, 0x85, 0xCD, 0x93, 0x32, 0xA2, 0x97, 0xC3, 0xCB, 0xFC, 0x43, 0x01, 0x5E, - 0xF6, 0x66, 0x71, 0xCE, 0xAA, 0x37, 0xAC, 0x05, 0xC2, 0xE3, 0xB7, 0x3B, 0xF7, 0xDA, 0x3D, 0xE5, - 0x00, 0x95, 0x1C, 0x48, 0xD7, 0xF9, 0xB7, 0x5D, 0x09, 0xE6, 0xEB, 0x02, 0xF9, 0xD3, 0x9F, 0x48, - 0x52, 0xF6, 0xC7, 0xDD, 0x7E, 0x5F, 0x77, 0x9E, 0x35, 0x7F, 0x4F, 0x26, 0x98, 0xE7, 0xEE, 0xA1, - 0xB0, 0xE5, 0x7A, 0xE8, 0xD1, 0xB1, 0x6E, 0x4B, 0x4E, 0x14, 0x89, 0xB5, 0xA4, 0x45, 0x20, 0x40, - 0xD3, 0x70, 0x6D, 0x20, 0x79, 0x5C, 0xF1, 0xA1, 0x14, 0x2B, 0xD3, 0xBC, 0x27, 0xD6, 0x6F, 0xA7, - 0xF4, 0x2E, 0x4E, 0x15, 0xA5, 0xF4, 0xB3, 0x9E, 0x37, 0xE5, 0x0F, 0x49, 0x62, 0x6A, 0x68, 0xEB, - 0xA2, 0x26, 0x5E, 0x16, 0x0A, 0xA0, 0xAB, 0xF2, 0x49, 0x38, 0xE4, 0x81, 0x15, 0x0B, 0xF1, 0x2B, - 0x1F, 0xFB, 0x82, 0x20, 0x94, 0xE0, 0x33, 0x32, 0xBF, 0xBA, 0xEF, 0x5C, 0x36, 0x31, 0xE0, 0xC5, - 0x6F, 0x3A, 0x9E, 0x44, 0xF7, 0xB2, 0xDA, 0x1A, 0x5C, 0x67, 0x91, 0x5B, 0x6F, 0x5F, 0xE3, 0x3B, - 0x2F, 0x00, 0x51, 0x30, 0x91, 0x4B, 0x1F, 0xF4, 0xC8, 0xC3, 0x6B, 0xCD, 0x30, 0x91, 0xC2, 0x1C, - 0x2A, 0x9A, 0xD4, 0xD2, 0xDE, 0x61, 0x42, 0xFD, 0x10, 0x8F, 0x6E, 0xE0, 0x8E, 0x8F, 0x74, 0x62, - 0x04, 0xCB, 0x51, 0x70, 0x5E, 0xC8, 0x60, 0x1A, 0x04, 0x38, 0xA5, 0xB3, 0xD6, 0x60, 0xCF, 0xB3, - 0xED, 0x99, 0xB3, 0x5F, 0xC3, 0x54, 0xE5, 0x46, 0xA1, 0x98, 0xB8, 0x9A, 0x69, 0x57, 0x81, 0x22, - 0x49, 0xA8, 0xF3, 0xF4, 0x48, 0x62, 0x7E, 0x79, 0x57, 0x06, 0x48, 0x97, 0x08, 0x6D, 0x5C, 0x3E, - 0x68, 0x25, 0x71, 0x40, 0x35, 0x14, 0x2A, 0x7D, 0xA0, 0x5A, 0xB6, 0xF3, 0x7D, 0xA9, 0x13, 0x74, - 0x3B, 0x90, 0xC3, 0x42, 0x06, 0xB4, 0x8D, 0xB5, 0x63, 0x32, 0x68, 0x00, 0x2A, 0x03, 0xB2, 0x9E, - 0x6A, 0xC7, 0x1D, 0xA2, 0xD5, 0xD6, 0xD5, 0x1B, 0xDF, 0x41, 0x89, 0xEF, 0xAD, 0xC8, 0x7B, 0x34, - 0x71, 0x39, 0xDB, 0x40, 0x00, 0x78, 0xB1, 0x27, 0x93, 0x20, 0x5B, 0x32, 0x3E, 0xB1, 0xA2, 0x94, - 0xA7, 0xB7, 0x39, 0x24, 0x7A, 0xC6, 0x47, 0xAF, 0x32, 0x4C, 0x99, 0x9E, 0xBE, 0x62, 0x95, 0x00, - 0xB9, 0x69, 0x6C, 0x2A, 0x4F, 0x37, 0xE5, 0x90, 0x5C, 0xCA, 0xEE, 0x39, 0xB4, 0xF6, 0x11, 0x8E, - 0xA9, 0xBA, 0x60, 0x0B, 0xD5, 0x29, 0x07, 0x3E, 0xB9, 0x2F, 0x52, 0x3A, 0x82, 0x04, 0xA3, 0xC9, - 0x63, 0x3F, 0x04, 0xA6, 0x98, 0x90, 0x85, 0x5F, 0xEC, 0x68, 0xE6, 0x38, 0xA1, 0xF1, 0x0B, 0xAF, - 0xB1, 0x78, 0xAD, 0xFE, 0xAD, 0xB4, 0x2F, 0x97, 0xA6, 0xF4, 0x00, 0xAA, 0x06, 0xCF, 0x76, 0xFC, - 0x4E, 0x3F, 0x5E, 0x1E, 0x9D, 0x5E, 0x1C, 0x9E, 0x9F, 0xC2, 0x1A, 0xB5, 0xB6, 0x39, 0x3A, 0xF5, - 0x71, 0x2B, 0x57, 0x99, 0x53, 0xA4, 0xEC, 0xD1, 0xEE, 0xED, 0x7B, 0x1A, 0x29, 0x46, 0x47, 0x9D, - 0x61, 0x4B, 0xED, 0x92, 0xB6, 0x9F, 0xA8, 0x9A, 0x37, 0x65, 0x4B, 0x33, 0xA7, 0x65, 0xFD, 0xC3, - 0xF3, 0x5F, 0x0E, 0xCF, 0x1B, 0xB4, 0x8B, 0xDB, 0x11, 0x02, 0xFD, 0xCD, 0x7D, 0x00, 0x96, 0xBB, - 0xC4, 0xBE, 0x05, 0x27, 0x96, 0x1F, 0x11, 0x3F, 0xB7, 0xB6, 0xEE, 0x7F, 0x3A, 0x3F, 0x3F, 0x3C, - 0x35, 0xF6, 0x60, 0x6E, 0x23, 0x93, 0x41, 0x0C, 0x53, 0xC9, 0x74, 0x82, 0xF6, 0x9C, 0xA7, 0x63, - 0x7C, 0xE2, 0xB6, 0xC9, 0xD3, 0x94, 0x4E, 0x47, 0xF7, 0xFA, 0x59, 0x34, 0x1F, 0x30, 0x7A, 0xDB, - 0x62, 0x77, 0x5D, 0x14, 0x39, 0xEC, 0x14, 0x22, 0x32, 0x73, 0xA3, 0xBE, 0xD2, 0x85, 0xD8, 0xCF, - 0xF2, 0x56, 0x68, 0xE6, 0x81, 0xA6, 0x02, 0x49, 0xC3, 0x4D, 0xA4, 0x8F, 0x37, 0x89, 0x4E, 0x3B, - 0xBA, 0xD2, 0x2D, 0xD6, 0xF3, 0x71, 0x27, 0x7E, 0x7C, 0xF7, 0x1B, 0x7D, 0x94, 0x4A, 0xE6, 0x2E, - 0xA3, 0xFC, 0xD9, 0x9E, 0x82, 0xF6, 0xBF, 0x17, 0x4F, 0x83, 0xE1, 0x56, 0xD4, 0xB5, 0xD4, 0xBC, - 0x9F, 0x6E, 0x8C, 0xEA, 0xC6, 0x18, 0x5C, 0x05, 0x55, 0x73, 0x1F, 0xDB, 0x51, 0x50, 0xA9, 0x19, - 0xDD, 0x04, 0x8D, 0x21, 0x93, 0x93, 0x30, 0xE4, 0x78, 0xE5, 0x11, 0x27, 0x85, 0xBD, 0xC5, 0xF7, - 0x46, 0xD0, 0x9E, 0x76, 0x5B, 0xB9, 0x6F, 0x3F, 0x1A, 0x59, 0x59, 0x32, 0x5A, 0xEA, 0x18, 0xDB, - 0xE1, 0xF9, 0xF9, 0x47, 0x75, 0x16, 0x7A, 0xA4, 0xA1, 0x55, 0x66, 0xF2, 0x99, 0x35, 0x88, 0xC5, - 0xA0, 0x6A, 0xBD, 0xF2, 0x14, 0xAB, 0xBA, 0x30, 0xF4, 0x23, 0x3B, 0xA6, 0x2E, 0x1E, 0x3A, 0x14, - 0x7B, 0x72, 0xF1, 0x5E, 0x91, 0xD1, 0xD1, 0xCA, 0x93, 0x53, 0xF5, 0xE1, 0xA9, 0x51, 0xE1, 0x9B, - 0x84, 0xFA, 0x83, 0x87, 0x55, 0x4D, 0xB8, 0x86, 0x4C, 0x3A, 0xBA, 0xD0, 0xC9, 0xEC, 0x66, 0x36, - 0x1A, 0xB5, 0x77, 0x55, 0x95, 0x64, 0x11, 0xEF, 0xDD, 0x5B, 0xEA, 0x11, 0x1B, 0x1F, 0xE8, 0x0D, - 0x16, 0x42, 0x91, 0xDF, 0x0C, 0x85, 0x79, 0x8F, 0x13, 0x15, 0x74, 0xB3, 0x17, 0xB9, 0xD7, 0x3C, - 0xCB, 0x18, 0x46, 0xF5, 0x31, 0x13, 0x21, 0x56, 0x98, 0xF8, 0x2D, 0x0D, 0xD8, 0x06, 0x4F, 0x8A, - 0x1C, 0x1C, 0x74, 0x9C, 0xF8, 0x1F, 0xDB, 0x4E, 0xB7, 0xA5, 0x20, 0xF5, 0x18, 0xD7, 0x11, 0xDA, - 0x0A, 0x7C, 0x53, 0x6B, 0x11, 0x69, 0x1E, 0x7A, 0x40, 0x4A, 0x5D, 0xAD, 0xC7, 0x18, 0x93, 0x8A, - 0xD0, 0x7C, 0xF5, 0x35, 0xAE, 0xB0, 0xB3, 0xFF, 0xF1, 0xE3, 0xF9, 0xC1, 0xD1, 0xE9, 0xDE, 0xC5, - 0x21, 0xB8, 0x7F, 0x67, 0x9F, 0x2E, 0x2E, 0x2F, 0x3E, 0x9F, 0xE1, 0xAF, 0xBF, 0xEC, 0x1D, 0x1F, - 0x1D, 0x5C, 0x7E, 0x3A, 0xFD, 0xCB, 0xE9, 0xC7, 0x5F, 0x4F, 0xD3, 0x2D, 0x7B, 0xC7, 0x0E, 0x6F, - 0xA4, 0xFB, 0xF0, 0x89, 0x79, 0xC4, 0x80, 0x7A, 0xC3, 0x77, 0x87, 0x0E, 0xDC, 0xB1, 0x3D, 0x32, - 0x94, 0x70, 0x53, 0xF5, 0xF1, 0xFA, 0x98, 0xB2, 0x57, 0x36, 0xF5, 0xB3, 0x4B, 0x30, 0x1E, 0xE0, - 0x6D, 0x45, 0xF8, 0x98, 0x5B, 0x22, 0x17, 0xFE, 0x66, 0x12, 0xDE, 0xB4, 0x46, 0xF5, 0x22, 0x77, - 0x37, 0x36, 0x9B, 0xAE, 0x86, 0x4C, 0xF0, 0x20, 0xE3, 0x69, 0x98, 0x58, 0xE5, 0x81, 0xED, 0x11, - 0x8A, 0x02, 0x61, 0x26, 0xD3, 0xF5, 0xA0, 0xF3, 0x5D, 0x87, 0xDD, 0x99, 0x0F, 0x45, 0x95, 0x3D, - 0xC2, 0xBF, 0xF1, 0x5A, 0xF8, 0x2C, 0x2D, 0xCB, 0x72, 0xC7, 0x4F, 0x39, 0xC3, 0x36, 0x59, 0x69, - 0x63, 0x34, 0x6D, 0x9B, 0x75, 0x53, 0x47, 0x3D, 0xC9, 0x93, 0x8C, 0x6F, 0x22, 0x78, 0xDD, 0xF4, - 0xAA, 0x97, 0x84, 0x43, 0xC7, 0x1D, 0xBA, 0x51, 0xDA, 0x4D, 0x78, 0x44, 0x9D, 0x77, 0x61, 0x14, - 0x01, 0x54, 0xB1, 0xB1, 0xBB, 0x02, 0x46, 0x79, 0x2D, 0x2F, 0x17, 0xBD, 0x2B, 0x23, 0x93, 0x43, - 0x2C, 0x0B, 0x2B, 0x0B, 0x4B, 0x69, 0x07, 0x2E, 0x2F, 0xB3, 0xB7, 0xAE, 0x46, 0x23, 0x32, 0xF4, - 0x7D, 0xA7, 0x02, 0x34, 0x01, 0xE8, 0xB4, 0x9F, 0x6B, 0x83, 0x77, 0x90, 0xB8, 0xD4, 0xAE, 0x22, - 0x04, 0xF1, 0xCE, 0x4B, 0x23, 0x65, 0x15, 0xA7, 0xDD, 0x6C, 0xC1, 0x06, 0x6A, 0x84, 0x71, 0x3C, - 0xA1, 0xA2, 0x02, 0x2C, 0x6D, 0x82, 0x7A, 0xB4, 0x06, 0xDE, 0x3D, 0x2A, 0xD1, 0xC4, 0x0F, 0x43, - 0x17, 0xA3, 0x7D, 0xB9, 0x56, 0xE0, 0x38, 0x8D, 0xF5, 0x25, 0x1D, 0x92, 0xE9, 0x87, 0x93, 0x93, - 0xCE, 0x98, 0xFF, 0x4B, 0xBF, 0x11, 0xD3, 0xC7, 0x15, 0xD3, 0xC7, 0x93, 0x93, 0x7E, 0xBF, 0x13, - 0xB2, 0x7F, 0x0A, 0x38, 0x31, 0x7C, 0x06, 0x04, 0x2B, 0xE9, 0xE7, 0x17, 0x46, 0x3D, 0x61, 0x77, - 0xD4, 0x66, 0x97, 0xDC, 0xFF, 0xC5, 0x10, 0x68, 0xCF, 0xEF, 0x90, 0x75, 0x18, 0x6D, 0xDB, 0xD6, - 0xDA, 0xDA, 0xFA, 0x4B, 0x96, 0x5D, 0x90, 0xC9, 0xAF, 0x93, 0xC6, 0x5F, 0xA7, 0x23, 0xFE, 0x0D, - 0xE9, 0xCD, 0x83, 0xF0, 0x47, 0x1C, 0x7F, 0x16, 0xCB, 0x78, 0x01, 0x23, 0xAD, 0x47, 0xEC, 0x11, - 0xE6, 0x5C, 0x74, 0x90, 0x11, 0x62, 0x6D, 0x90, 0xDE, 0x46, 0xA7, 0x67, 0xAD, 0x6F, 0x1B, 0x58, - 0x49, 0x6D, 0xD2, 0x1B, 0xB2, 0x36, 0x67, 0x4E, 0x7A, 0x8C, 0x99, 0xB5, 0x94, 0x99, 0x95, 0xAE, - 0xB5, 0xB1, 0xD2, 0xED, 0xAE, 0x58, 0x1B, 0x9D, 0xEE, 0x66, 0xCF, 0xC4, 0x8E, 0xD9, 0xB2, 0xBD, - 0xC1, 0x2B, 0x0C, 0x73, 0x62, 0xED, 0x25, 0xF2, 0x74, 0x4D, 0xEF, 0x68, 0xC0, 0xF9, 0xE9, 0x76, - 0x91, 0x9B, 0xAD, 0xAD, 0xED, 0xED, 0x1E, 0x59, 0x3C, 0xE0, 0x9A, 0x85, 0x55, 0xF8, 0x6F, 0x4B, - 0x09, 0x8F, 0xA9, 0x3B, 0xEB, 0xD1, 0xA1, 0x1D, 0x81, 0xDD, 0xEC, 0xBB, 0x43, 0x4F, 0xF5, 0x1E, - 0xD4, 0xB1, 0x6B, 0xA5, 0x86, 0x23, 0xB5, 0x52, 0x49, 0x31, 0xF7, 0xBB, 0xF0, 0xDA, 0xC0, 0x9E, - 0x64, 0xDC, 0xDA, 0x28, 0x3A, 0x8C, 0xEC, 0x67, 0xE7, 0x58, 0x78, 0xB7, 0x00, 0x8C, 0x17, 0x13, - 0x05, 0x37, 0x1F, 0xE9, 0x4D, 0x22, 0x95, 0x09, 0x35, 0x6C, 0x29, 0xE9, 0xD4, 0x95, 0x15, 0x44, - 0x84, 0x69, 0x42, 0xD3, 0x7E, 0x06, 0x6B, 0x8D, 0x73, 0x26, 0xDF, 0x72, 0x60, 0x6F, 0x78, 0x87, - 0x37, 0x94, 0x5B, 0x70, 0x9E, 0x5D, 0x94, 0x25, 0xDE, 0x10, 0x44, 0x63, 0x32, 0x24, 0x04, 0x3A, - 0xFA, 0x76, 0x9C, 0xAC, 0xC7, 0xDC, 0xD0, 0xE2, 0x9A, 0x4A, 0x9A, 0xE5, 0x92, 0x6F, 0x39, 0xFD, - 0xBA, 0xCB, 0xEE, 0xA6, 0xE0, 0x13, 0x92, 0xB9, 0xE5, 0x9B, 0x4B, 0xB0, 0x20, 0x5B, 0x5D, 0xCD, - 0x8E, 0x78, 0xF9, 0x99, 0xEF, 0xE6, 0x73, 0x35, 0xC7, 0x2B, 0xC5, 0x1C, 0xF0, 0x24, 0x23, 0xEC, - 0x48, 0x89, 0x5F, 0x52, 0x62, 0x07, 0xAD, 0x20, 0x5E, 0x6F, 0x10, 0xDF, 0xFD, 0x4E, 0x1D, 0x06, - 0xD6, 0x4D, 0xE0, 0x7C, 0x12, 0xA1, 0x37, 0x0A, 0x16, 0x61, 0x5F, 0x54, 0x14, 0x12, 0x6A, 0x7E, - 0xF3, 0xDB, 0x92, 0x71, 0xA4, 0x13, 0x5F, 0x5A, 0x6D, 0x65, 0x37, 0x31, 0x55, 0xFC, 0x44, 0x59, - 0xB9, 0x2D, 0xCE, 0x12, 0x15, 0xF3, 0xE4, 0xF8, 0xC5, 0x84, 0x12, 0x32, 0x27, 0x27, 0x72, 0xD4, - 0xDF, 0x3B, 0x17, 0xA6, 0x68, 0x98, 0x5E, 0x94, 0x29, 0x37, 0x9D, 0x98, 0xD9, 0xD5, 0xA9, 0x8F, - 0xD7, 0x8B, 0x6C, 0x02, 0x82, 0xDE, 0x58, 0xE9, 0xEA, 0x3B, 0xFF, 0xB3, 0x8A, 0xFE, 0xF2, 0xF4, - 0xE3, 0xE5, 0xC1, 0xE1, 0xFE, 0xD1, 0xC9, 0xDE, 0xB1, 0xD6, 0x0B, 0x21, 0x85, 0x09, 0xC8, 0xC1, - 0x66, 0x25, 0xFC, 0x68, 0xE2, 0x96, 0xD5, 0x81, 0x2F, 0xAE, 0x38, 0x84, 0x51, 0x64, 0xE9, 0x80, - 0x92, 0x05, 0x2D, 0x83, 0xC4, 0x72, 0xFC, 0x73, 0x22, 0x2F, 0x01, 0x00, 0x22, 0x93, 0x82, 0xEC, - 0x0C, 0xAE, 0x55, 0x4C, 0x6C, 0x39, 0x45, 0xB2, 0x4A, 0x36, 0x61, 0x0A, 0x60, 0x29, 0x03, 0x62, - 0x1A, 0xAB, 0x64, 0x6D, 0x13, 0x73, 0xE5, 0x2C, 0x69, 0x77, 0xDE, 0x95, 0x91, 0x6C, 0xF6, 0x6B, - 0x4C, 0x64, 0xFF, 0x8C, 0xDD, 0x21, 0xBF, 0x83, 0xF9, 0x60, 0x5A, 0x3D, 0x69, 0x43, 0x14, 0x47, - 0xA3, 0x3A, 0x40, 0xD9, 0xF8, 0xCC, 0x1D, 0x7E, 0x1B, 0x38, 0x3A, 0x73, 0x4B, 0xD7, 0x93, 0xB1, - 0xA9, 0xCC, 0xD0, 0xF3, 0x1B, 0x9A, 0x15, 0x07, 0x66, 0x3A, 0x22, 0x15, 0x0D, 0xC9, 0x19, 0x8E, - 0xFA, 0xD0, 0xA8, 0x3B, 0x00, 0x73, 0x87, 0x9F, 0x59, 0x4F, 0x15, 0xD1, 0xB0, 0x38, 0x66, 0x01, - 0x60, 0x40, 0x6C, 0x56, 0xD2, 0xBA, 0x4A, 0xF7, 0xC8, 0xFA, 0xA5, 0x2A, 0x98, 0xA2, 0x4D, 0x5D, - 0xAE, 0x0F, 0x2B, 0x8F, 0xA4, 0x10, 0x97, 0x27, 0x27, 0x97, 0x07, 0x7B, 0xFD, 0x0F, 0x9A, 0x5A, - 0x88, 0x68, 0xAA, 0xD4, 0x6C, 0x89, 0xBB, 0x72, 0x2B, 0xFA, 0x5D, 0xCA, 0x54, 0x07, 0x84, 0x29, - 0x47, 0x48, 0xCC, 0xCE, 0x94, 0x76, 0x58, 0x4E, 0xD7, 0xCA, 0xF5, 0xBB, 0x5F, 0x25, 0x63, 0x9A, - 0xE9, 0xDD, 0x67, 0xD6, 0x59, 0xF9, 0x7D, 0xD5, 0x4B, 0xFA, 0x2A, 0xF6, 0x8E, 0xE7, 0xDE, 0x57, - 0x60, 0xDE, 0x9F, 0x59, 0x77, 0x3D, 0x9B, 0xB9, 0x4F, 0x12, 0x4F, 0x95, 0x29, 0x50, 0x6E, 0x50, - 0x2F, 0x6D, 0x50, 0x76, 0x0E, 0xFC, 0x47, 0x9F, 0xA0, 0xB8, 0x52, 0xA6, 0x1B, 0x38, 0x73, 0xD5, - 0xC9, 0x9D, 0x12, 0x31, 0xA5, 0x06, 0xFC, 0x87, 0x09, 0x40, 0x58, 0x50, 0xF2, 0x78, 0x16, 0xB4, - 0xE2, 0x68, 0x24, 0x3F, 0x8D, 0x67, 0x51, 0x3F, 0xF5, 0x92, 0x7E, 0x22, 0x8F, 0xB3, 0x2E, 0xE1, - 0x06, 0xE2, 0x19, 0x75, 0xD6, 0x73, 0x33, 0x9D, 0xFF, 0xD3, 0xAC, 0xA6, 0xD8, 0xD0, 0x52, 0x4E, - 0x86, 0x0C, 0x08, 0xF8, 0xE1, 0x90, 0xA1, 0x20, 0xC9, 0x1D, 0xB6, 0xBD, 0xA4, 0x25, 0x0E, 0x30, - 0x74, 0x07, 0x3F, 0xF3, 0x49, 0x37, 0xE6, 0xA5, 0x1D, 0x76, 0xDC, 0xD4, 0x4D, 0x2F, 0xD8, 0xB7, - 0x89, 0x3F, 0x8D, 0xF0, 0x0F, 0x5B, 0xEC, 0xDA, 0x03, 0x50, 0xDF, 0x57, 0xF7, 0xE0, 0x71, 0x43, - 0xF9, 0x0A, 0xA4, 0x35, 0xA6, 0x64, 0x41, 0x1B, 0x32, 0x0B, 0x6D, 0x42, 0xA3, 0x81, 0x1C, 0x32, - 0xCC, 0xF8, 0x66, 0x7C, 0x48, 0x7C, 0xB5, 0x4D, 0x2A, 0x63, 0xDE, 0xAF, 0x17, 0x9B, 0x97, 0xD2, - 0x41, 0x23, 0xBF, 0x59, 0x61, 0xD0, 0xB8, 0xEA, 0x2A, 0xB7, 0x64, 0x1C, 0xD6, 0xA9, 0x86, 0xA5, - 0xDF, 0x96, 0x24, 0x31, 0xEB, 0xA7, 0xB5, 0x32, 0x1B, 0xE6, 0xB3, 0xAE, 0x19, 0xD9, 0xBC, 0x94, - 0xD6, 0x3C, 0xB0, 0x6E, 0x9B, 0x11, 0xDB, 0x5C, 0x91, 0xC5, 0xAE, 0xFB, 0x9C, 0x51, 0xF6, 0x3F, - 0x9F, 0xBC, 0xFD, 0x78, 0xCC, 0x90, 0xEA, 0x57, 0x56, 0x46, 0xBE, 0x37, 0x64, 0x59, 0x9A, 0x0E, - 0xE8, 0x30, 0xA0, 0xFA, 0xFE, 0x48, 0xA6, 0x27, 0xB4, 0xAE, 0x85, 0xC5, 0x99, 0x8E, 0xC0, 0x58, - 0x0F, 0x86, 0xEB, 0xA6, 0xB5, 0xA3, 0x65, 0xBE, 0x4C, 0x4A, 0x5F, 0x93, 0x5C, 0xCB, 0xC7, 0x07, - 0xBA, 0x64, 0xBA, 0x14, 0xBD, 0x1A, 0x64, 0x87, 0xED, 0xCB, 0xA5, 0x4C, 0x86, 0xCD, 0x19, 0xBB, - 0x37, 0x8F, 0xB5, 0x64, 0x08, 0x65, 0x44, 0xB8, 0x0C, 0xA3, 0x8A, 0x59, 0x97, 0xB8, 0xEA, 0x4E, - 0xF6, 0xF0, 0x62, 0x4E, 0x8A, 0xD2, 0x88, 0xB9, 0x95, 0xA7, 0xE0, 0x8E, 0xEB, 0x5C, 0x23, 0xFE, - 0xFE, 0xFB, 0xBF, 0x54, 0x06, 0xF1, 0xDB, 0x42, 0x4B, 0x65, 0xB3, 0x09, 0x5E, 0x62, 0x6A, 0xB7, - 0x66, 0x5B, 0xE6, 0xD2, 0xF4, 0xFE, 0x92, 0x3C, 0x80, 0x67, 0x57, 0xC1, 0x39, 0x23, 0x94, 0x56, - 0x55, 0x8F, 0x81, 0x57, 0xEF, 0xF9, 0x39, 0x89, 0x40, 0x72, 0x65, 0x1E, 0x83, 0xEB, 0xC7, 0xC5, - 0xAE, 0xAD, 0x60, 0x97, 0xFE, 0xD1, 0xCD, 0xB0, 0xC2, 0xF3, 0x89, 0x69, 0x6B, 0xBD, 0x0E, 0xCF, - 0x02, 0x41, 0x11, 0xCF, 0x95, 0x27, 0x80, 0xCD, 0xB9, 0x4F, 0x00, 0xF2, 0xE8, 0xAB, 0x39, 0x05, - 0x64, 0x44, 0xF4, 0x44, 0x53, 0x43, 0x66, 0x74, 0xD7, 0x9D, 0x1D, 0x4C, 0x8C, 0xAF, 0x3C, 0x11, - 0xE7, 0x33, 0xCF, 0x1C, 0x26, 0xE6, 0x17, 0xB2, 0x53, 0xCA, 0xBF, 0xB6, 0x5A, 0x8F, 0xD5, 0x86, - 0xA5, 0xC6, 0xD3, 0x93, 0x89, 0x77, 0xF2, 0xD8, 0x82, 0xCF, 0x35, 0xAF, 0x73, 0x52, 0x77, 0xE9, - 0x1A, 0xA6, 0xD1, 0x2C, 0xCC, 0x59, 0x81, 0x66, 0x6C, 0x49, 0x71, 0x3F, 0x3C, 0x71, 0x5B, 0xF4, - 0x89, 0x63, 0xFE, 0x23, 0xBA, 0xA8, 0x41, 0x99, 0x6B, 0x4A, 0x2A, 0x3D, 0x2D, 0xE6, 0x31, 0x0E, - 0x42, 0x1A, 0xE0, 0x93, 0x91, 0x02, 0x66, 0xF5, 0x5F, 0x9D, 0xD5, 0x4E, 0x84, 0x17, 0xAE, 0x07, - 0x4B, 0x3B, 0x44, 0x4D, 0x08, 0x11, 0x9F, 0xEB, 0xC3, 0x92, 0xB8, 0xCD, 0xF3, 0x4F, 0xC2, 0x0A, - 0xF6, 0x26, 0x90, 0x83, 0x24, 0x79, 0xF2, 0xCC, 0x37, 0xB8, 0x6A, 0x8E, 0x2F, 0x56, 0xAD, 0x48, - 0x41, 0x28, 0xF0, 0x59, 0x59, 0xA4, 0x63, 0x35, 0x25, 0xED, 0xA3, 0x48, 0xAD, 0xB9, 0x8C, 0x78, - 0x31, 0x1A, 0x54, 0x29, 0xE7, 0xC8, 0x97, 0x59, 0x92, 0x7C, 0x79, 0x1D, 0xEF, 0x29, 0x2B, 0x77, - 0x81, 0xDA, 0xC6, 0x17, 0x3B, 0x3D, 0x9E, 0xA9, 0x4F, 0xAC, 0xE1, 0xA5, 0xBB, 0xD0, 0xA2, 0x24, - 0x8D, 0x97, 0x2B, 0x58, 0x89, 0x87, 0x77, 0x6E, 0x34, 0xB8, 0x21, 0x45, 0x55, 0x58, 0x78, 0x02, - 0xBD, 0xB6, 0xA7, 0xA3, 0xE8, 0x95, 0x96, 0xEB, 0x9F, 0xF7, 0x44, 0xEB, 0x93, 0xF7, 0xCD, 0xF3, - 0xEF, 0x3C, 0x3D, 0x61, 0xAE, 0xF6, 0xAE, 0xC4, 0x00, 0x2F, 0x25, 0x2F, 0x56, 0x5E, 0xBF, 0xE7, - 0xD0, 0x92, 0xB7, 0x29, 0xE6, 0x4A, 0x10, 0x16, 0x57, 0xB9, 0x24, 0xD3, 0x7D, 0xCF, 0xB9, 0x92, - 0xBC, 0x2C, 0xA2, 0x49, 0x1E, 0x8F, 0x28, 0x9F, 0x8F, 0x73, 0x29, 0xAF, 0x3C, 0x12, 0x65, 0xE6, - 0xBD, 0x14, 0xC8, 0x38, 0xD9, 0x62, 0x9A, 0x7B, 0x7B, 0x8B, 0xE8, 0x2A, 0x9B, 0x5B, 0x8F, 0x40, - 0xB9, 0x5C, 0xD8, 0x2B, 0x8F, 0x43, 0x5E, 0x9F, 0x48, 0x0B, 0x25, 0xFF, 0x18, 0x0D, 0xAF, 0x42, - 0x9B, 0x4B, 0xFF, 0xB1, 0xC4, 0x5E, 0x89, 0x05, 0xDE, 0x03, 0x05, 0x2C, 0x3C, 0xBC, 0xC8, 0xB3, - 0x76, 0x0F, 0x2F, 0xFE, 0x3F, 0x53, 0xDF, 0xB5, 0xEA, 0x6E, 0x9B, 0x00 + 0x1F, 0x8B, 0x08, 0x08, 0xD1, 0x32, 0xB7, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xEB, 0x7A, 0xDB, 0x38, 0x92, 0xE8, 0xFF, + 0xF9, 0xBE, 0x79, 0x07, 0x8C, 0xCE, 0x9C, 0x96, 0x3C, 0x96, 0x65, 0x4A, 0xBE, 0xC4, 0x8E, 0xE3, + 0xCC, 0x71, 0x6C, 0x27, 0xF1, 0x19, 0x5F, 0x74, 0x2C, 0xA7, 0xBB, 0xD3, 0x99, 0xAC, 0x97, 0x16, + 0x61, 0x99, 0x1B, 0x89, 0xD4, 0x90, 0x94, 0x1D, 0xF7, 0x6C, 0xDE, 0x69, 0x9F, 0x61, 0x9F, 0xEC, + 0x54, 0x01, 0x20, 0x09, 0x90, 0xE0, 0x55, 0x92, 0xDB, 0xD3, 0x9B, 0x7C, 0x5F, 0xBB, 0x6D, 0x02, + 0x75, 0x41, 0xA1, 0x50, 0x28, 0x5C, 0xAA, 0x70, 0x6F, 0x7A, 0x64, 0x64, 0x06, 0xF4, 0xC1, 0x7C, + 0x24, 0xFB, 0xE4, 0xDF, 0x1F, 0xFC, 0x97, 0xEB, 0xEB, 0x7F, 0xFE, 0xE7, 0x83, 0xED, 0x58, 0xEE, + 0x43, 0x67, 0xEC, 0x0E, 0xCD, 0xC0, 0x76, 0x9D, 0xCE, 0x9D, 0xEB, 0x07, 0x8E, 0x39, 0xA1, 0xDF, + 0x5E, 0xEE, 0x74, 0xD7, 0x1F, 0xFC, 0x7F, 0xDF, 0xFB, 0xE3, 0x1F, 0xEE, 0x01, 0xF0, 0x81, 0xDE, + 0xF8, 0xEE, 0xF0, 0x0B, 0x0D, 0xE0, 0xEF, 0x3F, 0xFE, 0x41, 0x00, 0x99, 0x96, 0x75, 0x7C, 0x4F, + 0x9D, 0xE0, 0xD4, 0xF6, 0x03, 0xEA, 0x50, 0xAF, 0xD5, 0x1C, 0xBB, 0xA6, 0xD5, 0x6C, 0x13, 0xD7, + 0x39, 0x85, 0x5F, 0x56, 0x58, 0xDD, 0xDB, 0x99, 0x33, 0x44, 0xCC, 0xE2, 0x63, 0x8B, 0x22, 0xC4, + 0x0A, 0xF9, 0xE7, 0x1F, 0xFF, 0x40, 0xE0, 0x9F, 0xED, 0xD8, 0xC1, 0x4F, 0xF4, 0x66, 0xC0, 0x70, + 0xB7, 0x10, 0xE2, 0x9B, 0x02, 0x94, 0x28, 0x0F, 0xC1, 0x22, 0x76, 0xA0, 0x25, 0x0E, 0x7D, 0x20, + 0x71, 0x15, 0xD1, 0x42, 0xC4, 0xA4, 0x54, 0xEC, 0xB8, 0xCE, 0x84, 0xFA, 0xBE, 0x39, 0xA2, 0x00, + 0x12, 0xA1, 0x6F, 0x4D, 0xFC, 0x51, 0x84, 0x14, 0xFF, 0x4D, 0x4D, 0xCF, 0xA7, 0x27, 0xCE, 0xD0, + 0x9D, 0xD8, 0xCE, 0x08, 0x4B, 0x3B, 0x96, 0x19, 0x98, 0x21, 0xB6, 0x6F, 0x29, 0xFE, 0x46, 0xB4, + 0x45, 0x23, 0x04, 0x1E, 0x0D, 0x66, 0x9E, 0x43, 0x2C, 0x77, 0x38, 0x9B, 0x40, 0x23, 0x3B, 0x23, + 0x1A, 0x1C, 0x8F, 0x29, 0xFE, 0xFA, 0xE6, 0xF1, 0x04, 0x5A, 0x1E, 0x35, 0x0F, 0x25, 0x7A, 0x6B, + 0x7F, 0xA5, 0xD6, 0xA9, 0x89, 0x2D, 0x30, 0xF6, 0xE4, 0x4F, 0xAE, 0x33, 0x92, 0xBE, 0x4D, 0xC7, + 0x66, 0x70, 0xEB, 0x7A, 0x93, 0xBE, 0x47, 0xA1, 0x18, 0x0A, 0x1A, 0x0D, 0x51, 0x32, 0xA2, 0xAE, + 0x45, 0x03, 0x7B, 0xC8, 0x71, 0x6C, 0x1A, 0x1D, 0xA3, 0x9B, 0x2C, 0x01, 0x06, 0xF7, 0xC9, 0x5A, + 0xD7, 0xD8, 0xEA, 0x74, 0x77, 0x13, 0x65, 0x07, 0x63, 0x84, 0xEA, 0x6E, 0x19, 0x46, 0x27, 0x04, + 0xA3, 0x43, 0x7A, 0xFB, 0x33, 0x03, 0xE8, 0xED, 0x18, 0x3D, 0x63, 0xBB, 0xB3, 0xB5, 0xBD, 0x23, + 0x15, 0x7D, 0xC4, 0xA2, 0xCD, 0x17, 0xDD, 0xED, 0x1D, 0x63, 0xB3, 0xB3, 0x69, 0x6C, 0x48, 0x45, + 0xBF, 0x30, 0x06, 0x76, 0xB6, 0xB7, 0xB7, 0xB7, 0x3A, 0x9B, 0x3B, 0x9B, 0xA2, 0x64, 0x6C, 0xFA, + 0xC1, 0x5B, 0x7B, 0x4C, 0xCF, 0x41, 0x9D, 0x64, 0xC6, 0x6F, 0xF1, 0xDB, 0x6C, 0x72, 0x43, 0x3D, + 0xA9, 0x9D, 0x0E, 0xFB, 0x70, 0x71, 0x8B, 0x00, 0xFE, 0x80, 0x8E, 0xE9, 0x30, 0xA0, 0x96, 0x54, + 0xEE, 0x8B, 0x4F, 0xAC, 0x5C, 0xC6, 0xE6, 0xDF, 0xB9, 0xA0, 0x8E, 0x23, 0xFC, 0x8E, 0x7A, 0x88, + 0xBD, 0x6B, 0x8E, 0x7D, 0x2A, 0x4A, 0xDD, 0x9B, 0xC0, 0xB4, 0x1D, 0x6A, 0x9D, 0xF1, 0xBE, 0x2F, + 0x57, 0xE3, 0x8D, 0xE9, 0xD3, 0x44, 0x2D, 0x41, 0x45, 0x54, 0xBA, 0xBC, 0x3A, 0x3C, 0xD3, 0xA0, + 0xC2, 0x86, 0x5D, 0x99, 0x37, 0xF0, 0x83, 0x7E, 0x0D, 0x64, 0x1E, 0x87, 0xAE, 0xE7, 0x51, 0xA6, + 0x30, 0xC9, 0x12, 0xA1, 0x93, 0xC9, 0xCF, 0x28, 0x3A, 0x41, 0xEB, 0xEA, 0x71, 0x4A, 0x73, 0x8A, + 0x04, 0xAF, 0xAC, 0x58, 0xB0, 0x6A, 0xDE, 0x47, 0xAD, 0x41, 0xD1, 0xA3, 0xB4, 0x3E, 0x7D, 0xDE, + 0x4B, 0x17, 0xFE, 0x68, 0x8E, 0x67, 0x9A, 0xD2, 0xC3, 0x3B, 0x3A, 0xFC, 0x72, 0xE3, 0x7E, 0xD5, + 0xC3, 0x86, 0xA5, 0x2A, 0x30, 0xAF, 0x00, 0x6D, 0x74, 0x3D, 0xCB, 0x3F, 0x3E, 0x3C, 0x7E, 0x2B, + 0xC3, 0x89, 0xCF, 0xEF, 0x84, 0xE6, 0xC9, 0x45, 0xB7, 0xB3, 0xF1, 0xB8, 0x0F, 0xAC, 0x7C, 0x98, + 0xC2, 0x30, 0x93, 0x65, 0x1E, 0x42, 0xFA, 0x34, 0xB8, 0xB2, 0x27, 0xD4, 0x9D, 0x05, 0x91, 0x1E, + 0x38, 0xD6, 0x11, 0x0C, 0x49, 0xF5, 0xEB, 0x10, 0xB9, 0x3A, 0xA7, 0x0F, 0x6F, 0x6D, 0x6F, 0xF2, + 0x60, 0x7A, 0x54, 0x2D, 0x85, 0x71, 0xA8, 0x2D, 0xFB, 0xE3, 0x1F, 0x86, 0xAE, 0x03, 0xBD, 0x08, + 0xBA, 0x77, 0x18, 0xF5, 0x90, 0x3F, 0x70, 0x67, 0xDE, 0x90, 0x35, 0x6D, 0x27, 0xD5, 0x7D, 0xA2, + 0x30, 0x25, 0x9A, 0x54, 0x8D, 0xBE, 0x67, 0xBB, 0x9E, 0x1D, 0xD8, 0xB2, 0x88, 0x38, 0xB1, 0x43, + 0x17, 0x84, 0x61, 0x3B, 0xD0, 0x5C, 0xEC, 0x3E, 0x2C, 0x16, 0xD6, 0xE3, 0xF0, 0xE2, 0xE2, 0xF2, + 0xE8, 0xE4, 0xFC, 0xE0, 0xEA, 0xF8, 0xFA, 0xE4, 0xBC, 0xFF, 0xE1, 0xEA, 0xFA, 0xEA, 0x63, 0xFF, + 0xF8, 0xFA, 0xE8, 0xE8, 0x25, 0x31, 0xDA, 0x64, 0x7D, 0xFD, 0x88, 0xDE, 0x9A, 0x33, 0x18, 0xB4, + 0x47, 0x47, 0x1D, 0x2B, 0xFC, 0x97, 0x0F, 0x78, 0x76, 0xF6, 0x92, 0x74, 0x19, 0x28, 0xFC, 0xDA, + 0x99, 0xE0, 0xBF, 0x7C, 0x80, 0x6B, 0x84, 0xE8, 0x71, 0x08, 0x52, 0x1A, 0xE4, 0xFA, 0xE8, 0x60, + 0xF0, 0xFE, 0x25, 0xD9, 0xE0, 0x70, 0x6B, 0xE5, 0xE1, 0x06, 0x1F, 0xCF, 0xDE, 0x5C, 0x9C, 0xBE, + 0x24, 0x9B, 0x1C, 0xF2, 0xBF, 0xFF, 0x2B, 0x04, 0x9D, 0x4C, 0x9A, 0x45, 0x2D, 0x1B, 0x0C, 0x5E, + 0x92, 0xAD, 0x88, 0x53, 0x32, 0x18, 0x74, 0x7C, 0xF6, 0xAF, 0x04, 0x55, 0x80, 0xDC, 0xAE, 0x09, + 0x29, 0x9A, 0xFA, 0x22, 0x6A, 0xEA, 0x5A, 0x35, 0xF0, 0xB0, 0xC5, 0x3B, 0x71, 0x8B, 0x9B, 0x11, + 0x86, 0x46, 0x71, 0x9B, 0xAF, 0xCF, 0x2F, 0xAE, 0x8F, 0x8E, 0x0F, 0x4F, 0xCE, 0x0E, 0x00, 0xC9, + 0x6E, 0xD8, 0xB5, 0x83, 0x01, 0x59, 0x23, 0xE7, 0x2E, 0xB1, 0xE8, 0xD0, 0x9E, 0x98, 0xE3, 0x52, + 0x9C, 0xC8, 0x88, 0xBA, 0x86, 0x2C, 0x8E, 0xEA, 0xB8, 0x50, 0x28, 0x2A, 0xC2, 0xAE, 0x2C, 0xA0, + 0xD2, 0x08, 0x4F, 0xCE, 0x7F, 0x3C, 0x38, 0x3D, 0x39, 0xBA, 0xFE, 0x70, 0xFE, 0xB7, 0xF3, 0x8B, + 0x9F, 0xCE, 0x01, 0x4F, 0xAF, 0x2D, 0x4D, 0x98, 0x30, 0x7C, 0xEE, 0xA9, 0x07, 0x53, 0x40, 0x3C, + 0x82, 0x70, 0x7E, 0xE8, 0x18, 0xD1, 0x18, 0x0C, 0x3F, 0x9F, 0x38, 0xD3, 0x59, 0x20, 0xEC, 0x66, + 0x62, 0xB8, 0x75, 0xB2, 0xDA, 0xA2, 0xFA, 0x2A, 0x29, 0x37, 0x20, 0x9A, 0xE3, 0xD7, 0xD7, 0x71, + 0x18, 0xBB, 0x63, 0x0A, 0x2E, 0xD3, 0xA8, 0xD5, 0x08, 0xEB, 0x84, 0x86, 0xFC, 0x25, 0x69, 0x90, + 0x55, 0x82, 0x00, 0x0C, 0x21, 0x42, 0x20, 0x6F, 0xE8, 0x44, 0x00, 0x33, 0xE8, 0x4F, 0xF8, 0xD3, + 0xB1, 0x1D, 0xB4, 0x9A, 0xED, 0x66, 0xE8, 0x54, 0xC0, 0xEC, 0x4E, 0x5A, 0x63, 0x70, 0x65, 0xBE, + 0xB2, 0xE9, 0x0E, 0xFE, 0xF7, 0x8A, 0xD5, 0xEF, 0x8C, 0xA9, 0x33, 0x0A, 0xEE, 0x40, 0x7C, 0x5D, + 0xFC, 0xB8, 0xBA, 0x4F, 0x7A, 0x8A, 0xAB, 0x82, 0x78, 0x6D, 0x9C, 0x22, 0xB1, 0xF2, 0xA7, 0xAF, + 0x9F, 0xF7, 0xD4, 0xA2, 0x7B, 0x73, 0x1C, 0x95, 0x01, 0x4B, 0x5D, 0xB9, 0x3C, 0xD1, 0x08, 0xDB, + 0xE2, 0x6C, 0x03, 0xB6, 0x55, 0xD2, 0x68, 0x23, 0x28, 0xFF, 0x00, 0xBF, 0xC4, 0xED, 0xE0, 0x80, + 0x83, 0x29, 0x74, 0x24, 0xA0, 0x86, 0x66, 0x4F, 0x4C, 0xC7, 0xF2, 0xE3, 0x32, 0xFB, 0x96, 0xB4, + 0x6C, 0xAB, 0x63, 0x3B, 0xC3, 0xF1, 0xCC, 0xA2, 0x7E, 0xAB, 0xE1, 0x5B, 0x67, 0xEE, 0xCC, 0x81, + 0x0E, 0x6B, 0xAC, 0x28, 0x8C, 0x73, 0x44, 0x57, 0xE8, 0x2A, 0xB9, 0xCE, 0xBA, 0x7B, 0x7B, 0x4B, + 0x06, 0x47, 0x04, 0x0C, 0xB3, 0xA9, 0x56, 0x41, 0x7C, 0xAC, 0x11, 0x30, 0xBB, 0xB1, 0x69, 0xA1, + 0x91, 0xC2, 0x82, 0xFF, 0xEE, 0x6C, 0x8B, 0xB6, 0x1A, 0x38, 0xF5, 0x9E, 0x99, 0x0E, 0xF4, 0x80, + 0xD7, 0x58, 0xD9, 0x53, 0x6B, 0x7D, 0x53, 0xFF, 0xA4, 0x80, 0x4A, 0x41, 0x1E, 0x78, 0xB3, 0x0C, + 0xDC, 0x38, 0xEB, 0x97, 0xC6, 0x2D, 0xFD, 0x1A, 0x91, 0xC0, 0xFE, 0x01, 0x0A, 0xAA, 0x13, 0x97, + 0xA6, 0x95, 0x72, 0xF2, 0x80, 0xB5, 0x04, 0xA1, 0xC8, 0xA9, 0x0C, 0xEC, 0x60, 0xCC, 0x66, 0xFC, + 0xCB, 0xAB, 0xBF, 0xB1, 0x4E, 0x4A, 0x00, 0x43, 0x0F, 0x92, 0x01, 0x38, 0xA2, 0xD3, 0x46, 0x02, + 0x43, 0x6A, 0xAE, 0xC5, 0x76, 0x27, 0xEA, 0xE8, 0x1D, 0x95, 0x74, 0xBF, 0x24, 0x19, 0x86, 0x8A, + 0xC7, 0x3F, 0xFE, 0x2D, 0x4F, 0x88, 0x37, 0xE0, 0xA7, 0x1C, 0xBA, 0xCE, 0xAD, 0x3D, 0x4A, 0xC9, + 0x30, 0xAE, 0x34, 0x9D, 0x16, 0x56, 0xA1, 0xC1, 0x1D, 0xF5, 0x1C, 0x1A, 0x14, 0x56, 0x74, 0x82, + 0x62, 0x64, 0x53, 0xD7, 0x0B, 0xFC, 0x9C, 0x5A, 0x5C, 0xB7, 0x40, 0x12, 0x40, 0xD2, 0x1C, 0xF7, + 0xA1, 0xF6, 0xC5, 0x94, 0x4D, 0xF2, 0x39, 0x38, 0x61, 0x44, 0x5D, 0xB9, 0x83, 0xA3, 0x43, 0xD3, + 0xB3, 0x72, 0x70, 0x8E, 0xCC, 0x31, 0x68, 0x95, 0xFB, 0xDE, 0x04, 0x5F, 0x37, 0x08, 0xC0, 0x80, + 0xE4, 0xD4, 0x0D, 0xEC, 0x71, 0x50, 0xC8, 0xE4, 0x0D, 0xA5, 0x53, 0xEA, 0x41, 0xB5, 0xC0, 0x73, + 0xC7, 0x39, 0xEC, 0xCD, 0x7C, 0x7A, 0xE0, 0xFB, 0xE0, 0xBB, 0x9E, 0xBB, 0x0F, 0xA1, 0x2F, 0x97, + 0x53, 0x7D, 0x42, 0x4D, 0x7F, 0xE6, 0xB1, 0x35, 0xCC, 0x65, 0x68, 0x59, 0x73, 0xB8, 0x98, 0xB8, + 0xBE, 0x69, 0x0F, 0xCF, 0xCF, 0x8E, 0x0F, 0x06, 0x01, 0x0C, 0xE8, 0xC9, 0x91, 0xE7, 0x4E, 0x61, + 0xA5, 0x98, 0x2B, 0x30, 0xC0, 0x7F, 0x4F, 0x1F, 0x4F, 0x1C, 0x21, 0x08, 0x3F, 0x9F, 0xF9, 0x53, + 0x58, 0xA8, 0x8E, 0xED, 0x5F, 0xA9, 0x75, 0x04, 0x6D, 0xF0, 0xEC, 0x9B, 0x19, 0xF6, 0x47, 0x89, + 0x86, 0x00, 0xE8, 0xB1, 0x83, 0xBE, 0xF9, 0xF1, 0xD7, 0x00, 0x9D, 0xBD, 0x4B, 0xD3, 0xB2, 0xDD, + 0x3C, 0x3D, 0x93, 0xAA, 0x0D, 0xFA, 0x07, 0x97, 0x57, 0xE7, 0xDC, 0xB1, 0x0B, 0x5B, 0x94, 0x23, + 0x04, 0xFF, 0x6E, 0x16, 0x60, 0x95, 0x73, 0xF7, 0xF0, 0xCE, 0xF4, 0x46, 0xA1, 0xC3, 0x79, 0x66, + 0x3B, 0xB3, 0x80, 0xFA, 0x21, 0xAF, 0x47, 0x14, 0xD6, 0x1D, 0xBC, 0xA7, 0xB2, 0x10, 0x31, 0x87, + 0x91, 0x8E, 0xC7, 0x6C, 0x65, 0x7E, 0x6E, 0xDE, 0xDB, 0x43, 0xA8, 0x0E, 0xA6, 0xF3, 0xDC, 0x0D, + 0x88, 0x3F, 0x9B, 0xA2, 0xF6, 0xC2, 0x1A, 0x09, 0xA6, 0xAB, 0x5F, 0x8E, 0x8F, 0xCA, 0x99, 0x3C, + 0xDD, 0xC0, 0x7D, 0x6B, 0x0E, 0x61, 0xF2, 0xB9, 0xEF, 0xC1, 0xE8, 0xFD, 0xCF, 0xFF, 0x24, 0x79, + 0x35, 0xC8, 0xE9, 0x1B, 0x30, 0xF9, 0x1A, 0x6B, 0xBE, 0xC8, 0x61, 0x2E, 0xC6, 0x5C, 0xF1, 0x30, + 0xE7, 0x15, 0x17, 0x31, 0xCC, 0xA3, 0x1E, 0xFF, 0x3E, 0xCC, 0xBF, 0x0F, 0x73, 0xCD, 0x30, 0x7F, + 0xBA, 0xF1, 0x99, 0x39, 0xF8, 0xB8, 0xC4, 0x7F, 0xDE, 0x6A, 0x7C, 0x1F, 0x7B, 0xCF, 0x78, 0xEC, + 0xF1, 0x7A, 0xA5, 0xC7, 0x9E, 0x18, 0x4C, 0x65, 0xC7, 0x9E, 0x18, 0xAA, 0x95, 0xC6, 0x9E, 0x98, + 0x91, 0xCA, 0x8C, 0xBD, 0x88, 0xF9, 0xE5, 0x8F, 0xBD, 0xC8, 0xAF, 0xAA, 0x33, 0xF6, 0xF8, 0x4E, + 0x20, 0xF8, 0xA6, 0x23, 0xC0, 0x61, 0x3D, 0x3A, 0xE6, 0xC4, 0x1E, 0x9E, 0xB9, 0x16, 0xD5, 0x77, + 0x09, 0x2E, 0xAC, 0x1C, 0xFA, 0xC0, 0x95, 0x4A, 0xEC, 0x16, 0xF3, 0x3F, 0x5A, 0xCD, 0x41, 0x00, + 0x23, 0x77, 0xD8, 0x6C, 0x93, 0xA6, 0xD1, 0xD4, 0x36, 0x8B, 0x51, 0xC2, 0x6D, 0xEE, 0x56, 0x84, + 0xA2, 0x4D, 0x66, 0x8E, 0x05, 0x83, 0xD3, 0xA1, 0x96, 0x0E, 0x24, 0x8B, 0xD4, 0xFF, 0x9B, 0x99, + 0xA8, 0x11, 0x21, 0xBD, 0xEE, 0xB2, 0xE9, 0xF5, 0x29, 0x2C, 0xC1, 0xA0, 0xF3, 0x4C, 0x07, 0xC9, + 0xF5, 0x96, 0x4D, 0xEE, 0x60, 0x16, 0xB8, 0x13, 0x37, 0xB0, 0xEF, 0x29, 0x92, 0xDB, 0x58, 0x36, + 0xB9, 0x4B, 0xB0, 0x89, 0x04, 0x86, 0x3F, 0x12, 0xDB, 0x5C, 0x36, 0xB1, 0xF7, 0xD4, 0xBC, 0x7F, + 0x24, 0x67, 0xE6, 0xF0, 0x0E, 0x20, 0xBD, 0x47, 0xA4, 0xB9, 0xB5, 0x6C, 0x9A, 0x1F, 0x0E, 0x7E, + 0x44, 0x3A, 0xDB, 0x4B, 0xA7, 0xE3, 0x8C, 0xED, 0x89, 0x0D, 0xB3, 0x14, 0x52, 0x7B, 0x51, 0x97, + 0x5A, 0x1A, 0x68, 0xC4, 0xEC, 0x1A, 0xDF, 0x2B, 0x67, 0x36, 0xED, 0xD6, 0xC5, 0x05, 0x65, 0x63, + 0xA5, 0xE3, 0xD3, 0xE0, 0x20, 0xE0, 0x56, 0x85, 0xB6, 0x9A, 0xB8, 0x3D, 0xB1, 0x76, 0xE3, 0xAF, + 0xB9, 0x9E, 0x3D, 0xB2, 0xC1, 0xFE, 0xAF, 0xB1, 0xD5, 0x2D, 0x32, 0x73, 0x75, 0x47, 0xC9, 0xBB, + 0xF3, 0xC1, 0x80, 0x0C, 0x4D, 0x87, 0x80, 0xF7, 0x0C, 0x46, 0x91, 0xA0, 0xD1, 0x23, 0xE0, 0x81, + 0x12, 0xDC, 0x7F, 0xBF, 0xDF, 0x20, 0x66, 0x40, 0x2C, 0xFB, 0xF6, 0x96, 0x7A, 0x60, 0x3A, 0x89, + 0x07, 0x74, 0xFC, 0x0E, 0x79, 0xEB, 0x7A, 0xAC, 0xDE, 0xCB, 0xD0, 0x4E, 0x98, 0xC4, 0x67, 0x76, + 0x92, 0xED, 0xB3, 0x50, 0xE8, 0xC5, 0x70, 0xAB, 0xA6, 0xCD, 0x50, 0x01, 0x3F, 0xF0, 0x7F, 0x62, + 0x3B, 0x30, 0x01, 0xE1, 0x86, 0x40, 0x54, 0x8B, 0x43, 0x71, 0x84, 0x9C, 0xDE, 0xCB, 0xEC, 0xCA, + 0xE1, 0xD1, 0xD2, 0xC8, 0x73, 0x67, 0x53, 0x8E, 0x98, 0x32, 0x53, 0x08, 0x75, 0x2D, 0xFB, 0xDE, + 0xB6, 0x66, 0x50, 0x5B, 0x54, 0xF2, 0x3B, 0x5A, 0x39, 0xA3, 0xC8, 0xBC, 0x60, 0x38, 0xA9, 0x29, + 0x2F, 0x64, 0x91, 0xD8, 0x3E, 0x2C, 0xEA, 0x4D, 0xC7, 0x87, 0x2E, 0x45, 0xCF, 0xE3, 0xE6, 0x91, + 0xC0, 0x54, 0x4E, 0xD0, 0x2F, 0x40, 0x59, 0x99, 0xC4, 0x12, 0x7B, 0xC8, 0xEE, 0x2D, 0xE9, 0xBE, + 0xFF, 0x95, 0xB1, 0x1F, 0x32, 0x45, 0xBA, 0x86, 0xB1, 0xD5, 0x26, 0x67, 0x83, 0xB3, 0x4D, 0xCE, + 0xBF, 0xD1, 0x09, 0xAB, 0x74, 0x8D, 0x8D, 0x8D, 0x0E, 0xB9, 0xBA, 0x03, 0xEC, 0xD8, 0x19, 0x37, + 0x94, 0x8C, 0xDD, 0x07, 0x10, 0xBA, 0xC5, 0x4A, 0x3D, 0x34, 0xDF, 0x3E, 0x79, 0xB0, 0x83, 0x3B, + 0xFC, 0x0E, 0xD4, 0x1C, 0xEB, 0xC1, 0xB6, 0xE0, 0x2F, 0x28, 0xC4, 0x25, 0x8E, 0x8B, 0x35, 0x03, + 0x37, 0xE2, 0x0C, 0xB0, 0x3F, 0xAE, 0x9B, 0xE3, 0x31, 0x93, 0x6A, 0x2C, 0x14, 0x72, 0x8A, 0x9A, + 0xE8, 0xBF, 0x44, 0xC2, 0x58, 0x7D, 0xDB, 0x30, 0xB2, 0x05, 0x45, 0x53, 0xF3, 0x4C, 0x0D, 0x91, + 0xF1, 0xC9, 0x8A, 0x84, 0xBE, 0x07, 0x6F, 0x89, 0xBC, 0x95, 0xFF, 0x32, 0x54, 0x34, 0x18, 0x37, + 0x7C, 0xDA, 0x25, 0x87, 0x17, 0x67, 0xBD, 0x0E, 0x11, 0x7B, 0xF1, 0x2F, 0xC9, 0x5B, 0xDC, 0x97, + 0x6A, 0x96, 0xDD, 0x70, 0xD2, 0x78, 0x77, 0x57, 0xAE, 0x37, 0xBC, 0xFB, 0xDD, 0x39, 0x75, 0xF9, + 0xFB, 0x26, 0x59, 0xF5, 0x93, 0x6E, 0x5D, 0x29, 0xB7, 0x7B, 0x00, 0x02, 0xCA, 0xF0, 0xBA, 0x3F, + 0x9C, 0xED, 0xEE, 0x18, 0x73, 0xFB, 0xEE, 0x02, 0x4B, 0xC5, 0x85, 0x16, 0xEE, 0x7F, 0xBB, 0x30, + 0xAA, 0x70, 0xFC, 0xF5, 0xFB, 0xA7, 0x04, 0xAA, 0x91, 0xB3, 0x77, 0x07, 0x7F, 0x25, 0x1C, 0xBF, + 0x47, 0x3B, 0x9D, 0x4E, 0xE5, 0xC5, 0x58, 0xB6, 0x3F, 0xEC, 0x99, 0x52, 0x6F, 0x2C, 0xD5, 0x65, + 0x62, 0x9E, 0xE4, 0x93, 0xB8, 0x4C, 0x62, 0x0E, 0xEC, 0x3E, 0xAD, 0xEF, 0xD2, 0x5B, 0xEC, 0x24, + 0xF8, 0xDB, 0x5B, 0xF4, 0xAE, 0xF1, 0x62, 0x13, 0x7F, 0xEE, 0xB0, 0x9F, 0xBB, 0xF8, 0xB3, 0xDB, + 0xFB, 0xCD, 0x6D, 0x3C, 0x56, 0xEE, 0x19, 0x1D, 0x1C, 0x0E, 0xF4, 0x25, 0xC1, 0xC9, 0x5E, 0xD2, + 0x7A, 0x36, 0x97, 0x63, 0xD3, 0xDD, 0x7B, 0xEA, 0x79, 0xB6, 0x65, 0x51, 0x07, 0xEB, 0x23, 0xAF, + 0x0F, 0x77, 0x14, 0xE7, 0x5F, 0xC2, 0x8E, 0xBD, 0x27, 0xA0, 0xC2, 0x7C, 0x8E, 0xA8, 0x6D, 0x7F, + 0xFB, 0xAE, 0x1F, 0x0C, 0x99, 0xC1, 0xF9, 0xBE, 0xAE, 0x2E, 0x6D, 0x80, 0x9F, 0x60, 0x65, 0xFD, + 0x7D, 0x5F, 0xEB, 0xB9, 0xEC, 0x6B, 0xE5, 0x4C, 0xB0, 0xA7, 0xEF, 0x7A, 0xBB, 0x46, 0x3F, 0x8B, + 0x05, 0xED, 0x0C, 0x9B, 0x4D, 0x54, 0x9E, 0x96, 0x24, 0x2E, 0xAB, 0xD0, 0x15, 0x9D, 0x68, 0x3B, + 0xC7, 0x63, 0x7A, 0x1F, 0x29, 0x5D, 0x2D, 0x0C, 0x87, 0xE7, 0x17, 0xA5, 0x10, 0xFC, 0x2B, 0x59, + 0xFD, 0x6E, 0x64, 0xFB, 0xBB, 0xDD, 0x8D, 0xCD, 0x7F, 0x61, 0x6B, 0x5F, 0xE9, 0x00, 0x56, 0x3A, + 0x90, 0x1E, 0x39, 0xBE, 0x1F, 0xDE, 0x02, 0xFA, 0x91, 0x7A, 0x3E, 0xE8, 0xE5, 0x89, 0x13, 0x68, + 0x4F, 0xA7, 0x41, 0x0D, 0xED, 0xDB, 0x47, 0x5C, 0xF0, 0xB1, 0x41, 0x4D, 0xAC, 0x19, 0x45, 0xA6, + 0x6E, 0x05, 0x34, 0x61, 0xCB, 0x66, 0xA6, 0xD9, 0x7E, 0xFA, 0x74, 0x34, 0xFB, 0x78, 0xB4, 0xE0, + 0x80, 0x65, 0xDE, 0x23, 0x98, 0x85, 0xB9, 0x79, 0x38, 0x5F, 0xA0, 0xB5, 0x79, 0x12, 0x47, 0x6F, + 0xC0, 0x05, 0x69, 0xF2, 0xBD, 0x95, 0xDE, 0xD3, 0x6E, 0x8D, 0x6D, 0x3C, 0xAD, 0x7B, 0xB9, 0xF4, + 0xDD, 0xAA, 0x01, 0x35, 0x9F, 0x64, 0x87, 0xEA, 0xC0, 0xF6, 0x6E, 0x5C, 0xF0, 0x66, 0x48, 0x77, + 0xF4, 0x24, 0x3B, 0x55, 0x11, 0xBD, 0xDE, 0x68, 0xAE, 0xBD, 0xAA, 0xCA, 0xF4, 0x36, 0x19, 0xBD, + 0x9D, 0x65, 0xD3, 0xFB, 0xC9, 0x03, 0x87, 0x00, 0x29, 0xED, 0x2E, 0x9B, 0xD2, 0x1B, 0xFB, 0x0B, + 0x53, 0xC5, 0xEE, 0xC2, 0x06, 0x76, 0x78, 0x99, 0xE6, 0xF5, 0x3E, 0xE9, 0xF6, 0xBA, 0x5A, 0xD3, + 0x54, 0xDD, 0x3C, 0x15, 0x99, 0xA8, 0x33, 0x9C, 0xB1, 0x58, 0x3B, 0xF4, 0x2B, 0xC4, 0x9A, 0x6D, + 0xC9, 0x93, 0xDC, 0xF1, 0xDA, 0x60, 0xE8, 0xC2, 0x14, 0xC6, 0xC9, 0xF6, 0x16, 0x49, 0xF6, 0x5B, + 0x99, 0x59, 0x6D, 0x7D, 0x1D, 0xDC, 0x52, 0x36, 0x1D, 0x8D, 0xF0, 0xBA, 0xBD, 0x29, 0x7C, 0x03, + 0xBC, 0x08, 0x34, 0x73, 0xEC, 0xA0, 0x68, 0xFA, 0xF3, 0xAD, 0xB7, 0x1E, 0xA5, 0x83, 0x29, 0x4C, + 0x25, 0x8D, 0x15, 0x95, 0x1E, 0xCC, 0x3A, 0x89, 0xAA, 0x03, 0x70, 0x52, 0x8B, 0x6A, 0xDD, 0xC1, + 0x42, 0x01, 0x67, 0xC3, 0x93, 0xA3, 0xA2, 0x9A, 0x9A, 0x99, 0xB7, 0x08, 0xC4, 0x32, 0x1F, 0xFD, + 0x4B, 0x3A, 0x31, 0x6D, 0x87, 0x2D, 0x30, 0xF2, 0x2B, 0x4F, 0x3D, 0x17, 0x6F, 0x69, 0x19, 0x78, + 0x31, 0xB7, 0x64, 0xDD, 0x6E, 0x85, 0xBA, 0xBD, 0x0A, 0x75, 0x37, 0x2A, 0xD4, 0xDD, 0xAC, 0x50, + 0x77, 0xAB, 0x42, 0xDD, 0xED, 0x0A, 0x75, 0x5F, 0x94, 0xA9, 0xCB, 0x5C, 0xC2, 0xB3, 0x83, 0xC3, + 0xC2, 0x4E, 0xA3, 0xE0, 0xE6, 0xD3, 0x37, 0x57, 0xC5, 0x1A, 0x01, 0x6B, 0xCD, 0x30, 0x36, 0xA0, + 0xA8, 0xEA, 0x8D, 0x09, 0x5E, 0xB0, 0xF7, 0xD8, 0xA7, 0xB0, 0x7E, 0x41, 0x77, 0x2D, 0xAE, 0x9D, + 0x32, 0x35, 0x60, 0x59, 0x6C, 0x6B, 0x05, 0x60, 0x61, 0x78, 0xBC, 0xBF, 0x3A, 0x3B, 0x4D, 0x5D, + 0xA5, 0x2B, 0xF4, 0x11, 0xBD, 0xE0, 0x4B, 0x4A, 0x51, 0x75, 0x64, 0xB4, 0x15, 0x73, 0x08, 0x67, + 0x83, 0x7D, 0x98, 0x8E, 0x40, 0xBC, 0xB4, 0x31, 0x17, 0xDB, 0x43, 0x5C, 0xAC, 0x78, 0x93, 0x4B, + 0xBC, 0x30, 0xAF, 0x61, 0x98, 0x5D, 0xA4, 0x3F, 0x74, 0x27, 0x53, 0xB0, 0xA8, 0xB4, 0xB5, 0x52, + 0x03, 0x33, 0xDE, 0xB9, 0xBF, 0xA4, 0x43, 0x6A, 0x4F, 0x75, 0xF8, 0xD3, 0x95, 0x92, 0x44, 0x8A, + 0xC8, 0x08, 0x6D, 0xE4, 0x71, 0x21, 0x3A, 0x0A, 0x33, 0x0F, 0x8F, 0x79, 0xFA, 0x72, 0x35, 0xAD, + 0x90, 0xFF, 0xDC, 0x6A, 0xD8, 0xB8, 0xCC, 0xFF, 0x84, 0x51, 0x4C, 0xFB, 0x02, 0x2D, 0x5B, 0x07, + 0x7F, 0xFE, 0x74, 0x8F, 0x41, 0x0B, 0xFB, 0x78, 0x69, 0x52, 0x8B, 0x6E, 0x95, 0x34, 0x3E, 0x43, + 0x37, 0x00, 0xCC, 0xB4, 0xD5, 0x64, 0x21, 0x05, 0xEC, 0x60, 0x0C, 0xEF, 0x49, 0x56, 0x12, 0x59, + 0xB8, 0x4A, 0xF8, 0x30, 0xC5, 0x78, 0xA8, 0x50, 0xEC, 0x9A, 0x46, 0xE9, 0x2B, 0xB6, 0xE6, 0x20, + 0x86, 0xBE, 0xF4, 0xCC, 0x2F, 0x24, 0xC5, 0xAB, 0xB5, 0xC4, 0xFD, 0xDE, 0xF2, 0x0B, 0xA8, 0x38, + 0xE4, 0x48, 0x3B, 0x2A, 0xE4, 0x80, 0x24, 0xAD, 0xFA, 0xCF, 0x39, 0x38, 0xA5, 0xC0, 0xA6, 0x3C, + 0xFA, 0x6C, 0xE2, 0x5E, 0x26, 0xFD, 0x83, 0x71, 0x5E, 0xFB, 0x79, 0x68, 0xD5, 0x32, 0xE8, 0xB3, + 0x08, 0x2D, 0x0D, 0xE5, 0x30, 0x72, 0x6B, 0x59, 0x34, 0x3F, 0x66, 0xD0, 0xFC, 0xB8, 0x44, 0x9A, + 0xBF, 0x64, 0xD0, 0xFC, 0x65, 0x59, 0x34, 0xFD, 0xA9, 0xE3, 0x3E, 0xF4, 0x29, 0xEE, 0x43, 0xCE, + 0xB4, 0xBB, 0x02, 0x91, 0x9B, 0x4B, 0x8C, 0x15, 0xFD, 0xBE, 0xCF, 0x14, 0xA0, 0x61, 0x96, 0xF4, + 0x13, 0xB6, 0xBC, 0xD1, 0xA8, 0xC7, 0xC8, 0x75, 0x36, 0x13, 0x9F, 0x8C, 0xCF, 0xE4, 0x4F, 0x80, + 0xD9, 0x68, 0x90, 0x1F, 0x7E, 0xC0, 0xA6, 0x7E, 0xEA, 0x86, 0x1F, 0xB4, 0xFE, 0x77, 0x26, 0x77, + 0xAB, 0x4C, 0x50, 0x68, 0xFA, 0x5E, 0xDD, 0x78, 0xAF, 0x1B, 0x73, 0xEC, 0xAE, 0xF8, 0x7C, 0x19, + 0x8F, 0xD1, 0x5F, 0xDA, 0x19, 0x28, 0x8A, 0x0D, 0xEB, 0x4C, 0x67, 0xFE, 0x5D, 0x65, 0xDB, 0x23, + 0xD0, 0x87, 0x51, 0x64, 0xD9, 0x24, 0xC2, 0x1A, 0xF5, 0xC8, 0xDC, 0x4E, 0xB8, 0x4B, 0x92, 0xC2, + 0x9E, 0x88, 0x66, 0xAC, 0xA8, 0x5D, 0xB7, 0x13, 0xEE, 0x50, 0x6B, 0xEC, 0xB2, 0x1C, 0x33, 0x08, + 0xBD, 0xD1, 0x78, 0x15, 0x78, 0xC4, 0x1C, 0xDB, 0x23, 0x67, 0xBF, 0x39, 0xA6, 0xB7, 0x41, 0x33, + 0xD5, 0x29, 0x3A, 0x10, 0xEB, 0x35, 0xCE, 0x6A, 0x0A, 0x8F, 0xD8, 0xA5, 0xEB, 0x58, 0x50, 0x1A, + 0x3C, 0x54, 0x84, 0xF2, 0x50, 0xAF, 0xD8, 0x54, 0x4B, 0x82, 0xC7, 0x29, 0xDD, 0xE7, 0x33, 0xE6, + 0x8D, 0xFB, 0xB5, 0x09, 0xEE, 0xDB, 0x7E, 0x53, 0xC7, 0x4F, 0x93, 0xB0, 0x49, 0xB9, 0x89, 0xC8, + 0x4E, 0x8E, 0x9A, 0x64, 0x08, 0x15, 0x7C, 0xF8, 0xD3, 0xF5, 0x26, 0x6B, 0x0C, 0x7A, 0x8D, 0xE3, + 0x93, 0x22, 0x2E, 0xD8, 0xDE, 0x78, 0xF3, 0x75, 0x59, 0x9E, 0xD6, 0x03, 0x55, 0x89, 0xCB, 0xF4, + 0x37, 0xDB, 0xA0, 0x4D, 0x75, 0x0C, 0x06, 0x1A, 0x22, 0xEF, 0xD5, 0x66, 0xE3, 0xD9, 0xCD, 0xD7, + 0xB3, 0xF8, 0xDE, 0x0B, 0x43, 0x0B, 0xCB, 0x36, 0xA2, 0x7E, 0xBE, 0xC6, 0x13, 0x86, 0xEB, 0xA3, + 0xAB, 0xB3, 0xC4, 0x77, 0xDC, 0xE6, 0xBC, 0xC6, 0x3D, 0xD4, 0x6B, 0xDC, 0xC4, 0x55, 0xD9, 0x91, + 0x82, 0x45, 0x85, 0x06, 0xDA, 0xD6, 0x5E, 0x66, 0x95, 0x4B, 0x1E, 0xE1, 0x91, 0xB6, 0x93, 0x09, + 0x34, 0xA7, 0xE6, 0x0D, 0x1D, 0xEB, 0xC3, 0x3C, 0xA4, 0x9A, 0x47, 0x22, 0x7A, 0x29, 0x86, 0x0B, + 0xA3, 0x98, 0xAE, 0x53, 0x6B, 0x60, 0x94, 0x88, 0x04, 0x16, 0x06, 0x31, 0xBD, 0xDE, 0x27, 0x1B, + 0x5A, 0xC3, 0x24, 0x07, 0xC1, 0xF2, 0x88, 0x2D, 0x09, 0x1A, 0x8C, 0xDA, 0x5E, 0x9E, 0xF8, 0xF6, + 0xD9, 0x55, 0x1F, 0xFD, 0x86, 0x44, 0x32, 0x84, 0xF6, 0x4F, 0xFB, 0x32, 0x9D, 0xCC, 0x4D, 0x8A, + 0x74, 0xE4, 0xAD, 0x04, 0x95, 0xB1, 0xDE, 0x97, 0x83, 0x78, 0x99, 0x16, 0xDE, 0xA5, 0x2D, 0x69, + 0xCA, 0x0D, 0x4E, 0x00, 0xCB, 0xBD, 0xA1, 0x4A, 0x00, 0x07, 0xCE, 0x35, 0x8B, 0x2A, 0x93, 0x3E, + 0xF7, 0x74, 0x82, 0x51, 0xF5, 0x07, 0x10, 0x65, 0xE8, 0x52, 0x4E, 0x3F, 0xED, 0xEF, 0x93, 0xCD, + 0x4C, 0xD9, 0xD4, 0x65, 0x55, 0xFB, 0x79, 0x43, 0xDB, 0xB5, 0x8C, 0xE3, 0x4D, 0xE3, 0x45, 0xEF, + 0xDA, 0x08, 0xF9, 0xE7, 0x7F, 0x95, 0xD9, 0x32, 0x51, 0x3F, 0xA4, 0x7A, 0xC5, 0xB2, 0xEF, 0x15, + 0x8B, 0xC3, 0x2E, 0x6B, 0x11, 0xCF, 0x7D, 0xE0, 0x06, 0x6B, 0xE2, 0x8F, 0x24, 0x1E, 0x23, 0x93, + 0x95, 0xEA, 0xC9, 0x14, 0xDE, 0x31, 0x93, 0x05, 0xA0, 0xE4, 0x46, 0x2F, 0x89, 0x20, 0xA4, 0x39, + 0x74, 0xC7, 0x6B, 0xFE, 0x64, 0x6D, 0x93, 0xE0, 0x2F, 0xDB, 0xEC, 0x27, 0x63, 0x83, 0x81, 0x37, + 0x5F, 0x27, 0x40, 0xB9, 0x80, 0x01, 0xFE, 0xE5, 0xAB, 0x75, 0x56, 0xA3, 0x98, 0x0F, 0xA9, 0x7D, + 0x0A, 0xAD, 0xCD, 0xA6, 0x6A, 0xA7, 0x79, 0xA8, 0x7D, 0xC2, 0xFA, 0xF2, 0xB3, 0xD7, 0x66, 0x11, + 0x91, 0xC8, 0xB4, 0xA7, 0x5A, 0xC9, 0xD7, 0x56, 0x72, 0x19, 0x33, 0x42, 0xE5, 0x44, 0x38, 0xCD, + 0xC2, 0x7B, 0xEC, 0x79, 0x6E, 0xCC, 0xAA, 0xED, 0x8C, 0x6D, 0x87, 0xF2, 0x6F, 0x30, 0x25, 0x4C, + 0x8B, 0x11, 0xAF, 0x83, 0x50, 0x5E, 0xF3, 0x9F, 0x95, 0xA6, 0x85, 0x89, 0x6C, 0xC4, 0x53, 0x3B, + 0x12, 0xA2, 0xF4, 0x44, 0xDC, 0x03, 0x44, 0x35, 0xD5, 0x9E, 0x22, 0xC9, 0x92, 0x60, 0x46, 0xEB, + 0x5D, 0x1F, 0xCC, 0x56, 0x5E, 0x2D, 0x44, 0x75, 0x89, 0x07, 0x61, 0x6C, 0x24, 0xC0, 0xD0, 0xED, + 0xE6, 0xD5, 0xF6, 0xB1, 0x52, 0x34, 0xEA, 0xF3, 0x6A, 0xCB, 0xAC, 0x4A, 0xF8, 0x7B, 0x1B, 0x46, + 0x19, 0x88, 0x98, 0x44, 0x0A, 0xA0, 0xD6, 0xBC, 0xC4, 0xC2, 0x6B, 0xDF, 0xC2, 0x42, 0x34, 0x48, + 0xFA, 0x67, 0x45, 0x73, 0x54, 0xB2, 0xDE, 0x3F, 0x66, 0xE0, 0x2A, 0xDD, 0xDA, 0x6C, 0x2F, 0x20, + 0x55, 0x21, 0xAB, 0x57, 0x0B, 0xFA, 0x0D, 0xFF, 0x29, 0x78, 0xA3, 0x0B, 0x9F, 0x8D, 0x02, 0x93, + 0x53, 0x73, 0xCE, 0x2C, 0xB4, 0xAB, 0x7B, 0xBF, 0x4F, 0xDB, 0x16, 0x0B, 0xF9, 0xBB, 0x9D, 0xFB, + 0x6D, 0xED, 0x1C, 0xBF, 0xEE, 0x82, 0x26, 0x2A, 0xD7, 0x8E, 0xC5, 0xD5, 0xAE, 0xDF, 0xBD, 0x3B, + 0x98, 0xC7, 0x10, 0x2C, 0xC7, 0xF9, 0x5C, 0xD0, 0x40, 0xFA, 0x5D, 0x78, 0x03, 0xE2, 0xB4, 0x8D, + 0x2F, 0xB8, 0xB4, 0x9C, 0x64, 0xAA, 0xB8, 0x3C, 0x60, 0x2C, 0x71, 0x15, 0x87, 0x4C, 0x6E, 0xD6, + 0x7A, 0x25, 0x9A, 0xEF, 0xF2, 0x83, 0x33, 0x31, 0x4A, 0x8C, 0xE6, 0xEB, 0x8B, 0xDB, 0xDB, 0x57, + 0xEB, 0xFC, 0x6B, 0x55, 0xE8, 0x6E, 0xF3, 0x35, 0xD7, 0xB8, 0x6E, 0x5D, 0x0C, 0xBD, 0x10, 0x43, + 0xAF, 0x3C, 0x86, 0x75, 0x2E, 0xB9, 0x92, 0x63, 0x2E, 0xAD, 0xBB, 0x30, 0x5C, 0x06, 0xE6, 0x3D, + 0x65, 0x57, 0x76, 0x50, 0xFA, 0xEC, 0xA6, 0x25, 0xE3, 0x87, 0x98, 0x3E, 0x79, 0xA0, 0x78, 0xE5, + 0xA6, 0x19, 0xB0, 0x58, 0x02, 0xAC, 0xC2, 0x4B, 0x1E, 0x69, 0xD0, 0x51, 0x28, 0xDC, 0x41, 0x5D, + 0xC7, 0x0D, 0xB0, 0x80, 0xDC, 0x50, 0xEA, 0x10, 0xD3, 0xB2, 0xF8, 0xAD, 0x9B, 0x68, 0xEF, 0x26, + 0xB1, 0x5E, 0x4D, 0xA6, 0xFD, 0xE1, 0xFB, 0x1F, 0x52, 0xE7, 0x26, 0x47, 0x4B, 0x3A, 0x17, 0x50, + 0xBD, 0x2D, 0x13, 0x41, 0x82, 0xDF, 0x4F, 0xB3, 0x0A, 0x9D, 0x21, 0xA9, 0x5E, 0x39, 0x4F, 0x44, + 0x02, 0x58, 0x98, 0x23, 0xF2, 0xAC, 0xED, 0x4F, 0x6A, 0x5B, 0x84, 0x4C, 0x82, 0xB5, 0x8D, 0xD2, + 0xB6, 0x27, 0xBD, 0xAB, 0xC2, 0x8D, 0x4A, 0xB6, 0x51, 0x7A, 0x2D, 0x42, 0x21, 0xB2, 0xAC, 0x4E, + 0x69, 0xA3, 0xC3, 0xA7, 0xDF, 0x8C, 0x6D, 0x9D, 0x66, 0xE6, 0x3E, 0x51, 0x75, 0x2B, 0x3B, 0xFF, + 0xD8, 0x8B, 0x0E, 0x78, 0x16, 0x35, 0xF6, 0x94, 0xBC, 0x59, 0xE5, 0x06, 0x9F, 0x9A, 0x4C, 0xAB, + 0xDE, 0xE8, 0x93, 0xE2, 0x55, 0x44, 0xD2, 0xA9, 0x47, 0xCD, 0xF0, 0x53, 0x93, 0x54, 0xE5, 0x0D, + 0x90, 0xB8, 0x56, 0x88, 0x2E, 0x74, 0xD8, 0xC1, 0x6D, 0xCE, 0x72, 0xD7, 0x63, 0x20, 0x31, 0x5C, + 0x54, 0x5A, 0xD9, 0x23, 0x26, 0xCD, 0x57, 0x38, 0x70, 0x54, 0x94, 0xBA, 0xB1, 0x83, 0xA2, 0xD0, + 0xA7, 0xE6, 0x0A, 0x77, 0x33, 0x5E, 0xE9, 0x53, 0x7B, 0x69, 0x3D, 0xFE, 0x0C, 0x4C, 0xAC, 0x4F, + 0x34, 0x1C, 0xEA, 0x2E, 0x71, 0xE4, 0x64, 0x01, 0x4B, 0xE2, 0x09, 0x65, 0x5B, 0x22, 0x74, 0x48, + 0x47, 0x47, 0x4A, 0xDE, 0x73, 0xE5, 0xBA, 0x64, 0x62, 0x3A, 0x8F, 0x32, 0x75, 0xE2, 0xF3, 0x86, + 0x36, 0xAA, 0x69, 0x12, 0x6A, 0xA3, 0xED, 0x8C, 0xA4, 0x5C, 0x69, 0xBA, 0x83, 0xD8, 0x74, 0xAD, + 0x6A, 0x5B, 0xA4, 0x4E, 0x0C, 0x98, 0x7D, 0xC2, 0x9E, 0xAE, 0x54, 0xE3, 0xB0, 0x92, 0xDD, 0xDD, + 0xCC, 0x6F, 0x4D, 0xBA, 0x52, 0xB5, 0xC6, 0xB8, 0x81, 0x19, 0x02, 0x66, 0x1E, 0xBD, 0xA6, 0xEA, + 0x54, 0x6E, 0x8A, 0xB8, 0x01, 0x71, 0x02, 0x1D, 0x1F, 0x5F, 0x9A, 0xD0, 0xDE, 0x4A, 0xD0, 0xD6, + 0xEC, 0xF8, 0xDE, 0xB0, 0xCE, 0x95, 0x82, 0x54, 0x3E, 0x2D, 0xED, 0xC9, 0xBF, 0x2E, 0xEB, 0x56, + 0xD5, 0xD3, 0x11, 0x91, 0x0B, 0x53, 0x7B, 0x3E, 0x12, 0xA5, 0xC9, 0xAC, 0x85, 0xD4, 0xC5, 0xCB, + 0x43, 0x19, 0x58, 0x79, 0xA6, 0xCD, 0xAA, 0x17, 0x44, 0xE8, 0x8D, 0xEB, 0x86, 0xC9, 0x5C, 0x0A, + 0x4E, 0x09, 0xB3, 0x4E, 0xE2, 0x12, 0x38, 0x3A, 0x7C, 0x86, 0xD2, 0xED, 0xD7, 0xAB, 0x01, 0x8F, + 0x78, 0x97, 0x54, 0x5C, 0xF1, 0xE8, 0x88, 0xE9, 0x4B, 0x9F, 0xC7, 0x49, 0x0A, 0x04, 0x88, 0x00, + 0x27, 0x18, 0x7C, 0xCE, 0xA0, 0x79, 0xEA, 0x19, 0xBF, 0x54, 0xA2, 0xAC, 0x8A, 0x2D, 0x30, 0x6A, + 0xF0, 0x1F, 0xE6, 0x7C, 0xCC, 0x88, 0x9A, 0xA9, 0xD7, 0x80, 0xE2, 0xF3, 0xC4, 0xDC, 0x2C, 0x3D, + 0x35, 0x3B, 0xB6, 0x08, 0x69, 0x89, 0x9E, 0x2E, 0x97, 0x3D, 0xA8, 0xBC, 0x02, 0xE4, 0xE3, 0x5B, + 0x80, 0x2A, 0x94, 0x6E, 0xB3, 0xB1, 0xB8, 0x16, 0xE7, 0xAB, 0xCC, 0xDC, 0x4D, 0xFE, 0xA6, 0xE6, + 0xBC, 0x3B, 0xE4, 0x99, 0x07, 0xC1, 0xFB, 0x0B, 0x93, 0xFD, 0x4D, 0xD0, 0x19, 0xC4, 0x9C, 0xC9, + 0x18, 0xD5, 0x0D, 0x06, 0xD7, 0x2F, 0xD2, 0x36, 0xD3, 0x09, 0xA8, 0xE3, 0x98, 0xEF, 0xA9, 0x3D, + 0xBA, 0x0B, 0xAE, 0x27, 0x93, 0x0C, 0xF3, 0x9D, 0xA8, 0xA6, 0x2A, 0x0C, 0x59, 0xC7, 0xE0, 0x0E, + 0x9E, 0xF0, 0x30, 0x8B, 0x53, 0xB6, 0x5A, 0x00, 0x69, 0x51, 0x1F, 0x6A, 0xF3, 0x80, 0xE6, 0x9B, + 0x59, 0x10, 0x28, 0x61, 0x0A, 0x25, 0x13, 0xE0, 0x05, 0xDE, 0x63, 0x46, 0x97, 0xE3, 0x4D, 0x8B, + 0x5C, 0xED, 0xFB, 0x06, 0x7E, 0x76, 0x30, 0xBC, 0x23, 0x2D, 0x8A, 0x5B, 0x58, 0x19, 0xEE, 0x96, + 0xE4, 0xC3, 0x0C, 0xC0, 0xD1, 0xBE, 0x02, 0x34, 0xC4, 0xF6, 0x7D, 0xF8, 0xC9, 0x22, 0x4F, 0x4E, + 0x8E, 0xC2, 0xA4, 0x84, 0x15, 0x47, 0x79, 0x41, 0xCE, 0xC0, 0xB2, 0xCD, 0xD2, 0xA9, 0x58, 0x9D, + 0x76, 0xB1, 0x10, 0xF1, 0x3A, 0x0D, 0x93, 0xFB, 0xF5, 0x60, 0x3C, 0x26, 0x1E, 0x1D, 0xCD, 0xC6, + 0x98, 0xF3, 0x91, 0xAD, 0xB1, 0x78, 0x1F, 0x47, 0xCB, 0x9B, 0x64, 0xF7, 0x56, 0x6A, 0x74, 0xB6, + 0x51, 0xAA, 0xDA, 0xE0, 0x93, 0x7A, 0xFD, 0xF7, 0x4D, 0x9B, 0x5B, 0x33, 0x8C, 0xA8, 0x23, 0x78, + 0x63, 0x8D, 0xCA, 0x21, 0x89, 0xEC, 0x36, 0x0B, 0xBF, 0xBA, 0x07, 0x23, 0xDC, 0x19, 0x51, 0xB1, + 0x8B, 0x91, 0xB8, 0x77, 0xD3, 0x6C, 0xEE, 0xC5, 0xF5, 0xD9, 0x15, 0x48, 0x71, 0xDF, 0xEF, 0xCC, + 0x1F, 0xE9, 0xAA, 0x86, 0x5C, 0x1C, 0xB9, 0xB8, 0x48, 0x9C, 0xF1, 0x3C, 0x89, 0xA0, 0x52, 0x18, + 0xDA, 0x04, 0x6B, 0x47, 0x0F, 0x6F, 0x36, 0xC2, 0xAA, 0x8D, 0x3C, 0xC0, 0xFA, 0x30, 0xF6, 0x7B, + 0xA0, 0x43, 0x6E, 0x5D, 0x91, 0xCD, 0x1C, 0xD4, 0x2F, 0x99, 0x66, 0x91, 0x0F, 0x10, 0x45, 0x74, + 0x39, 0x59, 0x8F, 0xE3, 0x2E, 0x7F, 0xEB, 0x82, 0x07, 0x0F, 0x9D, 0xC9, 0x63, 0xA4, 0x38, 0x33, + 0x52, 0x2F, 0x8F, 0xD2, 0x99, 0x83, 0xDE, 0xFF, 0x0A, 0x8D, 0xB2, 0x6C, 0x7F, 0x8A, 0x5D, 0xC6, + 0x12, 0xB3, 0xE3, 0xF5, 0x73, 0x72, 0x38, 0xF3, 0x61, 0xEE, 0xE4, 0x7F, 0xC3, 0xA2, 0x17, 0xC5, + 0xD5, 0x5C, 0x91, 0xFB, 0x44, 0x83, 0x6A, 0x40, 0x87, 0xF5, 0x71, 0x61, 0x9C, 0x1A, 0xFA, 0x81, + 0x03, 0x11, 0x19, 0x39, 0x3F, 0xA6, 0xB7, 0xE8, 0xAE, 0xD5, 0x47, 0xC3, 0xBC, 0xBD, 0x37, 0x2C, + 0x8A, 0x57, 0x4E, 0x06, 0xCB, 0x6F, 0x2A, 0x2D, 0x18, 0xE9, 0x3B, 0xEA, 0xD6, 0xC7, 0xC9, 0x7D, + 0x9D, 0xF3, 0xC0, 0xB3, 0xA7, 0x03, 0x0A, 0xC2, 0xF3, 0x16, 0x82, 0xEA, 0x70, 0x6C, 0xB3, 0x7B, + 0xD3, 0x75, 0x51, 0x61, 0xB0, 0x22, 0x06, 0x84, 0xE1, 0x50, 0x73, 0x30, 0x5A, 0x63, 0x3E, 0x9E, + 0xFA, 0xAE, 0xED, 0x04, 0x7D, 0xEA, 0xDD, 0xC2, 0x62, 0x55, 0x5A, 0x9B, 0xCF, 0x8B, 0xF6, 0x38, + 0x0C, 0x75, 0x9E, 0x31, 0xB3, 0xBF, 0x18, 0x64, 0xEF, 0x45, 0x84, 0x03, 0x7F, 0xE6, 0xC0, 0x1D, + 0x8D, 0x58, 0x2C, 0xC2, 0x9C, 0xB8, 0xFD, 0xE9, 0xB9, 0xFB, 0x30, 0x2F, 0x96, 0x53, 0xD7, 0x33, + 0xEB, 0xE3, 0x10, 0x7E, 0x46, 0xFF, 0x0E, 0xF5, 0x97, 0xE2, 0xE9, 0x26, 0xF3, 0x49, 0xE6, 0x65, + 0x69, 0x21, 0xF2, 0x11, 0x68, 0x2E, 0x4F, 0xCE, 0x8F, 0x7F, 0x9E, 0x17, 0xD7, 0xC1, 0x65, 0x7F, + 0x41, 0x5C, 0xE1, 0x02, 0xE4, 0x6D, 0x74, 0x87, 0xDA, 0x62, 0xF7, 0x02, 0xE6, 0xC7, 0x18, 0x2E, + 0x86, 0x6A, 0x22, 0xCA, 0x0A, 0x28, 0xAF, 0x86, 0x31, 0xC6, 0xC9, 0x67, 0x19, 0xB4, 0x8B, 0xF8, + 0xBA, 0x81, 0xB2, 0x13, 0xC2, 0x8B, 0xC2, 0xBB, 0x95, 0xA9, 0xE2, 0x60, 0x28, 0xCC, 0xCC, 0x1B, + 0xF4, 0x4B, 0x92, 0x45, 0xDC, 0x98, 0xA5, 0x8B, 0x66, 0xD6, 0x34, 0xFD, 0xD1, 0xBA, 0x1B, 0x4E, + 0x8F, 0x45, 0xAA, 0x04, 0x0D, 0x0B, 0xA7, 0x66, 0x80, 0x0B, 0x77, 0x4D, 0xC9, 0x61, 0x6A, 0x27, + 0xD4, 0x96, 0x50, 0x7F, 0x4B, 0x3E, 0xDD, 0xC1, 0xD6, 0x0A, 0xE0, 0x9D, 0x84, 0x33, 0xB3, 0x70, + 0x86, 0xFC, 0xE0, 0x11, 0x1C, 0x10, 0x14, 0xDF, 0x98, 0x3D, 0x94, 0xD2, 0x70, 0x5C, 0x87, 0x36, + 0x52, 0x0F, 0x7F, 0xB0, 0xC5, 0x55, 0x09, 0xE8, 0x1B, 0x58, 0x25, 0x7C, 0x89, 0xC0, 0xC1, 0x43, + 0xF7, 0x28, 0xCE, 0xF9, 0x87, 0x83, 0x1F, 0x31, 0x7A, 0x1B, 0x3D, 0x0B, 0x11, 0x63, 0xCC, 0x52, + 0x75, 0xCB, 0x04, 0xC4, 0x43, 0x07, 0xF1, 0xA3, 0x27, 0xFC, 0xF9, 0x03, 0x56, 0x19, 0xC1, 0x95, + 0x83, 0x8B, 0xF5, 0xF5, 0x93, 0xD8, 0x2D, 0x8C, 0xAB, 0x0F, 0xC7, 0xBE, 0x78, 0x81, 0x04, 0x1F, + 0x1A, 0x88, 0x72, 0x48, 0xFF, 0x63, 0x46, 0xBD, 0x47, 0xFE, 0xC8, 0x86, 0xEB, 0x81, 0x6F, 0xD9, + 0x6A, 0x74, 0xE4, 0xD3, 0xF1, 0x36, 0xE9, 0x28, 0x67, 0x7F, 0x8D, 0xBC, 0x54, 0xE5, 0x12, 0x09, + 0xB1, 0xED, 0x0A, 0xDF, 0x57, 0x57, 0x15, 0x87, 0x47, 0xE2, 0x7A, 0x75, 0x5F, 0x86, 0xF8, 0xF4, + 0xF5, 0x73, 0x47, 0x64, 0x1D, 0x67, 0x51, 0x19, 0x6A, 0x09, 0xF7, 0x4B, 0x59, 0x61, 0xDC, 0x89, + 0x61, 0x7B, 0xA5, 0xA5, 0x4E, 0x5B, 0xB7, 0xD2, 0x59, 0x5F, 0xBF, 0xA4, 0x13, 0xF7, 0x9E, 0xB2, + 0x5B, 0xA2, 0xB8, 0x43, 0x8A, 0xB7, 0x49, 0xD9, 0x1F, 0xA2, 0x42, 0x55, 0xD9, 0xC4, 0x07, 0x19, + 0x2F, 0x1D, 0x37, 0x68, 0x75, 0x92, 0x97, 0x54, 0x57, 0x42, 0xB1, 0x79, 0x4A, 0x6E, 0x86, 0x27, + 0x96, 0x59, 0xB8, 0x80, 0xD1, 0x4A, 0x4D, 0xC7, 0x8B, 0x7C, 0x31, 0xBB, 0x1C, 0x2F, 0xCA, 0x4D, + 0x6F, 0x20, 0x84, 0x39, 0xC7, 0x9B, 0xED, 0x26, 0xFC, 0x94, 0x70, 0x01, 0x2F, 0x95, 0x79, 0x88, + 0x6E, 0x6E, 0x57, 0xE3, 0x23, 0xBA, 0x12, 0xAE, 0xE3, 0x25, 0x2C, 0xAC, 0xC4, 0x4F, 0xEE, 0xA9, + 0x42, 0x21, 0x5B, 0x9A, 0x13, 0x19, 0x76, 0xFB, 0x51, 0x8F, 0x95, 0x33, 0xC6, 0x79, 0xCE, 0x39, + 0x40, 0xC8, 0xE4, 0x3F, 0xB1, 0x64, 0x72, 0xC0, 0x15, 0x1D, 0xF1, 0x95, 0x57, 0xCC, 0x56, 0xFA, + 0x35, 0x24, 0xB4, 0x2E, 0x2D, 0xB5, 0x02, 0xAF, 0x92, 0x78, 0x5F, 0x05, 0x64, 0x12, 0x3F, 0xC1, + 0xD2, 0x0A, 0x0B, 0xDB, 0xA4, 0x67, 0x18, 0xC6, 0x8A, 0xD6, 0x28, 0xB2, 0x5B, 0x2B, 0x60, 0x0B, + 0xDB, 0x84, 0xAD, 0x19, 0xF1, 0x40, 0x4D, 0x35, 0x92, 0xD8, 0x5A, 0x7E, 0xB5, 0x25, 0xB1, 0x04, + 0xC3, 0x00, 0x04, 0x56, 0xF0, 0x92, 0xA0, 0x30, 0x22, 0x70, 0x4E, 0x26, 0x22, 0x32, 0x1C, 0x53, + 0xD3, 0x0B, 0xA9, 0x94, 0x44, 0xDD, 0xD4, 0xB2, 0x3A, 0x98, 0x0D, 0x87, 0xB0, 0x70, 0x64, 0xCC, + 0xCA, 0x6F, 0x3C, 0x44, 0xB8, 0x44, 0x05, 0x1D, 0xA3, 0x4D, 0xFE, 0xCC, 0x83, 0x8E, 0xB7, 0x18, + 0x6D, 0x69, 0x8C, 0x7A, 0xFE, 0x60, 0x99, 0x1A, 0xF2, 0x26, 0xA4, 0x19, 0xAE, 0x15, 0xE3, 0xF7, + 0xB3, 0x6E, 0xC5, 0xDA, 0x5C, 0xBB, 0xD0, 0xD4, 0x2C, 0xFB, 0xC3, 0x7D, 0x0E, 0x3C, 0xA2, 0xC5, + 0x59, 0xBC, 0xE3, 0x31, 0x2B, 0xD9, 0x12, 0x77, 0x8E, 0x22, 0xFE, 0xF6, 0x0A, 0xC0, 0x30, 0xB8, + 0x59, 0xB9, 0xA7, 0x94, 0x71, 0xA0, 0xC1, 0xF7, 0x0F, 0xFE, 0x99, 0x58, 0xE9, 0x27, 0xF7, 0x28, + 0xAA, 0x33, 0x9A, 0x26, 0x5A, 0xC4, 0xA6, 0xAE, 0x69, 0x85, 0x8C, 0x6A, 0xE2, 0x8A, 0x72, 0xBA, + 0x5F, 0x74, 0x5A, 0x3C, 0x04, 0x64, 0xAD, 0x92, 0x7B, 0xB4, 0x21, 0xF4, 0x5C, 0x3C, 0x16, 0x12, + 0xC7, 0x18, 0xA6, 0x94, 0x49, 0xD2, 0x81, 0xA4, 0xAF, 0xA1, 0xD7, 0x20, 0xF6, 0x26, 0x17, 0x62, + 0x67, 0x61, 0x4C, 0x62, 0xDB, 0x55, 0xC6, 0x8A, 0x13, 0x84, 0x7C, 0xEB, 0xE3, 0xC3, 0x9B, 0x9F, + 0x65, 0x55, 0x65, 0xE5, 0x62, 0x46, 0x61, 0xE5, 0x8C, 0xBC, 0x01, 0x43, 0x7E, 0x6B, 0x0B, 0x18, + 0x3F, 0x03, 0x2F, 0x12, 0x13, 0xC6, 0xDC, 0xD0, 0xE0, 0x01, 0x8F, 0xC6, 0x0D, 0xB6, 0x07, 0x05, + 0x65, 0x8D, 0x36, 0x5A, 0xBE, 0xF1, 0xD8, 0x9C, 0xFA, 0x14, 0x13, 0x77, 0xF2, 0xF4, 0x39, 0x6C, + 0xA7, 0x25, 0xA5, 0xDC, 0x3A, 0x1E, 0x70, 0x29, 0xBD, 0x54, 0x3E, 0x90, 0x40, 0x29, 0x5E, 0x30, + 0xE1, 0x5F, 0x29, 0x4E, 0xB6, 0xB3, 0x19, 0xD9, 0x9E, 0x53, 0x1E, 0xC8, 0x43, 0x69, 0x89, 0xD4, + 0xE3, 0x23, 0x4B, 0x1E, 0xA2, 0xEE, 0x80, 0x4F, 0x44, 0x60, 0xF3, 0x87, 0x3C, 0x7F, 0xC1, 0x10, + 0x56, 0x3E, 0x8A, 0x29, 0x17, 0x25, 0xBA, 0x31, 0x8A, 0xBA, 0x1E, 0x0D, 0x34, 0xA8, 0xCA, 0x61, + 0x75, 0x83, 0x19, 0xA6, 0xAF, 0x35, 0x56, 0xBA, 0x86, 0x9E, 0x66, 0x55, 0x98, 0xD9, 0x34, 0x17, + 0x82, 0x8F, 0x7E, 0x0D, 0x09, 0xB5, 0xC9, 0xE0, 0x67, 0xDA, 0xB8, 0x80, 0x78, 0x6B, 0xD3, 0xB1, + 0xE5, 0xB7, 0xA4, 0xB7, 0x7E, 0x0E, 0x85, 0x30, 0x84, 0xA3, 0x3E, 0x94, 0x12, 0xFE, 0x24, 0xE5, + 0x14, 0x09, 0x59, 0xEC, 0x31, 0x8A, 0xF4, 0x51, 0x20, 0xFD, 0x70, 0xA7, 0x12, 0x59, 0x88, 0xDC, + 0xC2, 0x4C, 0xF0, 0xB8, 0x8F, 0x10, 0x16, 0x13, 0x27, 0x54, 0x06, 0x44, 0x25, 0x13, 0xB0, 0xF0, + 0x6B, 0x49, 0xF0, 0x37, 0x71, 0x96, 0x3B, 0x80, 0x65, 0x39, 0xEF, 0x6A, 0xD0, 0x65, 0x4A, 0x25, + 0xE0, 0xCB, 0xD3, 0xEE, 0xF7, 0x25, 0x69, 0xC9, 0xDB, 0x43, 0x25, 0xC1, 0xA5, 0x5C, 0x78, 0x0C, + 0x03, 0xFE, 0x59, 0x0E, 0xF4, 0x27, 0xFB, 0xAD, 0x1D, 0x43, 0x3E, 0xD8, 0xB7, 0x76, 0x49, 0xC0, + 0xAB, 0xC3, 0xFE, 0x87, 0x23, 0x89, 0x6D, 0x58, 0xE5, 0x7E, 0xB0, 0xA6, 0x25, 0x81, 0x59, 0x38, + 0x7A, 0x0C, 0xCB, 0x16, 0x0C, 0x25, 0x41, 0xD3, 0x8B, 0xDC, 0xC7, 0x18, 0x91, 0xE4, 0x3F, 0x96, + 0x44, 0x37, 0x78, 0xF4, 0x03, 0x3A, 0x89, 0x31, 0xF8, 0xFC, 0xEF, 0x72, 0xC0, 0xC7, 0x6A, 0x42, + 0x43, 0x00, 0x8F, 0x52, 0x1C, 0x96, 0x43, 0x70, 0x7E, 0x25, 0x49, 0x10, 0xB3, 0x1E, 0x96, 0x03, + 0x7B, 0x2B, 0x3D, 0xC8, 0x04, 0x80, 0xF2, 0x42, 0x2C, 0x42, 0x20, 0xFC, 0x8C, 0xF4, 0x44, 0xC8, + 0x07, 0xB6, 0x18, 0xA4, 0x84, 0x93, 0x4F, 0xDB, 0x57, 0x9E, 0x68, 0x25, 0x4E, 0x4B, 0x80, 0xF7, + 0x28, 0xDA, 0xF8, 0x9A, 0xDE, 0xE6, 0xAE, 0x64, 0x6B, 0x59, 0xA2, 0xE2, 0xCD, 0x5D, 0x80, 0x34, + 0x3D, 0x73, 0x88, 0xE7, 0x80, 0xB2, 0xB5, 0x55, 0x0D, 0xC1, 0x8A, 0x44, 0x9D, 0x25, 0xB6, 0xCE, + 0x22, 0xCD, 0x4D, 0xBB, 0x66, 0x73, 0xBF, 0x8D, 0x8F, 0x9D, 0x19, 0x46, 0xB7, 0xD7, 0x66, 0x4F, + 0xB6, 0xA5, 0x2D, 0x3E, 0x2F, 0x65, 0x76, 0xBF, 0x6B, 0x30, 0x00, 0x9D, 0x55, 0x89, 0xC4, 0x8B, + 0x34, 0x0F, 0xE5, 0x24, 0x7D, 0x7C, 0xB3, 0x24, 0x9B, 0x23, 0x9E, 0x58, 0xAF, 0xC1, 0xE6, 0x9C, + 0x5D, 0x23, 0x73, 0xCE, 0xD9, 0x35, 0xCA, 0x50, 0x4E, 0xE1, 0x3E, 0x3C, 0xBF, 0x98, 0x0F, 0x75, + 0xEC, 0x11, 0x67, 0x6D, 0x80, 0x47, 0xA7, 0x7B, 0x1A, 0x5F, 0x59, 0xD7, 0xFB, 0x4E, 0x0C, 0x7D, + 0x68, 0x82, 0x9C, 0xBC, 0xF7, 0xAE, 0x1F, 0x08, 0x3D, 0xD8, 0x4A, 0xE9, 0xC1, 0x56, 0x86, 0x1E, + 0x68, 0x24, 0x90, 0x21, 0x85, 0x14, 0x3D, 0xB4, 0x6C, 0x9C, 0xDE, 0x2E, 0xFE, 0x4B, 0x92, 0x64, + 0x1F, 0x2B, 0x92, 0xD2, 0xB4, 0x8D, 0x3D, 0xD3, 0xC6, 0xB6, 0xE5, 0x39, 0xAD, 0x0D, 0x23, 0x49, + 0x68, 0xC3, 0xA8, 0xDF, 0x36, 0xDE, 0x92, 0x0F, 0x3E, 0xF5, 0xB2, 0x05, 0x9A, 0x2E, 0xC0, 0xFA, + 0xCC, 0x36, 0x06, 0x5F, 0x7A, 0x23, 0xB7, 0x33, 0x74, 0x27, 0xF8, 0x17, 0x7E, 0x25, 0x13, 0xE4, + 0x0C, 0x13, 0x2A, 0x83, 0xB1, 0xB1, 0xC1, 0xD9, 0x9D, 0x98, 0xF6, 0x18, 0xAF, 0x68, 0x7A, 0xE0, + 0x40, 0x15, 0xF0, 0x16, 0x1D, 0x34, 0x12, 0x7E, 0xC6, 0x87, 0xF7, 0x8F, 0x1F, 0xC0, 0x86, 0x8A, + 0x33, 0x4B, 0xBC, 0x36, 0x2A, 0x72, 0x2B, 0xFA, 0x04, 0x2C, 0x19, 0xED, 0x10, 0x4E, 0xD1, 0x7C, + 0x24, 0x0F, 0x26, 0x18, 0x11, 0x10, 0x85, 0x65, 0xFB, 0xEC, 0xAE, 0xEC, 0xF9, 0xD5, 0xE5, 0x49, + 0x1F, 0xB7, 0x9C, 0xD8, 0x55, 0xD1, 0xB1, 0xCB, 0xF9, 0x21, 0xF4, 0x2B, 0x38, 0x1E, 0xB8, 0x9D, + 0x17, 0xA6, 0x0E, 0xEC, 0x44, 0x24, 0xE5, 0x45, 0x0F, 0xFC, 0xC9, 0xF7, 0xA0, 0x70, 0x2D, 0xCB, + 0xE5, 0x94, 0x23, 0x1D, 0x49, 0x08, 0x61, 0x4B, 0xCA, 0x21, 0x10, 0xFA, 0xD3, 0xEB, 0x1A, 0xDD, + 0xB2, 0x80, 0x8A, 0x32, 0x34, 0x6E, 0xC6, 0x96, 0x77, 0x3D, 0x98, 0x9A, 0xDE, 0x97, 0xB7, 0x33, + 0xA7, 0xDB, 0xA8, 0x8E, 0xA4, 0xFF, 0x53, 0x45, 0x96, 0xC3, 0x8E, 0x0F, 0xA8, 0x1F, 0xFC, 0x1F, + 0xFC, 0x51, 0xA3, 0xD9, 0x88, 0x03, 0x08, 0x03, 0x96, 0x24, 0xE0, 0x48, 0x1D, 0x65, 0x57, 0x22, + 0x83, 0xE5, 0xBB, 0x77, 0x07, 0x59, 0x37, 0x6A, 0x00, 0x30, 0xB5, 0xEB, 0x88, 0xDE, 0x20, 0x2C, + 0x59, 0xA2, 0xB4, 0xFF, 0xD2, 0xAE, 0xEB, 0xFA, 0xFA, 0x84, 0x2D, 0x24, 0xB1, 0x8A, 0x6D, 0xF9, + 0xC4, 0x0F, 0x4C, 0x8F, 0xE9, 0x03, 0x53, 0xB0, 0x44, 0xB4, 0x6B, 0x6C, 0xB1, 0x9E, 0x3A, 0x65, + 0x24, 0xAE, 0x12, 0x63, 0x66, 0xF2, 0x37, 0x40, 0x9B, 0x3C, 0x9F, 0x8E, 0x6D, 0xFD, 0xDB, 0x7E, + 0x82, 0xFF, 0xCF, 0xCA, 0x62, 0x5A, 0xB7, 0x93, 0x26, 0xD1, 0xC8, 0xDC, 0x3E, 0xD3, 0xDF, 0xDE, + 0x97, 0x20, 0xF9, 0x8E, 0xE7, 0x9E, 0xE6, 0x1E, 0x6A, 0x72, 0x1D, 0x9B, 0x71, 0xE1, 0x5A, 0xC9, + 0xA1, 0x56, 0xBE, 0x7F, 0x58, 0xB4, 0xC1, 0x82, 0x65, 0xC6, 0x70, 0x3E, 0x37, 0xB9, 0xB1, 0x95, + 0x66, 0xBE, 0xEC, 0xF4, 0x63, 0x00, 0x97, 0xA9, 0xBA, 0x51, 0x50, 0xF1, 0xC9, 0x03, 0xA9, 0x15, + 0xA5, 0xC5, 0x9A, 0x0C, 0xAD, 0x2D, 0x96, 0xE9, 0xA4, 0x9E, 0x40, 0x27, 0xD5, 0xA4, 0xC9, 0x76, + 0x0F, 0x8A, 0xF5, 0x70, 0xCE, 0x26, 0xC7, 0xD1, 0x33, 0xFF, 0xF3, 0xDA, 0x5D, 0x72, 0x08, 0x3D, + 0x5D, 0xB3, 0xEB, 0x0C, 0x1F, 0xF5, 0x59, 0x37, 0x9E, 0x39, 0x39, 0x0C, 0x33, 0x2E, 0x31, 0x88, + 0xF2, 0x5E, 0x85, 0x9B, 0x43, 0xC4, 0xA9, 0x30, 0xF1, 0xDF, 0x50, 0xCC, 0x8A, 0x6B, 0x2C, 0x01, + 0xE3, 0x32, 0x08, 0x9C, 0x54, 0x7C, 0x1F, 0x46, 0xBF, 0x0A, 0xEA, 0xF2, 0x9D, 0x2F, 0x2C, 0xCF, + 0xDF, 0x84, 0x5B, 0xAC, 0x7A, 0x26, 0x03, 0xE6, 0x7F, 0xAF, 0xA2, 0x8B, 0xF6, 0x0D, 0xB3, 0x55, + 0x9C, 0xE5, 0xEB, 0x96, 0xD7, 0xB7, 0xE1, 0xA2, 0x4C, 0x73, 0x35, 0xAC, 0xEC, 0x9A, 0x4C, 0x2C, + 0x91, 0xDC, 0x1B, 0x1F, 0xA5, 0xCC, 0x32, 0xD3, 0xD3, 0xA1, 0xEB, 0x58, 0xE8, 0xF2, 0x6F, 0x1B, + 0xAC, 0x51, 0x9A, 0x26, 0x6D, 0x1B, 0xE2, 0x2D, 0x21, 0xB9, 0x39, 0x6F, 0xF4, 0x0F, 0x3A, 0xE4, + 0x53, 0xEB, 0xBB, 0xBE, 0x8D, 0xFF, 0x3F, 0x18, 0x0E, 0x67, 0xB0, 0x10, 0x7A, 0xE4, 0x4B, 0xA5, + 0x2D, 0x94, 0x67, 0x8A, 0x6A, 0xB7, 0xC3, 0xC8, 0x6E, 0x75, 0xF2, 0xC8, 0x4A, 0x84, 0x15, 0x6F, + 0x96, 0x5D, 0x2C, 0x3B, 0x66, 0x99, 0xDE, 0xDA, 0x64, 0xAD, 0xDB, 0xDB, 0x31, 0x7A, 0xC6, 0x76, + 0x67, 0x6B, 0x7B, 0x47, 0xE1, 0x55, 0x0F, 0xF2, 0x11, 0x41, 0x36, 0x5F, 0x74, 0xB7, 0x77, 0x8C, + 0xCD, 0xCE, 0xA6, 0xB1, 0x51, 0x02, 0xE4, 0x17, 0x00, 0xD9, 0x34, 0x76, 0xB6, 0xB7, 0xB7, 0xB7, + 0x3A, 0x9B, 0x3B, 0x9B, 0x05, 0x10, 0xA7, 0x66, 0xC0, 0x12, 0xDA, 0x23, 0x4C, 0xC7, 0xD8, 0x35, + 0x7A, 0xBB, 0x9B, 0x2F, 0x76, 0x8B, 0x60, 0x5C, 0x67, 0x24, 0x80, 0xD6, 0xBA, 0x06, 0x48, 0x6C, + 0x67, 0xCB, 0xD8, 0x7A, 0xB1, 0xDD, 0x2D, 0x00, 0x3B, 0x18, 0x07, 0x76, 0x30, 0xB3, 0xD8, 0xBE, + 0xCB, 0xD6, 0x36, 0x50, 0xDB, 0xD9, 0x4D, 0x2C, 0xE3, 0x92, 0xA7, 0x48, 0x2A, 0x92, 0x0C, 0x4D, + 0xC9, 0xA6, 0x9A, 0xDF, 0xD9, 0xD0, 0x99, 0x6A, 0xAF, 0x85, 0x3A, 0x9D, 0x7F, 0xBB, 0x30, 0x4F, + 0xBD, 0xEB, 0xCA, 0x78, 0x0E, 0x39, 0x57, 0x93, 0x75, 0x91, 0x69, 0x49, 0xE8, 0xEA, 0x0B, 0x83, + 0xFD, 0x6B, 0x93, 0xE8, 0x97, 0x68, 0x64, 0x84, 0x65, 0x38, 0x2C, 0xC4, 0xAF, 0x25, 0x46, 0x64, + 0x11, 0xD5, 0x8F, 0xBF, 0x09, 0xD5, 0x5F, 0x96, 0x42, 0xF5, 0x5B, 0xFE, 0x0D, 0xEE, 0x1A, 0x36, + 0xA2, 0xA6, 0x9D, 0xA8, 0x66, 0x2B, 0x34, 0x62, 0x8B, 0x6F, 0x68, 0xC1, 0x54, 0xF0, 0x23, 0xF5, + 0xF0, 0x21, 0x05, 0xF8, 0xB6, 0xCE, 0xE2, 0xAD, 0xE2, 0x04, 0x1D, 0xE5, 0x04, 0x2E, 0x69, 0xE6, + 0x5A, 0xB7, 0x6B, 0x6C, 0x6C, 0xB6, 0xC9, 0xCE, 0x8E, 0xB2, 0x09, 0xCB, 0x3F, 0xA3, 0xB0, 0xB1, + 0xA0, 0x94, 0xC1, 0xCD, 0x20, 0x98, 0x8C, 0xBE, 0x40, 0x92, 0xF8, 0x96, 0xC6, 0x96, 0x42, 0x6D, + 0x8B, 0xBD, 0x4E, 0xB1, 0x55, 0x5F, 0x91, 0xF4, 0x97, 0x2F, 0x81, 0x58, 0x8F, 0xCF, 0xCB, 0xBD, + 0xC4, 0xF4, 0xCC, 0xBF, 0xF3, 0x37, 0x34, 0x8C, 0x4E, 0x05, 0x5D, 0xFA, 0x96, 0xB3, 0x27, 0x1A, + 0xDD, 0x2F, 0xAE, 0xB5, 0x27, 0xCA, 0xA1, 0xE3, 0x4D, 0xAA, 0x6B, 0xA3, 0xF4, 0xEE, 0xB8, 0x0C, + 0xCF, 0x38, 0x37, 0x4A, 0xED, 0x8A, 0xCA, 0x14, 0x71, 0x57, 0x2B, 0xA4, 0x98, 0xBF, 0x2F, 0x5A, + 0x81, 0x58, 0x66, 0xFB, 0x70, 0x33, 0x89, 0x51, 0x33, 0x12, 0xED, 0x33, 0xE6, 0x6D, 0x5F, 0x2E, + 0xC9, 0xFE, 0x4F, 0x4F, 0x46, 0x34, 0xDE, 0xAD, 0x5B, 0x4E, 0x3F, 0xE6, 0x92, 0x7C, 0xC2, 0x76, + 0x4A, 0xFA, 0xDA, 0xAD, 0x4F, 0xB2, 0x5B, 0x4F, 0x5F, 0x05, 0xC5, 0xA4, 0xBE, 0x1A, 0xF9, 0xFA, + 0xDA, 0xAD, 0xA9, 0xAF, 0x4B, 0x69, 0x5F, 0x91, 0xBE, 0x3E, 0x15, 0x51, 0x49, 0x5F, 0x9F, 0x9E, + 0xE4, 0x13, 0xB6, 0x53, 0xD2, 0xD7, 0x5E, 0x7D, 0x92, 0xBD, 0x7A, 0xFA, 0xDA, 0xAB, 0xA5, 0xAF, + 0xBD, 0x9A, 0xFA, 0xBA, 0x94, 0xF6, 0x15, 0xE9, 0xEB, 0x53, 0x11, 0x95, 0xF4, 0xF5, 0xE9, 0x49, + 0x3E, 0x61, 0x3B, 0x25, 0x7D, 0xDD, 0xA8, 0x4F, 0x72, 0xA3, 0x9E, 0xBE, 0x6E, 0xD4, 0xD2, 0xD7, + 0x8D, 0x9A, 0xFA, 0xBA, 0x94, 0xF6, 0x15, 0xE9, 0xEB, 0x53, 0x11, 0x95, 0xF4, 0xF5, 0xE9, 0x49, + 0x2E, 0xAA, 0x9D, 0xFF, 0x02, 0x47, 0xBD, 0x5A, 0x2F, 0xBA, 0xDA, 0x61, 0xAF, 0xD6, 0x2D, 0x2E, + 0x77, 0xDC, 0xAB, 0xF5, 0x71, 0x2B, 0x1F, 0xBB, 0x66, 0xB8, 0xAD, 0x8D, 0xD2, 0xA0, 0x09, 0xE7, + 0x93, 0x9F, 0x38, 0x5B, 0x0F, 0x4E, 0xF0, 0xE0, 0xF4, 0x6A, 0x20, 0x09, 0xE9, 0xFF, 0x74, 0xB9, + 0xF5, 0x70, 0xE9, 0x6E, 0xBE, 0xAF, 0xD8, 0x84, 0xC8, 0x39, 0x6C, 0xD4, 0x11, 0x3E, 0x73, 0x0C, + 0x6A, 0x48, 0xBE, 0x0E, 0x41, 0xC9, 0xE7, 0xAA, 0x25, 0xEC, 0xBA, 0x80, 0x95, 0x69, 0x26, 0xBC, + 0x98, 0x5A, 0x82, 0xED, 0xD5, 0x14, 0x6C, 0xAF, 0xBE, 0x60, 0x7B, 0x75, 0x05, 0xDB, 0xAB, 0x2F, + 0xD8, 0x5E, 0x5D, 0xC1, 0x6E, 0xD4, 0x15, 0xEC, 0x46, 0x4D, 0xC1, 0x6E, 0xD4, 0x17, 0xEC, 0x46, + 0x5D, 0xC1, 0x6E, 0xD4, 0x17, 0x6C, 0x0A, 0x54, 0x3A, 0xAC, 0x90, 0xE3, 0x91, 0xB5, 0x87, 0x16, + 0x45, 0x61, 0xCB, 0x79, 0x3B, 0x28, 0x61, 0x6A, 0x05, 0x96, 0xB1, 0x40, 0xC2, 0x70, 0xC4, 0x1E, + 0xCA, 0x12, 0x37, 0x04, 0xAF, 0xDC, 0x2F, 0xD4, 0x09, 0x73, 0x7D, 0xEC, 0xA9, 0x3B, 0xCC, 0xEC, + 0x5B, 0x94, 0x45, 0x3F, 0xF5, 0xF2, 0x88, 0xF6, 0xCE, 0x62, 0x3E, 0x9D, 0x36, 0xD9, 0xD8, 0xE6, + 0xFF, 0x45, 0x93, 0xEB, 0xC6, 0x76, 0xD6, 0x15, 0xC6, 0xBE, 0xFE, 0x02, 0x55, 0xFE, 0xCE, 0x7B, + 0x21, 0x03, 0x8D, 0x46, 0x2A, 0x20, 0x79, 0x16, 0xB8, 0x7F, 0xA3, 0x8F, 0x97, 0xD4, 0xA1, 0x0F, + 0xE6, 0x38, 0xEB, 0x2E, 0x8E, 0xD2, 0x6B, 0x5E, 0x5E, 0x6F, 0x25, 0xA3, 0xC1, 0x2B, 0x9E, 0x32, + 0x51, 0x19, 0x1C, 0xA3, 0x9F, 0xDE, 0xF0, 0x93, 0x1D, 0x8E, 0x8E, 0x6D, 0x91, 0x6C, 0x1B, 0xA9, + 0x8D, 0xDF, 0x2E, 0x3F, 0x6B, 0x6A, 0xE3, 0xD7, 0xC4, 0xA6, 0x6F, 0x3F, 0xE3, 0xB9, 0xEE, 0x22, + 0xDA, 0xA7, 0xAC, 0xE3, 0x17, 0x45, 0x51, 0x92, 0x1F, 0x5E, 0x7C, 0x2E, 0xBC, 0xFD, 0x8A, 0xF7, + 0xA1, 0xCF, 0xA1, 0xE5, 0xAE, 0xF7, 0xE5, 0xDA, 0x18, 0x0C, 0x4E, 0x8E, 0x4A, 0x3B, 0x66, 0x9A, + 0xFB, 0xD5, 0xBA, 0xDB, 0x9F, 0x5A, 0x42, 0x7D, 0xD3, 0xF7, 0xE1, 0x37, 0xEB, 0x29, 0x88, 0x75, + 0x9F, 0xAA, 0x55, 0xDD, 0xA7, 0x6C, 0x55, 0xEF, 0xA9, 0x5A, 0xD5, 0x7B, 0xCA, 0x56, 0x6D, 0x3C, + 0x55, 0xAB, 0x36, 0x16, 0xD5, 0xAA, 0x70, 0xB0, 0x5D, 0x1D, 0xF6, 0xD7, 0x3F, 0x1C, 0xF5, 0x73, + 0xEC, 0xD5, 0xD5, 0xB0, 0xFA, 0x2D, 0x65, 0x61, 0x2F, 0xA2, 0xD0, 0xFB, 0xF8, 0xB2, 0xF0, 0xF6, + 0xD6, 0xD6, 0x46, 0xEA, 0x7E, 0x32, 0xFB, 0x28, 0x33, 0xAB, 0x84, 0x30, 0x14, 0xAD, 0xD5, 0x22, + 0x2A, 0xD2, 0x15, 0xE8, 0xF2, 0x57, 0xE1, 0xB5, 0xA4, 0xBE, 0x65, 0x08, 0xA2, 0xF2, 0xD1, 0x44, + 0x2C, 0x08, 0x0E, 0xBA, 0x10, 0x41, 0x68, 0xB9, 0xFB, 0x60, 0xD5, 0xE6, 0x6E, 0x66, 0x2D, 0x81, + 0xBB, 0xF5, 0xF5, 0x0B, 0x87, 0x84, 0x61, 0x18, 0x6D, 0x02, 0x55, 0x09, 0xEF, 0x25, 0x76, 0x8F, + 0x83, 0xD3, 0x63, 0x4F, 0xBC, 0xE3, 0xC2, 0x15, 0x28, 0xF0, 0x56, 0x58, 0xF8, 0x8A, 0x3C, 0xAE, + 0x60, 0x7D, 0xBC, 0x50, 0x12, 0xC0, 0xF4, 0x16, 0x5D, 0xDC, 0x98, 0x01, 0x16, 0xD7, 0x21, 0xA8, + 0xC7, 0x6D, 0xAC, 0xF2, 0x28, 0x1E, 0x88, 0xEF, 0x74, 0xA2, 0xC5, 0x2D, 0x8F, 0x1B, 0x10, 0x59, + 0xD9, 0xCE, 0x66, 0x01, 0xFD, 0x9A, 0x56, 0x62, 0x0C, 0x05, 0x49, 0x74, 0x27, 0x7C, 0xAA, 0xCD, + 0x5E, 0xAE, 0x38, 0xA2, 0x70, 0x7F, 0x96, 0x03, 0x20, 0x7B, 0x88, 0x89, 0x8C, 0x29, 0x15, 0xBB, + 0x6D, 0x0C, 0x50, 0xD1, 0xC1, 0x3E, 0x38, 0x7C, 0x6F, 0x3D, 0xFA, 0x8F, 0x19, 0x75, 0xD8, 0x95, + 0x80, 0x5D, 0x63, 0x03, 0x7E, 0xF4, 0x5E, 0x48, 0x5D, 0x08, 0x9F, 0xD8, 0x86, 0x53, 0xEF, 0x85, + 0xCC, 0xB3, 0x1C, 0xEF, 0x53, 0x30, 0xFB, 0x23, 0x3D, 0x10, 0x8C, 0x6D, 0x8E, 0xD9, 0x7D, 0x22, + 0x93, 0x79, 0x99, 0x22, 0xFE, 0xFA, 0x1A, 0xC7, 0x54, 0x37, 0x75, 0xD7, 0xA5, 0xAB, 0xBB, 0xE3, + 0xA2, 0x23, 0x29, 0x5F, 0x42, 0x93, 0x92, 0xC5, 0x16, 0x04, 0xA2, 0xA4, 0x82, 0xD2, 0xFD, 0x53, + 0xFB, 0x96, 0x8A, 0x6E, 0xC1, 0xE3, 0xD1, 0x9E, 0xCC, 0x0C, 0x3F, 0x1D, 0xED, 0x29, 0xBC, 0x64, + 0xC7, 0x2C, 0xAD, 0x28, 0x09, 0x2C, 0x7C, 0xE8, 0x10, 0x96, 0xED, 0xAA, 0x80, 0xA3, 0x45, 0x9E, + 0xD3, 0x3E, 0xE9, 0xF9, 0x6C, 0xD8, 0x54, 0x1E, 0x75, 0x95, 0xAB, 0xAB, 0x61, 0xD2, 0x9A, 0x8A, + 0xEA, 0x3A, 0x31, 0xBF, 0x02, 0xEC, 0x95, 0x1D, 0x86, 0x2B, 0x75, 0x8D, 0x2D, 0xE8, 0x8C, 0x94, + 0xCB, 0xD8, 0x6D, 0xC3, 0xF7, 0x76, 0x4F, 0x55, 0x19, 0x25, 0x16, 0xAC, 0x40, 0x4D, 0x39, 0x1D, + 0xD9, 0x3B, 0x9D, 0x9B, 0x52, 0xA9, 0xA5, 0x85, 0xD2, 0xBE, 0x6D, 0x83, 0xFC, 0x85, 0xF4, 0x72, + 0xAE, 0x2C, 0x25, 0xB8, 0x4C, 0xD4, 0xCF, 0x38, 0x1E, 0x57, 0x72, 0x06, 0x55, 0x14, 0x7F, 0x0C, + 0x1B, 0xDE, 0x06, 0x8C, 0x5C, 0xF7, 0xB4, 0xD7, 0xBE, 0x20, 0x91, 0xE8, 0x69, 0x1A, 0x45, 0xAD, + 0xD4, 0xE5, 0x33, 0xAA, 0xD8, 0x5A, 0x53, 0xC2, 0xC1, 0x26, 0x84, 0x30, 0xE7, 0x67, 0x7C, 0x32, + 0xAF, 0x3F, 0x9A, 0xDF, 0x5D, 0x4C, 0xCB, 0x73, 0xE8, 0x97, 0x69, 0x7E, 0x2A, 0x13, 0x6D, 0xB9, + 0x56, 0xAB, 0xA9, 0x6F, 0xB9, 0x87, 0xD8, 0xDB, 0xDD, 0xDC, 0xDD, 0x7E, 0x91, 0x72, 0x13, 0xDB, + 0xF0, 0xBD, 0x0D, 0x05, 0x8B, 0x69, 0x6E, 0x8A, 0x30, 0xBB, 0x60, 0x83, 0xEF, 0xA4, 0x89, 0x8D, + 0xEA, 0x8C, 0x16, 0x57, 0xCF, 0xAF, 0x5A, 0x4E, 0x10, 0x05, 0x89, 0x5F, 0x79, 0x68, 0xBA, 0xB1, + 0xB9, 0xA3, 0xE8, 0xBE, 0x98, 0xAB, 0x36, 0xDB, 0x3B, 0x8B, 0xD2, 0xFF, 0x62, 0x36, 0x0A, 0xE4, + 0xB4, 0xBE, 0x1E, 0x7A, 0x50, 0xB1, 0xDC, 0x32, 0xC3, 0x71, 0x32, 0x44, 0x72, 0xD2, 0x3F, 0xE0, + 0x01, 0x68, 0xAD, 0x28, 0x06, 0xF6, 0xA4, 0xDF, 0x90, 0xDA, 0xED, 0x38, 0x4E, 0x47, 0xFA, 0x4F, + 0x6E, 0x7A, 0x22, 0x8C, 0x36, 0xCB, 0xF2, 0x6A, 0x48, 0x1C, 0x9D, 0x0F, 0x96, 0x4E, 0xE3, 0x1D, + 0x98, 0x86, 0x07, 0xF3, 0x71, 0xE9, 0x74, 0x06, 0xB3, 0x1B, 0xF8, 0xB9, 0x58, 0x32, 0xE1, 0x8E, + 0x8A, 0xA8, 0x7D, 0x1E, 0x4C, 0x85, 0xF3, 0x6D, 0xA4, 0x9D, 0x6F, 0x43, 0xEB, 0x7C, 0x67, 0x10, + 0x92, 0x74, 0xE7, 0xFC, 0xAA, 0x5F, 0x5F, 0x6D, 0xA2, 0x13, 0x4D, 0x60, 0x6C, 0x3C, 0x3E, 0xFE, + 0x3A, 0x75, 0x1D, 0xEE, 0x3E, 0x83, 0x63, 0xD9, 0x95, 0xED, 0x09, 0xF3, 0x2A, 0xBB, 0x8A, 0x21, + 0x89, 0x83, 0xA7, 0x0B, 0xCF, 0x4B, 0xA7, 0xC0, 0xCF, 0xD0, 0x66, 0xA9, 0xF6, 0xC1, 0x8D, 0xC1, + 0xF0, 0x4E, 0xC5, 0x7F, 0xD9, 0x60, 0x6D, 0x37, 0xEA, 0x22, 0xBF, 0x04, 0xAB, 0x74, 0x44, 0xC7, + 0x4C, 0x47, 0x8C, 0x36, 0xCB, 0x51, 0x9C, 0xD8, 0xA6, 0x62, 0xF8, 0xBB, 0xDA, 0x6D, 0xAA, 0xCA, + 0x84, 0x6C, 0x7F, 0x2A, 0x5E, 0x0D, 0x58, 0x0A, 0xB5, 0xF8, 0x6C, 0x72, 0x7A, 0x49, 0x6F, 0xA9, + 0x07, 0xAE, 0x3E, 0x3D, 0xB1, 0xC4, 0x82, 0x37, 0xB5, 0xDE, 0x65, 0xCB, 0x5D, 0x3F, 0x9F, 0xC2, + 0x37, 0x29, 0x31, 0x4B, 0xC6, 0x2B, 0xF6, 0xA9, 0x14, 0x2D, 0x98, 0x9C, 0x4F, 0x54, 0x92, 0xF3, + 0xBF, 0xA9, 0x69, 0x2A, 0x94, 0x90, 0x67, 0x39, 0xD2, 0x7D, 0x9F, 0x74, 0xD5, 0xFC, 0x54, 0x51, + 0x5A, 0xA6, 0x26, 0x3E, 0x3B, 0xF2, 0x26, 0x70, 0x9A, 0xC0, 0x71, 0x1F, 0xAC, 0x28, 0xD8, 0x55, + 0x66, 0x4C, 0x59, 0x22, 0x1A, 0x09, 0xC5, 0x2A, 0x7C, 0x60, 0x7F, 0x36, 0x52, 0xCE, 0x55, 0x98, + 0xDD, 0x28, 0x42, 0x25, 0xD7, 0xF8, 0x73, 0xAB, 0xC1, 0xE3, 0x22, 0xD8, 0xB3, 0x53, 0x22, 0x78, + 0x9E, 0x2D, 0x45, 0x3E, 0x7F, 0xE2, 0x4F, 0x32, 0xB1, 0x44, 0x58, 0x3A, 0x29, 0x00, 0xC9, 0xCF, + 0x30, 0x07, 0x01, 0xCC, 0xB4, 0x15, 0xBD, 0xCD, 0x12, 0x27, 0xC6, 0x49, 0x4E, 0x07, 0x89, 0x36, + 0xBF, 0x5E, 0x5C, 0x93, 0xFD, 0x67, 0xDB, 0xE6, 0x7F, 0xAA, 0x7B, 0xE6, 0x65, 0x32, 0x20, 0x9F, + 0xBA, 0x26, 0x26, 0x04, 0xEB, 0x10, 0xD1, 0xF4, 0x07, 0xD3, 0x0E, 0x60, 0x2D, 0xDF, 0x54, 0xE3, + 0x0F, 0xF4, 0x5A, 0xA9, 0x0F, 0x7E, 0x09, 0x23, 0x5F, 0xD2, 0xAD, 0x7D, 0x19, 0xB6, 0x20, 0x3E, + 0xC9, 0x90, 0x73, 0xA4, 0x85, 0xE9, 0x0C, 0x53, 0xDE, 0xBA, 0xDA, 0x4D, 0x72, 0xB9, 0x9C, 0xA4, + 0x4B, 0xEE, 0xC7, 0x81, 0x79, 0x8F, 0x8D, 0xEA, 0x74, 0x12, 0xF7, 0x7A, 0x13, 0xF9, 0xCD, 0x1A, + 0x71, 0xC6, 0xE7, 0x76, 0x5E, 0x1F, 0xB4, 0x13, 0x68, 0x46, 0x34, 0x2B, 0x9B, 0x4B, 0x2A, 0xB9, + 0x8C, 0x92, 0xE8, 0x66, 0xAE, 0xBC, 0x2E, 0x0B, 0xC8, 0xED, 0x32, 0x57, 0x7E, 0x97, 0x05, 0xE5, + 0x78, 0x59, 0x40, 0x9E, 0x97, 0x39, 0x73, 0xBD, 0xCC, 0x95, 0xEF, 0x65, 0xEE, 0x9C, 0x2F, 0x73, + 0xE6, 0x7D, 0x59, 0x42, 0xEE, 0x97, 0x5C, 0x94, 0xF1, 0xA6, 0x4B, 0x8C, 0xC9, 0x8E, 0xBF, 0x95, + 0x47, 0x54, 0x94, 0x48, 0xA6, 0x04, 0x8A, 0xB2, 0xE9, 0x64, 0xE6, 0x48, 0x29, 0x33, 0x77, 0x5A, + 0x19, 0x6D, 0x26, 0x59, 0xB4, 0x4C, 0x9C, 0xE8, 0xBF, 0xCC, 0x64, 0xFD, 0xFC, 0xA6, 0xD2, 0x8C, + 0x89, 0x6E, 0x89, 0xF3, 0x46, 0xE4, 0xC8, 0x6B, 0x92, 0xB1, 0x25, 0xF3, 0xE2, 0xC8, 0xF9, 0x16, + 0x5B, 0x7C, 0x7E, 0x90, 0x2A, 0x5C, 0xBF, 0xEB, 0x0F, 0xD4, 0xF5, 0x33, 0xCF, 0xD2, 0x18, 0x73, + 0xF4, 0xC3, 0x0F, 0x44, 0x07, 0x06, 0x4A, 0x32, 0x66, 0x09, 0xE3, 0x2B, 0x83, 0xBE, 0xA1, 0xF6, + 0x91, 0x3B, 0xAB, 0x45, 0xF4, 0xF4, 0xE2, 0xFC, 0x60, 0xA0, 0xE5, 0x77, 0x25, 0xE9, 0x62, 0xE8, + 0x52, 0xA9, 0x14, 0x4E, 0x81, 0x92, 0xC2, 0xB0, 0x69, 0x4E, 0x11, 0xA5, 0xAC, 0x3B, 0x77, 0x2E, + 0x5E, 0xA5, 0x83, 0x25, 0x0F, 0x51, 0x38, 0x54, 0x94, 0x26, 0x56, 0xAB, 0xD5, 0xD5, 0xB4, 0xA6, + 0x68, 0x55, 0xA2, 0x91, 0xA6, 0x9A, 0x95, 0x73, 0xEF, 0x8D, 0x1D, 0x9C, 0x99, 0xD3, 0x38, 0x99, + 0xDE, 0xC4, 0x76, 0xE0, 0x87, 0xF9, 0xB5, 0x4D, 0x6E, 0x58, 0x89, 0x94, 0xC4, 0xB4, 0x1D, 0x19, + 0x8E, 0x93, 0x23, 0x79, 0x94, 0x87, 0xD7, 0x3B, 0xA2, 0x87, 0x34, 0x04, 0x97, 0x13, 0xD3, 0xFF, + 0xC2, 0x4B, 0x38, 0x2A, 0xB5, 0x94, 0xE9, 0x11, 0x87, 0x7E, 0x85, 0x54, 0x79, 0x16, 0x0F, 0xFE, + 0xE1, 0x35, 0x72, 0xC0, 0x3F, 0xB4, 0x18, 0x16, 0xE8, 0xC6, 0x2E, 0x79, 0xF5, 0x8A, 0x53, 0x83, + 0x4E, 0x82, 0xFE, 0x32, 0x52, 0x7D, 0x95, 0x93, 0xFD, 0x34, 0x23, 0xA9, 0xAA, 0x04, 0x2C, 0x35, + 0xAD, 0xB0, 0x7B, 0xF3, 0x7B, 0x24, 0xBD, 0x4F, 0x13, 0x66, 0x6A, 0x4D, 0x58, 0xCF, 0x30, 0x10, + 0x1E, 0x24, 0xA1, 0x09, 0x0E, 0xF3, 0x09, 0x98, 0x5C, 0x62, 0xC1, 0xAA, 0x75, 0x0A, 0x53, 0x00, + 0xDF, 0xB4, 0x51, 0xBB, 0x2E, 0x8A, 0x32, 0x93, 0xD3, 0x63, 0xDB, 0x78, 0x61, 0x44, 0x8D, 0xA2, + 0xDC, 0x93, 0xB2, 0x61, 0x47, 0xAD, 0x24, 0xFB, 0xDA, 0x3D, 0x7A, 0xE9, 0xB9, 0x10, 0x8B, 0x06, + 0x30, 0x3F, 0x50, 0xEB, 0x2D, 0xAC, 0xE6, 0x05, 0xA6, 0xF8, 0xA1, 0x14, 0x29, 0xF1, 0xF6, 0x7D, + 0xF8, 0x22, 0x0B, 0xC6, 0x7C, 0xF2, 0x77, 0xCA, 0x6C, 0x0B, 0xA6, 0x4E, 0xFB, 0xF6, 0x31, 0x7A, + 0x10, 0xAD, 0x25, 0xAB, 0xC7, 0x4A, 0xAC, 0x00, 0x2A, 0xDC, 0x3E, 0x51, 0x03, 0x48, 0xFD, 0xCE, + 0xE1, 0xC5, 0xC5, 0xE5, 0xD1, 0xC9, 0xF9, 0xC1, 0xD5, 0xF1, 0xF5, 0xC9, 0x79, 0xFF, 0xC3, 0xD5, + 0xF5, 0xD5, 0xC7, 0x3E, 0xFE, 0xFA, 0xE3, 0xC1, 0xE9, 0xC9, 0xD1, 0xF5, 0x87, 0xF3, 0xBF, 0x9D, + 0x5F, 0xFC, 0x74, 0x9E, 0x0A, 0xFD, 0x8F, 0xBA, 0x18, 0x19, 0x8D, 0x51, 0x62, 0x04, 0x3A, 0xB4, + 0x84, 0xCC, 0x9C, 0x2F, 0x0E, 0xE6, 0xF4, 0xDE, 0x7B, 0x96, 0xDA, 0xC3, 0xC6, 0xC5, 0x90, 0xBF, + 0xB7, 0x44, 0x2D, 0x89, 0xFB, 0x57, 0x64, 0xAD, 0xBB, 0x63, 0xF0, 0x51, 0xA1, 0x2B, 0x87, 0x59, + 0x6B, 0xC7, 0x58, 0xC9, 0x17, 0x46, 0x7C, 0x36, 0xB4, 0xC3, 0xF7, 0x08, 0x76, 0x8C, 0xE7, 0x29, + 0x86, 0x9C, 0x21, 0x24, 0xB4, 0x47, 0xD2, 0xF3, 0x30, 0xEA, 0x77, 0x4F, 0xA7, 0x90, 0xFC, 0x89, + 0xBB, 0x1A, 0x1A, 0xC9, 0x00, 0xBF, 0xAB, 0xE4, 0x77, 0x95, 0x2C, 0xAD, 0x92, 0x29, 0xF5, 0xF9, + 0xD3, 0xBE, 0x62, 0x19, 0xF3, 0x05, 0xC1, 0xED, 0xAC, 0xCF, 0x93, 0xBB, 0xB1, 0x14, 0x4D, 0xCF, + 0x48, 0x0E, 0xB9, 0x93, 0x82, 0xCC, 0xCA, 0xD4, 0x83, 0x45, 0x2D, 0xCE, 0x56, 0xF1, 0x48, 0xAB, + 0x37, 0x82, 0xF2, 0x3A, 0xA0, 0x2E, 0x27, 0x4A, 0x67, 0xC4, 0x2F, 0x52, 0xE0, 0xFC, 0x67, 0xE1, + 0xA5, 0x0F, 0xBC, 0x72, 0xA1, 0x79, 0xCE, 0xB3, 0x1D, 0x0E, 0x53, 0x2C, 0x07, 0x7F, 0x6A, 0x7D, + 0x8C, 0x9D, 0x1B, 0x60, 0xBF, 0x89, 0x8C, 0x4F, 0xD1, 0xC4, 0x9C, 0x78, 0xA1, 0x43, 0xCA, 0x15, + 0xAC, 0xCE, 0xC9, 0xF1, 0x4C, 0x2A, 0xC6, 0x0D, 0x23, 0xD6, 0x0A, 0xEB, 0xB4, 0x75, 0x6C, 0x48, + 0x79, 0x7E, 0x13, 0x86, 0x2F, 0x17, 0x1B, 0x54, 0xCA, 0x45, 0x97, 0x8E, 0x58, 0xE7, 0xA7, 0xA1, + 0xBE, 0x88, 0x10, 0xE1, 0x62, 0x16, 0x22, 0xD0, 0xFA, 0x90, 0xA9, 0x8C, 0xCC, 0xB1, 0x13, 0x59, + 0xDB, 0x79, 0x2C, 0xE9, 0x1E, 0x0A, 0x0C, 0xE8, 0x90, 0xFC, 0x76, 0xFE, 0x20, 0x7F, 0x86, 0x39, + 0xF6, 0xAC, 0xF6, 0x33, 0x53, 0xEE, 0xE8, 0x5E, 0x3C, 0xAC, 0xB5, 0xC2, 0xF8, 0x56, 0x9D, 0x3A, + 0xCF, 0x5A, 0x93, 0xC7, 0x81, 0x7C, 0x57, 0xA3, 0x0A, 0x07, 0xB5, 0xED, 0x66, 0xB6, 0x2E, 0x89, + 0x43, 0x88, 0x85, 0x2B, 0x53, 0xFC, 0x2E, 0xB6, 0xAA, 0x53, 0xF1, 0xFD, 0x72, 0x54, 0xAD, 0xC5, + 0x69, 0x92, 0xA6, 0x73, 0x74, 0x11, 0xDC, 0x0B, 0xEB, 0x15, 0x25, 0xC3, 0xA3, 0x4C, 0x64, 0x1E, + 0x58, 0xA3, 0xA2, 0x3A, 0x84, 0x3E, 0x43, 0x51, 0xC3, 0xBB, 0xCF, 0xBD, 0xE1, 0xDD, 0x25, 0x35, + 0xBC, 0xF7, 0xDC, 0x1B, 0xDE, 0x5B, 0x52, 0xC3, 0x37, 0x9E, 0x7B, 0xC3, 0x37, 0xAA, 0x37, 0x3C, + 0x85, 0xF5, 0x49, 0x5C, 0xCE, 0x6C, 0xD3, 0x19, 0xDF, 0x2C, 0x50, 0x9E, 0xA0, 0xA9, 0x6A, 0x33, + 0xD1, 0x3F, 0xC5, 0x07, 0xB9, 0xF8, 0xAB, 0xA8, 0x60, 0x21, 0xFD, 0xE9, 0xD8, 0x0E, 0x5A, 0xCD, + 0x4E, 0xC4, 0x3F, 0xB3, 0xAA, 0x58, 0x25, 0x34, 0x9E, 0xE0, 0xEE, 0x6E, 0x4A, 0x9B, 0x6F, 0x6C, + 0xFB, 0x06, 0xCB, 0x3F, 0x19, 0x9F, 0xC5, 0x14, 0xCD, 0xBE, 0xD9, 0xFE, 0xB9, 0x79, 0xDE, 0xE2, + 0x87, 0x4F, 0x61, 0xF9, 0xCA, 0x0A, 0x2F, 0x0B, 0xAB, 0xBF, 0x22, 0x86, 0xFA, 0xE1, 0x35, 0xBE, + 0x6C, 0xB1, 0xA2, 0xC5, 0xDE, 0x2D, 0xC0, 0xDE, 0x55, 0xB1, 0x77, 0x93, 0xD8, 0xBB, 0xB9, 0xD8, + 0x7B, 0x05, 0xD8, 0x7B, 0x2A, 0xF6, 0x5E, 0x12, 0x7B, 0x2F, 0x17, 0xFB, 0x46, 0x01, 0xF6, 0x0D, + 0x15, 0xFB, 0x46, 0x12, 0xFB, 0x46, 0x84, 0xFD, 0x99, 0xEE, 0x86, 0xD5, 0x52, 0x61, 0x29, 0x61, + 0xF6, 0x9D, 0xEB, 0x83, 0xEA, 0xCE, 0xE0, 0x57, 0xF8, 0xE9, 0x8D, 0x8B, 0x14, 0x5A, 0xDC, 0xF8, + 0x42, 0x28, 0xA1, 0xCE, 0x9D, 0xC0, 0x3D, 0x75, 0x1F, 0x58, 0x04, 0x1E, 0x6D, 0xAD, 0xC4, 0x0F, + 0x52, 0x03, 0xB2, 0x95, 0xAC, 0x40, 0x35, 0x24, 0xA7, 0x0F, 0x46, 0x4B, 0x7A, 0x11, 0x5D, 0xAD, + 0x0F, 0xB1, 0xB9, 0xAB, 0x7D, 0xDC, 0x1A, 0xD1, 0xD6, 0xED, 0x94, 0x1A, 0x1D, 0x93, 0xB3, 0x94, + 0xCB, 0x35, 0x61, 0x52, 0x47, 0x31, 0x41, 0x94, 0xEC, 0xD4, 0xB0, 0xAE, 0xEE, 0x2C, 0x41, 0xB9, + 0x2B, 0x6F, 0x5B, 0xDD, 0x36, 0xB1, 0xAD, 0x5E, 0x99, 0xBE, 0xE4, 0xDB, 0x34, 0x5D, 0xCD, 0xCD, + 0x3C, 0xB1, 0xB5, 0x0F, 0x78, 0xD2, 0x85, 0xE9, 0xB1, 0xD0, 0x9D, 0x63, 0x30, 0x00, 0x89, 0xE7, + 0xBD, 0xB1, 0xDC, 0xCD, 0x38, 0x19, 0x42, 0xD9, 0x64, 0x9D, 0xD8, 0x29, 0x37, 0x08, 0x71, 0xA2, + 0xE0, 0x1B, 0x61, 0x89, 0x07, 0x96, 0xA4, 0x77, 0xB1, 0xA3, 0xA1, 0x50, 0x30, 0x8E, 0xD9, 0x2B, + 0xD3, 0x57, 0xEE, 0x5B, 0x13, 0xAF, 0x4A, 0x3C, 0x1E, 0x89, 0x04, 0x03, 0x89, 0xA5, 0xB0, 0x5A, + 0x98, 0x7E, 0x8C, 0xBA, 0x11, 0x16, 0x91, 0x83, 0x29, 0x4C, 0x3B, 0xD4, 0x52, 0xAE, 0x6F, 0xB0, + 0x54, 0xA2, 0x16, 0x0B, 0xAB, 0xE4, 0xE4, 0xF0, 0x3C, 0x4B, 0xFF, 0xC0, 0x5B, 0x82, 0x14, 0xBB, + 0xF0, 0xDA, 0xEE, 0xB6, 0x1B, 0x99, 0x7C, 0x6B, 0x4E, 0x98, 0xD3, 0x6D, 0x28, 0xF5, 0x62, 0x5E, + 0xFC, 0x72, 0x5D, 0x66, 0x76, 0xD3, 0x82, 0xD7, 0xEE, 0xF6, 0xC9, 0xD7, 0xE4, 0x6D, 0xBB, 0xA2, + 0x77, 0x3E, 0xD5, 0x36, 0xFD, 0x4A, 0x3D, 0x37, 0x4C, 0x85, 0x2D, 0x3F, 0xEA, 0x23, 0x25, 0x00, + 0x67, 0xE7, 0x0D, 0x85, 0x69, 0xDA, 0x49, 0x0B, 0xE3, 0x53, 0x34, 0x79, 0xBC, 0x57, 0x62, 0x67, + 0x61, 0x91, 0xC9, 0xD4, 0xEB, 0x26, 0x04, 0xAF, 0x96, 0x0C, 0x7C, 0xA4, 0xE6, 0x2C, 0x8E, 0xB4, + 0xDD, 0x48, 0x86, 0x18, 0x71, 0x79, 0x25, 0xF3, 0x6D, 0xC7, 0x4D, 0x5F, 0x5C, 0xE6, 0xEE, 0x5A, + 0x49, 0x72, 0x2B, 0x24, 0xC8, 0xCD, 0x6C, 0x72, 0xC7, 0x28, 0x6E, 0x75, 0x9C, 0x72, 0x5B, 0x1C, + 0xF0, 0x2D, 0x36, 0x7B, 0xF7, 0xF3, 0x6B, 0x3B, 0x7F, 0xF3, 0x0A, 0xDB, 0xA2, 0x19, 0x22, 0x02, + 0xD7, 0x20, 0xF0, 0xA8, 0x39, 0x91, 0x14, 0xA2, 0x9C, 0x54, 0x38, 0x5A, 0x59, 0x2C, 0x12, 0xA2, + 0x67, 0x20, 0x93, 0x5C, 0x65, 0x48, 0x25, 0xC9, 0x9E, 0x4F, 0x21, 0xD2, 0xE8, 0x7E, 0x7B, 0x01, + 0x74, 0x3B, 0xF9, 0x22, 0x38, 0xE6, 0x81, 0x7A, 0x0B, 0x92, 0x40, 0x0A, 0xDB, 0x6F, 0x27, 0x80, + 0x38, 0xED, 0x00, 0xBB, 0x11, 0x91, 0xE5, 0x3F, 0xE0, 0xD4, 0x82, 0x33, 0x40, 0xC1, 0xF4, 0x52, + 0xE6, 0x7D, 0x09, 0xDD, 0xE4, 0xB2, 0xD0, 0x89, 0x25, 0x91, 0x2E, 0xFF, 0xB9, 0x4F, 0x2E, 0x51, + 0x86, 0xFF, 0x85, 0x4C, 0x30, 0x9A, 0xF7, 0x02, 0x9E, 0xED, 0x24, 0x93, 0x4C, 0x20, 0xBF, 0x38, + 0xB3, 0xF2, 0x4C, 0x24, 0x50, 0xC1, 0xAA, 0xCC, 0xDF, 0xFE, 0x24, 0xB2, 0x67, 0x6F, 0x53, 0x84, + 0x0B, 0xCE, 0x53, 0xE3, 0x83, 0xC5, 0x48, 0x3B, 0xDE, 0xAA, 0x43, 0xBB, 0xF7, 0xDB, 0xBD, 0x1E, + 0x84, 0xAB, 0x98, 0x84, 0xC5, 0x62, 0x33, 0x37, 0x7F, 0x46, 0x29, 0xEA, 0xEE, 0xBD, 0x12, 0x10, + 0x83, 0xEA, 0x10, 0x57, 0x95, 0x21, 0x7E, 0x94, 0x20, 0x36, 0x4B, 0x40, 0x5C, 0x9E, 0x1D, 0x6A, + 0x68, 0x7C, 0xAB, 0xF5, 0xB6, 0xCD, 0x88, 0xBD, 0xE5, 0xA7, 0x7A, 0xBC, 0xEF, 0xFA, 0xAA, 0xA4, + 0x8C, 0xCE, 0xD6, 0x5E, 0x21, 0xC4, 0xA0, 0x3A, 0xC4, 0x55, 0x65, 0x08, 0x59, 0x52, 0xF1, 0x70, + 0xCD, 0x86, 0x50, 0x25, 0x15, 0xD3, 0xF8, 0x36, 0xDF, 0x13, 0x26, 0x2C, 0x6C, 0x91, 0x79, 0x84, + 0xA1, 0x19, 0x63, 0xF4, 0x0C, 0x89, 0xD6, 0x36, 0x9E, 0xD5, 0x4E, 0x7C, 0x3A, 0xDC, 0x32, 0x8C, + 0x42, 0xC0, 0xAE, 0x04, 0xF8, 0x02, 0x01, 0x01, 0xAE, 0xAB, 0x6D, 0x9B, 0xE4, 0x87, 0xE6, 0x6B, + 0xB3, 0xA6, 0xFE, 0xA0, 0x6A, 0xFD, 0xAB, 0x8A, 0xF5, 0xE5, 0xDE, 0xE9, 0x15, 0xD6, 0x4F, 0x6B, + 0xB1, 0x16, 0x22, 0xED, 0x7F, 0xE2, 0x6F, 0x5D, 0x63, 0x63, 0x43, 0x86, 0x36, 0x64, 0xDB, 0xFD, + 0x2D, 0x6D, 0xB6, 0x44, 0x08, 0xF2, 0x77, 0xA3, 0xF5, 0x8C, 0x8C, 0x56, 0x2E, 0xCC, 0xE5, 0xCF, + 0x67, 0xD7, 0x97, 0x07, 0x3F, 0xFD, 0x5C, 0x9E, 0x2F, 0x84, 0x18, 0xBC, 0xBD, 0x7C, 0xF3, 0xF3, + 0x77, 0xDB, 0x58, 0xDB, 0x36, 0x66, 0xC2, 0x24, 0x47, 0x5F, 0x77, 0xB7, 0x2C, 0xB5, 0x24, 0x64, + 0xCF, 0xA8, 0x0B, 0xB9, 0xD9, 0xAB, 0x0D, 0xB9, 0xDD, 0xC8, 0x71, 0xF3, 0xBE, 0xCF, 0x02, 0xBF, + 0xAF, 0x59, 0x40, 0x8B, 0x20, 0xB5, 0x88, 0x97, 0xF4, 0x58, 0x9B, 0xCC, 0xAF, 0x1C, 0x3C, 0xD3, + 0xE6, 0x39, 0xE0, 0x99, 0x4E, 0xCF, 0x03, 0xBF, 0x9D, 0x93, 0x8C, 0x50, 0xEB, 0xC0, 0x23, 0x9C, + 0x7E, 0x1A, 0x54, 0x77, 0x0C, 0x9E, 0xD5, 0x54, 0xC8, 0x96, 0x48, 0xC8, 0xF9, 0x75, 0xD7, 0x30, + 0xB6, 0x4A, 0xCF, 0x09, 0x32, 0xD8, 0x8B, 0xCD, 0x7A, 0x60, 0x2F, 0x1A, 0xE9, 0xED, 0x81, 0x62, + 0xB0, 0x9D, 0x7A, 0xD4, 0x76, 0x92, 0xD4, 0xCA, 0x02, 0xEE, 0xD6, 0xA3, 0xB7, 0x5B, 0xAB, 0x75, + 0xDD, 0x5E, 0x2D, 0x6A, 0xDD, 0x5E, 0x2D, 0x6A, 0xBD, 0x0D, 0x65, 0xC6, 0x28, 0x2F, 0x95, 0x4D, + 0xE3, 0x45, 0x4F, 0xB1, 0xC6, 0x65, 0x49, 0x32, 0xC0, 0x6E, 0x23, 0x73, 0x5B, 0x68, 0x3E, 0x37, + 0x22, 0x5A, 0xF2, 0xF3, 0x11, 0xAC, 0xAA, 0x73, 0xD1, 0xAC, 0x26, 0x01, 0x66, 0x39, 0xC0, 0xC5, + 0x90, 0xEA, 0x50, 0xA8, 0x00, 0xB8, 0x53, 0x17, 0x70, 0xB7, 0x26, 0x60, 0x42, 0xD3, 0x16, 0x39, + 0x73, 0x67, 0xED, 0x43, 0xD5, 0x9F, 0x57, 0x92, 0x9D, 0x5A, 0xD1, 0xAC, 0x27, 0xA9, 0xD7, 0x01, + 0x3F, 0x1B, 0x9C, 0x6D, 0xD6, 0x99, 0x10, 0x4E, 0xDD, 0x07, 0xB4, 0xC3, 0x0F, 0xB6, 0x15, 0xDC, + 0xFD, 0x0E, 0x26, 0x05, 0xA3, 0xDE, 0xAC, 0xD0, 0x7B, 0xD2, 0x59, 0xA1, 0xF7, 0xC4, 0xB3, 0x42, + 0xEF, 0x49, 0x67, 0x85, 0xDE, 0xF7, 0x59, 0x61, 0x61, 0xB3, 0x42, 0xEF, 0xE9, 0x67, 0x85, 0x5E, + 0xDD, 0x59, 0xA1, 0x57, 0x77, 0x56, 0xE8, 0xD5, 0x9D, 0x15, 0x7A, 0x4F, 0x37, 0x2B, 0x18, 0x5B, + 0xFF, 0xB9, 0x5D, 0x4A, 0xBC, 0x15, 0x66, 0x95, 0x32, 0xD0, 0xC2, 0xAC, 0xAB, 0x2D, 0xFE, 0xBD, + 0x4D, 0x47, 0x33, 0x9F, 0x3D, 0x4A, 0x1A, 0x07, 0x24, 0xF9, 0x9A, 0x10, 0x1D, 0xFE, 0xA8, 0x64, + 0x2C, 0x0A, 0x8A, 0x7F, 0xEF, 0x69, 0x2A, 0x7D, 0x4C, 0x54, 0xFA, 0xA8, 0xAB, 0xF4, 0x4B, 0xA2, + 0xD2, 0x2F, 0x7B, 0xEA, 0xE6, 0x21, 0xB0, 0xF4, 0x8E, 0xBA, 0x16, 0x0D, 0xEC, 0x61, 0x3E, 0x5B, + 0xE9, 0xC8, 0xA1, 0x91, 0x80, 0x83, 0x92, 0x12, 0x91, 0x41, 0x51, 0x6D, 0xD7, 0x49, 0xD6, 0x7E, + 0x7F, 0x70, 0x7C, 0xD0, 0x3F, 0xD4, 0xD4, 0x3D, 0x18, 0x07, 0x91, 0x16, 0xA8, 0x49, 0x7E, 0x26, + 0xA6, 0xF7, 0x45, 0xC9, 0xF0, 0xD3, 0x2D, 0x4A, 0xE3, 0x53, 0x00, 0xDF, 0xD3, 0xC1, 0xF3, 0x98, + 0xFC, 0x88, 0x05, 0xD3, 0xFA, 0x8F, 0x99, 0x1F, 0x00, 0xB7, 0x9A, 0xAB, 0x4E, 0xEC, 0x94, 0xF9, + 0x9C, 0x3E, 0x9C, 0xBA, 0x52, 0xD8, 0x55, 0x2A, 0x1B, 0x4E, 0x5C, 0x49, 0x7F, 0x09, 0x8C, 0x7E, + 0xB5, 0x83, 0x64, 0x1E, 0x8B, 0x3B, 0xDB, 0x62, 0xE9, 0x3E, 0x6D, 0xA7, 0xCF, 0xD2, 0x0B, 0x89, + 0xF6, 0xE0, 0xE5, 0x3D, 0xCC, 0x48, 0x08, 0x0E, 0xCE, 0x89, 0xD3, 0xF7, 0x5C, 0x4C, 0xB5, 0x20, + 0xE5, 0xF9, 0x48, 0x92, 0x46, 0xCC, 0x07, 0x8E, 0xA5, 0x5C, 0x40, 0xC3, 0x7A, 0xDC, 0x43, 0xE2, + 0x09, 0xFB, 0x40, 0xF2, 0xF1, 0x1F, 0xAD, 0x98, 0x17, 0x96, 0x70, 0xD5, 0xC8, 0xB8, 0xB2, 0x76, + 0xE8, 0x4E, 0xA6, 0x63, 0x1A, 0x48, 0x59, 0xB2, 0xD8, 0x05, 0xBD, 0x10, 0x8B, 0x8C, 0x3F, 0xA4, + 0x99, 0xD1, 0x22, 0xFE, 0x59, 0xD3, 0xA2, 0x44, 0x73, 0x43, 0x8A, 0x0D, 0x29, 0x84, 0xEE, 0xD0, + 0x1C, 0x63, 0xDA, 0xE2, 0x87, 0x3B, 0xCA, 0xA3, 0xE8, 0x8E, 0x07, 0xFD, 0x8D, 0x1E, 0xB9, 0x33, + 0x7D, 0x8C, 0x48, 0xBB, 0xB5, 0xBD, 0x09, 0x14, 0x7A, 0xA0, 0xFF, 0xF6, 0x34, 0x20, 0xEE, 0x2D, + 0xBF, 0x58, 0x8E, 0x7B, 0x0C, 0xB1, 0x9C, 0xC8, 0xAD, 0xE7, 0x4E, 0xC8, 0x41, 0x9F, 0x03, 0x8C, + 0xC8, 0x14, 0x58, 0x93, 0xEF, 0x2B, 0x72, 0x34, 0x98, 0x08, 0xE3, 0x92, 0xE3, 0x91, 0x6F, 0x1C, + 0x1C, 0x01, 0x3B, 0xDE, 0xC4, 0x76, 0x28, 0x70, 0x60, 0x0F, 0xEF, 0x48, 0xAC, 0x16, 0x98, 0x4C, + 0x17, 0x19, 0x72, 0x3D, 0x7B, 0x04, 0x63, 0x6B, 0xCC, 0x48, 0xC7, 0x2E, 0x66, 0x98, 0x5C, 0x23, + 0xEC, 0x81, 0x3F, 0xED, 0x13, 0x67, 0x36, 0x1E, 0xAF, 0xA4, 0xEE, 0x5A, 0x86, 0xF2, 0x4C, 0x00, + 0x94, 0xCA, 0xB9, 0xC1, 0xBF, 0xBD, 0x24, 0x07, 0xE3, 0x31, 0x19, 0xC0, 0x77, 0xAB, 0x30, 0xBD, + 0xA3, 0xEB, 0xF8, 0xEE, 0x98, 0x76, 0xC6, 0xA0, 0xCC, 0x8D, 0x0F, 0x3C, 0x36, 0x98, 0xC0, 0x7F, + 0x20, 0x2F, 0x10, 0x5E, 0x5A, 0x14, 0xD9, 0x89, 0x59, 0x6E, 0xA3, 0x04, 0xA7, 0x63, 0xD7, 0xB4, + 0x7E, 0x32, 0xED, 0x40, 0x4D, 0x17, 0x80, 0x29, 0x5E, 0xC4, 0xE3, 0x1C, 0xFE, 0xEC, 0x66, 0x62, + 0x07, 0x61, 0x36, 0x51, 0x4C, 0x05, 0x03, 0x23, 0x12, 0xCB, 0xFD, 0x4F, 0xC6, 0x67, 0x29, 0x28, + 0x00, 0xA7, 0x3B, 0x11, 0x18, 0xE0, 0xD0, 0x07, 0x82, 0xF1, 0x97, 0x4A, 0x7A, 0x92, 0xB0, 0xBC, + 0x63, 0x4E, 0xA7, 0x7C, 0xD4, 0xA5, 0x11, 0xB7, 0x19, 0xE1, 0x15, 0x09, 0xAB, 0xF9, 0x1F, 0xE6, + 0x57, 0x81, 0xF1, 0xE7, 0xB3, 0xD3, 0xF7, 0x01, 0x26, 0x9F, 0xFB, 0xC7, 0x8C, 0xFA, 0x41, 0x84, + 0x17, 0x6B, 0x74, 0x5C, 0x40, 0xD9, 0x6A, 0xF4, 0x2F, 0x06, 0x57, 0x98, 0xA0, 0x66, 0x7D, 0xC6, + 0x9A, 0x15, 0xA2, 0x6E, 0x28, 0x55, 0xD9, 0xB8, 0x0B, 0x99, 0x89, 0x07, 0x26, 0xB7, 0x7A, 0xB2, + 0x54, 0x34, 0xD7, 0x4F, 0x5F, 0xDD, 0x78, 0xAF, 0x79, 0xA1, 0x8D, 0xD1, 0x93, 0x53, 0x25, 0x75, + 0x58, 0x63, 0x2F, 0x5F, 0xCA, 0x83, 0xC0, 0x0C, 0x66, 0x3E, 0xDE, 0x09, 0x4F, 0x58, 0xF1, 0x7C, + 0xA2, 0x50, 0xBF, 0x00, 0x71, 0x7A, 0xA8, 0xF3, 0x51, 0xA9, 0xAF, 0xD5, 0xC8, 0x19, 0xEE, 0x09, + 0x2A, 0xAE, 0x37, 0xA2, 0x41, 0xDF, 0xB4, 0x3D, 0x98, 0x58, 0xD1, 0x28, 0x27, 0xE6, 0x9F, 0x9B, + 0xC0, 0x79, 0xCB, 0xAA, 0xF0, 0x42, 0x8D, 0xBC, 0x50, 0xB3, 0x59, 0x2E, 0x27, 0x9F, 0x21, 0x73, + 0x83, 0x80, 0x3A, 0x1D, 0x39, 0x99, 0xC4, 0x94, 0x52, 0xEF, 0xEC, 0xE0, 0xD0, 0x4F, 0x02, 0x9E, + 0xBB, 0x0E, 0xCD, 0xBC, 0xBA, 0xCB, 0x68, 0x1E, 0xFB, 0xD3, 0x73, 0xF7, 0xA1, 0x0F, 0xF0, 0xBE, + 0xDE, 0x66, 0x03, 0x77, 0xCC, 0xAA, 0xA6, 0xB2, 0x05, 0x8E, 0x42, 0x6B, 0x26, 0x4A, 0x34, 0x7C, + 0x33, 0x40, 0x76, 0x39, 0x49, 0xE4, 0x71, 0xCB, 0xBC, 0x47, 0x2C, 0x23, 0x52, 0xF8, 0x88, 0x6E, + 0x64, 0x98, 0x96, 0x75, 0x7C, 0x0F, 0xBF, 0xE0, 0xFD, 0x6E, 0x0A, 0x34, 0x5A, 0x8D, 0xA3, 0x8B, + 0x33, 0x30, 0xE0, 0x01, 0x7E, 0x83, 0x7E, 0xA1, 0x98, 0x43, 0xB1, 0x45, 0xB1, 0xCA, 0x0A, 0xD9, + 0x7F, 0x8D, 0x5C, 0xC6, 0xEA, 0x2F, 0x84, 0x57, 0xE2, 0x82, 0x47, 0x3A, 0xEB, 0x9C, 0x7A, 0xAD, + 0x83, 0x65, 0x3F, 0xC0, 0xA5, 0x03, 0x0B, 0x9A, 0x84, 0x5F, 0x38, 0xEA, 0xE8, 0x5A, 0x87, 0x8D, + 0x77, 0x3D, 0xCC, 0xAF, 0xF0, 0x4B, 0xE2, 0x7E, 0x07, 0xAF, 0xF7, 0xC9, 0xFE, 0xDC, 0x71, 0x9D, + 0xE1, 0xD8, 0x1E, 0x62, 0xEE, 0x96, 0x48, 0xC8, 0xAD, 0xF4, 0xB3, 0xED, 0x6A, 0x8A, 0xC6, 0x9C, + 0xB7, 0x97, 0xB9, 0xF7, 0x66, 0xFA, 0x33, 0x8F, 0xDD, 0x36, 0x47, 0x67, 0xFB, 0xFD, 0xAF, 0xD0, + 0x13, 0x69, 0x81, 0x71, 0x9C, 0x68, 0x1D, 0xF4, 0x74, 0x35, 0x98, 0x06, 0x74, 0xA8, 0x6E, 0xDF, + 0x90, 0xF5, 0x4C, 0x82, 0xF2, 0x2D, 0xF6, 0x6F, 0xAA, 0x45, 0xD0, 0x62, 0x5D, 0x08, 0x83, 0x31, + 0xE5, 0x3C, 0xFE, 0xA4, 0x66, 0xE8, 0x19, 0xC4, 0x54, 0x73, 0x18, 0xB5, 0xCD, 0x2F, 0xC7, 0x9C, + 0x38, 0xB5, 0xD8, 0x0B, 0xF3, 0x21, 0x6B, 0x90, 0xE5, 0x65, 0x3E, 0x8E, 0x2D, 0x8D, 0x2F, 0x00, + 0x32, 0x9E, 0xFA, 0xE6, 0x96, 0x86, 0xF9, 0x94, 0x39, 0x6F, 0x72, 0xEB, 0x1B, 0xF6, 0x16, 0xA1, + 0x16, 0xD2, 0xAA, 0x10, 0x53, 0xB9, 0x26, 0x65, 0x71, 0x1B, 0xB7, 0x27, 0xA7, 0xD1, 0xFA, 0x26, + 0x31, 0x94, 0x3C, 0x96, 0x51, 0xCE, 0x7C, 0x80, 0x4B, 0x8F, 0xB9, 0x1A, 0x98, 0x8F, 0xB7, 0x5C, + 0x73, 0x71, 0x0D, 0x92, 0xDB, 0xDA, 0x51, 0xB4, 0x1A, 0x99, 0xAF, 0xB5, 0xEF, 0x58, 0x56, 0xAF, + 0x85, 0x37, 0xF6, 0x5D, 0x32, 0x59, 0x98, 0xB6, 0xAD, 0xBC, 0x29, 0x39, 0x6D, 0xE5, 0xC2, 0xD0, + 0xB4, 0x55, 0xAD, 0x96, 0xB5, 0x0B, 0x99, 0x5A, 0xE3, 0xD7, 0xD9, 0x6E, 0x54, 0x5E, 0xFF, 0xD2, + 0xBE, 0xB8, 0x20, 0x9D, 0xF2, 0xEE, 0x74, 0xB6, 0xF0, 0xBC, 0xF6, 0x00, 0x7C, 0x66, 0x98, 0xC4, + 0xD1, 0x0D, 0x3C, 0xED, 0xAE, 0x9F, 0xF6, 0x54, 0x6C, 0xDF, 0x12, 0xC1, 0x5F, 0x85, 0xBB, 0x14, + 0xF7, 0x9A, 0x48, 0xE4, 0xD2, 0x2C, 0xED, 0x76, 0xB6, 0x17, 0xCA, 0x92, 0x66, 0x07, 0xAB, 0x0A, + 0x3F, 0xDD, 0xEE, 0xF6, 0x82, 0x65, 0x94, 0x4A, 0x5C, 0x5D, 0x85, 0x9D, 0x4D, 0xDC, 0x42, 0xA9, + 0xC5, 0x4D, 0x4D, 0x82, 0xEA, 0x5E, 0x4F, 0x02, 0xB9, 0x7E, 0xE8, 0xF2, 0x97, 0x00, 0xCE, 0xE3, + 0x20, 0xE8, 0xB9, 0x46, 0xAC, 0x0E, 0x5B, 0x39, 0xA3, 0xA4, 0x09, 0xE1, 0xCE, 0x09, 0x34, 0xD7, + 0x8E, 0xF5, 0x52, 0x28, 0xB2, 0x9B, 0x1F, 0x3D, 0x3D, 0xB5, 0x90, 0xE6, 0x97, 0x7A, 0xC8, 0x2A, + 0xD1, 0x7C, 0x0E, 0x33, 0x57, 0xF3, 0x8B, 0x50, 0x68, 0x9B, 0x9F, 0x08, 0xD4, 0x5B, 0x80, 0x08, + 0xD2, 0x18, 0x8B, 0xC4, 0xA0, 0x89, 0x09, 0x04, 0x28, 0xF1, 0x56, 0x41, 0xF2, 0xDA, 0x70, 0x09, + 0x99, 0x14, 0xE2, 0x4B, 0xEC, 0x2F, 0xEA, 0xE5, 0x83, 0xEB, 0x46, 0x4C, 0xB6, 0x8B, 0xE9, 0xA5, + 0x1D, 0x3A, 0x9E, 0x4B, 0x32, 0x69, 0x5C, 0x51, 0xE6, 0x1A, 0x23, 0x43, 0x2B, 0x42, 0x90, 0x37, + 0xE6, 0xCC, 0x3A, 0xF2, 0xDC, 0x29, 0xBE, 0xF0, 0x90, 0x31, 0x67, 0x2B, 0x0F, 0x26, 0x96, 0x50, + 0xA1, 0x12, 0x5C, 0x75, 0x33, 0xE6, 0xD4, 0x52, 0x5C, 0x09, 0x57, 0xA3, 0x22, 0x57, 0xF5, 0xE9, + 0x55, 0x92, 0x82, 0x76, 0x14, 0x64, 0xBF, 0x6D, 0x3A, 0xEF, 0x68, 0x28, 0x7C, 0x35, 0x35, 0xA3, + 0xFB, 0xA7, 0x60, 0xCD, 0xF8, 0xA3, 0xDA, 0x75, 0x45, 0x57, 0x06, 0x43, 0x42, 0x18, 0x33, 0x9F, + 0x9E, 0xBA, 0x43, 0x73, 0x6C, 0xFF, 0x4A, 0xAD, 0x23, 0x68, 0xB0, 0x67, 0xDF, 0xCC, 0x78, 0x42, + 0xD2, 0x39, 0xE4, 0x90, 0x83, 0x34, 0x5F, 0x04, 0x63, 0x1D, 0xD4, 0x15, 0x2C, 0x37, 0x4F, 0x61, + 0x15, 0x3D, 0xD6, 0x6A, 0x43, 0x29, 0xC1, 0xD4, 0xC7, 0xAB, 0xD5, 0x9D, 0xE4, 0x4B, 0xAB, 0xF3, + 0x6A, 0x4C, 0x95, 0x97, 0x5B, 0x73, 0x47, 0xDB, 0x11, 0x0D, 0x4C, 0x7B, 0xEC, 0x57, 0x17, 0x50, + 0x35, 0x5C, 0xB9, 0x42, 0x79, 0x6F, 0x7A, 0x16, 0xEE, 0x4D, 0x71, 0x89, 0x44, 0xAF, 0x4A, 0x2D, + 0x4A, 0x46, 0x19, 0xE8, 0xAB, 0x89, 0x4C, 0x06, 0x9E, 0x5B, 0x66, 0x25, 0x91, 0xE9, 0x85, 0xC6, + 0xF6, 0xBA, 0x16, 0x21, 0x9E, 0x10, 0x51, 0x39, 0x41, 0xB0, 0xAD, 0x9F, 0xDA, 0x2D, 0x2F, 0x82, + 0xD6, 0xBB, 0x1D, 0xD2, 0x86, 0xE2, 0x22, 0x7C, 0x0E, 0x15, 0x5D, 0x96, 0x5D, 0xD1, 0xEC, 0x66, + 0xCE, 0xED, 0x68, 0xE4, 0xE2, 0x2B, 0xE5, 0x68, 0x28, 0xAF, 0x33, 0xCE, 0x2B, 0x89, 0x12, 0x8F, + 0x3C, 0xCA, 0x16, 0xD6, 0x33, 0x6B, 0xF7, 0x7B, 0x01, 0x70, 0x46, 0x23, 0xEB, 0x5B, 0x00, 0x64, + 0xF9, 0x3D, 0x50, 0x56, 0x07, 0x57, 0xB4, 0xF5, 0x98, 0x47, 0xEF, 0xF2, 0xE4, 0xFC, 0xF8, 0xE7, + 0x85, 0x08, 0x57, 0x41, 0x57, 0xD2, 0xCC, 0xA4, 0x40, 0xEB, 0x1B, 0x99, 0x2A, 0xA8, 0xB4, 0x02, + 0x51, 0xDE, 0xF6, 0x9B, 0x57, 0x1C, 0xA5, 0x1F, 0x0A, 0x4C, 0x0A, 0x23, 0x06, 0x9C, 0x53, 0x14, + 0xA5, 0x10, 0xE9, 0x05, 0xA1, 0x7B, 0xFE, 0x6F, 0x6E, 0x81, 0x54, 0x7D, 0x53, 0x30, 0x25, 0x18, + 0x40, 0x30, 0x31, 0x03, 0x7B, 0xA8, 0x62, 0x99, 0x57, 0x4A, 0x95, 0xB1, 0x66, 0x8A, 0x2C, 0x7C, + 0x32, 0x70, 0x11, 0x92, 0x2A, 0xF3, 0xFC, 0x60, 0xA6, 0x80, 0x18, 0xF0, 0xA2, 0xE4, 0x52, 0x84, + 0x2C, 0x21, 0x8E, 0xD2, 0xEF, 0x09, 0xD6, 0x97, 0xD2, 0x42, 0x9E, 0x2C, 0x94, 0x36, 0xEE, 0x73, + 0xD1, 0xD5, 0x16, 0x63, 0x6D, 0xB4, 0xBA, 0x3D, 0xE4, 0x83, 0x71, 0x60, 0x07, 0x33, 0xAB, 0xDE, + 0x38, 0x54, 0xEF, 0x86, 0x68, 0x48, 0x24, 0x9F, 0xCC, 0x5D, 0x26, 0x91, 0xD4, 0x1E, 0xDD, 0x12, + 0x48, 0xA9, 0x37, 0x77, 0x16, 0x4C, 0x20, 0x0A, 0x10, 0x7F, 0xE4, 0x01, 0xE2, 0x8F, 0xE4, 0x15, + 0x71, 0x66, 0x93, 0xC3, 0xD4, 0x43, 0xC8, 0x50, 0xA4, 0x09, 0x13, 0x87, 0x15, 0x55, 0xE0, 0x3A, + 0x22, 0x4A, 0x9C, 0xBD, 0xCB, 0x83, 0x69, 0x8A, 0xDE, 0xB0, 0xAF, 0xF8, 0x52, 0xCA, 0xA3, 0x7A, + 0xB7, 0x2B, 0xAE, 0xAE, 0x6D, 0x08, 0x9E, 0x45, 0x66, 0xB7, 0x23, 0xCC, 0xA3, 0x14, 0x53, 0x38, + 0x44, 0x80, 0xD6, 0xA3, 0xA2, 0x75, 0xEA, 0x6B, 0x27, 0x2B, 0xEA, 0xD5, 0xA1, 0x0C, 0xBF, 0x42, + 0xCE, 0x43, 0x56, 0xF1, 0x9E, 0x5F, 0xC1, 0x5B, 0xC6, 0x65, 0x1C, 0x05, 0xC1, 0xC6, 0x19, 0xC3, + 0x3F, 0xA7, 0xA7, 0x50, 0x88, 0x2B, 0xE3, 0x1E, 0xCA, 0xE2, 0x9A, 0xB1, 0x98, 0x06, 0x64, 0xB0, + 0x9E, 0xB8, 0xE4, 0x97, 0x97, 0x22, 0x2B, 0x2F, 0x83, 0x57, 0x86, 0x82, 0x27, 0xF3, 0x20, 0xCC, + 0x31, 0x36, 0xE2, 0x8C, 0xC0, 0xD9, 0x79, 0xBF, 0x1E, 0x59, 0x46, 0xC8, 0xAF, 0xDA, 0x73, 0x87, + 0x32, 0x63, 0xEB, 0xEB, 0x9E, 0xF6, 0xF8, 0x40, 0x1E, 0x63, 0x98, 0xB9, 0x5C, 0x5C, 0x4C, 0x60, + 0x29, 0xC3, 0x13, 0xCC, 0x60, 0x25, 0xE4, 0xA3, 0xF8, 0x34, 0x21, 0x95, 0x54, 0x4E, 0x33, 0x0E, + 0xF1, 0x1B, 0xFF, 0x5B, 0xBA, 0xAF, 0x45, 0x4E, 0x9C, 0xA1, 0xC7, 0xEE, 0xD4, 0x4C, 0x45, 0x92, + 0x35, 0xB2, 0x46, 0xFC, 0x07, 0x73, 0xCA, 0x5F, 0xBD, 0x67, 0xB7, 0x1E, 0x60, 0x4E, 0x8B, 0x59, + 0x23, 0x3E, 0x63, 0x8D, 0xE7, 0x90, 0xC1, 0x3A, 0x0E, 0x66, 0x5F, 0xBF, 0x03, 0x5B, 0x4E, 0x7D, + 0xE9, 0xD1, 0xDA, 0x98, 0x18, 0x79, 0x9D, 0xD8, 0x58, 0x65, 0xE9, 0x2B, 0xCC, 0x2F, 0xF4, 0x8C, + 0xBE, 0x47, 0x28, 0x6F, 0x4F, 0x57, 0xC4, 0x32, 0x45, 0xEE, 0x69, 0xFA, 0xBA, 0xBA, 0x9A, 0x94, + 0xE9, 0xEB, 0xAF, 0xAC, 0xAF, 0x35, 0x12, 0x92, 0xFF, 0xC9, 0x4C, 0x4B, 0x29, 0xE1, 0x32, 0x4E, + 0x90, 0xCA, 0x91, 0x94, 0x05, 0xB5, 0x46, 0xBA, 0x2B, 0x39, 0x84, 0x99, 0x48, 0xF2, 0xE9, 0x7E, + 0x5B, 0xA8, 0xC0, 0x98, 0x75, 0x95, 0x1B, 0xAD, 0x65, 0xAE, 0xA0, 0x8D, 0x6B, 0x18, 0x34, 0x26, + 0x2B, 0x5A, 0xA1, 0xD0, 0x24, 0xB2, 0xAC, 0xC9, 0x5A, 0xAA, 0x80, 0xF0, 0xDC, 0x0D, 0xE8, 0x4B, + 0xE5, 0xB1, 0x39, 0x1D, 0xFD, 0x55, 0xA0, 0xDF, 0x20, 0xAE, 0x33, 0x7E, 0x24, 0x0F, 0xAE, 0xF7, + 0xC5, 0x0F, 0xF9, 0x85, 0xBF, 0xED, 0x5B, 0x2D, 0xDE, 0x1C, 0x84, 0xEC, 0x25, 0x20, 0xDB, 0x09, + 0xDA, 0x04, 0x13, 0x25, 0xF9, 0x2C, 0x35, 0x7A, 0x87, 0x7C, 0xC0, 0xD1, 0x63, 0x7A, 0xF8, 0x82, + 0x5D, 0x80, 0xA3, 0x87, 0x52, 0x62, 0xDE, 0xB8, 0xF7, 0xB4, 0xB2, 0xAC, 0x56, 0x43, 0x59, 0x1D, + 0xD1, 0x02, 0x59, 0x7D, 0x4B, 0xE4, 0xAE, 0x21, 0x27, 0xB7, 0xC4, 0x1C, 0x03, 0x8C, 0xF5, 0xC8, + 0x06, 0xA5, 0x18, 0x8F, 0xD1, 0xA0, 0x6E, 0x33, 0x81, 0x12, 0x3B, 0x20, 0x63, 0x10, 0x69, 0x38, + 0x50, 0x93, 0x36, 0x9F, 0xDD, 0x58, 0x3A, 0x98, 0xBC, 0xE7, 0xC0, 0x4F, 0x3D, 0xFA, 0xD0, 0x4A, + 0x60, 0x53, 0x0C, 0x62, 0xFB, 0xE4, 0xBD, 0x6C, 0x50, 0x14, 0x5C, 0x11, 0x7F, 0x9A, 0xA1, 0x80, + 0xFF, 0x6E, 0x40, 0x0A, 0x5F, 0x9E, 0x6E, 0x88, 0xE0, 0xCB, 0x22, 0x11, 0x4B, 0xCB, 0x1F, 0x20, + 0x59, 0xE7, 0xD2, 0x85, 0x09, 0x2C, 0xB5, 0x0D, 0x43, 0x93, 0xC3, 0x68, 0x9F, 0x4A, 0x5A, 0x91, + 0xAB, 0x6E, 0x75, 0x92, 0x5F, 0xA2, 0x27, 0x79, 0x78, 0xFC, 0x36, 0x9E, 0xF3, 0xE5, 0x37, 0x07, + 0xA5, 0x18, 0x27, 0x07, 0x66, 0x29, 0xBC, 0x54, 0x87, 0x95, 0xA3, 0xC3, 0x74, 0x8F, 0x4E, 0x60, + 0x28, 0xBD, 0x31, 0x2D, 0x5C, 0xD7, 0xF8, 0xAD, 0x74, 0x9D, 0xD8, 0x57, 0xD6, 0xBE, 0x9D, 0x2C, + 0xD5, 0x17, 0x2F, 0x27, 0xEF, 0xA6, 0x9E, 0x4E, 0xDE, 0x65, 0x6F, 0x27, 0x9B, 0x30, 0xD3, 0xA9, + 0x0F, 0x28, 0xCB, 0x59, 0xD0, 0xF7, 0xD2, 0x34, 0xC4, 0x6B, 0xD0, 0x52, 0xAC, 0x42, 0x9B, 0xAC, + 0xBD, 0x08, 0xDF, 0x80, 0x7E, 0x91, 0x7A, 0x0C, 0x3A, 0x2C, 0x43, 0x9A, 0xE2, 0xD7, 0x39, 0xA8, + 0x7D, 0x7C, 0x52, 0x6A, 0xBF, 0x2C, 0x94, 0x5A, 0xD6, 0xF3, 0x93, 0xAA, 0xA3, 0x10, 0x3E, 0xCB, + 0x86, 0xFD, 0x47, 0xCC, 0x91, 0x89, 0x8F, 0x81, 0xF2, 0x97, 0x5F, 0x6C, 0x59, 0x57, 0xF9, 0x2B, + 0x53, 0x16, 0xFD, 0x9A, 0x88, 0xEF, 0x62, 0xC3, 0x7B, 0x4F, 0x14, 0xBD, 0xC2, 0x4B, 0xEF, 0xAE, + 0x67, 0xF9, 0x4C, 0x71, 0xC2, 0x2B, 0x98, 0xAB, 0xAB, 0xAC, 0x34, 0x35, 0x6C, 0x11, 0x25, 0x58, + 0xF4, 0xC0, 0x67, 0x0A, 0x18, 0xC1, 0x7D, 0x62, 0xB5, 0x3F, 0x87, 0x09, 0xD8, 0x49, 0x2A, 0xC9, + 0x73, 0xE8, 0xA6, 0x2B, 0x5A, 0x27, 0x9D, 0xE5, 0x32, 0x9C, 0x98, 0x64, 0x5D, 0x37, 0x84, 0xD3, + 0x84, 0x70, 0xD8, 0xA6, 0xC7, 0xC4, 0x2A, 0x69, 0xB2, 0x34, 0xC7, 0xB1, 0xDE, 0x65, 0x15, 0x7C, + 0xCC, 0x2A, 0xF8, 0x25, 0x95, 0x52, 0xBB, 0xBA, 0xF5, 0xE4, 0x8F, 0x2C, 0x31, 0xB1, 0xEF, 0x6B, + 0x84, 0xBB, 0xA2, 0xE2, 0x90, 0x2B, 0x4C, 0x67, 0xFE, 0x5D, 0x6B, 0xA9, 0x0D, 0x5B, 0xD1, 0x67, + 0xEB, 0x45, 0x5A, 0xB8, 0x9C, 0xD5, 0xD8, 0x28, 0x8B, 0xE2, 0x4D, 0xED, 0xD8, 0x4C, 0xC5, 0x17, + 0x82, 0x01, 0xA1, 0xB8, 0x97, 0x8F, 0xD7, 0xC9, 0xA1, 0xAE, 0x14, 0x1D, 0x24, 0xF7, 0xAF, 0x14, + 0x2E, 0x8B, 0x20, 0xAF, 0x59, 0x2E, 0xF9, 0xC4, 0xE4, 0xAA, 0xD3, 0x29, 0xA8, 0x9C, 0xA1, 0x51, + 0x08, 0x81, 0x62, 0x12, 0x4B, 0x8C, 0x50, 0x79, 0x94, 0xBB, 0x71, 0x7C, 0x6A, 0x65, 0x61, 0x08, + 0xAD, 0xC6, 0x11, 0x6B, 0x04, 0xC1, 0x53, 0x55, 0xD6, 0x28, 0x5C, 0x85, 0x44, 0x08, 0x56, 0x49, + 0xE3, 0xAF, 0x8D, 0x95, 0xCC, 0xDD, 0x29, 0xB9, 0x83, 0x90, 0x9B, 0x21, 0xC5, 0x66, 0x80, 0xC5, + 0xCC, 0x5E, 0xA4, 0x16, 0x0A, 0x15, 0x2F, 0xC1, 0xAB, 0x96, 0xFF, 0xB7, 0x15, 0x68, 0x66, 0x64, + 0x19, 0x17, 0x6D, 0xF7, 0x73, 0x56, 0xDD, 0x8F, 0xA9, 0xBA, 0xBD, 0xCC, 0xBA, 0xBF, 0xA4, 0xEA, + 0x6E, 0x24, 0xEB, 0xEA, 0xCD, 0x83, 0xDC, 0xC1, 0xBA, 0xA7, 0x44, 0x65, 0xCE, 0x8B, 0xAA, 0x7C, + 0x2C, 0xAE, 0xF2, 0x4B, 0x66, 0x15, 0x95, 0xBD, 0xD4, 0x5B, 0x99, 0xD1, 0x23, 0x5D, 0x92, 0xD0, + 0xC1, 0x31, 0xF6, 0x4C, 0xF0, 0x32, 0xB9, 0x4A, 0x10, 0xD3, 0xB1, 0xC8, 0xC4, 0x75, 0x5C, 0x7F, + 0x6A, 0xC2, 0x52, 0x91, 0xDD, 0xF1, 0xE7, 0x36, 0x3B, 0xB1, 0x37, 0x10, 0xEB, 0x8E, 0x1C, 0x2A, + 0x90, 0xA9, 0x16, 0x22, 0xAD, 0xBF, 0xEC, 0x33, 0xA0, 0x76, 0xA4, 0x8D, 0x4F, 0x7A, 0x2E, 0xE1, + 0x5B, 0x19, 0x59, 0x98, 0x25, 0x41, 0xC8, 0x8D, 0xC7, 0xC0, 0xBD, 0x64, 0x94, 0x84, 0xF4, 0x80, + 0x17, 0x66, 0x54, 0x75, 0x3D, 0x6A, 0x35, 0x0A, 0x9E, 0x0D, 0x66, 0x7B, 0x31, 0xF3, 0x93, 0x16, + 0xA5, 0x2F, 0xC9, 0xCF, 0xEB, 0x1F, 0xD7, 0x7F, 0x69, 0x24, 0xDE, 0x43, 0xD0, 0x08, 0xE1, 0x15, + 0xD9, 0x5A, 0x49, 0x9F, 0x92, 0x66, 0x4A, 0xD7, 0xB7, 0x7F, 0xA5, 0x44, 0x67, 0xCA, 0x93, 0xC6, + 0x34, 0xF2, 0x9B, 0xE3, 0x59, 0xB7, 0xF2, 0x2C, 0x8B, 0x83, 0xD7, 0x9D, 0x32, 0x55, 0x90, 0x42, + 0x2D, 0xD0, 0x01, 0x06, 0xAD, 0x10, 0xC9, 0xF0, 0x9B, 0xBC, 0x82, 0x32, 0x84, 0xF9, 0x27, 0xB6, + 0x71, 0xA2, 0x9D, 0x9B, 0xD3, 0x55, 0xC3, 0xD1, 0xC5, 0xCA, 0x13, 0x03, 0x31, 0x53, 0x16, 0xF8, + 0x2A, 0x00, 0x87, 0x4F, 0x4D, 0x25, 0x7F, 0x6E, 0x35, 0xFE, 0x97, 0x1E, 0x4E, 0x50, 0x04, 0x70, + 0x6A, 0x0E, 0xEF, 0x5A, 0x19, 0xDB, 0xA4, 0xB2, 0xD9, 0xFA, 0x73, 0x2B, 0xB8, 0xB3, 0x7D, 0xBE, + 0x0F, 0xD4, 0x5A, 0xC9, 0x9F, 0x05, 0x1C, 0x75, 0x16, 0xE8, 0xF8, 0xB3, 0x1B, 0xBE, 0x00, 0x6D, + 0x81, 0x1F, 0xD6, 0xDD, 0x92, 0x41, 0x14, 0xB4, 0x11, 0x2C, 0x4C, 0x96, 0xFC, 0x7D, 0x84, 0xD0, + 0xDA, 0x45, 0xD3, 0x67, 0x68, 0xD2, 0x12, 0x1F, 0x36, 0x3E, 0x73, 0x14, 0xF2, 0xAE, 0x74, 0xCA, + 0xB3, 0x0F, 0x63, 0x66, 0x4B, 0x7B, 0xF7, 0x21, 0x40, 0x91, 0x87, 0xAF, 0xD6, 0x2B, 0xE7, 0xE5, + 0x87, 0x30, 0x0B, 0xF3, 0xF4, 0xE3, 0xD7, 0xF8, 0xF2, 0x5D, 0xE4, 0xE8, 0xC4, 0x04, 0xBC, 0xE4, + 0x6E, 0xD7, 0xD8, 0xD8, 0x6C, 0x93, 0x9D, 0x1D, 0x85, 0x3E, 0xFF, 0x8C, 0x4C, 0x60, 0x41, 0x75, + 0x4F, 0x3C, 0x79, 0x6A, 0x82, 0x84, 0xB6, 0xB0, 0xE3, 0x15, 0x1A, 0x5B, 0xEC, 0xE1, 0xCE, 0xAD, + 0xDA, 0xE8, 0x13, 0xE7, 0x25, 0x40, 0xA4, 0x67, 0x18, 0x1D, 0x83, 0xC5, 0xBD, 0x76, 0x14, 0x7F, + 0x9F, 0x7D, 0x40, 0x6A, 0xEC, 0x97, 0xE7, 0xE9, 0xEB, 0x47, 0x2A, 0x54, 0xC3, 0xDF, 0x0F, 0x61, + 0x2B, 0xFB, 0xFC, 0x91, 0x0E, 0x56, 0xF4, 0xFB, 0x13, 0x04, 0x25, 0xDF, 0x3F, 0x31, 0x62, 0x14, + 0xA7, 0x57, 0x04, 0xA3, 0x6B, 0x8B, 0x44, 0xE8, 0xB9, 0xAE, 0x2C, 0xD4, 0xD7, 0x44, 0x59, 0x42, + 0xC9, 0xF4, 0xA5, 0xAA, 0x8E, 0x2C, 0x69, 0x25, 0x91, 0xE8, 0x3A, 0xFD, 0x6A, 0x22, 0xAA, 0xA4, + 0xAC, 0x28, 0xFE, 0x05, 0xC4, 0x95, 0xB1, 0x3E, 0x09, 0x39, 0xCF, 0x5D, 0xA3, 0xA4, 0x0D, 0x6E, + 0x91, 0x53, 0x9D, 0xD4, 0xC8, 0x1A, 0x8E, 0x75, 0xA4, 0x9C, 0xCF, 0x6B, 0xB5, 0x12, 0x75, 0x75, + 0xA5, 0x15, 0x4B, 0x81, 0x98, 0xA5, 0xF3, 0x58, 0x75, 0x25, 0x78, 0x67, 0xD2, 0x33, 0x1A, 0xDC, + 0xB9, 0x56, 0x66, 0x74, 0xA8, 0x12, 0x1A, 0x1A, 0x67, 0x56, 0x78, 0x19, 0x26, 0x52, 0x48, 0x3F, + 0xEC, 0x06, 0x38, 0xA5, 0xEE, 0x90, 0x28, 0x24, 0x2F, 0x7E, 0xA7, 0x4F, 0x9A, 0x73, 0x2E, 0xCB, + 0xE9, 0x4E, 0xF2, 0xB3, 0xEF, 0xC2, 0x01, 0x55, 0xF8, 0x28, 0x1E, 0x3B, 0xCB, 0xC8, 0x45, 0xB1, + 0x42, 0xD6, 0x48, 0x4B, 0xAA, 0x92, 0x3E, 0xC4, 0x17, 0xD5, 0x56, 0x49, 0xBA, 0x96, 0x3E, 0x52, + 0x66, 0x85, 0xAC, 0x93, 0xAE, 0x48, 0xA7, 0x90, 0xC7, 0x78, 0xE8, 0x27, 0x00, 0x9B, 0x1D, 0xBC, + 0xD4, 0x03, 0xA5, 0xAD, 0x8D, 0x82, 0xB8, 0xFD, 0x5C, 0x69, 0x69, 0x72, 0x9A, 0xE4, 0x08, 0x2B, + 0x29, 0x5B, 0xBD, 0xB4, 0x92, 0xFC, 0xA2, 0x20, 0x9E, 0x52, 0x5E, 0xA9, 0xCC, 0x21, 0x59, 0xD2, + 0x4A, 0xAF, 0xD0, 0x9F, 0xB5, 0x41, 0x99, 0x4D, 0xFA, 0x02, 0x90, 0x21, 0x50, 0x57, 0x24, 0x21, + 0xD1, 0xA8, 0xD6, 0xEB, 0x7D, 0xB2, 0xAD, 0x9D, 0xDC, 0xC7, 0x66, 0x10, 0xE2, 0x89, 0x6B, 0xAF, + 0x91, 0x4D, 0x94, 0x69, 0x4F, 0xF7, 0x1C, 0x65, 0xE6, 0x64, 0xAE, 0x5B, 0xA5, 0x17, 0xA4, 0x87, + 0xD1, 0xEC, 0x2E, 0x84, 0x9C, 0x47, 0x7C, 0xBD, 0xD6, 0xC4, 0x79, 0x28, 0x6B, 0xAD, 0x09, 0xAC, + 0x34, 0xC3, 0x26, 0x74, 0xF7, 0xA4, 0x3F, 0x5F, 0x45, 0x8D, 0x93, 0xBE, 0x6A, 0x8E, 0x2B, 0x0A, + 0x19, 0x5D, 0xDD, 0x57, 0xBC, 0xFF, 0x98, 0xC2, 0x2A, 0x49, 0xF1, 0xAE, 0x39, 0x99, 0xF8, 0x96, + 0x25, 0x8F, 0x74, 0x06, 0x1C, 0x21, 0x10, 0x40, 0x1C, 0xB2, 0xFE, 0xEC, 0x64, 0x93, 0x64, 0x3A, + 0x4F, 0x38, 0x39, 0xED, 0xA8, 0x20, 0x27, 0x8D, 0xC5, 0xE3, 0xB4, 0x24, 0x7D, 0xDD, 0xD0, 0x69, + 0x5D, 0x86, 0x69, 0xD1, 0xC1, 0xF7, 0x72, 0xE0, 0x33, 0xC3, 0x19, 0x53, 0x58, 0xBA, 0x9F, 0x53, + 0xE1, 0xB9, 0x75, 0x72, 0x12, 0x45, 0x39, 0x85, 0x2A, 0x20, 0xEA, 0xE5, 0x25, 0x37, 0x52, 0x31, + 0xA9, 0xD7, 0xAA, 0x32, 0x1F, 0x56, 0xD4, 0x0C, 0xF5, 0xBD, 0xEC, 0xCA, 0xEA, 0xC0, 0x29, 0xAC, + 0x18, 0x69, 0x51, 0x51, 0xCD, 0xB8, 0xF3, 0x73, 0x6A, 0xA6, 0x3A, 0xBA, 0xB8, 0x6E, 0xB2, 0x53, + 0xCB, 0xDF, 0xFD, 0x51, 0x32, 0xDF, 0xF8, 0x7C, 0x0A, 0x08, 0x45, 0x44, 0x98, 0xBD, 0xE6, 0x0B, + 0xFD, 0xBC, 0x9B, 0x40, 0xE9, 0xBD, 0xC2, 0x08, 0x43, 0xBD, 0xFD, 0x42, 0xD5, 0x73, 0xCB, 0xDF, + 0x33, 0x94, 0x4C, 0x77, 0xFE, 0xBE, 0x61, 0x62, 0xA9, 0x51, 0x7E, 0xEF, 0x50, 0xAB, 0x31, 0x49, + 0x75, 0x5A, 0xEE, 0x1E, 0x62, 0x5D, 0x16, 0xA2, 0xBD, 0x44, 0xD0, 0xE5, 0x75, 0x54, 0xD3, 0x75, + 0xD0, 0xC0, 0x8C, 0x2D, 0xC5, 0xA4, 0x7C, 0xCA, 0x6E, 0x2B, 0x4A, 0x1D, 0xA0, 0x6E, 0x2D, 0x26, + 0x97, 0xE5, 0xD5, 0xB7, 0x17, 0x4B, 0x2D, 0xEC, 0x17, 0xBA, 0xC5, 0x98, 0x58, 0x9D, 0xCF, 0xBB, + 0xCD, 0x28, 0xC9, 0xA6, 0xF2, 0x56, 0x63, 0x34, 0x86, 0x7E, 0xEB, 0xED, 0x46, 0x55, 0x5B, 0x64, + 0xFF, 0x0C, 0x1D, 0xB1, 0x17, 0xA9, 0x59, 0x76, 0x61, 0xDB, 0x92, 0xE9, 0x39, 0x56, 0xAD, 0xB1, + 0x99, 0x04, 0xD9, 0x4A, 0x7E, 0xD8, 0x2E, 0xC4, 0xF1, 0x42, 0xDD, 0xFC, 0x2C, 0x61, 0x31, 0x97, + 0xB3, 0xEB, 0xAA, 0x28, 0xC4, 0x37, 0x5D, 0xEA, 0x39, 0x65, 0xF7, 0x54, 0xCE, 0x75, 0xC5, 0x5D, + 0x78, 0xF8, 0x29, 0xF5, 0x74, 0xE7, 0x3F, 0x5C, 0xDB, 0x69, 0x35, 0x9B, 0x71, 0xC6, 0xAF, 0x44, + 0x9D, 0x76, 0x89, 0x3A, 0x7F, 0xFF, 0x7B, 0xBA, 0x92, 0x47, 0x83, 0x99, 0xE7, 0xB0, 0x05, 0x40, + 0x9A, 0xC9, 0x11, 0x0D, 0x30, 0xDB, 0x98, 0x6A, 0xB6, 0x59, 0xD6, 0x37, 0xB0, 0x6B, 0xA0, 0x53, + 0x61, 0x21, 0xDA, 0x5E, 0xEE, 0x16, 0x24, 0x8D, 0x9F, 0x52, 0x29, 0x5C, 0xC1, 0xC9, 0xDB, 0x87, + 0x27, 0xB7, 0x6C, 0xBB, 0x30, 0x30, 0x6F, 0xC8, 0x83, 0xE9, 0x13, 0x9C, 0xFB, 0x09, 0xE6, 0x28, + 0xA3, 0x56, 0x9B, 0xF0, 0x31, 0x8F, 0x65, 0x63, 0xCA, 0xB3, 0xDB, 0xF9, 0x43, 0x0F, 0x5F, 0xFB, + 0x4A, 0x2E, 0xA4, 0xC6, 0xF4, 0xCC, 0x74, 0xCC, 0x11, 0xF5, 0xAE, 0xB0, 0x6A, 0x2A, 0x17, 0x19, + 0x43, 0xF0, 0xFA, 0x55, 0xE0, 0x11, 0x73, 0x6C, 0x8F, 0x9C, 0xFD, 0xE6, 0x98, 0xDE, 0x06, 0x4D, + 0xF8, 0x70, 0xF7, 0x1A, 0x37, 0x2D, 0x5E, 0xAD, 0xC3, 0x2F, 0xF8, 0xC7, 0x00, 0xCC, 0x9D, 0xF8, + 0xC3, 0x7A, 0xFD, 0x8A, 0xBF, 0xEC, 0x1A, 0x3C, 0x4E, 0xE9, 0x3E, 0x77, 0x5A, 0x6E, 0xDC, 0xAF, + 0x4D, 0x62, 0x5B, 0xFB, 0x4D, 0x24, 0xC8, 0xB7, 0x0E, 0x0E, 0xC6, 0xE3, 0x26, 0x61, 0x8F, 0x12, + 0xC3, 0x57, 0xD7, 0x9B, 0xAC, 0xB1, 0x8A, 0x6B, 0x1C, 0x54, 0xE2, 0x8B, 0x6D, 0x92, 0x36, 0x89, + 0xB8, 0xD2, 0xC9, 0x31, 0x84, 0x2C, 0xBB, 0xA3, 0x11, 0xE6, 0x7F, 0x02, 0x7E, 0xD6, 0x91, 0xEC, + 0x7A, 0xE0, 0x45, 0x3F, 0x18, 0xDF, 0xB2, 0x79, 0x47, 0x38, 0xD6, 0xC6, 0x2B, 0x6E, 0xE5, 0x1A, + 0x0D, 0x45, 0x9C, 0x5F, 0x27, 0xE3, 0xBB, 0x20, 0x98, 0xE6, 0xA7, 0x81, 0x93, 0x2A, 0x8A, 0x6C, + 0x70, 0xEF, 0x8E, 0x79, 0x32, 0x38, 0x9C, 0xBB, 0x59, 0xBE, 0xBA, 0x86, 0xC6, 0xCB, 0x0B, 0x41, + 0x58, 0x36, 0x2F, 0xD5, 0x8C, 0x88, 0x4B, 0x74, 0x43, 0x77, 0x82, 0x76, 0x26, 0xAC, 0xE8, 0x51, + 0x7F, 0x0A, 0xCE, 0x08, 0x63, 0x75, 0x05, 0x6F, 0x2B, 0x89, 0x8C, 0x88, 0xE4, 0x70, 0xF0, 0x23, + 0xCF, 0x5F, 0x68, 0x3B, 0x81, 0xCB, 0xBC, 0x86, 0x64, 0xA2, 0xD4, 0xDC, 0x1E, 0x05, 0x97, 0x5E, + 0x11, 0x43, 0xF1, 0x0C, 0xAC, 0x2A, 0x61, 0xEE, 0x0B, 0x6A, 0xA0, 0xF1, 0x22, 0xB1, 0x70, 0x5A, + 0xE9, 0xDD, 0x9B, 0xC0, 0xB4, 0x41, 0x31, 0xA5, 0x0A, 0x7A, 0xC5, 0xD7, 0x56, 0x4C, 0x2B, 0xBF, + 0x94, 0x94, 0x15, 0xAB, 0x24, 0xD5, 0x56, 0xEE, 0x77, 0x51, 0x4D, 0xEE, 0xF5, 0xA8, 0x81, 0x98, + 0x0F, 0xF1, 0x2C, 0x7E, 0x2C, 0x0E, 0x27, 0x8C, 0x4F, 0x9F, 0x33, 0x2A, 0xB0, 0x53, 0x03, 0x7D, + 0x8D, 0x30, 0x22, 0x26, 0x1B, 0x47, 0x58, 0x43, 0x45, 0xB2, 0x50, 0xED, 0x0B, 0xB3, 0x98, 0xFF, + 0xD6, 0x0A, 0x98, 0xD5, 0x2D, 0xAB, 0xFB, 0x72, 0x57, 0x24, 0x4C, 0x19, 0xB9, 0xA4, 0x53, 0x41, + 0xC1, 0x74, 0x1E, 0xB9, 0xCC, 0xC2, 0xEA, 0xEC, 0x80, 0xC4, 0x67, 0x0E, 0xF3, 0x3D, 0x17, 0xDF, + 0x1A, 0xB1, 0x3B, 0xB4, 0xC3, 0x8C, 0x9F, 0xF8, 0x82, 0x0E, 0x14, 0xFE, 0x89, 0x6F, 0xAE, 0x10, + 0xFE, 0xF6, 0x0C, 0xB1, 0x44, 0x2C, 0xBD, 0x9F, 0x7F, 0xFD, 0x31, 0xA5, 0x04, 0x99, 0x8F, 0x10, + 0x8A, 0x16, 0xA6, 0x00, 0x3E, 0x7D, 0xFD, 0x1C, 0x2F, 0x1D, 0xD3, 0x2A, 0xF3, 0x49, 0xF1, 0x9D, + 0xBE, 0x95, 0x68, 0x78, 0x68, 0x32, 0xAB, 0xB4, 0x1C, 0x93, 0x12, 0x13, 0x1E, 0xB7, 0x10, 0x23, + 0xA0, 0x65, 0xDA, 0xAE, 0x68, 0x6F, 0x6E, 0xE3, 0xD9, 0xF4, 0x95, 0x56, 0x67, 0x71, 0x99, 0xB5, + 0x81, 0xA3, 0x34, 0x33, 0x67, 0x51, 0x9A, 0x14, 0x13, 0x5B, 0x66, 0xDA, 0xE5, 0xBC, 0x74, 0x49, + 0x39, 0x3C, 0x30, 0xD5, 0xAF, 0xCF, 0x44, 0x72, 0xE7, 0xB3, 0xD2, 0x75, 0x54, 0x69, 0xF5, 0xA8, + 0xDA, 0x42, 0x72, 0xE2, 0xFB, 0x33, 0x11, 0x3F, 0x70, 0x72, 0xF4, 0x92, 0x6D, 0xFB, 0xEB, 0x59, + 0xA9, 0x1E, 0xF6, 0xA0, 0x52, 0xC2, 0xC5, 0x67, 0xA1, 0xE5, 0xC5, 0x4A, 0xA5, 0xAD, 0x2F, 0xAF, + 0x5C, 0x68, 0x81, 0xB1, 0xDA, 0x3C, 0x56, 0xF8, 0x59, 0x99, 0x50, 0xD6, 0x98, 0xE7, 0x63, 0x46, + 0x53, 0xB2, 0xAD, 0x6E, 0x4A, 0xBF, 0x5B, 0x94, 0xDF, 0x97, 0x45, 0x61, 0xA3, 0xD2, 0x5E, 0x9E, + 0x55, 0x91, 0xBC, 0xC8, 0x23, 0x98, 0x42, 0xF1, 0xCC, 0x44, 0x4A, 0xFC, 0x2B, 0x42, 0xA4, 0xD0, + 0x31, 0x2C, 0x9F, 0x36, 0x16, 0x51, 0x9E, 0x1C, 0x49, 0x07, 0x83, 0x82, 0x2B, 0x87, 0x9D, 0x05, + 0x5D, 0xDC, 0x32, 0x6C, 0x83, 0x30, 0xFA, 0xAA, 0x36, 0x56, 0x75, 0x87, 0x05, 0x8B, 0xF9, 0x61, + 0x93, 0x74, 0x7B, 0x02, 0x87, 0xEF, 0x5B, 0x9E, 0x38, 0x16, 0xC6, 0xCB, 0x00, 0xF3, 0xB2, 0x63, + 0xB2, 0x63, 0xB0, 0xD3, 0x58, 0x92, 0x4A, 0xEE, 0x1E, 0xD5, 0x96, 0xCD, 0xAA, 0x8C, 0x78, 0x5F, + 0xDF, 0x86, 0x15, 0xB1, 0x40, 0x94, 0x8E, 0x3E, 0x67, 0xDE, 0x38, 0xC0, 0xFC, 0x3F, 0xB8, 0xB8, + 0x6C, 0xAC, 0x23, 0x8E, 0xBF, 0xB2, 0x56, 0xB0, 0xAE, 0x93, 0xA5, 0xFA, 0x29, 0xC6, 0x8F, 0xCF, + 0x1B, 0xE3, 0xD9, 0xF0, 0x0F, 0x26, 0xE3, 0x67, 0xDF, 0x12, 0xFD, 0x11, 0x9A, 0x50, 0x59, 0x4B, + 0x22, 0xFC, 0xA1, 0x70, 0xC1, 0x7F, 0x87, 0xFA, 0x9D, 0xF0, 0xC0, 0xB9, 0x73, 0xE7, 0xD1, 0x5B, + 0x7C, 0x3B, 0x3C, 0xAC, 0x17, 0x07, 0xDD, 0x46, 0xF4, 0x56, 0x57, 0xF7, 0x72, 0xB4, 0x21, 0x5C, + 0x72, 0xC9, 0xE7, 0x66, 0xB1, 0x6D, 0xA8, 0xDA, 0x6D, 0x99, 0xD9, 0x83, 0x71, 0xFF, 0x2A, 0x46, + 0xAB, 0xE4, 0x0F, 0x76, 0xD2, 0xD9, 0x83, 0xE3, 0x9A, 0x98, 0x41, 0x38, 0x1E, 0x7B, 0xE1, 0x7A, + 0x28, 0x5A, 0x70, 0xC6, 0xE1, 0xA3, 0x7B, 0x25, 0x14, 0x9F, 0x26, 0xF2, 0x5D, 0x2F, 0x4C, 0xED, + 0xE5, 0x98, 0x41, 0xF5, 0x66, 0x40, 0x4A, 0x11, 0xC2, 0xDD, 0x25, 0x50, 0x00, 0xC6, 0x9B, 0x2F, + 0xAE, 0x08, 0xA4, 0xE7, 0x6E, 0x45, 0xD9, 0xD2, 0x3B, 0x8B, 0xB2, 0x8D, 0xD6, 0x10, 0xD0, 0x3F, + 0xB9, 0x5D, 0x5E, 0x5F, 0xBF, 0xA6, 0xD4, 0x94, 0x35, 0xA8, 0xB1, 0x57, 0x61, 0x82, 0xCE, 0x9F, + 0xA2, 0x23, 0x5E, 0xCA, 0x4C, 0xCC, 0x8A, 0x0C, 0xD6, 0xD7, 0x2F, 0xE9, 0x2D, 0x4C, 0xC5, 0x77, + 0x3C, 0xE3, 0x7C, 0x7C, 0xBD, 0x2A, 0x7F, 0x81, 0xAB, 0xEC, 0xE0, 0xEC, 0xA5, 0x23, 0x7D, 0x79, + 0xF6, 0xF7, 0xE4, 0x60, 0x90, 0x92, 0xDA, 0xE3, 0xAF, 0xDD, 0x05, 0xE5, 0xB1, 0xE7, 0xB8, 0x6A, + 0xA7, 0xAE, 0xE7, 0xDC, 0x6A, 0x02, 0xDC, 0xC1, 0x55, 0x18, 0x79, 0xF8, 0xD6, 0x42, 0x9B, 0x84, + 0xBF, 0xBE, 0x07, 0xEF, 0x60, 0x4C, 0xBD, 0x84, 0x98, 0x19, 0x9A, 0x34, 0x3C, 0xB3, 0x44, 0x6D, + 0x30, 0x42, 0x3C, 0xEF, 0x7B, 0x25, 0x58, 0x7E, 0x98, 0xD2, 0xE6, 0x87, 0x2A, 0x95, 0x20, 0xCD, + 0x1B, 0xD7, 0x0B, 0x00, 0x92, 0xFD, 0x3F, 0x07, 0x32, 0x23, 0x63, 0xFF, 0xB8, 0x28, 0x5B, 0xBF, + 0xFC, 0x48, 0x4A, 0x42, 0x2C, 0x61, 0x12, 0x75, 0xA9, 0xCB, 0xA7, 0xD4, 0x1B, 0xF2, 0x70, 0x66, + 0x5E, 0xD8, 0x19, 0xB3, 0x8C, 0xEB, 0x64, 0x9D, 0xF0, 0x3F, 0x03, 0x37, 0xC0, 0x2D, 0xCA, 0xBF, + 0xE0, 0x55, 0x06, 0x39, 0x2D, 0xBD, 0x40, 0xFC, 0xC6, 0xF4, 0xA4, 0xA3, 0xC7, 0x33, 0x33, 0xB8, + 0xEB, 0x78, 0xEE, 0x0C, 0x38, 0x12, 0x78, 0x57, 0x24, 0x98, 0x99, 0x94, 0xE4, 0x3F, 0xE1, 0x6E, + 0x6B, 0x00, 0x71, 0x3C, 0xFE, 0x6F, 0xA1, 0xA9, 0xD4, 0x12, 0xAF, 0x07, 0x44, 0x9B, 0xD7, 0x82, + 0xEB, 0xD7, 0xF8, 0x54, 0x8F, 0x91, 0x7E, 0x8B, 0x2C, 0x9B, 0x52, 0xA3, 0x1F, 0x3F, 0x49, 0xD0, + 0x26, 0x0F, 0x18, 0x04, 0xE7, 0x8C, 0xB8, 0xE2, 0x83, 0x33, 0xCB, 0xB4, 0xFD, 0x11, 0x7A, 0x6A, + 0xD2, 0xD0, 0x3F, 0x59, 0x9D, 0xD0, 0x95, 0x84, 0x40, 0x8B, 0x68, 0xF3, 0x77, 0x06, 0x48, 0xF4, + 0xD0, 0x40, 0xA1, 0x40, 0xE3, 0x03, 0xB0, 0x05, 0xD9, 0x01, 0xFE, 0x35, 0xB2, 0xFE, 0xF8, 0x4C, + 0x00, 0x3F, 0x5A, 0x79, 0xF3, 0x78, 0x62, 0x55, 0x66, 0x5E, 0x96, 0x8C, 0x3C, 0x10, 0xEA, 0x89, + 0xE5, 0xAD, 0x09, 0x9C, 0x5A, 0x49, 0xBC, 0xF2, 0x30, 0xA9, 0x87, 0xF7, 0x00, 0x31, 0x44, 0x88, + 0x25, 0xD4, 0xC1, 0x50, 0x64, 0x7E, 0x7D, 0x83, 0xD3, 0xAF, 0xEA, 0x23, 0xC5, 0xD9, 0x1B, 0xAE, + 0x86, 0xE5, 0xD2, 0xD2, 0xF2, 0x33, 0xBF, 0x08, 0x67, 0xE2, 0x0E, 0x6F, 0xC6, 0x36, 0x25, 0x3F, + 0xAB, 0xCC, 0x02, 0x0A, 0x1B, 0x19, 0x95, 0x63, 0x42, 0x4F, 0xF9, 0xB1, 0xA9, 0xDD, 0xCD, 0x9D, + 0x2C, 0x67, 0x00, 0x60, 0x78, 0x56, 0xDF, 0xA2, 0xC6, 0x95, 0x4A, 0x39, 0x1C, 0x35, 0x4E, 0x9B, + 0x29, 0xB8, 0xA8, 0x71, 0x99, 0xE9, 0x85, 0x47, 0x72, 0x79, 0x85, 0xC6, 0xCD, 0xAC, 0x69, 0x6E, + 0xB3, 0x3E, 0x58, 0x55, 0x9A, 0x35, 0xB3, 0xB2, 0x12, 0x7E, 0xE6, 0x36, 0x2C, 0x1B, 0x2C, 0x52, + 0x4E, 0x4B, 0xDF, 0xB4, 0xAE, 0xD1, 0xED, 0x1A, 0x59, 0x6D, 0xB3, 0xEE, 0x86, 0xD3, 0x63, 0x58, + 0xC3, 0x7A, 0x0E, 0x0D, 0x34, 0xED, 0x13, 0x25, 0x47, 0xEF, 0x0F, 0xFB, 0x05, 0x8D, 0x93, 0x1E, + 0x15, 0x38, 0xE9, 0xAB, 0x9C, 0x86, 0xF8, 0x8B, 0x1A, 0x2A, 0x65, 0xFA, 0x2F, 0x83, 0x42, 0x6D, + 0x08, 0x14, 0x62, 0x08, 0x3F, 0xBB, 0x41, 0x9E, 0x70, 0xBA, 0x53, 0xD1, 0x06, 0xF8, 0xF5, 0xC1, + 0xBE, 0xB5, 0xCF, 0x39, 0x4C, 0x29, 0x17, 0xD5, 0xB6, 0xFE, 0x6D, 0x5F, 0x82, 0xF9, 0xDC, 0x24, + 0x3F, 0xFC, 0x40, 0xA2, 0xB2, 0x3F, 0xEF, 0x0F, 0x06, 0x29, 0x2F, 0x3D, 0xE1, 0x4C, 0xCA, 0x14, + 0x33, 0x7D, 0x49, 0x94, 0xBC, 0x5C, 0x11, 0xDD, 0x45, 0xD6, 0x91, 0xD1, 0xE1, 0x29, 0x31, 0x56, + 0x92, 0x97, 0x31, 0xA0, 0x7D, 0x6C, 0x2D, 0xA2, 0xF8, 0x72, 0xE1, 0x99, 0x1B, 0x2B, 0x4E, 0x7B, + 0x65, 0xAC, 0x2F, 0xCF, 0xE9, 0x43, 0x98, 0x6B, 0x4C, 0xED, 0xFC, 0x64, 0x26, 0x9D, 0x3F, 0x45, + 0x79, 0xD6, 0xA1, 0xD5, 0xAD, 0x84, 0xAC, 0xD9, 0x9D, 0x88, 0x94, 0xA6, 0x9F, 0xF9, 0x23, 0x7E, + 0xDD, 0xA4, 0x19, 0x3E, 0x7C, 0x73, 0x28, 0x48, 0x42, 0x09, 0x3E, 0xB8, 0xF4, 0x93, 0xFD, 0xD6, + 0x66, 0x53, 0x0B, 0x86, 0xF4, 0xD3, 0xC9, 0x34, 0x78, 0x54, 0x54, 0x5A, 0xEF, 0xA5, 0x8B, 0x54, + 0x8E, 0x87, 0x09, 0xEE, 0x33, 0xEF, 0x70, 0x0A, 0x4E, 0x32, 0x99, 0x00, 0xF5, 0x72, 0x30, 0x4C, + 0x1D, 0xA6, 0x65, 0x98, 0x91, 0x45, 0xC3, 0x1A, 0xA9, 0x37, 0xCD, 0x50, 0x63, 0xC4, 0x1B, 0x34, + 0xB8, 0x21, 0xA5, 0x9C, 0x89, 0xC1, 0xC2, 0x18, 0xBC, 0x22, 0x32, 0x9C, 0x79, 0x1E, 0x7A, 0x09, + 0xAC, 0x59, 0xA8, 0x0D, 0x6C, 0xEF, 0xA8, 0xFF, 0x93, 0x2F, 0x69, 0xE2, 0xD8, 0x17, 0x13, 0x60, + 0x3D, 0x95, 0xCB, 0xD3, 0x2E, 0x09, 0x77, 0xA6, 0x72, 0x49, 0x2D, 0x58, 0xDD, 0x97, 0x21, 0xE2, + 0x45, 0x49, 0x1B, 0x17, 0x2C, 0x89, 0x92, 0xF0, 0xE6, 0x3A, 0x14, 0x26, 0xBB, 0x43, 0x35, 0x84, + 0x97, 0x87, 0x52, 0x7F, 0x24, 0x8D, 0x45, 0x16, 0x1B, 0x29, 0xD8, 0x36, 0x56, 0x8F, 0x48, 0xA1, + 0x91, 0x28, 0x0F, 0xCA, 0xBA, 0xAD, 0x1D, 0xF7, 0x4D, 0xA2, 0x7E, 0x52, 0xE9, 0xF1, 0x89, 0xA0, + 0x38, 0x76, 0x48, 0xDE, 0x44, 0x0A, 0x6B, 0xB0, 0x4D, 0x0D, 0xC0, 0x20, 0x36, 0x8D, 0x22, 0x74, + 0x2B, 0xFA, 0x07, 0x88, 0xD4, 0x0A, 0x52, 0x40, 0x8D, 0x44, 0x54, 0xFB, 0x8C, 0x5C, 0x8A, 0xB3, + 0x8C, 0xC7, 0xE4, 0x58, 0x3D, 0xA0, 0xA0, 0x1D, 0xB9, 0xCA, 0x13, 0x68, 0x19, 0x64, 0x57, 0x34, + 0x9B, 0x21, 0x8D, 0x43, 0x04, 0x64, 0x63, 0x40, 0xF0, 0x86, 0x1A, 0x96, 0x81, 0x40, 0x8A, 0xDB, + 0x29, 0x1C, 0x5C, 0x82, 0xD9, 0xE8, 0x81, 0x2C, 0x02, 0xB3, 0x93, 0xCF, 0xAE, 0xA5, 0xEC, 0xA5, + 0xED, 0x77, 0x44, 0xE8, 0x47, 0x5E, 0xA9, 0x75, 0xAB, 0xFE, 0xAD, 0x36, 0x33, 0x93, 0xAE, 0xFC, + 0x34, 0x71, 0x02, 0x03, 0xDB, 0xA5, 0x3C, 0xBF, 0xB8, 0x3E, 0x39, 0xBF, 0x3A, 0xBE, 0x3C, 0x87, + 0xB5, 0x72, 0x75, 0xA3, 0x75, 0xEE, 0xE2, 0x46, 0xB4, 0x3A, 0x17, 0x49, 0x69, 0xD0, 0xED, 0xFB, + 0x77, 0x34, 0x50, 0xEC, 0x52, 0x62, 0x92, 0x2E, 0xB4, 0x5D, 0xC9, 0x5D, 0xD0, 0xA4, 0x19, 0x54, + 0x36, 0x63, 0x33, 0xDA, 0x37, 0x38, 0xBE, 0xFC, 0xF1, 0xF8, 0xB2, 0x4E, 0xEB, 0xB8, 0xA5, 0x21, + 0xD0, 0xFB, 0xDC, 0x95, 0x60, 0xA9, 0x6C, 0xCC, 0x7B, 0xF0, 0x95, 0xF9, 0x09, 0xF9, 0xB3, 0x6C, + 0xF1, 0xE1, 0x87, 0xCB, 0xCB, 0xE3, 0x73, 0x7D, 0x6F, 0x66, 0x36, 0x35, 0x1A, 0xE0, 0x30, 0xF9, + 0xCC, 0xA6, 0x68, 0xFC, 0x79, 0x1E, 0xD0, 0xDF, 0xA2, 0x85, 0xCA, 0xD4, 0x96, 0x24, 0x96, 0x5C, + 0x65, 0xB0, 0x3B, 0x91, 0xC0, 0xEE, 0x7D, 0x83, 0x05, 0x20, 0x29, 0xE2, 0xD8, 0xCB, 0xC7, 0x94, + 0xC1, 0x92, 0xFA, 0xEC, 0x1D, 0xE2, 0xEF, 0x67, 0xAE, 0x0F, 0xF5, 0xE3, 0x4F, 0x85, 0x92, 0x47, + 0xA1, 0x78, 0x24, 0x41, 0x2B, 0xC3, 0xD4, 0xF1, 0x5C, 0xCA, 0xA8, 0x3D, 0x2B, 0x87, 0xE4, 0x99, + 0xA8, 0x83, 0xDE, 0xCF, 0x29, 0x67, 0x13, 0x53, 0x83, 0x22, 0xDD, 0x71, 0x20, 0x87, 0x77, 0xE2, + 0xB1, 0x3D, 0xDC, 0x2A, 0xBB, 0x95, 0x5B, 0xF9, 0xDD, 0x17, 0xD2, 0xFB, 0x42, 0x1A, 0x4F, 0x43, + 0xD5, 0xE6, 0x27, 0xF1, 0x33, 0x54, 0x92, 0x5A, 0x2F, 0x23, 0xC1, 0x55, 0x86, 0x8F, 0x31, 0xE2, + 0xC8, 0xE5, 0xD1, 0x28, 0xDF, 0x1C, 0x0C, 0x23, 0x79, 0xD0, 0xF4, 0x76, 0x1B, 0xD9, 0x6F, 0xB0, + 0x6A, 0xF9, 0x59, 0xC9, 0xB0, 0xEB, 0x21, 0xC2, 0xE3, 0xCB, 0xCB, 0x8B, 0xC4, 0xCC, 0xB5, 0xB4, + 0x71, 0x57, 0x34, 0x45, 0x30, 0x6B, 0x11, 0x4A, 0x43, 0x1D, 0x0D, 0xEA, 0xA3, 0xC9, 0xA9, 0xC5, + 0xA8, 0x1B, 0x98, 0x21, 0x0B, 0xE2, 0x99, 0x51, 0xB1, 0x87, 0x18, 0xEE, 0x67, 0xE9, 0x5D, 0xB6, + 0x4C, 0x89, 0x55, 0x18, 0xBD, 0x09, 0x42, 0x7C, 0x63, 0x33, 0xF5, 0xD8, 0x68, 0x59, 0x93, 0x9F, + 0xC0, 0xA6, 0x9C, 0xC8, 0x24, 0x29, 0xED, 0xA7, 0xB7, 0x47, 0x13, 0x4F, 0x1F, 0xA7, 0xB2, 0x85, + 0xBC, 0xB3, 0xEF, 0xA9, 0x43, 0x4C, 0x7C, 0x5E, 0xDB, 0x6B, 0xFA, 0x22, 0x67, 0x1E, 0xCA, 0xF6, + 0x11, 0x67, 0x38, 0xE8, 0x77, 0x27, 0xB0, 0x6F, 0x79, 0xD2, 0x3A, 0xBC, 0x22, 0xC9, 0xAC, 0x88, + 0x58, 0xD7, 0xE2, 0xB7, 0xF8, 0xA6, 0x3C, 0x38, 0x65, 0xE4, 0xE8, 0xA8, 0x63, 0x85, 0xFF, 0xD8, + 0xB1, 0x80, 0x29, 0xC7, 0x08, 0x84, 0xC8, 0x4E, 0xD0, 0x9C, 0xE0, 0x13, 0x75, 0x2D, 0x24, 0x7A, + 0xEC, 0x00, 0xAD, 0xC4, 0x6E, 0x41, 0x88, 0x33, 0xAA, 0x09, 0x72, 0x50, 0x5F, 0xB7, 0xF3, 0x3B, + 0x87, 0x17, 0x17, 0x97, 0x47, 0x27, 0xE7, 0x07, 0x57, 0xC7, 0xE0, 0x4C, 0xF6, 0x3F, 0x5C, 0x5D, + 0x5F, 0x7D, 0xEC, 0xE3, 0xAF, 0x3F, 0x1E, 0x9C, 0x9E, 0x1C, 0x5D, 0x7F, 0x38, 0xFF, 0xDB, 0xF9, + 0xC5, 0x4F, 0xE7, 0xD2, 0xE1, 0x83, 0x65, 0xFA, 0x77, 0x72, 0xD6, 0x83, 0xC8, 0x8E, 0x62, 0x4C, + 0x83, 0xAE, 0xC0, 0xA2, 0x43, 0x7B, 0x62, 0x8E, 0x75, 0x45, 0xDC, 0xA2, 0x5D, 0xDC, 0x9E, 0x52, + 0xF6, 0xEE, 0x6D, 0xEA, 0xD0, 0x16, 0xEC, 0x0B, 0x78, 0x6E, 0x01, 0x3E, 0x97, 0x18, 0x89, 0x87, + 0xBF, 0x3B, 0x86, 0x81, 0xF4, 0xA8, 0x6F, 0xE4, 0xE1, 0xCE, 0x64, 0x93, 0xDC, 0x88, 0xC9, 0x1F, + 0x44, 0x3D, 0xF3, 0x25, 0x0B, 0x3E, 0x34, 0x1D, 0x42, 0x51, 0x30, 0xCC, 0xB8, 0xDA, 0x0E, 0x28, + 0x83, 0x6D, 0xB1, 0xDC, 0x08, 0x7E, 0x58, 0xE7, 0x80, 0xF0, 0x8F, 0xBC, 0x1A, 0x3E, 0x20, 0xCD, + 0x92, 0x28, 0xF2, 0xD3, 0x5D, 0xBF, 0x4D, 0xD6, 0xDA, 0x78, 0x6D, 0xB9, 0xCD, 0x3A, 0xAC, 0x93, + 0x38, 0xB8, 0x94, 0x0C, 0x75, 0xD4, 0x05, 0x29, 0x33, 0x9D, 0x08, 0x00, 0xF7, 0x2D, 0x7B, 0x64, + 0x07, 0x71, 0x97, 0xE1, 0x59, 0x7D, 0x66, 0xFC, 0x2F, 0x42, 0xA8, 0xF2, 0x63, 0x41, 0x1B, 0x5A, + 0xB9, 0xAD, 0xAE, 0xE6, 0xBF, 0xBF, 0x24, 0x53, 0x44, 0x3C, 0xCD, 0xB5, 0xE6, 0x4A, 0xDC, 0x9B, + 0xAB, 0xAB, 0xEC, 0xED, 0xB8, 0xF1, 0x98, 0x8C, 0x5C, 0xD7, 0x2A, 0x03, 0x4E, 0x00, 0x3C, 0xEE, + 0xF4, 0xEA, 0xF0, 0x1D, 0x24, 0x2F, 0xB5, 0x2D, 0x17, 0x43, 0xB8, 0x05, 0x54, 0x4B, 0x7B, 0xC5, + 0x91, 0x3F, 0x5B, 0x16, 0x82, 0x4A, 0xE1, 0x75, 0x27, 0x5F, 0x51, 0x06, 0x96, 0x28, 0x23, 0x75, + 0x80, 0x08, 0x0B, 0x07, 0xD4, 0xA9, 0xA9, 0xEB, 0xFB, 0x36, 0xDE, 0xA8, 0xE6, 0x1A, 0x82, 0xA3, + 0x37, 0x52, 0x9E, 0x78, 0xA4, 0x4A, 0x5F, 0xCE, 0xCE, 0x3A, 0x13, 0xFE, 0x4F, 0xFA, 0x48, 0xB4, + 0x5F, 0xD7, 0xB4, 0x5F, 0xCF, 0xCE, 0x06, 0x83, 0x8E, 0xCF, 0xFE, 0xA9, 0x18, 0x88, 0xEE, 0x3B, + 0xE0, 0x58, 0x93, 0xBE, 0xC7, 0x56, 0x4D, 0x51, 0x1C, 0x16, 0x5C, 0x38, 0xBF, 0x14, 0xFF, 0x2F, + 0xDE, 0x37, 0x77, 0xDC, 0x0E, 0xD9, 0x84, 0x51, 0xB8, 0x6B, 0x6C, 0x6C, 0x6C, 0xBE, 0x60, 0x79, + 0x2C, 0x99, 0x2C, 0x3B, 0xD2, 0x85, 0xF7, 0xD8, 0x1A, 0xBC, 0x26, 0xBD, 0x45, 0x50, 0xBE, 0xC0, + 0x51, 0x69, 0xB0, 0x84, 0x27, 0x30, 0xFC, 0x7A, 0xC4, 0x1C, 0x63, 0x8A, 0x4F, 0x0B, 0x39, 0x21, + 0xC6, 0x16, 0xE9, 0x6D, 0x75, 0x7A, 0xC6, 0xE6, 0xAE, 0x8E, 0x97, 0xD8, 0x62, 0xBD, 0x26, 0x1B, + 0x0B, 0x66, 0xA5, 0xC7, 0xB8, 0xD9, 0x88, 0xB9, 0x59, 0xEB, 0x1A, 0x5B, 0x6B, 0xDD, 0xEE, 0x9A, + 0xB1, 0xD5, 0xE9, 0x6E, 0xF7, 0xB4, 0xFC, 0xE8, 0xAD, 0xDE, 0x6B, 0x8C, 0x24, 0x59, 0x10, 0x6F, + 0x2F, 0x90, 0xA9, 0x5B, 0xFA, 0x40, 0x3D, 0xCE, 0x50, 0xB7, 0x8B, 0xEC, 0xEC, 0xEC, 0xEC, 0xEE, + 0xF6, 0x48, 0xEB, 0x88, 0x2B, 0x18, 0x56, 0xE1, 0xBF, 0xAD, 0x44, 0x4C, 0xCA, 0x7E, 0xB1, 0x43, + 0x47, 0x66, 0x00, 0x46, 0x75, 0x60, 0x8F, 0x9C, 0x84, 0xC7, 0xA1, 0x0E, 0x67, 0x23, 0xB6, 0x26, + 0x92, 0xF5, 0x8A, 0xCA, 0xB9, 0xDB, 0x86, 0x51, 0x1B, 0x07, 0x92, 0xD5, 0x6B, 0xA3, 0xFC, 0x30, + 0xAA, 0x82, 0x1D, 0xD0, 0x61, 0x68, 0x07, 0x18, 0x35, 0x26, 0x0E, 0x6E, 0x53, 0xA4, 0x28, 0x2F, + 0x95, 0x8F, 0xC4, 0xFD, 0xAE, 0xA8, 0x6F, 0xD7, 0xD6, 0x10, 0x15, 0xA6, 0xA8, 0x8D, 0xBB, 0x1B, + 0x6C, 0x39, 0xCE, 0xAD, 0x7C, 0x97, 0x03, 0xBC, 0x32, 0x2C, 0xA1, 0xDC, 0xBE, 0xF3, 0xCC, 0xB6, + 0x2C, 0xF1, 0x8A, 0x20, 0x1B, 0xD2, 0x21, 0x3E, 0x10, 0xD2, 0xEC, 0x0D, 0xCA, 0x2A, 0xCD, 0xAD, + 0x30, 0x2E, 0xD7, 0xA4, 0xD9, 0x30, 0xFA, 0x96, 0xD1, 0xC1, 0xFB, 0x2C, 0x56, 0x08, 0xDF, 0x6D, + 0xCD, 0x2C, 0xDF, 0x5E, 0x81, 0xB5, 0xDE, 0xFA, 0xBA, 0xC6, 0x02, 0xC8, 0x9E, 0xE9, 0x1C, 0xD3, + 0x3A, 0xC7, 0xAC, 0x5C, 0xBB, 0xE0, 0xA9, 0x66, 0xD8, 0x09, 0x19, 0x0F, 0x21, 0x63, 0x67, 0xCA, + 0x20, 0x66, 0x67, 0x18, 0x06, 0xF6, 0xC7, 0xEE, 0x05, 0xEB, 0x2F, 0x70, 0x5E, 0x89, 0x50, 0x22, + 0x15, 0x8D, 0x30, 0x38, 0x2A, 0x0E, 0x09, 0x37, 0x8F, 0xEB, 0x37, 0x64, 0x24, 0xD2, 0xE4, 0x18, + 0xD7, 0x5B, 0xDB, 0x8F, 0x8C, 0x17, 0x3F, 0x40, 0x57, 0x93, 0x01, 0xB0, 0xEC, 0xD9, 0xFC, 0xC1, + 0x87, 0x7C, 0x52, 0x11, 0xA1, 0xB3, 0x33, 0xF5, 0xBA, 0xE4, 0x5B, 0x1B, 0x26, 0x73, 0x98, 0x80, + 0xD4, 0xA9, 0x39, 0x9E, 0xC2, 0x59, 0x70, 0xDB, 0xC5, 0x6D, 0x8B, 0xCD, 0x51, 0xD0, 0x2F, 0x6B, + 0xDD, 0xD4, 0x41, 0xC5, 0xBC, 0x7D, 0x70, 0x7D, 0x7E, 0x71, 0x7D, 0x74, 0x7C, 0x78, 0x72, 0x76, + 0x70, 0x9A, 0xEA, 0x0E, 0x9F, 0xC2, 0x2C, 0x65, 0x61, 0xE3, 0x22, 0x96, 0x12, 0x72, 0x57, 0x74, + 0x83, 0xAF, 0xD9, 0x38, 0x88, 0x56, 0x74, 0xF1, 0x18, 0x53, 0x24, 0x2E, 0xC3, 0x84, 0xF2, 0xFC, + 0x4B, 0x24, 0x37, 0x01, 0x81, 0xA2, 0x93, 0xEE, 0x26, 0x6A, 0xDC, 0xB1, 0x90, 0xDC, 0x6A, 0x8C, + 0x65, 0x9D, 0x6C, 0xC3, 0xF4, 0xC0, 0x72, 0x43, 0x84, 0x44, 0xD6, 0xC9, 0xC6, 0x36, 0x66, 0x50, + 0x5A, 0x49, 0xE6, 0x34, 0x50, 0x86, 0x77, 0x86, 0x1B, 0xA4, 0x23, 0xFC, 0x17, 0xEC, 0x16, 0xE5, + 0x05, 0xDA, 0x6F, 0xFA, 0xF5, 0x58, 0x62, 0xDC, 0xE2, 0x10, 0x55, 0x47, 0x2D, 0x1B, 0xB4, 0x99, + 0x63, 0x72, 0x0B, 0x87, 0x6C, 0x66, 0xE9, 0x66, 0x34, 0x60, 0xD5, 0x79, 0x7C, 0x81, 0xE3, 0xB5, + 0xF4, 0x68, 0x8D, 0x87, 0xA9, 0xA2, 0x2D, 0x59, 0x63, 0x34, 0x39, 0x5A, 0x2A, 0x8F, 0xCA, 0xEC, + 0x31, 0xA9, 0x57, 0x5B, 0x55, 0x42, 0xEC, 0x82, 0xB8, 0x80, 0xD0, 0xA0, 0xCE, 0xD0, 0xD9, 0xAA, + 0x2A, 0xF8, 0x14, 0xDA, 0x96, 0xD0, 0x37, 0x45, 0xB9, 0xBA, 0x5C, 0x3D, 0xD6, 0x96, 0xA6, 0x1F, + 0xD7, 0x67, 0x67, 0xD7, 0x47, 0x07, 0x83, 0xF7, 0x29, 0x2D, 0x11, 0x37, 0xCD, 0x62, 0xA3, 0x26, + 0x82, 0x1A, 0xD7, 0x52, 0x61, 0xB0, 0xB1, 0x4A, 0x08, 0x7B, 0x8F, 0xA0, 0x98, 0xC5, 0x2B, 0xEE, + 0xBD, 0xAC, 0x8E, 0x96, 0x01, 0xBA, 0x9F, 0x25, 0x7B, 0x9B, 0xEE, 0xEB, 0xE7, 0xD8, 0x73, 0xD9, + 0xFD, 0xD6, 0x8B, 0xFA, 0x2D, 0xF4, 0xAD, 0x97, 0xD0, 0x6F, 0x30, 0x0B, 0x3C, 0xC3, 0xAE, 0x7B, + 0x56, 0x53, 0xA5, 0x24, 0xA6, 0x72, 0x33, 0xA6, 0xDC, 0xAC, 0x5E, 0xDC, 0x2C, 0xCD, 0x94, 0xF9, + 0xBB, 0x98, 0xCD, 0xB8, 0x9A, 0xC6, 0xBB, 0x45, 0x0B, 0xD6, 0xD2, 0xBD, 0x22, 0x71, 0xC5, 0x96, + 0xFE, 0xB7, 0x15, 0x84, 0xB0, 0xB3, 0x64, 0x99, 0x76, 0xB6, 0xF4, 0x38, 0x25, 0xDF, 0x4D, 0x6C, + 0x99, 0x3E, 0xEB, 0x45, 0x7D, 0x46, 0x96, 0xB5, 0xDA, 0xE1, 0xE6, 0xE3, 0x99, 0x75, 0xDC, 0x73, + 0x34, 0xB0, 0xFF, 0x53, 0x6D, 0x6B, 0xB8, 0x8F, 0xA6, 0x9C, 0x64, 0x69, 0x90, 0xF0, 0xC3, 0x2C, + 0x4D, 0x41, 0x94, 0x7C, 0x6E, 0x77, 0x25, 0x99, 0x22, 0x42, 0xD3, 0x31, 0xD1, 0x09, 0x55, 0x7C, + 0x60, 0x20, 0xED, 0xFC, 0xE3, 0x16, 0x73, 0x9C, 0x45, 0xA1, 0x4D, 0xDC, 0x59, 0x80, 0x7F, 0x98, + 0xE2, 0x34, 0x01, 0xA1, 0x06, 0xAE, 0x7A, 0x38, 0x80, 0x1B, 0xDC, 0x37, 0x20, 0xB8, 0x09, 0x25, + 0xCD, 0xC4, 0x50, 0x6A, 0xB6, 0x09, 0x0D, 0x86, 0xCA, 0x1D, 0x6C, 0xC6, 0x3D, 0x63, 0x46, 0x62, + 0xAE, 0xAD, 0xD3, 0xA0, 0x8C, 0x83, 0x04, 0xB1, 0x89, 0xAA, 0x1C, 0x94, 0xF2, 0x90, 0x16, 0x8D, + 0x0E, 0x96, 0x57, 0xC2, 0x15, 0xFD, 0x88, 0x8F, 0x55, 0x2E, 0xFE, 0xB6, 0x22, 0x09, 0x3C, 0x75, + 0xF0, 0x2C, 0x33, 0x92, 0x75, 0x3C, 0x37, 0x27, 0xAB, 0xD7, 0xF2, 0x82, 0x0A, 0x56, 0x86, 0x73, + 0xA2, 0x5B, 0x2C, 0xB6, 0x70, 0x31, 0xB0, 0x68, 0x9C, 0x83, 0x8F, 0x67, 0x6F, 0x2E, 0x4E, 0x39, + 0xD6, 0x54, 0xBC, 0xD0, 0xD8, 0x75, 0x46, 0x2C, 0xA9, 0xD7, 0x11, 0x1D, 0x79, 0x34, 0xB9, 0x27, + 0x93, 0xEE, 0x90, 0x44, 0x1F, 0xC3, 0xDA, 0x2F, 0x89, 0x41, 0x5F, 0x11, 0x86, 0xF1, 0xB6, 0xB1, + 0x97, 0x4C, 0xB2, 0x1A, 0x15, 0xBF, 0x22, 0xD9, 0x86, 0x91, 0x9B, 0x00, 0xC5, 0xB2, 0x29, 0x5A, + 0x36, 0x4C, 0x0F, 0xE7, 0x17, 0x2B, 0x9A, 0x8C, 0xAE, 0x73, 0x76, 0x75, 0x26, 0x7F, 0xD1, 0xB0, + 0x4A, 0xC9, 0x72, 0x15, 0x46, 0x1A, 0x33, 0x3C, 0x61, 0xD5, 0x3D, 0xCD, 0xD1, 0xCA, 0x82, 0xB4, + 0xA6, 0x1E, 0x7B, 0x6B, 0x4F, 0xC2, 0x1F, 0xD7, 0xC0, 0x7A, 0x1C, 0xFE, 0xF7, 0x7F, 0xA9, 0x2C, + 0xE2, 0xB7, 0x66, 0x23, 0xC1, 0x68, 0x2D, 0xCC, 0x44, 0xDB, 0xF6, 0xA4, 0xC5, 0x59, 0x48, 0xFB, + 0x07, 0x2B, 0xCA, 0xA0, 0x9E, 0x5F, 0x19, 0x17, 0x8D, 0x51, 0x5A, 0xA9, 0x2D, 0x05, 0x71, 0x4A, + 0x03, 0x16, 0x24, 0x05, 0xC9, 0xF5, 0x59, 0x0A, 0xDF, 0x4B, 0x46, 0x9F, 0x58, 0x19, 0xAF, 0xFC, + 0x4E, 0xCC, 0xB3, 0xC2, 0xF9, 0x99, 0x6E, 0xB3, 0xBF, 0x12, 0xE7, 0x02, 0x43, 0x3E, 0xE7, 0xE5, + 0x27, 0x87, 0xED, 0x25, 0x4C, 0x0E, 0xCA, 0x78, 0xAC, 0x38, 0x3D, 0xA4, 0x24, 0xF5, 0x54, 0xD3, + 0x46, 0x7A, 0xC0, 0x57, 0x9D, 0x39, 0x74, 0xAC, 0xAF, 0x3D, 0x15, 0xEF, 0xF3, 0xCF, 0x2A, 0x3A, + 0xF6, 0x9B, 0xE9, 0xE9, 0xE6, 0xEF, 0x8D, 0xC6, 0xD2, 0x5A, 0xB1, 0x52, 0x7F, 0xEA, 0xD2, 0x71, + 0x4F, 0x96, 0x2E, 0xFC, 0x6C, 0xAB, 0xBB, 0x20, 0xB5, 0x97, 0xA2, 0x62, 0xF5, 0x56, 0x62, 0xC1, + 0x6A, 0x34, 0x6F, 0x5B, 0xF2, 0xFB, 0xE2, 0xA9, 0x5B, 0x93, 0x9C, 0x51, 0x96, 0x30, 0xB6, 0x73, + 0x9B, 0xA4, 0x09, 0xFB, 0x52, 0x49, 0xA6, 0xAF, 0x79, 0x86, 0x97, 0xAA, 0x86, 0xF8, 0xB4, 0xAA, + 0x00, 0x5B, 0xFF, 0xBB, 0xB5, 0xDE, 0x09, 0x30, 0x28, 0x7E, 0xB8, 0xB2, 0x47, 0x92, 0xE9, 0x3D, + 0xC2, 0x0B, 0x09, 0xB0, 0xB2, 0x6E, 0xF3, 0x5C, 0xA6, 0xB0, 0x0C, 0xBE, 0xF3, 0x94, 0x9B, 0xA1, + 0x3C, 0x19, 0xEB, 0x6B, 0x5C, 0x7D, 0x87, 0x21, 0x6B, 0x6B, 0xD2, 0x2D, 0x1A, 0xF8, 0xAC, 0x2E, + 0xF8, 0xB1, 0x9E, 0x92, 0x3E, 0x54, 0xE4, 0x6A, 0x5D, 0x45, 0xCC, 0x78, 0x15, 0x56, 0x29, 0xE7, + 0xD8, 0x57, 0xF9, 0x33, 0x0E, 0xEA, 0x9E, 0x80, 0xA3, 0xEC, 0x02, 0x08, 0xEC, 0x26, 0x3E, 0x72, + 0xEB, 0xF0, 0xDC, 0x8E, 0xE1, 0x7E, 0x80, 0x14, 0xAF, 0x2E, 0x8A, 0xE2, 0x3B, 0x81, 0x79, 0x8B, + 0x7A, 0xFF, 0xC1, 0x0E, 0x86, 0x77, 0x24, 0xB7, 0x0E, 0xBB, 0x5D, 0x41, 0x6F, 0xCD, 0xD9, 0x38, + 0x78, 0x99, 0x7C, 0x94, 0x82, 0xF7, 0x4B, 0xE3, 0x83, 0xF3, 0xC5, 0x71, 0x1F, 0x9C, 0x54, 0x82, + 0xE6, 0xE4, 0x93, 0x28, 0x43, 0x0C, 0x1C, 0x6F, 0x95, 0xDE, 0x0C, 0xC8, 0x22, 0x27, 0x6F, 0x7C, + 0x2C, 0x98, 0x26, 0xAC, 0xCD, 0xB2, 0xA9, 0xC6, 0x5B, 0xAD, 0x0B, 0xA6, 0x7A, 0x9D, 0x4B, 0x96, + 0x2C, 0x93, 0x2E, 0x9F, 0xB6, 0xB3, 0x89, 0xAF, 0x2D, 0x8D, 0x38, 0xF3, 0x74, 0xF2, 0x84, 0x1D, + 0x6D, 0x60, 0x2D, 0xA1, 0xD5, 0xB9, 0xA4, 0x95, 0xDD, 0xB3, 0xA5, 0x10, 0x2F, 0x21, 0xF5, 0xB5, + 0x65, 0x71, 0x90, 0x9C, 0x75, 0xF3, 0xBB, 0x60, 0x39, 0xCD, 0x2F, 0x45, 0x9E, 0x77, 0xC3, 0xF2, + 0xE4, 0x5F, 0x8E, 0x0B, 0xDE, 0x15, 0xB9, 0x5C, 0x7C, 0x53, 0xA7, 0x29, 0xC5, 0x1C, 0x42, 0xD9, + 0xFF, 0x07, 0x6D, 0xC2, 0xC9, 0x8A, 0xFD, 0xA5, 0x00 }; ///main_js //To convert AP-Config\index.html to index_html[], run the Python index_html_zipper.py script in the Tools folder: @@ -1049,1090 +1056,1095 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xDC, 0xC8, 0xAF, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, - 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, - 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, - 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03, - 0x01, 0x49, 0x12, 0xCF, 0x20, 0x80, 0x8B, 0x41, 0xB2, 0x6E, 0x9D, 0xAA, 0x53, 0xCB, 0xE8, 0x5E, - 0x48, 0x6F, 0xA0, 0x97, 0x52, 0x2B, 0xE9, 0x88, 0xC8, 0x04, 0x08, 0x90, 0x18, 0x49, 0x90, 0x22, - 0x65, 0xF9, 0xBD, 0x2B, 0x89, 0x20, 0x72, 0x8A, 0x8C, 0x88, 0x8C, 0x88, 0x8C, 0xE1, 0xC3, 0x3F, - 0x9C, 0x7D, 0x39, 0xBD, 0xFB, 0xB5, 0x77, 0xCE, 0x46, 0xFE, 0xD8, 0x3C, 0xFA, 0xE9, 0x03, 0xFE, - 0x62, 0xA6, 0x6A, 0x0D, 0x3F, 0x36, 0xB8, 0xD5, 0x38, 0xFA, 0x09, 0x9E, 0x70, 0x55, 0x3F, 0xFA, - 0x89, 0xC1, 0xBF, 0x0F, 0x63, 0xEE, 0xAB, 0x4C, 0x1B, 0xA9, 0xAE, 0xC7, 0xFD, 0x8F, 0x8D, 0xC0, - 0x1F, 0x34, 0x0F, 0x1A, 0x6C, 0x27, 0xFE, 0xE5, 0xC8, 0xF7, 0x9D, 0x26, 0xFF, 0x23, 0x30, 0x1E, - 0x3E, 0x36, 0x7E, 0x69, 0x7E, 0x3D, 0x6E, 0x9E, 0xDA, 0x63, 0x47, 0xF5, 0x8D, 0x7B, 0x93, 0x37, - 0x98, 0x66, 0x5B, 0x3E, 0xB7, 0xA0, 0xE5, 0xE5, 0xF9, 0x47, 0xAE, 0x0F, 0xF9, 0xB6, 0x36, 0x72, - 0xED, 0x31, 0xFF, 0xD8, 0x9E, 0x74, 0xE2, 0x1B, 0xBE, 0xC9, 0x8F, 0xFA, 0x8E, 0xEA, 0x7E, 0xBB, - 0x08, 0x2C, 0x76, 0x7B, 0xF7, 0x57, 0xD6, 0xE7, 0x7E, 0xE0, 0x7C, 0xD8, 0x11, 0xDF, 0xC4, 0x86, - 0xB2, 0x54, 0x68, 0xDA, 0x78, 0x30, 0xF8, 0xA3, 0x63, 0xBB, 0x7E, 0x83, 0xBE, 0xC1, 0x7F, 0xD1, - 0x28, 0x8F, 0x86, 0xEE, 0x8F, 0x3E, 0xEA, 0xFC, 0xC1, 0xD0, 0x78, 0x93, 0x3E, 0x6C, 0x33, 0xC3, - 0x32, 0x7C, 0x43, 0x35, 0x9B, 0x9E, 0xA6, 0x9A, 0x30, 0xF0, 0x36, 0x1B, 0xAB, 0xDF, 0x8D, 0x71, - 0x30, 0x9E, 0x3C, 0x08, 0x3C, 0xEE, 0xD2, 0x27, 0x15, 0xE6, 0xFC, 0x51, 0xD9, 0x66, 0xDE, 0xC8, - 0x35, 0xAC, 0x6F, 0x4D, 0xDF, 0x6E, 0x0E, 0x0C, 0xFF, 0xE3, 0x13, 0xF7, 0x26, 0xB3, 0x35, 0xE1, - 0x0B, 0xE6, 0x72, 0xF3, 0x63, 0xC3, 0xF3, 0x9F, 0x4C, 0xEE, 0x8D, 0x38, 0xF7, 0x1B, 0x6C, 0xE4, - 0xF2, 0x01, 0x3C, 0x71, 0xB5, 0x9D, 0x7B, 0xDB, 0xF6, 0x3D, 0xDF, 0x55, 0x9D, 0xD6, 0xD8, 0xB0, - 0x5A, 0x9A, 0xE7, 0x35, 0x4A, 0x36, 0xA4, 0xA7, 0xF1, 0x06, 0x9E, 0xE6, 0x1A, 0x8E, 0xCF, 0xE0, - 0x3B, 0xF1, 0xC2, 0xDF, 0xFF, 0x08, 0xB8, 0xFB, 0xD4, 0xEC, 0xB6, 0xF6, 0x5B, 0x0A, 0x75, 0xFE, - 0x77, 0x78, 0xF5, 0xC3, 0x8E, 0x78, 0x2D, 0xA3, 0x4D, 0x72, 0x36, 0x95, 0x1A, 0xDC, 0x07, 0x96, - 0x0E, 0x13, 0x9A, 0x6D, 0x17, 0x6F, 0x78, 0x14, 0x6D, 0xC1, 0x7F, 0xD9, 0xD2, 0x6D, 0x2D, 0x18, - 0xC3, 0x2E, 0xBC, 0x6D, 0xD9, 0xD6, 0xD6, 0x1B, 0xCD, 0x34, 0xB4, 0x6F, 0x6F, 0xB6, 0xD9, 0x9B, - 0x96, 0x6F, 0x0F, 0x87, 0x26, 0x6F, 0xDE, 0xFB, 0x16, 0x7C, 0x1C, 0x04, 0x96, 0xE6, 0x1B, 0xB6, - 0xC5, 0xB6, 0xF8, 0x5B, 0xF6, 0xAF, 0x51, 0x6B, 0xD1, 0x03, 0x2C, 0x3F, 0x70, 0x5D, 0xE8, 0xE2, - 0x4E, 0x75, 0x87, 0xDC, 0x6F, 0x69, 0x23, 0xC3, 0xD4, 0xE1, 0xF3, 0xFF, 0x50, 0xFE, 0xE7, 0x5B, - 0xD9, 0xCD, 0xA9, 0xA9, 0x7A, 0xDE, 0xD6, 0x1B, 0x03, 0x76, 0xBC, 0xA9, 0xA9, 0x2E, 0xF7, 0x9B, - 0xBA, 0xFD, 0x68, 0xB1, 0xD8, 0xE7, 0xC0, 0x79, 0xF3, 0xF6, 0x2F, 0x51, 0xC7, 0xFF, 0xF6, 0x56, - 0x4C, 0x77, 0x7A, 0xF6, 0x08, 0xEC, 0xC9, 0xE4, 0x5B, 0x9E, 0x0F, 0x08, 0xAB, 0x35, 0x87, 0xAE, - 0x1D, 0x38, 0x53, 0xD3, 0x1A, 0x71, 0x63, 0x38, 0xF2, 0x0F, 0x99, 0xF2, 0x97, 0xC4, 0x63, 0xFB, - 0x81, 0xBB, 0x03, 0xD3, 0x7E, 0x3C, 0x64, 0x23, 0x43, 0xD7, 0xB9, 0x95, 0xFC, 0x16, 0x20, 0x68, - 0x79, 0x06, 0x2E, 0xF4, 0x50, 0x76, 0xC0, 0x94, 0xD6, 0xAE, 0xC7, 0xB8, 0xEA, 0xF1, 0xE4, 0x9B, - 0xF7, 0xB6, 0xAB, 0x03, 0xF6, 0xDD, 0xDB, 0xBE, 0x6F, 0x8F, 0x0F, 0x99, 0x67, 0x9B, 0x86, 0xCE, - 0xDA, 0xCE, 0x77, 0xF6, 0x8F, 0x9A, 0x82, 0xFF, 0x8B, 0x2D, 0xE5, 0xA7, 0xC9, 0x7C, 0x4D, 0xC3, - 0xF3, 0xD7, 0x7B, 0xB6, 0xF8, 0xCF, 0x51, 0x75, 0xDD, 0xB0, 0x86, 0x4D, 0x57, 0xCC, 0x69, 0x4F, - 0x71, 0xBE, 0xA7, 0x2F, 0x47, 0x74, 0x0B, 0x44, 0xE1, 0x31, 0x5F, 0xDF, 0x4E, 0x7F, 0x3E, 0x9A, - 0x5A, 0xA9, 0xF8, 0xEE, 0x90, 0x59, 0xB6, 0x35, 0x35, 0xC9, 0x31, 0x60, 0x8F, 0x61, 0x35, 0x4D, - 0x3E, 0x40, 0x40, 0x64, 0x8C, 0x79, 0x1F, 0xC0, 0x12, 0xAC, 0xC3, 0x01, 0x20, 0xAD, 0x37, 0xD5, - 0xB3, 0x1D, 0xF8, 0x40, 0xAC, 0x3C, 0x01, 0xC4, 0xF8, 0x6C, 0x0D, 0x0B, 0xBF, 0x3E, 0x77, 0x5D, - 0xDB, 0x9D, 0x6A, 0xA9, 0x1B, 0x9E, 0x63, 0xAA, 0x4F, 0x87, 0x4C, 0xBC, 0x92, 0x9C, 0x96, 0x66, - 0x9B, 0x36, 0xCC, 0xD7, 0xE5, 0x7A, 0xF2, 0xF9, 0x00, 0x98, 0x57, 0xD3, 0x33, 0xFE, 0x84, 0x01, - 0xBD, 0xB1, 0x6A, 0x9A, 0xDC, 0xCD, 0x1B, 0xB6, 0x1F, 0x68, 0x1A, 0xC2, 0xA3, 0xFA, 0xC0, 0x43, - 0x97, 0x4F, 0x6F, 0x7C, 0xDE, 0xD0, 0xD1, 0xF7, 0x8F, 0x12, 0xA5, 0xEE, 0x6D, 0x53, 0xCF, 0xDA, - 0xBE, 0xEF, 0x4D, 0x6A, 0x3F, 0x35, 0xAB, 0xEC, 0x8D, 0xC0, 0x7F, 0xC4, 0x9E, 0x0F, 0x59, 0x57, - 0xF9, 0xAF, 0xD9, 0xBD, 0x8A, 0x1E, 0x3A, 0x4A, 0x5E, 0xC7, 0x9D, 0x1C, 0xB4, 0x0A, 0x7B, 0xD8, - 0xCD, 0xED, 0x61, 0x37, 0xBB, 0x07, 0xD5, 0xF7, 0x81, 0xE9, 0x4E, 0x35, 0x76, 0xEC, 0x90, 0x5A, - 0xD4, 0x7B, 0x20, 0x81, 0xC0, 0x9F, 0x02, 0xF8, 0x9F, 0x4D, 0xC3, 0xD2, 0xF9, 0xF7, 0x43, 0xD6, - 0x56, 0x94, 0x29, 0x92, 0x90, 0xA4, 0xD0, 0x9E, 0x81, 0x06, 0x1C, 0x4A, 0x4D, 0x09, 0x91, 0x7D, - 0x25, 0xE5, 0x5B, 0x9A, 0xAE, 0x6F, 0x3B, 0x40, 0x46, 0xC9, 0xC9, 0x4A, 0xF6, 0x26, 0x18, 0xDA, - 0x87, 0x1D, 0x71, 0x74, 0xFF, 0xF4, 0xE1, 0xDE, 0xD6, 0x9F, 0x24, 0x8F, 0xD7, 0x8D, 0x07, 0xA6, - 0x21, 0xDF, 0xFC, 0xD8, 0xC0, 0x83, 0x52, 0x05, 0x04, 0x71, 0x1B, 0xCC, 0xD0, 0x3F, 0x36, 0xE4, - 0xF2, 0x2E, 0xE1, 0x71, 0x63, 0xC2, 0x0D, 0xA9, 0x81, 0x6A, 0x1A, 0x43, 0xEB, 0x63, 0x83, 0xE6, - 0xDB, 0x08, 0x9B, 0xCB, 0xF7, 0x63, 0xEF, 0xD2, 0xFB, 0xC6, 0x78, 0x38, 0xDD, 0xDD, 0x85, 0x61, - 0xF2, 0x1B, 0x38, 0xAD, 0x1B, 0x93, 0xA3, 0xE5, 0x44, 0x7C, 0x7B, 0x02, 0x92, 0xC6, 0xB7, 0x96, - 0x63, 0x0D, 0x1B, 0x30, 0x06, 0x1C, 0xD9, 0xF2, 0x31, 0x33, 0xF9, 0x03, 0x37, 0x1B, 0x47, 0xC0, - 0x9B, 0x1D, 0xD5, 0x8A, 0x77, 0xD7, 0xE3, 0xAE, 0x06, 0x67, 0x42, 0x23, 0x31, 0x26, 0xE1, 0xB5, - 0x98, 0x14, 0x61, 0x1E, 0x8C, 0x83, 0x10, 0xF8, 0xD8, 0x08, 0x29, 0x41, 0x12, 0x02, 0x1D, 0x5C, - 0xD0, 0x61, 0x6C, 0x75, 0x3B, 0xB0, 0x3C, 0x09, 0x19, 0xF1, 0x67, 0x1E, 0x94, 0xA6, 0x7A, 0x25, - 0x66, 0x13, 0xDF, 0x0D, 0x42, 0xBE, 0xC9, 0xDE, 0x89, 0xAD, 0x13, 0xC0, 0x75, 0x39, 0x88, 0x4C, - 0x97, 0x56, 0xCF, 0xB5, 0x91, 0x60, 0xE3, 0xF0, 0xBD, 0x3F, 0xBA, 0xC5, 0xEF, 0x7C, 0xE0, 0x8D, - 0x1F, 0x76, 0xEE, 0x8F, 0x3E, 0xDC, 0xBB, 0xF4, 0x1F, 0x4A, 0x3E, 0x42, 0x74, 0x61, 0x86, 0x07, - 0x7C, 0x02, 0xCF, 0x62, 0x78, 0xA5, 0xC5, 0x7A, 0x26, 0x72, 0x62, 0xF6, 0xA8, 0x1A, 0x7E, 0xAB, - 0xD5, 0x5A, 0xD5, 0xD4, 0x51, 0x8C, 0x33, 0xB9, 0xCF, 0x53, 0x66, 0xCE, 0xCE, 0xA0, 0xB3, 0x8C, - 0xA9, 0x8F, 0x54, 0x0F, 0x78, 0xF2, 0x23, 0xA3, 0x3E, 0x56, 0x31, 0xD9, 0x81, 0xE1, 0x8E, 0x1F, - 0xE1, 0xE8, 0xFF, 0xEA, 0x98, 0xB6, 0xAA, 0xA7, 0xCF, 0x7A, 0x7A, 0xBE, 0x17, 0xB2, 0x0D, 0x0B, - 0x1C, 0x5D, 0xF5, 0x39, 0xB0, 0x48, 0xD1, 0xAA, 0xC5, 0x92, 0x9B, 0x20, 0x16, 0x12, 0x6E, 0x44, - 0xC9, 0xC5, 0x1C, 0xFD, 0x94, 0x4A, 0x4A, 0x88, 0xC4, 0xB8, 0xD4, 0xE8, 0x7D, 0x10, 0x49, 0xC7, - 0xCD, 0x76, 0x07, 0x50, 0x14, 0x09, 0x28, 0xA2, 0x13, 0xD7, 0xFF, 0xD6, 0xF4, 0x50, 0x00, 0x8E, - 0x11, 0x49, 0x42, 0x3A, 0xFE, 0xD9, 0xB8, 0x30, 0x84, 0x88, 0x8C, 0xD8, 0x1D, 0x9B, 0x4D, 0x69, - 0x30, 0xC7, 0x00, 0xDB, 0xCE, 0x06, 0xEC, 0x18, 0x1A, 0xF5, 0xD4, 0x21, 0x2F, 0xB9, 0x20, 0xD7, - 0x7E, 0x9C, 0xD9, 0xC7, 0x7B, 0xD3, 0xD6, 0xBE, 0xFD, 0x25, 0xDE, 0x41, 0x41, 0x27, 0xE2, 0x18, - 0x41, 0xB6, 0x3C, 0xC5, 0x64, 0xF0, 0x1F, 0x2E, 0xFE, 0x1C, 0x24, 0x99, 0xA7, 0xC7, 0x11, 0x87, - 0xBD, 0x0B, 0x37, 0xF1, 0x30, 0xC6, 0x33, 0x00, 0x78, 0xE1, 0xE3, 0xBF, 0x71, 0xD7, 0x03, 0x26, - 0x9D, 0xCD, 0x19, 0x1E, 0x94, 0x96, 0x22, 0xB9, 0x03, 0xE2, 0xC4, 0xCC, 0x70, 0x93, 0x5E, 0x87, - 0x96, 0xE7, 0x95, 0xEE, 0xF6, 0xD3, 0x4D, 0xBF, 0x1F, 0x9B, 0x5B, 0x6C, 0x14, 0x56, 0x30, 0x8C, - 0xC0, 0xBB, 0x93, 0xBB, 0xCB, 0xB3, 0xEC, 0xDE, 0xCF, 0x04, 0x6E, 0x9E, 0x98, 0x01, 0xF7, 0x01, - 0x2D, 0x47, 0xEC, 0xF2, 0x0C, 0xCE, 0x56, 0xF8, 0x57, 0x72, 0x0C, 0xCD, 0x06, 0xB9, 0xC9, 0xB0, - 0x00, 0xE9, 0xBD, 0xAB, 0xAB, 0xCF, 0xD9, 0xE3, 0x5C, 0x5D, 0x8D, 0x0E, 0x67, 0xBA, 0x99, 0x82, - 0x0A, 0xB7, 0x75, 0x0E, 0x62, 0xF3, 0x95, 0xEA, 0x67, 0xF7, 0xB3, 0x0B, 0xCB, 0x7F, 0xAF, 0x74, - 0xDE, 0xEF, 0xBE, 0x7B, 0x2F, 0x67, 0xB8, 0x5D, 0xB6, 0xDB, 0x3C, 0x20, 0x37, 0xDB, 0xCA, 0x5E, - 0xAB, 0x7D, 0xB0, 0xA7, 0xEC, 0xBD, 0xDB, 0x6F, 0x57, 0xEC, 0xF8, 0xD8, 0xCC, 0x99, 0x6F, 0x7B, - 0x6F, 0x1F, 0x66, 0x7C, 0x10, 0x4E, 0x96, 0x6D, 0x1D, 0xF7, 0x4E, 0xDF, 0xCE, 0xC2, 0xB3, 0x14, - 0xDA, 0xC4, 0x60, 0x7D, 0x7E, 0x7A, 0x7E, 0x91, 0x3D, 0x28, 0x7E, 0x5B, 0x04, 0x6D, 0xAE, 0xF1, - 0xC1, 0x2F, 0x79, 0x00, 0xE9, 0x1C, 0x28, 0x1D, 0x65, 0xBF, 0xB5, 0xB7, 0x7F, 0x50, 0x12, 0x1E, - 0xD8, 0xE3, 0xAF, 0x39, 0x3D, 0xEE, 0xBE, 0x6B, 0xEF, 0x1F, 0x28, 0xBB, 0xAD, 0x5D, 0xA5, 0x5B, - 0xA1, 0xC7, 0xDF, 0xF2, 0x70, 0xE1, 0x60, 0x7F, 0x7F, 0x7F, 0xAF, 0xB5, 0x7B, 0xB0, 0x3B, 0x7D, - 0x2A, 0x17, 0x01, 0x36, 0xCE, 0xDB, 0x52, 0x3F, 0x8F, 0xDC, 0x90, 0x85, 0x8C, 0xFD, 0xA6, 0x32, - 0x2D, 0xCD, 0xCC, 0xF2, 0x3D, 0x3A, 0x50, 0x66, 0x18, 0xD3, 0x3F, 0x34, 0x9B, 0xAC, 0x19, 0xFE, - 0x63, 0x70, 0x74, 0x0F, 0x40, 0x8E, 0x61, 0xA7, 0xB6, 0x35, 0x30, 0x86, 0xB1, 0x2F, 0x9A, 0xCD, - 0xA3, 0x59, 0x86, 0x26, 0x87, 0xD7, 0x41, 0x2F, 0x03, 0xA5, 0x68, 0xA8, 0x3A, 0xCD, 0x4E, 0x0A, - 0x0F, 0xFB, 0x20, 0x14, 0x8F, 0x48, 0xA2, 0xF2, 0x2D, 0x06, 0xFF, 0x35, 0x1D, 0xD7, 0x80, 0xC9, - 0x3D, 0xB1, 0x89, 0xB2, 0x2C, 0x78, 0xB0, 0x23, 0xA6, 0x20, 0x66, 0xD0, 0x60, 0xFE, 0x93, 0x03, - 0xCB, 0x10, 0x5D, 0x34, 0x18, 0x1C, 0x5D, 0x6A, 0x53, 0xB4, 0xA0, 0xF3, 0xC4, 0x54, 0x1D, 0x8F, - 0x37, 0x52, 0xF7, 0x48, 0xBC, 0x4A, 0x6A, 0xF5, 0xC7, 0xC6, 0x3F, 0x86, 0xEF, 0xF6, 0x92, 0xBD, - 0xAB, 0xAE, 0xA1, 0x36, 0xF9, 0x77, 0xD8, 0x00, 0x9D, 0xE3, 0xC1, 0xAA, 0x9A, 0xD0, 0x9D, 0x78, - 0x8A, 0x67, 0x88, 0x6B, 0x9B, 0xDE, 0x64, 0x9C, 0x64, 0xDB, 0xA3, 0xD4, 0x51, 0x93, 0x00, 0x0C, - 0x5C, 0x95, 0x54, 0xFF, 0x0F, 0x46, 0x62, 0x69, 0xA8, 0xB5, 0x4F, 0x4E, 0x45, 0xD2, 0xE1, 0x51, - 0x9D, 0x67, 0xF7, 0x06, 0x9B, 0x52, 0xF3, 0xF1, 0xB8, 0x33, 0xD2, 0x70, 0x46, 0x00, 0x24, 0x15, - 0x63, 0xB2, 0xB6, 0x29, 0x5C, 0x06, 0x1B, 0xDF, 0xC3, 0x3E, 0x49, 0x72, 0x2D, 0xB7, 0x32, 0xC2, - 0x92, 0xD4, 0xBE, 0xBC, 0x11, 0xC8, 0x0B, 0x85, 0x1D, 0xCE, 0xA0, 0xCF, 0xCC, 0xDC, 0x54, 0x57, - 0x67, 0xF8, 0xA3, 0x89, 0x52, 0xFC, 0x34, 0x92, 0xA6, 0xB5, 0x18, 0xD8, 0xEE, 0x58, 0xDA, 0x03, - 0x00, 0xFD, 0x3B, 0x19, 0xDB, 0x11, 0xDB, 0x92, 0xC3, 0xCC, 0x17, 0x04, 0x35, 0xCB, 0x7E, 0x7D, - 0x5F, 0x62, 0xD9, 0xBD, 0xD7, 0x04, 0x5A, 0xD6, 0xF8, 0x98, 0xCC, 0x6C, 0x42, 0x2B, 0xC8, 0xEC, - 0x82, 0x6C, 0x0A, 0x68, 0xBB, 0x03, 0xC1, 0x85, 0x9B, 0x5C, 0xF3, 0x99, 0xCA, 0xE4, 0x6E, 0x33, - 0xC0, 0x2D, 0xD0, 0xE5, 0xB9, 0xC5, 0xA0, 0x7F, 0x10, 0x00, 0x98, 0x94, 0x83, 0x41, 0xC1, 0xB7, - 0xE1, 0xB9, 0xEA, 0x87, 0x2F, 0xB6, 0xD8, 0xB1, 0x2F, 0x64, 0xC8, 0xED, 0xB8, 0x4C, 0xF6, 0x68, - 0x80, 0x78, 0x10, 0x20, 0xA8, 0xA9, 0x63, 0xAE, 0x4F, 0xDE, 0x0F, 0x91, 0x4D, 0x1B, 0xA9, 0xD6, - 0x90, 0x7B, 0x0C, 0xC5, 0x3B, 0x4F, 0x7D, 0x80, 0x57, 0x1E, 0x69, 0x3C, 0x50, 0x92, 0x07, 0x03, - 0x8E, 0xE6, 0xA5, 0x68, 0x32, 0x20, 0xE1, 0x45, 0xFD, 0x80, 0x32, 0x4F, 0xEF, 0xBD, 0xE9, 0x43, - 0x9B, 0x24, 0xC6, 0xBE, 0xC1, 0x17, 0x1D, 0x98, 0x8C, 0xC7, 0xF5, 0x56, 0x0E, 0x6C, 0x67, 0xC0, - 0x47, 0xF8, 0x6B, 0x58, 0x03, 0xBB, 0xA9, 0x19, 0xAE, 0x06, 0x03, 0xFA, 0xFC, 0xBB, 0x1F, 0xD1, - 0xFA, 0xD8, 0xC3, 0x9D, 0xCA, 0xE2, 0x84, 0x53, 0x1C, 0x31, 0x1D, 0x05, 0xA6, 0xB8, 0x60, 0x09, - 0xF4, 0x40, 0x29, 0xED, 0xA8, 0x60, 0xF3, 0xD3, 0xF9, 0x77, 0x42, 0x67, 0x0E, 0xD9, 0x67, 0x2E, - 0x28, 0x0C, 0xCB, 0x09, 0x7C, 0xC9, 0xB3, 0x5C, 0x55, 0x37, 0xEC, 0x86, 0xB4, 0xE0, 0x4A, 0xF8, - 0xDF, 0x8A, 0x67, 0x0F, 0x2A, 0x08, 0x33, 0x1F, 0x1B, 0x4A, 0x51, 0x77, 0xA6, 0x7A, 0xCF, 0xCD, - 0x38, 0xEB, 0x50, 0x48, 0xC3, 0x3C, 0x92, 0x1B, 0x0F, 0x62, 0x00, 0xBD, 0xB1, 0x10, 0x28, 0x5F, - 0x04, 0x24, 0xDB, 0x95, 0x21, 0xD9, 0x16, 0x90, 0x6C, 0x77, 0xBA, 0xBB, 0x7B, 0xFB, 0xEF, 0x0E, - 0xDE, 0x2B, 0x93, 0xBF, 0x5E, 0xA1, 0x2A, 0xA1, 0xDA, 0xA9, 0x0C, 0xD5, 0x8E, 0x80, 0xEA, 0x2B, - 0x04, 0x25, 0x04, 0xBB, 0x95, 0x21, 0xD8, 0x7D, 0x85, 0x60, 0x02, 0x82, 0xBB, 0x95, 0x21, 0xB8, - 0xFB, 0x0A, 0xC1, 0x04, 0x04, 0xF7, 0x2A, 0x43, 0x70, 0xEF, 0x15, 0x82, 0x09, 0x08, 0xEE, 0x57, - 0x86, 0xE0, 0xFE, 0x2B, 0x04, 0x13, 0x10, 0x7C, 0x57, 0x19, 0x82, 0xEF, 0xEA, 0x83, 0x60, 0x8D, - 0x20, 0x14, 0xD3, 0x84, 0xF7, 0xA3, 0x79, 0x0A, 0x93, 0x7F, 0xA8, 0xDB, 0xC6, 0x2F, 0x70, 0xA4, - 0xB9, 0xB3, 0x4B, 0x7F, 0xEC, 0xD2, 0x4F, 0x1A, 0x88, 0xFA, 0x88, 0x64, 0xB8, 0x5C, 0xB0, 0x60, - 0xE7, 0x87, 0xC5, 0x20, 0x48, 0x2A, 0x66, 0x38, 0xE8, 0x01, 0x0D, 0xF7, 0xAE, 0xCA, 0x26, 0xA2, - 0xA0, 0xDE, 0x48, 0x40, 0x44, 0x6A, 0xC0, 0x09, 0xB5, 0x5C, 0xEC, 0x4A, 0x7E, 0xAF, 0xCE, 0x74, - 0x03, 0xBA, 0x38, 0x8C, 0xFA, 0x8E, 0x5D, 0x26, 0xE2, 0xFE, 0x3A, 0x79, 0x7B, 0x9B, 0x49, 0x01, - 0xB3, 0x03, 0x9D, 0x92, 0x12, 0x74, 0x0D, 0x2A, 0x0B, 0x1A, 0x70, 0x93, 0x83, 0xC9, 0x2B, 0xC4, - 0x9C, 0xE1, 0xEA, 0x47, 0x95, 0x59, 0x23, 0x8C, 0xBC, 0x43, 0xDE, 0x2B, 0x41, 0x5D, 0xD2, 0x64, - 0x92, 0x34, 0x7E, 0xD0, 0x0D, 0x91, 0x6F, 0xD1, 0x7D, 0x84, 0xC4, 0x9E, 0x46, 0x96, 0x55, 0x25, - 0x15, 0x13, 0xF3, 0xF5, 0x57, 0xBA, 0x08, 0xB6, 0x4E, 0xD1, 0x8B, 0x61, 0x66, 0x9C, 0xAD, 0xB7, - 0x0D, 0x79, 0x0F, 0x22, 0x1F, 0xA4, 0x5B, 0x20, 0x96, 0xA4, 0x59, 0xC7, 0xB4, 0x6B, 0x31, 0x89, - 0x69, 0x55, 0x18, 0x55, 0xE9, 0x81, 0xAA, 0xF9, 0x36, 0xAC, 0x5C, 0xE7, 0x03, 0x35, 0x30, 0x7D, - 0xAF, 0x48, 0x6D, 0x5D, 0x8A, 0xEA, 0x5A, 0xC4, 0x91, 0xCA, 0x63, 0xB5, 0x1B, 0x83, 0xFE, 0xB5, - 0x37, 0xAC, 0x0D, 0xA1, 0xD3, 0x8C, 0x44, 0x29, 0xAF, 0x4E, 0xD9, 0x05, 0xC9, 0xC2, 0xBF, 0x42, - 0xA3, 0xE0, 0xD8, 0x07, 0xBE, 0x19, 0xB7, 0x0C, 0xD6, 0x6C, 0x06, 0xC4, 0xF5, 0xCC, 0x65, 0x03, - 0x8C, 0x35, 0x4C, 0x87, 0x7B, 0x0C, 0x52, 0x53, 0xD6, 0x3F, 0xBC, 0x52, 0x79, 0x66, 0xD3, 0x5F, - 0xD2, 0x48, 0x97, 0xBB, 0x96, 0x6C, 0xEB, 0x1C, 0x73, 0xFC, 0x66, 0x3B, 0xD7, 0x44, 0x47, 0x57, - 0x69, 0x5C, 0xF5, 0x02, 0x97, 0x68, 0xFC, 0x56, 0xF5, 0xF9, 0x25, 0x9E, 0x34, 0x39, 0x14, 0x79, - 0x3D, 0x79, 0x9D, 0xE1, 0xFB, 0x87, 0xA5, 0x4E, 0xBB, 0x7C, 0x16, 0x9C, 0x71, 0x36, 0x76, 0x88, - 0x1F, 0xB6, 0x3B, 0x48, 0xD2, 0x5D, 0x36, 0x61, 0xE8, 0x65, 0xF8, 0x45, 0xEC, 0xFC, 0x9F, 0x5A, - 0xE0, 0xE7, 0x3F, 0x13, 0xF7, 0x9C, 0xF1, 0x93, 0xFE, 0xD2, 0x2A, 0xEC, 0x18, 0xFF, 0x7D, 0xFE, - 0xF3, 0xB0, 0xD4, 0x7B, 0x35, 0x32, 0xD5, 0x29, 0xE6, 0x7A, 0x37, 0xE2, 0xCC, 0x0A, 0xC6, 0xF7, - 0xDC, 0x65, 0xF6, 0x80, 0x91, 0x9F, 0x07, 0xE0, 0xAF, 0x87, 0x86, 0x42, 0xD3, 0xD6, 0x04, 0x32, - 0xFF, 0xE7, 0x7F, 0xFC, 0xEF, 0x81, 0xF1, 0x9D, 0x7B, 0xFF, 0xF9, 0x1F, 0xFF, 0x87, 0x39, 0xF0, - 0xA2, 0xC7, 0x01, 0x6D, 0xF5, 0x16, 0x3B, 0xB6, 0x9E, 0xFC, 0x91, 0x61, 0x0D, 0x99, 0x7A, 0x6F, - 0x3F, 0x70, 0xB6, 0xFB, 0xF9, 0x4F, 0x90, 0x29, 0x9F, 0x00, 0x6B, 0xD0, 0x74, 0x39, 0xB9, 0xBB, - 0x83, 0x97, 0x87, 0xDC, 0xA3, 0x9E, 0x80, 0xDE, 0x76, 0xA8, 0xE7, 0xE1, 0x10, 0xDB, 0x81, 0x44, - 0xAA, 0xB9, 0x1C, 0x96, 0xA6, 0x19, 0xDC, 0x6B, 0xB1, 0x1B, 0x1B, 0x90, 0x80, 0xE1, 0x8C, 0x62, - 0x80, 0x66, 0x2E, 0x5E, 0x5D, 0x1B, 0x1E, 0x79, 0x77, 0xB9, 0xE4, 0xD7, 0x85, 0xAC, 0xBF, 0x0D, - 0x83, 0x91, 0x25, 0xD3, 0xB0, 0xD8, 0x09, 0xFA, 0x0D, 0x8C, 0x6D, 0x9D, 0xB7, 0xD8, 0x99, 0x38, - 0x09, 0x0E, 0x71, 0x32, 0x2D, 0x76, 0x65, 0x8C, 0x0D, 0xDF, 0x3B, 0x64, 0x4A, 0x4B, 0x51, 0x94, - 0x76, 0xA7, 0x43, 0x0D, 0x15, 0xF8, 0xA6, 0xC4, 0xBE, 0x2F, 0xF5, 0xBC, 0x28, 0x7B, 0x6E, 0x4C, - 0xDE, 0x2B, 0x90, 0x07, 0x4B, 0x1C, 0x32, 0x19, 0xA4, 0x21, 0xA4, 0xD4, 0xBD, 0x79, 0x28, 0x23, - 0x2E, 0x4A, 0x0A, 0x1C, 0x4A, 0x15, 0x26, 0x63, 0x77, 0x05, 0xB3, 0x04, 0x54, 0x62, 0x18, 0x27, - 0xBD, 0xE9, 0xBC, 0x12, 0x66, 0x91, 0xE8, 0x17, 0x1B, 0x37, 0x71, 0x5D, 0x4F, 0x00, 0xC2, 0x6B, - 0x37, 0x5C, 0x8F, 0x02, 0x83, 0xF0, 0xF1, 0x91, 0xED, 0x7E, 0xD8, 0x81, 0x5F, 0x34, 0xDE, 0x7A, - 0xF0, 0xA4, 0x3E, 0xD7, 0x1A, 0x47, 0x7D, 0x22, 0x50, 0x8F, 0xDD, 0x73, 0xFF, 0x91, 0x03, 0x8D, - 0xC4, 0xDE, 0xF1, 0xD6, 0x8C, 0xE1, 0xE4, 0xCC, 0xB4, 0x05, 0xAC, 0x00, 0xE8, 0x5E, 0x60, 0x99, - 0x81, 0xCE, 0x91, 0xC0, 0x07, 0x2C, 0xE0, 0x02, 0x40, 0xED, 0xD0, 0xD4, 0x4F, 0xE3, 0x13, 0x78, - 0xF1, 0x02, 0xAF, 0x02, 0x03, 0x1A, 0x04, 0xA6, 0x60, 0x10, 0xBE, 0xFA, 0x8D, 0x78, 0x54, 0xE2, - 0x65, 0x8E, 0x0E, 0x16, 0x6C, 0xC0, 0x1F, 0xA3, 0x19, 0xA8, 0x9A, 0x6B, 0x7B, 0xF0, 0x0B, 0x98, - 0x13, 0xBC, 0x0D, 0x2F, 0x3E, 0xF0, 0x27, 0xB6, 0xD5, 0xD9, 0xFD, 0x6F, 0x6C, 0x64, 0x07, 0xAE, - 0xF7, 0xB6, 0x0E, 0xF6, 0x34, 0xE1, 0x47, 0x6D, 0x7C, 0xE9, 0xA0, 0xFD, 0x7E, 0x3F, 0x1C, 0x1F, - 0x58, 0x12, 0xC1, 0xBC, 0x34, 0x38, 0x63, 0xBE, 0x61, 0xAF, 0x5C, 0xA9, 0x56, 0xAE, 0x44, 0x24, - 0x34, 0x27, 0x5B, 0x82, 0xB6, 0x35, 0xF0, 0xA5, 0x39, 0xBE, 0x9E, 0x53, 0x99, 0x15, 0x1E, 0x39, - 0x4F, 0x96, 0x3A, 0x36, 0xB4, 0x6B, 0x40, 0x51, 0xF3, 0xCC, 0xB5, 0x1D, 0x21, 0x8A, 0x96, 0xB2, - 0x88, 0xC4, 0x9B, 0x36, 0x52, 0xF7, 0x70, 0x7F, 0xC6, 0x0A, 0x72, 0x26, 0xDA, 0x30, 0x6A, 0x74, - 0xB8, 0x62, 0x65, 0xF2, 0x58, 0xFF, 0x7B, 0xE0, 0xF9, 0x21, 0x33, 0xF1, 0xB9, 0x6B, 0xA9, 0x26, - 0x53, 0xCD, 0xA1, 0xED, 0x1A, 0xFE, 0x68, 0x8C, 0x54, 0x39, 0x56, 0x7D, 0x6D, 0x44, 0xDF, 0x83, - 0x82, 0x20, 0x54, 0x4E, 0xD5, 0x71, 0x40, 0x45, 0x16, 0xC2, 0x10, 0xB7, 0x1E, 0x0C, 0xD7, 0xB6, - 0x70, 0x6C, 0xC9, 0xA0, 0xE4, 0xE5, 0x2E, 0x33, 0xC6, 0xA0, 0x9A, 0x3E, 0x70, 0xD1, 0xB7, 0xCB, - 0x35, 0x6E, 0x00, 0x4B, 0x78, 0xE3, 0x89, 0x61, 0x1C, 0x90, 0xF1, 0x45, 0x07, 0xC0, 0xBA, 0xE2, - 0x5C, 0x4E, 0xDE, 0x15, 0x07, 0x78, 0xF7, 0x6A, 0x3F, 0x18, 0x3A, 0xDE, 0xE9, 0x02, 0xB7, 0x70, - 0x81, 0x97, 0x69, 0x5A, 0x40, 0xDC, 0x25, 0xF4, 0xC4, 0x45, 0x9F, 0x6D, 0xC0, 0xED, 0x16, 0xBA, - 0xC5, 0xD1, 0x88, 0xF1, 0x81, 0x70, 0xEA, 0x00, 0xAB, 0xC0, 0xF2, 0x02, 0xC3, 0xC7, 0x10, 0x0F, - 0x06, 0x30, 0xF2, 0x11, 0xEE, 0xC4, 0x7B, 0x68, 0xBF, 0xA8, 0xC1, 0x10, 0xDE, 0xB6, 0xB2, 0x96, - 0x84, 0x9C, 0xCC, 0x34, 0xBE, 0x71, 0x13, 0x9D, 0x34, 0xF0, 0x66, 0x1A, 0x84, 0x29, 0xE4, 0x61, - 0xC8, 0x16, 0x81, 0x3B, 0xC2, 0xDC, 0xA3, 0xF1, 0x40, 0x12, 0xC4, 0xDE, 0x41, 0x78, 0x13, 0x6C, - 0x37, 0x9A, 0xA5, 0x98, 0xB7, 0xF6, 0xB4, 0xBE, 0xCA, 0x78, 0x75, 0xE3, 0x9A, 0xC4, 0xE5, 0xC2, - 0x6B, 0x71, 0xE1, 0x08, 0x20, 0xAC, 0xA2, 0x49, 0xDA, 0x98, 0x26, 0xB4, 0x24, 0x53, 0xD2, 0x25, - 0xD9, 0x09, 0xAE, 0x54, 0xB8, 0x3E, 0x1A, 0x66, 0xE5, 0x7C, 0x62, 0x6C, 0x58, 0xE7, 0x26, 0x7F, - 0xC8, 0xD5, 0x85, 0xE7, 0x36, 0x9E, 0xCD, 0xC8, 0x35, 0x62, 0xB0, 0xB2, 0x4C, 0xE5, 0x1A, 0x90, - 0xB4, 0xFF, 0x37, 0x86, 0x4D, 0x08, 0xA9, 0x0F, 0x7F, 0x5A, 0xB1, 0x88, 0x23, 0xF9, 0x0B, 0xCC, - 0x03, 0xC3, 0xAE, 0x18, 0x0F, 0x27, 0x82, 0xD4, 0xA3, 0x73, 0x0C, 0x4B, 0xF0, 0x88, 0x04, 0x55, - 0x61, 0x2E, 0xF0, 0x80, 0xB0, 0x4D, 0xD3, 0xF0, 0xC9, 0x8E, 0x75, 0xCF, 0x51, 0x62, 0xD1, 0x05, - 0xA1, 0x81, 0xAA, 0x55, 0x56, 0x3F, 0x59, 0x9A, 0x6E, 0x52, 0x8E, 0xCC, 0xCA, 0x9C, 0xFE, 0xF3, - 0x92, 0x52, 0x95, 0xA3, 0x3C, 0x81, 0x9D, 0x15, 0x8E, 0x6E, 0xD1, 0x60, 0xF3, 0xCE, 0x6B, 0x98, - 0xF8, 0xE9, 0xCD, 0x97, 0x95, 0x91, 0x21, 0x8C, 0x55, 0x85, 0x0A, 0x4F, 0x77, 0x6E, 0x94, 0xE7, - 0xA6, 0xBE, 0x09, 0x75, 0xA1, 0xFB, 0x95, 0x6A, 0x8A, 0xB8, 0x8B, 0x54, 0x52, 0x9B, 0x98, 0x0C, - 0xF6, 0xF5, 0x13, 0x90, 0xDA, 0x91, 0x46, 0x7F, 0x3B, 0x3F, 0x6B, 0x5E, 0xBC, 0xEF, 0xD1, 0xB1, - 0xD6, 0x56, 0xA2, 0xC7, 0x5F, 0xAF, 0xDF, 0x1F, 0x28, 0xAF, 0xB4, 0x39, 0x1F, 0x6D, 0x22, 0x16, - 0x55, 0x21, 0x4D, 0x78, 0x7F, 0x63, 0x28, 0x13, 0x4D, 0xD7, 0xA1, 0x9D, 0xD5, 0xF2, 0x10, 0xF5, - 0x88, 0xF5, 0x9F, 0x8E, 0xB8, 0xF6, 0xED, 0xC4, 0xFE, 0xCE, 0xBD, 0x92, 0xD2, 0x34, 0x99, 0x8B, - 0xE3, 0x3D, 0x40, 0xC3, 0xE4, 0xE7, 0x12, 0x37, 0x83, 0xB5, 0x7A, 0x36, 0xDE, 0xC5, 0x25, 0x4C, - 0x90, 0x0D, 0x35, 0xD5, 0x21, 0xD9, 0x12, 0x04, 0x41, 0x58, 0xAA, 0x0C, 0x64, 0x05, 0x61, 0x51, - 0xBC, 0x83, 0x32, 0xA9, 0x20, 0x38, 0x38, 0xEB, 0x5C, 0x1B, 0x24, 0x4F, 0x20, 0x2C, 0xC3, 0x31, - 0xF9, 0x84, 0x20, 0x23, 0x45, 0x3B, 0xFA, 0x2A, 0x01, 0x32, 0x50, 0xFA, 0xFB, 0xF6, 0x98, 0xC7, - 0xC5, 0x53, 0x8F, 0xE9, 0x86, 0xE6, 0xA3, 0x1C, 0x8C, 0xD2, 0xAB, 0xC5, 0x81, 0x78, 0xD1, 0x8B, - 0x32, 0x70, 0x51, 0x94, 0x86, 0x69, 0x70, 0x17, 0xE3, 0x3E, 0x92, 0xDD, 0xD0, 0x7C, 0x1C, 0xFC, - 0x0B, 0xE9, 0x5B, 0x88, 0x4B, 0xC2, 0x08, 0x20, 0xA4, 0xDF, 0xE4, 0xCB, 0xE4, 0x6E, 0x29, 0xAC, - 0x96, 0xD3, 0x12, 0x35, 0x2C, 0x06, 0x45, 0x71, 0x7F, 0x64, 0x7B, 0x3C, 0x5A, 0x1A, 0xC8, 0xF2, - 0xD0, 0x49, 0x28, 0x81, 0x8F, 0xC5, 0x52, 0xEF, 0x39, 0x7E, 0x26, 0xDE, 0xA2, 0x07, 0x2E, 0xFE, - 0x1D, 0x09, 0xC4, 0x9A, 0x6A, 0x6A, 0x41, 0xB4, 0xBE, 0x88, 0xDF, 0x1C, 0xC3, 0xA8, 0xDC, 0x42, - 0x70, 0xAE, 0x97, 0xBF, 0x65, 0xC2, 0xA6, 0x9F, 0x80, 0xD4, 0x09, 0x37, 0xCE, 0xEC, 0x60, 0x8A, - 0xCE, 0x11, 0xC9, 0xC5, 0xE5, 0x4D, 0xFC, 0x02, 0xB2, 0xDC, 0x11, 0x33, 0xD3, 0x91, 0x3C, 0x48, - 0x04, 0x39, 0x24, 0xC6, 0xFE, 0x5D, 0x0E, 0x7E, 0x24, 0x7E, 0x97, 0xE3, 0x70, 0x82, 0x49, 0xCD, - 0x8E, 0x42, 0xCF, 0xC3, 0x1B, 0x26, 0x7A, 0x04, 0x73, 0x8F, 0x3C, 0x17, 0x52, 0x48, 0x39, 0x1A, - 0x7D, 0xEE, 0x2B, 0xBE, 0x54, 0x80, 0x7E, 0x52, 0x4D, 0xC3, 0xE4, 0xF6, 0x33, 0x41, 0x34, 0x1C, - 0xFD, 0x48, 0xFE, 0xB1, 0x6A, 0x98, 0x46, 0xE3, 0xD7, 0x0C, 0x54, 0xD3, 0xB6, 0x60, 0x72, 0xCF, - 0x05, 0xD4, 0xAB, 0x2F, 0x37, 0xC7, 0xFD, 0x3E, 0x00, 0x55, 0xFC, 0xB1, 0x72, 0xA0, 0x86, 0xE3, - 0xD7, 0x0C, 0x54, 0xE7, 0xD9, 0x00, 0xDA, 0x43, 0x60, 0xF6, 0x56, 0x0F, 0xC8, 0x5E, 0xED, 0x40, - 0xBC, 0x51, 0x1F, 0x0C, 0xED, 0x99, 0xC0, 0x08, 0x63, 0x5F, 0x9E, 0x36, 0x8E, 0x6E, 0x8E, 0xFF, - 0x76, 0x79, 0xBA, 0x6A, 0x50, 0xCA, 0xB1, 0xEB, 0x05, 0xE6, 0xBF, 0xFC, 0xF9, 0x6C, 0x34, 0xFE, - 0x2F, 0xBF, 0x21, 0x81, 0xE1, 0xCF, 0x55, 0x43, 0x52, 0x8C, 0x5C, 0x2F, 0x20, 0xFB, 0xF7, 0xEA, - 0x73, 0x01, 0xB2, 0x7F, 0x72, 0x0C, 0xCB, 0xC1, 0x9F, 0xAB, 0x06, 0xA4, 0x18, 0x79, 0x21, 0x40, - 0xCE, 0xA5, 0x5A, 0x3B, 0x13, 0xBF, 0x90, 0x84, 0xDC, 0xBB, 0x04, 0x7F, 0xB9, 0x42, 0x45, 0x86, - 0x66, 0x22, 0xCE, 0xE0, 0xCF, 0xAA, 0x27, 0x8D, 0xCA, 0x55, 0x0C, 0x0A, 0x13, 0x3C, 0xA9, 0x03, - 0x35, 0x84, 0x2C, 0xFC, 0x29, 0x9A, 0x50, 0xE3, 0xE8, 0x9C, 0x9E, 0x30, 0xF9, 0x88, 0x7D, 0x3E, - 0xEE, 0xEF, 0x9C, 0xEF, 0x17, 0xEA, 0x90, 0xA7, 0x36, 0x68, 0x25, 0x94, 0x7F, 0xC7, 0x5B, 0x3E, - 0x56, 0xCD, 0x4E, 0x7A, 0xC5, 0x17, 0x1A, 0x5F, 0x41, 0x31, 0xF9, 0x0C, 0x2D, 0xD8, 0xB1, 0x34, - 0xBB, 0xB3, 0x3E, 0x77, 0x29, 0x8A, 0x4C, 0x9B, 0xC0, 0x21, 0xBC, 0x5B, 0xD0, 0xE9, 0x9A, 0x92, - 0xB4, 0x9C, 0x10, 0xA8, 0x09, 0xB2, 0x88, 0x69, 0x27, 0xE7, 0xE5, 0x34, 0x93, 0x75, 0x74, 0xA9, - 0xAB, 0xA4, 0xC1, 0x97, 0xC2, 0xE1, 0x0A, 0xF8, 0x7B, 0xE3, 0xBB, 0x86, 0x73, 0x6A, 0x1A, 0x98, - 0xCC, 0x23, 0x44, 0xE0, 0x9B, 0xBB, 0xDB, 0xCB, 0x1E, 0x13, 0x0F, 0x8B, 0x15, 0xF8, 0xC5, 0xD1, - 0x31, 0x31, 0x87, 0x15, 0x59, 0x0A, 0xBE, 0x92, 0xF6, 0x6C, 0x78, 0x72, 0xB1, 0x1A, 0x8D, 0x8E, - 0x2A, 0x34, 0x5E, 0x6B, 0x60, 0xCE, 0x8A, 0x18, 0x3E, 0xD2, 0x48, 0x42, 0x6D, 0x56, 0x41, 0x3B, - 0xF6, 0x48, 0x95, 0xF6, 0x04, 0xDA, 0xB6, 0xD8, 0xAF, 0x76, 0xE0, 0x86, 0x91, 0x90, 0xE3, 0xC0, - 0xF3, 0xD1, 0x66, 0xF7, 0x68, 0xA0, 0xA7, 0x91, 0x48, 0x0A, 0xE1, 0xA2, 0xD3, 0x2F, 0x53, 0x7D, - 0x86, 0x5E, 0x19, 0xBE, 0x31, 0xE6, 0x71, 0xA5, 0xFA, 0xCC, 0xF0, 0xD6, 0x4F, 0xA3, 0x2E, 0xC5, - 0x89, 0xAD, 0xC9, 0xA6, 0x85, 0x6E, 0x8A, 0xA9, 0x51, 0xBC, 0x4B, 0x36, 0xF8, 0xC6, 0xA7, 0x01, - 0x3B, 0xC3, 0xDD, 0xCF, 0xB6, 0xE7, 0x97, 0xF0, 0x76, 0xDF, 0x9B, 0x31, 0x06, 0x8B, 0xE6, 0x85, - 0xDC, 0x03, 0xFB, 0x3F, 0x9C, 0xD7, 0x60, 0x79, 0x30, 0x9F, 0xC1, 0xB2, 0xC0, 0xF1, 0x3D, 0x1D, - 0x06, 0xA5, 0xAD, 0x97, 0xA9, 0xCD, 0x97, 0x6F, 0xCC, 0x5C, 0x31, 0x5E, 0xF4, 0x30, 0x39, 0xE1, - 0x12, 0xF1, 0x02, 0xFB, 0x5F, 0x35, 0x5E, 0x14, 0x1A, 0xB2, 0xD3, 0xA1, 0x30, 0x3F, 0x66, 0x60, - 0xF3, 0x17, 0x87, 0x19, 0x70, 0x14, 0xB8, 0xCB, 0xC4, 0x0C, 0xEC, 0x7F, 0xDD, 0x39, 0x06, 0xC1, - 0x60, 0x7E, 0xBC, 0xC0, 0xE6, 0x2F, 0x12, 0x2F, 0x7A, 0x3F, 0x17, 0x4B, 0xB6, 0x39, 0x98, 0x93, - 0x75, 0xF1, 0x58, 0x01, 0x73, 0x58, 0xEF, 0xE7, 0xB9, 0x91, 0xE7, 0x9D, 0x40, 0xDC, 0x55, 0x20, - 0x0F, 0x00, 0x6A, 0x31, 0xF4, 0xE9, 0xFD, 0xFC, 0x82, 0x10, 0xE8, 0xDA, 0x0E, 0x2C, 0xBF, 0x67, - 0x1B, 0xD6, 0x7C, 0x47, 0x0E, 0x35, 0x2F, 0x71, 0xE2, 0x40, 0xFF, 0xEB, 0xCB, 0x58, 0x62, 0x30, - 0x98, 0x07, 0x33, 0x26, 0xCD, 0x5F, 0x24, 0x5E, 0x2C, 0x89, 0xB1, 0x54, 0xC0, 0x9C, 0xE2, 0xB7, - 0xD6, 0x98, 0xF1, 0x24, 0x00, 0xB9, 0x18, 0x7A, 0xAD, 0x17, 0xE3, 0x89, 0xF4, 0xFB, 0x76, 0xED, - 0xB6, 0xCC, 0xD8, 0xEA, 0xEF, 0x30, 0xB9, 0xF0, 0xD8, 0xF0, 0x3F, 0x7D, 0x3A, 0x6E, 0x1C, 0x85, - 0x1F, 0x18, 0x7C, 0x42, 0x0D, 0x58, 0xF0, 0xE4, 0xE5, 0xDB, 0xA2, 0x32, 0xE6, 0x53, 0xB8, 0x99, - 0x81, 0x45, 0x1D, 0x72, 0x7D, 0xD5, 0xB6, 0x2B, 0xBA, 0xEA, 0xD7, 0x08, 0x3A, 0x98, 0x0A, 0xF4, - 0x8F, 0xC0, 0x40, 0xB7, 0x57, 0xF8, 0x6B, 0x18, 0x98, 0xAA, 0x3B, 0xB9, 0x40, 0x97, 0xF9, 0x2B, - 0xC9, 0x60, 0x40, 0x37, 0xF4, 0x64, 0xC5, 0xDA, 0x42, 0xF0, 0x8E, 0x45, 0xF0, 0xEF, 0x5B, 0xE6, - 0xC9, 0xCC, 0x4A, 0xF8, 0xBD, 0xE8, 0x12, 0x7E, 0x59, 0x4C, 0x0D, 0x7C, 0x7B, 0x8C, 0x69, 0xAF, - 0x55, 0xD3, 0x7C, 0x92, 0x41, 0xA4, 0xD2, 0x91, 0x40, 0x75, 0xB9, 0xE7, 0x33, 0xF5, 0x41, 0x35, - 0x28, 0x25, 0xFA, 0xB4, 0x7D, 0x22, 0xC5, 0xA8, 0xF0, 0x12, 0x6D, 0x61, 0xC2, 0x89, 0x9D, 0x80, - 0x88, 0x0E, 0xEC, 0x27, 0x22, 0xDC, 0x32, 0x67, 0x2C, 0x19, 0xC5, 0x19, 0x85, 0x0D, 0x0F, 0xB9, - 0x2F, 0x23, 0xB0, 0xAF, 0x0C, 0xCF, 0xDF, 0x7A, 0x3B, 0x13, 0x9F, 0x3C, 0xD6, 0xE9, 0x97, 0x4C, - 0x38, 0x9D, 0x19, 0xEF, 0x99, 0x6F, 0x64, 0x2A, 0x11, 0x0B, 0x5A, 0x18, 0xF7, 0x89, 0x31, 0xB5, - 0xB9, 0xA3, 0xCC, 0x19, 0x16, 0x8A, 0xFD, 0xE6, 0x6F, 0xA0, 0x04, 0x10, 0x85, 0x39, 0x7A, 0xF1, - 0xE0, 0x50, 0x68, 0xBA, 0x78, 0x7C, 0xE8, 0x64, 0xAF, 0x8B, 0x02, 0xB4, 0xCB, 0x93, 0xF0, 0x34, - 0x5E, 0x5C, 0x02, 0x16, 0xDF, 0xE1, 0x69, 0x52, 0xC6, 0x16, 0x78, 0x73, 0x7D, 0x7E, 0x4C, 0xCE, - 0x73, 0xB7, 0xC7, 0x3F, 0xFF, 0x42, 0x29, 0xCA, 0x90, 0xE2, 0xFC, 0x47, 0x9B, 0x8D, 0x6D, 0x20, - 0x39, 0xCD, 0x1E, 0x8F, 0x6D, 0x8B, 0xBC, 0x86, 0xB0, 0xC2, 0x01, 0x3A, 0xF4, 0xC0, 0xF6, 0x7A, - 0xC2, 0x33, 0x5E, 0x00, 0xEA, 0x3E, 0xF0, 0x93, 0xBE, 0x38, 0x5E, 0xE0, 0xE0, 0xBB, 0x9E, 0x70, - 0x8D, 0x07, 0x4A, 0xB7, 0xD8, 0x3B, 0x25, 0x96, 0xEC, 0x4C, 0x36, 0xF4, 0x5A, 0xEC, 0x5C, 0xD5, - 0x46, 0x51, 0x3F, 0x22, 0x3A, 0x47, 0xF0, 0x54, 0xB9, 0x83, 0xEC, 0x71, 0x64, 0x4C, 0xDE, 0x10, - 0x19, 0xD4, 0x74, 0x49, 0xE0, 0x6C, 0x4B, 0x79, 0x4B, 0x13, 0xC7, 0x14, 0x77, 0xF6, 0xC0, 0xC7, - 0x60, 0x1E, 0x8A, 0xF7, 0x11, 0xBD, 0x51, 0xC2, 0x62, 0x39, 0xE5, 0xAD, 0x36, 0xFB, 0x08, 0x44, - 0x30, 0xF9, 0x32, 0xFA, 0x06, 0x43, 0x24, 0xDB, 0xE8, 0x5B, 0xB8, 0xCD, 0xF6, 0xE4, 0x3B, 0xE2, - 0x3B, 0x19, 0x75, 0xB4, 0xC7, 0x28, 0x9A, 0xF2, 0x6D, 0x8C, 0xC1, 0x10, 0xC0, 0x80, 0x9D, 0x6D, - 0xB3, 0x4F, 0x7D, 0xFA, 0x71, 0x87, 0x3F, 0xFE, 0xB6, 0x2D, 0x80, 0x78, 0x7D, 0x1A, 0x0B, 0x65, - 0xC4, 0x03, 0xA5, 0xA3, 0x6C, 0x64, 0x82, 0xB6, 0xA2, 0x90, 0xE4, 0x7C, 0x3A, 0xCA, 0xC9, 0x1D, - 0x98, 0x92, 0xF9, 0x72, 0x2F, 0x25, 0xF1, 0x65, 0x6A, 0x8F, 0xF3, 0xE6, 0x6B, 0x88, 0xF3, 0xC2, - 0xD9, 0x9C, 0x0D, 0xD6, 0x98, 0xAB, 0x72, 0x77, 0xBD, 0xAC, 0x84, 0x0D, 0xE5, 0x3C, 0x5B, 0x23, - 0x3E, 0x4B, 0xD9, 0x01, 0xEE, 0xEC, 0x3E, 0x45, 0xA6, 0x19, 0xD6, 0x30, 0xEC, 0x7E, 0x92, 0xA7, - 0x01, 0x30, 0x23, 0xFA, 0x36, 0xC4, 0x2D, 0xAF, 0x64, 0xD6, 0x86, 0x92, 0x51, 0x5A, 0xCB, 0x81, - 0x96, 0x8C, 0x07, 0x5E, 0x0E, 0xC0, 0xAE, 0x92, 0x9D, 0x27, 0xC0, 0x25, 0xBF, 0x5B, 0x02, 0xB0, - 0xD2, 0x72, 0xE6, 0xA6, 0x9F, 0xBD, 0xB6, 0xA7, 0x1A, 0x1A, 0x32, 0x80, 0xBE, 0xEF, 0x72, 0x75, - 0x1C, 0x06, 0x60, 0x79, 0x65, 0x20, 0x9A, 0xD5, 0x49, 0xBB, 0x44, 0x18, 0x57, 0x96, 0x76, 0xE5, - 0x51, 0x0F, 0x97, 0x18, 0xB4, 0x04, 0xD2, 0x25, 0xF6, 0xF9, 0x3B, 0x48, 0xCB, 0xC4, 0xA1, 0x64, - 0xE7, 0x22, 0xA2, 0x09, 0xBE, 0x3C, 0x2C, 0xE7, 0x68, 0x3C, 0x61, 0x4A, 0xF1, 0xF0, 0x98, 0xD4, - 0x71, 0x68, 0x35, 0xA9, 0xDF, 0x94, 0x0E, 0x8C, 0x9C, 0x37, 0xAC, 0x26, 0x31, 0x53, 0x9B, 0x9C, - 0x47, 0x63, 0x49, 0x1B, 0xDB, 0xCA, 0x18, 0xB0, 0x43, 0x3C, 0x9E, 0xBB, 0x9F, 0x76, 0xE3, 0xA8, - 0x53, 0x47, 0x3F, 0x1D, 0xCC, 0x32, 0x5C, 0x43, 0x3F, 0xDD, 0xC6, 0xD1, 0x5E, 0x1D, 0xFD, 0xEC, - 0x22, 0x7C, 0xEA, 0xE8, 0x68, 0x0F, 0x01, 0x54, 0x47, 0x47, 0xFB, 0xB8, 0xB2, 0x3A, 0x3A, 0x7A, - 0x07, 0x4B, 0x5B, 0xBC, 0x97, 0x03, 0x58, 0xD7, 0xE2, 0xBD, 0xBC, 0x87, 0x45, 0xD5, 0x80, 0x84, - 0x84, 0xCD, 0x35, 0xF4, 0xD3, 0xC6, 0x3C, 0xE2, 0x35, 0xF4, 0x03, 0xD8, 0xDC, 0xAD, 0x63, 0x3E, - 0x80, 0xCD, 0xFB, 0x75, 0xF4, 0x03, 0xD8, 0xDC, 0x19, 0x1B, 0xD6, 0xE2, 0x1D, 0x01, 0x36, 0xEF, - 0xD5, 0xD2, 0xD1, 0x3E, 0xF1, 0x9F, 0x3A, 0x7A, 0x42, 0x74, 0xAE, 0x67, 0x4E, 0x07, 0xB8, 0x6B, - 0xB5, 0xF4, 0xF4, 0x1E, 0xF7, 0xAD, 0x72, 0x4F, 0xC5, 0x51, 0x90, 0x4B, 0xB2, 0x5D, 0x4C, 0xDB, - 0x30, 0x26, 0x26, 0x85, 0xF0, 0x58, 0xA4, 0x60, 0xA1, 0xF8, 0x81, 0xB9, 0x69, 0xE9, 0x46, 0x4A, - 0x49, 0x30, 0x25, 0x25, 0xA1, 0x5C, 0x39, 0xA5, 0x53, 0xAF, 0x9C, 0xD2, 0x4E, 0xC8, 0x29, 0x9D, - 0xA5, 0xC9, 0x29, 0xED, 0x4C, 0x39, 0xA5, 0xFD, 0x2A, 0xA7, 0xBC, 0xCA, 0x29, 0xAF, 0x72, 0xCA, - 0xAB, 0x9C, 0xF2, 0x2A, 0xA7, 0xBC, 0xCA, 0x29, 0x9B, 0x26, 0xA7, 0x74, 0x36, 0x2F, 0x2D, 0x5A, - 0xB1, 0x21, 0xA6, 0xA4, 0x61, 0x2B, 0x66, 0xEE, 0xC6, 0x6B, 0x0C, 0x34, 0x1D, 0x2E, 0x37, 0xBE, - 0xB8, 0xC4, 0xE3, 0xD0, 0xAE, 0x9A, 0x97, 0xA5, 0x93, 0x92, 0x4B, 0x3D, 0x67, 0x96, 0x4E, 0x51, - 0xC3, 0xD0, 0x5B, 0x56, 0xF1, 0x9E, 0x93, 0x58, 0xD7, 0x95, 0xAE, 0x67, 0x62, 0x0D, 0x33, 0xF6, - 0x01, 0x01, 0x99, 0x52, 0x91, 0x2F, 0xA3, 0x74, 0x0D, 0xFE, 0x8B, 0x01, 0x7B, 0x2A, 0xD1, 0x27, - 0x41, 0x60, 0x9D, 0x12, 0x7D, 0xE6, 0x2E, 0x7F, 0xCE, 0x32, 0x3C, 0x24, 0xF3, 0x92, 0x81, 0xF9, - 0xD2, 0x12, 0xB9, 0xBE, 0x0B, 0xBD, 0xD8, 0x13, 0xC9, 0xC2, 0x43, 0x40, 0xDD, 0xC1, 0xC3, 0xBE, - 0xEC, 0x27, 0x4C, 0x21, 0x1E, 0x3E, 0x4F, 0x7A, 0x2B, 0xC8, 0x86, 0x85, 0xD7, 0xD3, 0x71, 0xBD, - 0x60, 0x66, 0x84, 0x23, 0xF1, 0x57, 0xF3, 0xD2, 0x5A, 0x71, 0xF0, 0xFC, 0xA5, 0x48, 0x52, 0xE7, - 0xB8, 0x5C, 0x33, 0x00, 0x71, 0xA2, 0x7C, 0x9A, 0xF6, 0x80, 0xA9, 0x0C, 0xA7, 0xC9, 0x3C, 0x99, - 0x13, 0x8A, 0x8A, 0x30, 0xFA, 0xEC, 0x9B, 0x45, 0x65, 0x9E, 0x7D, 0x4A, 0xA3, 0x79, 0xCF, 0x99, - 0x7D, 0x4F, 0x25, 0x0D, 0x75, 0x76, 0xFF, 0x84, 0x49, 0x38, 0xBD, 0xD0, 0xB8, 0x8F, 0x89, 0x38, - 0xB1, 0xE7, 0xB0, 0xC7, 0x16, 0x65, 0xA5, 0xA3, 0x1E, 0xA1, 0x27, 0xBC, 0x5D, 0xA2, 0x04, 0x17, - 0x78, 0xF3, 0x44, 0x13, 0x17, 0x39, 0xA6, 0xD4, 0x6F, 0x78, 0xDB, 0xE5, 0x38, 0xAE, 0xFD, 0x1D, - 0x68, 0xD9, 0xC7, 0x1C, 0x4F, 0xFB, 0x4A, 0x94, 0xFF, 0xEE, 0xD1, 0x76, 0xFD, 0x91, 0x48, 0xF0, - 0xA4, 0xEA, 0x61, 0xAD, 0x22, 0x31, 0x01, 0x9C, 0x2D, 0x5E, 0x95, 0x0F, 0x60, 0x66, 0xD1, 0x22, - 0x70, 0x34, 0x9D, 0xD9, 0xD6, 0x74, 0x1E, 0xBE, 0x30, 0x6D, 0xDF, 0x98, 0xFB, 0x23, 0x5B, 0x67, - 0xAA, 0x36, 0x32, 0x38, 0x26, 0xC5, 0xFA, 0xF7, 0xAE, 0xA2, 0x8D, 0x53, 0x72, 0x5A, 0xE1, 0x4D, - 0x1F, 0x5E, 0xD4, 0x3F, 0x00, 0x77, 0x69, 0xB1, 0x4B, 0x4B, 0x83, 0xF1, 0xBD, 0x30, 0xB9, 0x55, - 0x98, 0xCF, 0xE3, 0xCB, 0x3D, 0x46, 0x07, 0x88, 0x81, 0xEF, 0x8C, 0x31, 0x0F, 0x13, 0x89, 0xDE, - 0x0A, 0x9F, 0x01, 0x1D, 0x73, 0xC9, 0x5A, 0x0C, 0xAB, 0x06, 0xC6, 0x22, 0xFA, 0x0D, 0xD1, 0x17, - 0x8F, 0x12, 0x52, 0xD1, 0x58, 0x74, 0xF1, 0x88, 0xB9, 0xB2, 0x60, 0x0A, 0x06, 0xE6, 0xF0, 0x3A, - 0xE1, 0x58, 0x80, 0x75, 0xF2, 0x92, 0xE1, 0x85, 0x93, 0xD6, 0x29, 0xEC, 0x80, 0x12, 0x02, 0x36, - 0xE1, 0x95, 0x71, 0x94, 0xB7, 0x54, 0xA6, 0xBB, 0xA2, 0x12, 0x4B, 0x98, 0x93, 0x99, 0xEA, 0x97, - 0x4E, 0xF2, 0x88, 0x28, 0x22, 0xA9, 0xD7, 0x5E, 0x4B, 0x19, 0x4F, 0x2E, 0xEE, 0xF6, 0xE9, 0xE6, - 0x6E, 0x5F, 0x51, 0xBC, 0x6D, 0xD6, 0x6E, 0xD1, 0x07, 0x7A, 0x61, 0xE3, 0xE2, 0x14, 0x42, 0x0E, - 0x20, 0xE3, 0xC5, 0xBC, 0x46, 0x89, 0x78, 0xC3, 0xB0, 0xCD, 0x9C, 0x81, 0x0D, 0x0B, 0x79, 0x8E, - 0x4D, 0xF3, 0x07, 0x7B, 0x82, 0x4B, 0x32, 0x4F, 0x66, 0xAE, 0x4B, 0x61, 0xBB, 0x93, 0x96, 0xE5, - 0x06, 0xB1, 0xB2, 0xDC, 0x6D, 0x54, 0x0C, 0x73, 0x31, 0x56, 0x85, 0x6D, 0x79, 0x6F, 0x0F, 0x4B, - 0x5B, 0x23, 0x8A, 0x32, 0x23, 0x56, 0x30, 0x17, 0x54, 0xF3, 0x73, 0x4F, 0x01, 0x52, 0xC9, 0x61, - 0x9C, 0x8C, 0xF6, 0x8B, 0xF8, 0x84, 0x55, 0x93, 0xF5, 0x56, 0x8E, 0x46, 0x3D, 0xC9, 0xCB, 0xC2, - 0x08, 0xBC, 0x72, 0xB2, 0x79, 0x35, 0x9C, 0x0B, 0x39, 0x5D, 0xA9, 0xAE, 0x89, 0x1B, 0x76, 0xCF, - 0x40, 0xAC, 0x07, 0x3E, 0x84, 0xE7, 0x7B, 0xC4, 0x19, 0x4B, 0x35, 0xDF, 0x1A, 0x2F, 0x8A, 0xA2, - 0x84, 0x9C, 0x12, 0x4F, 0xEF, 0x0B, 0xA3, 0x43, 0x17, 0x46, 0xD1, 0x99, 0x0D, 0x98, 0x17, 0x57, - 0xA7, 0x3B, 0x5A, 0x1D, 0xD2, 0x2E, 0xCB, 0xB5, 0x8B, 0x84, 0x81, 0x45, 0x85, 0xB5, 0x0B, 0xEC, - 0x64, 0x56, 0x52, 0x8B, 0xAC, 0x85, 0x29, 0x32, 0x5B, 0x35, 0x59, 0x4D, 0x0C, 0x70, 0x44, 0xBF, - 0x12, 0x27, 0x9E, 0x28, 0x7B, 0x7E, 0xC4, 0xB6, 0x4E, 0x47, 0x36, 0xA6, 0xE0, 0xC1, 0x1A, 0xB2, - 0xCC, 0x2E, 0x76, 0xF4, 0xFF, 0x24, 0xAB, 0xE0, 0xBE, 0x0D, 0x4B, 0xAD, 0x3E, 0x8B, 0xE4, 0x17, - 0x97, 0xF8, 0xFC, 0x98, 0x84, 0x16, 0xC9, 0x79, 0x28, 0xF8, 0x80, 0x9C, 0x47, 0xD5, 0xA1, 0x85, - 0xCC, 0xC6, 0x41, 0xE2, 0x00, 0x69, 0x44, 0xAE, 0x33, 0x5A, 0x07, 0x8B, 0x55, 0xD9, 0x45, 0x29, - 0x49, 0x84, 0x5A, 0x62, 0x62, 0xCF, 0xA4, 0x9B, 0x94, 0x10, 0x7C, 0xC6, 0x63, 0xAE, 0x1B, 0x42, - 0xC2, 0xBB, 0xE7, 0x43, 0x23, 0x4C, 0x1C, 0x4A, 0x61, 0x96, 0xB7, 0x77, 0xA7, 0xD7, 0xB3, 0xAE, - 0x8E, 0xC7, 0x52, 0x6A, 0x8C, 0xC4, 0x32, 0xC3, 0x13, 0x32, 0x5F, 0x24, 0x82, 0x92, 0x28, 0xD4, - 0xEB, 0xF5, 0xD8, 0x96, 0x23, 0x0A, 0xB5, 0x7B, 0x1C, 0x04, 0xD4, 0xC0, 0x65, 0x7E, 0xE0, 0xDB, - 0xA0, 0x82, 0x99, 0x6F, 0xA9, 0xB8, 0x24, 0xBE, 0x35, 0x25, 0x1A, 0x31, 0x75, 0x08, 0x5D, 0xA0, - 0xAB, 0x25, 0xCC, 0x93, 0xDC, 0xB5, 0xB4, 0x48, 0xF2, 0x8D, 0x89, 0x4D, 0x61, 0xF5, 0xEF, 0x37, - 0xDE, 0x04, 0x6E, 0x98, 0x3D, 0xD9, 0x0E, 0x4C, 0x9D, 0xBB, 0xDB, 0xA0, 0x77, 0x99, 0x36, 0xE0, - 0x96, 0xBD, 0x79, 0x12, 0x13, 0x81, 0xB6, 0x86, 0x98, 0xCE, 0x32, 0x81, 0xF6, 0x19, 0x94, 0x4C, - 0x53, 0x10, 0x3A, 0x61, 0x88, 0x47, 0x48, 0x77, 0xA2, 0x60, 0xB3, 0x2C, 0xE2, 0x24, 0xB7, 0x3E, - 0x41, 0xDB, 0x4A, 0x69, 0xA7, 0xFA, 0x09, 0xED, 0xCF, 0xE1, 0x67, 0x4D, 0xCC, 0x20, 0x6F, 0x8E, - 0x54, 0x3C, 0x9A, 0x4D, 0xBE, 0x88, 0x22, 0xFB, 0x73, 0xAF, 0xA9, 0x4A, 0x39, 0x8B, 0x87, 0x25, - 0x9D, 0x0B, 0x36, 0x68, 0x89, 0x52, 0x45, 0xAC, 0xF1, 0x04, 0x74, 0xBB, 0x91, 0x34, 0x20, 0x02, - 0x4B, 0x0E, 0x66, 0x44, 0x82, 0x92, 0xD7, 0x78, 0x59, 0x4E, 0x57, 0x81, 0x47, 0xA0, 0x8D, 0xC1, - 0xB4, 0x54, 0x65, 0xA1, 0xF2, 0x86, 0xC7, 0xC8, 0x11, 0x6B, 0x76, 0x24, 0x74, 0xC2, 0xBA, 0xC2, - 0x98, 0x70, 0xDA, 0xD6, 0x0B, 0xF4, 0xEB, 0x46, 0x37, 0xC0, 0x72, 0xEE, 0x57, 0xCB, 0xB7, 0x95, - 0xF6, 0x02, 0x99, 0x21, 0x5A, 0x26, 0xB8, 0x13, 0xD3, 0x8C, 0xB1, 0x60, 0x34, 0xA1, 0xDA, 0xF4, - 0x86, 0x60, 0x9B, 0xBF, 0xEC, 0xFC, 0xBA, 0xF3, 0x1B, 0x82, 0x89, 0x7B, 0xAD, 0x97, 0x6B, 0x44, - 0x5D, 0x0D, 0x09, 0x24, 0xCA, 0x23, 0x74, 0xE7, 0xB8, 0x18, 0xA6, 0x2D, 0x39, 0x17, 0x85, 0xE4, - 0xB3, 0xC8, 0x2A, 0x4E, 0x47, 0xBF, 0x54, 0x10, 0x76, 0x2B, 0xDC, 0x77, 0xA7, 0xA9, 0x6D, 0x07, - 0x4B, 0x91, 0x84, 0x63, 0x0B, 0xAE, 0x24, 0xF8, 0x4E, 0xDA, 0xBD, 0x08, 0xE5, 0x6C, 0x29, 0x38, - 0xF4, 0x6B, 0x39, 0x1C, 0xFA, 0xF5, 0xC5, 0xE0, 0xD0, 0xAF, 0x73, 0xE2, 0xD0, 0xAF, 0xAF, 0x38, - 0x94, 0x85, 0x43, 0xBF, 0x95, 0xC3, 0xA1, 0xDF, 0x5E, 0x0C, 0x0E, 0xFD, 0x36, 0x27, 0x0E, 0xFD, - 0xF6, 0x8A, 0x43, 0x53, 0x38, 0x64, 0x81, 0x00, 0x85, 0xE2, 0xB9, 0x10, 0xD4, 0xCB, 0x60, 0x51, - 0xB9, 0xFA, 0xA1, 0xCF, 0x8A, 0x48, 0x45, 0x51, 0xA9, 0xF1, 0x35, 0x57, 0x42, 0xA4, 0x78, 0xCB, - 0x97, 0x63, 0x6F, 0x3C, 0x3A, 0x0D, 0xE3, 0xA5, 0xBE, 0xE2, 0x95, 0x4B, 0x4C, 0x8C, 0x7E, 0xF6, - 0x52, 0x4E, 0x54, 0x2D, 0x04, 0xAD, 0x04, 0x83, 0x84, 0x74, 0x2C, 0xCD, 0x1A, 0x94, 0x0C, 0x19, - 0xE4, 0xE4, 0x3F, 0x02, 0xD8, 0x17, 0x98, 0xBE, 0x66, 0x3B, 0x4F, 0x3B, 0x0E, 0xC6, 0x66, 0x4A, - 0x0B, 0xC8, 0x8C, 0x44, 0xBD, 0xD9, 0x72, 0x74, 0xF9, 0x6A, 0x48, 0xCB, 0xE5, 0x3E, 0x55, 0xD4, - 0xA7, 0x69, 0xB2, 0xA1, 0x18, 0xBF, 0x8C, 0x8A, 0xD1, 0xC0, 0x5C, 0xE4, 0x9B, 0x87, 0x62, 0xA7, - 0x24, 0x68, 0xCA, 0xF9, 0x8A, 0x8A, 0x31, 0xE3, 0x9E, 0x95, 0x7D, 0x61, 0x03, 0x8A, 0x21, 0xB4, - 0x60, 0x73, 0x38, 0xA7, 0xAC, 0xEF, 0x3C, 0xE3, 0x4F, 0xF2, 0xBF, 0x2B, 0x8D, 0x1B, 0x51, 0xC4, - 0xD2, 0xF7, 0xE6, 0xA3, 0xA1, 0xFB, 0xA3, 0xC3, 0xEE, 0x9E, 0x52, 0x2E, 0x5E, 0x29, 0xCB, 0x0F, - 0x08, 0x55, 0x57, 0x61, 0x9F, 0x3A, 0x66, 0xCD, 0x76, 0xE7, 0x40, 0xE9, 0x28, 0xFB, 0xAD, 0xBD, - 0xFD, 0x03, 0xD6, 0xDC, 0x7D, 0xD7, 0xDE, 0x3F, 0x50, 0x76, 0x5B, 0xBB, 0x4A, 0x97, 0xED, 0x2A, - 0x07, 0xFB, 0xFB, 0xFB, 0x7B, 0xAD, 0xDD, 0x83, 0xDD, 0x3A, 0xFC, 0x28, 0xC3, 0x21, 0x4F, 0x56, - 0x34, 0x64, 0x97, 0x86, 0x3C, 0x5D, 0xD1, 0x68, 0xBB, 0x8D, 0xA3, 0x63, 0x3C, 0xB8, 0xEE, 0x46, - 0xAA, 0x7F, 0xE9, 0xDD, 0xD9, 0xF6, 0x95, 0x6D, 0x0D, 0xEF, 0xEC, 0x13, 0x7E, 0x26, 0x30, 0x10, - 0xF8, 0x48, 0xE6, 0x44, 0x2A, 0x55, 0x4C, 0x9B, 0x7B, 0xD2, 0xE5, 0xDD, 0xB8, 0xD6, 0x4D, 0x06, - 0x99, 0xB9, 0x60, 0xAA, 0xD1, 0x86, 0xA4, 0xEA, 0x7A, 0x52, 0x32, 0xA9, 0xD7, 0x70, 0x24, 0xBB, - 0x47, 0x6B, 0xD1, 0xB1, 0xAE, 0x57, 0xB4, 0x0E, 0xE5, 0x44, 0x1B, 0xAA, 0x4B, 0x9D, 0x75, 0xD8, - 0x7F, 0x68, 0xE4, 0xAA, 0x6B, 0xDE, 0x3A, 0x20, 0xA0, 0xCF, 0x97, 0x39, 0xF3, 0xC9, 0x08, 0x38, - 0xF7, 0x33, 0xFA, 0xB4, 0x2E, 0x36, 0x39, 0x40, 0x00, 0x90, 0x25, 0xB6, 0x45, 0x61, 0x5A, 0x55, - 0xA7, 0x64, 0x10, 0xDB, 0x64, 0x82, 0x8B, 0x2A, 0x83, 0xBB, 0x5C, 0x83, 0xD3, 0x22, 0x26, 0x49, - 0xD0, 0xDB, 0x62, 0x51, 0xCC, 0xF0, 0x5B, 0x3F, 0x9E, 0x7B, 0x63, 0x95, 0x6C, 0x29, 0xF5, 0xDF, - 0x2E, 0x7C, 0xC2, 0xCA, 0x06, 0x39, 0x97, 0x0B, 0xED, 0xE7, 0xBF, 0x5C, 0xF8, 0x44, 0xE5, 0x0F, - 0xE4, 0x25, 0x5B, 0xBD, 0x77, 0x0A, 0x43, 0xD9, 0xEB, 0xB3, 0xF9, 0xBC, 0x3C, 0xDB, 0xB5, 0xC2, - 0xA7, 0x68, 0xE5, 0x93, 0xAB, 0x85, 0xAA, 0x61, 0x31, 0xB9, 0x9C, 0x2D, 0x71, 0xB5, 0x90, 0x32, - 0x5A, 0x74, 0xBD, 0x70, 0x75, 0x35, 0x2A, 0x3D, 0xF0, 0xFA, 0xDF, 0x42, 0xC0, 0x6A, 0xA6, 0x2F, - 0x1E, 0xF0, 0xD1, 0xEB, 0xB5, 0x43, 0x1D, 0xFE, 0x3C, 0x04, 0xCF, 0x2B, 0xD5, 0x2F, 0x4E, 0x72, - 0x92, 0xE9, 0xC0, 0xB3, 0x3B, 0x95, 0x87, 0x6E, 0x77, 0x86, 0xB6, 0xA0, 0x7F, 0xC3, 0x0F, 0x74, - 0x5E, 0x83, 0x07, 0xD8, 0xFE, 0x12, 0x2C, 0x2F, 0x09, 0x18, 0x54, 0x37, 0xE1, 0xC9, 0x96, 0x2F, - 0xCD, 0xD3, 0x4B, 0xAC, 0x0D, 0x15, 0x92, 0xA5, 0xA2, 0x06, 0x0C, 0xB0, 0xFE, 0xB8, 0x11, 0x42, - 0x61, 0x0E, 0xE4, 0x90, 0x4D, 0x5F, 0x8C, 0x89, 0x57, 0x88, 0xE4, 0x3E, 0x89, 0x9E, 0x17, 0x58, - 0x08, 0xD7, 0x4F, 0x35, 0xD0, 0x56, 0x33, 0xFA, 0x66, 0x25, 0x9C, 0x03, 0x61, 0x5C, 0x8C, 0xC4, - 0xC4, 0x50, 0x87, 0x15, 0x03, 0x5A, 0x43, 0x53, 0x4F, 0x72, 0xC2, 0xF9, 0xC6, 0x9E, 0x4D, 0xBD, - 0x40, 0xAE, 0xDC, 0x38, 0x95, 0xE0, 0x8F, 0x4D, 0xC1, 0xAA, 0x1B, 0xC5, 0xC4, 0x3C, 0x9B, 0x35, - 0xF2, 0xF3, 0xF1, 0x79, 0xE9, 0xD3, 0xF8, 0x5A, 0x75, 0xBF, 0xED, 0xC0, 0x68, 0xE8, 0x75, 0x39, - 0xDF, 0x11, 0x5E, 0x8F, 0xD4, 0x11, 0x93, 0x3C, 0x3E, 0x73, 0x6C, 0xCA, 0x8E, 0xEF, 0xED, 0x07, - 0xCE, 0xCE, 0x4D, 0xD3, 0x70, 0x3C, 0xDB, 0xD0, 0x43, 0x2F, 0x36, 0x00, 0xC2, 0x37, 0xE9, 0xE4, - 0x6F, 0x48, 0x01, 0x25, 0x12, 0xBD, 0x50, 0xE1, 0x52, 0x25, 0xE4, 0xE2, 0xEF, 0xE3, 0xF3, 0xB1, - 0x6D, 0x05, 0x54, 0x63, 0x5A, 0x06, 0x0D, 0xE0, 0x16, 0x59, 0x7A, 0x15, 0xC1, 0x65, 0xE9, 0xC2, - 0x4B, 0x15, 0x01, 0xA6, 0xB4, 0xCD, 0xB7, 0x90, 0x5D, 0xEF, 0x56, 0x91, 0xDD, 0xAA, 0xDF, 0xC8, - 0x45, 0x98, 0x5C, 0x76, 0x4D, 0xE5, 0xAE, 0x84, 0x4A, 0xBE, 0xE6, 0xCC, 0x4E, 0xA4, 0x86, 0xF4, - 0xA0, 0x4B, 0xE4, 0x24, 0x84, 0x5F, 0xE9, 0x3C, 0x91, 0xC9, 0xBC, 0x57, 0x26, 0x1F, 0xF8, 0x87, - 0xBB, 0x15, 0xCC, 0xC8, 0x69, 0x8A, 0xB3, 0x50, 0x8C, 0x91, 0x38, 0x84, 0x7B, 0x6E, 0xCC, 0x9D, - 0x36, 0x66, 0x00, 0xC3, 0x6A, 0xF5, 0xC0, 0x4D, 0x50, 0xA3, 0xA9, 0xC2, 0xC7, 0x28, 0x14, 0x4C, - 0x35, 0x35, 0x68, 0x8A, 0xFC, 0x05, 0x13, 0x64, 0x8B, 0x1A, 0x94, 0x9C, 0xC1, 0x23, 0xE2, 0x39, - 0x73, 0x9C, 0x20, 0xCB, 0xD0, 0x72, 0x2E, 0x07, 0x61, 0x11, 0xCC, 0xED, 0x68, 0x6A, 0xA2, 0xD2, - 0xA8, 0x9C, 0x30, 0x45, 0x3F, 0xFD, 0xB3, 0x17, 0xDC, 0xFB, 0xAE, 0x4A, 0x55, 0x3C, 0xFF, 0x99, - 0xB8, 0x47, 0xE8, 0x33, 0x7B, 0x0C, 0xBF, 0x2D, 0x4B, 0x65, 0x92, 0x67, 0x61, 0xE0, 0xCD, 0xF1, - 0x6D, 0x6F, 0x92, 0x2B, 0x34, 0xE2, 0x46, 0x51, 0x7E, 0x3E, 0xE8, 0x8E, 0x0A, 0xE0, 0x60, 0x19, - 0xEE, 0xD0, 0x71, 0x76, 0xC2, 0xCF, 0x46, 0xD0, 0xC3, 0x13, 0x7B, 0x1C, 0x71, 0x4B, 0x46, 0x35, - 0x89, 0xBA, 0xA1, 0xC4, 0xC4, 0xC8, 0xBB, 0x55, 0x95, 0x97, 0x57, 0x8E, 0x0D, 0xFC, 0x66, 0x94, - 0x18, 0x75, 0x9B, 0x22, 0x8C, 0x02, 0x4B, 0xBC, 0x40, 0x4D, 0xA2, 0x3A, 0xE0, 0x2D, 0x76, 0x63, - 0xFB, 0xFC, 0x90, 0x22, 0xB5, 0xA2, 0x75, 0xD2, 0x96, 0x53, 0xC4, 0x91, 0xF9, 0xA8, 0x3E, 0x79, - 0xD2, 0x82, 0x25, 0x2B, 0x9C, 0x8E, 0x30, 0xD6, 0x30, 0xE3, 0xE6, 0x8F, 0xF9, 0x08, 0xB2, 0x0D, - 0x54, 0xFA, 0xCA, 0x24, 0x3B, 0x2D, 0x17, 0xB1, 0xBB, 0xB1, 0x04, 0xDE, 0xC9, 0x20, 0x70, 0x56, - 0x2A, 0x0B, 0x6F, 0x3A, 0xA1, 0x9B, 0xD0, 0xC5, 0x71, 0xEF, 0x74, 0x9A, 0xCE, 0xE1, 0xD1, 0x9A, - 0x92, 0x39, 0xCC, 0x2C, 0x85, 0xCA, 0x55, 0x5D, 0x2F, 0x4B, 0xE0, 0x92, 0x42, 0xCA, 0x92, 0xF7, - 0x2B, 0xF1, 0x55, 0x21, 0xBE, 0x15, 0x2A, 0xD6, 0x12, 0x71, 0x8B, 0xA5, 0xEC, 0xBD, 0x34, 0x29, - 0x1B, 0xF1, 0xA8, 0xB4, 0xE0, 0xBC, 0x3C, 0xEC, 0xCE, 0x17, 0x98, 0x43, 0x0C, 0xEE, 0x8D, 0x28, - 0x7E, 0x9C, 0x10, 0x3B, 0x29, 0x40, 0x7B, 0xC1, 0x38, 0x7C, 0x59, 0x95, 0x2F, 0x8B, 0x93, 0x65, - 0x9B, 0x39, 0xD4, 0x48, 0xA3, 0x46, 0x22, 0x1F, 0x2C, 0x9D, 0x2B, 0xE2, 0x6B, 0xC2, 0x6B, 0xF4, - 0xB3, 0x70, 0x19, 0xD7, 0x0D, 0x42, 0xCB, 0x6D, 0xE6, 0x8D, 0xF0, 0xF4, 0xC1, 0xDC, 0x0E, 0x88, - 0x64, 0xA8, 0xE7, 0x51, 0x08, 0x0A, 0x60, 0xF2, 0xCB, 0xF4, 0xA9, 0xC8, 0x95, 0xAD, 0xF7, 0x96, - 0xE7, 0xE9, 0x16, 0x62, 0x6E, 0x98, 0x3C, 0xB8, 0xBA, 0x4D, 0x44, 0xF4, 0xB0, 0x32, 0x8B, 0x08, - 0xDD, 0x6B, 0xAC, 0x86, 0xB4, 0x43, 0x97, 0x92, 0xD0, 0x38, 0xDF, 0x98, 0xC7, 0x24, 0x46, 0xAE, - 0x6C, 0xCF, 0x4C, 0xD9, 0x9F, 0xE0, 0xF8, 0x10, 0xC1, 0x56, 0x14, 0x2E, 0x0E, 0xD2, 0x5F, 0xB8, - 0x34, 0x76, 0xCF, 0x07, 0x98, 0x8B, 0x5A, 0x9C, 0x59, 0x18, 0xCD, 0x25, 0xCF, 0x8D, 0x28, 0xBD, - 0x35, 0xF9, 0x3F, 0xC5, 0x7D, 0x9C, 0xD0, 0x57, 0xEA, 0x07, 0xA4, 0xC1, 0xFD, 0x25, 0x3A, 0x09, - 0x46, 0x08, 0x36, 0x97, 0xA3, 0x60, 0xD8, 0xFA, 0xD5, 0x59, 0x70, 0xE9, 0x84, 0x54, 0xBF, 0xB3, - 0xE0, 0x95, 0xEA, 0xEF, 0xA0, 0x55, 0x19, 0x8D, 0x67, 0xAF, 0x3E, 0x83, 0xCF, 0xE4, 0x33, 0x18, - 0x52, 0x50, 0x49, 0xBF, 0xC1, 0xD2, 0xDB, 0x13, 0xDF, 0xDC, 0xDA, 0xDD, 0x0C, 0x27, 0xA7, 0x52, - 0xBA, 0xAB, 0xE1, 0xE4, 0xFB, 0x35, 0x73, 0x37, 0xDC, 0x55, 0x5A, 0xCA, 0x7B, 0xA5, 0xF3, 0x7E, - 0xF7, 0xDD, 0x7B, 0xD6, 0x6C, 0x2B, 0x7B, 0xAD, 0xF6, 0xC1, 0x9E, 0xB2, 0xF7, 0x6E, 0xBF, 0xCD, - 0xDA, 0x7B, 0xFB, 0xF0, 0xDD, 0xC1, 0xFB, 0x7A, 0x7D, 0x0D, 0x57, 0x30, 0x5E, 0xE8, 0x68, 0xB8, - 0x82, 0xA1, 0x4A, 0x78, 0x19, 0x66, 0xCE, 0xA2, 0x92, 0x8D, 0x7A, 0xBE, 0x19, 0xBF, 0xBA, 0x18, - 0x66, 0xB8, 0x18, 0xCE, 0x0A, 0x91, 0xB5, 0xBB, 0x19, 0x86, 0x43, 0x2C, 0xC1, 0xD5, 0x70, 0xD9, - 0xB3, 0x8F, 0x8F, 0xB1, 0x1C, 0x97, 0xC3, 0x65, 0xAF, 0x20, 0x39, 0xCA, 0xC6, 0xBB, 0x1E, 0xC6, - 0x8F, 0xAE, 0x1F, 0xC6, 0x03, 0x71, 0x33, 0xEB, 0xB4, 0xF7, 0xB9, 0xFB, 0x80, 0x75, 0x5A, 0x13, - 0x75, 0xDA, 0xC5, 0xC3, 0x95, 0xD5, 0x69, 0x0F, 0xE7, 0xF0, 0x3C, 0x75, 0xDA, 0x3D, 0x1A, 0x1D, - 0x05, 0xEF, 0xC0, 0x21, 0xE4, 0x0E, 0xF3, 0x94, 0xBC, 0xF1, 0x66, 0x0A, 0xB6, 0x53, 0xD6, 0xB4, - 0x99, 0x72, 0xED, 0x5F, 0x28, 0x61, 0x89, 0xA8, 0xD7, 0x2E, 0xA4, 0x79, 0x1F, 0x2F, 0x4F, 0x54, - 0x0D, 0xD3, 0x7F, 0x48, 0x85, 0x38, 0xD9, 0x4F, 0x20, 0xB2, 0x82, 0x58, 0x89, 0x52, 0xF1, 0x2F, - 0xA7, 0x86, 0xBB, 0xD8, 0xD0, 0x79, 0xD3, 0x49, 0x7C, 0x28, 0x51, 0x5B, 0x26, 0x35, 0x43, 0x67, - 0xC9, 0x32, 0x6B, 0x49, 0x2E, 0x5F, 0xC8, 0x01, 0x4A, 0x95, 0x5A, 0x9B, 0x59, 0xB6, 0x92, 0x91, - 0xAC, 0xB3, 0x70, 0xB8, 0xA9, 0x64, 0x9E, 0x29, 0x1D, 0x17, 0x33, 0xAD, 0x38, 0x15, 0xB3, 0x36, - 0x66, 0xE8, 0xAC, 0xA1, 0xB6, 0x9A, 0x40, 0x81, 0xC2, 0xFA, 0x6A, 0x15, 0xFC, 0xAD, 0x93, 0x79, - 0x3B, 0x2B, 0xAF, 0xB4, 0xFE, 0x72, 0x58, 0xB5, 0xFB, 0xD1, 0xC4, 0xD7, 0x44, 0x15, 0x19, 0x3F, - 0xDB, 0x9E, 0x3F, 0x47, 0x29, 0x9F, 0x25, 0x94, 0x10, 0x0F, 0xFF, 0xE1, 0x8C, 0x0E, 0x17, 0xF5, - 0xE2, 0x38, 0xA8, 0x64, 0xE5, 0xAA, 0x6C, 0xE9, 0xCA, 0x80, 0x62, 0x85, 0xD1, 0x9C, 0xBC, 0x8E, - 0x16, 0xB5, 0x7D, 0x55, 0xF7, 0x19, 0x79, 0x66, 0x2C, 0xEC, 0xD9, 0xEE, 0x9A, 0x61, 0x21, 0xCE, - 0xE8, 0xB9, 0xB1, 0xB0, 0xF0, 0xCE, 0x23, 0x0B, 0x8E, 0x8B, 0xE3, 0xA1, 0xE8, 0xE8, 0x87, 0xC3, - 0x43, 0x2C, 0xD2, 0xBE, 0x5E, 0x78, 0x88, 0x33, 0xDA, 0x34, 0x6E, 0x28, 0xA1, 0xB8, 0x38, 0x16, - 0x8A, 0x8E, 0x7E, 0x48, 0x2C, 0xEC, 0xFD, 0x5C, 0x13, 0x1E, 0x66, 0x55, 0x51, 0x9F, 0x03, 0x0F, - 0x4B, 0x57, 0x4B, 0xCF, 0x41, 0xC5, 0x77, 0x95, 0xAE, 0x80, 0x6B, 0x41, 0x45, 0x02, 0x65, 0x3D, - 0xC8, 0x88, 0x5D, 0xFD, 0x40, 0xE8, 0x38, 0x29, 0x20, 0xBF, 0x64, 0xA6, 0x48, 0x03, 0x55, 0x38, - 0x9B, 0x61, 0x46, 0x9B, 0xC3, 0x14, 0x13, 0x50, 0x5C, 0x04, 0x0F, 0xE3, 0x1D, 0xFD, 0x90, 0x58, - 0xB8, 0x74, 0xA6, 0x38, 0x07, 0x1E, 0x6E, 0x14, 0x53, 0x9C, 0x02, 0x65, 0x3D, 0xC8, 0xF8, 0x3C, - 0x4C, 0x71, 0x81, 0x57, 0xCA, 0x98, 0x04, 0x36, 0xDE, 0xDE, 0xD3, 0x5E, 0x96, 0xBD, 0xA7, 0x5D, - 0xD5, 0xDE, 0xD3, 0xD9, 0x54, 0x7B, 0x4F, 0xFB, 0xA5, 0xDA, 0x7B, 0xDA, 0xAF, 0xF6, 0x9E, 0x1A, - 0xEC, 0x3D, 0xED, 0xBA, 0xEC, 0x3D, 0xED, 0x1F, 0xD3, 0xDE, 0xD3, 0x7E, 0xB5, 0xF7, 0xD4, 0x62, - 0xEF, 0x69, 0xD7, 0x65, 0xEF, 0x69, 0xFF, 0x98, 0xF6, 0x9E, 0xF6, 0xAB, 0xBD, 0xA7, 0x06, 0x7B, - 0x4F, 0xBB, 0x2E, 0x7B, 0x4F, 0xFB, 0x47, 0xB5, 0xF7, 0xB4, 0x5F, 0xED, 0x3D, 0x75, 0xD9, 0x7B, - 0xDA, 0xF5, 0xD9, 0x7B, 0xDA, 0x3F, 0xA6, 0xBD, 0xA7, 0xFD, 0x6A, 0xEF, 0xA9, 0xC1, 0xDE, 0xD3, - 0xAE, 0xCB, 0xDE, 0xD3, 0xFE, 0x51, 0xED, 0x3D, 0xED, 0x57, 0x7B, 0x4F, 0x5D, 0xF6, 0x9E, 0x76, - 0x7D, 0xF6, 0x9E, 0xF6, 0xAB, 0xBD, 0x67, 0xDD, 0xEC, 0x3D, 0x9D, 0x65, 0xD9, 0x7B, 0x3A, 0x55, - 0xED, 0x3D, 0xDD, 0x4D, 0xB5, 0xF7, 0x74, 0x5E, 0xAA, 0xBD, 0xA7, 0xF3, 0x6A, 0xEF, 0xA9, 0xC1, - 0xDE, 0xD3, 0xA9, 0xCB, 0xDE, 0xD3, 0xF9, 0x31, 0xED, 0x3D, 0x9D, 0x57, 0x7B, 0x4F, 0x2D, 0xF6, - 0x9E, 0x4E, 0x5D, 0xF6, 0x9E, 0xCE, 0x8F, 0x69, 0xEF, 0xE9, 0xBC, 0xDA, 0x7B, 0x6A, 0xB0, 0xF7, - 0x74, 0xEA, 0xB2, 0xF7, 0x74, 0x7E, 0x54, 0x7B, 0x4F, 0xE7, 0xD5, 0xDE, 0x53, 0x97, 0xBD, 0xA7, - 0x53, 0x9F, 0xBD, 0xA7, 0xF3, 0x63, 0xDA, 0x7B, 0x3A, 0xAF, 0xF6, 0x9E, 0x1A, 0xEC, 0x3D, 0x9D, - 0xBA, 0xEC, 0x3D, 0x9D, 0x1F, 0xD5, 0xDE, 0xD3, 0x79, 0xB5, 0xF7, 0xD4, 0x65, 0xEF, 0xE9, 0xD4, - 0x67, 0xEF, 0xE9, 0xBC, 0xDA, 0x7B, 0xD6, 0xCD, 0xDE, 0xD3, 0x5D, 0x96, 0xBD, 0xA7, 0x5B, 0xD5, - 0xDE, 0xB3, 0xBB, 0xA9, 0xF6, 0x9E, 0xEE, 0x4B, 0xB5, 0xF7, 0x74, 0x5F, 0xED, 0x3D, 0x35, 0xD8, - 0x7B, 0xBA, 0x75, 0xD9, 0x7B, 0xBA, 0x3F, 0xA6, 0xBD, 0xA7, 0xFB, 0x6A, 0xEF, 0xA9, 0xC5, 0xDE, - 0xD3, 0xAD, 0xCB, 0xDE, 0xD3, 0xFD, 0x31, 0xED, 0x3D, 0xDD, 0x57, 0x7B, 0x4F, 0x0D, 0xF6, 0x9E, - 0x6E, 0x5D, 0xF6, 0x9E, 0xEE, 0x8F, 0x6A, 0xEF, 0xE9, 0xBE, 0xDA, 0x7B, 0xEA, 0xB2, 0xF7, 0x74, - 0xEB, 0xB3, 0xF7, 0x74, 0x7F, 0x4C, 0x7B, 0x4F, 0xF7, 0xD5, 0xDE, 0x53, 0x83, 0xBD, 0xA7, 0x5B, - 0x97, 0xBD, 0xA7, 0xFB, 0xA3, 0xDA, 0x7B, 0xBA, 0xAF, 0xF6, 0x9E, 0xBA, 0xEC, 0x3D, 0xDD, 0xFA, - 0xEC, 0x3D, 0xDD, 0x17, 0x63, 0xEF, 0x29, 0xCA, 0x11, 0x94, 0xD3, 0xAB, 0xB4, 0x01, 0x45, 0x39, - 0xD1, 0x86, 0xDC, 0xBF, 0xE6, 0x9E, 0xA7, 0x0E, 0xF9, 0x95, 0xE1, 0xF9, 0x58, 0xB8, 0x92, 0x2A, - 0x04, 0xCC, 0x65, 0x22, 0xCA, 0x4F, 0x0B, 0x95, 0x48, 0xFA, 0x56, 0xCA, 0x3C, 0x14, 0x3E, 0xC7, - 0x14, 0xFB, 0xC2, 0xB8, 0x71, 0xED, 0x0D, 0x71, 0x8A, 0xF9, 0x23, 0xA5, 0x5A, 0x90, 0xA6, 0x2D, - 0x44, 0xD9, 0x7D, 0xE7, 0xEF, 0xDA, 0xED, 0xDD, 0xE9, 0x35, 0xBB, 0xA5, 0xE4, 0xB0, 0x1F, 0x0C, - 0x42, 0x37, 0x4C, 0x62, 0x05, 0x6D, 0x4F, 0xD1, 0x22, 0xD4, 0xA8, 0xC3, 0x64, 0x54, 0xC2, 0x5C, - 0x54, 0x3A, 0x53, 0x17, 0xCD, 0xD0, 0xF5, 0xB5, 0x31, 0x4E, 0xF9, 0xD2, 0x1A, 0xD8, 0xC5, 0xB5, - 0xE5, 0x64, 0xFE, 0x2E, 0x5A, 0x28, 0xA6, 0x8D, 0x77, 0x55, 0xCB, 0x1B, 0x1B, 0x7E, 0xAC, 0xE4, - 0x01, 0xAE, 0x98, 0xA9, 0x98, 0xA3, 0x5A, 0x17, 0xA9, 0xB4, 0x30, 0xD5, 0x6E, 0xFB, 0xF3, 0x9F, - 0x94, 0x0B, 0x7E, 0x2C, 0xB0, 0xC9, 0x63, 0x6D, 0x45, 0xD9, 0xDB, 0x86, 0x9F, 0xEF, 0x76, 0xF1, - 0xE7, 0x01, 0xFD, 0x7C, 0x8F, 0x3F, 0xDB, 0x9D, 0x5D, 0x91, 0x60, 0x5E, 0x69, 0x85, 0x8D, 0xDA, - 0x9D, 0xAE, 0x22, 0x33, 0xD5, 0xCB, 0x34, 0xBD, 0xA6, 0xFD, 0x48, 0x55, 0x19, 0xF0, 0x5B, 0xAA, - 0x73, 0xE1, 0x89, 0xAA, 0x28, 0xF0, 0x1C, 0xC6, 0xB7, 0x74, 0x4A, 0x7A, 0x8A, 0x49, 0xEF, 0x7C, - 0xD5, 0x30, 0x6D, 0x57, 0x56, 0x53, 0x90, 0x73, 0x85, 0xDE, 0x9F, 0x76, 0x54, 0xD3, 0x14, 0xBB, - 0x15, 0xCE, 0xA8, 0xC5, 0xAE, 0x0C, 0xF8, 0xD2, 0x3B, 0x64, 0x0A, 0xBE, 0xDC, 0x51, 0xE2, 0xD5, - 0x1A, 0x44, 0x0D, 0x16, 0x82, 0x1D, 0x8C, 0xE7, 0x53, 0xBD, 0x06, 0x1B, 0x38, 0x88, 0x6B, 0xE8, - 0x3A, 0xB7, 0xF0, 0x7D, 0x9C, 0x2B, 0x95, 0x6B, 0x31, 0x2C, 0x86, 0x88, 0xC2, 0xC6, 0xB6, 0xCE, - 0x37, 0x2B, 0x75, 0x58, 0xAA, 0x05, 0x71, 0x1E, 0x4A, 0xA8, 0xDF, 0x88, 0x48, 0x3D, 0x26, 0x9B, - 0xDE, 0xDB, 0x40, 0x05, 0xE3, 0xB0, 0x75, 0x21, 0xC7, 0x4D, 0x4D, 0x2E, 0x99, 0x9E, 0x48, 0x32, - 0x56, 0x18, 0xC5, 0xE5, 0x1E, 0xF7, 0xEF, 0x6C, 0x44, 0x14, 0x99, 0x17, 0x8E, 0xAA, 0xBA, 0xDE, - 0xE2, 0x63, 0xD8, 0xF5, 0x52, 0x67, 0x42, 0xD8, 0xB0, 0x5C, 0x1E, 0xC9, 0xB2, 0x75, 0x67, 0x9E, - 0x17, 0x18, 0x57, 0xF6, 0xE3, 0x49, 0x48, 0x66, 0x11, 0x40, 0x4A, 0x41, 0x03, 0x33, 0x53, 0x02, - 0x91, 0x46, 0xAD, 0x81, 0xEA, 0xAC, 0x6F, 0x95, 0x40, 0x53, 0x0C, 0x1B, 0xC4, 0xDB, 0x71, 0xF2, - 0xD8, 0x6A, 0x2C, 0x3B, 0x7D, 0x64, 0x89, 0xC7, 0x69, 0x83, 0x7C, 0xF8, 0x87, 0x66, 0x93, 0x35, - 0xC3, 0x7F, 0xA1, 0x38, 0xC6, 0xDD, 0x01, 0x26, 0x8E, 0x16, 0xF4, 0x16, 0xFB, 0xBA, 0xD9, 0x9C, - 0xEA, 0x31, 0x46, 0x68, 0x3A, 0xC8, 0xAA, 0x86, 0xCE, 0x86, 0xAA, 0x93, 0x5A, 0xD0, 0x39, 0xE3, - 0x7A, 0x27, 0xF3, 0x3E, 0x07, 0x61, 0xE8, 0x38, 0x61, 0xFA, 0xC0, 0x32, 0xC7, 0xF3, 0x4F, 0xD9, - 0x17, 0x3D, 0xD3, 0x47, 0x76, 0xAF, 0x17, 0x76, 0x5C, 0xE9, 0x34, 0x8E, 0x9A, 0xA5, 0x0E, 0x95, - 0xCC, 0xFA, 0x9D, 0xB1, 0xE1, 0x42, 0xDA, 0x4B, 0xC0, 0x37, 0x70, 0x45, 0x69, 0x12, 0x79, 0x60, - 0x3B, 0xB1, 0x37, 0x16, 0x3F, 0xB5, 0xD3, 0x31, 0x3B, 0x0D, 0x39, 0x0A, 0x39, 0x70, 0xB4, 0xFA, - 0x94, 0x51, 0xB2, 0x19, 0xEE, 0x5C, 0x72, 0xE0, 0x19, 0xA5, 0xD1, 0x64, 0x97, 0x67, 0x87, 0xA1, - 0xD4, 0x3C, 0x82, 0x0E, 0x1F, 0x61, 0xB1, 0x97, 0x67, 0x39, 0xE9, 0xD5, 0x77, 0x8E, 0x51, 0x50, - 0xCE, 0xCD, 0x8F, 0x7E, 0x86, 0x25, 0x8E, 0x40, 0xEA, 0x36, 0x4C, 0xF6, 0x8D, 0xC3, 0x9F, 0xB0, - 0xF5, 0x86, 0xCB, 0xA3, 0x61, 0x74, 0xF8, 0xFA, 0x96, 0x8F, 0x55, 0xC3, 0x32, 0xAC, 0x61, 0xCE, - 0x48, 0x36, 0xFB, 0x2B, 0xB4, 0xCE, 0x14, 0xCB, 0x9F, 0x35, 0xA5, 0x6B, 0x1C, 0xC5, 0x4E, 0xA3, - 0x9C, 0xA3, 0x5E, 0x94, 0xDE, 0x35, 0xFE, 0x7D, 0x2E, 0x53, 0x8A, 0x35, 0x66, 0xAB, 0xC8, 0x03, - 0x9B, 0x39, 0xF1, 0x15, 0xE6, 0x84, 0xBD, 0x6A, 0xE2, 0xC9, 0xC0, 0x76, 0xD8, 0x65, 0x2F, 0x49, - 0xAB, 0x5A, 0x0C, 0x18, 0x24, 0x67, 0xA9, 0x0F, 0x20, 0xDA, 0x51, 0x05, 0xAC, 0xD9, 0x94, 0xAD, - 0x1B, 0x97, 0xB1, 0x75, 0xC8, 0xED, 0xA1, 0xAB, 0x3A, 0x23, 0x43, 0xBB, 0xE5, 0x43, 0x58, 0xE3, - 0x99, 0x6B, 0x3B, 0x82, 0xAB, 0x14, 0x61, 0x24, 0x21, 0xDE, 0x74, 0xF3, 0xC6, 0xD1, 0xA7, 0xE8, - 0x09, 0x13, 0x8F, 0x8A, 0x15, 0xFC, 0x64, 0xB9, 0x82, 0x99, 0x2E, 0x53, 0xE7, 0x99, 0x54, 0xD9, - 0x75, 0x39, 0xEB, 0x30, 0xBB, 0x6C, 0xEE, 0x1E, 0x24, 0x93, 0xE2, 0x2B, 0x8D, 0xA3, 0xAF, 0xFD, - 0x72, 0x89, 0xEA, 0x67, 0x2B, 0x13, 0x9C, 0x7F, 0x9D, 0xAB, 0x25, 0x4C, 0xF1, 0x78, 0xBE, 0x96, - 0xC0, 0x29, 0xFE, 0x7A, 0x3B, 0x57, 0xCB, 0xDD, 0xC6, 0xD1, 0x7F, 0x57, 0x01, 0x57, 0x8A, 0x1B, - 0x17, 0xE7, 0xE1, 0xAF, 0x97, 0xFA, 0xFA, 0x62, 0xF7, 0x9F, 0xEC, 0xC0, 0x65, 0x93, 0x6D, 0x66, - 0x2E, 0xED, 0xB3, 0xD4, 0xBE, 0x40, 0xA1, 0x03, 0x06, 0x2C, 0xD2, 0x29, 0x4B, 0x4A, 0x1D, 0xB8, - 0xFC, 0x8F, 0x80, 0x5B, 0xDA, 0x13, 0xE9, 0x6C, 0x02, 0x2B, 0x54, 0x33, 0xC6, 0xBB, 0x40, 0xAA, - 0x70, 0x0C, 0x2D, 0x46, 0xA4, 0x5F, 0xFB, 0xEB, 0x44, 0x9E, 0x42, 0x36, 0x72, 0x17, 0xA0, 0x5D, - 0xC7, 0xE9, 0x73, 0x1F, 0x93, 0x51, 0x7B, 0x99, 0xE7, 0xF3, 0x62, 0x67, 0x4F, 0xE9, 0xF3, 0x47, - 0x0D, 0x7C, 0x1B, 0xCE, 0xC5, 0x5B, 0x6E, 0xF1, 0x47, 0xD5, 0x04, 0xEC, 0x86, 0xCF, 0x78, 0x50, - 0x32, 0xF9, 0xA4, 0x64, 0xA1, 0x97, 0x45, 0x4E, 0x92, 0xE9, 0x29, 0x94, 0xDF, 0xE8, 0xC5, 0x72, - 0xE5, 0x4B, 0x24, 0xFE, 0x19, 0x4F, 0x06, 0x12, 0x2C, 0x90, 0x17, 0x31, 0x58, 0x2B, 0xE8, 0x1A, - 0x9D, 0x03, 0x86, 0x72, 0x05, 0xAA, 0x1E, 0x24, 0x6E, 0x3C, 0x6D, 0x33, 0x9C, 0x26, 0x56, 0xA4, - 0xC3, 0x9A, 0x95, 0x80, 0xB9, 0xBE, 0xCF, 0xC7, 0x0E, 0x55, 0xCE, 0x02, 0x6C, 0xB3, 0x90, 0x0C, - 0xE0, 0xCF, 0x37, 0x9F, 0xED, 0x31, 0x7F, 0xC3, 0x2C, 0xEE, 0x3F, 0xDA, 0xEE, 0xB7, 0x6D, 0xD0, - 0x83, 0x40, 0x24, 0x52, 0xB1, 0xAB, 0x6D, 0xFC, 0xDA, 0xC5, 0x25, 0xD2, 0x58, 0x31, 0xDC, 0x16, - 0x47, 0xBC, 0x5E, 0xBA, 0xFE, 0x67, 0xCD, 0x89, 0xF5, 0x8B, 0x09, 0xA1, 0xBC, 0x23, 0x51, 0x25, - 0xF3, 0x77, 0xFC, 0x30, 0x8A, 0x0B, 0xD0, 0x42, 0x90, 0xEC, 0xB9, 0xF6, 0xC0, 0x30, 0xF9, 0x9D, - 0xFD, 0x8D, 0x97, 0xF0, 0x0D, 0x2B, 0xBC, 0x7B, 0x99, 0x2D, 0xD1, 0x26, 0xE5, 0x55, 0x39, 0x0E, - 0xA3, 0x81, 0x0E, 0xAB, 0x6D, 0xC1, 0xE2, 0xA5, 0x1A, 0x26, 0x25, 0x46, 0x89, 0x87, 0xDA, 0xEE, - 0x50, 0xB5, 0x8C, 0x3F, 0x85, 0x6E, 0x31, 0x52, 0x3D, 0x4C, 0x5A, 0x6F, 0xBB, 0x8E, 0x4D, 0xE6, - 0x23, 0xE0, 0xA6, 0xD6, 0xB0, 0xEF, 0xBB, 0x5C, 0x1D, 0x13, 0xDF, 0x4C, 0x88, 0x3A, 0xAA, 0xA6, - 0xA1, 0x61, 0x7A, 0x5B, 0x24, 0xC8, 0x37, 0x48, 0xDE, 0x71, 0x39, 0xF6, 0xCA, 0x90, 0x30, 0xA9, - 0x77, 0x2D, 0xF0, 0x00, 0x83, 0x65, 0xBE, 0x7B, 0xE6, 0xC8, 0x85, 0xFB, 0xB8, 0xF0, 0x38, 0x3A, - 0x02, 0x56, 0x3F, 0xB1, 0x26, 0x13, 0xD9, 0xF6, 0x39, 0xEB, 0x3B, 0xAA, 0xFB, 0xED, 0x22, 0xB0, - 0x04, 0x84, 0x1A, 0x73, 0x54, 0xB4, 0xA8, 0xB3, 0x04, 0x44, 0x39, 0x8C, 0x2E, 0xC3, 0xB1, 0xB2, - 0x6E, 0xC6, 0xDE, 0x95, 0x21, 0xC4, 0x0A, 0xD7, 0x10, 0x05, 0xA8, 0x5D, 0xBA, 0x0E, 0x79, 0x7E, - 0x3F, 0x35, 0x14, 0x26, 0xAF, 0x8D, 0x01, 0xD4, 0x7B, 0x40, 0x91, 0xAC, 0xE0, 0xF9, 0x70, 0x40, - 0x7C, 0x75, 0x80, 0xD8, 0x38, 0x1A, 0x8E, 0xE8, 0x09, 0x9D, 0x52, 0xE2, 0xD9, 0x0A, 0x0E, 0xA9, - 0xD9, 0x69, 0x3C, 0xC7, 0x31, 0x25, 0xEB, 0x2C, 0x8B, 0x12, 0x2E, 0x09, 0x06, 0x40, 0x07, 0xD8, - 0xA3, 0x61, 0x9A, 0x68, 0xEA, 0x96, 0x93, 0xE5, 0x3A, 0x31, 0x8A, 0x80, 0x26, 0xAC, 0xA3, 0x7D, - 0x1D, 0x9B, 0x59, 0x80, 0xAF, 0xCC, 0x76, 0xB0, 0xE6, 0x70, 0x60, 0x19, 0xFE, 0x53, 0x75, 0x5D, - 0x68, 0xBD, 0xCF, 0x22, 0xDC, 0xAD, 0xC0, 0xE3, 0xC7, 0x9E, 0x67, 0x78, 0xFE, 0x8D, 0xFD, 0x78, - 0x1A, 0x6E, 0x68, 0xC5, 0xCA, 0xDC, 0xA5, 0xD1, 0xB8, 0x34, 0x2A, 0xC7, 0x67, 0x05, 0x92, 0x56, - 0xF8, 0x67, 0x85, 0x3A, 0x95, 0x8B, 0x60, 0x70, 0x72, 0xF4, 0x67, 0x3A, 0xE9, 0x08, 0x8B, 0xA3, - 0x72, 0xDA, 0x13, 0x10, 0x5C, 0x7F, 0x3A, 0x16, 0x15, 0x56, 0x66, 0x51, 0x18, 0xE4, 0x26, 0x63, - 0x0C, 0xA7, 0xD5, 0x83, 0xAC, 0x8C, 0xAD, 0x6A, 0x7F, 0x04, 0x86, 0x67, 0xD0, 0x19, 0xE9, 0x00, - 0xF6, 0x63, 0x9D, 0x60, 0x4B, 0xE3, 0xF3, 0xA1, 0xF1, 0x1A, 0x1C, 0x56, 0x8B, 0x33, 0x5F, 0xB9, - 0xBB, 0x58, 0xFC, 0xCE, 0x34, 0xFE, 0xE4, 0x3A, 0xAC, 0xDF, 0x77, 0x8D, 0xFB, 0x80, 0x6A, 0x03, - 0xAE, 0x13, 0xF6, 0xA7, 0xCE, 0x50, 0x54, 0xED, 0xA3, 0xC7, 0x2C, 0xFE, 0xBC, 0xC6, 0xF2, 0xAE, - 0x0B, 0x92, 0x4D, 0xC6, 0xB4, 0xD7, 0x82, 0x84, 0xCC, 0x08, 0x76, 0x71, 0x6B, 0x17, 0xDE, 0x71, - 0x92, 0xCC, 0x67, 0xCA, 0x82, 0x88, 0x11, 0x5D, 0x51, 0xB1, 0x52, 0xC3, 0x02, 0xCA, 0x52, 0xA3, - 0x2A, 0xDF, 0x28, 0xAF, 0x80, 0xBC, 0x60, 0xF9, 0xA0, 0xEE, 0xC5, 0x7A, 0xD9, 0x6C, 0x8A, 0x2A, - 0x77, 0xE5, 0x63, 0xA6, 0x6D, 0xED, 0x1D, 0x48, 0x55, 0x57, 0xFC, 0x81, 0x9B, 0x25, 0x4C, 0x6A, - 0x69, 0xDA, 0x4C, 0x7E, 0xA7, 0x59, 0xF8, 0xCE, 0xF0, 0x0D, 0x46, 0xAF, 0x94, 0xF7, 0xAC, 0x49, - 0x1A, 0xE0, 0x0A, 0x06, 0x2E, 0xB1, 0xE2, 0x72, 0x98, 0x38, 0xAF, 0x01, 0x2F, 0xDB, 0x90, 0xD7, - 0x56, 0x14, 0x85, 0x7D, 0xC7, 0x1B, 0x7E, 0xE5, 0xDB, 0x98, 0x74, 0x0E, 0x8F, 0x57, 0xAC, 0x41, - 0x39, 0x63, 0xE2, 0xDB, 0xA3, 0x2E, 0xF7, 0xEA, 0xEA, 0x11, 0x16, 0xD7, 0xD9, 0xC3, 0x1E, 0xE1, - 0x67, 0x3D, 0x3D, 0x76, 0xA7, 0xD7, 0xFD, 0x19, 0x98, 0x01, 0x10, 0x9D, 0x05, 0xA7, 0xDB, 0xD3, - 0x42, 0x3D, 0xEF, 0x26, 0x57, 0x5F, 0x5B, 0xBF, 0x7B, 0x49, 0x18, 0xCC, 0xD7, 0x6F, 0x85, 0x6A, - 0xA1, 0x4B, 0x61, 0xA0, 0xD2, 0x6A, 0x89, 0x9C, 0x6F, 0xC2, 0x3D, 0xF5, 0x38, 0x25, 0xFA, 0x48, - 0x89, 0x26, 0xD2, 0x43, 0x2B, 0xB1, 0x46, 0x54, 0xAC, 0xB1, 0x5E, 0xE2, 0x18, 0x86, 0xD6, 0xB9, - 0xDE, 0x92, 0x48, 0xC0, 0xC6, 0xEA, 0x13, 0xF2, 0x56, 0x9D, 0x3B, 0xF0, 0x2D, 0xCA, 0xDA, 0x31, - 0xD6, 0x99, 0x05, 0xAF, 0x4D, 0x60, 0xA5, 0xB9, 0x86, 0xCE, 0x8A, 0x12, 0xCC, 0x2A, 0x2E, 0xC2, - 0x5D, 0xDF, 0x7B, 0xFE, 0x0B, 0x70, 0x9C, 0xC5, 0xB2, 0xEE, 0xC0, 0xE3, 0x7D, 0x57, 0xBB, 0x06, - 0x8F, 0xB5, 0xCC, 0xBA, 0xE5, 0x9E, 0x40, 0x6F, 0xE6, 0x7A, 0x1B, 0x1B, 0xAF, 0xD5, 0xBD, 0x76, - 0xEE, 0x72, 0xE6, 0xBB, 0xDA, 0x4E, 0x31, 0x62, 0xC2, 0x06, 0xE7, 0x57, 0x3C, 0x44, 0x04, 0xBC, - 0xB0, 0xC3, 0x1A, 0x92, 0xC2, 0x9F, 0x0C, 0xC8, 0x15, 0xA8, 0x92, 0xBB, 0x78, 0xA5, 0x71, 0x76, - 0x7C, 0x77, 0xCC, 0x10, 0x7C, 0xDB, 0xCC, 0x1B, 0x81, 0x9A, 0x33, 0x08, 0x40, 0x0A, 0x93, 0x2C, - 0x15, 0xDD, 0x81, 0xA6, 0x71, 0x33, 0x55, 0x46, 0x09, 0x7B, 0xC3, 0x45, 0x7F, 0x71, 0x8A, 0xEE, - 0x57, 0x13, 0x4D, 0xC9, 0xCF, 0x0D, 0xDB, 0x9D, 0x8E, 0x54, 0xCB, 0x8A, 0x09, 0x34, 0xE1, 0x62, - 0x4B, 0x1E, 0xDA, 0x71, 0xE9, 0x26, 0xEA, 0xF3, 0x44, 0x0D, 0x40, 0x20, 0xBC, 0xC5, 0x8F, 0x84, - 0x3D, 0x0C, 0x1F, 0x90, 0x27, 0xE3, 0x21, 0x9B, 0x53, 0x80, 0x49, 0xF6, 0x9D, 0x5C, 0x82, 0x78, - 0x94, 0x26, 0x7A, 0xCC, 0x27, 0x75, 0xEC, 0x1E, 0x28, 0x20, 0x78, 0xE0, 0xCF, 0x85, 0x8E, 0xC4, - 0xF7, 0xFB, 0xD8, 0x0D, 0xFE, 0x5C, 0x4C, 0x5E, 0x79, 0xDF, 0xC1, 0x7E, 0xE8, 0xD7, 0x62, 0x42, - 0xC5, 0xC1, 0x2E, 0x76, 0x44, 0xBF, 0x16, 0x3B, 0xEB, 0xDF, 0xD1, 0xCA, 0xE8, 0xD7, 0x62, 0x4B, - 0x6B, 0xEF, 0x89, 0xB5, 0xD1, 0xEF, 0xC5, 0x64, 0xB0, 0xAE, 0x42, 0xAB, 0x13, 0xBF, 0x17, 0x13, - 0x91, 0xF6, 0x15, 0x81, 0x00, 0xF4, 0x7B, 0x31, 0x14, 0xE8, 0xB4, 0x05, 0x12, 0xD0, 0xEF, 0xCD, - 0x11, 0x84, 0xEE, 0xC8, 0xF3, 0x16, 0x68, 0x96, 0xEE, 0x17, 0x50, 0x67, 0x44, 0x99, 0xE8, 0xF6, - 0xF8, 0xEC, 0xF2, 0x0B, 0x31, 0xAD, 0xD0, 0x73, 0x56, 0x03, 0xE6, 0x31, 0x14, 0x96, 0x98, 0xB1, - 0xEA, 0x6B, 0xC0, 0xE2, 0x50, 0x8D, 0x74, 0xB1, 0xCE, 0xEE, 0xC8, 0x46, 0xBE, 0x07, 0x7A, 0x24, - 0x91, 0x69, 0x4C, 0xEC, 0x21, 0xB4, 0xB9, 0x77, 0xBC, 0x97, 0x26, 0xE6, 0x94, 0xE3, 0xBB, 0xB8, - 0x3D, 0x35, 0xB3, 0xDD, 0xA9, 0x2E, 0x1B, 0x47, 0xD7, 0xC1, 0x77, 0x26, 0x3F, 0xCC, 0xCD, 0x6F, - 0xA7, 0x3B, 0x4D, 0x9B, 0x7C, 0x9D, 0x3C, 0x17, 0x88, 0xE4, 0xE6, 0xFA, 0xFC, 0x78, 0x51, 0xCD, - 0xAE, 0xD7, 0xEB, 0xEF, 0x9C, 0x3F, 0xA0, 0x63, 0xF5, 0x1D, 0x60, 0xFD, 0x10, 0x4B, 0x5E, 0x2F, - 0xA4, 0xD8, 0x09, 0xEF, 0xCF, 0xE0, 0xBB, 0x5C, 0x31, 0x6C, 0xCD, 0x65, 0xE7, 0x74, 0x51, 0xD5, - 0xEE, 0xF8, 0xEC, 0x74, 0xE7, 0xEC, 0xF8, 0x74, 0xB3, 0xD8, 0x41, 0x24, 0xB0, 0x44, 0xB4, 0x2F, - 0x05, 0x42, 0xE9, 0x38, 0xAF, 0x1B, 0x83, 0x01, 0x77, 0x11, 0xF2, 0xAA, 0xE3, 0x98, 0x86, 0x30, - 0x2E, 0x79, 0x2D, 0x86, 0xBB, 0x8A, 0xDA, 0x11, 0x99, 0x97, 0xF0, 0x45, 0xE0, 0x0F, 0x06, 0x08, - 0x40, 0x77, 0xBF, 0xEC, 0xDC, 0xFE, 0x82, 0xFC, 0x21, 0x32, 0x44, 0x21, 0x5D, 0xBB, 0x63, 0xFA, - 0xBB, 0xC5, 0x70, 0x23, 0xE5, 0x16, 0x26, 0x5A, 0x3B, 0x01, 0x08, 0xB3, 0x68, 0xDD, 0x85, 0x7E, - 0x60, 0x06, 0x3A, 0xB3, 0x03, 0x1F, 0x4D, 0x78, 0x78, 0x9D, 0xB1, 0x67, 0x79, 0x78, 0xDD, 0x19, - 0x10, 0xD3, 0xF2, 0xC3, 0xC6, 0x68, 0xC9, 0x83, 0x79, 0xC0, 0xBE, 0x45, 0x1D, 0xE1, 0xFD, 0xA9, - 0xC5, 0x54, 0x5D, 0x27, 0x5B, 0x31, 0x4C, 0xA6, 0x7F, 0x76, 0xBC, 0xD3, 0x3F, 0xBD, 0x12, 0x86, - 0x66, 0x4D, 0xEC, 0x75, 0x8B, 0xFD, 0x3C, 0xE2, 0xDC, 0xDC, 0x39, 0x33, 0x5C, 0x76, 0x67, 0x68, - 0xDF, 0x12, 0xD3, 0xA0, 0x2B, 0x7F, 0xDB, 0x37, 0x1E, 0x38, 0x0C, 0x00, 0x42, 0xD8, 0x40, 0xD5, - 0x0C, 0x6B, 0xD8, 0x62, 0x72, 0x6B, 0x13, 0xEF, 0xCA, 0xDB, 0xD5, 0x81, 0xE1, 0x8E, 0xD1, 0xE9, - 0x71, 0x0A, 0x3E, 0x11, 0x5F, 0x44, 0x40, 0xBD, 0x38, 0x2B, 0x5A, 0xC8, 0x31, 0x50, 0x44, 0xAB, - 0x93, 0xD7, 0x09, 0x09, 0xF3, 0x0C, 0xB7, 0xAB, 0x26, 0x01, 0x33, 0xD1, 0xF3, 0xCC, 0xDC, 0x5F, - 0xC5, 0xCB, 0x57, 0xF1, 0xF2, 0x55, 0xBC, 0xAC, 0xCD, 0xAB, 0xC5, 0x12, 0xC7, 0x02, 0x46, 0x35, - 0x6D, 0xCB, 0x30, 0xAF, 0x69, 0x61, 0x73, 0xF6, 0xBC, 0xC9, 0x94, 0x35, 0x63, 0x0C, 0x35, 0xC6, - 0x4F, 0x05, 0x7C, 0x37, 0x44, 0xD0, 0xAC, 0xC4, 0x54, 0x23, 0xB5, 0x1F, 0xCF, 0xC2, 0xD0, 0xE8, - 0x33, 0x65, 0x15, 0x29, 0x6B, 0x74, 0x5F, 0xEC, 0x7A, 0xAF, 0xF4, 0x15, 0x9F, 0xB8, 0x95, 0x3A, - 0x8F, 0x4F, 0x3C, 0x72, 0x61, 0x0F, 0x9F, 0x96, 0x0F, 0x33, 0xC6, 0xE6, 0xD5, 0x42, 0x8C, 0x17, - 0xF7, 0x67, 0x9F, 0x9A, 0x7B, 0x75, 0x94, 0x5A, 0x9C, 0x7A, 0x62, 0x14, 0xF4, 0x89, 0x5B, 0x9C, - 0xC8, 0x45, 0x15, 0xD0, 0xC0, 0x28, 0x1F, 0xD6, 0x97, 0x12, 0x11, 0x88, 0x27, 0xF0, 0xDE, 0x58, - 0x06, 0x4F, 0x8E, 0x03, 0xA0, 0x95, 0x01, 0x65, 0x6C, 0xD8, 0x16, 0x76, 0x28, 0xC0, 0x1F, 0x8C, - 0x3E, 0x94, 0xB2, 0x92, 0xF6, 0xD4, 0x62, 0xE8, 0x38, 0x63, 0xB8, 0xDC, 0x13, 0xF7, 0xE8, 0x2E, - 0xD7, 0xB8, 0x33, 0x45, 0x4D, 0xD2, 0x17, 0x51, 0x74, 0xD0, 0x56, 0x94, 0x6D, 0x45, 0x51, 0x02, - 0x4F, 0x8A, 0x63, 0x26, 0xB7, 0x86, 0x64, 0xDF, 0xD2, 0xD9, 0xFB, 0xE8, 0x2B, 0x31, 0x03, 0xEE, - 0x3F, 0x72, 0x6E, 0x89, 0xF7, 0xBC, 0x56, 0x95, 0x00, 0xEB, 0x65, 0x91, 0x63, 0x25, 0xDD, 0xAF, - 0x4A, 0xA4, 0x7F, 0x06, 0x69, 0x9E, 0x71, 0x0C, 0x1B, 0xF5, 0xE6, 0xA6, 0xD0, 0x85, 0x5C, 0x29, - 0xB3, 0xE4, 0xA8, 0xC4, 0x3C, 0xEF, 0x60, 0xA7, 0x4E, 0xC4, 0x46, 0x09, 0xEC, 0x2E, 0xDD, 0xE5, - 0x9C, 0x1E, 0x96, 0x77, 0xB3, 0xA8, 0xC1, 0xB6, 0xFE, 0xDF, 0xFF, 0xF5, 0xDE, 0x1E, 0x96, 0x5F, - 0x4C, 0x15, 0xF2, 0x5F, 0xD8, 0xAD, 0x2F, 0xD3, 0xC5, 0x2F, 0x2F, 0x23, 0x55, 0xA5, 0x5E, 0xF1, - 0xDF, 0x0C, 0x02, 0xCD, 0x6C, 0x4C, 0xC5, 0x99, 0x3A, 0xC5, 0x5D, 0xD6, 0x91, 0xA7, 0xA0, 0xC4, - 0x5D, 0xCF, 0x3C, 0x44, 0xB5, 0x7C, 0xC4, 0xBF, 0x22, 0xBE, 0xB5, 0x74, 0x74, 0xEF, 0xC5, 0x98, - 0x64, 0xA5, 0xB1, 0x04, 0x4D, 0x6C, 0x00, 0xAA, 0xCF, 0xE2, 0x99, 0x04, 0xED, 0xE2, 0x08, 0x2B, - 0x3A, 0xDA, 0x04, 0x34, 0xA5, 0x0B, 0x31, 0xA2, 0x29, 0x7D, 0xC8, 0xE7, 0x55, 0x76, 0x0B, 0x71, - 0xB6, 0x67, 0x9B, 0xAA, 0x8B, 0xB7, 0xC4, 0xAB, 0xC1, 0xDA, 0x70, 0xB8, 0xC3, 0x39, 0x38, 0x6E, - 0x42, 0xBF, 0x4E, 0x5F, 0xC4, 0xEC, 0x7E, 0x2F, 0xB4, 0xBE, 0x79, 0xB4, 0xF3, 0x6C, 0x83, 0xE4, - 0xAD, 0xE1, 0x19, 0xD6, 0x90, 0xE1, 0x76, 0x56, 0x53, 0xD3, 0xB2, 0xED, 0x93, 0x17, 0xAA, 0x69, - 0xCE, 0xDF, 0x67, 0x79, 0xBD, 0x6D, 0x89, 0x12, 0xE8, 0x94, 0x5D, 0x50, 0x48, 0x80, 0x9E, 0x31, - 0x44, 0x3B, 0x5A, 0xE8, 0x4B, 0x36, 0x42, 0x77, 0x06, 0x11, 0x58, 0xA9, 0x91, 0x91, 0x6C, 0xCB, - 0x15, 0xB0, 0xE4, 0xB0, 0xEE, 0xB7, 0x28, 0xA1, 0x62, 0x28, 0x4D, 0xE2, 0x85, 0x81, 0x84, 0x0C, - 0xBD, 0x11, 0x13, 0x3C, 0x63, 0x9B, 0x50, 0x75, 0x43, 0x97, 0x29, 0x41, 0x56, 0x91, 0x22, 0x2B, - 0x30, 0x9E, 0xB9, 0x53, 0x4B, 0xAD, 0x42, 0x6D, 0xFB, 0x2C, 0xC3, 0xB6, 0xC9, 0xC0, 0x7E, 0x65, - 0x0F, 0x87, 0x18, 0x56, 0x2D, 0xB5, 0xB8, 0xD2, 0x40, 0xAB, 0xAC, 0xED, 0x09, 0x73, 0xBE, 0x1C, - 0x6E, 0x25, 0x5A, 0x5F, 0xE9, 0xA9, 0xCD, 0x6A, 0x87, 0xE9, 0x20, 0x7A, 0x66, 0x65, 0x11, 0xE6, - 0x31, 0x71, 0x3C, 0x08, 0xC5, 0x6D, 0x8E, 0x33, 0xF4, 0xDE, 0x0A, 0x85, 0xAE, 0xAB, 0x44, 0xA6, - 0x73, 0xED, 0x89, 0xDD, 0x5E, 0xF7, 0x5B, 0x18, 0xE5, 0x33, 0x08, 0x4C, 0x69, 0x8E, 0xC1, 0x78, - 0x44, 0x66, 0x1A, 0xDF, 0x40, 0x67, 0x0C, 0xF0, 0x52, 0xDF, 0x77, 0x0D, 0xD5, 0x1A, 0x06, 0xA6, - 0xB4, 0xB9, 0xF4, 0xB9, 0x88, 0x08, 0x42, 0xE1, 0x12, 0xE8, 0xE9, 0x1B, 0xDA, 0xE6, 0x89, 0xF1, - 0x49, 0x37, 0xD2, 0xDF, 0xCE, 0xCF, 0x9A, 0x17, 0xEF, 0x7B, 0xEC, 0xD2, 0xF2, 0xF9, 0x50, 0x7A, - 0x90, 0x5C, 0xAB, 0x56, 0xA0, 0x8A, 0xFE, 0xC7, 0xB6, 0xCB, 0x93, 0xD6, 0xFF, 0x62, 0x7D, 0xB4, - 0xA2, 0xDF, 0xE9, 0xE6, 0x6B, 0x94, 0x71, 0x8C, 0xAA, 0x4D, 0xA5, 0xA4, 0x01, 0xB0, 0xE3, 0x65, - 0x89, 0x2C, 0x34, 0xEB, 0x95, 0x89, 0x2C, 0x82, 0x55, 0xD4, 0x2E, 0xB2, 0x24, 0x17, 0x31, 0xBB, - 0x2B, 0x6B, 0x24, 0xB2, 0x60, 0x36, 0x1C, 0xDF, 0x26, 0x77, 0xC2, 0xBA, 0x44, 0x16, 0x72, 0x4D, - 0x14, 0x89, 0x76, 0x5E, 0x86, 0xC4, 0x12, 0xB1, 0x42, 0xC2, 0xFC, 0x48, 0x66, 0x31, 0x81, 0xB6, - 0xB8, 0xCE, 0xD0, 0xC9, 0x73, 0x14, 0xE6, 0x22, 0x33, 0xA6, 0xB8, 0x4E, 0x0C, 0xBC, 0xAF, 0xC2, - 0x48, 0x75, 0xC3, 0x75, 0x00, 0xBA, 0x51, 0x78, 0x5C, 0x62, 0x4C, 0x3F, 0x79, 0x88, 0xAD, 0xA1, - 0x91, 0x3A, 0x36, 0xB7, 0x29, 0x1B, 0x35, 0xA3, 0xC7, 0xA5, 0x37, 0x25, 0x96, 0xF8, 0xE4, 0x19, - 0xEC, 0xD5, 0x55, 0x40, 0x5C, 0x8D, 0xF4, 0x32, 0xC6, 0x29, 0x97, 0xF4, 0x2F, 0x85, 0x2C, 0x25, - 0x94, 0x23, 0xCA, 0x24, 0x9F, 0xA1, 0x78, 0xC4, 0xC9, 0x21, 0xA5, 0xD7, 0xDB, 0xF9, 0x7A, 0xF2, - 0xCB, 0x4E, 0xBF, 0x77, 0x7C, 0x7B, 0x77, 0x83, 0x74, 0x1A, 0x8A, 0x15, 0x5F, 0xE1, 0x41, 0x27, - 0x46, 0xA5, 0x17, 0x6A, 0x35, 0x5B, 0xD9, 0xC6, 0x0A, 0x06, 0x11, 0xE0, 0x05, 0x4C, 0xFA, 0x76, - 0xE0, 0x6A, 0x29, 0xC7, 0x78, 0x65, 0x32, 0x09, 0x8F, 0xF0, 0xD4, 0xFE, 0x81, 0x26, 0xC2, 0x6D, - 0x92, 0x5B, 0x21, 0x9E, 0x57, 0x3C, 0x6E, 0x67, 0x8E, 0xDA, 0xD4, 0xC1, 0xEE, 0x00, 0xD1, 0x1B, - 0xB9, 0xCB, 0xAD, 0x9C, 0xFE, 0x76, 0xDE, 0x03, 0x77, 0xF6, 0x64, 0x14, 0x49, 0x4B, 0xE6, 0x38, - 0x14, 0x67, 0x8E, 0xED, 0xCB, 0x5E, 0xC5, 0x7B, 0xE0, 0x4A, 0xC7, 0xEA, 0xF2, 0x34, 0x0B, 0x8A, - 0x38, 0x93, 0x58, 0x10, 0x8F, 0x32, 0x43, 0x37, 0x17, 0x0C, 0xCC, 0x34, 0x74, 0x71, 0xA2, 0x12, - 0x85, 0xCA, 0x14, 0x04, 0xF1, 0xB4, 0x2F, 0x1E, 0x6D, 0x61, 0x8B, 0x3C, 0xA5, 0x6F, 0xCE, 0xBF, - 0x34, 0xCF, 0xDE, 0x9F, 0x1E, 0x32, 0x89, 0x18, 0x02, 0xBA, 0x31, 0xB2, 0xBE, 0xEC, 0x6D, 0xEA, - 0xFD, 0xD1, 0x02, 0xAF, 0x14, 0x86, 0x79, 0xA2, 0xA3, 0xF9, 0xB1, 0xF9, 0x88, 0x29, 0x49, 0xC8, - 0x91, 0x5C, 0xB2, 0x52, 0x52, 0x9C, 0xA4, 0x6F, 0x14, 0xE6, 0x16, 0x65, 0x5F, 0xFB, 0x27, 0xC5, - 0x4E, 0xE5, 0xCB, 0x0B, 0xD6, 0x17, 0x87, 0xC5, 0x27, 0xCB, 0xF3, 0xEE, 0xEC, 0xAF, 0xDE, 0x7D, - 0x9F, 0x9C, 0xC0, 0xA2, 0xE3, 0x75, 0x7A, 0xB6, 0x85, 0x80, 0x85, 0xD5, 0x2C, 0x3F, 0xB2, 0x3F, - 0x63, 0xCE, 0x2B, 0x0E, 0xEF, 0xFF, 0x22, 0xC0, 0x42, 0x20, 0x92, 0xBE, 0x73, 0xE4, 0xA6, 0xB6, - 0x65, 0xF0, 0x6D, 0xE1, 0x46, 0x41, 0xB9, 0x92, 0xE0, 0x78, 0x7C, 0x2B, 0x76, 0x1A, 0x09, 0x0B, - 0x77, 0x9B, 0x9C, 0x27, 0x62, 0x01, 0x9D, 0x9E, 0xAF, 0xFA, 0x81, 0x17, 0x4B, 0x51, 0x5B, 0xF9, - 0xC0, 0x7C, 0xCE, 0xD0, 0xFE, 0x0A, 0x5F, 0x65, 0x07, 0x09, 0x65, 0x51, 0xD5, 0x54, 0xBC, 0xD0, - 0xCF, 0xC6, 0x85, 0x91, 0x1F, 0x2E, 0x54, 0x32, 0x54, 0xA8, 0x6A, 0x98, 0xD0, 0x5C, 0x51, 0x41, - 0xE9, 0x11, 0x41, 0xB8, 0x86, 0xB9, 0x02, 0x82, 0x62, 0x0D, 0x67, 0x41, 0x1B, 0x83, 0xCC, 0x54, - 0x28, 0xD0, 0xA3, 0x31, 0x30, 0x16, 0x8B, 0x04, 0x9A, 0x8D, 0x02, 0x9A, 0xDE, 0xB5, 0xC2, 0xE8, - 0x9F, 0xCC, 0xB9, 0x57, 0x0B, 0xFC, 0xC9, 0x0F, 0xFA, 0x49, 0xC3, 0xC4, 0x1B, 0x91, 0xD7, 0xC9, - 0x4B, 0xBF, 0xC0, 0xAE, 0x81, 0x29, 0x44, 0x82, 0x32, 0x88, 0x5E, 0x4C, 0x73, 0xB9, 0x0E, 0x8D, - 0x80, 0x15, 0x88, 0x80, 0x6E, 0x98, 0x1B, 0x68, 0xA5, 0xBB, 0x62, 0x77, 0x64, 0x8A, 0x29, 0xA0, - 0xEF, 0x63, 0x50, 0x6C, 0xC3, 0x4F, 0x91, 0x9A, 0xEB, 0xBB, 0x86, 0xCC, 0xFE, 0x41, 0x7E, 0x57, - 0x98, 0x2E, 0x45, 0xBE, 0x33, 0x49, 0x82, 0x98, 0x88, 0x09, 0x6F, 0x95, 0x4D, 0xD9, 0xB8, 0x28, - 0x43, 0xC8, 0xFA, 0x2E, 0xEB, 0x08, 0xAC, 0x7C, 0x37, 0x1C, 0x97, 0x6E, 0x11, 0x5D, 0xE5, 0xA6, - 0xFD, 0xAE, 0xF4, 0xFB, 0x98, 0x89, 0x34, 0x76, 0x63, 0xDA, 0x9D, 0x31, 0x2D, 0xE1, 0x2B, 0xAC, - 0x9D, 0x7F, 0x17, 0x3B, 0xD7, 0xBD, 0x6B, 0x95, 0x8C, 0x41, 0x29, 0x93, 0x96, 0x07, 0x96, 0x0F, - 0xFB, 0x98, 0x37, 0x88, 0x93, 0xDE, 0x7E, 0x9E, 0x6B, 0xD5, 0x7C, 0xA6, 0xBB, 0xC4, 0x5D, 0xEA, - 0x41, 0x1F, 0xF0, 0x97, 0x5E, 0xB0, 0x53, 0xBD, 0x9F, 0x33, 0xC1, 0xB0, 0x56, 0xFB, 0x17, 0x2D, - 0xA7, 0xDA, 0xB6, 0x85, 0xCD, 0x36, 0x69, 0xEB, 0xDA, 0x65, 0x09, 0xAC, 0xB3, 0x46, 0x1B, 0x24, - 0x26, 0x5D, 0x69, 0x73, 0xDA, 0x9B, 0x46, 0x53, 0xED, 0xC5, 0x69, 0x6A, 0xAD, 0xB6, 0x6C, 0x3E, - 0x9A, 0x6A, 0x6F, 0x22, 0x4D, 0x75, 0xCA, 0xD2, 0x54, 0x77, 0x8D, 0x36, 0xA8, 0x53, 0x9D, 0xA6, - 0x3A, 0x9B, 0x46, 0x53, 0x9D, 0xC5, 0x69, 0x6A, 0xAD, 0xB6, 0x6C, 0x3E, 0x9A, 0xEA, 0x6C, 0x22, - 0x4D, 0x75, 0xCB, 0xD2, 0xD4, 0xEE, 0x1A, 0x6D, 0x50, 0xB7, 0x3A, 0x4D, 0x75, 0x37, 0x8D, 0xA6, - 0xBA, 0x8B, 0xD3, 0xD4, 0x5A, 0x6D, 0xD9, 0x7C, 0x34, 0xD5, 0x5D, 0x35, 0x4D, 0x45, 0x7A, 0x3D, - 0xA9, 0xD4, 0x68, 0x8B, 0xAF, 0x72, 0xB9, 0x30, 0xBD, 0x99, 0xA2, 0x97, 0x2F, 0x0F, 0xDC, 0x3D, - 0xEE, 0x35, 0x8E, 0x42, 0x23, 0x02, 0x67, 0xD7, 0xB6, 0x5E, 0x74, 0x79, 0x90, 0xBC, 0x2C, 0x48, - 0x4E, 0xA9, 0x31, 0x35, 0x4D, 0x39, 0x40, 0x55, 0x73, 0xFF, 0xAC, 0x79, 0xFF, 0xB8, 0x84, 0x51, - 0x7E, 0xD6, 0x94, 0x8F, 0x3A, 0x78, 0x7E, 0xBB, 0x7C, 0xE3, 0x7D, 0x7D, 0xB6, 0x82, 0x4B, 0x8B, - 0x1D, 0xF7, 0x62, 0x31, 0x56, 0x51, 0x2A, 0x12, 0xD4, 0xED, 0x5D, 0x5B, 0xD5, 0x35, 0x15, 0x94, - 0x7F, 0x19, 0x0B, 0xAB, 0x69, 0xDC, 0xF3, 0x18, 0xA5, 0x92, 0x65, 0x98, 0xC7, 0x9A, 0xA3, 0x49, - 0xF1, 0xAF, 0x4D, 0x01, 0xD2, 0x16, 0x83, 0xBE, 0xC8, 0xB8, 0x90, 0xDE, 0x5B, 0x2C, 0xCF, 0x35, - 0xE5, 0x4D, 0x12, 0xEF, 0xA2, 0x8D, 0x21, 0x16, 0x27, 0x4C, 0x86, 0x05, 0xBA, 0x5D, 0xE7, 0x4C, - 0xD6, 0xE0, 0x80, 0x41, 0x2E, 0x7B, 0x18, 0x87, 0xEB, 0xC2, 0xE0, 0x6B, 0x69, 0x67, 0xA8, 0x66, - 0x37, 0xBC, 0x3B, 0xED, 0xB1, 0x1D, 0xF6, 0xF5, 0xAC, 0xB7, 0xE9, 0xC6, 0x43, 0x58, 0x08, 0xAC, - 0x62, 0x2E, 0xF3, 0x61, 0xA2, 0xE9, 0x2C, 0x90, 0xA7, 0x41, 0x34, 0x65, 0x45, 0xF4, 0x35, 0xE7, - 0xAB, 0xEE, 0x3C, 0xBB, 0x1D, 0x31, 0x67, 0x11, 0x0B, 0x5A, 0x12, 0x0B, 0x6F, 0x55, 0x2A, 0xDC, - 0xA6, 0xDC, 0x69, 0xCE, 0xA9, 0x69, 0x00, 0x47, 0x68, 0x1C, 0x21, 0x58, 0xC5, 0xDF, 0xF9, 0x7C, - 0x74, 0xF1, 0xEB, 0x90, 0xC9, 0xA0, 0x99, 0xD4, 0x1A, 0xD5, 0xF8, 0xF2, 0xC3, 0x77, 0x4F, 0xEC, - 0xEF, 0x9C, 0x6A, 0x9D, 0x2D, 0x9B, 0xE5, 0x0D, 0x26, 0xF9, 0x2F, 0x33, 0x18, 0x54, 0xC4, 0x9A, - 0x9C, 0xC0, 0x1B, 0x89, 0xFB, 0x13, 0xAC, 0xE6, 0x07, 0x4C, 0x69, 0x68, 0x3C, 0x70, 0x8B, 0x10, - 0xD4, 0xA3, 0x82, 0x9E, 0x93, 0xDB, 0x14, 0xF1, 0x0D, 0xDE, 0xA7, 0xAC, 0x0B, 0x93, 0xCA, 0x3C, - 0xAE, 0x23, 0x90, 0xE7, 0xA6, 0xF4, 0x9A, 0x2B, 0xAC, 0x26, 0x7E, 0x9E, 0x47, 0xC3, 0x60, 0x80, - 0x7C, 0x63, 0xAE, 0xF0, 0x02, 0x68, 0x78, 0x58, 0xD3, 0x55, 0x5A, 0xE4, 0xDD, 0x05, 0x7B, 0x47, - 0xB7, 0x5E, 0xB0, 0xA3, 0x81, 0x17, 0x4F, 0xFC, 0xDB, 0x79, 0xBF, 0x7B, 0xB0, 0xBE, 0x17, 0x5C, - 0x45, 0xB5, 0x74, 0xE6, 0x8D, 0xE7, 0xA9, 0x22, 0x9F, 0x26, 0x77, 0xB4, 0xA0, 0x5F, 0x67, 0xB6, - 0xC9, 0xBC, 0x11, 0x3A, 0xD5, 0xAF, 0xF7, 0xEA, 0x45, 0xE0, 0xCF, 0xB6, 0x37, 0x1F, 0x02, 0x63, - 0x43, 0xEC, 0x2B, 0x17, 0x52, 0x13, 0xBE, 0x7C, 0xB8, 0xE2, 0x6B, 0x63, 0xF4, 0x74, 0x44, 0x71, - 0x99, 0xC2, 0x81, 0x85, 0x84, 0x15, 0xBA, 0x63, 0x8F, 0x70, 0xE6, 0x8F, 0x23, 0x43, 0x1B, 0x09, - 0xAF, 0x6D, 0x98, 0xA3, 0x46, 0x73, 0x4C, 0x26, 0xDA, 0x46, 0x06, 0x49, 0xF1, 0xF6, 0xAD, 0x57, - 0xCA, 0x29, 0x45, 0x39, 0x02, 0x95, 0xCA, 0xDD, 0xC8, 0xA4, 0x91, 0x11, 0xB6, 0x5F, 0x1D, 0x19, - 0xE5, 0x9D, 0x24, 0x95, 0x74, 0x76, 0x27, 0x4D, 0x3A, 0xA8, 0xBA, 0x8E, 0xD2, 0x26, 0x84, 0x9A, - 0x05, 0x28, 0x51, 0xBB, 0x5B, 0x08, 0x50, 0xE2, 0xEF, 0x15, 0x08, 0x50, 0x72, 0xD0, 0x52, 0x02, - 0x94, 0x78, 0xF7, 0xB9, 0x05, 0x28, 0xD0, 0x08, 0xED, 0x47, 0x66, 0x58, 0xF7, 0x76, 0x00, 0xA2, - 0x13, 0x71, 0x0C, 0x21, 0x52, 0x09, 0x77, 0xAF, 0x84, 0x38, 0x95, 0x22, 0x36, 0xC9, 0x50, 0xAF, - 0x90, 0xCD, 0x60, 0xE9, 0x65, 0xD1, 0x7C, 0x7D, 0xAE, 0x97, 0xF3, 0x24, 0x2A, 0xB1, 0x07, 0x4B, - 0x97, 0xA8, 0xC4, 0x30, 0xAF, 0x12, 0xD5, 0xCB, 0x39, 0x17, 0x62, 0x3B, 0x5A, 0xF6, 0x28, 0x98, - 0x34, 0x59, 0xDE, 0x51, 0x50, 0x67, 0x29, 0xD3, 0x38, 0x40, 0x72, 0xF9, 0xDE, 0x8D, 0xEF, 0x1A, - 0xA0, 0xD9, 0x63, 0x1E, 0x92, 0x46, 0x65, 0x0E, 0x37, 0xE3, 0x9C, 0x3C, 0xD3, 0xE5, 0xD1, 0xCD, - 0xDD, 0xED, 0x25, 0x08, 0x5B, 0xF4, 0xA9, 0x44, 0x79, 0xCA, 0x3A, 0xAB, 0x1D, 0x66, 0x71, 0x4D, - 0x3E, 0xC6, 0x10, 0x39, 0x8E, 0x06, 0x36, 0x31, 0x3B, 0x4D, 0xA6, 0x61, 0x21, 0x76, 0x8A, 0x61, - 0xAD, 0x21, 0x47, 0x95, 0x93, 0x27, 0xF6, 0xE8, 0xC5, 0x4B, 0xC7, 0x21, 0x6B, 0x1D, 0x72, 0x5F, - 0x54, 0x97, 0xAF, 0xA8, 0x90, 0x2E, 0x85, 0xFE, 0x4A, 0x54, 0x27, 0x5D, 0x95, 0xA4, 0x21, 0x10, - 0x67, 0x23, 0x24, 0x8D, 0xAF, 0x7A, 0x24, 0x69, 0xA0, 0xED, 0x6B, 0x35, 0x92, 0xC6, 0x64, 0xD0, - 0x09, 0xBD, 0x05, 0xBA, 0xF3, 0xDC, 0xB2, 0xC4, 0xC4, 0xF6, 0x4C, 0xE2, 0x82, 0x07, 0x5D, 0x72, - 0x4B, 0xE3, 0x9E, 0xF4, 0x53, 0x3E, 0xEB, 0xAD, 0xBB, 0x44, 0x10, 0xE8, 0xE5, 0x8A, 0x74, 0x2E, - 0x2C, 0x13, 0x04, 0xFA, 0x3A, 0xCA, 0x04, 0x88, 0xC0, 0xE9, 0x32, 0x41, 0x5B, 0x69, 0xB7, 0x95, - 0x57, 0xA1, 0x20, 0x4F, 0x28, 0x48, 0x6E, 0x69, 0x29, 0xA1, 0x20, 0xD1, 0x64, 0xC3, 0xF5, 0xC3, - 0x88, 0x25, 0xD5, 0xC1, 0xB5, 0xAB, 0x5D, 0xCE, 0x88, 0x74, 0xF4, 0x1B, 0x7E, 0x31, 0x43, 0x8B, - 0x98, 0xEB, 0x5E, 0x26, 0xDE, 0x72, 0x16, 0xBC, 0x71, 0xE0, 0x4C, 0x5D, 0xC9, 0x50, 0x2C, 0xDE, - 0xB3, 0xDF, 0xC8, 0x64, 0x4F, 0x7F, 0x8D, 0x2E, 0x64, 0xCE, 0x3D, 0x87, 0x4A, 0xE8, 0x9D, 0xF7, - 0x7B, 0xCD, 0x9B, 0x2F, 0x3F, 0x2F, 0xFB, 0x7C, 0x0F, 0x87, 0x5B, 0xF2, 0x39, 0x8E, 0x96, 0x44, - 0x4A, 0x72, 0x8C, 0x21, 0x7F, 0xB0, 0xB4, 0x6E, 0x27, 0x4C, 0xC9, 0x19, 0x25, 0x53, 0x16, 0x17, - 0xC7, 0x80, 0xD5, 0x4D, 0xFA, 0x63, 0x1B, 0x8D, 0x8E, 0xD1, 0x23, 0x10, 0x82, 0x7D, 0x43, 0xDC, - 0x2C, 0x8B, 0xB8, 0x4E, 0x74, 0x59, 0x27, 0x79, 0x96, 0x62, 0xAC, 0xC7, 0x86, 0xE7, 0x25, 0xA3, - 0xAC, 0xBF, 0x0C, 0x06, 0x6B, 0xED, 0x73, 0x1E, 0x51, 0xC5, 0x3C, 0x79, 0x18, 0xD2, 0x11, 0x30, - 0x67, 0xBD, 0x82, 0x34, 0xAF, 0x8F, 0x4F, 0x0F, 0x43, 0x56, 0x4A, 0x63, 0xC3, 0x83, 0x06, 0xF3, - 0xFC, 0x27, 0xDC, 0x21, 0x79, 0x9D, 0x7E, 0x28, 0xD8, 0xE8, 0x5F, 0x1A, 0x47, 0xC7, 0xC7, 0x87, - 0x27, 0x27, 0x87, 0xA7, 0xA7, 0x87, 0x67, 0x67, 0x87, 0xE7, 0xE7, 0x87, 0x17, 0x17, 0x55, 0xDD, - 0x42, 0xE6, 0x9A, 0x69, 0x4F, 0x35, 0x30, 0x1B, 0x38, 0x4D, 0xD8, 0x3B, 0xAC, 0x18, 0x69, 0x56, - 0xEE, 0x2C, 0x74, 0x38, 0x77, 0x61, 0xE5, 0x5E, 0xF6, 0xD2, 0x6F, 0x6C, 0x8B, 0xAF, 0x44, 0x3D, - 0x2E, 0x25, 0xCC, 0x61, 0x23, 0x39, 0x53, 0x21, 0xB2, 0x01, 0x63, 0x02, 0x4E, 0x38, 0x3E, 0xDC, - 0x73, 0xBE, 0xFF, 0xA5, 0x68, 0xC9, 0xF2, 0x98, 0x49, 0x1E, 0x1F, 0x08, 0x05, 0x38, 0x55, 0x10, - 0xD6, 0x02, 0xD0, 0x8D, 0xAC, 0x73, 0x28, 0x55, 0x4E, 0x2C, 0xBE, 0x3F, 0x88, 0x54, 0x05, 0x27, - 0x1A, 0x02, 0x94, 0x05, 0x74, 0xD9, 0x20, 0x59, 0x1E, 0x98, 0x89, 0x1B, 0x70, 0x90, 0x2C, 0xE1, - 0x5B, 0xB9, 0xD5, 0xE9, 0xE5, 0x7B, 0x56, 0x70, 0xC5, 0x11, 0xAB, 0xB0, 0xFE, 0x68, 0x4B, 0x1D, - 0xC3, 0xDB, 0x66, 0xFC, 0xBB, 0xE1, 0xA3, 0xEB, 0x8B, 0x3C, 0xEB, 0x85, 0xCF, 0x0A, 0xD9, 0x28, - 0xE9, 0x16, 0xC4, 0xE3, 0x3E, 0x6C, 0x9C, 0x04, 0x6E, 0x60, 0xF9, 0x86, 0xC9, 0xDE, 0xE0, 0x6A, - 0xDE, 0xA0, 0x5D, 0xD2, 0xE3, 0x58, 0xF3, 0xFA, 0xAB, 0x65, 0xF8, 0x32, 0x64, 0xC6, 0x7B, 0x54, - 0x1D, 0xA4, 0xBE, 0xF0, 0x12, 0x85, 0x7B, 0xD2, 0xB1, 0x05, 0xE0, 0xCA, 0xB0, 0xE0, 0x57, 0x60, - 0x51, 0xEE, 0x61, 0x50, 0xE6, 0x55, 0x5F, 0x94, 0xD0, 0x75, 0xEC, 0x47, 0xBC, 0x3D, 0xB6, 0x5A, - 0x9B, 0x1B, 0x52, 0x57, 0x0F, 0x43, 0x58, 0x49, 0x4C, 0xE9, 0x85, 0x8D, 0x32, 0x92, 0xA4, 0x85, - 0x30, 0xA0, 0x54, 0x3C, 0xC4, 0x08, 0xA8, 0xC2, 0x1D, 0x08, 0x71, 0x78, 0x35, 0xD1, 0xA4, 0x89, - 0xD9, 0x02, 0xF6, 0xC9, 0xBA, 0xCD, 0xCF, 0x40, 0x3A, 0x40, 0x0C, 0x94, 0xFF, 0x44, 0xD5, 0x34, - 0x43, 0x17, 0x25, 0x3E, 0x75, 0x6E, 0xF2, 0x30, 0x6F, 0x93, 0x23, 0x98, 0x39, 0x9D, 0x35, 0x22, - 0x58, 0x3B, 0x5C, 0x17, 0x1B, 0x07, 0x78, 0xF3, 0x69, 0xB8, 0xF0, 0xF3, 0x9E, 0x87, 0x95, 0xA7, - 0xE1, 0xCF, 0x01, 0xE6, 0x71, 0xA2, 0xA8, 0x32, 0x41, 0x5B, 0x40, 0x4E, 0x44, 0x71, 0xF9, 0x46, - 0xFE, 0x75, 0xA5, 0x84, 0xF9, 0x8F, 0xAA, 0x3C, 0xBE, 0x9D, 0xDC, 0xFF, 0x74, 0xCE, 0x5D, 0x81, - 0x47, 0x0F, 0xA8, 0x3B, 0x71, 0xF0, 0xCE, 0xF2, 0xEA, 0xA3, 0x09, 0x19, 0x54, 0x63, 0xD5, 0x4E, - 0xDA, 0x74, 0xAF, 0xBD, 0xE1, 0x94, 0xC2, 0xD6, 0x0F, 0xC8, 0x6D, 0x70, 0x59, 0xAA, 0x67, 0xB6, - 0xF4, 0x65, 0xDA, 0xAE, 0x9A, 0x9B, 0xF8, 0x7C, 0x5A, 0x3C, 0xB0, 0x40, 0x2A, 0xA8, 0x24, 0x90, - 0x15, 0xDA, 0xBD, 0xCB, 0x33, 0xA8, 0x2B, 0x98, 0x2C, 0x66, 0x66, 0xBA, 0x55, 0x8B, 0x4D, 0x10, - 0x8B, 0x33, 0x18, 0x31, 0xDA, 0x8A, 0x0C, 0xDF, 0x09, 0xD5, 0x00, 0x57, 0x28, 0xA5, 0xD5, 0xE7, - 0xD4, 0x0F, 0x9E, 0xCB, 0xEA, 0x9D, 0x8D, 0x5C, 0x21, 0xC6, 0xCE, 0x9B, 0xB6, 0x6D, 0x2E, 0x2E, - 0x74, 0x6A, 0xDB, 0xAE, 0x6E, 0x58, 0x42, 0x95, 0xBF, 0xA0, 0xA2, 0xE9, 0x96, 0xF6, 0xC4, 0xB6, - 0xAE, 0x3F, 0xFF, 0xF9, 0xF6, 0x39, 0x7C, 0x51, 0x28, 0x17, 0xFD, 0x20, 0x9A, 0x07, 0xA1, 0x86, - 0xB8, 0xE7, 0x40, 0x43, 0x05, 0x1B, 0xD9, 0x8E, 0x83, 0x32, 0x54, 0x98, 0x15, 0x5C, 0x16, 0xE1, - 0xF1, 0x5A, 0x92, 0x71, 0xC1, 0xB9, 0x42, 0xE2, 0x95, 0x68, 0x35, 0xE2, 0xAA, 0xCB, 0xB8, 0xAA, - 0x8D, 0x98, 0x0D, 0xE7, 0x8D, 0x2B, 0x4E, 0x24, 0xE8, 0x52, 0x24, 0x15, 0x41, 0xAF, 0x17, 0x2D, - 0xBE, 0xFC, 0x68, 0xD8, 0x18, 0x12, 0xBD, 0x6F, 0x2B, 0x00, 0x8A, 0x16, 0xBB, 0x32, 0xC6, 0x20, - 0xEB, 0xC1, 0x67, 0x05, 0x8D, 0x36, 0xEC, 0x7D, 0xE7, 0x1D, 0x3E, 0x7E, 0x01, 0xE7, 0x95, 0x94, - 0xF8, 0x85, 0x4D, 0x78, 0x0F, 0xE7, 0xD0, 0x65, 0x13, 0xC5, 0xA5, 0x8A, 0x49, 0x33, 0x27, 0xF3, - 0xB3, 0xE4, 0xB6, 0x13, 0x9E, 0x3C, 0x81, 0x7A, 0x84, 0x73, 0xE5, 0x34, 0xBB, 0xCC, 0xE6, 0x0B, - 0x5A, 0x3C, 0xEB, 0xA5, 0x2A, 0x51, 0x62, 0xC1, 0x0B, 0x85, 0x1D, 0x9D, 0xEB, 0x06, 0x95, 0xF5, - 0x65, 0xA6, 0xE1, 0xF9, 0xDC, 0x42, 0x0C, 0x46, 0x75, 0x63, 0xD5, 0x04, 0x76, 0x3C, 0xF0, 0xE9, - 0x66, 0x10, 0x24, 0x2E, 0xB1, 0x59, 0x94, 0xEF, 0x43, 0xCC, 0x75, 0x1B, 0x38, 0x34, 0xE8, 0x29, - 0x38, 0x35, 0x99, 0x3E, 0x24, 0xCA, 0x07, 0x03, 0xAF, 0x1B, 0x43, 0xCB, 0x46, 0x39, 0xCF, 0xB3, - 0x05, 0x85, 0x11, 0x13, 0x97, 0xEF, 0x21, 0x17, 0x1F, 0xA0, 0xDF, 0x47, 0x48, 0x94, 0x52, 0xC3, - 0xC2, 0xFC, 0x9C, 0x58, 0xA3, 0x34, 0x16, 0x06, 0x00, 0x94, 0xE3, 0xF2, 0xA6, 0x38, 0x81, 0xA6, - 0x87, 0x89, 0x11, 0x5D, 0x57, 0xF1, 0x26, 0x14, 0xD7, 0x56, 0xB0, 0xD9, 0xBE, 0xA2, 0x78, 0xAF, - 0xE4, 0x36, 0x1F, 0xB9, 0x89, 0x8C, 0x34, 0x98, 0x55, 0xD5, 0x55, 0x35, 0x51, 0xAD, 0x7D, 0xCC, - 0xED, 0xC0, 0xFF, 0xDD, 0x2B, 0x4F, 0x73, 0xD9, 0x7D, 0x2C, 0x83, 0xF0, 0x2A, 0x08, 0x7C, 0xD5, - 0xAC, 0xFB, 0xB1, 0x4C, 0x7B, 0xAC, 0xE7, 0x1A, 0x36, 0xE6, 0xE3, 0xDC, 0x74, 0x63, 0x7F, 0x6C, - 0x4D, 0xE1, 0x92, 0x72, 0x4D, 0xFF, 0x33, 0xDD, 0x66, 0x5C, 0x05, 0x64, 0xF7, 0x3B, 0xBB, 0x33, - 0x71, 0xB8, 0xA6, 0x5E, 0x0F, 0xC4, 0xD2, 0x7E, 0x2D, 0xE9, 0x92, 0xA0, 0xC2, 0x2D, 0x41, 0xD9, - 0x95, 0xD5, 0x92, 0x0E, 0xA6, 0x5C, 0x18, 0x63, 0x0C, 0x3E, 0x22, 0x61, 0x9D, 0x77, 0x65, 0x0C, - 0x38, 0x16, 0xC7, 0xC9, 0xE6, 0xEE, 0x33, 0x17, 0xBD, 0xBB, 0x91, 0x01, 0x6F, 0x9F, 0xFE, 0xD8, - 0x9F, 0xB9, 0xE8, 0x8D, 0xEF, 0x93, 0x18, 0x87, 0x85, 0xE3, 0x1C, 0xAE, 0x48, 0x19, 0x38, 0x8E, - 0xA5, 0x80, 0x93, 0x99, 0xDD, 0x18, 0xA0, 0x28, 0xE5, 0x71, 0x36, 0x06, 0xCC, 0xB2, 0x85, 0x7B, - 0x31, 0x1C, 0x3A, 0x98, 0xD0, 0xD9, 0x78, 0x90, 0xE5, 0x11, 0xE9, 0xD4, 0x1A, 0xAB, 0xD6, 0x53, - 0x78, 0x60, 0xB5, 0x26, 0x04, 0x1C, 0xBA, 0x22, 0x0B, 0x7F, 0x17, 0x19, 0xA7, 0x41, 0x36, 0x36, - 0xCC, 0x30, 0x8F, 0xB9, 0x6B, 0xC2, 0x0C, 0x72, 0xE1, 0xA1, 0xB2, 0x87, 0x6F, 0xB5, 0x3B, 0x4A, - 0xD4, 0xD9, 0x7A, 0x69, 0x0A, 0xE5, 0x22, 0x50, 0xDF, 0x24, 0x0E, 0x93, 0xDD, 0x37, 0xE5, 0xDC, - 0xAF, 0xDE, 0x88, 0x83, 0xE3, 0x4D, 0xD8, 0x49, 0xFC, 0xE0, 0x78, 0x33, 0x4D, 0xAB, 0xD3, 0xB8, - 0x58, 0xFD, 0x76, 0xC0, 0x29, 0xE8, 0x72, 0x69, 0x7E, 0x39, 0x85, 0xC9, 0x98, 0x66, 0x69, 0x61, - 0x72, 0x26, 0x2C, 0x3B, 0x41, 0xD3, 0xB1, 0x87, 0xA5, 0x10, 0x08, 0x4F, 0x9D, 0x10, 0x8B, 0x41, - 0x16, 0x23, 0x5D, 0x25, 0x9E, 0x21, 0x31, 0xC4, 0x5B, 0xB2, 0xE3, 0x60, 0x58, 0xA4, 0x1A, 0x92, - 0x0C, 0xE0, 0x2F, 0x08, 0x6C, 0x2E, 0x47, 0x7D, 0x09, 0xAD, 0xD0, 0x61, 0x37, 0xE1, 0xBB, 0xE4, - 0xC1, 0x2F, 0xB1, 0x9F, 0x6A, 0xE1, 0x7D, 0xC3, 0xF7, 0xE8, 0x31, 0xC8, 0x6A, 0xF0, 0xB4, 0x45, - 0xC5, 0x7F, 0x87, 0x5C, 0xA4, 0x61, 0xF4, 0x54, 0x24, 0x34, 0xF2, 0xBF, 0x7D, 0xD3, 0x87, 0xBF, - 0x93, 0x5C, 0xFC, 0x4D, 0x49, 0x23, 0xDD, 0xDA, 0x24, 0x7A, 0x8A, 0x9F, 0xD4, 0x92, 0x15, 0x8E, - 0xBF, 0x37, 0xB1, 0x1C, 0xAB, 0xC0, 0x88, 0x69, 0xA4, 0x0C, 0xF7, 0xFD, 0xCA, 0xC8, 0x74, 0xC7, - 0x4F, 0xB7, 0xD7, 0x65, 0x98, 0xE6, 0xA2, 0xFE, 0xB1, 0xE3, 0x13, 0x7A, 0x57, 0x69, 0x1C, 0x29, - 0xF9, 0x76, 0xB5, 0x45, 0x47, 0x68, 0x37, 0x8E, 0xDA, 0xCB, 0x1D, 0x01, 0x76, 0xAC, 0xB3, 0xDC, - 0x11, 0xBA, 0x8D, 0xA3, 0xEE, 0x72, 0x47, 0xD8, 0x6D, 0x1C, 0xED, 0x2E, 0x77, 0x84, 0xBD, 0xC6, - 0xD1, 0xDE, 0x72, 0x47, 0xD8, 0x6F, 0x1C, 0xED, 0x2F, 0x77, 0x84, 0x77, 0x8D, 0xA3, 0x77, 0x45, - 0x23, 0xB8, 0x55, 0x86, 0xCE, 0x20, 0x38, 0xA9, 0xF3, 0xCD, 0x61, 0xE4, 0x8E, 0x8C, 0xDB, 0x2E, - 0x6A, 0x99, 0x77, 0xF6, 0x69, 0x76, 0xE7, 0xE8, 0xC5, 0x28, 0x75, 0x51, 0x3B, 0xD4, 0x32, 0x73, - 0x6C, 0xDC, 0x0B, 0x27, 0x86, 0xBC, 0xB4, 0x3C, 0xDF, 0x0D, 0xF0, 0x3C, 0x78, 0x16, 0xDD, 0x02, - 0x41, 0x6D, 0x44, 0x53, 0x08, 0x75, 0x81, 0x1A, 0x35, 0x8E, 0xCB, 0x99, 0xCE, 0x2B, 0xF9, 0x18, - 0xCD, 0x34, 0x9F, 0xDD, 0x82, 0x19, 0x08, 0x4E, 0xA9, 0x13, 0xB1, 0xE5, 0x3D, 0xB7, 0xCB, 0x51, - 0xC1, 0x6A, 0xE6, 0xD0, 0x21, 0xC8, 0xC5, 0xDF, 0x30, 0x2B, 0xC6, 0xE6, 0xD6, 0x7D, 0x1F, 0x71, - 0x47, 0x33, 0x18, 0x3B, 0xDC, 0xF2, 0x08, 0xF4, 0xD1, 0xA5, 0x29, 0x7E, 0x51, 0x60, 0x53, 0x9E, - 0xB4, 0x5A, 0xC5, 0x5D, 0xC6, 0xEC, 0x4C, 0x57, 0xA5, 0xCA, 0x50, 0xB8, 0x13, 0x6E, 0x15, 0x5E, - 0xF1, 0x47, 0xE3, 0x93, 0x6D, 0x0F, 0x59, 0x0D, 0xA8, 0x24, 0xE8, 0xB5, 0xEC, 0x72, 0x7D, 0xB6, - 0x44, 0x6A, 0x6B, 0xA3, 0xEE, 0x26, 0x96, 0x83, 0x68, 0x22, 0x95, 0xF3, 0x9D, 0xE1, 0x1C, 0x9B, - 0x00, 0xD1, 0x40, 0x07, 0xFD, 0x42, 0xA6, 0x31, 0x86, 0x67, 0x2C, 0x7C, 0xB8, 0x5C, 0x14, 0x4A, - 0x99, 0xC3, 0x8A, 0xB0, 0x47, 0x2E, 0xD5, 0xB1, 0x71, 0x3F, 0x61, 0xBD, 0xAA, 0x9C, 0x40, 0x3C, - 0x19, 0xB3, 0x8A, 0x4E, 0xEF, 0x96, 0x1A, 0x7D, 0x97, 0x52, 0xDA, 0x68, 0x83, 0x42, 0x3B, 0xB2, - 0xD9, 0x9D, 0x5C, 0x67, 0x6F, 0x04, 0xEA, 0xCC, 0x29, 0xD1, 0xCC, 0xEF, 0xE3, 0xF1, 0x72, 0xBD, - 0xE6, 0x53, 0x87, 0x6C, 0xA4, 0xDA, 0x69, 0x67, 0xED, 0x28, 0xC7, 0x72, 0x5F, 0xA8, 0x75, 0x3E, - 0x33, 0xA4, 0xAE, 0xD9, 0xD6, 0x78, 0xBC, 0xF2, 0xFB, 0xB4, 0xE3, 0xDE, 0x29, 0xEA, 0x6D, 0x32, - 0x93, 0x8E, 0xAF, 0x5A, 0x1A, 0x5E, 0xAD, 0xD9, 0x63, 0x59, 0x4A, 0x1D, 0x14, 0x47, 0x19, 0xE9, - 0x1D, 0x62, 0x99, 0xB4, 0x9C, 0x84, 0x1F, 0x1D, 0x5C, 0x1C, 0xD3, 0x68, 0x01, 0x2D, 0x76, 0x87, - 0x06, 0x18, 0xF8, 0x7F, 0xE0, 0x05, 0xAA, 0x69, 0x3E, 0xA1, 0xC2, 0x69, 0xF9, 0x61, 0x25, 0x1C, - 0x2C, 0xED, 0xA7, 0xCF, 0xF4, 0x87, 0x1E, 0x50, 0x18, 0xC4, 0xA9, 0x9A, 0x1A, 0x45, 0x38, 0xE9, - 0x4C, 0x0F, 0x5C, 0x72, 0x81, 0x92, 0x2F, 0xC0, 0x37, 0xC6, 0xBD, 0x2B, 0xAB, 0x79, 0x1D, 0x8F, - 0xED, 0x40, 0x44, 0x7D, 0xAA, 0xBA, 0x2E, 0x2E, 0xF0, 0x3E, 0x1F, 0x9F, 0x87, 0x77, 0x28, 0x30, - 0x7F, 0x97, 0xDC, 0xA7, 0x06, 0xC6, 0x77, 0x74, 0x23, 0x51, 0x31, 0xA4, 0x00, 0xB8, 0xFE, 0xD8, - 0xC6, 0xFC, 0x45, 0xA7, 0xDE, 0x21, 0xBB, 0xB3, 0x5D, 0x6D, 0xB4, 0xD5, 0x6E, 0xBF, 0x03, 0x50, - 0xB3, 0xF3, 0xBF, 0xFD, 0x75, 0x6B, 0xB7, 0x83, 0x7F, 0x5D, 0x00, 0xF4, 0x7C, 0x60, 0xC9, 0x9E, - 0x6A, 0x68, 0x5B, 0xFB, 0xEF, 0x27, 0x8F, 0x44, 0xE5, 0x00, 0xF6, 0xD0, 0x49, 0x3C, 0x85, 0x8F, - 0xEF, 0x14, 0xF8, 0xF8, 0x92, 0xE2, 0x13, 0x24, 0x16, 0xD7, 0x74, 0xBB, 0xD0, 0xC8, 0xA6, 0xD8, - 0x72, 0xF7, 0x09, 0xA9, 0x4D, 0x57, 0x1E, 0xB1, 0x50, 0xC8, 0x8C, 0x3E, 0x73, 0xA4, 0xB6, 0xDF, - 0x57, 0xC3, 0x86, 0xC2, 0xC1, 0xAA, 0x32, 0x20, 0xD1, 0x8E, 0x6D, 0xA9, 0xAD, 0x6F, 0x2D, 0xB5, - 0x95, 0x0B, 0xFD, 0x1E, 0x1E, 0x34, 0xA2, 0x4E, 0xEE, 0x5B, 0xE0, 0x47, 0xCF, 0x70, 0xBD, 0x2F, - 0x18, 0x08, 0x99, 0xA0, 0x44, 0x29, 0x78, 0xC9, 0x2F, 0x80, 0x4A, 0xBC, 0xB1, 0x38, 0x08, 0x91, - 0x22, 0xD1, 0xC8, 0x6B, 0x58, 0x9A, 0x19, 0x20, 0x17, 0xC0, 0x62, 0x3F, 0x16, 0x7A, 0x76, 0x78, - 0x2D, 0x76, 0x63, 0x23, 0x6B, 0xA0, 0x6A, 0x5B, 0xAA, 0xC9, 0x8E, 0x6F, 0x7B, 0x58, 0xCB, 0x22, - 0x30, 0x29, 0x7F, 0x58, 0xD8, 0x20, 0x1E, 0x67, 0xD4, 0x3A, 0x18, 0xBF, 0x92, 0x71, 0x29, 0x32, - 0x8E, 0xD0, 0xAF, 0x0A, 0x01, 0x87, 0x8D, 0x9E, 0x97, 0x74, 0x33, 0x54, 0xF3, 0x2C, 0xDD, 0xBC, - 0xFF, 0x04, 0xC2, 0xD5, 0x78, 0xD3, 0xEF, 0xFC, 0xC4, 0x2A, 0xE6, 0xD2, 0xBE, 0x13, 0x4D, 0x67, - 0x41, 0x9C, 0x80, 0xCF, 0x94, 0xD6, 0xED, 0x89, 0xA6, 0xCF, 0x7E, 0x7F, 0x97, 0xB3, 0x84, 0x39, - 0xD5, 0xED, 0xC0, 0x31, 0x6D, 0x55, 0xBF, 0xE1, 0x8F, 0x17, 0x86, 0x3B, 0xC6, 0xCA, 0xAC, 0x67, - 0xC6, 0x43, 0x99, 0x02, 0x97, 0xA5, 0xD4, 0x9C, 0x99, 0xCE, 0x1B, 0x47, 0x12, 0xCA, 0xE1, 0x83, - 0x82, 0xA4, 0xA3, 0xC4, 0xA0, 0x28, 0xA4, 0xC3, 0xFF, 0x16, 0x36, 0xF9, 0x1B, 0x77, 0x91, 0x2B, - 0x7E, 0x75, 0x86, 0xAE, 0x0A, 0x4A, 0x4B, 0x66, 0xA0, 0xC3, 0x83, 0xD2, 0x52, 0xE6, 0xB1, 0xA4, - 0x67, 0x1F, 0x77, 0x39, 0x04, 0x9D, 0xE7, 0xD2, 0x7A, 0x8A, 0x70, 0x89, 0x03, 0x61, 0x2E, 0xB7, - 0xD6, 0xC8, 0xEA, 0xA7, 0x4D, 0x75, 0x87, 0x36, 0x3E, 0x1A, 0x82, 0x6E, 0x0B, 0xE1, 0x8B, 0x08, - 0xB8, 0x13, 0x8C, 0x5B, 0x91, 0x62, 0x27, 0xA6, 0xD1, 0x77, 0x54, 0xF7, 0xDB, 0x45, 0x40, 0xF7, - 0x91, 0x1E, 0xE7, 0x74, 0xB7, 0x09, 0xB3, 0x1A, 0xC8, 0x59, 0x91, 0x9C, 0x1B, 0x55, 0xD2, 0x88, - 0x6E, 0x38, 0x85, 0xA3, 0xCC, 0x5A, 0xE9, 0x74, 0x31, 0xC6, 0x1F, 0x4E, 0x3E, 0xDC, 0x4B, 0xF4, - 0xF5, 0x15, 0x3C, 0xFE, 0x79, 0x9D, 0xFB, 0x6F, 0x4F, 0x27, 0xA4, 0x25, 0x8C, 0x32, 0x27, 0xDC, - 0x57, 0x63, 0x18, 0xB0, 0x1A, 0xAF, 0xFD, 0xF8, 0x34, 0x56, 0x2C, 0x5C, 0xD1, 0x7A, 0x23, 0xDC, - 0x42, 0xAE, 0xAF, 0x1A, 0x96, 0x27, 0x2F, 0xC2, 0xF1, 0xBA, 0x8F, 0x0D, 0xB8, 0xEA, 0x07, 0x78, - 0xC9, 0x0E, 0xD4, 0xC0, 0xC6, 0xEA, 0x13, 0xB3, 0x6C, 0x72, 0xCC, 0x07, 0xC5, 0x0A, 0xA6, 0x8E, - 0xC2, 0x95, 0x8F, 0x37, 0xEE, 0xA0, 0x51, 0x71, 0x3C, 0x46, 0x08, 0x25, 0x07, 0x06, 0x07, 0xE9, - 0x0A, 0xB3, 0x0A, 0xAF, 0xBB, 0xEF, 0xD5, 0xF3, 0xE2, 0xDF, 0x71, 0xE0, 0xDB, 0xE1, 0xD6, 0x7F, - 0x75, 0x60, 0x33, 0x79, 0x64, 0x2D, 0xC5, 0xAF, 0xB0, 0x5E, 0xB5, 0x16, 0x61, 0x63, 0x71, 0xD5, - 0x32, 0xEA, 0x61, 0x65, 0xB1, 0x26, 0x69, 0x93, 0x5F, 0x31, 0xF6, 0x66, 0xE5, 0x80, 0x70, 0xB8, - 0x6B, 0xD8, 0xE8, 0x3B, 0x89, 0x06, 0x07, 0x2D, 0xE2, 0xEE, 0x71, 0x3E, 0xDA, 0x62, 0xD0, 0x58, - 0xA5, 0x47, 0x8E, 0x6B, 0xEB, 0x81, 0xF0, 0x2B, 0x79, 0x10, 0xA7, 0x63, 0x3A, 0xB7, 0xDD, 0xC6, - 0x8B, 0xF0, 0xD0, 0x67, 0x04, 0x8D, 0x6D, 0x22, 0x91, 0xB1, 0x1A, 0xEE, 0x14, 0x8E, 0xB6, 0xD9, - 0xF8, 0x9E, 0xDC, 0x5C, 0x5A, 0x54, 0x72, 0x87, 0x17, 0x29, 0x0D, 0x3E, 0x97, 0xCA, 0x9B, 0xAA, - 0xFA, 0xC6, 0x10, 0x8F, 0x4E, 0x94, 0x6B, 0xC3, 0x0A, 0x00, 0xF1, 0xCB, 0xD5, 0x97, 0xCC, 0xF1, - 0x7E, 0x12, 0x69, 0x2E, 0xDE, 0xCD, 0x28, 0xCD, 0xB2, 0xFF, 0x98, 0xF7, 0x38, 0x0C, 0xEA, 0x1D, - 0x3E, 0x73, 0x75, 0x4C, 0xC4, 0xDF, 0x88, 0x49, 0x44, 0x08, 0x1B, 0xD0, 0x3E, 0x21, 0xDE, 0x46, - 0x94, 0x31, 0x93, 0x4F, 0x3B, 0x95, 0x20, 0x98, 0x3A, 0xF1, 0xF2, 0x25, 0x7F, 0xA9, 0xB1, 0x5C, - 0xF5, 0x08, 0xDD, 0x3A, 0x38, 0x6D, 0x73, 0x42, 0x4B, 0xDE, 0x05, 0xC0, 0x6D, 0xB5, 0x61, 0x3D, - 0x4F, 0x6F, 0x37, 0xAF, 0x70, 0x66, 0xC9, 0x52, 0xB2, 0xA5, 0x3D, 0x67, 0x11, 0x9D, 0xBC, 0x31, - 0x70, 0x00, 0xA9, 0x1E, 0x67, 0xA1, 0x68, 0x89, 0x21, 0x9D, 0xDC, 0x1E, 0xE6, 0x55, 0x9A, 0xCB, - 0xF8, 0x1B, 0x57, 0xF7, 0xAC, 0x8D, 0x2E, 0xF4, 0xB3, 0x8D, 0x5C, 0xAA, 0x69, 0x0C, 0x2D, 0xE0, - 0x14, 0x64, 0xB0, 0x13, 0xD0, 0x81, 0xC7, 0x9F, 0xB8, 0x9F, 0x90, 0xE9, 0xCB, 0x07, 0x54, 0x15, - 0x2A, 0x0C, 0xD3, 0x5D, 0x97, 0x88, 0x5F, 0x2E, 0xA9, 0x3B, 0x0C, 0x13, 0x3D, 0xA3, 0xE6, 0x20, - 0xB8, 0x22, 0x8A, 0xEA, 0x0F, 0xDD, 0x56, 0x7B, 0xB7, 0xD5, 0xDE, 0x2B, 0xA3, 0x35, 0x08, 0x58, - 0x1C, 0x7D, 0x80, 0x83, 0x67, 0x48, 0x31, 0xC3, 0x71, 0x19, 0x59, 0x74, 0xD9, 0x93, 0x5F, 0x9D, - 0xA8, 0x6E, 0x74, 0xF8, 0xB6, 0x3B, 0x0D, 0xA0, 0xCC, 0xEF, 0xF0, 0x87, 0xA2, 0x14, 0x73, 0x0B, - 0x09, 0xD1, 0x47, 0x43, 0xF7, 0x47, 0x87, 0x5D, 0x45, 0xA1, 0x88, 0x70, 0x40, 0x11, 0xD9, 0x71, - 0x29, 0x83, 0x4D, 0xFA, 0x9C, 0x72, 0x22, 0xF5, 0xBA, 0xEF, 0xFE, 0x6B, 0x81, 0xE9, 0x46, 0xAE, - 0xBD, 0x2E, 0xC3, 0x6B, 0x19, 0xF5, 0x7A, 0x5A, 0x51, 0x2C, 0x99, 0x6E, 0x6E, 0x60, 0x98, 0x80, - 0x3D, 0xA2, 0x26, 0xC4, 0x3D, 0x30, 0x29, 0xFA, 0x48, 0xE6, 0x8C, 0xE0, 0x7E, 0x6C, 0xF8, 0x21, - 0x1A, 0x5C, 0xD0, 0x73, 0xDB, 0xD2, 0xC8, 0x2B, 0x2E, 0x0E, 0x33, 0xD4, 0xDE, 0x7F, 0x56, 0x0D, - 0x1F, 0x63, 0x26, 0x77, 0xB2, 0x07, 0x15, 0x2F, 0xB2, 0x93, 0xCB, 0x9B, 0x39, 0xBC, 0x3A, 0x6B, - 0xF3, 0x2C, 0x0C, 0x31, 0x19, 0xCE, 0x8A, 0xC0, 0x32, 0xFC, 0x37, 0xDE, 0xE4, 0x60, 0xB8, 0x7F, - 0x62, 0xC2, 0x14, 0x41, 0x57, 0x30, 0x0C, 0x60, 0x81, 0xF4, 0x83, 0xF0, 0x98, 0x5C, 0x0B, 0x45, - 0x09, 0x37, 0x99, 0x33, 0x02, 0xDA, 0xC5, 0x08, 0xBC, 0xDE, 0xE9, 0xAA, 0x5D, 0xFE, 0xB2, 0x5D, - 0x8B, 0xA6, 0xD1, 0x19, 0x57, 0x53, 0x35, 0xE0, 0x34, 0x0B, 0x3B, 0x53, 0xD9, 0xDF, 0x24, 0x32, - 0x4F, 0xF5, 0xFC, 0xBE, 0x8F, 0xA2, 0xD3, 0x4C, 0x6D, 0x93, 0x42, 0xF3, 0x10, 0x49, 0x3B, 0x51, - 0x07, 0x91, 0xF5, 0xE7, 0x12, 0xF6, 0x07, 0x23, 0x60, 0xE8, 0x69, 0xA5, 0xD2, 0x26, 0x93, 0xBE, - 0x92, 0x73, 0x5B, 0xB4, 0x9C, 0x89, 0xD2, 0x38, 0xBA, 0xB5, 0x29, 0xE5, 0x5C, 0xC5, 0x8A, 0x26, - 0xED, 0xC6, 0xD1, 0x89, 0xEA, 0xF1, 0xCA, 0xED, 0x3A, 0x98, 0x90, 0xB1, 0x7A, 0x01, 0x95, 0xAE, - 0x18, 0x0E, 0xB3, 0x38, 0xAE, 0x47, 0x11, 0x95, 0x5E, 0x20, 0x5C, 0x6B, 0x85, 0x85, 0x14, 0x83, - 0x5D, 0xC5, 0x55, 0xAA, 0x18, 0x1D, 0xA8, 0x89, 0x5C, 0x42, 0xC2, 0xCC, 0x0F, 0x3D, 0xCA, 0xFC, - 0xF0, 0xC5, 0x42, 0xEA, 0x22, 0xBF, 0xB4, 0xD6, 0xDA, 0x27, 0xB2, 0x31, 0xED, 0xE1, 0x9D, 0xDD, - 0x3F, 0x3B, 0x55, 0x33, 0xAB, 0x11, 0xAD, 0x20, 0x40, 0x7A, 0x08, 0x87, 0xFC, 0x10, 0x63, 0xA4, - 0x87, 0x78, 0x52, 0xF7, 0xCF, 0x18, 0x4E, 0x67, 0x35, 0xD1, 0xD2, 0x72, 0xE8, 0xD5, 0x65, 0x0A, - 0x55, 0x41, 0x6E, 0xD7, 0x5C, 0x00, 0x39, 0x59, 0xB0, 0x19, 0x99, 0x06, 0x7D, 0xC2, 0x25, 0xCA, - 0x0B, 0x1A, 0xD5, 0xE7, 0x8E, 0x14, 0x59, 0xD8, 0xA1, 0x61, 0x9A, 0xA3, 0xD1, 0xC6, 0xC5, 0x40, - 0x27, 0x40, 0x5E, 0xA4, 0xA8, 0x96, 0xB7, 0xFB, 0x94, 0xD5, 0x52, 0xE3, 0x3C, 0x1B, 0xA4, 0x34, - 0x98, 0x07, 0x86, 0xBA, 0x35, 0xE6, 0xD2, 0x37, 0xD5, 0xEF, 0x4C, 0xAE, 0xA3, 0x50, 0xCC, 0xC3, - 0x41, 0xD8, 0x16, 0xE8, 0x6A, 0x6F, 0x0F, 0xAB, 0x19, 0x1E, 0x16, 0xD7, 0x45, 0x43, 0x7F, 0x24, - 0xF4, 0x0F, 0x41, 0xA6, 0x05, 0xAB, 0x46, 0x6C, 0x62, 0x18, 0x9E, 0x41, 0x86, 0x13, 0x6D, 0x64, - 0xF0, 0x07, 0x44, 0x3C, 0x53, 0x2C, 0x46, 0xAA, 0x9F, 0x9C, 0x7C, 0x30, 0x26, 0x7E, 0x21, 0x7C, - 0x10, 0x10, 0xDC, 0x98, 0x89, 0x51, 0x36, 0xF8, 0x9E, 0x69, 0xC3, 0x0F, 0x10, 0x13, 0xC7, 0xDB, - 0x14, 0xE6, 0x69, 0xE1, 0x9C, 0xB6, 0xA9, 0xC2, 0x3C, 0xA8, 0xBA, 0x5E, 0xE0, 0x3E, 0xF0, 0x27, - 0x4A, 0x63, 0xAB, 0x42, 0x67, 0x2E, 0x5A, 0x2C, 0xE3, 0x17, 0xC3, 0x30, 0xFA, 0xB4, 0x9A, 0x2A, - 0x55, 0xD9, 0x58, 0x70, 0x28, 0xB6, 0xEE, 0x1C, 0x1C, 0x4C, 0xBE, 0x2A, 0xA9, 0xC2, 0x2E, 0x4D, - 0x7D, 0x2D, 0x67, 0xE3, 0x29, 0x6F, 0xD9, 0xAB, 0xAC, 0xB2, 0xC6, 0x70, 0xB6, 0x94, 0x6E, 0x30, - 0x79, 0x7F, 0x65, 0x21, 0xD4, 0xF3, 0x93, 0xA2, 0x70, 0x5F, 0x58, 0x84, 0x18, 0x0B, 0x37, 0x10, - 0xF5, 0x00, 0xE9, 0x26, 0x21, 0xE9, 0x71, 0xA9, 0xE4, 0x06, 0x94, 0x93, 0xC4, 0xF9, 0x24, 0xC5, - 0x09, 0xCB, 0x26, 0x52, 0x63, 0xC8, 0xE7, 0x31, 0xE6, 0x07, 0x13, 0xE2, 0xA7, 0x11, 0x1E, 0x7D, - 0x47, 0xD1, 0xE5, 0x94, 0x2C, 0xC3, 0xA4, 0x53, 0x41, 0x66, 0xCC, 0x55, 0x05, 0x35, 0x0A, 0xAA, - 0x7B, 0xE9, 0x84, 0xB5, 0x44, 0xCA, 0x92, 0x28, 0x58, 0x81, 0xB6, 0x44, 0x8B, 0xA5, 0x52, 0x97, - 0x14, 0xD1, 0x84, 0x0E, 0x2B, 0x87, 0x28, 0x41, 0x5F, 0x31, 0xC2, 0x2C, 0x61, 0xF8, 0x9D, 0xD1, - 0x68, 0xA6, 0x06, 0x8C, 0xD1, 0x76, 0xC2, 0x28, 0x43, 0x02, 0x1B, 0xA9, 0x99, 0xA8, 0xBD, 0x1C, - 0x0A, 0x14, 0x29, 0x6D, 0x68, 0x8C, 0x2D, 0xED, 0x46, 0x1D, 0xE7, 0xDC, 0x74, 0xF7, 0x2F, 0xCE, - 0x7F, 0x87, 0x91, 0x5A, 0xC1, 0xFD, 0xF7, 0x5A, 0xED, 0x87, 0x0B, 0x58, 0xDB, 0x16, 0xE3, 0x7E, - 0x8B, 0x64, 0x05, 0xCC, 0xB7, 0xAE, 0x91, 0x33, 0xE5, 0x0D, 0x7F, 0x04, 0x70, 0xD5, 0x60, 0x57, - 0x9B, 0xB1, 0xAF, 0xC5, 0xBA, 0x47, 0xE3, 0x5A, 0x1F, 0x3F, 0xD2, 0x95, 0x3C, 0x3C, 0x28, 0x97, - 0x5A, 0x6A, 0x79, 0x52, 0xCE, 0xA9, 0x69, 0x63, 0x72, 0x3E, 0xB2, 0x75, 0x04, 0xAE, 0x8B, 0x11, - 0x26, 0xC8, 0x5D, 0xD1, 0xEF, 0x8C, 0xA6, 0xED, 0x49, 0x96, 0x6B, 0x5B, 0x7C, 0x43, 0x58, 0x5E, - 0xBD, 0xD8, 0x19, 0x69, 0x6D, 0xED, 0x29, 0x22, 0xAE, 0xED, 0xAE, 0xF4, 0xB6, 0x17, 0xA9, 0x53, - 0xE1, 0x1D, 0xE9, 0x6D, 0x2F, 0x94, 0x93, 0x57, 0x76, 0xE9, 0x39, 0x99, 0xC5, 0xF3, 0xA5, 0xD7, - 0x8B, 0x5F, 0x7B, 0x22, 0x42, 0x86, 0x4E, 0x9D, 0xB7, 0x7C, 0xC0, 0x5D, 0x4C, 0x76, 0xCF, 0x7A, - 0xB6, 0x67, 0xC8, 0xDC, 0x44, 0xF6, 0x58, 0x64, 0xBB, 0x6A, 0x2B, 0xCA, 0xDE, 0x0E, 0xFC, 0xD8, - 0x8F, 0x24, 0x82, 0xC8, 0x5D, 0x5A, 0x04, 0xF7, 0x0E, 0x5F, 0xCC, 0xDD, 0x65, 0xB4, 0x47, 0x6B, - 0x71, 0x5D, 0x39, 0x99, 0x0E, 0xA5, 0x41, 0x01, 0xA4, 0x9A, 0x4B, 0x0E, 0x85, 0x6E, 0x4A, 0x71, - 0x15, 0x39, 0x16, 0x0B, 0x07, 0x63, 0x5B, 0xDE, 0xDB, 0x35, 0xB8, 0xAA, 0x44, 0x5A, 0x0D, 0xD5, - 0xC0, 0xE9, 0xCB, 0xC9, 0x1C, 0xFC, 0x4D, 0x5A, 0x29, 0xD0, 0x12, 0x66, 0xC8, 0x75, 0xC9, 0x7A, - 0x73, 0xD3, 0xD9, 0x1D, 0x5E, 0xAF, 0x22, 0xA7, 0xA4, 0xCF, 0x14, 0xF4, 0x2B, 0x7D, 0x09, 0x39, - 0xDB, 0x76, 0xF9, 0xD7, 0x8F, 0xB5, 0xDA, 0x7F, 0xAE, 0x29, 0x7C, 0xA3, 0x06, 0x2B, 0x90, 0x3C, - 0xDE, 0xA0, 0x99, 0xF0, 0xCF, 0x5D, 0xCE, 0x19, 0x27, 0x27, 0x7F, 0x7B, 0x79, 0x73, 0xFE, 0x4B, - 0x74, 0xCA, 0xD1, 0xA7, 0x55, 0x9F, 0x73, 0x89, 0x99, 0xAC, 0xC7, 0x49, 0x27, 0xE0, 0x90, 0xA8, - 0x21, 0x29, 0xB9, 0x82, 0x30, 0xEA, 0x3E, 0x1A, 0xFE, 0x48, 0x66, 0x92, 0x05, 0x51, 0xCD, 0x8A, - 0x18, 0x05, 0xC9, 0x68, 0xA4, 0x46, 0xE8, 0xD2, 0x2F, 0xF9, 0xA5, 0x1C, 0x74, 0xF1, 0x4D, 0x5A, - 0xF8, 0xA8, 0x23, 0x3F, 0x61, 0xA0, 0xE6, 0xEF, 0xA8, 0x31, 0x9D, 0x49, 0x48, 0xA5, 0x5E, 0x5A, - 0x95, 0x71, 0x82, 0x9B, 0x3E, 0x04, 0x69, 0x8E, 0xF1, 0x9E, 0xE7, 0xAA, 0x37, 0x43, 0xBD, 0x94, - 0x62, 0xBF, 0x89, 0xFD, 0x3E, 0xAC, 0xC0, 0x65, 0x13, 0xF7, 0x65, 0x29, 0xB3, 0x46, 0x30, 0x65, - 0x2F, 0xA6, 0xEC, 0xFD, 0x59, 0xFE, 0x5D, 0x5A, 0x9B, 0x7D, 0xB6, 0x83, 0x12, 0x97, 0x69, 0xF9, - 0x17, 0x6B, 0xFB, 0xD4, 0x8B, 0xB7, 0x50, 0x37, 0x98, 0xB8, 0x63, 0xB7, 0x86, 0x7E, 0x00, 0x5D, - 0xDA, 0x7B, 0x4C, 0xBA, 0xB0, 0x94, 0xEF, 0x29, 0xFF, 0x1A, 0x6E, 0xF9, 0x4A, 0x5F, 0x36, 0xCB, - 0x49, 0xA6, 0x96, 0x0A, 0x5D, 0xA5, 0x76, 0xD8, 0x08, 0x41, 0x15, 0xC6, 0x1E, 0xAA, 0xD2, 0xC1, - 0xCA, 0x24, 0xE3, 0x9C, 0xED, 0x70, 0x2B, 0x71, 0xD1, 0x12, 0x42, 0x76, 0x93, 0xF4, 0xC5, 0x0A, - 0x7C, 0xE4, 0xCB, 0x3D, 0x16, 0x3A, 0x27, 0xFA, 0x08, 0xA5, 0x87, 0x7A, 0xD9, 0x09, 0x0C, 0x90, - 0x23, 0x51, 0xD7, 0xC9, 0x4D, 0xEC, 0xC9, 0x52, 0xA2, 0x63, 0x65, 0x31, 0xA6, 0x92, 0x98, 0x7B, - 0xC4, 0x53, 0xD2, 0x56, 0x54, 0x13, 0x4B, 0xF1, 0x16, 0x65, 0x27, 0x9D, 0x85, 0x39, 0xC9, 0xDE, - 0xE2, 0x3C, 0x44, 0x59, 0xAC, 0x8B, 0x5D, 0x64, 0x43, 0x8B, 0x75, 0xB1, 0xD7, 0x38, 0xEA, 0x2E, - 0x38, 0x0B, 0xCC, 0xC2, 0xA3, 0xBC, 0x08, 0x2E, 0xC8, 0x1F, 0x38, 0x30, 0x9B, 0x94, 0x14, 0x7B, - 0x89, 0x94, 0xAC, 0x2F, 0xC7, 0x1C, 0x56, 0x93, 0xD3, 0x9A, 0xF0, 0x54, 0x04, 0x5C, 0xF0, 0x6D, - 0xDB, 0x1F, 0x51, 0x06, 0xEA, 0x3B, 0x10, 0xC9, 0x2B, 0x73, 0xC7, 0x38, 0x47, 0x9C, 0xED, 0xAE, - 0x71, 0x74, 0x12, 0x3E, 0x63, 0x3D, 0xD7, 0xF6, 0x6D, 0xE0, 0x7F, 0x95, 0xBC, 0x85, 0x52, 0xBA, - 0xCC, 0x98, 0x79, 0x0D, 0xFE, 0x43, 0xFD, 0x5E, 0x6F, 0x2E, 0xEF, 0xA1, 0xAB, 0xF3, 0x79, 0x9C, - 0x87, 0x60, 0x34, 0xF6, 0x4F, 0x6C, 0x9E, 0xC6, 0xB0, 0x17, 0x5F, 0x06, 0x83, 0xF5, 0xF0, 0x1E, - 0x3A, 0x8D, 0xEA, 0xC3, 0x60, 0x32, 0x7C, 0xB4, 0xAC, 0x9C, 0x62, 0xAF, 0x86, 0xC6, 0x26, 0x3B, - 0x2F, 0x12, 0xF0, 0x32, 0x2C, 0xEE, 0x87, 0x58, 0x40, 0xC2, 0xC8, 0x16, 0x2C, 0xFF, 0xED, 0x76, - 0xEC, 0xA5, 0x2B, 0xFB, 0xB1, 0x79, 0x6E, 0x71, 0x77, 0xF8, 0xC4, 0xB6, 0x00, 0x28, 0x6F, 0x29, - 0x83, 0xBE, 0x1F, 0xB8, 0x56, 0xEC, 0x1D, 0x7B, 0x30, 0x88, 0xD1, 0x75, 0x04, 0xC0, 0xF5, 0x77, - 0x41, 0xBA, 0xE7, 0xDC, 0xA1, 0xF2, 0xDA, 0x22, 0x7A, 0x79, 0x59, 0xD5, 0xD9, 0x4E, 0x68, 0x98, - 0x58, 0xFC, 0x8E, 0x6E, 0xE0, 0x6F, 0xF1, 0x78, 0xD9, 0xB5, 0xDA, 0xC2, 0xC1, 0x97, 0x9D, 0x7E, - 0x52, 0xD6, 0x69, 0x97, 0x25, 0x19, 0xEE, 0x83, 0x3F, 0xFF, 0xC4, 0x90, 0x01, 0x9B, 0x32, 0xA8, - 0x32, 0x35, 0xA0, 0xF2, 0x0A, 0x9C, 0xEB, 0xF7, 0x2A, 0x66, 0x92, 0x14, 0x86, 0xE5, 0xC0, 0xC3, - 0x2C, 0x20, 0x15, 0xBC, 0x8B, 0xD6, 0x03, 0x6B, 0xC6, 0x5C, 0xF5, 0x02, 0x97, 0xA0, 0xD3, 0xD7, - 0x54, 0x73, 0x31, 0xE6, 0x3C, 0xDD, 0x59, 0xE3, 0xE8, 0x7A, 0xF2, 0x84, 0xD1, 0xA3, 0x4A, 0x9C, - 0x79, 0xA6, 0xBF, 0xD4, 0x29, 0xD7, 0xC0, 0x95, 0xAF, 0x39, 0x6C, 0xB5, 0x37, 0x0F, 0x63, 0xBE, - 0xE0, 0xDC, 0xDF, 0xB9, 0x44, 0xBB, 0x91, 0xB7, 0x1E, 0xCC, 0xF2, 0x4C, 0xDC, 0xFB, 0xCA, 0x4A, - 0x5D, 0x58, 0x0E, 0x24, 0xA0, 0x32, 0x5C, 0x86, 0xC5, 0xC6, 0xB4, 0x4A, 0xE4, 0x79, 0x80, 0xBC, - 0xBE, 0xF4, 0x90, 0xD0, 0x6D, 0x50, 0xE8, 0x30, 0xD6, 0x51, 0x1D, 0x0C, 0x10, 0xF2, 0x54, 0x4D, - 0x58, 0x64, 0x7D, 0x02, 0xF6, 0x68, 0x99, 0x4F, 0x13, 0x3A, 0x90, 0xC1, 0x35, 0xD4, 0xAB, 0xA8, - 0xDF, 0x25, 0x2F, 0x99, 0xE3, 0x92, 0x90, 0x00, 0xE5, 0x26, 0x24, 0x41, 0xAD, 0x9D, 0x35, 0x62, - 0x30, 0x19, 0xF9, 0xAB, 0xA6, 0x44, 0x37, 0x9E, 0x09, 0xD8, 0xC1, 0xD7, 0x78, 0x8B, 0xBA, 0x6C, - 0x3E, 0x19, 0x9B, 0xC9, 0x33, 0x95, 0xA7, 0x4E, 0x84, 0x26, 0xBA, 0x62, 0xD5, 0x13, 0x9F, 0x9C, - 0x11, 0x37, 0x1D, 0x74, 0xCA, 0xA1, 0x84, 0xBA, 0x3A, 0x77, 0x4C, 0xFB, 0x49, 0x38, 0xDD, 0xCB, - 0x2E, 0x0C, 0xCC, 0xE4, 0x0B, 0x24, 0x6E, 0xFB, 0x28, 0x83, 0x6B, 0x32, 0x03, 0xD2, 0x4C, 0x6E, - 0xAF, 0xB5, 0xE7, 0xAE, 0x53, 0x41, 0x86, 0xB4, 0x25, 0xB5, 0x94, 0xBB, 0xAC, 0x9A, 0x46, 0xC7, - 0xE5, 0xF7, 0x20, 0xDD, 0x84, 0xD1, 0x59, 0x35, 0x04, 0x07, 0xE6, 0x6A, 0x19, 0x72, 0xBF, 0xBD, - 0xC3, 0xD5, 0x9B, 0xD1, 0x27, 0xA1, 0x82, 0x72, 0x12, 0xB9, 0x21, 0x82, 0x94, 0x1B, 0xB5, 0x54, - 0x44, 0xE0, 0xE6, 0x26, 0xCA, 0x99, 0xF3, 0x3E, 0x2D, 0x89, 0x31, 0x85, 0xA9, 0x0F, 0x12, 0xAF, - 0xCF, 0x73, 0x7B, 0x36, 0xAF, 0x7E, 0xE9, 0x8D, 0x02, 0x1F, 0xCF, 0xFB, 0x1B, 0xFB, 0x74, 0x84, - 0x69, 0x60, 0x64, 0xE1, 0x0D, 0x39, 0x93, 0x53, 0xC9, 0x25, 0x05, 0xD1, 0xAD, 0xDE, 0x35, 0x3F, - 0x7F, 0x76, 0xA0, 0xA0, 0xC9, 0xEF, 0x45, 0x6A, 0x7F, 0x1F, 0x0B, 0x36, 0x21, 0x39, 0x0E, 0x0F, - 0x97, 0xEB, 0xB6, 0x5F, 0x0E, 0x68, 0xAB, 0xF4, 0xE7, 0x4F, 0x3D, 0x44, 0x48, 0x35, 0x03, 0x85, - 0x4C, 0x16, 0x3E, 0xC0, 0x5C, 0x57, 0x24, 0x88, 0x10, 0x94, 0x80, 0x64, 0x65, 0xD6, 0x75, 0x18, - 0xAD, 0xF0, 0x68, 0x41, 0xF1, 0x07, 0xDD, 0x46, 0x2D, 0xB4, 0xE4, 0x80, 0x04, 0x04, 0x5F, 0x93, - 0xE5, 0x1A, 0xC5, 0x76, 0x4A, 0xF7, 0x20, 0x6A, 0x00, 0x92, 0x34, 0x8F, 0xA3, 0xC6, 0x38, 0x45, - 0x52, 0x23, 0x2C, 0x71, 0xF6, 0x2C, 0x85, 0x19, 0x2C, 0x23, 0xAD, 0x64, 0x3E, 0x1A, 0x3C, 0xCB, - 0x41, 0x55, 0x40, 0x30, 0x8B, 0x9D, 0x5C, 0x78, 0x5B, 0x91, 0xBB, 0x6B, 0xE1, 0xE8, 0xCF, 0x70, - 0x70, 0x79, 0x11, 0x27, 0xC8, 0x39, 0xAF, 0x22, 0x82, 0xC8, 0x3A, 0xB2, 0xB2, 0x09, 0x25, 0x0C, - 0x8F, 0x99, 0xF8, 0x30, 0x2B, 0x6C, 0x2B, 0x2C, 0x71, 0xF9, 0x96, 0xEA, 0x7D, 0x28, 0xDB, 0xCA, - 0x81, 0xD2, 0xFA, 0xE1, 0x4E, 0xBA, 0x22, 0x1E, 0x5D, 0x74, 0xF4, 0xE5, 0xB7, 0x5F, 0xC2, 0x59, - 0xB8, 0x5A, 0xAD, 0xE6, 0x42, 0xD5, 0x7C, 0xDB, 0x9D, 0x64, 0xA2, 0x8F, 0x8A, 0x03, 0x8B, 0xE7, - 0xB1, 0x84, 0xF1, 0xCB, 0xD5, 0x69, 0xA6, 0xE7, 0x51, 0xE4, 0xAD, 0x51, 0x9F, 0x8E, 0x33, 0xBD, - 0x52, 0x41, 0x8B, 0xDC, 0xC5, 0xF4, 0xAF, 0x48, 0x7C, 0x74, 0x86, 0x80, 0x20, 0x89, 0xA1, 0x05, - 0x42, 0x2F, 0x76, 0xA3, 0xCA, 0x6E, 0x91, 0xF2, 0x2C, 0xAB, 0xF5, 0x90, 0x19, 0xC9, 0xF3, 0x6D, - 0xD8, 0x9E, 0xB0, 0x45, 0x8B, 0x1D, 0x43, 0x27, 0x22, 0x12, 0xC1, 0x42, 0x0F, 0x0F, 0x0C, 0x46, - 0x1E, 0xAB, 0x06, 0xE5, 0x28, 0xA2, 0x48, 0x86, 0xD4, 0x32, 0xC3, 0x93, 0x31, 0x96, 0x54, 0x52, - 0x78, 0x95, 0x2A, 0x54, 0x39, 0x8C, 0x6E, 0x54, 0xAD, 0xA8, 0x30, 0x98, 0xC6, 0x99, 0x45, 0xAB, - 0x28, 0x4C, 0x21, 0x61, 0xA2, 0x4C, 0x70, 0x54, 0x42, 0x61, 0x96, 0x32, 0x72, 0x0B, 0x45, 0x38, - 0x69, 0x53, 0xAD, 0x21, 0x6A, 0xBB, 0x5A, 0x51, 0x86, 0x73, 0x2C, 0x01, 0x6A, 0xF1, 0xE7, 0x2B, - 0xC9, 0xC0, 0xE5, 0x04, 0x96, 0x50, 0x90, 0xE1, 0x7C, 0xAA, 0xEB, 0x4A, 0x09, 0x21, 0xA7, 0x1A, - 0xCF, 0x0C, 0x59, 0x2E, 0xA5, 0xC7, 0x14, 0x78, 0xA7, 0x32, 0x47, 0x46, 0x6B, 0x7F, 0xEE, 0x6A, - 0x0D, 0x53, 0x8B, 0xAD, 0xB5, 0xDE, 0x5B, 0x4D, 0x87, 0x92, 0x9C, 0xE1, 0xD9, 0xE7, 0xD3, 0x1E, - 0x9C, 0x45, 0x21, 0x58, 0x03, 0x8C, 0x5A, 0xC0, 0x67, 0x4B, 0x3C, 0x86, 0xE2, 0x23, 0x4F, 0x38, - 0x83, 0x3E, 0xD2, 0x9C, 0x70, 0x1A, 0xC0, 0x0F, 0xB2, 0xCB, 0xD1, 0xAD, 0xE6, 0xB0, 0x8A, 0xEB, - 0x52, 0x11, 0x74, 0xE8, 0xC0, 0xC2, 0xCA, 0xBE, 0x38, 0xF7, 0x56, 0xA8, 0xC3, 0x20, 0xAF, 0xC2, - 0x87, 0xAA, 0x4C, 0x1A, 0x7E, 0xD9, 0x63, 0xC7, 0xBA, 0x8E, 0x07, 0xC3, 0x36, 0x3B, 0xBB, 0xE9, - 0x6F, 0xB3, 0x4F, 0xAA, 0xCF, 0x1F, 0xA5, 0x2D, 0xB9, 0x1F, 0xDC, 0x63, 0x4F, 0xD7, 0xAA, 0xF7, - 0x6D, 0x83, 0xAE, 0x39, 0xF2, 0x93, 0x56, 0xD0, 0xB2, 0x2F, 0x7B, 0x7D, 0x79, 0x10, 0x0B, 0xA4, - 0x0F, 0x81, 0xB6, 0x2C, 0x0D, 0x27, 0x44, 0xA3, 0xCB, 0x5E, 0x22, 0x99, 0xF5, 0xDE, 0x8C, 0xDE, - 0x72, 0x31, 0xB5, 0x29, 0xCF, 0xA0, 0x94, 0x20, 0xBA, 0x90, 0xF2, 0x20, 0xCF, 0xB8, 0x34, 0x94, - 0x22, 0x25, 0x64, 0x1A, 0x81, 0x5E, 0x52, 0x5E, 0xE9, 0xBD, 0x2A, 0x19, 0xA5, 0x71, 0xDE, 0x39, - 0xF9, 0xA4, 0x63, 0x9B, 0x5F, 0x2A, 0x42, 0x72, 0xF2, 0xFE, 0xEA, 0xB2, 0x48, 0xD7, 0x8A, 0xE5, - 0xC0, 0x47, 0x0A, 0xD0, 0x1C, 0xDE, 0x58, 0x67, 0xCC, 0xC6, 0x05, 0xBC, 0x22, 0x73, 0x2E, 0x32, - 0x17, 0x83, 0x68, 0x0A, 0x9B, 0xA1, 0xC1, 0x86, 0xA2, 0xB3, 0x3C, 0x11, 0x0B, 0x50, 0x5A, 0xBE, - 0xB5, 0xCE, 0x68, 0x1D, 0x2E, 0xE4, 0x15, 0xB5, 0x73, 0x51, 0xBB, 0x1C, 0x98, 0xA6, 0xD0, 0x5B, - 0x36, 0xDA, 0x50, 0x14, 0x17, 0x82, 0x5E, 0x01, 0x86, 0xC7, 0xA4, 0xC1, 0x75, 0xC6, 0x72, 0x4F, - 0x4C, 0x73, 0x0C, 0xD3, 0x7C, 0xC5, 0xF4, 0x7C, 0x4C, 0x97, 0xDB, 0x5E, 0x09, 0xD1, 0x45, 0x9B, - 0x35, 0x28, 0x4D, 0x93, 0x2D, 0xE6, 0xCF, 0x5B, 0x70, 0x3C, 0x5C, 0xE2, 0x8D, 0xEF, 0xA0, 0x4F, - 0x61, 0x01, 0x39, 0x44, 0xE8, 0x77, 0x73, 0xD7, 0x23, 0x1F, 0xC4, 0x3A, 0xAA, 0x85, 0x87, 0x08, - 0x3F, 0xD3, 0x79, 0xA4, 0x7F, 0x21, 0x0D, 0xB4, 0x3B, 0xDD, 0x4D, 0x2C, 0xCE, 0x5D, 0x06, 0x95, - 0xAB, 0x95, 0x6A, 0x99, 0xDE, 0xB1, 0x42, 0xBB, 0xFD, 0x54, 0x83, 0x25, 0x5F, 0x5A, 0x57, 0xB3, - 0xC6, 0xE1, 0x56, 0x3F, 0x97, 0x21, 0xCE, 0xF2, 0x9D, 0x25, 0xD8, 0xE0, 0x60, 0x45, 0x73, 0x99, - 0xDF, 0x26, 0xED, 0xE6, 0xB4, 0xBC, 0x4D, 0x40, 0x29, 0x8D, 0x6E, 0xD2, 0xE6, 0x86, 0xCB, 0x7C, - 0x6E, 0x73, 0xDB, 0x64, 0x71, 0xB5, 0x5A, 0xDA, 0xAA, 0x30, 0x3A, 0x0B, 0xB1, 0xDF, 0x34, 0xCF, - 0xBF, 0x3B, 0x00, 0x3E, 0xAB, 0x88, 0xD1, 0xE1, 0xAB, 0x2C, 0x7C, 0xF7, 0x70, 0x45, 0xEE, 0x01, - 0xE2, 0x6A, 0xDF, 0xD2, 0xC9, 0x03, 0xDC, 0x0B, 0x73, 0xB0, 0x19, 0xE3, 0x60, 0x3C, 0x09, 0x7E, - 0x0D, 0x73, 0x96, 0x7B, 0xC2, 0x4A, 0x8E, 0x7E, 0xBA, 0x61, 0x0A, 0xC0, 0x16, 0x3B, 0x6F, 0x0D, - 0x5B, 0xF2, 0x2E, 0x55, 0xF0, 0x4D, 0xB2, 0xEB, 0x61, 0x60, 0xFD, 0x3E, 0xDE, 0xC2, 0x78, 0x93, - 0x9B, 0x1A, 0xEC, 0x0A, 0x33, 0x3B, 0xFD, 0xAF, 0x7D, 0xF6, 0x91, 0xED, 0xEF, 0x7A, 0xAF, 0xAC, - 0x55, 0x92, 0x4A, 0x02, 0x47, 0x0A, 0x59, 0xEB, 0x54, 0x83, 0xFA, 0x59, 0x6B, 0xED, 0x24, 0xE0, - 0x72, 0xCD, 0xF0, 0xE2, 0x21, 0xAE, 0x19, 0xF8, 0x1F, 0xBE, 0xF7, 0x8C, 0xB8, 0xEF, 0x84, 0x73, - 0x08, 0xEB, 0xC3, 0xC9, 0xAC, 0xAA, 0x9A, 0x69, 0x6B, 0xDF, 0xF2, 0x90, 0xBD, 0xD9, 0x51, 0x26, - 0xE8, 0x3E, 0xE9, 0x85, 0xF0, 0x1D, 0xBF, 0xFB, 0xC8, 0xFE, 0xBD, 0x1D, 0xBC, 0xA2, 0x7C, 0x84, - 0xC1, 0x11, 0x4E, 0x94, 0xC2, 0xF7, 0xF0, 0xED, 0xF5, 0x47, 0xF6, 0x5B, 0xDB, 0xF6, 0xCF, 0xB8, - 0x59, 0x68, 0xC6, 0xC0, 0xF7, 0x18, 0xBD, 0xF8, 0x8C, 0xD8, 0xEE, 0xDB, 0x74, 0xD9, 0x6D, 0x07, - 0x96, 0xDE, 0xF4, 0x5D, 0xC3, 0x01, 0xB4, 0x46, 0xF7, 0x76, 0x19, 0x75, 0xE1, 0x46, 0xA9, 0x54, - 0x08, 0xFB, 0xD1, 0xCD, 0x2B, 0x88, 0x7B, 0xA3, 0x2B, 0xAF, 0xD8, 0x2C, 0xF1, 0x73, 0xB2, 0xE9, - 0x65, 0xB0, 0x39, 0x7A, 0x7B, 0x43, 0xB0, 0x19, 0x44, 0x40, 0x51, 0xD2, 0xA6, 0x14, 0x4A, 0x47, - 0x6F, 0xAF, 0x81, 0x04, 0xC3, 0x11, 0x98, 0x80, 0xC7, 0x26, 0xC8, 0xA6, 0x0F, 0xBC, 0x2C, 0x5E, - 0xB7, 0x15, 0xE5, 0x15, 0xB5, 0x13, 0xC8, 0x3A, 0xC1, 0x80, 0xD2, 0xF8, 0x1D, 0x35, 0xD9, 0x00, - 0x24, 0x0F, 0xF1, 0xE1, 0x52, 0x2F, 0xC2, 0xF0, 0x08, 0x73, 0x2E, 0xCF, 0x56, 0x8A, 0xDE, 0x1A, - 0xA6, 0x70, 0x27, 0xE7, 0x24, 0x63, 0x60, 0x48, 0x24, 0x9F, 0x42, 0xE3, 0x18, 0x02, 0x7F, 0xEA, - 0xF5, 0x63, 0xD9, 0x54, 0x31, 0x6B, 0xC1, 0x48, 0x75, 0x55, 0xAD, 0x20, 0x76, 0xE8, 0xE5, 0xE0, - 0x75, 0x81, 0x55, 0x6E, 0x6A, 0xCB, 0x4B, 0xA1, 0xF4, 0xE4, 0xFD, 0xB5, 0x32, 0x65, 0x50, 0xC2, - 0xE0, 0x6B, 0xD5, 0x52, 0xD1, 0x11, 0xB5, 0x16, 0x63, 0x86, 0x6D, 0x69, 0x51, 0xA1, 0x1A, 0xEC, - 0xFD, 0xCA, 0xF0, 0xA8, 0xF8, 0x88, 0xB8, 0xD2, 0x37, 0xB9, 0x1C, 0xAC, 0x31, 0x5F, 0xE5, 0xD9, - 0x0C, 0x7B, 0xC6, 0xB4, 0xD9, 0x23, 0xC3, 0xCC, 0x71, 0x11, 0x1F, 0x3F, 0xD5, 0xD0, 0x31, 0xD3, - 0x7F, 0x86, 0xE1, 0x23, 0xD1, 0x53, 0x39, 0x53, 0x47, 0x02, 0xD4, 0xD2, 0xCC, 0x11, 0x03, 0xC8, - 0xB3, 0x9B, 0x3B, 0xE2, 0x4B, 0x5A, 0xD8, 0xE0, 0x91, 0x2C, 0xB8, 0x94, 0x8E, 0xD4, 0xFD, 0x33, - 0xD6, 0x37, 0xFE, 0xC4, 0xA0, 0x53, 0xE9, 0xAA, 0xAB, 0xE3, 0xC7, 0xEC, 0x1C, 0xB9, 0x0A, 0xBB, - 0x3E, 0x41, 0x0A, 0x61, 0x3B, 0xEC, 0xC2, 0xE5, 0xF1, 0x76, 0xF8, 0xB1, 0xEF, 0x00, 0x6F, 0xCC, - 0x66, 0x88, 0x45, 0x9D, 0x96, 0x37, 0x67, 0x53, 0xC9, 0xC9, 0xE9, 0xDD, 0xBB, 0xC3, 0x87, 0x59, - 0xA7, 0x85, 0xEF, 0x4A, 0x78, 0xBC, 0x31, 0xF9, 0xC0, 0x7F, 0x93, 0xC3, 0x2F, 0xFC, 0xD1, 0x11, - 0xE6, 0x09, 0xFE, 0xB0, 0x03, 0x7F, 0xE4, 0xBE, 0x85, 0x90, 0x2A, 0x7A, 0x4B, 0x3F, 0x4A, 0x30, - 0xB5, 0x89, 0xE3, 0x54, 0x38, 0xF7, 0x3E, 0xC5, 0xBC, 0x1E, 0x9B, 0x69, 0x01, 0xE9, 0xD2, 0xE9, - 0xAA, 0xF0, 0x5A, 0x26, 0xF2, 0xB4, 0x8A, 0x03, 0x83, 0xC8, 0x11, 0xB3, 0xE7, 0xC2, 0x14, 0xB3, - 0x7C, 0xAA, 0x76, 0x7C, 0x77, 0x71, 0x70, 0xE9, 0x94, 0x38, 0xF9, 0xFC, 0x3B, 0x39, 0xCC, 0xFE, - 0x1E, 0xBA, 0x0A, 0xFD, 0xAE, 0xB4, 0xFC, 0xEF, 0x7E, 0xF6, 0xD8, 0x61, 0xDB, 0x3D, 0xDA, 0xFB, - 0xA2, 0xB7, 0x32, 0x80, 0x28, 0x82, 0xA0, 0x71, 0xD5, 0x97, 0x67, 0x02, 0xA4, 0xD9, 0x53, 0x29, - 0x06, 0x63, 0x06, 0xFC, 0x59, 0x9C, 0x41, 0xE4, 0x38, 0xD9, 0x4A, 0x88, 0xAE, 0x10, 0xD6, 0x9D, - 0x4E, 0x5B, 0xE9, 0xB6, 0x7F, 0x57, 0x3A, 0x4A, 0x5B, 0xD9, 0x17, 0x69, 0xAB, 0x8B, 0x00, 0x09, - 0x4D, 0xD8, 0x5F, 0x97, 0x05, 0xF0, 0x99, 0xF9, 0xBC, 0x68, 0x98, 0x77, 0x94, 0xF7, 0xE5, 0x60, - 0xBE, 0xAB, 0x1C, 0xAC, 0x02, 0xE6, 0x72, 0x3E, 0x6B, 0x09, 0x73, 0x78, 0x8A, 0xCC, 0xF9, 0x28, - 0x83, 0x93, 0x17, 0x6E, 0x92, 0x38, 0xC3, 0x0A, 0xB6, 0x29, 0xFF, 0x2A, 0xA7, 0x31, 0x91, 0x8A, - 0x62, 0x0B, 0x05, 0x15, 0x9E, 0xFB, 0xC4, 0x26, 0xC5, 0x5F, 0xC5, 0xD9, 0xC5, 0x4B, 0xEC, 0x63, - 0x1D, 0x6F, 0xCC, 0xB3, 0x16, 0x10, 0x4B, 0xB0, 0x9E, 0x19, 0xAD, 0x46, 0xFE, 0xBD, 0xC8, 0x7A, - 0x0A, 0xB6, 0x32, 0xFD, 0x92, 0x39, 0xDF, 0x65, 0xB9, 0x5C, 0x05, 0xBE, 0xCC, 0xEA, 0x7B, 0xF8, - 0x77, 0x7B, 0x72, 0x76, 0xB6, 0xE3, 0xE5, 0xF6, 0x44, 0x65, 0x3A, 0x14, 0xA0, 0x72, 0xCA, 0xEC, - 0x89, 0x82, 0x6F, 0x3F, 0x95, 0x56, 0x62, 0xD2, 0x2B, 0x34, 0x3A, 0x29, 0x35, 0x19, 0x95, 0x58, - 0x49, 0xC6, 0xC2, 0x92, 0x8B, 0xD9, 0xD5, 0x0F, 0xA5, 0x38, 0x25, 0x16, 0x83, 0x25, 0xD9, 0x02, - 0x2F, 0xAD, 0x40, 0x7A, 0xC5, 0xC8, 0x05, 0x4B, 0x9F, 0xD2, 0x2B, 0x26, 0x6F, 0x8E, 0xDC, 0x74, - 0xF9, 0x74, 0x56, 0xF1, 0x4E, 0x2B, 0xE2, 0x39, 0xA5, 0xDB, 0x61, 0xE4, 0x9D, 0x07, 0x02, 0x32, - 0xFC, 0xDD, 0x26, 0xBD, 0xBB, 0xDD, 0x09, 0x1F, 0x29, 0x59, 0x41, 0x91, 0x39, 0x45, 0x06, 0xD4, - 0x07, 0x7E, 0xE2, 0x5B, 0x33, 0x5A, 0x8A, 0x48, 0x2E, 0x96, 0x24, 0x03, 0x7C, 0x57, 0x5C, 0x14, - 0x52, 0xC1, 0x00, 0xF8, 0x94, 0xBA, 0xFF, 0x53, 0xB1, 0x05, 0x33, 0x8A, 0x32, 0x76, 0x83, 0x4A, - 0x71, 0x3B, 0x52, 0x8A, 0xB3, 0x09, 0x28, 0x94, 0x7C, 0xC5, 0x2C, 0xAB, 0x6A, 0x94, 0xC9, 0xD6, - 0x61, 0xE8, 0x4A, 0xD9, 0x80, 0x96, 0xB4, 0x60, 0x96, 0x12, 0xDB, 0x23, 0xB6, 0xA4, 0xD2, 0x26, - 0xF0, 0xEF, 0x86, 0x9F, 0xB6, 0x09, 0x76, 0xE0, 0xE3, 0x14, 0x53, 0x37, 0x03, 0xDB, 0x4C, 0x36, - 0xE3, 0x1C, 0x3E, 0xA1, 0x83, 0x7C, 0xEA, 0x86, 0x50, 0x48, 0xD0, 0xEC, 0x3E, 0x60, 0x66, 0x8B, - 0x07, 0x69, 0xAB, 0x88, 0x46, 0xA8, 0xB8, 0x31, 0x72, 0xE6, 0x69, 0x1B, 0x53, 0x10, 0x29, 0xE4, - 0x1C, 0xFD, 0x93, 0x75, 0xEF, 0x39, 0x7F, 0x29, 0x02, 0x7B, 0xEC, 0x63, 0xFC, 0x4F, 0x4F, 0x73, - 0x0D, 0xC7, 0x67, 0x9E, 0xAB, 0xC1, 0xFE, 0xBA, 0xDA, 0x0E, 0x46, 0xAA, 0xB5, 0xFE, 0x4E, 0xA3, - 0x89, 0xAF, 0xB2, 0x9A, 0x4C, 0x7A, 0x86, 0x15, 0x7B, 0x18, 0x29, 0x65, 0x63, 0x15, 0x1E, 0x8F, - 0x7D, 0x64, 0xBA, 0xAD, 0x05, 0x68, 0x74, 0x6A, 0xFD, 0x11, 0x70, 0xF7, 0x49, 0x28, 0x0D, 0xB6, - 0x0B, 0x6A, 0xC3, 0xD6, 0x9B, 0x96, 0xEF, 0xBF, 0x79, 0x1B, 0xB5, 0x0C, 0xDB, 0xB4, 0xE0, 0x78, - 0x3F, 0x57, 0xB5, 0xD1, 0x96, 0xCF, 0x3E, 0x1E, 0xB1, 0x7F, 0x4D, 0x2C, 0x03, 0x93, 0x91, 0x62, - 0x32, 0x02, 0xCF, 0x77, 0x55, 0xA7, 0x75, 0x27, 0x5A, 0x6C, 0xF9, 0x93, 0x4E, 0xFE, 0xED, 0xAD, - 0x9C, 0x61, 0x38, 0x2F, 0x00, 0x36, 0x68, 0x9A, 0xC0, 0x37, 0x3E, 0xEC, 0x8C, 0xFC, 0xB1, 0x79, - 0xF4, 0xFF, 0x01, 0x4A, 0x32, 0x29, 0x6B, 0x23, 0x58, 0x00 + 0x1F, 0x8B, 0x08, 0x08, 0xCA, 0x32, 0xB7, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xEB, 0x72, 0xDB, 0xCC, + 0x92, 0xD8, 0xFF, 0x54, 0xE5, 0x1D, 0x66, 0xB9, 0xD9, 0xB5, 0x9C, 0x88, 0x14, 0x48, 0x4A, 0xB2, + 0xAC, 0x63, 0xAB, 0x8A, 0xBA, 0xD9, 0xCA, 0x91, 0x64, 0x46, 0x94, 0xCF, 0x77, 0x49, 0x25, 0x5F, + 0x41, 0xC0, 0x90, 0xC4, 0x31, 0x08, 0xE0, 0xC3, 0x45, 0xB2, 0xBC, 0xB5, 0x5B, 0xFB, 0x18, 0xC9, + 0x83, 0xE4, 0x05, 0xF2, 0x28, 0x79, 0x92, 0x74, 0xF7, 0x0C, 0x40, 0x80, 0x04, 0x08, 0x80, 0x04, + 0x29, 0x52, 0xA6, 0xCF, 0xF9, 0x24, 0x0A, 0xC4, 0xDC, 0x7A, 0xBA, 0x7B, 0xBA, 0x7B, 0xFA, 0xF2, + 0xE1, 0x1F, 0xCE, 0xBF, 0x9C, 0xDD, 0xFF, 0xD6, 0xBD, 0x60, 0x43, 0x7F, 0x64, 0x9E, 0xFC, 0xC7, + 0xFF, 0xF0, 0x01, 0x7F, 0x33, 0x53, 0xB5, 0x06, 0x1F, 0x6B, 0xDC, 0xAA, 0xC1, 0x13, 0x7C, 0xC6, + 0x55, 0x1D, 0x3E, 0x31, 0xF8, 0xF7, 0x61, 0xC4, 0x7D, 0x95, 0x69, 0x43, 0xD5, 0xF5, 0xB8, 0xFF, + 0xB1, 0x16, 0xF8, 0xFD, 0xFA, 0x51, 0x8D, 0xED, 0x25, 0xBE, 0x1D, 0xFA, 0xBE, 0x53, 0xE7, 0x7F, + 0x06, 0xC6, 0xE3, 0xC7, 0xDA, 0xAF, 0xF5, 0xAF, 0x9D, 0xFA, 0x99, 0x3D, 0x72, 0x54, 0xDF, 0x78, + 0x30, 0x79, 0x8D, 0x69, 0xB6, 0xE5, 0x73, 0x0B, 0x9A, 0x5E, 0x5D, 0x7C, 0xE4, 0xFA, 0x80, 0xEF, + 0x6A, 0x43, 0xD7, 0x1E, 0xF1, 0x8F, 0xCD, 0x58, 0x2F, 0xBE, 0xE1, 0x9B, 0xFC, 0xA4, 0xE7, 0xA8, + 0xEE, 0xB7, 0xCB, 0xC0, 0x62, 0x77, 0xF7, 0x7F, 0x65, 0x3D, 0xEE, 0x07, 0xCE, 0x87, 0x3D, 0xF1, + 0x4D, 0x7C, 0x30, 0x4B, 0x85, 0xC6, 0xB5, 0x47, 0x83, 0x3F, 0x39, 0xB6, 0xEB, 0xD7, 0xC4, 0x57, + 0xF8, 0x2F, 0x1A, 0xE8, 0xC9, 0xD0, 0xFD, 0xE1, 0x47, 0x9D, 0x3F, 0x1A, 0x1A, 0xAF, 0xD3, 0x1F, + 0xBB, 0xCC, 0xB0, 0x0C, 0xDF, 0x50, 0xCD, 0xBA, 0xA7, 0xA9, 0x26, 0x8C, 0xBD, 0xCB, 0x46, 0xEA, + 0x77, 0x63, 0x14, 0x8C, 0xC6, 0x0F, 0x02, 0x8F, 0xBB, 0xF4, 0x97, 0x0A, 0xD3, 0xFE, 0xA8, 0xEC, + 0x32, 0x6F, 0xE8, 0x1A, 0xD6, 0xB7, 0xBA, 0x6F, 0xD7, 0xFB, 0x86, 0xFF, 0xF1, 0x99, 0x7B, 0xB1, + 0x09, 0x9B, 0xF0, 0x0D, 0x73, 0xB9, 0xF9, 0xB1, 0xE6, 0xF9, 0xCF, 0x26, 0xF7, 0x86, 0x9C, 0xFB, + 0x35, 0x36, 0x74, 0x79, 0x1F, 0x9E, 0xB8, 0xDA, 0xDE, 0x83, 0x6D, 0xFB, 0x9E, 0xEF, 0xAA, 0x4E, + 0x63, 0x64, 0x58, 0x0D, 0xCD, 0xF3, 0x6A, 0x45, 0x5B, 0xD2, 0xD3, 0x44, 0x0B, 0x4F, 0x73, 0x0D, + 0xC7, 0x67, 0xF0, 0xA5, 0x78, 0xE3, 0xEF, 0x7F, 0x06, 0xDC, 0x7D, 0xAE, 0xB7, 0x1B, 0x87, 0x0D, + 0x85, 0xBA, 0xFF, 0x3B, 0xBC, 0xFB, 0x61, 0x4F, 0xBC, 0x96, 0xD5, 0x28, 0x39, 0xA1, 0x72, 0x2D, + 0x1E, 0x02, 0x4B, 0x87, 0x39, 0xA5, 0x34, 0x4C, 0x34, 0x3D, 0x19, 0x6F, 0xC5, 0x7F, 0xDA, 0xD1, + 0x6D, 0x2D, 0x18, 0xC1, 0x6E, 0xBC, 0x6D, 0xD8, 0xD6, 0xCE, 0x1B, 0xCD, 0x34, 0xB4, 0x6F, 0x6F, + 0x76, 0xD9, 0x9B, 0x86, 0x6F, 0x0F, 0x06, 0x26, 0xAF, 0x3F, 0xF8, 0x16, 0xFC, 0xD9, 0x0F, 0x2C, + 0xCD, 0x37, 0x6C, 0x8B, 0xED, 0xF0, 0xB7, 0xEC, 0x5F, 0xC6, 0xCD, 0x45, 0x17, 0x00, 0x85, 0xC0, + 0x75, 0xA1, 0x8F, 0x7B, 0xD5, 0x1D, 0x70, 0xBF, 0xA1, 0x0D, 0x0D, 0x53, 0x87, 0xBF, 0xFF, 0xBB, + 0xF2, 0x3F, 0xDE, 0xCA, 0x7E, 0xCE, 0x4C, 0xD5, 0xF3, 0x76, 0xDE, 0x18, 0xB0, 0xF5, 0x75, 0x4D, + 0x75, 0xB9, 0x5F, 0xD7, 0xED, 0x27, 0x8B, 0xC5, 0xFE, 0x0E, 0x9C, 0x37, 0x6F, 0xFF, 0x32, 0xEE, + 0xF9, 0x5F, 0xDF, 0xCA, 0x29, 0x4F, 0xAF, 0x01, 0xE1, 0x1E, 0x5B, 0x42, 0xC3, 0xF3, 0x01, 0x83, + 0xB5, 0xFA, 0xC0, 0xB5, 0x03, 0x67, 0x72, 0x72, 0x43, 0x6E, 0x0C, 0x86, 0xFE, 0x31, 0x53, 0xFE, + 0x92, 0x7C, 0x6E, 0x3F, 0x72, 0xB7, 0x6F, 0xDA, 0x4F, 0xC7, 0x6C, 0x68, 0xE8, 0x3A, 0xB7, 0x26, + 0xBE, 0x06, 0x68, 0x5A, 0x9E, 0x81, 0x2B, 0x3E, 0x96, 0x5D, 0x30, 0xA5, 0xB1, 0xEF, 0x31, 0xAE, + 0x7A, 0x7C, 0xE2, 0xD5, 0x07, 0xDB, 0xD5, 0x01, 0x1F, 0x1F, 0x6C, 0xDF, 0xB7, 0x47, 0xC7, 0xCC, + 0xB3, 0x4D, 0x43, 0x67, 0x4D, 0xE7, 0x3B, 0xFB, 0x47, 0x4D, 0xC1, 0xFF, 0xC5, 0xD7, 0x14, 0xAE, + 0x81, 0xA6, 0x6D, 0x1A, 0x9E, 0xBF, 0x01, 0x93, 0xC6, 0x7F, 0x8E, 0xAA, 0xEB, 0x86, 0x35, 0xA8, + 0xBB, 0x62, 0x5E, 0x07, 0x8A, 0xF3, 0x3D, 0x73, 0x59, 0xA2, 0x6B, 0xA0, 0x17, 0x8F, 0xF9, 0xFA, + 0x6E, 0xC6, 0x17, 0xC3, 0xC9, 0x25, 0x8B, 0x2F, 0x8F, 0x99, 0x65, 0x5B, 0x93, 0x73, 0x1D, 0x01, + 0x52, 0x19, 0x56, 0xDD, 0xE4, 0x7D, 0x04, 0x49, 0xF6, 0xC8, 0x0F, 0x01, 0x2C, 0xC6, 0x3A, 0xEE, + 0x03, 0x3E, 0x7B, 0x93, 0xDD, 0xDB, 0x81, 0x0F, 0xE4, 0xCC, 0x93, 0x20, 0x4D, 0xCE, 0xDB, 0xB0, + 0xF0, 0x8D, 0x0B, 0xD7, 0xB5, 0xDD, 0xC9, 0xD6, 0xBA, 0xE1, 0x39, 0xA6, 0xFA, 0x7C, 0xCC, 0xC4, + 0x3B, 0x13, 0xF3, 0xD3, 0x6C, 0xD3, 0x86, 0x99, 0xBB, 0x5C, 0x9F, 0xF8, 0xA2, 0x0F, 0x6C, 0xAE, + 0xEE, 0x19, 0x3F, 0x60, 0x58, 0x6F, 0xA4, 0x9A, 0x26, 0x77, 0x73, 0x06, 0xEF, 0x05, 0x9A, 0x86, + 0xE0, 0x99, 0x67, 0xF8, 0x81, 0xCB, 0xA7, 0x10, 0x62, 0xE6, 0x04, 0xA2, 0x17, 0x9E, 0x24, 0xB6, + 0x3D, 0xD8, 0xA6, 0x3E, 0x63, 0x57, 0xBF, 0xD7, 0xA9, 0x8F, 0xC9, 0xC9, 0xCD, 0xD8, 0x1D, 0xFC, + 0x47, 0x4C, 0xFD, 0x98, 0xB5, 0x95, 0x7F, 0x9A, 0xD9, 0xB5, 0xE8, 0xA5, 0xA5, 0xCC, 0xEC, 0xBD, + 0x35, 0x1B, 0xED, 0xC2, 0x5E, 0xF6, 0x67, 0xF7, 0xB2, 0x3F, 0xB3, 0x17, 0xD5, 0xF7, 0x81, 0x65, + 0x4F, 0x76, 0xE0, 0xD8, 0x21, 0x5D, 0xA9, 0x0F, 0x40, 0x2B, 0x81, 0x3F, 0xB9, 0x09, 0x3F, 0xEA, + 0x86, 0xA5, 0xF3, 0xEF, 0xC7, 0xAC, 0xA9, 0x28, 0x93, 0xC4, 0x23, 0x89, 0xA6, 0x39, 0x0D, 0x1C, + 0x38, 0xD9, 0xEA, 0x12, 0x40, 0x87, 0x4A, 0xDA, 0xD7, 0x34, 0x6D, 0xDF, 0x76, 0x80, 0xE4, 0x26, + 0x27, 0x2D, 0x79, 0xA3, 0xE4, 0x85, 0x1F, 0xF6, 0xA4, 0x20, 0x00, 0x1F, 0x1F, 0x6C, 0xFD, 0x39, + 0x3C, 0x2A, 0x74, 0xE3, 0x91, 0x69, 0xC8, 0x7A, 0x3F, 0xD6, 0xF0, 0xD0, 0x55, 0x01, 0x7D, 0xDC, + 0x1A, 0x33, 0xF4, 0x8F, 0x35, 0xB9, 0xD2, 0x2B, 0x78, 0x5C, 0x8B, 0x31, 0x53, 0x6A, 0xA1, 0x9A, + 0xC6, 0xC0, 0xFA, 0x58, 0xA3, 0x89, 0xD7, 0xC2, 0xF6, 0xB2, 0x41, 0xFC, 0x65, 0x6A, 0x60, 0x8C, + 0x06, 0x93, 0x1D, 0x5E, 0x1A, 0x26, 0xBF, 0x85, 0xC3, 0xBF, 0x36, 0x3E, 0xA3, 0x4E, 0xC5, 0xB7, + 0xA7, 0x20, 0xBE, 0x7C, 0x6B, 0x38, 0xD6, 0xA0, 0x06, 0x83, 0x80, 0x00, 0x20, 0x1F, 0x33, 0x93, + 0x3F, 0x72, 0xB3, 0x76, 0x02, 0xCC, 0xDD, 0x51, 0xAD, 0x78, 0x77, 0x5D, 0xEE, 0x6A, 0x70, 0xB0, + 0xD4, 0x92, 0x83, 0x12, 0xDE, 0x8B, 0x69, 0x11, 0x52, 0xC2, 0x40, 0x08, 0x88, 0x8F, 0xB5, 0x90, + 0x54, 0x24, 0xA5, 0xD0, 0x11, 0x08, 0x3D, 0xC6, 0x17, 0xB8, 0x07, 0x2B, 0x0C, 0xC1, 0x23, 0x3F, + 0xCF, 0x04, 0xD6, 0x44, 0xCF, 0xC4, 0xA0, 0xE2, 0x5B, 0x43, 0x58, 0x39, 0xDE, 0x49, 0xB1, 0x91, + 0x02, 0xC6, 0x2E, 0x07, 0x49, 0xEC, 0xCA, 0xEA, 0xBA, 0x36, 0x92, 0x75, 0x02, 0xCC, 0x0F, 0x27, + 0x77, 0xF8, 0xA5, 0x0F, 0x5C, 0xF5, 0xC3, 0xDE, 0xC3, 0xC9, 0x87, 0x07, 0x97, 0xFE, 0x43, 0x79, + 0x4A, 0x88, 0x43, 0xCC, 0xF0, 0x80, 0xA5, 0xE0, 0xD1, 0x0E, 0xAF, 0x34, 0x58, 0xD7, 0x44, 0x2E, + 0xCE, 0x9E, 0x54, 0xC3, 0x6F, 0x34, 0x1A, 0x2B, 0x9C, 0x3E, 0x0A, 0x88, 0x26, 0xF7, 0x79, 0xDA, + 0xEC, 0xD9, 0x39, 0xF4, 0x96, 0x31, 0xFD, 0xA1, 0xEA, 0x01, 0x33, 0x7F, 0x62, 0xD4, 0xC9, 0x8A, + 0x26, 0xDC, 0x37, 0xDC, 0xD1, 0x13, 0x08, 0x13, 0x5F, 0x1D, 0xD3, 0x56, 0xF5, 0x8C, 0x99, 0x4F, + 0xCE, 0xF9, 0x52, 0x36, 0x62, 0x81, 0xA3, 0xAB, 0x3E, 0x07, 0x7E, 0x2A, 0x9A, 0x35, 0x58, 0x72, + 0x33, 0xC4, 0x62, 0xC2, 0x0D, 0x29, 0xBE, 0xA0, 0x93, 0x38, 0x83, 0x89, 0x93, 0x17, 0xE2, 0x35, + 0x2E, 0x38, 0x6A, 0x01, 0x32, 0xEF, 0xA8, 0xDE, 0x6C, 0x01, 0xD2, 0x22, 0x4D, 0x45, 0xA4, 0xE3, + 0xFA, 0xDF, 0xEA, 0x1E, 0xCA, 0xD8, 0x31, 0xBA, 0x49, 0x08, 0xE0, 0xBF, 0x18, 0x97, 0x86, 0x90, + 0xC2, 0x11, 0xDF, 0x13, 0x33, 0x2A, 0x01, 0xF0, 0x18, 0x88, 0x9B, 0xD9, 0x20, 0x1E, 0x41, 0xA3, + 0xAE, 0x3A, 0xE0, 0x85, 0x97, 0xE5, 0xDA, 0x4F, 0x53, 0x7B, 0xFA, 0x60, 0xDA, 0xDA, 0xB7, 0xBF, + 0x24, 0xBB, 0xC8, 0xE9, 0x46, 0x9C, 0x3D, 0xC8, 0xC1, 0x27, 0x19, 0x10, 0xFE, 0x43, 0x28, 0x5C, + 0x80, 0x70, 0xF4, 0xFC, 0x34, 0xE4, 0xB0, 0x93, 0xE1, 0x96, 0x1E, 0xC7, 0xF8, 0x09, 0x40, 0x31, + 0x7C, 0xFC, 0x37, 0xEE, 0x7A, 0xC0, 0xCC, 0xB3, 0x99, 0xC6, 0xA3, 0xD2, 0x50, 0x24, 0xE3, 0x40, + 0x0C, 0x99, 0x1E, 0x6F, 0xDC, 0xED, 0xC0, 0xF2, 0xBC, 0xC2, 0xFD, 0x7E, 0xBA, 0xED, 0xF5, 0x62, + 0x93, 0x8B, 0x0D, 0xC3, 0xF2, 0xC6, 0x11, 0x78, 0x78, 0x7A, 0x7F, 0x75, 0x9E, 0xDD, 0xFD, 0xB9, + 0xC0, 0xD5, 0x53, 0x33, 0xE0, 0x3E, 0xA0, 0xE9, 0x90, 0x5D, 0x9D, 0xC3, 0x91, 0x0C, 0xFF, 0x8A, + 0x0E, 0xA2, 0xD9, 0x20, 0x85, 0x19, 0x16, 0x50, 0x81, 0x77, 0x7D, 0xFD, 0x39, 0x7B, 0xA0, 0xEB, + 0xEB, 0xE1, 0xF1, 0x74, 0x3F, 0x13, 0x80, 0xE1, 0xB6, 0xCE, 0x41, 0x2C, 0xBF, 0x56, 0xFD, 0xEC, + 0x8E, 0xF6, 0x01, 0x02, 0xEF, 0x95, 0xD6, 0xFB, 0xFD, 0x77, 0xEF, 0xE5, 0x1C, 0x77, 0x0B, 0xF7, + 0x3B, 0x0B, 0xD0, 0xF5, 0xA6, 0x72, 0xD0, 0x68, 0x1E, 0x1D, 0x28, 0x07, 0xEF, 0x0E, 0x9B, 0x65, + 0x7B, 0xEE, 0x98, 0x33, 0x66, 0xDC, 0x3C, 0x38, 0x84, 0x39, 0x1F, 0x85, 0xD3, 0x65, 0x3B, 0x9D, + 0xEE, 0xD9, 0xDB, 0x14, 0x98, 0x16, 0xC3, 0x9E, 0x18, 0xC0, 0x2F, 0xCE, 0x2E, 0x2E, 0xB3, 0x87, + 0xC5, 0x6F, 0x73, 0x41, 0xCE, 0x35, 0xDE, 0xFF, 0x75, 0x16, 0x50, 0x5A, 0x47, 0x4A, 0x4B, 0x39, + 0x6C, 0x1C, 0x1C, 0x1E, 0x15, 0x85, 0x09, 0x76, 0xF9, 0xDB, 0x8C, 0x2E, 0xF7, 0xDF, 0x35, 0x0F, + 0x8F, 0x94, 0xFD, 0xC6, 0xBE, 0xD2, 0x2E, 0xD3, 0xE5, 0xEF, 0xB3, 0x50, 0xE2, 0xE8, 0xF0, 0xF0, + 0xF0, 0xA0, 0xB1, 0x7F, 0xB4, 0x3F, 0x75, 0x76, 0xE7, 0x42, 0x37, 0xC9, 0xEF, 0x32, 0x9E, 0x0C, + 0xDD, 0x90, 0xA9, 0x8C, 0xFC, 0xBA, 0x32, 0x25, 0xFC, 0x4C, 0xB3, 0x43, 0x3A, 0x71, 0x52, 0xB8, + 0xD5, 0x3F, 0xD4, 0xEB, 0xAC, 0x1E, 0xFE, 0x63, 0x70, 0xCA, 0xF7, 0x41, 0xEE, 0x61, 0x67, 0xB6, + 0xD5, 0x37, 0x06, 0xB1, 0x2F, 0xEA, 0xF5, 0x93, 0x14, 0x36, 0x27, 0xA7, 0xA0, 0x83, 0x06, 0x08, + 0xAA, 0xD7, 0x40, 0x75, 0xEA, 0xAD, 0x34, 0xCE, 0xF6, 0x41, 0x68, 0x35, 0x91, 0x10, 0xE6, 0x5B, + 0x0C, 0xFE, 0xAB, 0x3B, 0xAE, 0x01, 0x13, 0x7C, 0x66, 0x63, 0x25, 0x5D, 0xB0, 0x67, 0x47, 0x4C, + 0x42, 0xCC, 0xA1, 0xC6, 0xFC, 0x67, 0x07, 0x96, 0x22, 0xBA, 0xA8, 0x31, 0x38, 0xDE, 0xD4, 0xBA, + 0x68, 0x41, 0xC7, 0x8D, 0xA9, 0x3A, 0x1E, 0xAF, 0xA5, 0xEF, 0x97, 0x78, 0x97, 0xD4, 0xF9, 0x8F, + 0xB5, 0x7F, 0x0C, 0x5F, 0xEE, 0x26, 0xBB, 0x57, 0x5D, 0x43, 0xAD, 0xF3, 0xEF, 0xB0, 0x17, 0x3A, + 0xC7, 0xE3, 0x57, 0x35, 0xA1, 0x3F, 0xF1, 0x14, 0xCF, 0x17, 0xD7, 0x36, 0xBD, 0xF1, 0x40, 0xC9, + 0xB6, 0x27, 0xE9, 0xC3, 0x26, 0x81, 0x18, 0xB8, 0x2A, 0x19, 0x1D, 0x3E, 0x18, 0x89, 0xC5, 0xA1, + 0xB9, 0x60, 0x7C, 0x6C, 0x92, 0xF1, 0x00, 0xED, 0x08, 0xEC, 0xC1, 0x60, 0x13, 0xF6, 0x05, 0x3C, + 0x0F, 0x8D, 0x54, 0x04, 0x12, 0x30, 0xC9, 0x40, 0x9F, 0xAC, 0xCD, 0x0A, 0x97, 0xC2, 0x46, 0x0F, + 0xB0, 0x5B, 0x92, 0x82, 0x0B, 0xAE, 0x8E, 0xB0, 0x25, 0xB5, 0x33, 0x6F, 0x08, 0x92, 0x45, 0x6E, + 0x8F, 0xD3, 0x68, 0x34, 0x35, 0x3B, 0xD5, 0xD5, 0x19, 0xFE, 0xA8, 0xA3, 0x06, 0x30, 0x8D, 0xAF, + 0x69, 0x6D, 0xFA, 0xB6, 0x3B, 0x92, 0x36, 0x08, 0x20, 0x86, 0x56, 0xD6, 0xB6, 0xC4, 0xB6, 0xE6, + 0x38, 0xFB, 0x0D, 0x41, 0xE3, 0xB2, 0x67, 0xDF, 0x97, 0x08, 0xF7, 0xE0, 0xD5, 0x81, 0xC2, 0x35, + 0x3E, 0x22, 0x8B, 0x9F, 0xD0, 0x29, 0xB2, 0xFB, 0x20, 0x3B, 0x06, 0x5A, 0x12, 0x41, 0xC6, 0xE1, + 0x26, 0xD7, 0x7C, 0xA6, 0x32, 0xB9, 0xEF, 0x0C, 0xD0, 0x8C, 0xF9, 0x43, 0x6E, 0x31, 0x18, 0x00, + 0x64, 0x04, 0x26, 0xE5, 0x67, 0x0F, 0xA8, 0x00, 0x9E, 0xAB, 0x7E, 0xF8, 0x62, 0x83, 0x75, 0x7C, + 0x21, 0x77, 0xEE, 0xC6, 0x65, 0xB8, 0x27, 0x03, 0x24, 0x88, 0x00, 0x01, 0x4E, 0x1D, 0x73, 0x7D, + 0xFC, 0x7E, 0x88, 0x76, 0xDA, 0x50, 0xB5, 0x06, 0xDC, 0x63, 0x28, 0x0E, 0x7A, 0xEA, 0x23, 0xBC, + 0xF2, 0x44, 0xE3, 0x81, 0x0A, 0xDE, 0xEF, 0x73, 0xB4, 0x70, 0x45, 0x93, 0x01, 0x89, 0x30, 0xEA, + 0xC7, 0x76, 0xC5, 0x7B, 0x6F, 0x7A, 0xD0, 0x26, 0x89, 0xBB, 0x6F, 0xF0, 0x45, 0x07, 0x26, 0xE3, + 0x71, 0xBD, 0x31, 0x0B, 0xBC, 0x53, 0x00, 0x24, 0x54, 0x36, 0xAC, 0xBE, 0x5D, 0xD7, 0x0C, 0x57, + 0x83, 0x11, 0x7D, 0xFE, 0xDD, 0x8F, 0x08, 0x7F, 0xE4, 0xE1, 0x6E, 0x65, 0x72, 0xC8, 0x09, 0x4E, + 0x99, 0x81, 0x08, 0x53, 0xBC, 0xB1, 0x00, 0x9A, 0xA0, 0x3C, 0x77, 0x92, 0x87, 0x03, 0xE9, 0xCC, + 0x3D, 0xA1, 0x87, 0x47, 0x4C, 0x75, 0x26, 0x40, 0x0C, 0xCB, 0x09, 0x7C, 0xC9, 0xC6, 0x5C, 0x55, + 0x37, 0xEC, 0x9A, 0xB4, 0x2A, 0xCB, 0x6D, 0xB8, 0x13, 0xCF, 0x1E, 0x55, 0x90, 0x79, 0x3E, 0xD6, + 0x94, 0xDC, 0xFE, 0x4C, 0xF5, 0x81, 0x9B, 0x71, 0x66, 0xA2, 0x90, 0x9E, 0x7A, 0x22, 0x11, 0x00, + 0x64, 0x05, 0x7A, 0x63, 0x51, 0x88, 0xBE, 0x12, 0x78, 0x36, 0xCB, 0xC3, 0xB3, 0x29, 0xE0, 0xD9, + 0x6C, 0xB5, 0xF7, 0x0F, 0x0E, 0xDF, 0x1D, 0xBD, 0x57, 0xC6, 0x9F, 0xB6, 0xB0, 0x8D, 0xC3, 0xB6, + 0x55, 0x1E, 0xB6, 0x2D, 0x01, 0xDB, 0x2D, 0x1C, 0xE3, 0x70, 0x6C, 0x97, 0x87, 0x63, 0x7B, 0x0B, + 0xC7, 0x69, 0x38, 0xEE, 0x97, 0x87, 0xE3, 0xFE, 0x16, 0x8E, 0xD3, 0x70, 0x3C, 0x28, 0x0F, 0xC7, + 0x83, 0x2D, 0x1C, 0xA7, 0xE1, 0x78, 0x58, 0x1E, 0x8E, 0x87, 0x5B, 0x38, 0x4E, 0xC3, 0xF1, 0x5D, + 0x79, 0x38, 0xBE, 0xAB, 0x14, 0x8E, 0x95, 0x42, 0x52, 0xCC, 0x15, 0x1A, 0x44, 0x93, 0x15, 0xF7, + 0x0C, 0xA1, 0x7A, 0x1C, 0xBF, 0x4A, 0x92, 0x06, 0xD5, 0x36, 0x7D, 0xD8, 0xA7, 0x9F, 0x34, 0x12, + 0xF5, 0x11, 0x89, 0x7C, 0xB3, 0x81, 0x83, 0xBD, 0x1F, 0x17, 0x00, 0x44, 0x52, 0xAF, 0xC3, 0x61, + 0x8F, 0x68, 0xC0, 0x77, 0xA5, 0x76, 0x13, 0x25, 0xFC, 0x5A, 0x02, 0x2A, 0x52, 0x8D, 0x4E, 0x28, + 0xF7, 0x62, 0x77, 0x72, 0xBA, 0x75, 0x26, 0x5B, 0xD0, 0xC5, 0x66, 0xD4, 0x79, 0xEC, 0xB2, 0x13, + 0x37, 0xDA, 0x99, 0xB9, 0xC9, 0xD9, 0xF4, 0x30, 0x3D, 0xD4, 0x19, 0x69, 0x50, 0x37, 0xA0, 0xEF, + 0xA0, 0x91, 0x38, 0x39, 0x9C, 0xBC, 0xDE, 0x9C, 0x35, 0xE0, 0x52, 0x90, 0x66, 0xDA, 0xAA, 0x23, + 0xEF, 0xBD, 0x0F, 0x8A, 0x90, 0x9B, 0x34, 0xC0, 0x24, 0x4D, 0x29, 0x74, 0x43, 0xE5, 0x5B, 0x74, + 0x0B, 0x22, 0x11, 0xA9, 0x96, 0x65, 0xA3, 0x49, 0x45, 0xCA, 0x1C, 0x15, 0x98, 0xEE, 0xAC, 0xAD, + 0x33, 0x74, 0xC6, 0x98, 0x1A, 0x68, 0xE7, 0x6D, 0x4D, 0x5E, 0xBF, 0xC8, 0x07, 0x19, 0xD6, 0x8C, + 0x65, 0xA9, 0xE7, 0x31, 0x15, 0x5D, 0x4C, 0x63, 0x52, 0x9F, 0x46, 0x7D, 0xBC, 0xAF, 0x6A, 0xBE, + 0x0D, 0x8B, 0xD7, 0x79, 0x5F, 0x0D, 0x4C, 0xDF, 0xCB, 0xD5, 0x7D, 0x97, 0xA3, 0xFF, 0xE6, 0x72, + 0xA9, 0x12, 0x18, 0xEE, 0xC6, 0xF6, 0xE0, 0xC6, 0x1B, 0x54, 0x89, 0xDC, 0xA9, 0x86, 0xA7, 0xD4, + 0xB7, 0x27, 0x8C, 0x8E, 0x74, 0xA3, 0xB0, 0x52, 0x8B, 0xE3, 0xC8, 0x07, 0x8E, 0x1A, 0x37, 0x3B, + 0x56, 0x6D, 0x63, 0xC4, 0x25, 0xCD, 0x65, 0x60, 0x8C, 0x35, 0xCC, 0xD8, 0x80, 0x18, 0xB4, 0x26, + 0x4C, 0x8B, 0x78, 0x8D, 0xF3, 0xF2, 0x76, 0xC5, 0xA4, 0x01, 0x70, 0xF6, 0x7A, 0xB2, 0x2D, 0x7F, + 0xCC, 0xF1, 0xEB, 0xCD, 0x1C, 0xF3, 0x1F, 0x5D, 0xE5, 0x71, 0xD5, 0x0B, 0x5C, 0x22, 0xFC, 0x3B, + 0xD5, 0xE7, 0x57, 0x78, 0x10, 0xCD, 0xA2, 0xD2, 0x9B, 0xF1, 0xFB, 0x0C, 0x1B, 0x1C, 0x17, 0x3B, + 0x0F, 0x73, 0xB8, 0x73, 0xC6, 0xF1, 0xD9, 0x22, 0x4E, 0xD9, 0x6C, 0x21, 0xA1, 0xB7, 0xD9, 0x98, + 0xD9, 0x17, 0x62, 0x23, 0x31, 0x29, 0x61, 0x62, 0x91, 0x9F, 0x7F, 0x24, 0xEE, 0x5B, 0xE3, 0xF2, + 0xC0, 0x95, 0x95, 0xDF, 0x33, 0xFE, 0xFB, 0xFC, 0xE3, 0xB8, 0xD8, 0x8B, 0x55, 0xF2, 0xDB, 0x09, + 0xBE, 0x7B, 0x3F, 0xE4, 0xCC, 0x0A, 0x46, 0x0F, 0xDC, 0x65, 0x76, 0x9F, 0x91, 0x47, 0x0A, 0x20, + 0xB3, 0x87, 0x86, 0x48, 0xD3, 0xD6, 0x04, 0x66, 0xFF, 0xBF, 0x7F, 0xFF, 0x5F, 0x7D, 0xE3, 0x3B, + 0xF7, 0xFE, 0xDF, 0xBF, 0xFF, 0x6F, 0xE6, 0xC0, 0x8B, 0x1E, 0x07, 0x1C, 0xD6, 0x1B, 0xAC, 0x63, + 0x3D, 0xFB, 0x43, 0xC3, 0x1A, 0x30, 0xF5, 0xC1, 0x7E, 0xE4, 0x6C, 0xFF, 0xF3, 0x0F, 0x90, 0x41, + 0x9F, 0x01, 0x7D, 0xD0, 0x34, 0x3A, 0xBE, 0x3B, 0x84, 0x97, 0x07, 0xDC, 0xA3, 0x9E, 0x80, 0xFA, + 0xF6, 0xA8, 0xE7, 0xC1, 0x00, 0xDB, 0x81, 0x04, 0xAB, 0xB9, 0x1C, 0xD6, 0xA6, 0x19, 0xDC, 0x6B, + 0xB0, 0x5B, 0x1B, 0x50, 0x81, 0xE1, 0x8C, 0x62, 0xB0, 0x66, 0x2E, 0x5E, 0xA5, 0x1B, 0x1E, 0xB9, + 0xAC, 0xB9, 0xE4, 0xAC, 0x86, 0xA7, 0x42, 0x13, 0x06, 0x23, 0x4B, 0xA9, 0x61, 0xB1, 0x53, 0xF4, + 0x67, 0x18, 0xD9, 0x3A, 0x6F, 0xB0, 0x73, 0x71, 0x48, 0x1C, 0xE3, 0x64, 0x1A, 0xEC, 0xDA, 0x18, + 0x19, 0xBE, 0x77, 0xCC, 0x94, 0x86, 0xA2, 0x28, 0xCD, 0x56, 0x8B, 0x1A, 0x2A, 0xF0, 0x4D, 0x91, + 0xBD, 0x5F, 0xEE, 0x51, 0x52, 0xF8, 0x48, 0x19, 0xBF, 0x98, 0x27, 0x3A, 0x16, 0x39, 0x80, 0x32, + 0x68, 0x44, 0xC8, 0xB4, 0x07, 0x73, 0x91, 0x48, 0x5C, 0xEC, 0x14, 0x98, 0x94, 0x2A, 0x78, 0xC6, + 0xEE, 0x25, 0xA6, 0x29, 0xA9, 0xC8, 0x38, 0x4E, 0x7A, 0xDB, 0xB9, 0xA5, 0xD1, 0x7C, 0x21, 0x31, + 0x36, 0x74, 0xC2, 0x77, 0x80, 0xA0, 0x84, 0x37, 0x7E, 0xB8, 0x26, 0x05, 0xC6, 0xE1, 0xA3, 0x13, + 0xDB, 0xFD, 0xB0, 0x07, 0xBF, 0xC4, 0x90, 0xEB, 0xC2, 0xA3, 0x7A, 0x5C, 0xAB, 0x9D, 0xF4, 0x88, + 0x5A, 0x3D, 0xF6, 0xC0, 0xFD, 0x27, 0x0E, 0x04, 0x13, 0x7B, 0xC7, 0x5B, 0x3B, 0xFE, 0x33, 0x63, + 0xAE, 0x0D, 0xE0, 0x0C, 0xC0, 0x06, 0x04, 0xBA, 0x19, 0xE8, 0xF9, 0x09, 0x6C, 0xC1, 0x02, 0xA6, + 0x00, 0xC4, 0x0F, 0x4D, 0xFD, 0x34, 0xB6, 0x81, 0xF7, 0x3C, 0xF0, 0x2A, 0xF0, 0xA3, 0x7E, 0x60, + 0x0A, 0x7E, 0xE1, 0xAB, 0xDF, 0x88, 0x65, 0x25, 0x5E, 0xE6, 0xE8, 0xF1, 0xC1, 0xFA, 0xFC, 0x29, + 0x9A, 0x81, 0xAA, 0xB9, 0xB6, 0x07, 0xBF, 0x80, 0x57, 0xC1, 0xDB, 0xF0, 0xE2, 0x23, 0x7F, 0x66, + 0x3B, 0xAD, 0xFD, 0xFF, 0xC2, 0x86, 0x76, 0xE0, 0x7A, 0x6F, 0xAB, 0xE0, 0x56, 0x63, 0xF6, 0xD4, + 0xC4, 0x97, 0x8E, 0x9A, 0xEF, 0x0F, 0xC3, 0xF1, 0x81, 0x43, 0x11, 0xD0, 0x8B, 0xC3, 0x33, 0xE6, + 0xC8, 0xB6, 0x65, 0x52, 0xD5, 0x33, 0x29, 0x22, 0xA5, 0x79, 0xB9, 0x14, 0x34, 0xAE, 0x84, 0x4D, + 0xCD, 0xF3, 0xFD, 0xDC, 0x7A, 0xB0, 0x70, 0x16, 0x7A, 0xB6, 0xD4, 0x91, 0xA1, 0xDD, 0x00, 0xBA, + 0x9A, 0xE7, 0xAE, 0xED, 0x08, 0x91, 0xB5, 0x98, 0x59, 0x25, 0xDE, 0xB6, 0x96, 0xBA, 0x97, 0x87, + 0x53, 0xA6, 0x94, 0x73, 0xD1, 0x86, 0x51, 0xA3, 0xE3, 0x95, 0x6B, 0xA1, 0x1D, 0xFD, 0xEF, 0x81, + 0xE7, 0x87, 0xBC, 0xC5, 0xE7, 0xAE, 0xA5, 0x9A, 0x4C, 0x35, 0x07, 0xB6, 0x6B, 0xF8, 0xC3, 0x11, + 0x12, 0xE9, 0x48, 0xF5, 0xB5, 0x21, 0x7D, 0x0F, 0xCA, 0x84, 0xD0, 0x55, 0x55, 0xC7, 0x01, 0xED, + 0x5A, 0x88, 0x4A, 0xDC, 0x7A, 0x34, 0x5C, 0xDB, 0xC2, 0xC1, 0x25, 0xBF, 0x92, 0x57, 0xCB, 0xCC, + 0x18, 0x81, 0x4E, 0xFB, 0xC8, 0x45, 0xDF, 0x2E, 0xD7, 0xB8, 0x01, 0x1C, 0xE2, 0x8D, 0x27, 0x86, + 0x71, 0x40, 0x1D, 0x10, 0x1D, 0x00, 0x27, 0x8B, 0x33, 0x3D, 0x79, 0x53, 0x1D, 0xE0, 0xCD, 0xAF, + 0xFD, 0x68, 0xE8, 0x78, 0xA3, 0x0C, 0xCC, 0xC3, 0x05, 0xD6, 0xA6, 0x69, 0x01, 0x31, 0x9B, 0xD0, + 0xA3, 0x18, 0x3D, 0xD3, 0x01, 0xC9, 0x1B, 0xE8, 0xBF, 0x47, 0x23, 0xC6, 0x07, 0xC2, 0xA9, 0x03, + 0xB0, 0x02, 0xCB, 0x0B, 0x0C, 0x1F, 0x83, 0x5D, 0x18, 0x00, 0xC9, 0x47, 0xC8, 0x13, 0x2B, 0xA2, + 0x1D, 0xA3, 0x06, 0x03, 0x78, 0xDB, 0xCA, 0x5A, 0x12, 0x32, 0x36, 0xD3, 0xF8, 0xC6, 0x4D, 0x74, + 0x17, 0xC1, 0x7B, 0x71, 0x10, 0xB5, 0x90, 0xA5, 0x21, 0x97, 0x04, 0x66, 0x09, 0x73, 0x8F, 0xC6, + 0x03, 0x39, 0x11, 0x7B, 0x07, 0xD1, 0x4E, 0x70, 0xE1, 0x68, 0x96, 0x62, 0xDE, 0xDA, 0xF3, 0x5A, + 0x6B, 0xF1, 0x73, 0x58, 0xE9, 0x24, 0x46, 0xE7, 0x5F, 0xCC, 0x0B, 0x5F, 0x04, 0x61, 0x67, 0x4D, + 0x92, 0xC8, 0x24, 0xC1, 0x25, 0x59, 0x94, 0x2E, 0xC9, 0x4F, 0xF0, 0xA8, 0xFC, 0x35, 0xD2, 0x38, + 0x2F, 0xC2, 0x34, 0x46, 0x86, 0x75, 0x61, 0xF2, 0xC7, 0xD9, 0x1A, 0xF4, 0xFC, 0x56, 0xB8, 0x29, + 0xA1, 0x47, 0x0C, 0x57, 0x94, 0xC5, 0xDC, 0x00, 0xC2, 0xF6, 0xFE, 0xC6, 0xB0, 0x09, 0x21, 0xF8, + 0x71, 0x49, 0x3C, 0xAC, 0x40, 0xFE, 0x91, 0xDC, 0x06, 0x66, 0x82, 0xE1, 0x68, 0x8C, 0x87, 0x53, + 0x41, 0x5A, 0xD2, 0x39, 0xC6, 0x5F, 0x78, 0x44, 0x90, 0xAA, 0xB0, 0x33, 0x78, 0x40, 0xE6, 0xA6, + 0x69, 0xF8, 0x64, 0x0E, 0x7B, 0xE0, 0x28, 0xCE, 0xE8, 0x82, 0xEC, 0x40, 0x2D, 0x2B, 0xAC, 0xCB, + 0x2C, 0x4F, 0x8F, 0x29, 0x48, 0x75, 0x85, 0x44, 0x83, 0xB9, 0x09, 0xAB, 0xCC, 0x31, 0x9F, 0x40, + 0xD3, 0x32, 0xC7, 0xBA, 0x68, 0xB1, 0xA1, 0x67, 0x39, 0xCC, 0xFE, 0xEC, 0xF6, 0xCB, 0x0A, 0xA9, + 0x12, 0x46, 0x2B, 0x43, 0x94, 0x67, 0x7B, 0xB7, 0xCA, 0xCB, 0x13, 0xE3, 0x98, 0xD8, 0xD0, 0x33, + 0x4C, 0x35, 0x45, 0x40, 0x49, 0x2A, 0xE5, 0x8D, 0xAD, 0x0D, 0x87, 0xFA, 0x29, 0x48, 0xF8, 0x48, + 0xB2, 0xBF, 0x5F, 0x9C, 0xD7, 0x2F, 0xDF, 0x77, 0xE9, 0xCC, 0x6B, 0x2A, 0xD1, 0xE3, 0xAF, 0x37, + 0xEF, 0x8F, 0x94, 0x2D, 0xA9, 0x2E, 0x40, 0xAA, 0x88, 0x4C, 0xA5, 0x28, 0x15, 0x1A, 0x6C, 0x16, + 0xA1, 0xA2, 0x3D, 0x3C, 0xB4, 0xDB, 0x5A, 0x1E, 0x62, 0x21, 0x1D, 0x0A, 0x67, 0x43, 0xAE, 0x7D, + 0x3B, 0xB5, 0xBF, 0x73, 0xAF, 0xA8, 0xE0, 0x4D, 0x26, 0xE8, 0x78, 0x17, 0xD0, 0x32, 0xF9, 0x77, + 0x91, 0x8B, 0xC8, 0x6A, 0x5D, 0x30, 0xEF, 0xE3, 0xC2, 0x28, 0x88, 0x91, 0x9A, 0xEA, 0x90, 0x18, + 0x0A, 0x32, 0x23, 0xAC, 0x56, 0x06, 0xFD, 0x82, 0x5C, 0x29, 0xDE, 0x41, 0xF1, 0x55, 0x90, 0x1F, + 0x1C, 0x84, 0xAE, 0x0D, 0x42, 0x2A, 0x90, 0x99, 0xE1, 0x98, 0x7C, 0x4C, 0x9E, 0x91, 0x8A, 0x1E, + 0x7D, 0x95, 0x80, 0x9A, 0x07, 0x72, 0xB0, 0x3D, 0xE2, 0x71, 0x49, 0xD6, 0x63, 0xBA, 0xA1, 0xF9, + 0x28, 0x32, 0xA3, 0xA0, 0x6B, 0x71, 0x20, 0x65, 0x74, 0xF7, 0x0C, 0x5C, 0x94, 0xBA, 0x61, 0x1A, + 0xDC, 0xC5, 0x38, 0x96, 0x64, 0x37, 0x34, 0x1F, 0x07, 0x3F, 0x21, 0xB5, 0x0B, 0x99, 0x4A, 0x98, + 0x0F, 0x84, 0xA0, 0x9C, 0x7C, 0x99, 0xFC, 0x42, 0x85, 0xF9, 0x73, 0x52, 0xF8, 0x86, 0xC5, 0xA0, + 0xD4, 0xEE, 0x0F, 0x6D, 0x8F, 0x47, 0x4B, 0x03, 0xB1, 0x1F, 0x3A, 0x09, 0x85, 0xF5, 0x91, 0x58, + 0xEA, 0x03, 0xC7, 0xBF, 0x89, 0xD3, 0xE8, 0x81, 0x8B, 0x9F, 0x23, 0xD9, 0x59, 0x53, 0x4D, 0x2D, + 0x88, 0xD6, 0x17, 0x71, 0x9F, 0x0E, 0x8C, 0xCA, 0x2D, 0x04, 0xE7, 0xDA, 0x39, 0x86, 0x26, 0xAE, + 0x09, 0x12, 0xC0, 0x3A, 0xE5, 0xC6, 0xB9, 0x1D, 0x4C, 0xD0, 0x3C, 0xA2, 0xBA, 0xB8, 0x17, 0x8A, + 0x5F, 0x75, 0x16, 0x3C, 0x76, 0xA6, 0x7A, 0x92, 0x87, 0x8B, 0x20, 0x8A, 0xC4, 0xE0, 0x7F, 0xC8, + 0xD1, 0x4F, 0xC4, 0xEF, 0x82, 0x0C, 0x4F, 0xB0, 0xAC, 0xE9, 0x61, 0xE8, 0x79, 0x78, 0x7D, 0x45, + 0x8F, 0x60, 0xF6, 0x91, 0xDB, 0x44, 0x0A, 0x49, 0x47, 0xC3, 0x2F, 0x70, 0x93, 0x98, 0x0A, 0xD4, + 0x4F, 0xAA, 0x69, 0x98, 0xDC, 0x7E, 0x29, 0xA8, 0x86, 0xC3, 0x9F, 0xC8, 0x0F, 0x2B, 0x87, 0x6B, + 0x34, 0x81, 0xCA, 0x01, 0x6B, 0xDA, 0x16, 0x4C, 0xEF, 0xC5, 0x00, 0x7B, 0xFD, 0xE5, 0xB6, 0xD3, + 0xEB, 0x01, 0x60, 0xC5, 0x87, 0xD5, 0x03, 0x36, 0x9C, 0x40, 0xE5, 0x80, 0x75, 0x5E, 0x0E, 0xA8, + 0x5D, 0x04, 0x68, 0xF7, 0x05, 0x80, 0xD9, 0x5D, 0x02, 0x20, 0x6F, 0xD5, 0x47, 0x43, 0x7B, 0x29, + 0x50, 0xC2, 0xE0, 0x57, 0x67, 0xB5, 0x93, 0xDB, 0xCE, 0xDF, 0xAE, 0xCE, 0x56, 0x0E, 0x4E, 0x39, + 0x78, 0xD5, 0x00, 0xFD, 0x6F, 0x3F, 0x5E, 0x8E, 0xDE, 0xFF, 0xDB, 0xEF, 0x48, 0x6B, 0xF8, 0x73, + 0xE5, 0xD0, 0x14, 0x43, 0x57, 0x0D, 0xCC, 0xDE, 0x83, 0xFA, 0x62, 0xC0, 0xEC, 0x9D, 0x76, 0x60, + 0x45, 0xF8, 0x73, 0xE5, 0xC0, 0x14, 0x43, 0x2F, 0x08, 0xCC, 0xF9, 0x54, 0x71, 0x67, 0xEC, 0x8D, + 0x92, 0x90, 0x8B, 0x97, 0xE2, 0xBD, 0x57, 0x40, 0xDF, 0xA1, 0xD9, 0x88, 0xE3, 0xF9, 0xB3, 0xEA, + 0x49, 0x1B, 0x75, 0x29, 0x33, 0xC4, 0x18, 0x63, 0x2A, 0x41, 0x12, 0x21, 0x31, 0x7F, 0x8A, 0xA6, + 0x54, 0x3B, 0xB9, 0xA0, 0x27, 0x4C, 0x3E, 0x62, 0x9F, 0x3B, 0xBD, 0xBD, 0x8B, 0xC3, 0x7C, 0x95, + 0xF3, 0xCC, 0x06, 0xE5, 0x85, 0x72, 0x1A, 0x79, 0x2B, 0x40, 0xB0, 0xE9, 0x69, 0xAF, 0xFC, 0x96, + 0xE4, 0x2B, 0xA8, 0x30, 0x9F, 0xA1, 0x09, 0xEB, 0x48, 0x5B, 0x3E, 0xEB, 0x71, 0x97, 0x02, 0xE3, + 0xB4, 0x31, 0x28, 0xC2, 0x0B, 0x0B, 0x9D, 0xAE, 0x42, 0x49, 0x1F, 0x0A, 0x01, 0x9B, 0xA0, 0x91, + 0x98, 0x1E, 0x73, 0x51, 0x50, 0x87, 0x59, 0x53, 0x07, 0xBF, 0x92, 0x4A, 0x7F, 0x31, 0x74, 0x2E, + 0x81, 0xCA, 0xB7, 0xBE, 0x6B, 0x38, 0x67, 0xA6, 0x81, 0x49, 0x4E, 0x42, 0x5C, 0xBE, 0xBD, 0xBF, + 0xBB, 0xEA, 0x32, 0xF1, 0xB0, 0x80, 0xCE, 0xBF, 0x38, 0x62, 0x26, 0x26, 0xB1, 0x32, 0xEB, 0xC2, + 0x57, 0xD2, 0xB8, 0x0D, 0x4F, 0xAE, 0x57, 0xA3, 0xF1, 0x51, 0xED, 0xC6, 0x0B, 0x13, 0xCC, 0xE0, + 0x11, 0xC3, 0x4C, 0x1A, 0x4A, 0xA8, 0xDA, 0x2A, 0x68, 0xD4, 0x1E, 0xA9, 0xDF, 0x9E, 0x40, 0xE0, + 0x06, 0xFB, 0xCD, 0x0E, 0xDC, 0x30, 0xCC, 0x73, 0x14, 0x78, 0x3E, 0x5A, 0xFD, 0x9E, 0x0C, 0x74, + 0x73, 0x12, 0xC9, 0x31, 0x5C, 0x74, 0x4A, 0x66, 0xAA, 0xCF, 0xD0, 0x11, 0xC4, 0x37, 0x46, 0x3C, + 0xAE, 0x88, 0x9F, 0x1B, 0xDE, 0x5A, 0x6A, 0xE1, 0x05, 0xD9, 0xB3, 0x35, 0xDE, 0xBB, 0xD0, 0x6D, + 0x32, 0x35, 0x5C, 0x79, 0xE9, 0xB6, 0xE3, 0xF8, 0x44, 0x60, 0x83, 0xB8, 0xFB, 0xD9, 0xF6, 0xFC, + 0x02, 0xAE, 0xF9, 0x07, 0x53, 0x76, 0x65, 0xD1, 0x3C, 0x9F, 0x9D, 0xE0, 0x00, 0xC7, 0x73, 0xDB, + 0x3D, 0x8F, 0xE6, 0xB4, 0x7B, 0xE6, 0x78, 0xE9, 0xA7, 0x83, 0xA1, 0xB8, 0x11, 0x34, 0xB5, 0xFD, + 0x4A, 0x6C, 0xA2, 0x2B, 0x47, 0x90, 0x2E, 0xA6, 0x85, 0x5C, 0x26, 0x82, 0xE0, 0x00, 0xAB, 0x47, + 0x90, 0x5C, 0xC3, 0x78, 0x3A, 0x20, 0x16, 0x40, 0x11, 0x6C, 0xFF, 0x3A, 0x51, 0x04, 0xCE, 0x08, + 0x77, 0xA9, 0x28, 0x82, 0x03, 0xAC, 0x3F, 0x0F, 0x21, 0x30, 0x2C, 0x80, 0x20, 0xD8, 0xFE, 0xF5, + 0x22, 0x48, 0xF7, 0x97, 0x02, 0x62, 0xF0, 0x0C, 0x1C, 0xCA, 0xBA, 0xDF, 0x2C, 0x83, 0x43, 0xAC, + 0xFB, 0xCB, 0xFC, 0x68, 0xF4, 0x4E, 0x20, 0xF1, 0x4A, 0xD0, 0x08, 0x80, 0xB5, 0x20, 0x22, 0x75, + 0x7F, 0x79, 0x6D, 0xA8, 0x74, 0x63, 0x07, 0x96, 0xDF, 0xB5, 0x0D, 0x6B, 0xBE, 0xE3, 0x88, 0x9A, + 0x17, 0x39, 0x8D, 0x60, 0x80, 0x75, 0xE6, 0x35, 0x31, 0x30, 0xCC, 0x85, 0x22, 0xE3, 0xF6, 0xAF, + 0x17, 0x41, 0x96, 0xC5, 0x6B, 0xCA, 0xE0, 0x50, 0x81, 0xD7, 0xD6, 0x9A, 0x19, 0x25, 0xA0, 0xB9, + 0x20, 0xA6, 0xAD, 0x1F, 0x33, 0x8A, 0x4C, 0x04, 0xCD, 0xEA, 0x6D, 0xA4, 0x31, 0x10, 0xDC, 0x63, + 0xB6, 0xE7, 0x91, 0xE1, 0x7F, 0xFA, 0xD4, 0xA9, 0x9D, 0x84, 0x7F, 0x30, 0xF8, 0x0B, 0x35, 0x68, + 0xC1, 0xAC, 0x57, 0x60, 0xD8, 0xCA, 0x98, 0x50, 0xFE, 0x9E, 0x06, 0x16, 0xF5, 0xC8, 0xF5, 0xD5, + 0x5B, 0xC2, 0xC8, 0xC5, 0x40, 0x23, 0x08, 0x61, 0x8E, 0xD5, 0x3F, 0x03, 0x03, 0x3D, 0x73, 0xE1, + 0xD3, 0x20, 0x30, 0x55, 0x77, 0x7C, 0x71, 0x2F, 0x13, 0x82, 0x92, 0xD1, 0x81, 0x3C, 0x03, 0xC8, + 0x26, 0xB6, 0x83, 0x20, 0x1E, 0x89, 0x00, 0xE7, 0xB7, 0xCC, 0x93, 0xA9, 0xA7, 0xF0, 0x7B, 0xD1, + 0x25, 0xFC, 0xB2, 0x98, 0x1A, 0xF8, 0xF6, 0x08, 0xB3, 0x92, 0xAB, 0xA6, 0xF9, 0x2C, 0x03, 0x64, + 0xA5, 0x03, 0x83, 0xEA, 0x72, 0xCF, 0x67, 0xEA, 0xA3, 0x6A, 0x50, 0xFE, 0xFA, 0x49, 0x1B, 0x47, + 0x8A, 0x61, 0xE2, 0xF5, 0x5A, 0xD6, 0x84, 0xD7, 0x3D, 0x81, 0x12, 0x3D, 0xEE, 0x4F, 0x45, 0x10, + 0xE9, 0xAC, 0xF1, 0x64, 0x70, 0x6A, 0x14, 0x1B, 0x3D, 0xE0, 0xBE, 0x0C, 0x36, 0xBF, 0x36, 0x3C, + 0x7F, 0xE7, 0xED, 0x54, 0x14, 0xF6, 0x48, 0xA7, 0x5F, 0x32, 0x01, 0x78, 0x66, 0x18, 0x6B, 0x8E, + 0xC1, 0xAA, 0x40, 0x8C, 0x6B, 0x6E, 0x38, 0x2B, 0xC6, 0x0C, 0xCF, 0x1E, 0x66, 0xCE, 0x70, 0x57, + 0xEC, 0x38, 0x67, 0x23, 0x25, 0x8C, 0x28, 0x6E, 0xD3, 0x8B, 0x07, 0xBD, 0x42, 0xDB, 0x0A, 0xE2, + 0x5E, 0xC7, 0x5B, 0x9E, 0x1B, 0x89, 0x5E, 0x9C, 0x9E, 0x27, 0xB1, 0xE3, 0x0A, 0x10, 0xFA, 0x1E, + 0xCF, 0x98, 0x42, 0xC6, 0xC5, 0xDB, 0x9B, 0x8B, 0x0E, 0xF9, 0xF3, 0xDD, 0x75, 0x7E, 0xF9, 0x95, + 0x12, 0xBA, 0x21, 0xF9, 0xF9, 0x4F, 0x36, 0x1B, 0xD9, 0x40, 0x7F, 0x9A, 0x3D, 0x1A, 0xD9, 0x16, + 0xB9, 0x2E, 0x61, 0x71, 0x0A, 0xF4, 0x2A, 0x82, 0x3D, 0xF6, 0x84, 0x27, 0xBF, 0x80, 0xD5, 0x43, + 0xE0, 0x27, 0x1D, 0x82, 0xBC, 0xC0, 0xC1, 0x77, 0x3D, 0xE1, 0xCA, 0x0F, 0x64, 0x6F, 0xB1, 0x77, + 0x4A, 0x2C, 0x35, 0x9C, 0x6C, 0xE8, 0x35, 0xD8, 0x85, 0xAA, 0x0D, 0xA3, 0x7E, 0x44, 0x70, 0x91, + 0xE0, 0xB1, 0x72, 0x17, 0xD9, 0xD3, 0xD0, 0x18, 0xBF, 0x21, 0xF2, 0xCD, 0xE9, 0x92, 0xDA, 0xD9, + 0x8E, 0xF2, 0x96, 0x26, 0x8E, 0x69, 0x01, 0xED, 0xBE, 0x8F, 0xB1, 0x48, 0x14, 0xAE, 0x24, 0x7A, + 0xA3, 0xB4, 0xD0, 0x72, 0xCA, 0x3B, 0x4D, 0xF6, 0x11, 0x48, 0x61, 0xFC, 0x65, 0xF4, 0x0D, 0x06, + 0x7C, 0x36, 0xD1, 0xDD, 0x71, 0x97, 0x1D, 0xC8, 0x77, 0xC4, 0x77, 0x32, 0x68, 0xEA, 0x80, 0x51, + 0x6C, 0xE8, 0xDB, 0x18, 0xB7, 0x21, 0x80, 0x01, 0x6F, 0xDB, 0x65, 0x9F, 0x7A, 0xF4, 0xE3, 0x1E, + 0x7F, 0xFC, 0x6D, 0x57, 0x00, 0xF1, 0xE6, 0x2C, 0x16, 0x98, 0x89, 0x27, 0x4C, 0x4B, 0xD9, 0xDC, + 0x74, 0x76, 0x79, 0xF1, 0xD6, 0x39, 0x04, 0x35, 0x23, 0xE9, 0x62, 0x4A, 0xF6, 0xD0, 0x83, 0xD4, + 0xE4, 0xA1, 0xA9, 0x7D, 0xCE, 0x9D, 0xA4, 0x22, 0xCE, 0x1A, 0xA7, 0x13, 0x55, 0x58, 0x23, 0xAE, + 0xCA, 0x6D, 0xF6, 0xB2, 0xB2, 0x54, 0x14, 0x74, 0xBB, 0x8D, 0xF8, 0x2E, 0x25, 0x43, 0xB8, 0xB7, + 0x7B, 0x14, 0x62, 0x67, 0x58, 0x83, 0xB0, 0xFF, 0x71, 0x72, 0x0A, 0xC0, 0x91, 0xE8, 0xDB, 0x10, + 0xCB, 0xBC, 0xA2, 0xA9, 0x2A, 0x8A, 0xC6, 0x9A, 0x2D, 0x09, 0x62, 0x32, 0xD4, 0x79, 0x49, 0x40, + 0xBB, 0x4E, 0xF6, 0x9E, 0x00, 0x99, 0xFC, 0x6E, 0x29, 0x00, 0x4B, 0x4D, 0x46, 0x9C, 0x7E, 0x26, + 0xDB, 0x9E, 0x6A, 0x68, 0xC8, 0x11, 0x7A, 0xBE, 0xCB, 0xD5, 0x51, 0x18, 0x44, 0xE6, 0x15, 0x02, + 0x6B, 0x56, 0x2F, 0xCD, 0x22, 0xB1, 0x68, 0x59, 0xCA, 0x98, 0x47, 0x5D, 0x5C, 0x61, 0xDC, 0x15, + 0x08, 0xA0, 0xD8, 0xE9, 0x1F, 0x20, 0x52, 0x13, 0xD3, 0x92, 0xBD, 0x8B, 0xA0, 0x2C, 0xF8, 0xF2, + 0xB8, 0xA0, 0x2F, 0xF4, 0x98, 0x4F, 0xC5, 0xA3, 0x7B, 0x52, 0x07, 0xA2, 0xF5, 0xA4, 0x7E, 0x53, + 0x3C, 0xD6, 0x73, 0xEE, 0xB0, 0xA0, 0xC4, 0x5C, 0x6D, 0xF2, 0x6B, 0x8D, 0x65, 0xBC, 0x6C, 0x2A, + 0x23, 0xC0, 0x12, 0xF1, 0x78, 0xFE, 0x8E, 0x9A, 0xB5, 0x93, 0x56, 0x25, 0x1D, 0xB5, 0x30, 0x85, + 0x73, 0x15, 0x1D, 0xB5, 0x6B, 0x27, 0x07, 0x95, 0x74, 0xB4, 0x8F, 0x30, 0xAA, 0xA4, 0xA7, 0x03, + 0x04, 0x52, 0x25, 0x3D, 0x1D, 0xE2, 0xE2, 0x2A, 0xE9, 0xE9, 0x1D, 0xAC, 0xAE, 0x82, 0x6E, 0x8E, + 0x60, 0x69, 0x15, 0x74, 0xF3, 0x1E, 0xD6, 0x55, 0x05, 0x36, 0x12, 0x5E, 0x57, 0xD1, 0x51, 0x13, + 0x53, 0xB6, 0x57, 0xD1, 0x11, 0xE0, 0x75, 0xBB, 0x92, 0x19, 0x01, 0x5E, 0x1F, 0x56, 0xD2, 0x11, + 0xE0, 0x75, 0x6B, 0x64, 0x58, 0x15, 0xF4, 0x04, 0x78, 0x7D, 0x50, 0x4D, 0x4F, 0x87, 0xC4, 0x8F, + 0x2A, 0xE9, 0x0A, 0x11, 0xBB, 0xA2, 0x59, 0x1D, 0xE1, 0xDE, 0x55, 0xD3, 0xD5, 0x7B, 0xDC, 0xBD, + 0xF2, 0x5D, 0x15, 0x88, 0xEC, 0x5C, 0x96, 0xD1, 0x63, 0xD2, 0xF8, 0x31, 0xB6, 0x45, 0x84, 0xE7, + 0x25, 0xC5, 0x3A, 0xC5, 0x4F, 0xD2, 0x0D, 0x4C, 0xB4, 0x52, 0x4C, 0xC0, 0x29, 0x2A, 0x2A, 0xCD, + 0x14, 0x63, 0x5A, 0x15, 0x8B, 0x31, 0xCD, 0x84, 0x18, 0xD3, 0x5A, 0x9E, 0x18, 0xD3, 0xCC, 0x14, + 0x63, 0x9A, 0x5B, 0x31, 0x66, 0x2B, 0xC6, 0x6C, 0xC5, 0x98, 0xAD, 0x18, 0xB3, 0x15, 0x63, 0xB6, + 0x62, 0xCC, 0x6B, 0x11, 0x63, 0x5A, 0x1B, 0x99, 0x2F, 0xAE, 0x80, 0x1D, 0xA7, 0xA8, 0x71, 0x2C, + 0x66, 0x3F, 0xC7, 0xCB, 0x11, 0x61, 0x84, 0x5C, 0x7E, 0xF8, 0x74, 0x91, 0xE7, 0x63, 0x5B, 0xED, + 0xCC, 0xF4, 0xA6, 0x94, 0x75, 0xEB, 0x65, 0xD3, 0x9B, 0x8A, 0x5A, 0x94, 0xDE, 0xD2, 0x4A, 0x2A, + 0x9D, 0xC6, 0xFA, 0x2E, 0x75, 0xFF, 0x13, 0x6B, 0x98, 0xB5, 0x21, 0x08, 0xCC, 0x94, 0x72, 0x8A, + 0x59, 0xC5, 0x84, 0xF0, 0x5F, 0x0C, 0xE2, 0x13, 0x29, 0x52, 0x09, 0x08, 0x6B, 0x96, 0x22, 0x75, + 0x36, 0x0C, 0xE6, 0x2E, 0x8E, 0x44, 0x52, 0x32, 0xD9, 0xAE, 0xAF, 0x2C, 0x91, 0x4D, 0x3D, 0xDF, + 0xFD, 0x3E, 0x91, 0x8F, 0x3D, 0x84, 0xD7, 0x3D, 0x3C, 0xEC, 0xC9, 0x8E, 0xC2, 0x2C, 0xED, 0xE1, + 0xF3, 0xA4, 0xAB, 0x84, 0x6C, 0x98, 0x7F, 0x27, 0x1E, 0x57, 0x26, 0xA6, 0x86, 0x38, 0x11, 0x9F, + 0xEA, 0x57, 0xD6, 0xCA, 0x53, 0x05, 0x5C, 0x89, 0x64, 0x7E, 0x8E, 0xCB, 0x35, 0x03, 0x50, 0x28, + 0x4A, 0x43, 0x6A, 0xF7, 0x99, 0xCA, 0x70, 0xA2, 0xCC, 0x93, 0xC9, 0xB2, 0xA8, 0x96, 0xA6, 0xCF, + 0xBE, 0x59, 0x54, 0x00, 0xDC, 0xA7, 0xEC, 0xA3, 0x0F, 0x9C, 0xD9, 0x0F, 0x54, 0x90, 0x52, 0x67, + 0x0F, 0xCF, 0x98, 0xBB, 0xD4, 0x0B, 0xEF, 0x0E, 0x30, 0x7F, 0x29, 0xF6, 0x1C, 0xF6, 0xD8, 0xA0, + 0xEC, 0x7D, 0xD4, 0x23, 0xF4, 0x84, 0xD7, 0x58, 0x94, 0xDC, 0x03, 0xAF, 0xB8, 0x68, 0xE6, 0x22, + 0xF9, 0x96, 0xFA, 0x0D, 0xAF, 0xD5, 0x1C, 0xC7, 0xB5, 0xBF, 0x03, 0x61, 0xFB, 0x98, 0xFC, 0xEA, + 0x50, 0x89, 0xF2, 0x04, 0x3E, 0xD9, 0xAE, 0x3F, 0x14, 0x99, 0xAF, 0x54, 0x3D, 0x2C, 0x21, 0x25, + 0x26, 0x80, 0xB3, 0xC5, 0x0B, 0xFA, 0x3E, 0xCC, 0x2C, 0x5A, 0x04, 0x8E, 0xA6, 0x33, 0xDB, 0x9A, + 0xCC, 0x57, 0x18, 0xA6, 0x37, 0x1C, 0x71, 0x7F, 0x68, 0xEB, 0x4C, 0xD5, 0x86, 0x06, 0xC7, 0x6C, + 0x61, 0xFF, 0xD6, 0x56, 0xB4, 0x51, 0x4A, 0xB2, 0x2F, 0xBC, 0x52, 0x44, 0xF7, 0x80, 0x47, 0x60, + 0x35, 0x0D, 0x76, 0x65, 0x69, 0x30, 0xBE, 0x17, 0x66, 0xFD, 0x0A, 0x73, 0x99, 0x7C, 0x79, 0xC0, + 0xB8, 0x06, 0x31, 0xF0, 0xBD, 0x31, 0xE2, 0x61, 0xFE, 0xD5, 0x3B, 0xE1, 0xA9, 0xA0, 0x63, 0x22, + 0x5E, 0x8B, 0x61, 0xB1, 0xC7, 0x58, 0xFE, 0x02, 0x43, 0xF4, 0xC5, 0xA3, 0x4C, 0x5D, 0x34, 0x16, + 0xDD, 0x70, 0x62, 0x12, 0x31, 0x98, 0x82, 0x81, 0xC9, 0xCD, 0x4E, 0x39, 0x56, 0xD5, 0x1D, 0xBF, + 0x64, 0x78, 0xE1, 0xA4, 0x75, 0x0A, 0x98, 0xA0, 0xC4, 0x89, 0x75, 0x78, 0x65, 0x14, 0xA5, 0x7B, + 0x95, 0x79, 0xC0, 0xA8, 0xF2, 0x15, 0x66, 0xB8, 0xA6, 0x72, 0xB4, 0xE3, 0x1C, 0x2A, 0x8A, 0xC8, + 0x76, 0x76, 0xD0, 0x50, 0x46, 0xE3, 0x1B, 0xC2, 0x43, 0xBA, 0x22, 0x3C, 0x54, 0x14, 0x6F, 0x97, + 0x35, 0x1B, 0xF4, 0x07, 0xBD, 0xB0, 0x99, 0x11, 0x16, 0x21, 0x2B, 0x90, 0xE1, 0x6F, 0x5E, 0xAD, + 0x48, 0x20, 0x65, 0xD8, 0x68, 0xDE, 0x98, 0x8C, 0xC5, 0xDC, 0xD8, 0x26, 0x39, 0x85, 0x3D, 0xC6, + 0x29, 0x99, 0x59, 0x74, 0xA6, 0xA3, 0x63, 0xB3, 0x95, 0x96, 0xEB, 0x07, 0xB1, 0xB3, 0xE0, 0x8D, + 0x57, 0x0C, 0x85, 0x31, 0xDC, 0x86, 0xED, 0x78, 0x6F, 0x8F, 0x8B, 0x5B, 0x33, 0xF2, 0xD2, 0x48, + 0x96, 0xB1, 0x36, 0x94, 0xF3, 0xCC, 0x4F, 0x81, 0x53, 0xD1, 0x71, 0x9C, 0x8C, 0x0E, 0x16, 0x72, + 0x4F, 0x2B, 0x2B, 0x13, 0xBE, 0x00, 0x3E, 0x75, 0x25, 0x73, 0x0B, 0xC3, 0x0A, 0x0B, 0xCA, 0xF2, + 0xE5, 0xB0, 0x2F, 0xE4, 0x7D, 0xC5, 0xFA, 0x26, 0x06, 0xD9, 0x3E, 0x07, 0x3D, 0x00, 0x58, 0x13, + 0x1E, 0xFC, 0x11, 0xB3, 0x2C, 0xD6, 0x7E, 0x67, 0xB4, 0x30, 0xB6, 0x12, 0x9E, 0x4A, 0x94, 0x7D, + 0xC8, 0x8F, 0x7D, 0x5D, 0x18, 0x5B, 0xA7, 0x76, 0x61, 0x6E, 0xB4, 0x9D, 0xEC, 0x69, 0xA5, 0xF8, + 0xBB, 0x44, 0x3F, 0x33, 0x92, 0x14, 0x16, 0x96, 0xE6, 0x2E, 0xB1, 0x97, 0x69, 0x51, 0x2E, 0x32, + 0x3F, 0xA6, 0x08, 0x75, 0x25, 0x85, 0x39, 0x31, 0xC2, 0x09, 0xFD, 0x4A, 0x9C, 0x87, 0xA2, 0xD2, + 0xFD, 0x09, 0xDB, 0x39, 0x1B, 0xDA, 0x98, 0x8F, 0x08, 0x6B, 0x02, 0x33, 0xBB, 0x40, 0x78, 0xC2, + 0x27, 0x59, 0xD8, 0xF8, 0x6D, 0x58, 0x37, 0xF7, 0x85, 0x64, 0xC3, 0xB8, 0x4C, 0xE8, 0xC7, 0x64, + 0xB8, 0x48, 0x12, 0x44, 0xD1, 0x08, 0x24, 0x41, 0xAA, 0xFC, 0x2D, 0xA4, 0x3A, 0x0E, 0x32, 0x09, + 0xC8, 0x2B, 0x72, 0xA9, 0xD1, 0x4A, 0x58, 0xAC, 0x70, 0x32, 0xCA, 0x51, 0x22, 0x8C, 0x14, 0x73, + 0xA2, 0x26, 0x3D, 0xB6, 0x84, 0x68, 0x34, 0x1A, 0x71, 0xDD, 0x10, 0x32, 0xE0, 0x03, 0x1F, 0x18, + 0x61, 0xCE, 0x55, 0x0A, 0x21, 0xBD, 0xBB, 0x3F, 0xBB, 0x99, 0x76, 0xC1, 0xEC, 0x48, 0xB9, 0x32, + 0x12, 0xDC, 0x0C, 0x4F, 0x48, 0x85, 0x91, 0x90, 0x4A, 0xC2, 0x52, 0xB7, 0xDB, 0x65, 0x3B, 0x8E, + 0x49, 0x72, 0x97, 0xC7, 0x41, 0x84, 0x0D, 0x5C, 0xE6, 0x07, 0xBE, 0x0D, 0x0A, 0x9B, 0xF9, 0x96, + 0xAA, 0x82, 0xE2, 0x5B, 0x13, 0xC2, 0x13, 0x53, 0x07, 0xD0, 0x05, 0xBA, 0x80, 0xC2, 0x3C, 0xC9, + 0x73, 0x4C, 0x8B, 0x64, 0xE3, 0x98, 0x60, 0x15, 0x56, 0x78, 0x7F, 0xE3, 0x8D, 0xE1, 0x86, 0x79, + 0xA8, 0xED, 0xC0, 0xD4, 0xB9, 0xBB, 0x0B, 0x3A, 0x9A, 0x69, 0x03, 0x7E, 0xD9, 0x1B, 0x2A, 0x53, + 0x11, 0x7C, 0xAB, 0x88, 0x57, 0x2D, 0x94, 0x59, 0x20, 0x83, 0xA8, 0x69, 0x12, 0x42, 0x87, 0x0C, + 0xD1, 0x09, 0x29, 0x50, 0x94, 0xE2, 0x96, 0x35, 0xB5, 0x24, 0x06, 0x24, 0xC8, 0x5C, 0x29, 0x1E, + 0x02, 0x30, 0xE6, 0x03, 0xF3, 0x38, 0x83, 0x13, 0x63, 0x98, 0x35, 0x4B, 0x2A, 0x0C, 0xCE, 0xC6, + 0x5F, 0x44, 0xB9, 0x0C, 0x66, 0xDF, 0x85, 0x15, 0xF4, 0x6A, 0x0F, 0xCB, 0x75, 0xE7, 0xED, 0xD3, + 0x52, 0xA5, 0x8E, 0x58, 0xEB, 0x31, 0x04, 0xF7, 0x23, 0x61, 0x41, 0x44, 0xC5, 0x1C, 0x4D, 0x49, + 0x0C, 0x45, 0xAF, 0x0C, 0xB3, 0x5C, 0xC0, 0x02, 0x8F, 0x20, 0x1C, 0x03, 0x6D, 0xA1, 0x02, 0x4F, + 0x25, 0x2C, 0x99, 0x91, 0x5B, 0xD8, 0xF4, 0x50, 0xE8, 0x12, 0x76, 0x8D, 0x01, 0xF0, 0xB4, 0xBD, + 0x97, 0xE8, 0x80, 0x8E, 0xDE, 0x89, 0x05, 0x9D, 0xC1, 0x56, 0x60, 0x7E, 0xED, 0x06, 0x32, 0xDF, + 0xB6, 0xCC, 0x01, 0x28, 0x26, 0x1A, 0xE3, 0xCA, 0x68, 0x95, 0xB5, 0xE9, 0x0D, 0xC1, 0x49, 0x7F, + 0xDD, 0xFB, 0x6D, 0xEF, 0x77, 0x84, 0x14, 0xF7, 0x1A, 0xAF, 0xDC, 0x2E, 0xBB, 0x2A, 0x6A, 0x48, + 0x54, 0xA1, 0x68, 0xCF, 0x73, 0x19, 0x4D, 0x5B, 0x73, 0x01, 0x04, 0xFE, 0x6B, 0x2D, 0x93, 0xC4, + 0xE2, 0x34, 0xF5, 0x6B, 0x19, 0xA9, 0xB8, 0xCC, 0x35, 0x7B, 0x9A, 0xAE, 0x77, 0xB4, 0x1C, 0x99, + 0x39, 0xB6, 0xE6, 0x72, 0x22, 0xF2, 0xB8, 0xE1, 0xEB, 0xD1, 0xE8, 0x96, 0x83, 0x4D, 0xBF, 0x15, + 0xC3, 0xA6, 0xDF, 0x5E, 0x13, 0x36, 0xFD, 0x36, 0x2F, 0x36, 0xFD, 0xB6, 0xC5, 0xA6, 0xD9, 0xD8, + 0xF4, 0x7B, 0x31, 0x6C, 0xFA, 0xFD, 0x35, 0x61, 0xD3, 0xEF, 0xF3, 0x62, 0xD3, 0xEF, 0x5B, 0x6C, + 0x4A, 0xC5, 0x26, 0x0B, 0x04, 0x2D, 0x14, 0xE8, 0x85, 0x68, 0x5F, 0x04, 0x9F, 0x0A, 0x56, 0x7E, + 0x7D, 0x61, 0x94, 0xCA, 0x8B, 0xB9, 0x8D, 0x2F, 0xBB, 0x1C, 0x4A, 0xC5, 0x9B, 0xBE, 0x32, 0x13, + 0xE6, 0xC9, 0x59, 0x18, 0xFC, 0xF5, 0x15, 0xAF, 0x75, 0x62, 0x72, 0xF7, 0x1A, 0x14, 0xD6, 0xA2, + 0x62, 0x2D, 0x68, 0x69, 0xE8, 0x27, 0xC4, 0x69, 0x69, 0x1A, 0xA1, 0x04, 0xD3, 0x20, 0x58, 0xFF, + 0x19, 0xC0, 0xF6, 0xC0, 0x02, 0x34, 0xDB, 0x79, 0xDE, 0x73, 0x30, 0xEE, 0x54, 0x5A, 0x51, 0xA6, + 0x44, 0xF0, 0x8D, 0x17, 0xBC, 0xCB, 0xD4, 0xA6, 0x5A, 0x36, 0x43, 0x2A, 0xA5, 0x78, 0x4D, 0x52, + 0x11, 0xC5, 0x2E, 0x66, 0x94, 0x01, 0x07, 0x7E, 0x23, 0xDF, 0x3C, 0x16, 0x3B, 0x26, 0x01, 0x54, + 0xD0, 0xA7, 0x55, 0x0C, 0x1A, 0x77, 0xFF, 0xEC, 0x09, 0x83, 0x52, 0x0C, 0xB7, 0x05, 0xEB, 0xC3, + 0x49, 0x65, 0x7D, 0xE7, 0x19, 0x3F, 0xC8, 0x3B, 0xB0, 0x38, 0x92, 0x44, 0xE1, 0x57, 0xDF, 0xEB, + 0x4F, 0x86, 0xEE, 0x0F, 0x8F, 0xDB, 0x07, 0x4A, 0xC1, 0xE0, 0xAB, 0x2C, 0xCF, 0x24, 0x54, 0x7C, + 0x85, 0xB9, 0xAB, 0xC3, 0xEA, 0xCD, 0xD6, 0x91, 0xD2, 0x52, 0x0E, 0x1B, 0x07, 0x87, 0x47, 0xAC, + 0xBE, 0xFF, 0xAE, 0x79, 0x78, 0xA4, 0xEC, 0x37, 0xF6, 0x95, 0x36, 0xDB, 0x57, 0x8E, 0x0E, 0x0F, + 0x0F, 0x0F, 0x1A, 0xFB, 0x47, 0xFB, 0x95, 0xF8, 0x7A, 0x86, 0x63, 0x9E, 0xAE, 0x6A, 0xCC, 0x36, + 0x8D, 0x79, 0xB6, 0xAA, 0xE1, 0xF6, 0x6B, 0x27, 0x1D, 0x3C, 0xD1, 0xEE, 0x87, 0xAA, 0x7F, 0xE5, + 0xDD, 0xDB, 0xF6, 0xB5, 0x6D, 0x0D, 0xEE, 0xED, 0x53, 0x7E, 0x2E, 0xF0, 0x10, 0xB8, 0x4A, 0xE6, + 0x4C, 0xCA, 0x55, 0xB3, 0x9B, 0x7F, 0xDA, 0x25, 0x9C, 0xCB, 0xD6, 0x51, 0x48, 0x99, 0xBA, 0xC9, + 0xAA, 0xD2, 0x1A, 0xA5, 0xEA, 0x7A, 0x52, 0x74, 0xA9, 0xD8, 0x04, 0x25, 0xFB, 0x47, 0xBB, 0x53, + 0x47, 0xD7, 0xCB, 0xDA, 0x99, 0x66, 0xC4, 0x51, 0xAA, 0xCB, 0x9D, 0x77, 0x38, 0x40, 0x68, 0x30, + 0xAB, 0x6C, 0xE6, 0x3A, 0xA0, 0xA2, 0xCF, 0x97, 0x3A, 0xF7, 0xF1, 0x10, 0x38, 0xFB, 0x73, 0xFA, + 0x6B, 0x7D, 0x2C, 0x7C, 0x80, 0x06, 0x20, 0x68, 0xEC, 0x8A, 0x92, 0xC2, 0xAA, 0x4E, 0x59, 0x30, + 0x76, 0xC9, 0xA0, 0x17, 0x95, 0x7B, 0x77, 0xB9, 0x06, 0x27, 0x48, 0x4C, 0xCC, 0xA0, 0xB7, 0xC5, + 0xB2, 0x98, 0xE1, 0x37, 0x7E, 0x52, 0xFF, 0xCB, 0x72, 0x29, 0x63, 0x96, 0x70, 0x7F, 0xF1, 0x09, + 0x6B, 0x49, 0xCC, 0xB8, 0xBE, 0x68, 0xAE, 0xC3, 0xF5, 0xC5, 0x27, 0xAA, 0x38, 0x21, 0xEF, 0xF3, + 0x2A, 0xBF, 0xB5, 0x18, 0xC8, 0x8E, 0x5F, 0xD0, 0xFB, 0xE6, 0xE5, 0xEE, 0x2D, 0x3E, 0x45, 0x8B, + 0x1F, 0xDF, 0x5D, 0x94, 0x8E, 0xEF, 0x99, 0xC9, 0xED, 0x12, 0x77, 0x17, 0x29, 0xC3, 0x45, 0xF7, + 0x17, 0xD7, 0xD7, 0xC3, 0xE2, 0x23, 0x6F, 0xC2, 0x3D, 0x07, 0x2C, 0x68, 0xF2, 0x6A, 0x03, 0x1F, + 0x6D, 0x2F, 0x36, 0x2A, 0x74, 0x2E, 0x22, 0xB0, 0x5E, 0xAB, 0x7E, 0x81, 0x64, 0x2F, 0x99, 0xDE, + 0x44, 0xFB, 0x13, 0x49, 0xFB, 0xF6, 0xA7, 0x08, 0x0D, 0x06, 0x30, 0xFC, 0x40, 0xE7, 0x55, 0xF8, + 0xA5, 0x1D, 0x2E, 0xC3, 0x78, 0x93, 0x00, 0xC3, 0x1C, 0xF6, 0x40, 0xD9, 0xF4, 0x55, 0xFA, 0x9F, + 0x89, 0x05, 0xA2, 0x0E, 0xB3, 0x5C, 0x1C, 0x81, 0x11, 0x36, 0x01, 0x49, 0x42, 0x40, 0xCC, 0x83, + 0x25, 0xB2, 0xED, 0xEB, 0x32, 0x1C, 0x0B, 0x11, 0xDE, 0x27, 0x39, 0xF5, 0x12, 0x2B, 0x1A, 0xFB, + 0xA9, 0x56, 0xDF, 0x92, 0xA6, 0xE4, 0xAC, 0xDC, 0x7C, 0x20, 0xBC, 0x8B, 0xA1, 0x98, 0x18, 0xEB, + 0xB8, 0x6C, 0xE0, 0x6E, 0x68, 0x2E, 0x4A, 0x4E, 0x79, 0xB6, 0xC1, 0x68, 0xA3, 0xEF, 0xAE, 0xCB, + 0xB7, 0x4E, 0xE5, 0x00, 0x1D, 0x53, 0xF0, 0xF0, 0x5A, 0x3E, 0x71, 0x4F, 0x67, 0xDC, 0xFC, 0xDC, + 0xB9, 0x28, 0x7E, 0x5C, 0xDF, 0xA8, 0xEE, 0xB7, 0x3D, 0x18, 0x0E, 0x5D, 0x43, 0xE7, 0x3C, 0xE4, + 0x2B, 0x92, 0x4C, 0x62, 0xD2, 0xC9, 0x67, 0x8E, 0x6D, 0x59, 0xE7, 0xC1, 0x7E, 0xE4, 0xEC, 0xC2, + 0x34, 0x0D, 0xC7, 0xB3, 0x0D, 0x3D, 0x74, 0xAF, 0x03, 0x38, 0x7C, 0x93, 0xF1, 0x09, 0x86, 0x14, + 0x62, 0x22, 0x09, 0x0D, 0x15, 0x35, 0x55, 0x02, 0x2F, 0xFE, 0x3E, 0x3E, 0x1F, 0xD9, 0x56, 0x40, + 0x75, 0xC3, 0x65, 0xBC, 0x03, 0x6E, 0x93, 0xA5, 0x97, 0x12, 0x6E, 0x96, 0x2F, 0xE0, 0x94, 0x12, + 0x72, 0x8A, 0x1B, 0x92, 0x73, 0x99, 0xF8, 0x7E, 0x29, 0x19, 0xAF, 0xFC, 0xED, 0x5F, 0x84, 0xD1, + 0x85, 0x97, 0x55, 0xF0, 0xDE, 0xA9, 0xE8, 0x7B, 0xCE, 0xF4, 0x5C, 0x2A, 0x49, 0xB0, 0xBA, 0x54, + 0xCE, 0x42, 0xA8, 0x96, 0xCE, 0x28, 0x99, 0xCC, 0x0D, 0x66, 0xF2, 0xBE, 0x7F, 0xBC, 0x5F, 0xC6, + 0x3A, 0x9D, 0xA6, 0x75, 0x0B, 0xAD, 0x1A, 0x29, 0x45, 0x78, 0x12, 0xC7, 0x1C, 0x7F, 0x63, 0xB6, + 0xB4, 0xBF, 0x07, 0x9E, 0x0F, 0xDC, 0x05, 0xB5, 0xA0, 0x52, 0x8C, 0x8D, 0x42, 0xDB, 0x54, 0x53, + 0x83, 0xB6, 0xC8, 0x6F, 0x30, 0x01, 0xB9, 0x28, 0x1D, 0xCA, 0x19, 0x3C, 0x22, 0x1E, 0x34, 0xCF, + 0xC9, 0xB2, 0x14, 0xCD, 0xE8, 0xAA, 0x1F, 0x56, 0x2F, 0xDD, 0x8D, 0x26, 0x27, 0x4A, 0xC4, 0xCA, + 0x29, 0x53, 0x20, 0xD7, 0x7F, 0xF6, 0x82, 0x07, 0xDF, 0x55, 0xA9, 0xFC, 0xEA, 0x7F, 0x26, 0x6E, + 0x12, 0x3A, 0xF7, 0x76, 0xE0, 0xB7, 0x65, 0xA9, 0x4C, 0xF2, 0x30, 0x8C, 0x21, 0xEA, 0xDC, 0x75, + 0xC7, 0xC9, 0x56, 0x23, 0xEE, 0x14, 0xE5, 0x34, 0x84, 0xEE, 0xA8, 0x1E, 0x11, 0x16, 0x57, 0x0F, + 0x3D, 0x7C, 0xC7, 0xFC, 0x6D, 0x08, 0x3D, 0x3C, 0xB3, 0xA7, 0x21, 0xB7, 0x64, 0x80, 0x96, 0x28, + 0xF8, 0x4A, 0x4C, 0x8D, 0xDC, 0x70, 0x55, 0x79, 0x43, 0xE6, 0xD8, 0xC0, 0x7E, 0x86, 0x89, 0x51, + 0x77, 0x29, 0x58, 0x2A, 0xB0, 0xC4, 0x0B, 0xD4, 0x24, 0xAA, 0xEE, 0xDE, 0x60, 0xB7, 0xB6, 0xCF, + 0x8F, 0x29, 0xE8, 0x2C, 0x5A, 0x27, 0xED, 0x3A, 0x05, 0x4F, 0x99, 0x4F, 0xEA, 0xB3, 0x27, 0x2D, + 0x61, 0xB2, 0x34, 0xED, 0x10, 0x03, 0x28, 0x33, 0x2E, 0x18, 0x99, 0x8F, 0x20, 0xDB, 0x4C, 0x45, + 0xB1, 0x50, 0xBE, 0xD8, 0x82, 0xA1, 0xC9, 0x1B, 0x4C, 0xEA, 0xAD, 0x0C, 0x52, 0x67, 0xC5, 0xF2, + 0x19, 0xA7, 0x93, 0xBC, 0x09, 0x7D, 0x74, 0xBA, 0x67, 0x93, 0x14, 0x0F, 0x8F, 0xD6, 0x96, 0xE0, + 0x61, 0x6E, 0x29, 0xF4, 0xAE, 0xEA, 0x7A, 0x51, 0x52, 0x97, 0xB4, 0x52, 0x94, 0xD0, 0xB7, 0x64, + 0x58, 0x9A, 0x0C, 0x57, 0xAA, 0x8D, 0x4B, 0x0C, 0xCE, 0x97, 0xC4, 0x0F, 0xD2, 0x24, 0x71, 0x44, + 0xA7, 0xE2, 0xB2, 0xF5, 0x12, 0xD1, 0x7C, 0xB6, 0x4C, 0x1D, 0xA2, 0x72, 0x77, 0x48, 0x71, 0xF2, + 0x84, 0xE1, 0x49, 0x19, 0xDB, 0x0B, 0x46, 0xE1, 0xCB, 0xAA, 0x7C, 0x59, 0x1C, 0x36, 0xBB, 0xCC, + 0xA1, 0x46, 0x1A, 0x35, 0x12, 0x69, 0x75, 0xE9, 0xA8, 0x11, 0x5F, 0x13, 0x82, 0xA3, 0x7F, 0x87, + 0xCB, 0xB8, 0x6E, 0x10, 0x7E, 0xEE, 0x32, 0x6F, 0x88, 0x07, 0x12, 0xE6, 0xB5, 0x40, 0x64, 0x43, + 0x9D, 0x90, 0xC2, 0x67, 0x00, 0xA5, 0x5F, 0xAF, 0x2F, 0xC7, 0x4C, 0xF1, 0xFB, 0x60, 0x89, 0x8E, + 0x77, 0x21, 0x02, 0x87, 0x89, 0x98, 0xE7, 0x30, 0xA6, 0x88, 0x2E, 0x56, 0x68, 0x4A, 0x11, 0x17, + 0x26, 0xAB, 0xA2, 0xF3, 0xD0, 0x9B, 0x25, 0xB4, 0xF8, 0xD7, 0xE6, 0xB1, 0xA9, 0x91, 0x63, 0xDD, + 0x8B, 0x93, 0xF9, 0x27, 0x38, 0x54, 0x44, 0xD4, 0x18, 0x45, 0xC6, 0x83, 0x74, 0x18, 0x2E, 0x8E, + 0x3D, 0xF0, 0x3E, 0xE6, 0xF7, 0x16, 0x27, 0x19, 0x86, 0xA5, 0xC9, 0xD3, 0x24, 0x4A, 0x19, 0x4E, + 0x4E, 0x58, 0x71, 0x47, 0x2B, 0x74, 0xD8, 0xFA, 0x49, 0x09, 0xF2, 0x70, 0x99, 0x6E, 0x8B, 0x11, + 0x9E, 0xCD, 0xE7, 0xBA, 0x18, 0x36, 0xDF, 0xBA, 0x2F, 0xAE, 0x8A, 0xAA, 0xAA, 0x77, 0x5F, 0xBC, + 0x56, 0xFD, 0x3D, 0x34, 0x51, 0xA3, 0xED, 0x6D, 0xEB, 0xC5, 0x58, 0x8D, 0x11, 0x76, 0x6E, 0x2F, + 0xC6, 0x90, 0xA0, 0x0A, 0x7A, 0x32, 0x16, 0xDF, 0xA6, 0xF8, 0x2E, 0x57, 0xEF, 0xF9, 0x38, 0x3E, + 0xAE, 0xD2, 0xBD, 0x1F, 0xC7, 0xDF, 0xAF, 0x9D, 0x07, 0xE4, 0xBE, 0xD2, 0x50, 0xDE, 0x2B, 0xAD, + 0xF7, 0xFB, 0xEF, 0xDE, 0xB3, 0x7A, 0x53, 0x39, 0x68, 0x34, 0x8F, 0x0E, 0x94, 0x83, 0x77, 0x87, + 0x4D, 0xD6, 0x3C, 0x38, 0x84, 0xEF, 0x8E, 0xDE, 0x57, 0xEC, 0xFE, 0xB8, 0x8A, 0x01, 0x43, 0xDF, + 0xC7, 0x55, 0x8C, 0x55, 0xC0, 0xF1, 0x31, 0x73, 0x1A, 0xE5, 0xEC, 0xDD, 0x73, 0xCE, 0x79, 0xEB, + 0xF5, 0x38, 0xD3, 0xEB, 0x71, 0x5A, 0xD4, 0xAC, 0xDE, 0xF3, 0x31, 0x1C, 0x63, 0x19, 0xDE, 0x8F, + 0x4B, 0x9F, 0x7F, 0x7C, 0x90, 0x25, 0x79, 0x41, 0x2E, 0x7D, 0x0D, 0xC9, 0x61, 0x5E, 0x81, 0x37, + 0x64, 0xFC, 0x3C, 0xFB, 0xB9, 0x9C, 0x22, 0x97, 0x96, 0xC2, 0x25, 0xB5, 0xC2, 0x5E, 0xBB, 0x40, + 0x72, 0x95, 0xD9, 0x05, 0xF5, 0x84, 0x49, 0xF3, 0x16, 0xAB, 0xD8, 0xF5, 0xB8, 0xFB, 0x88, 0x55, + 0x76, 0x2F, 0xE8, 0x91, 0x2C, 0x4A, 0x2F, 0x1E, 0x16, 0xC8, 0x98, 0xB2, 0x48, 0x11, 0xBD, 0x94, + 0x49, 0xAC, 0x2C, 0x37, 0x0B, 0xE8, 0x10, 0x42, 0x0F, 0x16, 0xEB, 0xF5, 0x68, 0x7C, 0x94, 0xD1, + 0x03, 0x87, 0x30, 0x3D, 0x4C, 0xD4, 0xF2, 0xC6, 0x9B, 0x4C, 0x93, 0x22, 0x12, 0xCB, 0x61, 0xD1, + 0x3B, 0xD4, 0x93, 0xB1, 0xA1, 0xA1, 0xF1, 0x06, 0xFB, 0x42, 0x19, 0x5B, 0x74, 0x8E, 0x7F, 0x09, + 0xC1, 0xDF, 0xC7, 0x4B, 0x19, 0x55, 0xC3, 0xFC, 0x27, 0x52, 0x91, 0x4E, 0xF6, 0x13, 0x88, 0xB4, + 0x28, 0x96, 0x9C, 0x82, 0x46, 0xD5, 0x04, 0x53, 0xEA, 0xE0, 0x6D, 0x68, 0xAA, 0x13, 0x6B, 0xBC, + 0xAF, 0xF3, 0x27, 0xD2, 0xF8, 0x50, 0xA4, 0xBE, 0x4F, 0x6A, 0x66, 0xD3, 0x82, 0x05, 0xF0, 0x92, + 0xDC, 0x3F, 0x9F, 0x29, 0x14, 0x2A, 0x82, 0x37, 0xB5, 0x74, 0x25, 0x23, 0xC9, 0x69, 0xFE, 0x78, + 0x13, 0x59, 0x50, 0x53, 0x7A, 0x2E, 0xC0, 0xC9, 0xE2, 0x34, 0xCD, 0x9A, 0x98, 0xD9, 0xB4, 0x8A, + 0xAA, 0x77, 0x02, 0x17, 0xF2, 0x2B, 0xDF, 0x95, 0xF2, 0x0B, 0x4F, 0x26, 0x3C, 0x2D, 0xBF, 0xDC, + 0x65, 0x14, 0x29, 0xAB, 0xDE, 0x8B, 0x27, 0xBE, 0x2E, 0xAA, 0x9E, 0xF9, 0xD9, 0xF6, 0xFC, 0x79, + 0xAA, 0x2A, 0x2D, 0xA3, 0x34, 0x7C, 0xF8, 0x0F, 0xE7, 0x74, 0xBC, 0xB0, 0xFF, 0xC8, 0x51, 0x39, + 0x7B, 0x59, 0x69, 0x9B, 0x59, 0x06, 0x24, 0xCB, 0x0C, 0xE7, 0xCC, 0xEA, 0x69, 0x61, 0x2B, 0xDA, + 0x3C, 0xEE, 0x2A, 0x2F, 0x8E, 0x8F, 0x5D, 0xDB, 0x5D, 0x3B, 0x7C, 0xC4, 0x39, 0xBD, 0x3C, 0x3E, + 0xE6, 0x5E, 0xAA, 0x64, 0xC1, 0xB2, 0x02, 0x8C, 0x14, 0x3D, 0xFD, 0x9C, 0x18, 0x09, 0x02, 0x9B, + 0xBB, 0x6E, 0x18, 0x89, 0x73, 0xDA, 0x3C, 0x0E, 0x29, 0x21, 0x59, 0x01, 0x3E, 0x8A, 0x9E, 0x7E, + 0x5E, 0x7C, 0xEC, 0xFE, 0x52, 0x15, 0x46, 0xEE, 0x67, 0x38, 0xEB, 0xCE, 0x83, 0x91, 0xAC, 0xFB, + 0xCB, 0xE2, 0x48, 0xF9, 0xAE, 0xDC, 0xBD, 0x73, 0x25, 0x48, 0x49, 0xE0, 0xAC, 0x08, 0x2D, 0xB1, + 0xAF, 0x9F, 0x0D, 0x31, 0x6F, 0xEC, 0xC0, 0xF2, 0xBB, 0x78, 0xAF, 0xBB, 0x6C, 0x46, 0x49, 0x23, + 0x95, 0x39, 0xB9, 0x61, 0x4E, 0x9B, 0xC4, 0x28, 0x13, 0x90, 0x5C, 0x08, 0x23, 0xE3, 0x3D, 0xFD, + 0xBC, 0xF8, 0xB8, 0x7C, 0x46, 0x39, 0x0F, 0x46, 0x6E, 0x18, 0xA3, 0x9C, 0x00, 0x67, 0x45, 0x68, + 0xF9, 0x62, 0x8C, 0x72, 0x91, 0x77, 0x8A, 0xD9, 0x14, 0x5E, 0x81, 0xE1, 0xA8, 0xB9, 0x34, 0xC3, + 0x51, 0xB3, 0xB4, 0xE1, 0xA8, 0xB5, 0xC9, 0x86, 0xA3, 0xE6, 0x6B, 0x36, 0x1C, 0x35, 0xB7, 0x86, + 0xA3, 0x8A, 0x0C, 0x47, 0xCD, 0xCA, 0x0C, 0x47, 0xCD, 0x9F, 0xD8, 0x70, 0xD4, 0xDC, 0x1A, 0x8E, + 0x2A, 0x33, 0x1C, 0x35, 0x2B, 0x33, 0x1C, 0x35, 0x7F, 0x62, 0xC3, 0x51, 0x73, 0x6B, 0x38, 0xAA, + 0xC8, 0x70, 0xD4, 0xAC, 0xCC, 0x70, 0xD4, 0xFC, 0xA9, 0x0D, 0x47, 0xCD, 0xAD, 0xE1, 0xA8, 0x4A, + 0xC3, 0x51, 0xB3, 0x42, 0xC3, 0x51, 0xF3, 0x27, 0x36, 0x1C, 0x35, 0xB7, 0x86, 0xA3, 0x8A, 0x0C, + 0x47, 0xCD, 0xCA, 0x0C, 0x47, 0xCD, 0x9F, 0xDA, 0x70, 0xD4, 0xDC, 0x1A, 0x8E, 0xAA, 0x34, 0x1C, + 0x35, 0x2B, 0x34, 0x1C, 0x35, 0xB7, 0x86, 0xA3, 0x75, 0x35, 0x1C, 0xB5, 0x96, 0x66, 0x38, 0x6A, + 0x95, 0x36, 0x1C, 0xB5, 0x37, 0xD9, 0x70, 0xD4, 0x7A, 0xCD, 0x86, 0xA3, 0xD6, 0xD6, 0x70, 0x54, + 0x91, 0xE1, 0xA8, 0x55, 0x99, 0xE1, 0xA8, 0xF5, 0x13, 0x1B, 0x8E, 0x5A, 0x5B, 0xC3, 0x51, 0x65, + 0x86, 0xA3, 0x56, 0x65, 0x86, 0xA3, 0xD6, 0x4F, 0x6C, 0x38, 0x6A, 0x6D, 0x0D, 0x47, 0x15, 0x19, + 0x8E, 0x5A, 0x95, 0x19, 0x8E, 0x5A, 0x3F, 0xB5, 0xE1, 0xA8, 0xB5, 0x35, 0x1C, 0x55, 0x69, 0x38, + 0x6A, 0x55, 0x68, 0x38, 0x6A, 0xFD, 0xC4, 0x86, 0xA3, 0xD6, 0xD6, 0x70, 0x54, 0x91, 0xE1, 0xA8, + 0x55, 0x99, 0xE1, 0xA8, 0xF5, 0x53, 0x1B, 0x8E, 0x5A, 0x5B, 0xC3, 0x51, 0x95, 0x86, 0xA3, 0x56, + 0x85, 0x86, 0xA3, 0xD6, 0xD6, 0x70, 0xB4, 0xAE, 0x86, 0xA3, 0xF6, 0xD2, 0x0C, 0x47, 0xED, 0xD2, + 0x86, 0xA3, 0xFD, 0x4D, 0x36, 0x1C, 0xB5, 0x5F, 0xB3, 0xE1, 0xA8, 0xBD, 0x35, 0x1C, 0x55, 0x64, + 0x38, 0x6A, 0x57, 0x66, 0x38, 0x6A, 0xFF, 0xC4, 0x86, 0xA3, 0xF6, 0xD6, 0x70, 0x54, 0x99, 0xE1, + 0xA8, 0x5D, 0x99, 0xE1, 0xA8, 0xFD, 0x13, 0x1B, 0x8E, 0xDA, 0x5B, 0xC3, 0x51, 0x45, 0x86, 0xA3, + 0x76, 0x65, 0x86, 0xA3, 0xF6, 0x4F, 0x6D, 0x38, 0x6A, 0x6F, 0x0D, 0x47, 0x55, 0x1A, 0x8E, 0xDA, + 0x15, 0x1A, 0x8E, 0xDA, 0x3F, 0xB1, 0xE1, 0xA8, 0xBD, 0x35, 0x1C, 0x55, 0x64, 0x38, 0x6A, 0x57, + 0x66, 0x38, 0x6A, 0xFF, 0xD4, 0x86, 0xA3, 0xF6, 0xD6, 0x70, 0x54, 0xA5, 0xE1, 0xA8, 0x5D, 0xA1, + 0xE1, 0xA8, 0xFD, 0xCA, 0x0C, 0x47, 0xF9, 0xB9, 0x94, 0x66, 0x75, 0x2D, 0xCD, 0x49, 0x51, 0x42, + 0xB9, 0x01, 0xF7, 0x6F, 0xB8, 0xE7, 0xA9, 0x03, 0x7E, 0x6D, 0x78, 0x3E, 0x16, 0x1F, 0xA5, 0x02, + 0x0D, 0x73, 0x59, 0x9B, 0x72, 0xB2, 0x68, 0x25, 0x72, 0xE6, 0x15, 0xB2, 0x34, 0x85, 0xCF, 0xB1, + 0xBE, 0x81, 0xB0, 0x90, 0xDC, 0x78, 0x03, 0x9C, 0x63, 0xCE, 0x50, 0xA9, 0xD6, 0xA8, 0x49, 0x63, + 0x53, 0x76, 0xE7, 0x39, 0xDB, 0x77, 0x77, 0x7F, 0x76, 0xC3, 0xEE, 0x28, 0xF1, 0xEE, 0x07, 0x83, + 0x50, 0x0F, 0xB3, 0x7E, 0x41, 0xE3, 0x33, 0x34, 0x2E, 0xD5, 0x2A, 0xB1, 0x3E, 0x15, 0xB1, 0x3C, + 0x15, 0xCE, 0x6E, 0x46, 0x73, 0x74, 0x7D, 0x6D, 0x84, 0x93, 0xBE, 0xB2, 0xFA, 0x76, 0x81, 0x52, + 0x80, 0x32, 0xE7, 0x19, 0xAD, 0x15, 0xF3, 0xF5, 0xBB, 0xAA, 0xE5, 0x8D, 0x0C, 0x3F, 0x56, 0x74, + 0x02, 0x17, 0xCD, 0x54, 0xCC, 0x07, 0xAE, 0x8B, 0xF4, 0x63, 0x98, 0xC9, 0xB8, 0xF9, 0xF9, 0x07, + 0x25, 0xE1, 0x1F, 0x09, 0x9C, 0xF2, 0x58, 0x53, 0x51, 0x0E, 0x76, 0xE1, 0xE7, 0xBB, 0x7D, 0xFC, + 0x79, 0x44, 0x3F, 0xDF, 0xE3, 0xCF, 0x66, 0x6B, 0x5F, 0x64, 0xF6, 0x57, 0x1A, 0x61, 0xA3, 0x66, + 0xAB, 0xAD, 0xC8, 0x12, 0x01, 0x32, 0x0B, 0xB2, 0x69, 0x3F, 0x51, 0x5D, 0x0C, 0xFC, 0x96, 0x8A, + 0x8D, 0x78, 0xA2, 0x42, 0x0D, 0x3C, 0x87, 0xF1, 0x2D, 0x9D, 0x12, 0xC9, 0x62, 0xD6, 0x40, 0x5F, + 0x35, 0x4C, 0xDB, 0x95, 0xF5, 0x2C, 0xE4, 0x5C, 0xA1, 0xF7, 0xE7, 0x3D, 0xD5, 0x34, 0xC5, 0x86, + 0x85, 0x33, 0x6A, 0xB0, 0x6B, 0x03, 0xBE, 0xF4, 0x8E, 0x99, 0x82, 0x2F, 0xB7, 0x94, 0x78, 0xBD, + 0x0C, 0x51, 0x0F, 0x87, 0x80, 0x07, 0xE3, 0xF9, 0x54, 0x31, 0xC3, 0x06, 0x86, 0xE2, 0x1A, 0xBA, + 0xCE, 0x2D, 0x7C, 0x1F, 0xE7, 0x4A, 0xA5, 0x73, 0x0C, 0x8B, 0x21, 0xB2, 0xB0, 0x91, 0xAD, 0xF3, + 0x0D, 0x4C, 0xB7, 0x96, 0x6A, 0x90, 0x9C, 0x8B, 0x24, 0x96, 0x61, 0x93, 0xA4, 0x3E, 0x93, 0x8D, + 0x1F, 0x6C, 0xA0, 0x87, 0x51, 0xD4, 0x3E, 0x97, 0x0F, 0xA7, 0x66, 0xEA, 0x4C, 0xCF, 0xCA, 0x19, + 0x2B, 0x53, 0xE3, 0x72, 0x8F, 0xFB, 0xF7, 0x36, 0x62, 0x8C, 0x4C, 0xAA, 0x47, 0x15, 0x7A, 0xEF, + 0xF0, 0x31, 0x6C, 0x7F, 0xB1, 0xB3, 0x22, 0x6C, 0x59, 0x30, 0x29, 0x67, 0xE1, 0x52, 0x40, 0x2F, + 0x0C, 0x90, 0x6B, 0xFB, 0xE9, 0x34, 0xA4, 0xB9, 0x08, 0x28, 0xC5, 0x20, 0x82, 0x89, 0x3E, 0x81, + 0x64, 0xA3, 0xE6, 0x40, 0x83, 0xD6, 0xB7, 0x92, 0xE0, 0x29, 0x00, 0x20, 0xC4, 0xE1, 0x51, 0xF2, + 0x34, 0xAB, 0xAD, 0x24, 0x1B, 0x67, 0x91, 0xE7, 0xE9, 0x23, 0x7D, 0xF8, 0x87, 0x7A, 0x9D, 0xD5, + 0xC3, 0x7F, 0xA1, 0xE4, 0xC6, 0xDD, 0x3E, 0xA6, 0xE9, 0x16, 0x34, 0x18, 0xFB, 0xBA, 0x5E, 0x9F, + 0xEC, 0x34, 0x46, 0x7C, 0x3A, 0x88, 0xB6, 0x86, 0xCE, 0x06, 0xAA, 0x93, 0x5E, 0xB1, 0x3B, 0xE3, + 0x2A, 0x29, 0xF3, 0xEE, 0x08, 0xA1, 0xE9, 0x38, 0x61, 0x22, 0xC6, 0x22, 0xC7, 0x77, 0x3A, 0x90, + 0xD2, 0xCF, 0xF4, 0x6E, 0x37, 0xEC, 0xB9, 0xD4, 0x69, 0x1D, 0x35, 0x4B, 0x1F, 0x2B, 0x99, 0x69, + 0x3D, 0x6B, 0xF3, 0x85, 0x68, 0x98, 0x00, 0x72, 0xE0, 0x8A, 0x8A, 0x31, 0xF2, 0x44, 0x77, 0x62, + 0x6F, 0x54, 0x70, 0xAC, 0x67, 0xA0, 0x7A, 0x2A, 0x9A, 0xE4, 0x72, 0xE7, 0x08, 0x04, 0x69, 0x03, + 0x65, 0x33, 0xE3, 0x79, 0x45, 0xC6, 0x73, 0xCA, 0x4F, 0xCA, 0xAE, 0xCE, 0x8F, 0x43, 0x49, 0x7B, + 0x08, 0x7D, 0x3E, 0xC1, 0x9A, 0xAF, 0xCE, 0x67, 0xA4, 0xB6, 0xDF, 0xEB, 0xA0, 0x70, 0x3D, 0x3B, + 0x35, 0xFD, 0x39, 0x96, 0xA2, 0x02, 0x51, 0xDD, 0x30, 0xD9, 0x37, 0x0E, 0x1F, 0x01, 0x09, 0x0C, + 0x97, 0x47, 0xE3, 0xE8, 0xF0, 0xF5, 0x1D, 0x1F, 0xA9, 0x86, 0x65, 0x58, 0x83, 0x19, 0x43, 0xD9, + 0xEC, 0xAF, 0xD0, 0x3A, 0x5B, 0x96, 0x7F, 0xE9, 0x9C, 0xB9, 0x71, 0x74, 0x3B, 0x8B, 0x32, 0xBA, + 0x7A, 0x51, 0xFE, 0xDC, 0xF8, 0xF7, 0xB3, 0xB9, 0x55, 0xAC, 0x35, 0x5B, 0x49, 0xA6, 0xDD, 0xCC, + 0xA9, 0xAF, 0x34, 0xEB, 0xEE, 0x75, 0x1D, 0x4F, 0x0E, 0xB6, 0xC7, 0xAE, 0xBA, 0x49, 0xDA, 0xD5, + 0x62, 0xF0, 0x20, 0xA9, 0x4C, 0x7D, 0x04, 0x41, 0x90, 0x2A, 0x96, 0x4D, 0x27, 0xC5, 0xDD, 0xCC, + 0x9C, 0xB8, 0x03, 0x6E, 0x0F, 0x5C, 0xD5, 0x19, 0x1A, 0xDA, 0x1D, 0x1F, 0xC0, 0x42, 0xCF, 0x5D, + 0xDB, 0x11, 0xAC, 0x26, 0x17, 0x37, 0x09, 0x05, 0x27, 0xDB, 0xD7, 0x4E, 0x3E, 0x45, 0x4F, 0x98, + 0x78, 0x54, 0xC0, 0x4C, 0x90, 0x2C, 0x1C, 0x31, 0xD5, 0x67, 0xEA, 0x4C, 0x93, 0x7A, 0xBF, 0x2E, + 0xE7, 0x1D, 0x65, 0xF0, 0x9D, 0xB9, 0x15, 0xC9, 0xD2, 0x04, 0x4A, 0xED, 0xE4, 0x6B, 0xAF, 0x60, + 0xB5, 0x80, 0xE9, 0x1A, 0x11, 0x17, 0x5F, 0xE7, 0x6B, 0x0A, 0xB3, 0xEC, 0xCC, 0xD9, 0x14, 0x38, + 0xC7, 0x5F, 0xEF, 0xE6, 0x6B, 0xBA, 0x5F, 0x3B, 0xF9, 0xAF, 0x2A, 0x60, 0x4D, 0x81, 0xD6, 0x05, + 0x0A, 0x22, 0x54, 0x4C, 0x8C, 0x3D, 0x81, 0x05, 0xCF, 0x76, 0xE0, 0xB2, 0xF1, 0x76, 0x33, 0x97, + 0xF6, 0x5B, 0xAA, 0x6E, 0xA0, 0x0D, 0x02, 0x5F, 0x16, 0xF9, 0xAB, 0x25, 0xE1, 0xF6, 0x5D, 0xFE, + 0x67, 0xC0, 0x2D, 0xED, 0x99, 0x14, 0x3E, 0x81, 0x1D, 0xAA, 0x19, 0xE3, 0x66, 0x20, 0x77, 0x38, + 0x86, 0x16, 0xA3, 0xD9, 0xAF, 0xBD, 0x35, 0xA3, 0x56, 0x21, 0x40, 0xB9, 0x8B, 0xD1, 0xB2, 0xE3, + 0xF4, 0xB8, 0x8F, 0x39, 0xC0, 0xBD, 0xEC, 0x13, 0x7C, 0xC1, 0x63, 0xA9, 0xF0, 0xD1, 0xA4, 0x06, + 0xBE, 0x0D, 0xC7, 0xE6, 0x1D, 0xB7, 0xF8, 0x93, 0x6A, 0x02, 0xAA, 0xC3, 0xDF, 0x78, 0x8E, 0x32, + 0xF9, 0xA4, 0x68, 0x25, 0x9E, 0x45, 0xCE, 0x98, 0xC9, 0x39, 0x94, 0xD8, 0xF1, 0x05, 0x8B, 0x16, + 0x48, 0x7C, 0xFE, 0x05, 0xCF, 0x0C, 0x12, 0x3D, 0x90, 0x3D, 0x31, 0x58, 0x2E, 0x68, 0x29, 0xAD, + 0x23, 0x86, 0x92, 0x07, 0x2A, 0x2D, 0x24, 0x90, 0x3C, 0xEF, 0x32, 0x9C, 0x28, 0x96, 0x14, 0xC4, + 0xFA, 0xA3, 0x80, 0xC4, 0xBE, 0xCF, 0x47, 0x0E, 0x55, 0x3B, 0x03, 0xBC, 0xB3, 0x90, 0x22, 0xE0, + 0xE3, 0x9B, 0xCF, 0xF6, 0x88, 0xBF, 0x61, 0x16, 0xF7, 0x9F, 0x6C, 0xF7, 0xDB, 0x2E, 0xA8, 0x50, + 0x20, 0x35, 0xA9, 0xD8, 0xD5, 0x2E, 0x7E, 0xED, 0xE2, 0x22, 0x69, 0xAC, 0x18, 0x9A, 0x0B, 0x01, + 0x40, 0x2F, 0x5E, 0xCE, 0xB5, 0xEA, 0x0A, 0x07, 0x05, 0x88, 0xA2, 0x8C, 0x7F, 0x53, 0x39, 0x03, + 0x7B, 0xFC, 0x98, 0x8A, 0x0B, 0xDC, 0x42, 0xE2, 0xEC, 0xBA, 0x76, 0xDF, 0x30, 0xF9, 0xBD, 0xFD, + 0x8D, 0x17, 0x71, 0x5D, 0xCB, 0xBD, 0xE7, 0x99, 0xAE, 0xAF, 0x27, 0x25, 0x5B, 0x39, 0x10, 0xA3, + 0x91, 0x8E, 0x4B, 0xEE, 0x44, 0x05, 0xC5, 0x33, 0xC6, 0x55, 0x63, 0x89, 0xAF, 0xDA, 0xEE, 0x40, + 0xB5, 0x8C, 0x1F, 0x42, 0x1D, 0x19, 0xAA, 0x1E, 0x56, 0x0E, 0xB0, 0x5D, 0xC7, 0x26, 0x7B, 0x14, + 0x70, 0x58, 0x6B, 0xD0, 0xF3, 0x5D, 0xAE, 0x8E, 0x88, 0x97, 0x26, 0xA4, 0x21, 0x55, 0xD3, 0xD0, + 0xF0, 0xBD, 0x2B, 0xAA, 0x14, 0x18, 0x24, 0x12, 0xB9, 0x1C, 0x7B, 0x65, 0x48, 0xA3, 0xD4, 0xBB, + 0x16, 0x78, 0x80, 0xCA, 0xB2, 0xE8, 0x00, 0x73, 0xE4, 0xD2, 0x7D, 0x5C, 0x7A, 0x1C, 0x2F, 0x01, + 0xBD, 0x9F, 0x59, 0x9D, 0x89, 0x92, 0x07, 0x9C, 0xF5, 0x1C, 0xD5, 0xFD, 0x76, 0x19, 0x58, 0x02, + 0x46, 0xB5, 0x79, 0xAA, 0x8C, 0x54, 0x5A, 0x94, 0xA3, 0x20, 0x6E, 0x17, 0x62, 0x60, 0x59, 0x37, + 0x71, 0xEF, 0x0A, 0x51, 0x65, 0x89, 0xCB, 0x8E, 0x1C, 0x14, 0x2F, 0x5E, 0x72, 0x7E, 0x76, 0x47, + 0x95, 0xD4, 0xA0, 0xAF, 0x90, 0x1D, 0x54, 0x7C, 0x6E, 0x91, 0x28, 0xE1, 0xF9, 0x70, 0x6C, 0x7C, + 0x75, 0x80, 0xF0, 0x38, 0xDA, 0xA1, 0xE8, 0x09, 0x1D, 0x5E, 0xE2, 0xD9, 0x2A, 0xCE, 0xAE, 0xE9, + 0x79, 0xBC, 0xCC, 0xE9, 0x25, 0x6B, 0x69, 0x8B, 0x12, 0x3B, 0x09, 0x76, 0x40, 0xE7, 0xDA, 0x93, + 0x61, 0x9A, 0x68, 0x49, 0x97, 0xD3, 0xE5, 0x3A, 0xB1, 0x8D, 0x80, 0xA6, 0xAC, 0xA3, 0xF9, 0x1E, + 0x9B, 0x59, 0x80, 0xB8, 0xCC, 0x76, 0xB0, 0xA8, 0x74, 0x60, 0x19, 0xFE, 0xF3, 0x1C, 0xCA, 0xD3, + 0xFA, 0x1F, 0x51, 0xB8, 0x69, 0x81, 0xC7, 0x3B, 0x9E, 0x67, 0x78, 0xFE, 0xAD, 0xFD, 0x74, 0x16, + 0xEE, 0x6B, 0xD9, 0x2A, 0xEC, 0xC5, 0x11, 0xBA, 0x30, 0x52, 0xC7, 0xE7, 0x05, 0xA2, 0x58, 0xF8, + 0xB1, 0x4C, 0xD9, 0xD1, 0x45, 0x70, 0x39, 0x39, 0xFC, 0x8B, 0x9D, 0x80, 0x84, 0xCF, 0x51, 0xE5, + 0xF4, 0x31, 0x14, 0x6E, 0x3E, 0x75, 0x44, 0xF9, 0x9B, 0x69, 0x64, 0x06, 0xC1, 0xCA, 0x18, 0xC1, + 0x29, 0xF6, 0x28, 0x8B, 0xA0, 0xAB, 0xDA, 0x9F, 0x81, 0xE1, 0x19, 0x74, 0x76, 0x3A, 0x40, 0x07, + 0x58, 0x09, 0xDA, 0xD2, 0xF8, 0x9C, 0x08, 0xBD, 0x16, 0x87, 0x58, 0x25, 0x0C, 0x59, 0xEE, 0x32, + 0x56, 0x2F, 0x34, 0x8D, 0x1F, 0x5C, 0x07, 0x28, 0xF8, 0xAE, 0xF1, 0x10, 0x50, 0x7D, 0xC7, 0xF5, + 0x22, 0x84, 0xD4, 0x39, 0x8A, 0xC2, 0x8B, 0xF4, 0x98, 0xC5, 0x9F, 0x57, 0x5A, 0xB9, 0x77, 0x41, + 0x12, 0xCA, 0x98, 0xF8, 0x9A, 0x90, 0x93, 0x19, 0xC1, 0x2F, 0x6E, 0x34, 0xC3, 0x8B, 0x55, 0x92, + 0x0B, 0x4D, 0x59, 0xD7, 0x32, 0xA2, 0x31, 0x2A, 0x40, 0x6B, 0x58, 0x40, 0x65, 0x6A, 0x54, 0xD3, + 0x1D, 0xC5, 0x19, 0x90, 0x26, 0x2C, 0x1F, 0xD4, 0xC3, 0x58, 0x2F, 0x9B, 0x4F, 0x5D, 0x05, 0xEF, + 0x96, 0xCC, 0xB4, 0x1D, 0xBE, 0x07, 0xC1, 0xEB, 0x9A, 0x3F, 0x72, 0xB3, 0x88, 0x65, 0x2E, 0x4D, + 0xF5, 0x99, 0xDD, 0x6B, 0x16, 0xE6, 0x33, 0x7C, 0x83, 0xD1, 0x2B, 0x25, 0xDC, 0x7C, 0x92, 0x76, + 0xBC, 0x9C, 0x91, 0x0B, 0xAC, 0xB9, 0x20, 0x46, 0xCE, 0x6D, 0x08, 0xCC, 0x36, 0x08, 0x36, 0x15, + 0x45, 0x61, 0xDF, 0xD1, 0xBF, 0x40, 0xF9, 0x36, 0x22, 0x05, 0xC5, 0xE3, 0x65, 0x0B, 0x8A, 0x4E, + 0x99, 0x0A, 0x0F, 0xA8, 0xCF, 0x83, 0xCA, 0xBA, 0x84, 0xF5, 0xB5, 0x0E, 0xB0, 0x4B, 0xF8, 0x59, + 0x51, 0x97, 0xED, 0xC9, 0xA5, 0x7F, 0x06, 0xCE, 0x00, 0x04, 0x68, 0xC1, 0xA9, 0xF7, 0xBC, 0x58, + 0xD7, 0xFB, 0x49, 0x00, 0x54, 0xD7, 0xF1, 0x41, 0x12, 0x0C, 0x73, 0x76, 0x5C, 0xA6, 0xFE, 0xEB, + 0x72, 0x38, 0xAA, 0x34, 0x7F, 0x22, 0x2B, 0x1C, 0xB3, 0x53, 0x3D, 0x4E, 0x94, 0x3E, 0x12, 0xA5, + 0x89, 0x94, 0xD1, 0x48, 0x2C, 0x13, 0xB5, 0x71, 0x2C, 0x7B, 0x39, 0x82, 0xB1, 0x75, 0xAE, 0x37, + 0x24, 0x2A, 0xB0, 0x91, 0xFA, 0x8C, 0xCC, 0x56, 0xE7, 0x0E, 0x7C, 0x8B, 0x22, 0x79, 0x8C, 0x97, + 0x66, 0x81, 0x6C, 0x43, 0x78, 0xEB, 0x6C, 0x8B, 0x69, 0x79, 0xF9, 0x66, 0x65, 0x37, 0xF0, 0xAE, + 0xEF, 0xAD, 0xC3, 0xCD, 0x3B, 0xCE, 0x63, 0x69, 0x97, 0xEF, 0xF1, 0xCE, 0xCB, 0xDD, 0xBF, 0xC7, + 0x5A, 0x66, 0xDE, 0xAE, 0x8F, 0x21, 0x38, 0x75, 0xAD, 0x8E, 0xAD, 0xD7, 0xED, 0x3E, 0x7D, 0xF6, + 0x92, 0xE6, 0xBD, 0x52, 0x4F, 0xB1, 0x89, 0xC2, 0x46, 0xE7, 0x15, 0xAF, 0x44, 0x64, 0xBC, 0xB4, + 0xC3, 0xAA, 0xA0, 0xC2, 0xDB, 0x0D, 0xA8, 0x18, 0x88, 0x95, 0xBB, 0x78, 0x67, 0x72, 0xDE, 0xB9, + 0xEF, 0x30, 0x04, 0xE3, 0x2E, 0xF3, 0x86, 0xA0, 0x1B, 0xF5, 0x03, 0x10, 0xD7, 0x24, 0xB7, 0x45, + 0x1F, 0xA5, 0x29, 0x3C, 0x4D, 0x15, 0x64, 0xC2, 0xEE, 0x70, 0xE9, 0x5F, 0x9C, 0xDC, 0x2B, 0xDD, + 0x44, 0x5B, 0xF2, 0xC3, 0xC3, 0x86, 0x67, 0x43, 0xD5, 0xB2, 0x62, 0x62, 0x4F, 0xB8, 0xE0, 0xA2, + 0xE7, 0x7A, 0x5C, 0x06, 0x8A, 0x3A, 0x3D, 0x55, 0x03, 0x10, 0x1E, 0xEF, 0xF0, 0x4F, 0x42, 0x24, + 0x86, 0x0F, 0xC8, 0xDB, 0xF2, 0x98, 0xCD, 0x2B, 0xE6, 0x24, 0x3B, 0x4F, 0x2E, 0x42, 0x3C, 0x4A, + 0x93, 0x4F, 0xE6, 0x14, 0x4D, 0xF6, 0x8F, 0x14, 0x90, 0x4E, 0xF0, 0xE7, 0x62, 0x67, 0xE6, 0xFB, + 0x43, 0xEC, 0x07, 0x7F, 0x2E, 0x28, 0xD5, 0xBC, 0x6F, 0x61, 0x47, 0xF4, 0x6B, 0x41, 0xC9, 0xE3, + 0x68, 0x1F, 0x7B, 0xA2, 0x5F, 0x0B, 0xCA, 0x03, 0xEF, 0x68, 0x71, 0xF4, 0x6B, 0xC1, 0xD5, 0x35, + 0x0F, 0xC4, 0xF2, 0xE8, 0xF7, 0x82, 0xC2, 0x5A, 0x5B, 0xA1, 0x05, 0x8A, 0xDF, 0x0B, 0x8A, 0x52, + 0x87, 0x8A, 0xC0, 0x03, 0xFA, 0xBD, 0x20, 0x26, 0xB4, 0x9A, 0x02, 0x17, 0xE8, 0xF7, 0x46, 0x09, + 0x4C, 0xF7, 0xE4, 0x27, 0x0C, 0x04, 0x4C, 0x97, 0x17, 0xA8, 0x6C, 0xA2, 0xEC, 0x74, 0xD7, 0x39, + 0xBF, 0xFA, 0x42, 0x4C, 0x2C, 0xF4, 0xF3, 0xD5, 0x80, 0x95, 0x0C, 0x84, 0x39, 0x67, 0xA4, 0xFA, + 0x1A, 0xB0, 0x3C, 0xD4, 0x3F, 0x5D, 0xAC, 0xA4, 0x3C, 0xB4, 0x91, 0x0F, 0x82, 0x02, 0x4A, 0x24, + 0x1B, 0x13, 0x8F, 0x08, 0x7B, 0x1E, 0x1C, 0xEF, 0x55, 0x8A, 0x43, 0x05, 0x79, 0x31, 0xEE, 0x52, + 0xD5, 0xAC, 0x78, 0xA2, 0xCF, 0xDA, 0xC9, 0x4D, 0xF0, 0x9D, 0xC9, 0x3F, 0xE6, 0xE7, 0xC1, 0x93, + 0xBD, 0xA6, 0x4D, 0xBF, 0x52, 0x3E, 0x0C, 0x04, 0x73, 0x7B, 0x73, 0xD1, 0x59, 0x58, 0x25, 0xEC, + 0x76, 0x7B, 0x7B, 0x17, 0x8F, 0xE8, 0x10, 0x7E, 0x0F, 0x04, 0x30, 0xC0, 0x0A, 0xE7, 0x8B, 0x69, + 0x84, 0xC2, 0x4B, 0x35, 0xF8, 0x2E, 0x17, 0x0D, 0xFB, 0x73, 0xD5, 0x3A, 0x5B, 0x58, 0x27, 0xEC, + 0x9C, 0x9F, 0xED, 0x9D, 0x77, 0xCE, 0x36, 0x8E, 0x3B, 0x44, 0xF2, 0x4C, 0xC4, 0x0A, 0xA4, 0xDC, + 0x28, 0xBD, 0xFE, 0x75, 0xA3, 0xDF, 0xE7, 0x2E, 0x82, 0x5F, 0x75, 0x1C, 0xD3, 0x10, 0x46, 0x2A, + 0xAF, 0xC1, 0x70, 0x6F, 0x51, 0xA9, 0x22, 0x33, 0x15, 0xBE, 0x08, 0xEC, 0xC2, 0x00, 0xF9, 0xE8, + 0xFE, 0xD7, 0xBD, 0xBB, 0x5F, 0x91, 0x5D, 0x44, 0x06, 0x2D, 0xA4, 0x72, 0x77, 0x44, 0x9F, 0x1B, + 0x0C, 0x77, 0x53, 0xEE, 0x63, 0xA2, 0xB5, 0x13, 0x80, 0xD0, 0x8B, 0x16, 0x63, 0xE8, 0x07, 0x66, + 0xA0, 0x33, 0x3B, 0xF0, 0xD1, 0x18, 0x88, 0x97, 0x25, 0x07, 0x96, 0x87, 0x57, 0xAB, 0x01, 0xF1, + 0x30, 0x3F, 0x6C, 0x8C, 0x36, 0x41, 0x98, 0x07, 0xEC, 0x5D, 0xD4, 0x11, 0xDE, 0xD5, 0x5A, 0x4C, + 0xD5, 0x75, 0xB2, 0x3F, 0xC3, 0x64, 0x7A, 0xE7, 0x9D, 0xBD, 0xDE, 0xD9, 0xB5, 0x30, 0x5E, 0x6B, + 0x62, 0xBF, 0x1B, 0xEC, 0x97, 0x21, 0xE7, 0xE6, 0xDE, 0xB9, 0xE1, 0xB2, 0x7B, 0x43, 0xFB, 0x96, + 0x98, 0x06, 0xF9, 0x19, 0xD8, 0xBE, 0xF1, 0xC8, 0x61, 0x00, 0x10, 0xD1, 0xFA, 0xAA, 0x66, 0x58, + 0x83, 0x06, 0x93, 0xBB, 0x9B, 0x78, 0x57, 0xDE, 0xE4, 0xF6, 0x0D, 0x77, 0x84, 0xCE, 0x98, 0x13, + 0xF0, 0x89, 0xD8, 0x24, 0x02, 0xEA, 0x75, 0x5A, 0xE3, 0x42, 0xEE, 0x81, 0x22, 0x5C, 0xA5, 0x9C, + 0x4F, 0xC8, 0xA0, 0xE7, 0xB8, 0x69, 0x55, 0x89, 0xA0, 0x89, 0xAE, 0xA7, 0x66, 0xBF, 0x15, 0x40, + 0xB7, 0x02, 0xE8, 0x56, 0x00, 0x5D, 0x8A, 0x53, 0x8D, 0x25, 0x4E, 0x0A, 0x8C, 0xD2, 0xDA, 0x95, + 0x61, 0x6B, 0x93, 0xE2, 0xE8, 0xF4, 0x11, 0x94, 0x29, 0x8D, 0xC6, 0x78, 0x6C, 0x8C, 0xC5, 0x0A, + 0x18, 0x6F, 0x8E, 0x28, 0x5A, 0x92, 0xCF, 0x46, 0xC6, 0x02, 0x3C, 0x23, 0x43, 0xA3, 0xD1, 0x84, + 0x45, 0xA5, 0xB0, 0x31, 0x7F, 0xC1, 0x4B, 0xC4, 0xC2, 0x17, 0x89, 0xE2, 0xDE, 0xEB, 0x22, 0x3E, + 0xF5, 0xC8, 0xDF, 0x3E, 0x7C, 0x5A, 0x22, 0xA0, 0x1A, 0xDB, 0x97, 0x0C, 0xA6, 0x5E, 0xDC, 0xF9, + 0x7E, 0x62, 0xF6, 0x73, 0xE0, 0x56, 0x05, 0x84, 0x14, 0x23, 0xA6, 0x4F, 0xDC, 0xE2, 0x44, 0x39, + 0xAA, 0x00, 0x08, 0xC6, 0x29, 0xB1, 0x9E, 0x94, 0x97, 0x40, 0x78, 0x81, 0xF7, 0x46, 0x32, 0x2E, + 0x74, 0x14, 0x00, 0xD9, 0xF4, 0x29, 0x5F, 0xC5, 0xAE, 0x30, 0x62, 0x01, 0x16, 0x61, 0x60, 0xA5, + 0x94, 0xA4, 0xB4, 0xE7, 0x06, 0x43, 0xBF, 0x1D, 0xC3, 0xE5, 0x9E, 0xB8, 0xB9, 0x77, 0xB9, 0xC6, + 0x9D, 0x09, 0xC2, 0x92, 0xEE, 0x91, 0xA2, 0x83, 0xA6, 0xA2, 0xEC, 0x2A, 0x8A, 0x12, 0x78, 0x52, + 0x58, 0x33, 0xB9, 0x35, 0x20, 0xE3, 0x98, 0xCE, 0xDE, 0x47, 0x5F, 0x89, 0x19, 0x70, 0xFF, 0x89, + 0x73, 0x4B, 0xBC, 0xE7, 0x35, 0x4A, 0xC5, 0x92, 0x2F, 0x8D, 0x32, 0xCB, 0x29, 0x8A, 0xE5, 0xD2, + 0x1B, 0x64, 0x50, 0xE9, 0x39, 0xC7, 0xB0, 0x58, 0x6F, 0x7E, 0x62, 0x5D, 0xCC, 0xBD, 0x33, 0x4B, + 0xCC, 0x4A, 0xCC, 0xF4, 0x1E, 0x36, 0xEC, 0x54, 0xEC, 0x97, 0x40, 0xF3, 0xE2, 0x7D, 0xCE, 0xE9, + 0xF5, 0x79, 0x3F, 0x8D, 0x22, 0x6C, 0xE7, 0xFF, 0xFE, 0x1F, 0xEF, 0xED, 0x71, 0x89, 0xE5, 0x94, + 0x62, 0x05, 0x8B, 0xBB, 0x19, 0x66, 0xBA, 0x1C, 0xCE, 0xCA, 0xD7, 0x55, 0xAE, 0x5B, 0xFC, 0x37, + 0x85, 0x47, 0x53, 0xBB, 0x53, 0x76, 0xAE, 0x4E, 0x7E, 0x9F, 0x95, 0xA4, 0x67, 0x28, 0x72, 0x95, + 0x34, 0x1F, 0x81, 0xAD, 0x80, 0x06, 0xAE, 0x89, 0x93, 0x2D, 0x1F, 0xF3, 0xBB, 0x31, 0xBE, 0x59, + 0x6E, 0x30, 0x41, 0x1F, 0x1B, 0x81, 0xF5, 0xD3, 0x08, 0x27, 0xC1, 0x5B, 0x01, 0xEA, 0x8A, 0x9E, + 0x36, 0x05, 0x61, 0xE9, 0xC2, 0x8D, 0x28, 0x4C, 0x1F, 0xF0, 0xB9, 0x15, 0xE4, 0x5C, 0xEC, 0xED, + 0xDA, 0xA6, 0xEA, 0xE2, 0xB5, 0xF4, 0x8A, 0xF0, 0x37, 0x1C, 0xEF, 0x78, 0x1E, 0x2E, 0x9C, 0x50, + 0xCA, 0xD3, 0x97, 0x31, 0xBD, 0xED, 0x8B, 0xAD, 0x70, 0x2E, 0x9D, 0x3E, 0xDB, 0xA8, 0x79, 0x67, + 0x78, 0x86, 0x35, 0x60, 0xB8, 0xA7, 0x25, 0xB5, 0xBA, 0x6C, 0x1B, 0xE7, 0xA5, 0x6A, 0x9A, 0x0B, + 0x74, 0x5A, 0x42, 0xCD, 0x5B, 0xA6, 0x94, 0x3A, 0x61, 0x59, 0x14, 0x52, 0xA2, 0x67, 0x0C, 0xD0, + 0x12, 0x17, 0x7A, 0xB5, 0x0D, 0xD1, 0x8F, 0x42, 0x44, 0x8A, 0x6A, 0x64, 0x66, 0xDB, 0x71, 0x05, + 0x3C, 0x39, 0x2C, 0xFD, 0x2D, 0x4A, 0xB1, 0x18, 0x01, 0x94, 0x78, 0xA1, 0x2F, 0x81, 0x43, 0x6F, + 0xC4, 0x84, 0xD3, 0xD8, 0x46, 0x94, 0xDE, 0xD5, 0xA5, 0x4A, 0x99, 0xA5, 0x24, 0xCD, 0x32, 0x7C, + 0x68, 0x81, 0xA4, 0x5B, 0x2B, 0xD1, 0xF2, 0x3E, 0xCB, 0xB8, 0x74, 0x32, 0xD7, 0x5F, 0xDB, 0x83, + 0x01, 0x86, 0x8D, 0x4B, 0xA5, 0xAF, 0x38, 0xE8, 0xCA, 0x6B, 0x87, 0xE2, 0x7A, 0x40, 0x0E, 0xB8, + 0x1A, 0x2D, 0xB1, 0xF8, 0xE4, 0xA6, 0xD5, 0xC9, 0x74, 0x30, 0xBD, 0xB8, 0x76, 0x09, 0x33, 0x19, + 0xBB, 0x39, 0x84, 0x72, 0x39, 0xC7, 0x39, 0x7A, 0x6F, 0x85, 0x06, 0xD8, 0x56, 0x22, 0x4B, 0xBC, + 0xF6, 0xCC, 0xEE, 0x6E, 0x7A, 0x0D, 0x0C, 0x50, 0xEA, 0x07, 0xA6, 0x34, 0xE5, 0x60, 0x60, 0x25, + 0x33, 0x8D, 0x6F, 0xA0, 0x64, 0x06, 0xE8, 0x3F, 0xE0, 0xBB, 0x86, 0x6A, 0x0D, 0x02, 0x53, 0xDA, + 0x6B, 0x7A, 0x5C, 0x04, 0x33, 0xA1, 0x00, 0x0A, 0xB4, 0xF5, 0x0D, 0x4D, 0xFD, 0xC4, 0x08, 0xA5, + 0x77, 0xEB, 0xEF, 0x17, 0xE7, 0xF5, 0xCB, 0xF7, 0x5D, 0x76, 0x65, 0xF9, 0x7C, 0x20, 0xFD, 0x56, + 0x6E, 0x54, 0x2B, 0x50, 0x45, 0xFF, 0x23, 0xDB, 0xE5, 0xC9, 0xCB, 0x84, 0x7C, 0x05, 0xB6, 0xAC, + 0x3B, 0xEC, 0xEB, 0x50, 0x41, 0xE3, 0x88, 0x55, 0x9D, 0x0E, 0x4A, 0x23, 0x60, 0xCF, 0x4B, 0x13, + 0x67, 0x68, 0xDE, 0xAB, 0x13, 0x67, 0x04, 0xDB, 0xA8, 0x5E, 0x9C, 0x49, 0x2E, 0x63, 0x7A, 0x67, + 0xD6, 0x4A, 0x9C, 0xC1, 0xB4, 0x40, 0xBE, 0x4D, 0xFE, 0x8D, 0x95, 0x89, 0x33, 0xE4, 0x2C, 0x29, + 0x52, 0x0E, 0xBD, 0x1A, 0x69, 0x26, 0xE2, 0x8C, 0x44, 0x02, 0x91, 0x3C, 0x63, 0x02, 0x95, 0x71, + 0x9D, 0xA1, 0xE7, 0xE9, 0x30, 0x4C, 0xD3, 0x66, 0x4C, 0x30, 0xA1, 0x18, 0x88, 0xB7, 0x82, 0xCA, + 0xFC, 0x66, 0xF0, 0x00, 0x14, 0xA9, 0xF0, 0x1C, 0xC5, 0xCC, 0x05, 0xE4, 0xA3, 0xB6, 0x96, 0x26, + 0xEF, 0xD8, 0xEC, 0x26, 0x2C, 0xDE, 0x8C, 0x1E, 0x17, 0xDF, 0x9D, 0x58, 0xCA, 0x97, 0x97, 0xB0, + 0x7E, 0x97, 0x02, 0x73, 0x39, 0x42, 0xCC, 0x18, 0xA8, 0x60, 0x76, 0xC4, 0x14, 0x22, 0x95, 0x90, + 0x8E, 0xE8, 0x94, 0xDC, 0x95, 0xE2, 0x51, 0x32, 0xC7, 0x94, 0x87, 0x70, 0xEF, 0xEB, 0xE9, 0xAF, + 0x7B, 0xBD, 0x6E, 0xE7, 0xEE, 0xFE, 0x16, 0xA9, 0x36, 0x94, 0x39, 0xBE, 0xC2, 0x83, 0x56, 0x8C, + 0x66, 0x2F, 0xD5, 0x92, 0xD6, 0xB6, 0x8D, 0x96, 0x1A, 0x22, 0xF0, 0x0B, 0xC0, 0xF4, 0xEC, 0xC0, + 0xD5, 0x52, 0x8E, 0xF8, 0xF2, 0x04, 0x13, 0x1E, 0xEF, 0xA9, 0x03, 0x00, 0x75, 0x84, 0x9B, 0x25, + 0x37, 0x44, 0x3C, 0x2F, 0x7B, 0x12, 0x4F, 0x9D, 0xC2, 0xA9, 0xA3, 0xDD, 0x03, 0xC6, 0xD7, 0x66, + 0x2E, 0xB8, 0x7C, 0x0A, 0xE1, 0xB9, 0xCF, 0xE2, 0xE9, 0x33, 0x53, 0x64, 0x6A, 0x99, 0xE7, 0xB8, + 0x9C, 0x3A, 0xD2, 0xAF, 0xBA, 0x65, 0xAF, 0x9B, 0xCB, 0x9D, 0xB8, 0x4B, 0xD4, 0x41, 0x28, 0x64, + 0x4E, 0x22, 0x43, 0x3C, 0x4C, 0x0E, 0xFD, 0x6B, 0x30, 0xCA, 0xD4, 0xD0, 0xC5, 0x61, 0x4B, 0xE4, + 0x2A, 0xF3, 0x2C, 0xC4, 0xF3, 0xDD, 0x78, 0xB4, 0x91, 0x0D, 0xF2, 0xE0, 0xBE, 0xBD, 0xF8, 0x52, + 0x3F, 0x7F, 0x7F, 0x76, 0xCC, 0x24, 0x7A, 0x08, 0x08, 0xC7, 0x68, 0xFC, 0xAA, 0xBB, 0xC9, 0x57, + 0x53, 0x8B, 0xBC, 0x53, 0x20, 0x68, 0x15, 0xFD, 0xE0, 0x3B, 0xE6, 0x13, 0xE6, 0x61, 0x21, 0x3F, + 0x77, 0xC9, 0x5E, 0x49, 0xD3, 0x92, 0xBE, 0x59, 0x98, 0x98, 0x95, 0x7D, 0xED, 0x9D, 0x16, 0xF0, + 0x79, 0x5F, 0x62, 0x3E, 0x02, 0x71, 0x86, 0x7C, 0xB2, 0x3C, 0xEF, 0xDE, 0xFE, 0xEA, 0x3D, 0xF4, + 0xC8, 0x0D, 0x2D, 0x3A, 0x78, 0x27, 0xE7, 0x9B, 0x0F, 0x5F, 0x58, 0xD0, 0x0A, 0xB2, 0x17, 0x64, + 0xCC, 0x7A, 0xE5, 0x29, 0x0C, 0xBE, 0x08, 0xD0, 0x10, 0x98, 0xA4, 0x07, 0x1F, 0x39, 0xCB, 0xED, + 0x18, 0x7C, 0x57, 0x78, 0x6E, 0x50, 0xC6, 0x28, 0x38, 0x38, 0xDF, 0x8A, 0xFD, 0x46, 0x2A, 0xC3, + 0x3D, 0x27, 0x7F, 0x8D, 0x58, 0x78, 0xAA, 0xE7, 0xAB, 0x7E, 0xE0, 0xC5, 0xB2, 0xFC, 0x96, 0x3F, + 0x4A, 0x5F, 0x38, 0x7D, 0x41, 0x99, 0xEF, 0x66, 0x45, 0x37, 0x65, 0x13, 0xD9, 0x44, 0xA4, 0xD3, + 0x2F, 0xC6, 0xA5, 0x91, 0x13, 0xE8, 0x54, 0x34, 0xC8, 0xA9, 0x6C, 0x80, 0xD3, 0x7C, 0xF1, 0x4C, + 0xE9, 0xB1, 0x4C, 0xB8, 0x8C, 0xB9, 0x42, 0x99, 0x62, 0x0D, 0x53, 0x40, 0x1C, 0x83, 0xCE, 0x44, + 0x10, 0xD3, 0x93, 0xD1, 0x37, 0x16, 0x8C, 0x61, 0x4A, 0x89, 0x5F, 0x9A, 0xDA, 0xBE, 0xDC, 0xB8, + 0xA5, 0xEC, 0xF9, 0x97, 0x0D, 0x59, 0xCA, 0x09, 0x57, 0x4A, 0xC3, 0xCC, 0x5B, 0x91, 0xE6, 0xCA, + 0xCB, 0xB8, 0x34, 0xAF, 0x82, 0x55, 0x44, 0x82, 0x35, 0x08, 0x69, 0x4C, 0x73, 0xB9, 0x0E, 0xAD, + 0x80, 0x41, 0x88, 0xA0, 0x75, 0x98, 0x1E, 0xE8, 0xB4, 0xFB, 0x62, 0x9B, 0x64, 0xCE, 0x2D, 0xA0, + 0xFA, 0x0E, 0xA8, 0xC5, 0xE1, 0x5F, 0x91, 0x92, 0xEC, 0xBB, 0x86, 0xCC, 0x7B, 0x42, 0x0E, 0x60, + 0x98, 0x2B, 0x46, 0xBE, 0x33, 0xCE, 0x17, 0x99, 0x88, 0x7B, 0x6F, 0x14, 0xCE, 0x6F, 0xB9, 0x30, + 0x9B, 0xC8, 0xFC, 0x32, 0xFB, 0x8C, 0x2C, 0x7F, 0x1B, 0x1D, 0x97, 0x86, 0x11, 0x7B, 0xE5, 0xE6, + 0xFD, 0xA1, 0xF4, 0x7A, 0x98, 0xC3, 0x35, 0x76, 0x41, 0xDB, 0x9E, 0xB2, 0x52, 0xE1, 0x2B, 0xAC, + 0x99, 0x73, 0xF7, 0x3B, 0xDF, 0x3D, 0x6F, 0x99, 0xE4, 0x49, 0x29, 0xD3, 0x96, 0x07, 0x9A, 0x0F, + 0xFB, 0x39, 0x73, 0x14, 0x27, 0xBD, 0x83, 0xB9, 0xAE, 0x71, 0xF3, 0x18, 0xF2, 0x52, 0x77, 0xAB, + 0x0B, 0x9D, 0xC0, 0x27, 0x3D, 0x67, 0xC7, 0xBA, 0xBF, 0x64, 0x03, 0x63, 0xCD, 0x36, 0x32, 0x5A, + 0x51, 0xC9, 0xFD, 0x0B, 0xDB, 0x6D, 0xDC, 0x1E, 0x36, 0x8B, 0x52, 0x5C, 0x6B, 0xAD, 0x36, 0x4A, + 0x4C, 0xBB, 0xDC, 0x26, 0x35, 0x37, 0x92, 0xC8, 0x9A, 0x15, 0x10, 0xD9, 0x9A, 0xED, 0xDD, 0x9C, + 0x44, 0xD6, 0xDC, 0x58, 0x22, 0x6B, 0x15, 0x25, 0xB2, 0xF6, 0x5A, 0x6D, 0x54, 0x6B, 0x0E, 0x22, + 0x6B, 0x6D, 0x24, 0x91, 0xB5, 0x2A, 0x20, 0xB2, 0x35, 0xDB, 0xBB, 0x39, 0x89, 0xAC, 0xB5, 0xB1, + 0x44, 0xD6, 0x2E, 0x4A, 0x64, 0xFB, 0x6B, 0xB5, 0x51, 0xED, 0x39, 0x88, 0xAC, 0xBD, 0x91, 0x44, + 0xD6, 0xAE, 0x80, 0xC8, 0xD6, 0x6C, 0xEF, 0xE6, 0x24, 0xB2, 0xF6, 0x4B, 0x10, 0x59, 0x64, 0x29, + 0x20, 0x0D, 0x1D, 0xAD, 0xFF, 0xA5, 0x2E, 0x34, 0x26, 0x77, 0x55, 0x74, 0xF3, 0xE5, 0x91, 0xBB, + 0x9D, 0x6E, 0xED, 0x24, 0xB4, 0x4B, 0x70, 0x76, 0x63, 0xEB, 0xB9, 0x17, 0x16, 0xC9, 0x0B, 0x8A, + 0xE4, 0xA4, 0x6A, 0x13, 0x13, 0x95, 0x23, 0x94, 0xBE, 0x61, 0x98, 0xBE, 0x51, 0xE8, 0x14, 0xB9, + 0x06, 0x98, 0xBE, 0x3D, 0x40, 0x85, 0x3E, 0xA7, 0x61, 0xCE, 0x7D, 0x41, 0x85, 0xB6, 0x87, 0x2B, + 0x8B, 0x75, 0xBA, 0xB1, 0xE0, 0xB1, 0x28, 0x2B, 0x0B, 0xDA, 0x0A, 0x5C, 0x5B, 0xD5, 0x35, 0xD5, + 0xF3, 0xC3, 0xB8, 0x5F, 0x4D, 0xE3, 0x9E, 0xC7, 0x28, 0x39, 0x2F, 0xC3, 0x44, 0xE1, 0x1C, 0x0D, + 0x97, 0x7F, 0xAD, 0x0B, 0xB8, 0x36, 0x18, 0xF4, 0x45, 0xC6, 0x8A, 0xF4, 0xDE, 0x62, 0x89, 0xC4, + 0x29, 0xB5, 0x94, 0x78, 0x17, 0x6D, 0x16, 0xB1, 0x98, 0x68, 0x32, 0x54, 0xD0, 0x5D, 0x3F, 0x67, + 0xB2, 0x0C, 0x0A, 0x0C, 0x72, 0xD5, 0xC5, 0x98, 0x63, 0x17, 0x06, 0x5F, 0x5F, 0xBB, 0x45, 0x69, + 0xE3, 0xE4, 0xFD, 0x59, 0x97, 0xED, 0xB1, 0xAF, 0xE7, 0xDD, 0x57, 0x60, 0xA1, 0x84, 0xB5, 0xC0, + 0x42, 0xE6, 0xB2, 0x51, 0x26, 0x9A, 0xA6, 0x40, 0x7B, 0x12, 0x4C, 0x13, 0xA6, 0x4A, 0x5F, 0x73, + 0xBE, 0xEA, 0xCE, 0x3A, 0x18, 0x2B, 0x67, 0x2D, 0x64, 0x61, 0x73, 0x65, 0xFE, 0x95, 0x4E, 0x89, + 0xAB, 0x9C, 0x7B, 0xCD, 0x39, 0x33, 0x0D, 0xE0, 0x12, 0xB5, 0x13, 0x84, 0xAE, 0xF8, 0x9C, 0xC3, + 0x60, 0x17, 0xBF, 0x8A, 0x19, 0x8F, 0x9A, 0x4D, 0xC1, 0x51, 0x51, 0x36, 0x3F, 0x7C, 0xF9, 0xD4, + 0xFE, 0xCE, 0xA9, 0x40, 0xDD, 0xF2, 0x39, 0x61, 0x7F, 0x9C, 0x4A, 0x34, 0x83, 0x6F, 0x45, 0x1C, + 0xCB, 0x09, 0xBC, 0xA1, 0xB8, 0xBC, 0xC1, 0x6A, 0x8C, 0xC0, 0xAB, 0x06, 0xC6, 0x23, 0xB7, 0x08, + 0x57, 0x3D, 0xAA, 0xCF, 0x3A, 0xBE, 0xCA, 0x11, 0xDF, 0xE0, 0x65, 0xCE, 0x3A, 0xF1, 0xAE, 0xCC, + 0x03, 0x3D, 0x02, 0xFC, 0xEC, 0x0C, 0x68, 0xF3, 0xC5, 0x0B, 0xC5, 0x8F, 0xFC, 0x68, 0x20, 0x4C, + 0x11, 0x50, 0x9B, 0x2B, 0x58, 0x02, 0x1A, 0x1E, 0x57, 0x75, 0x9F, 0x17, 0x79, 0xA2, 0xC1, 0x16, + 0xD2, 0xCD, 0x1B, 0x6C, 0x6C, 0xE0, 0xC5, 0xD3, 0x2A, 0xB7, 0xDE, 0xEF, 0x1F, 0xAD, 0xF5, 0x25, + 0x5B, 0x6E, 0x85, 0xA3, 0xB9, 0x43, 0x95, 0xCA, 0x88, 0xB3, 0xC9, 0x7D, 0xCD, 0xEB, 0xD8, 0x99, + 0x6E, 0x33, 0x77, 0xF0, 0xD1, 0x3C, 0xD7, 0x8C, 0x15, 0xE3, 0xF2, 0x67, 0xDB, 0x9B, 0x0F, 0x97, + 0xB1, 0x21, 0xF6, 0x35, 0x1B, 0x5C, 0x63, 0x6E, 0x7D, 0xBC, 0xF2, 0x7B, 0x6C, 0x74, 0xD1, 0x44, + 0xF1, 0x9A, 0xE2, 0xA0, 0x85, 0x30, 0x16, 0xBA, 0x95, 0x0F, 0x71, 0xF2, 0x4F, 0x43, 0x43, 0x1B, + 0x0A, 0xEF, 0x73, 0x98, 0xA5, 0x46, 0xB3, 0x4C, 0xE6, 0x34, 0x47, 0xA6, 0x49, 0x39, 0x07, 0x1A, + 0x5B, 0x32, 0x2A, 0x4E, 0x46, 0x02, 0xA5, 0x0A, 0xDE, 0x04, 0xA5, 0xD1, 0x14, 0x76, 0xB0, 0x52, + 0x9A, 0x9A, 0x79, 0xC6, 0x94, 0x53, 0xFC, 0x9D, 0x34, 0xF9, 0xA1, 0xF4, 0x62, 0x4A, 0xD8, 0x22, + 0xAA, 0x96, 0xB3, 0x44, 0xB5, 0x76, 0x21, 0x67, 0x89, 0xCF, 0xAB, 0x90, 0xB3, 0xE4, 0xA8, 0xC5, + 0xE4, 0x2C, 0xF1, 0xF2, 0xCB, 0xCB, 0x59, 0xA0, 0x4F, 0xDA, 0x4F, 0xCC, 0xB0, 0x1E, 0xEC, 0x00, + 0x24, 0x2C, 0x62, 0x22, 0x42, 0xF2, 0x12, 0xFE, 0x69, 0x09, 0xA9, 0x2B, 0x45, 0xBA, 0x92, 0x21, + 0x6D, 0x21, 0xE7, 0xC1, 0x0A, 0xDB, 0xA2, 0xF9, 0x7A, 0x5D, 0x76, 0xCF, 0x12, 0xBC, 0xC4, 0x4E, + 0xAC, 0x40, 0xF0, 0x12, 0x03, 0x6D, 0x05, 0xAF, 0xD7, 0x76, 0x62, 0xC4, 0xF6, 0xB5, 0xF0, 0x21, + 0x31, 0x6E, 0xB3, 0xD4, 0x43, 0xA2, 0xDA, 0xCA, 0xB4, 0x71, 0xB0, 0xCC, 0x64, 0x86, 0xB7, 0xBE, + 0x6B, 0x38, 0x67, 0x94, 0xA5, 0xA5, 0x56, 0x9E, 0xEB, 0x4D, 0xF9, 0x59, 0x4F, 0xF5, 0x79, 0x72, + 0x7B, 0x7F, 0x77, 0x05, 0x42, 0x19, 0xFD, 0x55, 0xA4, 0xC8, 0x68, 0xA5, 0xC5, 0x2A, 0xB3, 0x58, + 0x29, 0x1F, 0x61, 0x48, 0x20, 0x47, 0x9B, 0x9D, 0x98, 0x9F, 0x26, 0xF3, 0xD4, 0x10, 0x8F, 0xC5, + 0x98, 0xDE, 0x90, 0xCD, 0xCA, 0xE9, 0x13, 0xCF, 0xF4, 0xE2, 0xE5, 0xFE, 0x90, 0xDF, 0x0E, 0xB8, + 0x4F, 0x8E, 0x89, 0xA5, 0x95, 0xD9, 0xE5, 0x50, 0x63, 0xA1, 0x5A, 0xB3, 0xAB, 0x13, 0x46, 0x04, + 0x06, 0x6D, 0x8C, 0x30, 0xF2, 0x55, 0x8F, 0x84, 0x11, 0x34, 0xA6, 0xAD, 0x48, 0x18, 0x19, 0x8F, + 0x3A, 0xA6, 0xBE, 0x40, 0x77, 0x5E, 0x5E, 0xDA, 0x18, 0xDB, 0xB6, 0x49, 0xA0, 0xF0, 0xA0, 0x4F, + 0x6E, 0x69, 0xDC, 0x93, 0x3E, 0xD7, 0xE7, 0xDD, 0x4D, 0x90, 0x19, 0x02, 0xBD, 0x60, 0xB9, 0xD5, + 0xC5, 0xA5, 0x86, 0x40, 0x5F, 0x4B, 0xA9, 0x01, 0x51, 0x39, 0x5D, 0x6A, 0x68, 0x2A, 0xCD, 0xA6, + 0xB2, 0x15, 0x1B, 0x72, 0xC5, 0x86, 0xE4, 0xC6, 0x16, 0x13, 0x1B, 0x12, 0x6D, 0x5E, 0x83, 0x6E, + 0x19, 0xB1, 0xA9, 0x8A, 0xD8, 0x79, 0xE9, 0xCB, 0x20, 0x51, 0x0E, 0x60, 0xF3, 0x2F, 0x82, 0x68, + 0x1D, 0x73, 0xDD, 0x03, 0xC5, 0x5B, 0xA6, 0xC0, 0x39, 0x0E, 0xA0, 0x89, 0x2B, 0x20, 0x8A, 0x43, + 0x5C, 0x87, 0x1B, 0xA0, 0x19, 0x4B, 0x58, 0xAF, 0x0B, 0xA0, 0x0B, 0xCF, 0xA1, 0x3A, 0x88, 0x17, + 0xBD, 0x6E, 0xFD, 0xF6, 0xCB, 0x2F, 0x4B, 0x97, 0x02, 0xC2, 0xF1, 0x96, 0x7E, 0xDA, 0xA3, 0x91, + 0x92, 0xD2, 0x4A, 0x63, 0xC8, 0x23, 0xAC, 0xAE, 0xDD, 0x0A, 0x33, 0x9E, 0x46, 0xE9, 0xAB, 0xC5, + 0xF5, 0x35, 0x60, 0x78, 0x9D, 0x3E, 0xEC, 0xA2, 0x3D, 0x33, 0x7A, 0x04, 0x72, 0xB3, 0x6F, 0x88, + 0xFB, 0x6D, 0x11, 0xDD, 0x8A, 0x8E, 0xF8, 0x24, 0x02, 0x53, 0xDC, 0xF9, 0xC8, 0xF0, 0xBC, 0x64, + 0xE4, 0xF9, 0x97, 0x7E, 0x7F, 0xFD, 0x3D, 0xE9, 0x23, 0x22, 0x99, 0x2B, 0x55, 0x45, 0x3A, 0x2A, + 0xCE, 0x5A, 0xB5, 0xA0, 0xD5, 0x9B, 0xCE, 0xD9, 0x71, 0xC8, 0x65, 0x69, 0x74, 0x78, 0x50, 0x63, + 0x9E, 0xFF, 0x8C, 0x1B, 0x25, 0xEF, 0xF6, 0x8F, 0x05, 0x87, 0xFD, 0x4B, 0xED, 0xA4, 0xD3, 0x39, + 0x3E, 0x3D, 0x3D, 0x3E, 0x3B, 0x3B, 0x3E, 0x3F, 0x3F, 0xBE, 0xB8, 0x38, 0xBE, 0xBC, 0x2C, 0xEF, + 0xAE, 0x32, 0xDF, 0x64, 0xBB, 0xAA, 0x81, 0x99, 0xD8, 0x69, 0xCE, 0xDE, 0x71, 0xD9, 0x28, 0xBB, + 0x82, 0x07, 0xA6, 0xC3, 0xB9, 0x0B, 0xCB, 0xF7, 0xB2, 0xD7, 0x7F, 0x6B, 0x5B, 0x7C, 0x65, 0x5A, + 0x76, 0x31, 0xE9, 0x0F, 0x5B, 0xC9, 0xE9, 0x0A, 0x19, 0x0F, 0xF8, 0x15, 0xF0, 0xC8, 0xD1, 0xF1, + 0x81, 0xF3, 0xFD, 0x2F, 0xB9, 0x0B, 0x97, 0x87, 0x50, 0xF2, 0x70, 0x41, 0x58, 0xC0, 0x99, 0x83, + 0x30, 0x17, 0x00, 0xAF, 0x65, 0x9D, 0x52, 0xA9, 0x92, 0x65, 0x81, 0xDB, 0x8A, 0x48, 0xCB, 0x70, + 0xA2, 0x31, 0x40, 0xCF, 0x40, 0x5F, 0x12, 0x52, 0x02, 0x80, 0xC1, 0xB8, 0x01, 0x07, 0x61, 0x14, + 0xBE, 0x95, 0x7B, 0x9E, 0x51, 0x69, 0x69, 0x15, 0x57, 0x2A, 0x63, 0x75, 0xDB, 0x7F, 0xB2, 0xA5, + 0x7A, 0xE2, 0xED, 0x32, 0xFE, 0xDD, 0xF0, 0xD1, 0x2B, 0x47, 0x8A, 0x03, 0xC2, 0x9D, 0x86, 0x0C, + 0xA0, 0x74, 0xEB, 0xE2, 0x71, 0x1F, 0x76, 0x4F, 0xC2, 0x37, 0xB0, 0x7C, 0xC3, 0x64, 0x6F, 0x70, + 0x3D, 0x6F, 0xD0, 0xE8, 0xE9, 0x71, 0x2C, 0x73, 0xFE, 0xD5, 0x32, 0x7C, 0x19, 0x1D, 0xE4, 0x3D, + 0xA9, 0x0E, 0xD2, 0x62, 0x78, 0x69, 0xC3, 0x3D, 0xE9, 0x73, 0x03, 0xA0, 0x65, 0x58, 0xAE, 0x2D, + 0xB0, 0x28, 0xDF, 0xB3, 0x35, 0xC0, 0x5A, 0xC9, 0x54, 0x27, 0xD9, 0xB1, 0x9F, 0xF0, 0x06, 0xDB, + 0x6A, 0x6C, 0x78, 0x4C, 0x61, 0x55, 0x2C, 0x62, 0x35, 0x01, 0xB6, 0x97, 0x36, 0xCA, 0x52, 0x92, + 0x2C, 0xC2, 0xE8, 0x5A, 0xF1, 0x10, 0x83, 0xBE, 0xF2, 0x77, 0x22, 0x44, 0xE7, 0x15, 0x85, 0xD6, + 0x26, 0xE6, 0x0B, 0x78, 0x28, 0xCB, 0x74, 0xBF, 0x08, 0x19, 0x01, 0x61, 0x50, 0xD2, 0x18, 0x55, + 0xD3, 0x0C, 0x5D, 0x54, 0x6F, 0xD5, 0xB9, 0xC9, 0xC3, 0xDC, 0x57, 0x8E, 0xE0, 0xF1, 0x74, 0x0A, + 0x89, 0x30, 0xF6, 0x70, 0x65, 0x6C, 0x14, 0xE0, 0xC5, 0xAB, 0xE1, 0xC2, 0xCF, 0x07, 0x1E, 0x96, + 0x1A, 0x87, 0x8F, 0x7D, 0xCC, 0x85, 0x45, 0xC1, 0x74, 0x82, 0xCE, 0x80, 0xB4, 0x88, 0xFA, 0x72, + 0x6E, 0x13, 0xD6, 0x98, 0x2A, 0x16, 0x38, 0xC4, 0x66, 0xF1, 0xF2, 0x24, 0x1A, 0xA4, 0x73, 0xF3, + 0x32, 0x7C, 0xBB, 0x4F, 0xFD, 0x89, 0x53, 0x79, 0x9A, 0x7F, 0x9F, 0x8C, 0x09, 0xA2, 0x24, 0xFB, + 0x76, 0xD2, 0x26, 0x7C, 0xE3, 0x0D, 0x26, 0x94, 0xBD, 0x5E, 0x40, 0x4E, 0x8E, 0xCB, 0xD4, 0x5D, + 0x67, 0x48, 0x69, 0xA6, 0xED, 0xAA, 0x33, 0xF3, 0xCF, 0x4F, 0xCA, 0x0F, 0x16, 0x88, 0x0D, 0xE5, + 0x04, 0xB7, 0x7C, 0xE3, 0x7A, 0x71, 0x96, 0x75, 0x0D, 0xD3, 0xC5, 0x04, 0x57, 0x77, 0x6A, 0x01, + 0x6B, 0xC6, 0xE2, 0x1C, 0x47, 0x0C, 0xB7, 0x32, 0xEB, 0x7A, 0x42, 0x99, 0xC0, 0x45, 0x4A, 0xC1, + 0xF6, 0x45, 0x35, 0x8A, 0x17, 0x34, 0xAD, 0xCF, 0xC0, 0xB2, 0x10, 0x77, 0xE7, 0xCE, 0x85, 0x37, + 0x1F, 0x63, 0x3A, 0xB3, 0x6D, 0x57, 0x37, 0x2C, 0x61, 0x0D, 0xB8, 0x74, 0xF9, 0x9F, 0x01, 0xB7, + 0xB4, 0x67, 0xB6, 0x73, 0xF3, 0xF9, 0xC7, 0xDB, 0x97, 0xF1, 0x90, 0xA1, 0xD2, 0x00, 0xFD, 0x68, + 0x26, 0x84, 0x23, 0xE2, 0x56, 0x05, 0xCD, 0x1D, 0x6C, 0x68, 0x3B, 0x0E, 0x4A, 0x5A, 0x61, 0x72, + 0x76, 0x59, 0x31, 0xC9, 0x6B, 0x48, 0x66, 0x06, 0x27, 0x0E, 0x09, 0x61, 0xA2, 0xD5, 0x90, 0xAB, + 0x2E, 0xE3, 0xAA, 0x36, 0x64, 0x36, 0x9C, 0x44, 0xAE, 0x38, 0xAB, 0xA0, 0x4B, 0x91, 0x88, 0x05, + 0x7D, 0x71, 0xB4, 0x38, 0x00, 0xA2, 0x61, 0x63, 0xD8, 0xF4, 0xBE, 0xA9, 0x00, 0x30, 0x1A, 0xEC, + 0xDA, 0x18, 0x81, 0x44, 0x08, 0x7F, 0x2B, 0x68, 0xFB, 0x61, 0xEF, 0x5B, 0xEF, 0xF0, 0xF1, 0x2B, + 0x39, 0xC9, 0xA4, 0x7A, 0x20, 0x4C, 0xCE, 0x07, 0x38, 0x8D, 0x36, 0x1B, 0xEB, 0x39, 0xA5, 0x8C, + 0xA5, 0x33, 0xF2, 0x6E, 0x4B, 0x06, 0x3C, 0x66, 0xD3, 0x63, 0xD0, 0x47, 0xA8, 0x57, 0x50, 0x1D, + 0xCC, 0x6C, 0xBF, 0xB0, 0x2D, 0xB5, 0x6A, 0x0A, 0x13, 0xB5, 0x2F, 0xBC, 0x50, 0x20, 0xD2, 0xB9, + 0x6E, 0x50, 0x11, 0x67, 0x66, 0x1A, 0x9E, 0xCF, 0x2D, 0xC4, 0x65, 0x54, 0x4F, 0x56, 0x4F, 0x6C, + 0x9D, 0xBE, 0x4F, 0x77, 0x92, 0x20, 0x97, 0x89, 0x3D, 0xA3, 0x14, 0x29, 0x62, 0xB6, 0xBB, 0xC0, + 0xB6, 0x41, 0xB3, 0xC1, 0xC9, 0xC9, 0x8C, 0x2B, 0x51, 0x22, 0x1D, 0x78, 0xDD, 0x18, 0x58, 0x36, + 0x4A, 0x83, 0x9E, 0x2D, 0xA8, 0x8D, 0x38, 0xBB, 0x7C, 0x0F, 0x59, 0x7B, 0x1F, 0xDD, 0x50, 0x42, + 0x02, 0x95, 0x3A, 0x19, 0x66, 0x42, 0xC5, 0xDA, 0xB3, 0xB1, 0x98, 0x06, 0xA0, 0x22, 0x97, 0xD7, + 0xC5, 0xC1, 0x34, 0x39, 0x4C, 0x8C, 0x00, 0xDB, 0x8A, 0x37, 0xA6, 0xBE, 0xA6, 0x82, 0xCD, 0x0E, + 0x15, 0xC5, 0xDB, 0x92, 0xDE, 0x02, 0xA4, 0x27, 0x72, 0xF9, 0x60, 0x12, 0x5B, 0x57, 0x25, 0xF7, + 0x20, 0xCC, 0x77, 0x6B, 0x07, 0xFE, 0x1F, 0x5E, 0x09, 0xFA, 0xCB, 0xEE, 0x64, 0x49, 0x44, 0x58, + 0x4E, 0x2C, 0x2C, 0x7D, 0x83, 0x10, 0x4B, 0x64, 0xC8, 0xBA, 0xAE, 0x61, 0x63, 0xFE, 0xD3, 0x57, + 0x70, 0xA1, 0x10, 0x5B, 0x56, 0xB8, 0xAA, 0x99, 0xD7, 0x0B, 0xD3, 0xFD, 0x66, 0xDC, 0x37, 0x64, + 0x77, 0x9C, 0xB2, 0x47, 0x71, 0xE0, 0xA6, 0xDE, 0x41, 0xC4, 0x52, 0xA9, 0x2D, 0xEF, 0x26, 0xA2, + 0xCC, 0x5D, 0x44, 0xE1, 0xE5, 0x55, 0x94, 0x49, 0xA7, 0x60, 0xF8, 0x66, 0x0C, 0x4E, 0x22, 0x25, + 0xA0, 0x77, 0x6D, 0xF4, 0x39, 0xD6, 0x34, 0x9A, 0xC1, 0xFA, 0xA7, 0x2E, 0x9B, 0xF7, 0x23, 0x93, + 0xE0, 0x21, 0x7D, 0x38, 0x9C, 0xBA, 0x6C, 0x8E, 0x6F, 0x98, 0x18, 0x88, 0x85, 0x03, 0x1D, 0xAF, + 0x4C, 0x81, 0xE8, 0xC4, 0x32, 0xEC, 0xC9, 0xC4, 0x79, 0x0C, 0xF0, 0x95, 0x12, 0x6A, 0x1B, 0x7D, + 0x66, 0xD9, 0xC2, 0x3F, 0x1A, 0xCE, 0x24, 0xCC, 0xAC, 0x6D, 0x3C, 0xCA, 0xB2, 0x97, 0x74, 0xA8, + 0x8D, 0x54, 0xEB, 0x39, 0x3C, 0xCF, 0x1A, 0x63, 0x82, 0x0E, 0x7D, 0xA9, 0x85, 0x23, 0x8E, 0x0C, + 0x3E, 0x21, 0xA3, 0x1D, 0xE6, 0xFD, 0xC7, 0xBC, 0x3F, 0x61, 0x82, 0xBE, 0xF0, 0xCC, 0x39, 0xC0, + 0xB7, 0x9A, 0x2D, 0x25, 0xEA, 0x6C, 0xED, 0xB4, 0x8B, 0x82, 0xE1, 0xB7, 0x6F, 0x12, 0x67, 0xCD, + 0xFE, 0x9B, 0x82, 0xFE, 0x61, 0x6F, 0xC4, 0xB9, 0xF2, 0x26, 0xEC, 0x25, 0x7E, 0xAE, 0xBC, 0x99, + 0xA4, 0xDD, 0x49, 0x9C, 0x9C, 0xE7, 0x06, 0xC2, 0xC9, 0xE9, 0x74, 0x99, 0x1E, 0x43, 0xF9, 0x59, + 0xAD, 0xA6, 0x09, 0x63, 0x7C, 0x5C, 0x2C, 0x3F, 0xD3, 0x55, 0xC7, 0xC3, 0x6A, 0x15, 0x84, 0xB4, + 0x4E, 0x88, 0xD2, 0x20, 0xB7, 0x91, 0x8E, 0x13, 0xCF, 0x46, 0x19, 0x22, 0x31, 0xD9, 0x84, 0x30, + 0x1E, 0x54, 0x0D, 0xE9, 0x07, 0x90, 0x19, 0x84, 0x3B, 0x97, 0xA3, 0x9E, 0x85, 0x36, 0xEE, 0xB0, + 0x9B, 0xF0, 0x5D, 0x8A, 0x47, 0x90, 0xA4, 0x40, 0xD5, 0x0D, 0xBF, 0xE1, 0x7B, 0xF4, 0x18, 0xE4, + 0x3A, 0x78, 0xDA, 0xA0, 0x4A, 0xCF, 0x03, 0x2E, 0x52, 0x5E, 0x7A, 0x2A, 0x52, 0x1D, 0xB9, 0x0E, + 0xBF, 0xE9, 0xC1, 0xE7, 0x24, 0x77, 0x7F, 0x53, 0xD4, 0xEC, 0xB7, 0x56, 0x19, 0xB3, 0xE2, 0x47, + 0xB9, 0x64, 0x8F, 0xA3, 0xEF, 0x75, 0x2C, 0xBC, 0x2B, 0x30, 0x63, 0x12, 0x3F, 0xC3, 0xED, 0xBF, + 0x36, 0xB2, 0x83, 0x0B, 0xD2, 0x4D, 0x80, 0x19, 0xD6, 0xBE, 0x68, 0x00, 0xEC, 0xF9, 0x94, 0xDE, + 0x55, 0x6A, 0x27, 0x4A, 0x8E, 0xA5, 0x6E, 0xD1, 0x21, 0x9A, 0xB5, 0x93, 0xE6, 0x92, 0x87, 0x80, + 0x8D, 0x6B, 0x2D, 0x79, 0x88, 0x76, 0xED, 0xA4, 0xBD, 0xE4, 0x21, 0xF6, 0x6B, 0x27, 0xFB, 0x4B, + 0x1E, 0xE2, 0xA0, 0x76, 0x72, 0xB0, 0xE4, 0x21, 0x0E, 0x6B, 0x27, 0x87, 0x4B, 0x1E, 0xE2, 0x5D, + 0xED, 0xE4, 0x5D, 0xEE, 0x10, 0x6E, 0xA9, 0xC1, 0x33, 0x48, 0x4F, 0xAA, 0x8B, 0xF3, 0x18, 0xD0, + 0x23, 0xC3, 0xB9, 0x8B, 0x1A, 0xEA, 0xBD, 0x7D, 0x96, 0xDD, 0x3B, 0x3A, 0x5C, 0x4A, 0x3D, 0xD6, + 0x0E, 0x35, 0xD4, 0x59, 0xF6, 0xF3, 0x4A, 0x72, 0x70, 0x5E, 0x59, 0x9E, 0xEF, 0x06, 0x78, 0x4A, + 0xBC, 0x90, 0x36, 0x82, 0x20, 0x37, 0xA2, 0x49, 0x84, 0xCA, 0x43, 0x95, 0x3A, 0xCA, 0xD5, 0x54, + 0xEF, 0xA5, 0x3C, 0x9F, 0xA6, 0x9A, 0xA7, 0x6C, 0xC5, 0x14, 0x14, 0x27, 0xF4, 0x8F, 0xD8, 0x02, + 0xD7, 0xC0, 0x11, 0x2A, 0x6F, 0x45, 0x73, 0xE9, 0x1C, 0x14, 0xAF, 0x60, 0x98, 0x65, 0x03, 0x93, + 0x2B, 0xBF, 0xF4, 0xB8, 0xA7, 0x39, 0x8C, 0x1C, 0x6E, 0x79, 0xB4, 0x05, 0xD1, 0x5D, 0x2D, 0x7E, + 0x91, 0x67, 0xAF, 0x1E, 0x37, 0x5B, 0xC9, 0x8D, 0xC9, 0xF4, 0x5C, 0x57, 0xA7, 0xFC, 0x50, 0x38, + 0x17, 0x6E, 0x18, 0x7A, 0x19, 0x44, 0x33, 0x20, 0x73, 0x21, 0xF2, 0x1F, 0x50, 0x62, 0xD0, 0xE7, + 0xDA, 0xE5, 0xFA, 0x74, 0x39, 0xDC, 0xC6, 0xE6, 0xDD, 0x80, 0x2C, 0x09, 0xE5, 0x44, 0x62, 0xED, + 0x7B, 0xC3, 0xE9, 0x98, 0x00, 0xD7, 0x40, 0x07, 0x95, 0x44, 0x26, 0x94, 0x86, 0x67, 0x2C, 0x7C, + 0xB8, 0x64, 0x5C, 0x4A, 0x99, 0xC4, 0xCA, 0xD0, 0x48, 0xAE, 0xD6, 0xB1, 0x71, 0x5F, 0x61, 0xC9, + 0xAA, 0x9C, 0x42, 0x3C, 0x33, 0xB6, 0x8A, 0xBE, 0xFB, 0x96, 0x1A, 0x7D, 0x97, 0x52, 0x9E, 0x6A, + 0xD3, 0xC2, 0x55, 0x66, 0xF0, 0x40, 0xB9, 0xDA, 0xEE, 0x10, 0x54, 0xA0, 0x33, 0x22, 0xA1, 0x3F, + 0x46, 0xA3, 0x65, 0xBB, 0xFF, 0xA7, 0x0E, 0x5A, 0x4B, 0xB5, 0x02, 0x4F, 0x1B, 0x63, 0x3A, 0x72, + 0x7F, 0xA8, 0x75, 0x0E, 0x87, 0xA4, 0xBE, 0xD9, 0xCE, 0x68, 0xF4, 0x02, 0x17, 0x78, 0x9D, 0xEE, + 0x19, 0x2A, 0x7C, 0x32, 0xF7, 0x90, 0xAF, 0x5A, 0x1A, 0xDE, 0xE5, 0xD9, 0x23, 0xE1, 0x07, 0x82, + 0x1A, 0xA7, 0x0C, 0x78, 0x0F, 0x11, 0x4E, 0xDA, 0x5F, 0xC2, 0x3F, 0x1D, 0x5C, 0x1F, 0xD3, 0x68, + 0x09, 0x0D, 0x76, 0x8F, 0x66, 0x1C, 0xF8, 0x7F, 0xE0, 0x05, 0xAA, 0x69, 0x3E, 0xA3, 0xA6, 0x6A, + 0xF9, 0x61, 0x25, 0x23, 0x2C, 0xDB, 0xA8, 0x4F, 0xF5, 0x87, 0x8E, 0x59, 0x18, 0xB8, 0xAA, 0x9A, + 0x1A, 0x05, 0x70, 0xE9, 0x4C, 0x0F, 0x5C, 0xF2, 0xCC, 0x92, 0x2F, 0xC0, 0x37, 0xC6, 0x83, 0x2B, + 0x8B, 0xB3, 0x75, 0x46, 0x76, 0x20, 0x22, 0x5D, 0x55, 0x5D, 0x17, 0x37, 0x86, 0x9F, 0x3B, 0x17, + 0xE1, 0x55, 0x0D, 0xCC, 0xDF, 0x25, 0xAF, 0xAE, 0xBE, 0xF1, 0x1D, 0x3D, 0x5A, 0x54, 0x8C, 0x8E, + 0x80, 0xB3, 0x60, 0x64, 0x63, 0xC6, 0xA7, 0x33, 0xEF, 0x98, 0xDD, 0xDB, 0xAE, 0x36, 0xDC, 0x69, + 0x36, 0xDF, 0x01, 0xB0, 0xD9, 0xC5, 0xDF, 0xFE, 0xBA, 0xB3, 0xDF, 0xC2, 0x4F, 0x97, 0x00, 0x3E, + 0x1F, 0xD8, 0xB4, 0xA7, 0x1A, 0xDA, 0xCE, 0xE1, 0xFB, 0xF1, 0x23, 0x51, 0xDE, 0x81, 0x3D, 0xB6, + 0x12, 0x4F, 0xE1, 0xCF, 0x77, 0x0A, 0xFC, 0xF9, 0xDA, 0x42, 0x2D, 0x24, 0x32, 0x57, 0x75, 0x85, + 0x51, 0xCB, 0xA6, 0xDD, 0x82, 0x97, 0x16, 0xA9, 0x6D, 0x5F, 0x24, 0xF8, 0x22, 0x9F, 0x39, 0x7D, + 0xE6, 0x48, 0x79, 0x7F, 0xAC, 0x8A, 0x2D, 0x85, 0xC3, 0x95, 0x65, 0x48, 0xA2, 0x1D, 0xDB, 0x51, + 0x1B, 0xDF, 0x1A, 0x6A, 0x63, 0xF6, 0x2E, 0x74, 0xF1, 0x04, 0x12, 0xE5, 0x91, 0xDF, 0x02, 0x7F, + 0x7A, 0x11, 0xFF, 0x02, 0xC1, 0x50, 0xC8, 0x96, 0x45, 0x13, 0x09, 0xF9, 0x07, 0x10, 0x8D, 0x37, + 0x12, 0x67, 0x24, 0x52, 0x28, 0x9A, 0x8E, 0x0D, 0x4B, 0x33, 0x03, 0xE4, 0x0A, 0x58, 0xAE, 0xC9, + 0x42, 0x1F, 0x13, 0xAF, 0xC1, 0x6E, 0x6D, 0x64, 0x15, 0x54, 0x3D, 0x4D, 0x35, 0x59, 0xE7, 0xAE, + 0x8B, 0x95, 0x47, 0x02, 0x93, 0x32, 0xB0, 0x85, 0x0D, 0xE2, 0x21, 0x54, 0x8D, 0xA3, 0xD1, 0x96, + 0xAC, 0x8B, 0x93, 0x75, 0x84, 0x86, 0xA5, 0x08, 0x3A, 0x6C, 0xB5, 0x06, 0xA4, 0x9C, 0xAD, 0xDC, + 0x67, 0xAA, 0xF7, 0xBD, 0x67, 0x10, 0xC3, 0x46, 0xAF, 0xE0, 0xA2, 0x51, 0x2C, 0x64, 0x2E, 0x05, + 0x3E, 0xD1, 0x34, 0x05, 0xD8, 0x09, 0x18, 0x4D, 0x28, 0xEE, 0x9E, 0x68, 0xBB, 0x16, 0x77, 0x86, + 0xB3, 0xD6, 0x31, 0xB7, 0xCA, 0x1E, 0x38, 0xA6, 0xAD, 0xEA, 0xB7, 0xFC, 0xE9, 0xD2, 0x70, 0x47, + 0x58, 0x94, 0xF7, 0xDC, 0x78, 0x2C, 0x54, 0xD3, 0xB4, 0x90, 0x7E, 0x34, 0xD5, 0x7B, 0xED, 0x44, + 0x42, 0x3B, 0x7C, 0x90, 0x97, 0xDF, 0x95, 0x78, 0x17, 0xC5, 0xA8, 0xF8, 0xDF, 0xC2, 0x36, 0x7F, + 0xE3, 0x2E, 0x72, 0xCC, 0xAF, 0xCE, 0xC0, 0x55, 0x41, 0xDB, 0xC9, 0x0C, 0xDA, 0x78, 0x54, 0x1A, + 0xCA, 0x9C, 0xC6, 0xFA, 0x19, 0x47, 0xE2, 0x2C, 0x52, 0x9F, 0xE5, 0x89, 0x7B, 0x86, 0xD0, 0x89, + 0x83, 0x62, 0x3E, 0x6F, 0xDC, 0xC8, 0xA0, 0xA8, 0x4D, 0xF4, 0x87, 0xE6, 0x43, 0x1A, 0x83, 0x6E, + 0x29, 0xE1, 0x8B, 0x08, 0xC6, 0x31, 0xFC, 0x5B, 0x99, 0x62, 0x28, 0x66, 0xD2, 0x73, 0x54, 0xF7, + 0xDB, 0x65, 0x40, 0x57, 0xA1, 0x1E, 0xE7, 0x74, 0xAD, 0x0A, 0x13, 0xEB, 0xCB, 0x89, 0x91, 0x70, + 0x1C, 0x15, 0x40, 0x89, 0x2E, 0x57, 0x85, 0x0B, 0xCF, 0xBA, 0xE9, 0x84, 0xB1, 0xA3, 0x21, 0x9C, + 0x7F, 0xB8, 0xA5, 0xE8, 0xA7, 0x2C, 0x4F, 0x81, 0x97, 0x0E, 0x53, 0xB8, 0x3B, 0x1B, 0x93, 0x9A, + 0xB0, 0xF1, 0x9C, 0x72, 0x5F, 0x8D, 0xA1, 0xC2, 0x8A, 0xC2, 0x0F, 0xE2, 0xF3, 0x58, 0xB9, 0x28, + 0x46, 0x4B, 0x8E, 0x90, 0x0C, 0x4F, 0x04, 0xD5, 0xB0, 0x3C, 0x79, 0x19, 0x8F, 0xB7, 0x8C, 0xAC, + 0xCF, 0x55, 0x3F, 0xC0, 0x8B, 0x7E, 0xA0, 0x0C, 0x36, 0x52, 0x9F, 0x99, 0x65, 0x53, 0x84, 0x01, + 0xA8, 0x65, 0x30, 0x79, 0x14, 0xC5, 0x7C, 0xBC, 0xF5, 0x07, 0x7D, 0x8C, 0xE3, 0x11, 0x43, 0xB8, + 0xD9, 0x37, 0x38, 0xC8, 0x62, 0x98, 0xD0, 0x79, 0x13, 0xDC, 0xC3, 0x5E, 0x1A, 0x11, 0x3B, 0x81, + 0x6F, 0x87, 0x28, 0xF0, 0xD5, 0x81, 0x3D, 0xE5, 0x91, 0x25, 0x16, 0xBF, 0xC2, 0x12, 0xE6, 0x5A, + 0x84, 0x96, 0x05, 0xAA, 0xD2, 0x51, 0x17, 0xAB, 0x0B, 0x9F, 0x49, 0x9B, 0xFE, 0xCA, 0xF1, 0x38, + 0x2B, 0x3B, 0x86, 0xC3, 0x5D, 0xC3, 0x46, 0x57, 0x4F, 0x34, 0x5C, 0x68, 0x11, 0xCF, 0x8F, 0xB3, + 0xD6, 0x06, 0x83, 0xC6, 0x2A, 0x3D, 0x72, 0x5C, 0x5B, 0x0F, 0x84, 0x97, 0xCB, 0xA3, 0x38, 0x39, + 0xD3, 0x19, 0xF0, 0x2E, 0xDE, 0xC4, 0x87, 0x1E, 0x2C, 0x68, 0xBF, 0x13, 0x29, 0xA4, 0xD5, 0x70, + 0xB7, 0x70, 0xB4, 0x57, 0x80, 0xF9, 0xC9, 0x3D, 0xA6, 0x95, 0x25, 0x37, 0x7A, 0xA1, 0x8A, 0xF1, + 0xF3, 0x29, 0xCD, 0xA9, 0xCA, 0x73, 0x0C, 0x03, 0xE9, 0xA0, 0xB9, 0x31, 0xAC, 0x00, 0x48, 0xA0, + 0x60, 0x51, 0xD1, 0x19, 0x5E, 0x59, 0x22, 0x05, 0xC8, 0xBB, 0x29, 0xBD, 0x5B, 0x0E, 0x10, 0x73, + 0x7F, 0x87, 0x51, 0xBD, 0xE3, 0x17, 0x2F, 0x8A, 0x8A, 0x98, 0x1C, 0xB1, 0x8C, 0x08, 0x75, 0x03, + 0xDA, 0x2C, 0xC4, 0xE0, 0x88, 0x46, 0xA6, 0x72, 0x9A, 0xA7, 0x92, 0x06, 0x53, 0xC7, 0xCE, 0xC9, + 0xE4, 0xC7, 0x35, 0x92, 0xEB, 0x1E, 0xA2, 0x87, 0x09, 0xA7, 0xBD, 0x4E, 0xE8, 0xD9, 0xFB, 0x00, + 0xBA, 0x9D, 0x26, 0x2C, 0xE8, 0xF9, 0xED, 0x46, 0xD6, 0x4B, 0x2D, 0x5A, 0x4B, 0xB8, 0xB0, 0xBF, + 0x2F, 0x22, 0x95, 0x37, 0x02, 0x7E, 0x20, 0xF5, 0xEB, 0x2C, 0x4C, 0x2D, 0x32, 0xA6, 0x33, 0xB3, + 0x8B, 0xB9, 0xB5, 0xEE, 0x42, 0x9E, 0xD2, 0x73, 0x39, 0x04, 0x8F, 0xFD, 0x0A, 0x66, 0x98, 0xCD, + 0x54, 0xD3, 0x18, 0x58, 0xC0, 0x3A, 0xC8, 0x10, 0x28, 0xA0, 0x04, 0x8F, 0x3F, 0x71, 0x3F, 0xA1, + 0x00, 0x94, 0x88, 0x16, 0xCB, 0x55, 0x2F, 0x26, 0xFB, 0x2E, 0x10, 0xB8, 0x5D, 0x54, 0xD3, 0x18, + 0x24, 0xBA, 0x46, 0x3D, 0x43, 0x30, 0x4A, 0x94, 0xEA, 0x1F, 0xDB, 0x8D, 0xE6, 0x7E, 0xA3, 0x79, + 0x50, 0x4C, 0xC7, 0x10, 0xF0, 0x38, 0xF9, 0x00, 0x47, 0xD2, 0x80, 0x82, 0xA5, 0xE3, 0xD2, 0xB4, + 0xE8, 0xB4, 0x2B, 0xBF, 0x3A, 0x55, 0xDD, 0xE8, 0x60, 0x6E, 0xB6, 0x6A, 0x40, 0xA9, 0xDF, 0xE1, + 0x83, 0xA2, 0x14, 0x60, 0x1F, 0x12, 0xAC, 0x4F, 0x86, 0xEE, 0x0F, 0x8F, 0xDB, 0x8A, 0x42, 0xF1, + 0xF0, 0x80, 0x2E, 0xB2, 0xE7, 0x62, 0xE6, 0x9F, 0xF4, 0x59, 0xCD, 0x88, 0x48, 0x6C, 0xBF, 0xFB, + 0xA7, 0x3C, 0x43, 0x90, 0x5C, 0x7E, 0x95, 0x66, 0xDD, 0x42, 0xDA, 0xF9, 0xA4, 0x86, 0x59, 0x34, + 0x77, 0x5F, 0xDF, 0x30, 0x01, 0x93, 0x44, 0xD5, 0x8E, 0x07, 0x60, 0x5E, 0xF4, 0x27, 0x99, 0x45, + 0x82, 0x87, 0x91, 0xE1, 0x87, 0x18, 0x71, 0x49, 0xCF, 0x6D, 0x4B, 0x23, 0xCF, 0xBD, 0x38, 0xE8, + 0x50, 0xFB, 0xFF, 0x45, 0x35, 0x7C, 0x8C, 0x11, 0xDD, 0x9B, 0x31, 0xAA, 0x78, 0x93, 0x9D, 0x5E, + 0xDD, 0xCE, 0xE5, 0x85, 0x5A, 0x9D, 0x07, 0x64, 0x88, 0xD8, 0x70, 0x90, 0x04, 0x96, 0xE1, 0xBF, + 0xF1, 0xC6, 0xA7, 0xC6, 0xC3, 0x33, 0x13, 0xE6, 0x0C, 0xBA, 0xF1, 0x61, 0x00, 0x0F, 0xA4, 0x27, + 0x84, 0xC9, 0xF8, 0x16, 0x2A, 0xCA, 0x69, 0xCA, 0x9C, 0x21, 0x10, 0x33, 0x86, 0x1A, 0x76, 0xCF, + 0x56, 0xEF, 0x9A, 0x38, 0xC3, 0xED, 0x69, 0x12, 0xB9, 0x71, 0x41, 0xA5, 0xC3, 0x6C, 0x33, 0x51, + 0x35, 0x83, 0x2D, 0x8E, 0x83, 0x10, 0x55, 0xCF, 0xEF, 0xF9, 0x28, 0x63, 0x4D, 0x95, 0xA2, 0xC9, + 0x37, 0x35, 0x91, 0x54, 0x14, 0xF5, 0x10, 0x59, 0x92, 0xAE, 0x60, 0x9F, 0x30, 0xBA, 0x87, 0x9E, + 0x96, 0xAB, 0x44, 0x33, 0xEE, 0x2C, 0x39, 0xBB, 0x85, 0xAB, 0xCF, 0x28, 0xB5, 0x93, 0x3B, 0x9B, + 0x12, 0xF8, 0x95, 0x2D, 0x40, 0xD3, 0xAC, 0x9D, 0x9C, 0xAA, 0x1E, 0x2F, 0xDF, 0xB0, 0x85, 0xC9, + 0x2E, 0xE7, 0xA8, 0x78, 0xD3, 0x16, 0x03, 0x62, 0x8A, 0xCC, 0xB5, 0xA9, 0x7A, 0xD3, 0x0D, 0x84, + 0x4B, 0xB0, 0xB0, 0xBE, 0x62, 0x94, 0xAF, 0xB8, 0xC9, 0x15, 0xE3, 0x03, 0x75, 0x91, 0x97, 0x4A, + 0x98, 0x0F, 0xA3, 0x4B, 0xF9, 0x30, 0xBE, 0x58, 0x48, 0x6D, 0xE4, 0x3F, 0xD7, 0xD8, 0x8C, 0x9C, + 0x3F, 0xA6, 0x3D, 0xB8, 0xB7, 0x7B, 0xE7, 0x67, 0x6A, 0x76, 0x3D, 0xA9, 0x55, 0xC4, 0x88, 0x0F, + 0x40, 0x16, 0x18, 0x60, 0x98, 0xF8, 0x00, 0xCF, 0xF3, 0xDE, 0x39, 0xC3, 0x09, 0xAD, 0x28, 0x60, + 0x5C, 0x8E, 0xBD, 0xCA, 0x8C, 0xAC, 0x2A, 0x88, 0xFB, 0x9A, 0x0B, 0x70, 0x27, 0x13, 0x39, 0x23, + 0x73, 0xA3, 0x4F, 0x58, 0x45, 0xF9, 0x57, 0xA3, 0x02, 0xEE, 0x91, 0x26, 0x0C, 0xDB, 0x34, 0x48, + 0xF3, 0x82, 0xDA, 0xCC, 0x30, 0xF0, 0x04, 0xE4, 0x73, 0x35, 0xDD, 0x12, 0x46, 0xA4, 0xC2, 0x7A, + 0x6E, 0x9C, 0x9B, 0x83, 0x50, 0x07, 0x53, 0xC1, 0xD0, 0xBE, 0xDA, 0x5C, 0x0A, 0xAB, 0xFA, 0x9D, + 0xC9, 0xA5, 0xE4, 0x4B, 0x85, 0x38, 0x0A, 0xDB, 0x01, 0x5D, 0xEF, 0xED, 0x71, 0x49, 0x13, 0x46, + 0x05, 0xDA, 0x6C, 0xE8, 0x2E, 0x85, 0x3E, 0x2B, 0xC8, 0xC9, 0x60, 0xE1, 0x88, 0x58, 0x0C, 0x23, + 0x4E, 0xC8, 0x08, 0xA3, 0x0D, 0x0D, 0xFE, 0x88, 0x38, 0x68, 0x8A, 0xF5, 0x48, 0x05, 0x96, 0x93, + 0x5F, 0xC8, 0xD8, 0x57, 0x85, 0xF7, 0x03, 0x02, 0x1D, 0x33, 0x31, 0x7E, 0x08, 0xDF, 0x33, 0x6D, + 0xF8, 0x01, 0x52, 0xE5, 0x68, 0x97, 0xE2, 0x5B, 0x2D, 0x9C, 0xD4, 0x2E, 0xDA, 0x31, 0x51, 0x59, + 0xF6, 0x02, 0xF7, 0x91, 0x3F, 0x53, 0xE6, 0x60, 0x15, 0x3A, 0x73, 0xD1, 0x0E, 0x1A, 0xBF, 0x9C, + 0x86, 0xD1, 0x27, 0x15, 0x5D, 0xA9, 0x0C, 0xC7, 0xA2, 0x62, 0xB1, 0x75, 0xEB, 0xE8, 0x68, 0xFC, + 0x55, 0x51, 0x25, 0x78, 0x79, 0x0A, 0x70, 0x41, 0x83, 0x51, 0x09, 0x5B, 0x61, 0x69, 0xA5, 0x37, + 0x86, 0xBA, 0xC5, 0x14, 0x8A, 0x71, 0x83, 0x55, 0x86, 0x91, 0x2F, 0x40, 0x96, 0xC2, 0x9B, 0x62, + 0x11, 0xC2, 0xCC, 0xDF, 0x48, 0x54, 0x1D, 0xA4, 0xDB, 0x86, 0xA4, 0xCD, 0xE5, 0x52, 0x1E, 0x10, + 0x51, 0x12, 0xFD, 0x93, 0xC4, 0x27, 0x0C, 0xA6, 0x48, 0x98, 0x21, 0xF7, 0xC7, 0x58, 0x26, 0xAC, + 0x51, 0x90, 0x46, 0x83, 0xF4, 0x1D, 0xC5, 0xD8, 0x53, 0x16, 0x11, 0x93, 0xCE, 0x0A, 0x99, 0xA2, + 0x58, 0x15, 0x84, 0x29, 0x08, 0xF0, 0x67, 0xA0, 0xB1, 0x65, 0x52, 0x99, 0xC4, 0xC4, 0x32, 0x74, + 0x26, 0x9A, 0x2C, 0x9B, 0xD2, 0xA4, 0x18, 0x27, 0x14, 0x60, 0x39, 0x4A, 0x11, 0x5A, 0x8B, 0x51, + 0x69, 0x11, 0xA3, 0xF2, 0x94, 0x12, 0x34, 0x31, 0x64, 0x8C, 0xD2, 0x13, 0xF6, 0x1D, 0x12, 0xEA, + 0x48, 0x43, 0x45, 0x7D, 0xE7, 0x58, 0x20, 0x4B, 0x71, 0x03, 0x66, 0x6C, 0x75, 0xB7, 0xEA, 0x68, + 0xC6, 0x45, 0x7B, 0xEF, 0xF2, 0xE2, 0x0F, 0x18, 0xAA, 0x11, 0x3C, 0x7C, 0xAF, 0xD8, 0x2C, 0xB9, + 0x98, 0x09, 0x6F, 0x41, 0x8E, 0xB8, 0x50, 0x86, 0xC5, 0xD9, 0x06, 0x3B, 0x72, 0xFF, 0xBC, 0xE5, + 0x4F, 0x00, 0xB5, 0x2A, 0x4C, 0x75, 0x53, 0x26, 0xBB, 0x58, 0xFF, 0x68, 0xAF, 0xEB, 0xE1, 0x9F, + 0xE4, 0x13, 0x00, 0x0F, 0x0A, 0xA6, 0xE4, 0x5A, 0xA2, 0x18, 0x74, 0x66, 0xDA, 0x98, 0xE8, 0x90, + 0x2C, 0x26, 0x81, 0xEB, 0x62, 0xD8, 0x0C, 0xF2, 0x5C, 0x74, 0x8E, 0xA3, 0x89, 0x7B, 0x92, 0x11, + 0xDB, 0x16, 0xDF, 0x1C, 0x46, 0x58, 0x39, 0xA2, 0x46, 0xBA, 0x5E, 0x73, 0x82, 0xAA, 0xAB, 0xBB, + 0xA3, 0xBD, 0xEB, 0x46, 0x3A, 0x58, 0x78, 0x37, 0x7B, 0xD7, 0x0D, 0x45, 0xEA, 0xD5, 0xDD, 0xB5, + 0x8E, 0xA7, 0xF1, 0x92, 0x89, 0x0A, 0xE3, 0xB7, 0xAD, 0x88, 0x9A, 0xA1, 0x1B, 0xEA, 0x1D, 0xEF, + 0x73, 0x17, 0xAB, 0x0F, 0xB0, 0xAE, 0xED, 0x19, 0x32, 0x97, 0x93, 0x3D, 0x12, 0x69, 0xC2, 0x9A, + 0x8A, 0x72, 0xB0, 0x07, 0x3F, 0x0E, 0x23, 0x89, 0x21, 0xF2, 0xF6, 0x16, 0x41, 0xCD, 0x83, 0xD7, + 0x75, 0x65, 0x1A, 0x6D, 0xD5, 0x9A, 0xDC, 0x92, 0x8E, 0x27, 0x44, 0xB9, 0x62, 0x00, 0xBB, 0xE6, + 0x12, 0x58, 0xA1, 0x9B, 0x62, 0x6C, 0x46, 0x0E, 0xC6, 0xC2, 0xD1, 0xD8, 0x8E, 0xF7, 0x76, 0x2D, + 0x6E, 0x48, 0x91, 0x70, 0x43, 0xDD, 0x71, 0xF2, 0x4E, 0x74, 0x06, 0x26, 0x27, 0xAD, 0x1C, 0x68, + 0x53, 0x33, 0xE4, 0xCA, 0x64, 0xFD, 0xC0, 0xC9, 0x64, 0x17, 0xDB, 0x1B, 0xD0, 0x14, 0x31, 0x35, + 0x05, 0x0B, 0x8B, 0xDF, 0x7D, 0x4E, 0x37, 0x5E, 0xC9, 0xAD, 0x67, 0xC5, 0x46, 0xA4, 0x1B, 0x8A, + 0x48, 0xA9, 0xC4, 0x94, 0x24, 0x0F, 0x3E, 0x68, 0x28, 0x7C, 0x8A, 0x97, 0x74, 0xFA, 0xC9, 0xF9, + 0xDF, 0x5D, 0xDD, 0x5E, 0xFC, 0x1A, 0x9D, 0x7F, 0xF4, 0xD7, 0xCA, 0x4F, 0xC0, 0xC4, 0x54, 0xD6, + 0xE5, 0x0C, 0x14, 0xA0, 0x48, 0xD4, 0x08, 0x95, 0x5C, 0x42, 0xD8, 0x89, 0x9F, 0x0C, 0x7F, 0x28, + 0xB3, 0xF5, 0x82, 0x38, 0x67, 0x45, 0x8C, 0x83, 0xE4, 0x38, 0xD2, 0x3A, 0x74, 0xE9, 0x4D, 0xFD, + 0xAA, 0x8E, 0xC0, 0xF8, 0x5E, 0x2D, 0x7E, 0x08, 0x92, 0x6B, 0x33, 0x90, 0xF7, 0x77, 0xD4, 0xB2, + 0xCE, 0x25, 0xBC, 0x52, 0x6F, 0xC7, 0x0A, 0x39, 0xE8, 0x4D, 0x1E, 0x8F, 0x34, 0xCB, 0x78, 0xD7, + 0x73, 0xD5, 0x06, 0xA2, 0x5E, 0x8A, 0x31, 0xE5, 0xC4, 0xBE, 0x1F, 0x97, 0x61, 0xBD, 0x89, 0x9B, + 0xB9, 0x94, 0x79, 0x23, 0xA4, 0xB2, 0x97, 0x53, 0xF8, 0xA6, 0x6E, 0xF6, 0xAD, 0x5D, 0x93, 0x7D, + 0xB6, 0x83, 0x22, 0xD7, 0x76, 0xB3, 0xAF, 0xF0, 0x0E, 0xA9, 0x1B, 0x6F, 0xB1, 0x7E, 0x30, 0x9D, + 0xC9, 0x7E, 0x15, 0x1D, 0x01, 0xD6, 0x34, 0x0F, 0x98, 0xF4, 0xA8, 0x29, 0xD1, 0x55, 0xCE, 0x85, + 0xDF, 0x0A, 0x14, 0xC5, 0x6C, 0x16, 0x94, 0xCC, 0xC4, 0x15, 0x7A, 0x70, 0xED, 0xB1, 0x21, 0x82, + 0x2B, 0x0C, 0xB2, 0x54, 0xA5, 0xDF, 0x97, 0x49, 0x66, 0x3E, 0xDB, 0xE1, 0x56, 0xE2, 0x22, 0x27, + 0x84, 0xEE, 0xA6, 0xE9, 0x98, 0x65, 0xD8, 0xCA, 0x97, 0x07, 0xAC, 0x78, 0x4F, 0xB4, 0x12, 0x4A, + 0x17, 0x15, 0x73, 0x17, 0x18, 0x61, 0x86, 0xE8, 0x5D, 0x29, 0x73, 0xB1, 0xC7, 0x8B, 0x89, 0x4E, + 0x9B, 0x05, 0x79, 0x4C, 0x62, 0xF6, 0x11, 0x8B, 0x49, 0x5B, 0x53, 0x55, 0x1C, 0xC6, 0x5B, 0x98, + 0xBB, 0xB4, 0x16, 0x67, 0x2C, 0x07, 0x15, 0xB0, 0x14, 0x65, 0xC1, 0x3E, 0xF6, 0x91, 0x2D, 0x2D, + 0xD8, 0xC7, 0x41, 0xED, 0xA4, 0xBD, 0xE8, 0x3C, 0x30, 0x55, 0x91, 0xF2, 0x5A, 0xF8, 0x22, 0x7F, + 0xE4, 0xC0, 0x7D, 0x52, 0x72, 0x14, 0x26, 0x52, 0xDE, 0xBE, 0x32, 0xA3, 0x5A, 0x75, 0xEE, 0x74, + 0xC2, 0x9B, 0x12, 0xD0, 0xC2, 0xB7, 0x6D, 0x7F, 0x48, 0x59, 0xBF, 0xEF, 0x41, 0x7C, 0x2F, 0xCF, + 0x32, 0xE3, 0x6C, 0x72, 0xBA, 0xBF, 0xDA, 0xC9, 0x69, 0xF8, 0x8C, 0x75, 0x5D, 0xDB, 0xB7, 0x81, + 0x29, 0x96, 0x73, 0x5D, 0x4A, 0xE9, 0x33, 0x63, 0xEE, 0x55, 0x38, 0x33, 0xF5, 0xBA, 0xDD, 0xF9, + 0x5C, 0x99, 0xAE, 0x2F, 0xE6, 0xF2, 0x64, 0x82, 0xF1, 0xD8, 0x3F, 0xB3, 0xB9, 0x5A, 0xC3, 0x8E, + 0x7C, 0xE9, 0xF7, 0xD7, 0xC6, 0x95, 0xE9, 0x2C, 0x2A, 0xE1, 0x83, 0x25, 0x09, 0xD0, 0x38, 0x73, + 0x86, 0xDD, 0x1A, 0x1A, 0x1B, 0x63, 0x80, 0xC8, 0x75, 0xCC, 0xB0, 0x5A, 0x23, 0x62, 0x03, 0xC9, + 0x2B, 0x3B, 0x00, 0x82, 0xB7, 0xBB, 0xB1, 0x97, 0xAE, 0xED, 0xA7, 0xFA, 0x85, 0xC5, 0xDD, 0xC1, + 0x33, 0xDB, 0x01, 0xC0, 0xBC, 0xA5, 0x3A, 0x06, 0x7E, 0xE0, 0x5A, 0xB1, 0x77, 0xEC, 0x7E, 0x3F, + 0x46, 0xE8, 0x11, 0x10, 0x37, 0xC4, 0x1F, 0xEA, 0x81, 0x73, 0x87, 0xEA, 0xAB, 0x8B, 0xC8, 0xED, + 0xA5, 0x95, 0xD7, 0x3B, 0xA5, 0x71, 0x62, 0xD1, 0x48, 0xBA, 0x81, 0xBF, 0xC5, 0xE3, 0xA5, 0x17, + 0xDB, 0x0B, 0x47, 0x5F, 0x7E, 0x32, 0x4F, 0x8A, 0xFE, 0x8B, 0x2A, 0x64, 0x3C, 0x04, 0x3F, 0x7E, + 0x60, 0xD4, 0x83, 0x4D, 0xC9, 0x69, 0x99, 0x1A, 0x50, 0xB5, 0x0B, 0xCE, 0xF5, 0x07, 0x15, 0xF3, + 0x72, 0x0A, 0x73, 0x75, 0xE0, 0x61, 0x6A, 0x94, 0x32, 0x9E, 0x4E, 0xEB, 0x83, 0x3E, 0x23, 0xAE, + 0x7A, 0x81, 0x4B, 0x30, 0xEA, 0x69, 0xAA, 0xB9, 0x20, 0xCF, 0x9E, 0xEC, 0xAD, 0x76, 0x72, 0x33, + 0x7E, 0xC2, 0xE8, 0x51, 0x39, 0x86, 0x3D, 0xD5, 0x61, 0xEA, 0xA4, 0xAB, 0x60, 0xD6, 0x37, 0x1C, + 0xB6, 0xDC, 0x9B, 0x8B, 0x5F, 0x5F, 0x72, 0xEE, 0xEF, 0x5D, 0xA1, 0xF9, 0xC9, 0x5B, 0x1B, 0x0E, + 0x7A, 0x2E, 0x6E, 0x9B, 0x65, 0x85, 0x35, 0xAC, 0xD4, 0x12, 0x50, 0xF9, 0x34, 0xC3, 0x62, 0x23, + 0x5A, 0x29, 0x32, 0x42, 0x40, 0x64, 0x5F, 0xFA, 0x68, 0xE8, 0x36, 0x28, 0x82, 0x18, 0xCE, 0xA9, + 0xF6, 0xFB, 0x08, 0x7E, 0x2A, 0x20, 0x2D, 0x72, 0x64, 0x01, 0xCF, 0xB4, 0xCC, 0xE7, 0x31, 0x4D, + 0xC8, 0x58, 0x21, 0xEA, 0x55, 0xD4, 0x5D, 0x93, 0x57, 0xDB, 0x71, 0x79, 0x49, 0x80, 0x73, 0x63, + 0xD2, 0xCB, 0x56, 0xCF, 0x2F, 0x31, 0x4C, 0x8E, 0xFC, 0x6A, 0x53, 0x02, 0x38, 0xCF, 0x05, 0x04, + 0xE1, 0x6B, 0xBC, 0xB7, 0x5D, 0x3A, 0xF3, 0x8C, 0x4D, 0xE5, 0xC5, 0x4A, 0x93, 0x27, 0x82, 0x2F, + 0x5D, 0xB1, 0xF0, 0xB1, 0x7B, 0xD0, 0x90, 0x9B, 0x0E, 0xFA, 0x07, 0x51, 0xCE, 0x62, 0x9D, 0x3B, + 0xA6, 0xFD, 0x2C, 0xE2, 0x05, 0x64, 0x17, 0x06, 0x26, 0x4B, 0x06, 0x82, 0xB7, 0x7D, 0x14, 0xD9, + 0x35, 0x99, 0x2B, 0x6A, 0x2A, 0x21, 0xDA, 0x66, 0xB0, 0xDC, 0x89, 0x30, 0x4A, 0xDA, 0x99, 0x6A, + 0x8A, 0x98, 0x96, 0x4E, 0x35, 0xE4, 0xF2, 0x07, 0x10, 0x81, 0xC2, 0xC0, 0xB3, 0x0A, 0xA2, 0x1F, + 0x67, 0x6B, 0x26, 0x72, 0xDF, 0xBD, 0xE3, 0x97, 0xB0, 0xD0, 0x8F, 0x83, 0x21, 0xE5, 0x34, 0x66, + 0x06, 0x41, 0x52, 0xE2, 0xD9, 0x42, 0x31, 0x8F, 0x9B, 0x9D, 0x4C, 0x68, 0xCE, 0xAB, 0xBB, 0x24, + 0xE2, 0xE4, 0xE7, 0x7E, 0x48, 0xBC, 0x3F, 0xD7, 0x45, 0xDD, 0x02, 0x9A, 0xA9, 0x37, 0x0C, 0x7C, + 0x14, 0x08, 0x6E, 0xED, 0xB3, 0x21, 0x66, 0xC8, 0x91, 0x45, 0x51, 0xE4, 0x6C, 0xCE, 0x24, 0xEB, + 0x14, 0x24, 0xF8, 0x12, 0x31, 0x05, 0xB3, 0xE7, 0x07, 0x7A, 0x9D, 0xFC, 0x5E, 0xD4, 0x57, 0xF0, + 0xB1, 0xC0, 0x16, 0x12, 0xE7, 0xE0, 0x78, 0xC9, 0xF1, 0x06, 0xC5, 0xE0, 0xB6, 0xDA, 0x40, 0x84, + 0xD4, 0xC3, 0x85, 0x14, 0x3A, 0x50, 0xE3, 0x64, 0x01, 0x0A, 0xCC, 0x0E, 0x46, 0x92, 0x0A, 0x01, + 0x0A, 0x08, 0x58, 0x26, 0xBC, 0x87, 0xE1, 0x72, 0x8F, 0x1C, 0x94, 0x8F, 0xD0, 0xB3, 0xD5, 0x42, + 0x83, 0x10, 0x88, 0x48, 0xF0, 0x35, 0x99, 0xC4, 0x51, 0xC6, 0xA7, 0x94, 0x17, 0xA2, 0x94, 0x23, + 0x89, 0xFE, 0x38, 0x6A, 0x8C, 0x6F, 0x24, 0xF5, 0xC8, 0x22, 0x67, 0xD2, 0x72, 0x58, 0xC3, 0xB2, + 0x72, 0x74, 0xCE, 0x46, 0x87, 0x17, 0x3A, 0xC1, 0x72, 0x68, 0x67, 0xB1, 0x23, 0x0D, 0xAF, 0x43, + 0x66, 0xEF, 0x5E, 0x38, 0xFC, 0x8B, 0x9C, 0x68, 0x5E, 0xC4, 0x17, 0x66, 0x1C, 0x64, 0x11, 0x6D, + 0x64, 0x9D, 0x65, 0xD9, 0x34, 0x13, 0x86, 0xF8, 0x8C, 0x3D, 0xAE, 0x15, 0xB6, 0x13, 0x16, 0x2D, + 0x7D, 0x4B, 0x25, 0x58, 0x94, 0x5D, 0xE5, 0x48, 0x69, 0xFC, 0x94, 0x47, 0x60, 0x1E, 0xD7, 0xCE, + 0x3D, 0x13, 0x67, 0x77, 0xB0, 0xA4, 0x43, 0x72, 0xD5, 0x6A, 0xD0, 0xA5, 0xAA, 0xF9, 0xB6, 0x3B, + 0xAE, 0x05, 0x10, 0xD5, 0x80, 0x16, 0xCF, 0x63, 0x19, 0xFB, 0x97, 0xAC, 0x04, 0x4D, 0x4E, 0x24, + 0xD7, 0x5F, 0xA4, 0x42, 0xA5, 0x68, 0x72, 0xB1, 0x82, 0x32, 0xB9, 0x8B, 0x99, 0x75, 0x91, 0x14, + 0xE9, 0x70, 0x01, 0x79, 0x13, 0xC3, 0x22, 0x84, 0x46, 0xED, 0x46, 0x95, 0xF9, 0x22, 0xB5, 0x5B, + 0x96, 0x53, 0x22, 0x63, 0x94, 0xE7, 0xDB, 0xB0, 0x45, 0x61, 0x8B, 0x06, 0xEB, 0x40, 0x27, 0x22, + 0x8A, 0xC2, 0x42, 0x1F, 0x13, 0x0C, 0xBC, 0x1E, 0xA9, 0x06, 0x25, 0x70, 0xA2, 0x28, 0x8C, 0xD4, + 0x62, 0xD2, 0xE3, 0x31, 0x96, 0x55, 0x38, 0x7A, 0xC5, 0x3A, 0x57, 0x31, 0xCC, 0xAE, 0x95, 0xAE, + 0x6D, 0xD1, 0x9F, 0x44, 0x9D, 0x85, 0xEB, 0x59, 0x4C, 0x20, 0x63, 0xA2, 0x18, 0x74, 0x54, 0xCC, + 0x62, 0x9A, 0x44, 0x66, 0x57, 0xED, 0x70, 0xD2, 0x26, 0x5B, 0x49, 0x94, 0x7A, 0xE9, 0xFA, 0x18, + 0x17, 0x58, 0xDA, 0xD5, 0xE2, 0x2F, 0x59, 0x1D, 0x83, 0xCB, 0x29, 0x2C, 0xA3, 0x36, 0xC6, 0xC5, + 0x44, 0xDF, 0xA5, 0x12, 0x6B, 0x4E, 0x34, 0x9E, 0x1E, 0xB3, 0x60, 0x7E, 0x93, 0x09, 0x18, 0x4F, + 0xA4, 0xE0, 0x8C, 0x96, 0xBF, 0x06, 0x95, 0x33, 0x26, 0x56, 0x5C, 0x75, 0xAD, 0xBE, 0xAA, 0xCE, + 0x2B, 0x39, 0xCB, 0xF3, 0xCF, 0x67, 0x5D, 0x38, 0xA6, 0x42, 0xE8, 0x06, 0x18, 0x73, 0x81, 0xCF, + 0x96, 0x79, 0x42, 0xC5, 0x87, 0x1E, 0x33, 0x0B, 0x7D, 0xA8, 0x39, 0xE1, 0x3C, 0x80, 0x45, 0xCC, + 0xA8, 0x25, 0xB8, 0xAA, 0x83, 0x2C, 0xAE, 0x80, 0x45, 0x10, 0xA2, 0xC3, 0x0C, 0x2B, 0x38, 0xE3, + 0xF4, 0x1B, 0xA1, 0xE2, 0x83, 0x1C, 0x0C, 0x1F, 0xAA, 0x32, 0x57, 0xFB, 0x55, 0x97, 0x75, 0x74, + 0x1D, 0x0F, 0x8D, 0x5D, 0x76, 0x7E, 0xDB, 0xDB, 0x65, 0x9F, 0x54, 0x9F, 0x3F, 0x49, 0x0B, 0x75, + 0x2F, 0x78, 0xC0, 0x9E, 0x6E, 0x54, 0xEF, 0xDB, 0xA6, 0x5D, 0xA4, 0xE4, 0x25, 0xEF, 0xA0, 0xD5, + 0x5F, 0x75, 0x7B, 0xF2, 0xAC, 0x16, 0x34, 0x10, 0xC2, 0x6E, 0x79, 0x7A, 0x51, 0x88, 0x52, 0x57, + 0xDD, 0x44, 0xFE, 0xF0, 0x83, 0x29, 0x6D, 0xE7, 0x72, 0x62, 0x77, 0x5E, 0x44, 0x93, 0x41, 0xCC, + 0x21, 0x8D, 0x43, 0x1E, 0x82, 0x69, 0xD8, 0x45, 0x9A, 0xCB, 0x24, 0x2E, 0xBD, 0xB6, 0x4C, 0xDE, + 0x07, 0xA5, 0x72, 0x78, 0xE3, 0xDC, 0x67, 0x64, 0xF0, 0x8E, 0xE1, 0x40, 0xB1, 0x20, 0xD0, 0x71, + 0x83, 0x95, 0xE6, 0xED, 0xAE, 0x16, 0xE3, 0x81, 0xB9, 0xE4, 0xA0, 0x3C, 0xBC, 0xB1, 0xDE, 0x58, + 0x8E, 0x4B, 0xD8, 0x22, 0x76, 0x3E, 0x62, 0x17, 0x80, 0xD3, 0x04, 0x66, 0x43, 0x8B, 0x0D, 0x46, + 0x6D, 0x79, 0x64, 0xE6, 0xA0, 0xB7, 0x7C, 0x6B, 0xBD, 0x51, 0x3C, 0x5C, 0xCA, 0x16, 0xCD, 0xF3, + 0xD1, 0xBC, 0x20, 0xAC, 0x26, 0x50, 0x5D, 0xB6, 0xDA, 0x60, 0x74, 0x17, 0x52, 0x61, 0x0E, 0xB6, + 0xC7, 0x44, 0xC7, 0xF5, 0xC6, 0x78, 0x4F, 0x4C, 0x74, 0x04, 0x13, 0xDD, 0x62, 0x7D, 0x01, 0xAC, + 0x97, 0xBB, 0x5F, 0x0E, 0xE9, 0x45, 0xA3, 0x75, 0x29, 0x20, 0x34, 0x4B, 0x37, 0x98, 0xBB, 0xDA, + 0x7C, 0xB8, 0xD4, 0x5B, 0xDF, 0x41, 0xDF, 0xC7, 0x1C, 0xF2, 0x88, 0x90, 0xF1, 0xF6, 0xBE, 0x4B, + 0xBE, 0x92, 0x95, 0x54, 0x8A, 0x0F, 0xF1, 0x7F, 0xAA, 0xF7, 0x48, 0x7B, 0x43, 0x92, 0x68, 0xB6, + 0xDA, 0x9B, 0x5A, 0x97, 0xBD, 0x10, 0x66, 0x97, 0xAB, 0xA7, 0x33, 0xB9, 0x6F, 0xF9, 0x17, 0x04, + 0x13, 0x2D, 0x56, 0x70, 0x6D, 0x5E, 0xDA, 0xD0, 0x87, 0xFB, 0xFE, 0x72, 0x36, 0x3E, 0xCB, 0x77, + 0x96, 0x61, 0xDE, 0x83, 0x45, 0xCD, 0x65, 0xD9, 0x1B, 0xB7, 0x9B, 0xDB, 0xA8, 0x37, 0x86, 0xA7, + 0xB4, 0xE7, 0x49, 0x73, 0x1E, 0xAE, 0x74, 0x0D, 0x2C, 0x79, 0xE3, 0x15, 0x56, 0x6D, 0xC4, 0x2B, + 0xC5, 0x02, 0x2D, 0x24, 0x08, 0xD3, 0xBC, 0xF8, 0xEE, 0x00, 0x18, 0xAD, 0x3C, 0x16, 0x88, 0xAF, + 0xB2, 0xF0, 0xDD, 0xE3, 0x95, 0x39, 0x2B, 0x08, 0x47, 0x03, 0x4B, 0x27, 0x2F, 0x76, 0x2F, 0xCC, + 0x5F, 0x67, 0x8C, 0x82, 0xD1, 0x38, 0xE6, 0x37, 0xCC, 0x19, 0xEF, 0x09, 0x9B, 0x3C, 0xBA, 0x18, + 0x87, 0x99, 0x14, 0x1B, 0xEC, 0xA2, 0x31, 0x68, 0xC8, 0xEB, 0x5C, 0xC1, 0x52, 0xC9, 0x66, 0x88, + 0xF9, 0x05, 0x0E, 0xF1, 0xEA, 0xC7, 0x1B, 0x5F, 0x0F, 0x61, 0x57, 0x98, 0x0A, 0xEB, 0x7F, 0x1E, + 0xB2, 0x8F, 0xEC, 0x70, 0xDF, 0xDB, 0x72, 0xDD, 0x88, 0xEB, 0x4E, 0xA2, 0x4A, 0x3E, 0xD7, 0x9D, + 0x68, 0xB1, 0x14, 0xAE, 0x5B, 0x3D, 0x39, 0xB8, 0x5C, 0x33, 0xBC, 0x78, 0x68, 0x6F, 0x06, 0x2D, + 0x84, 0xEF, 0xBD, 0x28, 0x1D, 0x38, 0xE1, 0x2C, 0xC2, 0x5A, 0x7F, 0x32, 0x65, 0xAD, 0x66, 0xDA, + 0xDA, 0xB7, 0x59, 0x88, 0x5F, 0x6F, 0x29, 0x63, 0xD4, 0x1F, 0xF7, 0x42, 0xB8, 0x8F, 0xDF, 0x7D, + 0x64, 0xFF, 0xD6, 0x0C, 0xB6, 0xE8, 0x9F, 0x44, 0xFF, 0x08, 0x35, 0x8A, 0xE1, 0x7E, 0xF8, 0xFA, + 0x66, 0x20, 0xFE, 0x9D, 0x6D, 0xFB, 0xE7, 0xDC, 0xCC, 0x35, 0x8A, 0xE0, 0x7B, 0x8C, 0x5E, 0x7C, + 0x51, 0xCC, 0xF7, 0x6D, 0xBA, 0x79, 0xB7, 0x03, 0x4B, 0xAF, 0xFB, 0xAE, 0xE1, 0x00, 0x8A, 0xA3, + 0x97, 0xBE, 0x0C, 0x24, 0x71, 0xA3, 0x4C, 0x33, 0x44, 0x09, 0xE8, 0x8C, 0x16, 0xC4, 0x9D, 0xEA, + 0x95, 0x2D, 0x66, 0xC7, 0x31, 0x7B, 0xBC, 0xF7, 0x85, 0x30, 0x3B, 0x7A, 0x7D, 0x83, 0x30, 0x1B, + 0xC4, 0x45, 0x51, 0x7C, 0xA8, 0x10, 0x7A, 0x47, 0x6F, 0xAF, 0x85, 0x94, 0xC3, 0x11, 0xA4, 0x80, + 0xD3, 0x26, 0x08, 0xB2, 0x8F, 0xBC, 0x28, 0x8E, 0x37, 0x15, 0x65, 0x8B, 0xE6, 0xD3, 0x68, 0x3E, + 0x46, 0x84, 0xE2, 0xB8, 0x1E, 0xB5, 0xD9, 0x10, 0x84, 0x0F, 0x31, 0xE3, 0x4A, 0xCF, 0xC3, 0xF6, + 0x08, 0x87, 0xAE, 0xCE, 0x57, 0x8C, 0xEA, 0x1A, 0xE6, 0xD0, 0x27, 0x0F, 0x2A, 0xA3, 0x6F, 0x48, + 0x84, 0x9F, 0x40, 0xE9, 0x18, 0x32, 0x7F, 0xEA, 0xF6, 0x62, 0xE9, 0x6A, 0x31, 0x8D, 0xC3, 0x50, + 0x75, 0x55, 0x2D, 0x2F, 0x34, 0xEA, 0x75, 0xE1, 0x78, 0x8E, 0xBD, 0x6F, 0x62, 0xE7, 0x8B, 0xA1, + 0xF7, 0xB8, 0xC1, 0x3A, 0x5A, 0x45, 0x28, 0x3F, 0xF3, 0x8D, 0x6A, 0xA9, 0xE8, 0x48, 0x5B, 0x91, + 0x5D, 0xC4, 0xB6, 0xB4, 0xA8, 0xAE, 0x10, 0xF6, 0x7F, 0x6D, 0x78, 0x54, 0x20, 0x46, 0xF8, 0x18, + 0x98, 0x5C, 0x0E, 0x57, 0x9B, 0xAF, 0xCE, 0x70, 0x96, 0x69, 0x64, 0xD2, 0x84, 0x92, 0x61, 0x31, + 0xB9, 0x8C, 0x4F, 0x20, 0xD5, 0x66, 0x32, 0x3D, 0x40, 0x86, 0x11, 0x25, 0xD1, 0x55, 0x41, 0xAB, + 0x49, 0x02, 0xDE, 0xD2, 0x62, 0x12, 0x83, 0xC9, 0x3A, 0x58, 0x4E, 0xE2, 0xCB, 0xAA, 0xC2, 0x76, + 0x92, 0x2C, 0x95, 0x95, 0x81, 0xE6, 0xBD, 0x73, 0xD6, 0x33, 0x7E, 0x60, 0xC8, 0xAD, 0xF4, 0x38, + 0xD6, 0xF1, 0xCF, 0xEC, 0x8C, 0xC4, 0x0A, 0xBB, 0x39, 0x45, 0xA2, 0x61, 0x7B, 0xEC, 0xD2, 0xE5, + 0xF1, 0x76, 0xF8, 0x67, 0xCF, 0x01, 0xAE, 0x39, 0x83, 0x55, 0xE6, 0xF5, 0x5A, 0xCA, 0x74, 0x4E, + 0x15, 0x45, 0x27, 0x37, 0xF2, 0x1E, 0x1F, 0x66, 0x9E, 0x26, 0xBE, 0x2B, 0xA1, 0xF2, 0xC6, 0xE4, + 0x7D, 0xFF, 0xCD, 0x2C, 0x46, 0xE2, 0x0F, 0x4F, 0x30, 0x37, 0xF3, 0x87, 0x3D, 0xF8, 0x30, 0xFB, + 0x35, 0x04, 0x58, 0xEE, 0x6B, 0xFA, 0x49, 0x82, 0xE1, 0x8D, 0xBD, 0xBC, 0xC2, 0xF9, 0xF7, 0x28, + 0xEA, 0xB7, 0x63, 0xA6, 0x05, 0xE8, 0x4B, 0x0F, 0xB1, 0xFC, 0x1B, 0xA1, 0xC8, 0x2F, 0x2C, 0x0E, + 0x11, 0x22, 0x50, 0x4C, 0x56, 0x0C, 0x93, 0xCC, 0x74, 0x00, 0xDB, 0xF3, 0xDD, 0x2A, 0x80, 0xA6, + 0x53, 0xCA, 0xEA, 0x8B, 0xEF, 0xE4, 0xFA, 0xFB, 0x47, 0xE8, 0xD1, 0xF4, 0x87, 0xD2, 0xF0, 0xBF, + 0xFB, 0x33, 0x86, 0x0F, 0x1B, 0x1F, 0x10, 0x1E, 0xE4, 0xBE, 0x96, 0x01, 0x4A, 0x11, 0x0F, 0x8E, + 0x4B, 0xBF, 0x3A, 0x17, 0x80, 0xCD, 0x9E, 0x4C, 0x01, 0x60, 0x66, 0x6C, 0x03, 0x8B, 0xB3, 0x8D, + 0x59, 0xDE, 0xC2, 0x12, 0xAE, 0xAB, 0x05, 0x79, 0xAB, 0xD5, 0x54, 0xDA, 0xCD, 0x3F, 0x94, 0x96, + 0xD2, 0x54, 0x0E, 0x45, 0xDE, 0xF0, 0x5C, 0x70, 0x42, 0x1B, 0xF6, 0xD7, 0xA5, 0xC1, 0x7D, 0x6A, + 0x46, 0xAF, 0x1F, 0xF4, 0x2D, 0xE5, 0x7D, 0x41, 0xD0, 0xEF, 0x2B, 0x47, 0x2B, 0x01, 0xBD, 0x9C, + 0xD1, 0xDA, 0x82, 0x1E, 0x1E, 0x23, 0xE3, 0x3E, 0xC9, 0x62, 0xF3, 0xF9, 0xBB, 0x25, 0x8E, 0xB9, + 0xBC, 0xFD, 0x9A, 0x7D, 0x85, 0x54, 0x1B, 0x8B, 0x50, 0xB1, 0xE5, 0x9E, 0x03, 0x67, 0xF6, 0x89, + 0x81, 0x8A, 0x4F, 0x05, 0xD2, 0xBC, 0x17, 0xD9, 0xD0, 0x6A, 0x5E, 0x99, 0x67, 0x3D, 0x20, 0xC4, + 0x60, 0x75, 0x3A, 0x5A, 0x91, 0xFC, 0xBC, 0xD8, 0x9A, 0x72, 0x37, 0x35, 0xEB, 0xE2, 0x7B, 0xB6, + 0x17, 0x76, 0xC1, 0xEA, 0x8A, 0x99, 0x95, 0x15, 0xF1, 0x73, 0x73, 0x7C, 0xC2, 0x36, 0xE3, 0xA5, + 0x14, 0x45, 0xC5, 0x41, 0x14, 0xB9, 0x66, 0x95, 0x50, 0x14, 0x65, 0xFC, 0xD2, 0x56, 0x96, 0xA5, + 0x0A, 0xA5, 0x57, 0xE2, 0x74, 0x52, 0x6A, 0x6F, 0x2A, 0xB1, 0xD2, 0x9B, 0xB9, 0x95, 0x35, 0x67, + 0x94, 0xB8, 0x94, 0x02, 0x98, 0x58, 0x10, 0x56, 0xD9, 0x0B, 0xA2, 0xC0, 0x8D, 0x45, 0x43, 0x34, + 0x2C, 0x7D, 0x52, 0x35, 0x89, 0xBD, 0x3B, 0x74, 0x33, 0xA4, 0xDB, 0x14, 0x75, 0x3E, 0xAD, 0x74, + 0xEB, 0x84, 0xAE, 0x88, 0x01, 0x88, 0x1E, 0x88, 0xD8, 0xF0, 0xB9, 0x49, 0xDA, 0x7C, 0xB3, 0x15, + 0x3E, 0x52, 0x32, 0x03, 0x44, 0x67, 0xD4, 0x81, 0x50, 0x1F, 0xF9, 0xA9, 0x6F, 0x4D, 0xE9, 0x3A, + 0x22, 0x6D, 0x5B, 0x92, 0x36, 0xF0, 0x5D, 0x71, 0x67, 0x49, 0x25, 0x1D, 0xE0, 0xAF, 0x74, 0x6C, + 0x98, 0x88, 0xA2, 0x98, 0xD2, 0xBE, 0xB1, 0x1F, 0xD4, 0xB4, 0x9B, 0x91, 0xA6, 0x3D, 0x83, 0xAC, + 0x42, 0xB9, 0x59, 0xCC, 0xB3, 0xB4, 0x8A, 0x9A, 0x6C, 0x1E, 0x06, 0xEC, 0x14, 0x0E, 0xE3, 0x49, + 0x0D, 0xE1, 0x29, 0xB0, 0x49, 0x62, 0x63, 0xCA, 0x6D, 0x05, 0xFF, 0x6E, 0xF8, 0x69, 0x5B, 0x61, + 0x07, 0x3E, 0xCE, 0x32, 0x75, 0x4B, 0xB0, 0xCD, 0x78, 0x4B, 0x2E, 0xE0, 0x2F, 0x0C, 0x02, 0x48, + 0xDF, 0x16, 0x8A, 0x86, 0x9A, 0xDE, 0x0D, 0xCC, 0x05, 0xF2, 0x28, 0xCD, 0x20, 0xD1, 0x10, 0x65, + 0xB7, 0x47, 0xCE, 0x3D, 0x6D, 0x7B, 0xF2, 0x82, 0xA4, 0x9C, 0x93, 0x7F, 0xB6, 0x1E, 0x3C, 0xE7, + 0x2F, 0xF9, 0xC0, 0x8F, 0xFF, 0x9D, 0xF8, 0xEC, 0x69, 0xAE, 0xE1, 0xF8, 0xCC, 0x73, 0x35, 0xD8, + 0x69, 0x57, 0xDB, 0xC3, 0x80, 0xBD, 0xC6, 0xDF, 0x69, 0x48, 0xF1, 0x55, 0x76, 0xA3, 0x58, 0xF7, + 0xB0, 0x74, 0x0F, 0xA3, 0xC5, 0x6C, 0xAC, 0xA5, 0xE4, 0xB1, 0x8F, 0x4C, 0xB7, 0xB5, 0x00, 0x4D, + 0x5B, 0x8D, 0x3F, 0x03, 0xEE, 0x3E, 0x0B, 0xC5, 0xC3, 0x76, 0x41, 0xF5, 0xD8, 0x79, 0xD3, 0xF0, + 0xFD, 0x37, 0x6F, 0xC7, 0x4D, 0xC3, 0x46, 0x0D, 0x10, 0x07, 0x2E, 0x54, 0x6D, 0xB8, 0xE3, 0xB3, + 0x8F, 0x27, 0xEC, 0x5F, 0x92, 0xCB, 0xC1, 0x54, 0xB0, 0x98, 0xBA, 0xC1, 0xF3, 0x5D, 0xD5, 0x69, + 0xDC, 0x8B, 0x26, 0x3B, 0x7E, 0xAC, 0x9B, 0x7F, 0x7D, 0x1B, 0xCE, 0x33, 0x9A, 0x1C, 0x80, 0x1E, + 0xB4, 0x57, 0xE2, 0x28, 0x1F, 0xF6, 0x86, 0xFE, 0xC8, 0x3C, 0xF9, 0xFF, 0xD6, 0x4D, 0xBD, 0x53, + 0xEC, 0x61, 0x00 }; ///index_html //Content of bootstrap.bundle.min.jss with gzip compression From 57dda7f2ea1c9a6d01334fc768f2e989ce54251d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Thu, 20 Feb 2025 15:39:18 +0000 Subject: [PATCH 275/276] mosaic : add NMEA and RTCM to "inWebConfig" --- Firmware/RTK_Everywhere/settings.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h index e4a8b3bbc..ed6ace872 100644 --- a/Firmware/RTK_Everywhere/settings.h +++ b/Firmware/RTK_Everywhere/settings.h @@ -1293,12 +1293,12 @@ const RTK_Settings_Entry rtkSettingsEntries[] = #ifdef COMPILE_MOSAICX5 { 1, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicConst, MAX_MOSAIC_CONSTELLATIONS, & settings.mosaicConstellations, "constellation_", }, - { 0, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicMSNmea, MAX_MOSAIC_NMEA_MSG, & settings.mosaicMessageStreamNMEA, "messageStreamNMEA_", }, - { 0, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicSINmea, MOSAIC_NUM_NMEA_STREAMS, & settings.mosaicStreamIntervalsNMEA, "streamIntervalNMEA_", }, - { 0, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicMIRvRT, MAX_MOSAIC_RTCM_V3_INTERVAL_GROUPS, & settings.mosaicMessageIntervalsRTCMv3Rover, "messageIntervalRTCMRover_", }, - { 0, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicMIBaRT, MAX_MOSAIC_RTCM_V3_INTERVAL_GROUPS, & settings.mosaicMessageIntervalsRTCMv3Base, "messageIntervalRTCMBase_", }, - { 0, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicMERvRT, MAX_MOSAIC_RTCM_V3_MSG, & settings.mosaicMessageEnabledRTCMv3Rover, "messageEnabledRTCMRover_", }, - { 0, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicMEBaRT, MAX_MOSAIC_RTCM_V3_MSG, & settings.mosaicMessageEnabledRTCMv3Base, "messageEnabledRTCMBase_", }, + { 1, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicMSNmea, MAX_MOSAIC_NMEA_MSG, & settings.mosaicMessageStreamNMEA, "messageStreamNMEA_", }, + { 1, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicSINmea, MOSAIC_NUM_NMEA_STREAMS, & settings.mosaicStreamIntervalsNMEA, "streamIntervalNMEA_", }, + { 1, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicMIRvRT, MAX_MOSAIC_RTCM_V3_INTERVAL_GROUPS, & settings.mosaicMessageIntervalsRTCMv3Rover, "messageIntervalRTCMRover_", }, + { 1, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicMIBaRT, MAX_MOSAIC_RTCM_V3_INTERVAL_GROUPS, & settings.mosaicMessageIntervalsRTCMv3Base, "messageIntervalRTCMBase_", }, + { 1, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicMERvRT, MAX_MOSAIC_RTCM_V3_MSG, & settings.mosaicMessageEnabledRTCMv3Rover, "messageEnabledRTCMRover_", }, + { 1, 1, 1, 0, 0, 1, 0, 0, 0, tMosaicMEBaRT, MAX_MOSAIC_RTCM_V3_MSG, & settings.mosaicMessageEnabledRTCMv3Base, "messageEnabledRTCMBase_", }, { 1, 1, 0, 0, 0, 1, 0, 0, 0, _bool, 0, & settings.enableLoggingRINEX, "enableLoggingRINEX", }, { 1, 1, 0, 0, 0, 1, 0, 0, 0, _uint8_t, 0, & settings.RINEXFileDuration, "RINEXFileDuration", }, { 1, 1, 0, 0, 0, 1, 0, 0, 0, _uint8_t, 0, & settings.RINEXObsInterval, "RINEXObsInterval", }, From dd18d2dcb7e47d760f292c00cc6e4f0aeb2630e9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 20 Feb 2025 16:07:12 +0000 Subject: [PATCH 276/276] Update form.h via Python --- Firmware/RTK_Everywhere/form.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Firmware/RTK_Everywhere/form.h b/Firmware/RTK_Everywhere/form.h index 09243530c..f25b49950 100644 --- a/Firmware/RTK_Everywhere/form.h +++ b/Firmware/RTK_Everywhere/form.h @@ -26,7 +26,7 @@ // python main_js_zipper.py static const uint8_t main_js[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xF9, 0x09, 0xB6, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, + 0x1F, 0x8B, 0x08, 0x08, 0x30, 0x53, 0xB7, 0x67, 0x02, 0xFF, 0x6D, 0x61, 0x69, 0x6E, 0x2E, 0x6A, 0x73, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0xFD, 0x5E, 0xDC, 0x3A, 0x92, 0xE8, 0xFF, 0x79, 0x0A, 0x4D, 0xDF, 0xB9, 0x03, 0x0C, 0x4D, 0xE3, 0x6E, 0x3E, 0x02, 0x21, 0x64, 0x2F, 0x01, 0x92, 0x70, 0x07, 0x08, 0x97, 0x26, 0xE7, 0x9C, 0x9C, 0x6C, 0x96, 0x35, 0x6D, 0xD1, 0x78, 0xD3, @@ -1049,7 +1049,7 @@ static const uint8_t main_js[] PROGMEM = { // python index_html_zipper.py static const uint8_t index_html[] PROGMEM = { - 0x1F, 0x8B, 0x08, 0x08, 0xF9, 0x09, 0xB6, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, + 0x1F, 0x8B, 0x08, 0x08, 0x30, 0x53, 0xB7, 0x67, 0x02, 0xFF, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E, 0x68, 0x74, 0x6D, 0x6C, 0x2E, 0x67, 0x7A, 0x69, 0x70, 0x00, 0xED, 0x7D, 0x59, 0x76, 0xDB, 0xCA, 0x92, 0xE0, 0xFF, 0x5D, 0x45, 0x16, 0xAB, 0xBB, 0x2C, 0x57, 0x8B, 0x14, 0x48, 0x4A, 0xB2, 0xAC, 0x67, 0xEB, 0x1C, 0x8D, 0xB6, 0xFA, 0x49, 0x32, 0x4B, 0x94, 0xDF, 0x1D, 0xFA, 0x74, 0xDF, 0x03,