tidier. minified more. hard reset.

This commit is contained in:
Thaddeus Hughes
2025-12-30 20:02:44 -06:00
parent d46cb252fb
commit 40a2b3765c
19 changed files with 913 additions and 194 deletions

View File

@@ -1,11 +1,4 @@
ESP-IDF template app
====================
SC-F001
=======
This is a template application to be used with [Espressif IoT Development Framework](https://github.com/espressif/esp-idf).
Please check [ESP-IDF docs](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for getting started instructions.
*Code in this repository is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.*
Firmware for SC-B001

View File

@@ -388,9 +388,9 @@ void control_task(void *param) {
}
int64_t elapsed_t = (current_time-timer_start);
int64_t total_t = (timer_end-timer_start);
int32_t ticks = get_sensor_counter(SENSOR_DRIVE);
//int64_t elapsed_t = (current_time-timer_start);
//int64_t total_t = (timer_end-timer_start);
//int32_t ticks = get_sensor_counter(SENSOR_DRIVE);
//ESP_LOGI("FSM", "[%d] %lld / %lld ms, %ld ticks", current_state, (long long) elapsed_t, (long long) total_t, (long) ticks);
// Output control

View File

@@ -24,11 +24,9 @@
#define TCA_REG_CONFIG1 0x07
// Debounce & Repeat Settings
#define DEBOUNCE_US 50000
#define REPEAT_US 200000
#define REPEAT_START_US 700000
#define MAX_REPEATS 100
#define DEBOUNCE_MS 50
#define REPEAT_MS 200
#define REPEAT_START_MS 700
// Static Variables
static bool i2c_initted = false;
@@ -87,8 +85,8 @@ esp_err_t i2c_stop() {
#define N_BTNS 2
static bool debounced_state[N_BTNS] = {false};
static bool last_known_state[N_BTNS] = {false};
static int64_t last_stable_time[N_BTNS] = {0};
static int64_t last_change_time[N_BTNS] = {0};
static uint64_t last_stable_time[N_BTNS] = {0};
static uint64_t last_change_time[N_BTNS] = {0};
static uint8_t claimed_repeats[N_BTNS] = {0};
esp_err_t i2c_poll_buttons() {
for (uint8_t btn = 0; btn < N_BTNS; ++btn) {
@@ -100,13 +98,13 @@ esp_err_t i2c_poll_buttons() {
uint8_t raw_buttons = (uint8_t)(port_val & 0x0F);
uint8_t raw_states = ~raw_buttons & 0x0F;
int64_t now = esp_timer_get_time() / 1000;
uint64_t now = esp_timer_get_time() / 1000;
for (uint8_t btn = 0; btn < N_BTNS; ++btn) {
bool raw_pressed = (raw_states & (1 << btn)) != 0;
if (raw_pressed != debounced_state[btn]) {
if (now - last_stable_time[btn] >= DEBOUNCE_US) {
if (now - last_stable_time[btn] >= DEBOUNCE_MS) {
debounced_state[btn] = raw_pressed;
last_stable_time[btn] = now;
last_change_time[btn] = now;
@@ -133,9 +131,9 @@ bool i2c_get_button_state(uint8_t button) {
bool i2c_get_button_repeat(uint8_t btn) {
if (btn >= N_BTNS || !debounced_state[btn]) return false;
int64_t now = esp_timer_get_time();
if (now + DEBOUNCE_US < last_change_time[btn]) return false;
if ((now - last_change_time[btn]) > (REPEAT_START_US + REPEAT_US * claimed_repeats[btn])) {
uint64_t now = esp_timer_get_time() / 1000;
if (now + DEBOUNCE_MS < last_change_time[btn]) return false;
if ((now - last_change_time[btn]) > (REPEAT_START_MS + REPEAT_MS * claimed_repeats[btn])) {
claimed_repeats[btn]++;
return true;
}
@@ -147,15 +145,18 @@ int8_t i2c_get_button_repeats(uint8_t btn) {
return 0;
if (btn >= N_BTNS || !debounced_state[btn]) return false;
int64_t now = esp_timer_get_time();
if (now + DEBOUNCE_US < last_change_time[btn]) return false;
if ((now - last_change_time[btn]) > (REPEAT_START_US + REPEAT_US * claimed_repeats[btn])) {
uint64_t now = esp_timer_get_time() / 1000;
if (now + DEBOUNCE_MS < last_change_time[btn]) return false;
if ((now - last_change_time[btn]) > (REPEAT_START_MS + REPEAT_MS * claimed_repeats[btn])) {
claimed_repeats[btn]++;
if (claimed_repeats[btn] > MAX_REPEATS)
claimed_repeats[btn] = MAX_REPEATS;
if (claimed_repeats[btn] > 100)
claimed_repeats[btn] = 100;
ESP_LOGI("BTN", "RPT %d", (uint8_t)claimed_repeats[btn]+2);
return claimed_repeats[btn]+1;
}
if (debounced_state[btn] && !last_known_state[btn]) {
ESP_LOGI("BTN", "FST %d", 1);
return 1;
}
@@ -166,6 +167,9 @@ int64_t i2c_get_button_ms(uint8_t btn) {
if (!i2c_get_button_state(btn))
return 0;
int64_t now = esp_timer_get_time();
uint64_t now = esp_timer_get_time() / 1000;
return now - last_change_time[btn];
}
int64_t i2c_get_button_us(uint8_t btn) {
return i2c_get_button_ms(btn)*1000;
}

View File

@@ -19,6 +19,7 @@ bool i2c_get_button_released(uint8_t button);
bool i2c_get_button_state(uint8_t button);
bool i2c_get_button_repeat(uint8_t btn);
int8_t i2c_get_button_repeats(uint8_t btn);
int64_t i2c_get_button_us(uint8_t btn);
int64_t i2c_get_button_ms(uint8_t btn);
#endif // I2C_H_

View File

@@ -104,23 +104,21 @@ black: #2f2f2f
<td>Battery (V)</td>
<td><input readonly="" id="voltage"/></td>
</tr>
</table>
<button id="commit_btn" onclick="commitParams()" disabled>Save Changes</button>
<br/>
<br/>
<details>
<summary>DANGER ZONE</summary>
<table>
<tr>
<td>Program RF Remote</td>
<td>
<button onclick="programRFSequence()">Program All Buttons</button>
</td>
</tr>
</table>
<button id="commit_btn" onclick="commitParams()" disabled>Save Changes</button>
<br/>
<br/>
<details>
<summary>DANGER ZONE</summary>
<table>
<tr>
<td>Calibration</td>
<td><button onclick="calibrate('jack')">Jack Calibration</button>
@@ -138,10 +136,7 @@ black: #2f2f2f
</table>
<table id="table"></table>
<td><button class="cmd" onclick="sendCommand('reboot')" style="background-color:#723; color: #fff">REBOOT</button></td>
<button class="cmd" onclick="sendCommand('reboot')" style="background-color:#723; color: #fff">REBOOT</button>
</details>
</div>
</div>
@@ -464,7 +459,13 @@ black: #2f2f2f
return;
}
// Disable RF controls during programming
// Clear temp storage and disable RF controls during programming
await fetch('./cmd', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({cmd: 'rf_clear_temp'})
});
await fetch('./cmd', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
@@ -478,51 +479,35 @@ black: #2f2f2f
// Give a moment for the learn flag to be set
await new Promise(resolve => setTimeout(resolve, 100));
// Ask user to press button or skip
const shouldSkip = !confirm(`Button ${i+1}/4: ${buttonNames[i]}\n\nPress the ${buttonNames[i]} button on your remote now, then press OK.\n\nPress Cancel to skip this button.`);
// Show dialog and wait for user to press OK
alert(`Button ${i+1}/4: ${buttonNames[i]}\n\nPress the ${buttonNames[i]} button on your remote now.\n\nPress OK when done (or just press OK to leave unprogrammed).`);
if (shouldSkip) {
// Cancel learning and set this button to -1 (disabled)
programRF(-1);
learnedCodes[i] = -1;
continue;
}
// Cancel learning mode
programRF(-1);
// Wait for code to be learned (poll for a bit)
let learned = false;
const startCode = learnedCodes[i]; // Should be null at this point
for (let attempt = 0; attempt < 50; attempt++) {
await new Promise(resolve => setTimeout(resolve, 100));
// Check what was learned (if anything)
try {
const response = await fetch('./cmd', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({cmd: 'rf_status'})
});
const data = await response.json();
// Check if code was learned by polling RF status via /cmd
try {
const response = await fetch('./cmd', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({cmd: 'rf_status'})
});
const data = await response.json();
// Check if this specific index changed from what we started with
if (data.codes[i] !== -1 && data.codes[i] !== null && data.codes[i] !== startCode) {
learnedCodes[i] = data.codes[i];
learned = true;
break;
}
} catch (e) {
console.error("Error checking RF status:", e);
}
// Get whatever is in temp storage (could be -1 if nothing was pressed)
learnedCodes[i] = data.codes[i];
} catch (e) {
console.error("Error checking RF status:", e);
learnedCodes[i] = -1;
}
if (!learned) {
if (confirm(`Timeout waiting for ${buttonNames[i]} button.\n\nRetry this button?`)) {
i--; // Retry this iteration
continue;
} else {
// Skip this button
learnedCodes[i] = -1;
}
// If nothing was learned, make sure it's set to -1
if (learnedCodes[i] === -1) {
await fetch('./cmd', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({cmd: 'rf_set_temp', index: i, code: -1})
});
}
}

View File

@@ -86,7 +86,8 @@ void driveLEDs(led_state_t state) {
case LED_STATE_ERRORED:
i2c_set_led1(patterns[state][(esp_timer_get_time()/200000) % 2]);
break;
case LED_STATE_BOOTING:
i2c_set_led1(0b001);
break;
@@ -106,18 +107,71 @@ void driveLEDs(led_state_t state) {
}
}
RTC_DATA_ATTR bool first_boot = true;
void app_main(void) {
esp_task_wdt_add(NULL);
// Say hello; turn on the lights
esp_sleep_wakeup_cause_t cause = rtc_wakeup_cause();
if (rtc_xtal_init() != ESP_OK) ESP_LOGE(TAG, "RTC FAILED");
// Say hello; turn on the lights
esp_sleep_wakeup_cause_t cause = rtc_wakeup_cause();
if (i2c_init() != ESP_OK) ESP_LOGE(TAG, "I2C FAILED");
i2c_set_relays(0);
driveLEDs(LED_STATE_BOOTING);
// Every boot we load parameters and monitor solar, no matter what
// Check for factory reset condition: Cold boot + button held
// This is a cold boot (power-on or hard reset)
// Check if button is being held (pin is LOW)
if (first_boot && gpio_get_level(GPIO_NUM_13) == 0) {
ESP_LOGW(TAG, "FACTORY RESET TRIGGERED - Button held on cold boot");
// Flash LED pattern to indicate factory reset
for (int i = 0; i < 10; i++) {
i2c_set_led1(0b111);
vTaskDelay(pdMS_TO_TICKS(100));
i2c_set_led1(0b000);
vTaskDelay(pdMS_TO_TICKS(100));
}
// Initialize minimal components needed for factory reset
if (storage_init() != ESP_OK) ESP_LOGE(TAG, "STORAGE FAILED");
// Perform factory reset
esp_err_t reset_err = factory_reset();
if (reset_err == ESP_OK) {
ESP_LOGI(TAG, "Factory reset completed successfully");
// Flash success pattern
for (int i = 0; i < 5; i++) {
i2c_set_led1(0b010);
vTaskDelay(pdMS_TO_TICKS(200));
i2c_set_led1(0b000);
vTaskDelay(pdMS_TO_TICKS(200));
}
} else {
ESP_LOGE(TAG, "Factory reset failed!");
// Flash error pattern
for (int i = 0; i < 5; i++) {
i2c_set_led1(0b100);
vTaskDelay(pdMS_TO_TICKS(200));
i2c_set_led1(0b000);
vTaskDelay(pdMS_TO_TICKS(200));
}
}
// Reboot the system
ESP_LOGI(TAG, "Rebooting system...");
vTaskDelay(pdMS_TO_TICKS(1000));
esp_restart();
}
first_boot = false;
// Every boot we load parameters and monitor solar, no matter what
if (adc_init() != ESP_OK) ESP_LOGE(TAG, "ADC FAILED");
if (rtc_xtal_init() != ESP_OK) ESP_LOGE(TAG, "RTC FAILED");
if (storage_init() != ESP_OK) ESP_LOGE(TAG, "STORAGE FAILED");
if (log_init() != ESP_OK) ESP_LOGE(TAG, "LOG FAILED");
if (run_solar_fsm() != ESP_OK) ESP_LOGE(TAG, "SOLAR FAILED");
@@ -174,7 +228,7 @@ void app_main(void) {
switch (fsm_get_state()) {
case STATE_IDLE:
// LED cue for user
if (i2c_get_button_ms(0) > 1600){
if (i2c_get_button_ms(0) > 1600){
driveLEDs(LED_STATE_START4);
} else if (i2c_get_button_ms(0) > 1100){
driveLEDs(LED_STATE_START3);
@@ -183,8 +237,6 @@ void app_main(void) {
} else if (i2c_get_button_ms(0) > 100){
driveLEDs(LED_STATE_START1);
} else{
if (
rtc_is_set() &&
!efuse_is_tripped(BRIDGE_JACK) &&
@@ -239,7 +291,6 @@ void app_main(void) {
send_log();
driveLEDs(LED_STATE_DRIVING);
if (i2c_get_button_tripped(0)) {
ESP_LOGI(TAG, "CTRL + Z PLZ!");
fsm_request(FSM_CMD_UNDO);
}
break;
@@ -252,20 +303,10 @@ void app_main(void) {
fsm_request(FSM_CMD_START);
set_next_alarm();
}
/*ESP_LOGI(TAG, "VOLTAGE: %2.3f | CURRENTS: %+2.8f %+2.8f %+2.8f",
get_battery_V(),
get_bridge_A(BRIDGE_DRIVE),
get_bridge_A(BRIDGE_JACK),
get_bridge_A(BRIDGE_AUX));*/
run_solar_fsm();
//check_shutdown_timer();
check_shutdown_timer();
esp_task_wdt_reset();
}
}

View File

@@ -82,7 +82,7 @@ esp_err_t adc_init() {
// Configure all channels
adc_oneshot_chan_cfg_t chan_cfg = {
.atten = ADC_ATTEN_DB_11,
.atten = ADC_ATTEN_DB_12,
.bitwidth = ADC_BITWIDTH_12,
};
@@ -94,7 +94,7 @@ esp_err_t adc_init() {
// Line fitting calibration (modern scheme)
adc_cali_line_fitting_config_t cali_cfg = {
.unit_id = ADC_UNIT_1,
.atten = ADC_ATTEN_DB_11,
.atten = ADC_ATTEN_DB_12,
.bitwidth = ADC_BITWIDTH_12,
};
ESP_ERROR_CHECK(adc_cali_create_scheme_line_fitting(&cali_cfg, &adc_cali_handle));

View File

@@ -40,6 +40,9 @@ typedef struct {
int learn_flag = -1;
bool controls_enabled = true;
// Temporary storage for learned keycodes (not committed to params yet)
static int64_t temp_keycodes[NUM_RF_BUTTONS] = {-1, -1, -1, -1, -1, -1, -1, -1};
// For rmt_rx_register_event_callbacks
static bool rfrx_done(rmt_channel_handle_t channel, const rmt_rx_done_event_data_t *edata, void *udata) {
BaseType_t high_task_wakeup = pdFALSE;
@@ -133,10 +136,9 @@ static void rf_433_receiver_task(void* param) {
ESP_LOGI(TAG, "GOT KEYCODE 0x%lx [%d]", (long) code, len);
if (learn_flag >= 0) {
// Store just the 32-bit code
set_param_value_t(PARAM_KEYCODE_0 + learn_flag,
(param_value_t){.i32 = (int32_t)code});
ESP_LOGI(TAG, "LEARNED KEYCODE");
// Store to temporary storage, not to params yet
temp_keycodes[learn_flag] = (int64_t)code;
ESP_LOGI(TAG, "LEARNED KEYCODE (temp storage)");
learn_flag = -1;
} else if (controls_enabled) {
// Only process RF commands if controls are enabled
@@ -149,9 +151,9 @@ static void rf_433_receiver_task(void* param) {
};
for (uint8_t i = 0; i < NUM_RF_BUTTONS; i++) {
int32_t match = get_param_value_t(PARAM_KEYCODE_0+i).i32;
int64_t match = get_param_value_t(PARAM_KEYCODE_0+i).i64;
// Compare just the code (lower 32 bits)
if ((uint32_t)match == code) {
if ((uint32_t)match == code && code!=-1) {
switch (i) {
case 0: pulseOverride(RELAY_A1); pulseOverride(RELAY_A3); break;
case 1: pulseOverride(RELAY_B1); pulseOverride(RELAY_A3); break;
@@ -233,4 +235,20 @@ void rf_433_disable_controls() {
void rf_433_enable_controls() {
controls_enabled = true;
}
int64_t rf_433_get_temp_keycode(uint8_t index) {
if (index >= NUM_RF_BUTTONS) return -1;
return temp_keycodes[index];
}
void rf_433_set_temp_keycode(uint8_t index, int64_t code) {
if (index >= NUM_RF_BUTTONS) return;
temp_keycodes[index] = code;
}
void rf_433_clear_temp_keycodes() {
for (uint8_t i = 0; i < NUM_RF_BUTTONS; i++) {
temp_keycodes[i] = -1;
}
}

View File

@@ -29,4 +29,8 @@ void rf_433_cancel_learn_keycode();
void rf_433_disable_controls();
void rf_433_enable_controls();
int64_t rf_433_get_temp_keycode(uint8_t index);
void rf_433_set_temp_keycode(uint8_t index, int64_t code);
void rf_433_clear_temp_keycodes();
#endif

View File

@@ -16,6 +16,7 @@
#include "esp_sleep.h"
#include "esp_timer.h"
#include "esp_err.h"
#include <time.h>
#define POWER_INACTIVITY_TIMEOUT_MS 180000

View File

@@ -58,7 +58,7 @@ static void sensor_debounce_task(void* param) {
uint8_t i = 0;
int64_t now = -1;
//int64_t now = -1;
while (1) {
if (xQueueReceive(sensor_event_queue, &evt, pdMS_TO_TICKS(100)) == pdTRUE) {
@@ -84,7 +84,7 @@ static void sensor_debounce_task(void* param) {
}
now = esp_timer_get_time();
//now = esp_timer_get_time();
/*// Wait for debounce period since last ISR
if (now - sensor_last_isr_time[i] >= (DEBOUNCE_TIME_US)) {

View File

@@ -354,6 +354,42 @@ esp_err_t commit_params(void) {
return ESP_OK;
}
// ============================================================================
// FACTORY RESET
// ============================================================================
esp_err_t factory_reset(void) {
if (storage_partition == NULL) {
ESP_LOGE(TAG, "Storage partition not initialized");
return ESP_ERR_INVALID_STATE;
}
ESP_LOGW(TAG, "FACTORY RESET: Erasing entire storage partition...");
// Erase the entire storage partition
esp_err_t err = esp_partition_erase_range(storage_partition, 0, storage_partition->size);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to erase storage partition: %s", esp_err_to_name(err));
return err;
}
ESP_LOGI(TAG, "Storage partition erased successfully");
// Reset all parameters to defaults in RAM
for (int i = 0; i < NUM_PARAMS; i++) {
memcpy(&parameter_table[i], &parameter_defaults[i], sizeof(param_value_t));
}
// Reset log indices
if (log_mutex) xSemaphoreTake(log_mutex, portMAX_DELAY);
log_head_index = 0;
log_tail_index = 0;
if (log_mutex) xSemaphoreGive(log_mutex);
ESP_LOGI(TAG, "Factory reset complete - all data erased");
return ESP_OK;
}
// ============================================================================
// INITIALIZATION FUNCTIONS
// ============================================================================

View File

@@ -163,6 +163,7 @@ char* get_param_string(param_idx_t id);
// Storage operations
esp_err_t commit_params(void);
esp_err_t factory_reset(void);
// Log functions
#define LOG_ENTRY_SIZE 32

File diff suppressed because one or more lines are too long

217
main/webpage_brotli.h Normal file
View File

@@ -0,0 +1,217 @@
#ifndef HTML_CONTENT_BR_H
#define HTML_CONTENT_BR_H
#include <Arduino.h>
const unsigned char PROGMEM html_content_br[] = {
0x1b, 0xdd, 0x2d, 0x00, 0x8c, 0xc3, 0x38, 0x86, 0x3c, 0x28, 0x7e, 0x6c, 0x06, 0x44, 0x69, 0x91,
0x2e, 0x7f, 0x9a, 0xff, 0x7f, 0x3f, 0x5f, 0x38, 0xe7, 0xf0, 0xb4, 0xf6, 0x22, 0xf7, 0x2b, 0xe8,
0x16, 0xa7, 0x55, 0xe7, 0xa5, 0x54, 0x87, 0x61, 0xb1, 0xc1, 0x8e, 0xe6, 0x40, 0x78, 0x40, 0xd7,
0x46, 0x96, 0x66, 0x3a, 0xa7, 0x35, 0xe3, 0x77, 0xac, 0x76, 0x60, 0xf0, 0x49, 0x75, 0x52, 0xf6,
0x97, 0xe8, 0xff, 0xa6, 0x96, 0x77, 0x97, 0x56, 0x61, 0x0c, 0xc3, 0x60, 0xc7, 0x01, 0x30, 0x04,
0xae, 0x7e, 0x99, 0x6f, 0x35, 0xfb, 0x9d, 0x2c, 0xef, 0xbe, 0x27, 0xdb, 0x69, 0x8e, 0x53, 0x4a,
0xfd, 0x33, 0x23, 0xb9, 0x68, 0x53, 0xae, 0xd4, 0xe2, 0x94, 0x56, 0x29, 0x0e, 0x85, 0x09, 0x5c,
0x96, 0x83, 0xc7, 0x02, 0x68, 0x16, 0xd9, 0xb2, 0x97, 0x9b, 0x29, 0x50, 0x8f, 0x36, 0x0d, 0xba,
0xb9, 0x26, 0x78, 0x31, 0x57, 0x16, 0x77, 0xa4, 0xac, 0x92, 0xd8, 0x86, 0x36, 0xcf, 0x83, 0x10,
0xc8, 0x4a, 0x2f, 0xc5, 0x4a, 0x10, 0xd0, 0x22, 0xe2, 0x9b, 0x48, 0x0f, 0x06, 0x7f, 0xd2, 0x84,
0x90, 0xd2, 0xd3, 0xf6, 0x58, 0xc6, 0x95, 0xa2, 0xd8, 0xe8, 0x1e, 0x67, 0x0f, 0xa0, 0xcd, 0x3e,
0xde, 0x5b, 0xfd, 0xe0, 0xde, 0x9f, 0xe6, 0x3c, 0x72, 0xb5, 0xdd, 0x13, 0xd4, 0x3a, 0x8b, 0x71,
0x8b, 0xc6, 0x31, 0x2c, 0x45, 0x42, 0x03, 0x3a, 0x45, 0xbe, 0xc6, 0xbe, 0x4c, 0xdc, 0x4d, 0x30,
0x1a, 0xfb, 0x81, 0x23, 0xdb, 0x6c, 0xba, 0xfb, 0xbc, 0x8c, 0xea, 0x1d, 0x21, 0x65, 0x5b, 0xed,
0xf5, 0xd7, 0x57, 0xb2, 0x4d, 0xf0, 0x35, 0x37, 0x1d, 0xfe, 0x60, 0x5b, 0xe4, 0x26, 0xc7, 0x65,
0x6b, 0x0b, 0x8e, 0x0f, 0x4f, 0xdb, 0xb2, 0xf6, 0xa0, 0x48, 0x10, 0xa4, 0x56, 0xa9, 0x88, 0x20,
0xfc, 0xb5, 0xf6, 0x95, 0xe3, 0xd9, 0xe5, 0xae, 0x2c, 0xca, 0x4b, 0x45, 0xc7, 0x1a, 0x7c, 0xcf,
0xde, 0xd8, 0xe5, 0xd9, 0x62, 0xa3, 0x12, 0x78, 0x6a, 0x6b, 0x85, 0xbe, 0xe9, 0x62, 0xea, 0xd0,
0x2b, 0x04, 0xd1, 0x73, 0xbc, 0x66, 0x6b, 0x70, 0xbf, 0x6e, 0x8a, 0x33, 0x09, 0x2d, 0xd6, 0x4b,
0x5d, 0x25, 0x87, 0xb5, 0x4c, 0x83, 0x4d, 0xf5, 0xbe, 0xe8, 0xdc, 0x98, 0x5d, 0x2f, 0x11, 0x78,
0x09, 0x4f, 0x37, 0xc0, 0x7f, 0x7d, 0xb6, 0xb9, 0x19, 0xd3, 0x66, 0x9a, 0x50, 0x3c, 0xf5, 0x99,
0x33, 0xcd, 0xe7, 0x97, 0xb3, 0x22, 0xd8, 0x8c, 0x4f, 0xc7, 0x85, 0x97, 0x16, 0x07, 0xd1, 0x2c,
0xce, 0xe2, 0x99, 0x53, 0x63, 0x5a, 0xa1, 0x19, 0x16, 0xeb, 0xdb, 0xee, 0x7c, 0x3c, 0xce, 0xa2,
0xb5, 0xde, 0x3b, 0x86, 0x29, 0x70, 0xf3, 0xe2, 0x53, 0xaa, 0xf2, 0x1d, 0x19, 0xd9, 0x88, 0xd5,
0xf9, 0x4a, 0xde, 0x9c, 0xff, 0xd3, 0xef, 0x48, 0x50, 0xb5, 0x8e, 0xaa, 0xcc, 0x44, 0xad, 0xa2,
0x3f, 0x0d, 0x90, 0x1d, 0xd8, 0xb5, 0xa3, 0x44, 0x0d, 0x50, 0x82, 0xb4, 0xd4, 0xa8, 0x79, 0x71,
0x4b, 0x3d, 0x99, 0xd7, 0xba, 0x54, 0x55, 0x7b, 0xfb, 0xca, 0xbb, 0x93, 0xf3, 0xe9, 0x0c, 0x2b,
0x24, 0xe9, 0x13, 0xcb, 0x59, 0x5b, 0xd6, 0x2d, 0x75, 0xac, 0xdc, 0x1e, 0x0b, 0xd7, 0xe4, 0x36,
0x36, 0x5f, 0xbe, 0x38, 0xd8, 0x69, 0x7d, 0xdd, 0xa3, 0xc3, 0xba, 0xff, 0xe2, 0xac, 0x32, 0x99,
0x06, 0x8f, 0x9f, 0xb0, 0x18, 0x7d, 0x3d, 0xa8, 0xb1, 0x19, 0x8a, 0x2b, 0x9a, 0x89, 0xd0, 0x8d,
0x80, 0xa3, 0x6b, 0x02, 0xae, 0x22, 0xe5, 0x70, 0x71, 0x43, 0xb5, 0xa5, 0xb0, 0x97, 0xa0, 0xe1,
0xfc, 0xd4, 0xa2, 0xa3, 0xdb, 0xd2, 0xe6, 0x92, 0x1a, 0xc7, 0xef, 0x10, 0x49, 0x1c, 0xa1, 0xdb,
0x5e, 0x64, 0x68, 0xf6, 0xa9, 0x56, 0x13, 0x64, 0x86, 0x25, 0xf3, 0xb8, 0xec, 0x51, 0x22, 0xa2,
0x79, 0xd3, 0x83, 0xac, 0x99, 0xa2, 0x40, 0x8e, 0xaf, 0xf2, 0x36, 0xd2, 0xa1, 0x95, 0x08, 0x6e,
0xe1, 0xe7, 0x20, 0x4a, 0x38, 0x4e, 0x47, 0xfc, 0x77, 0x78, 0x56, 0x6d, 0x58, 0x3b, 0x6b, 0xb8,
0x3d, 0x16, 0x89, 0x66, 0x20, 0xa2, 0xd6, 0x48, 0xe2, 0x6a, 0x69, 0xad, 0xdf, 0x1c, 0x6e, 0x4e,
0x37, 0xaf, 0x4a, 0x78, 0x12, 0x25, 0x87, 0xb7, 0x3d, 0xd6, 0x0c, 0x0f, 0x70, 0x63, 0x8a, 0xa6,
0xdc, 0xfb, 0x7e, 0x5f, 0xe5, 0x5b, 0x37, 0xb7, 0xf4, 0xb1, 0x9b, 0x45, 0xad, 0x27, 0xb7, 0xee,
0x2c, 0x59, 0xdd, 0xad, 0xa8, 0xaf, 0xfb, 0xa1, 0x6d, 0x10, 0x4e, 0x2a, 0x95, 0xf2, 0xd1, 0x0a,
0x6d, 0x32, 0x11, 0xa6, 0xd7, 0xba, 0x03, 0xe1, 0xc7, 0x5b, 0xd5, 0xe3, 0x3d, 0x4e, 0x81, 0x37,
0x40, 0x87, 0x26, 0xde, 0x1c, 0x20, 0x1e, 0xe1, 0x31, 0x8e, 0xe4, 0x63, 0x37, 0x09, 0xea, 0x09,
0xa9, 0x15, 0x46, 0x77, 0xec, 0x41, 0xaa, 0xac, 0x0f, 0x9d, 0xf7, 0xdb, 0xbf, 0x69, 0xa5, 0x3b,
0x01, 0xc9, 0xd7, 0xb7, 0xd9, 0x06, 0x33, 0xbd, 0xd5, 0x64, 0x50, 0x9b, 0xf1, 0x05, 0xd4, 0x3d,
0xa4, 0x31, 0x55, 0x89, 0x41, 0xc2, 0xc7, 0x19, 0xc8, 0xd5, 0x07, 0x7d, 0x6b, 0xa2, 0x53, 0xb9,
0xa9, 0xc0, 0x50, 0xd8, 0xd2, 0x39, 0xed, 0xd2, 0xcb, 0x53, 0x71, 0xbf, 0xb7, 0x4a, 0x53, 0xdc,
0xc7, 0xa7, 0x87, 0x74, 0x70, 0xb0, 0xd1, 0x0b, 0x7b, 0xb8, 0x0d, 0xcd, 0xbd, 0xce, 0xfa, 0x7c,
0xa7, 0x5d, 0x6f, 0x0d, 0x8d, 0xf3, 0x22, 0x09, 0xe3, 0x7b, 0xa3, 0xdf, 0xea, 0x64, 0x33, 0x90,
0x71, 0x30, 0xb1, 0xbb, 0x41, 0xbe, 0xa2, 0x88, 0xad, 0xcd, 0x8a, 0xd0, 0x7e, 0x88, 0x57, 0xcf,
0x13, 0xea, 0x56, 0xed, 0x1d, 0xd5, 0x31, 0xca, 0x6c, 0xc2, 0xb5, 0x84, 0xd1, 0x2b, 0x32, 0x81,
0xed, 0x54, 0x68, 0x93, 0x27, 0x28, 0xb8, 0x7f, 0x8b, 0x1b, 0xaf, 0x86, 0xb0, 0x51, 0xf1, 0x23,
0x37, 0xb6, 0xb1, 0x94, 0x25, 0xb4, 0x34, 0xb1, 0x79, 0xe6, 0x5f, 0x5e, 0x9d, 0xa7, 0x7b, 0x39,
0x9e, 0xc0, 0xea, 0xe7, 0x42, 0x60, 0x73, 0x45, 0x0f, 0xdb, 0x90, 0xc2, 0xe0, 0xe9, 0xa1, 0x3a,
0x9b, 0xf6, 0xd2, 0x6c, 0x81, 0x53, 0x35, 0x12, 0x19, 0x8a, 0x29, 0x82, 0x5a, 0x32, 0xe3, 0xd9,
0xf4, 0x2b, 0xc5, 0x97, 0x41, 0x32, 0xb0, 0x46, 0x80, 0xd7, 0x19, 0xb0, 0x8d, 0x21, 0xbd, 0x52,
0x6a, 0x17, 0x26, 0x58, 0x6a, 0x3e, 0x35, 0x79, 0x91, 0x69, 0x96, 0x0a, 0xdd, 0xab, 0xee, 0xbb,
0x10, 0xc3, 0x2c, 0xa8, 0x0b, 0x98, 0x74, 0xe7, 0xb9, 0xad, 0x4c, 0x8e, 0x3d, 0x90, 0x92, 0x3c,
0x30, 0xdd, 0x06, 0x6c, 0x96, 0xaf, 0x00, 0xb6, 0xe0, 0x2f, 0x41, 0x58, 0x27, 0x20, 0xd6, 0x91,
0xd2, 0x77, 0x88, 0x64, 0xf0, 0x82, 0x03, 0x7f, 0xbe, 0x3b, 0x1f, 0x70, 0x60, 0xd5, 0x85, 0x03,
0xde, 0xe5, 0x6d, 0x09, 0x5a, 0xea, 0x1e, 0x0d, 0x49, 0x6e, 0xb6, 0xac, 0x2c, 0xdd, 0x05, 0x8d,
0xb2, 0xce, 0x08, 0x21, 0x0c, 0x4c, 0xd9, 0xec, 0x8e, 0xba, 0x10, 0xf6, 0x13, 0xcd, 0xe6, 0x7c,
0x00, 0x9a, 0xe4, 0x66, 0x6c, 0xe6, 0x96, 0x2d, 0x1c, 0x74, 0xa0, 0x6f, 0xf3, 0x4a, 0x57, 0x3a,
0xb7, 0xed, 0x2b, 0xed, 0x1f, 0x4d, 0x5f, 0x25, 0x88, 0x17, 0xdc, 0x20, 0x2f, 0x63, 0x58, 0x09,
0x66, 0x97, 0x45, 0x17, 0x06, 0x1a, 0xa4, 0x8b, 0x13, 0x7a, 0x61, 0x79, 0x51, 0x95, 0xb5, 0xec,
0xa1, 0x8f, 0x5f, 0x32, 0x66, 0x5f, 0x0a, 0x07, 0xf7, 0xaf, 0x1f, 0x0c, 0x7a, 0x59, 0x1d, 0x32,
0xd3, 0x5d, 0xed, 0x55, 0xb4, 0xce, 0x7c, 0xb4, 0x99, 0xd6, 0x21, 0xad, 0x53, 0x9c, 0x05, 0xfd,
0x58, 0x75, 0x83, 0x75, 0x4f, 0xd6, 0xb4, 0xd4, 0xbe, 0xa0, 0x3e, 0xa7, 0x60, 0x4f, 0xd2, 0x05,
0x25, 0xbd, 0xb0, 0xa1, 0x2e, 0x40, 0x19, 0xad, 0xa4, 0x07, 0x67, 0xd5, 0xaf, 0xd8, 0x1e, 0x8b,
0x1c, 0xba, 0xe0, 0x26, 0x86, 0x44, 0xc4, 0xf2, 0x65, 0xc4, 0x61, 0xd8, 0xeb, 0xba, 0x66, 0x82,
0xc7, 0x92, 0xd1, 0x56, 0x44, 0x26, 0xe5, 0x24, 0x1a, 0xda, 0xe6, 0x70, 0xc7, 0x4a, 0x86, 0xe3,
0x31, 0x1d, 0x6a, 0x36, 0xfb, 0x85, 0x7c, 0xd3, 0xc1, 0x2e, 0x45, 0x41, 0x82, 0x17, 0xfa, 0x39,
0xc3, 0xe0, 0x8a, 0x87, 0xe6, 0x78, 0x54, 0x2e, 0x7d, 0x8a, 0x66, 0x14, 0xe8, 0x62, 0x47, 0xcb,
0x4c, 0xa2, 0xdc, 0xdc, 0xf6, 0x7b, 0x3b, 0xda, 0xed, 0x3f, 0xc1, 0x72, 0xb4, 0x3d, 0x16, 0x8c,
0xdf, 0xde, 0x6c, 0x16, 0xb3, 0x61, 0x22, 0x07, 0x9a, 0x0f, 0x46, 0x5d, 0xec, 0x1e, 0x75, 0x79,
0xe3, 0xe8, 0xbc, 0xeb, 0x66, 0xd0, 0x6f, 0x05, 0x2b, 0x48, 0xc1, 0x1e, 0x4f, 0x65, 0x0d, 0x76,
0x11, 0x40, 0xdd, 0xfa, 0x7b, 0xf4, 0xee, 0x41, 0x34, 0x46, 0x1a, 0x57, 0x66, 0xad, 0x87, 0xcf,
0xae, 0x06, 0x54, 0x54, 0xf8, 0x3f, 0x91, 0xdf, 0xeb, 0x0e, 0x5c, 0xb1, 0x9e, 0xca, 0x5b, 0xab,
0xb2, 0xbe, 0xcb, 0x38, 0xf7, 0x19, 0x94, 0xa0, 0x88, 0x91, 0xc2, 0x9b, 0x22, 0xaf, 0x2d, 0x33,
0x7d, 0xb8, 0x3e, 0x58, 0xc1, 0x83, 0xfb, 0x82, 0xd2, 0x59, 0x50, 0x1f, 0xae, 0x8b, 0xbd, 0x08,
0x37, 0xf3, 0x09, 0x26, 0x49, 0x36, 0x1f, 0x17, 0x06, 0x83, 0x8d, 0x17, 0xb2, 0x9d, 0x8b, 0x3a,
0xfb, 0xeb, 0x54, 0x25, 0x58, 0xa2, 0x60, 0x23, 0x81, 0x60, 0x5c, 0x1a, 0x96, 0x5d, 0xcc, 0x36,
0xa0, 0xa7, 0xf7, 0x74, 0xb7, 0xb2, 0x95, 0x33, 0x04, 0xfd, 0xe9, 0xab, 0x43, 0x93, 0x5b, 0x91,
0xd7, 0x16, 0x00, 0x5c, 0x45, 0xeb, 0x6f, 0xb8, 0x72, 0xa8, 0xb1, 0x3a, 0x7b, 0x36, 0x11, 0x16,
0xd1, 0x94, 0xa2, 0x2f, 0x9b, 0xeb, 0x62, 0x81, 0xd1, 0x82, 0x8b, 0x24, 0xcb, 0x21, 0xe5, 0x42,
0x80, 0x6a, 0x62, 0x40, 0x61, 0x64, 0xb0, 0xdb, 0xf1, 0x52, 0xa8, 0x07, 0x3f, 0xb9, 0xa7, 0x60,
0x6d, 0xb2, 0x33, 0x06, 0x90, 0xbb, 0xf0, 0x83, 0xc4, 0xde, 0x9b, 0x2c, 0x47, 0x79, 0x6d, 0x31,
0xf0, 0x8d, 0x9d, 0x5f, 0x6e, 0xdf, 0xd3, 0x60, 0x22, 0xa7, 0x10, 0xc7, 0xb8, 0xc9, 0x8b, 0x3b,
0xbd, 0xf7, 0xc8, 0x67, 0xc5, 0x5b, 0x2c, 0x2b, 0x23, 0x75, 0xaf, 0xac, 0x24, 0x63, 0x82, 0xcb,
0xbb, 0xf9, 0x68, 0x5e, 0x14, 0x82, 0x7b, 0xd4, 0x05, 0x03, 0x26, 0xaf, 0xc4, 0xe1, 0x22, 0xc3,
0xe1, 0x1c, 0xcd, 0xa1, 0xde, 0x04, 0xcb, 0xea, 0xa5, 0x63, 0x75, 0x95, 0x28, 0xc9, 0xc6, 0x90,
0x98, 0xa6, 0xda, 0xc7, 0xdc, 0x6b, 0x82, 0x2b, 0x2d, 0x17, 0x43, 0x15, 0x81, 0x3d, 0x08, 0x96,
0xc1, 0xf2, 0x4c, 0xff, 0xc8, 0x96, 0x05, 0x33, 0x5b, 0x32, 0xc1, 0x0d, 0x9a, 0x18, 0x01, 0x11,
0x06, 0xd0, 0x2f, 0x8c, 0xe0, 0xa9, 0x83, 0xb3, 0x97, 0x07, 0x34, 0x21, 0xcb, 0x12, 0xe3, 0x99,
0x05, 0x49, 0xb6, 0x05, 0x97, 0x87, 0x27, 0xc6, 0xe4, 0x83, 0x85, 0xbe, 0xa7, 0xd2, 0x5e, 0x84,
0xce, 0x01, 0xdb, 0xf7, 0xce, 0x6d, 0x5d, 0xa2, 0xc3, 0x4b, 0x4b, 0x12, 0xa3, 0x41, 0xf0, 0x24,
0xcb, 0xce, 0x9a, 0xe2, 0xb1, 0x55, 0x16, 0x0c, 0x46, 0x97, 0x15, 0x5e, 0x62, 0xfc, 0xe0, 0x60,
0x52, 0xce, 0x00, 0xa4, 0xd5, 0xdb, 0xaf, 0xad, 0xd1, 0x85, 0x18, 0xae, 0xcd, 0xd0, 0xb3, 0xc6,
0x38, 0xb9, 0x04, 0x05, 0x49, 0x78, 0x9d, 0xe6, 0xb7, 0xac, 0xf4, 0x0b, 0x59, 0x6b, 0x92, 0xbf,
0xdc, 0x4a, 0x94, 0x05, 0x8f, 0xf9, 0xe4, 0x38, 0x85, 0x99, 0x43, 0x51, 0x2d, 0x11, 0xcd, 0x11,
0xce, 0xc4, 0xde, 0xbf, 0xbe, 0xee, 0x19, 0x8d, 0x82, 0x99, 0xd3, 0x28, 0x52, 0x68, 0x01, 0x86,
0xd9, 0xbe, 0x3b, 0x1e, 0xe5, 0x0b, 0x2d, 0x1e, 0x18, 0xab, 0x6f, 0x22, 0x6b, 0xf8, 0x2f, 0x1a,
0x28, 0xd7, 0x94, 0x46, 0xab, 0x7c, 0x8c, 0x05, 0xfc, 0xe4, 0xdb, 0x36, 0xeb, 0x68, 0x8f, 0x47,
0xd1, 0x2e, 0x4e, 0x4c, 0x45, 0xa3, 0x62, 0x70, 0x2f, 0x22, 0x22, 0x7a, 0x7e, 0x49, 0x55, 0x1f,
0xee, 0x68, 0x65, 0xd0, 0x5d, 0x02, 0x0b, 0x25, 0x0c, 0x5b, 0xd2, 0x85, 0x4d, 0x4b, 0x3a, 0x59,
0xf1, 0x2e, 0x96, 0x0c, 0x61, 0x28, 0x3a, 0x58, 0x09, 0x16, 0x0d, 0x5e, 0x1e, 0x13, 0x00, 0xe0,
0x8d, 0xb7, 0x2d, 0x87, 0x08, 0x98, 0x6b, 0x47, 0xb0, 0x37, 0x13, 0x9e, 0xb5, 0x1a, 0x70, 0x91,
0x47, 0x80, 0x04, 0x6f, 0x0f, 0xc5, 0x6b, 0x9b, 0x39, 0x05, 0xd4, 0xc1, 0xf6, 0xe8, 0x67, 0x7f,
0xd3, 0x9b, 0x72, 0xa3, 0xe1, 0xe6, 0x18, 0x02, 0x1c, 0x70, 0xdf, 0x21, 0x84, 0xb6, 0xad, 0x72,
0xb8, 0xef, 0x1a, 0xcd, 0xce, 0xc6, 0x63, 0x00, 0x79, 0xb0, 0xa2, 0x33, 0xf7, 0xf9, 0x8a, 0x29,
0xf2, 0x98, 0xc1, 0xc7, 0xf1, 0x2e, 0x7f, 0xbc, 0xd1, 0xd1, 0xd9, 0xd3, 0x14, 0x17, 0xcb, 0x2a,
0x2d, 0x61, 0x72, 0x64, 0xa7, 0x23, 0x6a, 0x72, 0x7c, 0x7d, 0x19, 0x83, 0x0a, 0xd5, 0x0a, 0xf5,
0x04, 0xc7, 0xac, 0xc5, 0x83, 0x53, 0xf7, 0x26, 0x63, 0x05, 0x0b, 0xc8, 0x06, 0x3d, 0xef, 0x8b,
0xee, 0xc4, 0x18, 0x14, 0x2e, 0x84, 0x32, 0x2e, 0x5c, 0xf4, 0xcd, 0x48, 0xe0, 0xc3, 0x23, 0xa8,
0x81, 0x12, 0x2a, 0xed, 0xeb, 0x8e, 0x22, 0x93, 0x0d, 0x7f, 0x8d, 0x3b, 0x87, 0x02, 0xd0, 0xbf,
0x4f, 0x51, 0x92, 0x4f, 0x59, 0xeb, 0xb4, 0x47, 0x34, 0xe4, 0xb6, 0xc3, 0x71, 0x18, 0x2e, 0x03,
0xde, 0x31, 0xbb, 0x7c, 0xcf, 0x62, 0xdc, 0xe6, 0x31, 0xfa, 0x47, 0x5e, 0x11, 0xf6, 0x7a, 0xd3,
0x92, 0x85, 0xf2, 0x62, 0xbf, 0xf3, 0xcb, 0xbe, 0xea, 0xa2, 0xbb, 0xad, 0x02, 0x1d, 0x2c, 0x81,
0x93, 0xe0, 0x13, 0x68, 0x9c, 0xc3, 0xbe, 0xd3, 0x5e, 0x67, 0x2c, 0x1b, 0x0a, 0x6b, 0x58, 0x25,
0xa4, 0xdf, 0x99, 0xab, 0xdb, 0x77, 0xc3, 0xa3, 0x58, 0xa7, 0x9c, 0xb8, 0xcf, 0xb5, 0xc8, 0xcb,
0x89, 0x2c, 0x86, 0x11, 0x2c, 0x67, 0x6f, 0xd9, 0x2f, 0xb4, 0xc9, 0x4a, 0x22, 0xb6, 0xf5, 0xac,
0xef, 0xa2, 0x06, 0xf3, 0x3a, 0x8d, 0xb9, 0x02, 0x5f, 0xee, 0xbe, 0xea, 0x66, 0x3d, 0x4a, 0xca,
0x2d, 0xc4, 0x0c, 0x0d, 0x73, 0x28, 0xc7, 0x23, 0x73, 0x1d, 0x72, 0x78, 0xbc, 0x01, 0x80, 0xe3,
0xfa, 0x7e, 0x3e, 0xb5, 0x52, 0x5b, 0xfa, 0x63, 0x0e, 0xdb, 0x63, 0x80, 0xef, 0xdd, 0x2b, 0x2f,
0xc5, 0xac, 0x4d, 0x3f, 0x93, 0x91, 0x94, 0xb8, 0xf2, 0xd2, 0xc1, 0xd0, 0x6f, 0x37, 0x4c, 0x0e,
0x9e, 0x6b, 0x8a, 0x25, 0x40, 0xde, 0x2c, 0x50, 0x26, 0x13, 0x96, 0xa3, 0x6c, 0x1e, 0x12, 0xd2,
0x41, 0x99, 0x56, 0xbc, 0xc1, 0x34, 0x85, 0x3b, 0x32, 0x62, 0x54, 0x7d, 0xbd, 0x6a, 0xa6, 0x7a,
0xed, 0xfe, 0x12, 0x5d, 0x39, 0x97, 0xbe, 0xb6, 0x3f, 0xe0, 0x3a, 0x8b, 0x94, 0x56, 0x5d, 0x9d,
0xef, 0x77, 0x2c, 0xc1, 0xe9, 0x9d, 0x90, 0xe4, 0x1f, 0x0f, 0x48, 0xa9, 0x0b, 0x22, 0x6a, 0x8c,
0xc5, 0x30, 0xe4, 0x9d, 0xed, 0x49, 0x2e, 0x49, 0xf9, 0xbd, 0x57, 0xd1, 0xb8, 0x6c, 0x22, 0x49,
0xd9, 0xcd, 0x05, 0xc4, 0x1b, 0xaf, 0xaf, 0xf3, 0x24, 0x9f, 0xe0, 0x99, 0x49, 0x8c, 0x47, 0x9c,
0x5f, 0xc9, 0x31, 0x40, 0xd6, 0x76, 0x10, 0x02, 0x5c, 0x04, 0x59, 0x7b, 0xfa, 0x88, 0x49, 0x44,
0x03, 0xce, 0x94, 0x0e, 0xd3, 0x69, 0x0e, 0xa6, 0xbd, 0x45, 0xb9, 0x6c, 0x3a, 0xf2, 0x7a, 0x27,
0x1e, 0x04, 0x04, 0x13, 0xfb, 0x77, 0x2b, 0xcf, 0x2e, 0x9f, 0xf1, 0xa3, 0x86, 0xa9, 0x6e, 0xd8,
0x5b, 0x3c, 0xbf, 0xe1, 0x9c, 0xa1, 0x6e, 0x27, 0x75, 0x8b, 0x17, 0x97, 0x2f, 0x14, 0x4e, 0xd8,
0x22, 0x8b, 0x98, 0xf7, 0xfa, 0x25, 0xc9, 0xc9, 0x3a, 0x85, 0x21, 0x94, 0x7e, 0x69, 0x25, 0x05,
0xf5, 0x12, 0x5c, 0x4d, 0x3f, 0x2d, 0x9f, 0xde, 0x3d, 0x77, 0x8f, 0xe8, 0x6b, 0x01, 0xea, 0x97,
0x96, 0x90, 0x04, 0x17, 0xd0, 0x50, 0xe0, 0x07, 0x02, 0x05, 0xf9, 0xc3, 0x44, 0x4d, 0x5a, 0x20,
0x07, 0x9c, 0x2e, 0xfd, 0x96, 0xe1, 0xec, 0xc2, 0x5f, 0xe2, 0xd5, 0xc6, 0x7c, 0xac, 0xb0, 0x87,
0x94, 0x92, 0x31, 0x01, 0x6b, 0x22, 0x60, 0xc6, 0x08, 0x7b, 0xbe, 0x25, 0x48, 0x84, 0xf7, 0xd1,
0x38, 0xa5, 0x4c, 0xcb, 0xe0, 0xc0, 0x7c, 0xe4, 0xa1, 0xd9, 0xfe, 0x23, 0x11, 0x09, 0xd5, 0x3d,
0x46, 0x7e, 0xff, 0x96, 0x73, 0x85, 0xc8, 0xa2, 0xc9, 0xc3, 0x32, 0x98, 0x49, 0x06, 0x23, 0x75,
0x6d, 0xc3, 0xca, 0xe9, 0x93, 0x13, 0xee, 0x71, 0x60, 0xd9, 0xcc, 0x05, 0xae, 0xfa, 0xbc, 0xc0,
0x03, 0xc8, 0xe6, 0x3a, 0x0c, 0x75, 0x1d, 0x1a, 0x1f, 0xb5, 0x94, 0x72, 0xe1, 0xaa, 0x38, 0xa4,
0x4c, 0xe3, 0xcd, 0x8f, 0x36, 0xed, 0xd3, 0xaa, 0xe2, 0xa8, 0x6d, 0x19, 0x9c, 0xe5, 0xea, 0x29,
0x13, 0xd1, 0x78, 0xa9, 0x77, 0xbd, 0xe1, 0x58, 0xcf, 0xf7, 0xe3, 0x81, 0xd8, 0xc1, 0xde, 0xb0,
0x4b, 0x1b, 0x15, 0x6c, 0x2e, 0x11, 0x6e, 0x00, 0x62, 0x0b, 0x75, 0x54, 0x81, 0xf7, 0x80, 0x57,
0x4f, 0xce, 0x0b, 0x15, 0x3b, 0xcd, 0x21, 0xe8, 0x9d, 0x58, 0xca, 0xa4, 0x26, 0xad, 0x48, 0xd0,
0xb3, 0x70, 0x36, 0x52, 0xbe, 0x33, 0x8e, 0x38, 0x4e, 0x65, 0x99, 0x88, 0x6a, 0xe6, 0xbe, 0xd7,
0x52, 0x52, 0xa5, 0x3e, 0x2f, 0x40, 0xb9, 0x2e, 0xa9, 0xb3, 0x14, 0xf3, 0xd0, 0x6a, 0x1b, 0xdf,
0xff, 0x11, 0xc8, 0x53, 0xd0, 0xf2, 0x78, 0x54, 0xeb, 0xdb, 0x83, 0xae, 0x54, 0x10, 0x6c, 0xcc,
0x03, 0x51, 0x31, 0x67, 0x78, 0xbe, 0x53, 0x17, 0x14, 0x8c, 0x89, 0xed, 0xd2, 0x0c, 0xdc, 0x54,
0x9e, 0x75, 0xf5, 0x6b, 0x5d, 0xa4, 0x21, 0x88, 0x83, 0xd1, 0x34, 0xaa, 0x2e, 0xa2, 0xac, 0x00,
0xcb, 0xf3, 0x04, 0xb7, 0x1d, 0x03, 0x12, 0x78, 0xea, 0x57, 0x15, 0xf7, 0x04, 0x35, 0x00, 0x74,
0xb4, 0x3e, 0x80, 0x77, 0x3c, 0x80, 0xcb, 0xb7, 0xb5, 0xd8, 0x79, 0x0c, 0xbf, 0xac, 0xb7, 0xc3,
0x30, 0x14, 0xf0, 0xf8, 0x57, 0x75, 0xfe, 0x06, 0xf9, 0x52, 0xa3, 0xcf, 0x2c, 0xf1, 0x50, 0x74,
0x5e, 0x2a, 0x71, 0xf0, 0x6e, 0x5a, 0x6d, 0xba, 0x87, 0x94, 0x79, 0x18, 0x2e, 0x29, 0x0d, 0x98,
0x37, 0x0e, 0xb4, 0x98, 0x03, 0xd6, 0xd2, 0xee, 0x02, 0x3b, 0x09, 0xd4, 0x65, 0x40, 0x25, 0x40,
0x82, 0xe5, 0x15, 0x8b, 0x8b, 0xfc, 0xd9, 0x36, 0xcd, 0x72, 0xdf, 0x58, 0x42, 0x45, 0x72, 0x4a,
0xf4, 0xf1, 0xc4, 0x39, 0xe2, 0xf4, 0x78, 0xa5, 0x74, 0xc4, 0xbb, 0xa5, 0xc5, 0xbd, 0xf8, 0x96,
0xcf, 0xa2, 0x8e, 0x52, 0x01, 0x67, 0x96, 0x4a, 0xbd, 0xf3, 0x4b, 0x9b, 0x09, 0x80, 0xe9, 0x19,
0xcd, 0xd6, 0x96, 0x36, 0x72, 0x54, 0x31, 0xe0, 0x82, 0x9c, 0xb7, 0xf5, 0xa0, 0x3a, 0xf9, 0xe9,
0xb2, 0x02, 0x64, 0x42, 0x56, 0xe7, 0xcb, 0xcc, 0x86, 0xc4, 0x41, 0x6d, 0x0f, 0xb7, 0x03, 0x48,
0x86, 0x38, 0x0a, 0xfd, 0x4c, 0xf0, 0xee, 0x0c, 0x78, 0x98, 0x2c, 0x59, 0x13, 0xb8, 0x5f, 0x68,
0x9a, 0x87, 0x5d, 0x6e, 0xe3, 0xf2, 0x9d, 0xbc, 0x71, 0x09, 0x12, 0xeb, 0x32, 0x18, 0x5f, 0x64,
0x98, 0xe2, 0x3f, 0xef, 0x34, 0x38, 0xa6, 0x31, 0x0a, 0x0f, 0x8c, 0x3f, 0x7d, 0xbb, 0x65, 0xb5,
0x1d, 0xd2, 0x37, 0x70, 0x82, 0x20, 0x23, 0x13, 0x1f, 0x5b, 0x8c, 0x53, 0xde, 0x91, 0xd7, 0x80,
0x11, 0xbb, 0x40, 0x7b, 0x09, 0x23, 0xbe, 0x1f, 0x18, 0x61, 0x31, 0x1f, 0x70, 0x8a, 0x2e, 0x50,
0xc5, 0x73, 0x15, 0x51, 0xd0, 0x0d, 0xcb, 0xf1, 0x4d, 0x9c, 0x22, 0x99, 0x74, 0xd2, 0xd1, 0x6d,
0x0a, 0x2d, 0xb8, 0xec, 0x33, 0x1c, 0xe6, 0xd3, 0xd1, 0x7c, 0xa0, 0x87, 0xbc, 0xb1, 0xf9, 0xd8,
0x27, 0xcd, 0x0e, 0x5a, 0xf3, 0x93, 0x13, 0xf3, 0xe3, 0x75, 0x9f, 0x6a, 0x01, 0xd9, 0x91, 0x61,
0x0b, 0xc8, 0xca, 0x2f, 0x96, 0x0c, 0x98, 0x61, 0xf7, 0x62, 0xec, 0x3b, 0xff, 0x10, 0x16, 0xdd,
0x09, 0x33, 0x3b, 0x74, 0x94, 0x39, 0xe2, 0xa1, 0xdd, 0x70, 0xc5, 0x60, 0xfe, 0xcc, 0x29, 0xf0,
0x5d, 0x09, 0xcd, 0xa7, 0xd3, 0x58, 0xe9, 0xab, 0xb9, 0xf2, 0xf6, 0xb3, 0x50, 0x90, 0x8a, 0x87,
0x2a, 0x20, 0xff, 0x72, 0x5c, 0xb2, 0x1b, 0xe0, 0xba, 0x94, 0x78, 0x69, 0xf1, 0xfc, 0x0c, 0x27,
0x56, 0x88, 0x14, 0x51, 0x9e, 0xfc, 0xd5, 0x7f, 0xb2, 0xef, 0xf4, 0x70, 0xe2, 0x47, 0xf3, 0x38,
0xe8, 0x3b, 0x9c, 0xc1, 0x7e, 0xf3, 0xc3, 0xfe, 0xaf, 0x99, 0x1b, 0x80, 0x21, 0x5c, 0xdc, 0x41,
0x94, 0x61, 0x99, 0x1c, 0x03, 0x19, 0xf0, 0x23, 0xa3, 0x3b, 0x19, 0x9b, 0x40, 0x0d, 0x9e, 0x6a,
0xe0, 0xb6, 0x5e, 0x88, 0xa6, 0x75, 0x13, 0x9f, 0x3a, 0xa0, 0x01, 0x7a, 0xe2, 0x2f, 0xdd, 0x18,
0x4f, 0xbd, 0x39, 0x05, 0x48, 0x06, 0xac, 0x6a, 0x3f, 0x9a, 0x00, 0x13, 0x12, 0x1c, 0xc5, 0x32,
0x24, 0x24, 0x2a, 0x56, 0x8c, 0x80, 0x10, 0xf1, 0x0e, 0x7c, 0x4e, 0xc1, 0xb4, 0x38, 0x00, 0xb9,
0x2d, 0x54, 0x15, 0x2b, 0x93, 0xf1, 0xb2, 0x04, 0x1a, 0xa1, 0xb4, 0xde, 0x65, 0xcc, 0x48, 0xc0,
0xaa, 0xed, 0x30, 0x9a, 0xf8, 0xd9, 0x21, 0x3d, 0x9c, 0x3b, 0x61, 0x58, 0xd9, 0x9c, 0x96, 0x08,
0x62, 0x3c, 0x2f, 0xe8, 0x4c, 0xe3, 0x7b, 0x2f, 0x8e, 0x26, 0x2c, 0xc8, 0x8f, 0x9b, 0x38, 0x53,
0xc4, 0x13, 0x5a, 0x30, 0x9e, 0x7e, 0x39, 0xd4, 0x9e, 0x41, 0x2d, 0x59, 0x2f, 0x0c, 0xd5, 0x80,
0x3a, 0xaa, 0xa6, 0xd5, 0x65, 0xa2, 0xb0, 0x1d, 0x00, 0xa9, 0x64, 0x6b, 0x8f, 0x76, 0xa6, 0xef,
0xb6, 0xf3, 0xeb, 0xcb, 0xa1, 0x4e, 0x53, 0x3b, 0x7f, 0xd4, 0x76, 0xa7, 0x44, 0x6c, 0x71, 0x70,
0x2d, 0x52, 0xf9, 0x63, 0xcc, 0x1d, 0x04, 0x52, 0xa1, 0x4a, 0xbf, 0x9d, 0x33, 0xe0, 0x31, 0x89,
0xbc, 0x4d, 0xd5, 0xd8, 0x14, 0x0f, 0x96, 0x2f, 0x11, 0xfb, 0x02, 0xe8, 0x75, 0x9b, 0x8c, 0x2b,
0xf2, 0xc1, 0x7b, 0x27, 0x27, 0x00, 0xbb, 0x97, 0x36, 0xd2, 0x65, 0xc2, 0x3b, 0x1e, 0x12, 0x73,
0xa9, 0x39, 0x71, 0xb0, 0x6a, 0x6c, 0xc0, 0x5c, 0x0e, 0xfd, 0xaf, 0x41, 0x1c, 0x65, 0xb6, 0xcf,
0x68, 0x88, 0x0f, 0xe6, 0x50, 0x4c, 0x93, 0x23, 0x57, 0xd7, 0xdf, 0x5c, 0xa3, 0xd2, 0x55, 0xc7,
0x37, 0x76, 0x56, 0x69, 0xff, 0xf8, 0xb0, 0xdd, 0xb4, 0xcd, 0xdd, 0xe1, 0x36, 0x8a, 0x8e, 0x22,
0xcf, 0xbc, 0x9a, 0x76, 0xbf, 0xb9, 0xe6, 0x36, 0x3e, 0xe0, 0xe6, 0xd0, 0x6c, 0x06, 0x40, 0x60,
0xfe, 0xfb, 0x25, 0x00, 0x4f, 0xba, 0x23, 0xcb, 0x41, 0x82, 0x5e, 0xbe, 0x85, 0x2d, 0x8b, 0x39,
0x53, 0x64, 0xc9, 0x0e, 0x22, 0x82, 0xbd, 0x8f, 0xac, 0x0b, 0x1e, 0x3b, 0xf4, 0x37, 0xf7, 0xdd,
0x9a, 0xdf, 0x65, 0x9a, 0x40, 0xbc, 0x2a, 0x64, 0xbf, 0x6b, 0x7c, 0xcc, 0x74, 0xaf, 0x7d, 0xfa,
0x3f, 0x4c, 0x5f, 0x36, 0xe9, 0xbd, 0x1b, 0x34, 0xff, 0x5e, 0x56, 0x6f, 0x3c, 0xfd, 0x5e, 0x6a,
0x7c, 0x2d, 0xb4, 0x1b, 0x9f, 0x9e, 0xf7, 0x1b, 0xab, 0xd6, 0xf0, 0x59, 0x2f, 0x0a, 0x39, 0xa4,
0xeb, 0xec, 0xf0, 0xd2, 0x25, 0x3f, 0x0a, 0xa9, 0xef, 0xbb, 0xb9, 0xb0, 0xc1, 0x41, 0xb8, 0xc0,
0xc8, 0x3b, 0x04, 0x1f, 0x15, 0x0e, 0xb7, 0x5a, 0xe8, 0xbd, 0x73, 0x06, 0xa6, 0x1d, 0xc3, 0xfa,
0x1f, 0x3e, 0x1d, 0xe3, 0xbd, 0xad, 0xe8, 0xfb, 0x97, 0xfa, 0xae, 0x7d, 0xa8, 0x77, 0x12, 0xcc,
0x8b, 0x5c, 0xeb, 0xed, 0x12, 0xa0, 0xf9, 0x33, 0x3f, 0x85, 0x73, 0x06, 0x65, 0xc7, 0x9f, 0xfb,
0x5c, 0xba, 0x69, 0x2b, 0xcc, 0x25, 0xe4, 0xbb, 0xc4, 0x9e, 0xd9, 0xdb, 0x47, 0x7d, 0xd7, 0xbc,
0xef, 0xc6, 0xcb, 0xcd, 0xd6, 0x30, 0x3a, 0x53, 0x5b, 0xbe, 0xd8, 0x07, 0xcc, 0x01, 0x6d, 0x2b,
0x6a, 0x75, 0x10, 0x94, 0x78, 0x84, 0xfc, 0x85, 0x42, 0xdf, 0xbe, 0xe5, 0x6d, 0x73, 0x7d, 0xe7,
0x4d, 0x5b, 0x0d, 0x75, 0x00, 0xda, 0x38, 0x85, 0x11, 0x2a, 0x7b, 0x96, 0x5a, 0xdc, 0x61, 0x5c,
0xb8, 0x1d, 0x78, 0x7f, 0x0a, 0x57, 0x54, 0x07, 0x8d, 0xdf, 0xda, 0x47, 0xde, 0x76, 0xbb, 0x07,
};
const unsigned int html_content_br_len = 3296;
#endif // HTML_CONTENT_BR_H

View File

@@ -1,31 +1,225 @@
#!/usr/bin/env python3
"""
Enhanced HTML/CSS/JS Minifier and Compressor
This script provides multiple levels of optimization for embedded web pages
"""
import minify_html
import gzip
import brotli
import re
import sys
from pathlib import Path
with open("landingpage.html", "r", encoding="utf-8") as fin:
original_html = fin.read()
# Try to import optional JavaScript minifier
try:
import jsmin
HAS_JSMIN = True
except ImportError:
HAS_JSMIN = False
print("Warning: jsmin not installed. Install with: pip install jsmin --break-system-packages")
minified_html = minify_html.minify(
original_html,
minify_js=True,
minify_css=True,
keep_comments=False, # Remove comments
keep_html_and_head_opening_tags=False, # Remove <html> and <head> if possible
keep_closing_tags=True, # Keep closing tags (safer; set False for more aggression if you test thoroughly)
remove_processing_instructions=True, # Remove <?xml ...> etc.
#keep_comments=False,
remove_bangs=False # Keep <!DOCTYPE> bang (removing saves bytes but can break some edge cases)
)
# Try to import rjsmin (faster alternative)
try:
import rjsmin
HAS_RJSMIN = True
except ImportError:
HAS_RJSMIN = False
with open("webpage_minified.html", "w") as fout:
fout.write(minified_html)
minified_bytes = minified_html.encode('utf-8')
gzipped_bytes = gzip.compress(minified_bytes, compresslevel=9)
with open("webpage.h", "w") as fout:
fout.write("const char html_content[] = {")
fout.write(','.join(f'0x{byte:02x}' for byte in gzipped_bytes))
fout.write("};\n\n")
fout.write(f"const unsigned int html_content_len = {len(gzipped_bytes)};\n")
def extract_and_minify_js(html_content):
"""Extract JavaScript, minify it, and reinsert into HTML"""
if not (HAS_JSMIN or HAS_RJSMIN):
return html_content
# Find all script tags
script_pattern = re.compile(r'<script>(.*?)</script>', re.DOTALL)
def minify_script_content(match):
script_content = match.group(1)
# Skip if empty or too small
if len(script_content.strip()) < 50:
return match.group(0)
try:
# Use rjsmin if available (faster), otherwise jsmin
if HAS_RJSMIN:
minified = rjsmin.jsmin(script_content)
elif HAS_JSMIN:
minified = jsmin.jsmin(script_content)
else:
minified = script_content
return f'<script>{minified}</script>'
except Exception as e:
print(f"Warning: JS minification failed: {e}")
return match.group(0)
return script_pattern.sub(minify_script_content, html_content)
def aggressive_html_minify(html_content):
"""Apply aggressive minification strategies"""
# First pass: minify JavaScript
html_content = extract_and_minify_js(html_content)
# Use minify_html library
minified = minify_html.minify(
html_content,
minify_js=True,
minify_css=True,
keep_comments=False,
keep_html_and_head_opening_tags=False,
keep_closing_tags=True, # Safer - can set to False for more aggressive
remove_processing_instructions=True,
remove_bangs=False, # Keep <!DOCTYPE>
#do_not_minify_doctype=True,
#ensure_spec_compliant_unquoted_attribute_values=True,
#keep_spaces_between_attributes=False,
)
return minified
def generate_c_header(data, variable_name="html_content", use_progmem=True):
"""Generate C/C++ header file with compressed data"""
lines = []
# Add header guard
guard = variable_name.upper() + "_H"
lines.append(f"#ifndef {guard}")
lines.append(f"#define {guard}")
lines.append("")
# Add includes if using PROGMEM
if use_progmem:
lines.append("#include <Arduino.h>")
lines.append("")
# Add array declaration
progmem_keyword = "PROGMEM " if use_progmem else ""
lines.append(f"const unsigned char {progmem_keyword}{variable_name}[] = {{")
# Format bytes in rows of 16
hex_bytes = [f'0x{byte:02x}' for byte in data]
for i in range(0, len(hex_bytes), 16):
row = hex_bytes[i:i+16]
lines.append(" " + ", ".join(row) + ",")
lines.append("};")
lines.append("")
lines.append(f"const unsigned int {variable_name}_len = {len(data)};")
lines.append("")
lines.append(f"#endif // {guard}")
return "\n".join(lines)
def print_compression_stats(original_size, minified_size, gzip_size, brotli_size=None):
"""Print compression statistics"""
print("\n" + "="*60)
print("COMPRESSION STATISTICS")
print("="*60)
print(f"Original HTML: {original_size:,} bytes")
print(f"Minified HTML: {minified_size:,} bytes ({minified_size/original_size*100:.1f}%)")
print(f"Gzip (level 9): {gzip_size:,} bytes ({gzip_size/original_size*100:.1f}%)")
if brotli_size:
print(f"Brotli (level 11): {brotli_size:,} bytes ({brotli_size/original_size*100:.1f}%)")
print(f"\nSavings (gzip): {original_size - gzip_size:,} bytes ({(1-gzip_size/original_size)*100:.1f}% reduction)")
if brotli_size:
print(f"Savings (brotli): {original_size - brotli_size:,} bytes ({(1-brotli_size/original_size)*100:.1f}% reduction)")
print("="*60 + "\n")
def main():
input_file = "landingpage.html"
# Check if input file exists
if not Path(input_file).exists():
print(f"Error: {input_file} not found")
sys.exit(1)
# Read original HTML
print(f"Reading {input_file}...")
with open(input_file, "r", encoding="utf-8") as fin:
original_html = fin.read()
original_size = len(original_html.encode('utf-8'))
# Minify HTML
print("Minifying HTML/CSS/JS...")
minified_html = aggressive_html_minify(original_html)
minified_size = len(minified_html.encode('utf-8'))
# Save minified HTML
with open("webpage_minified.html", "w", encoding="utf-8") as fout:
fout.write(minified_html)
print("Saved: webpage_minified.html")
# Compress with gzip
print("Compressing with gzip (level 9)...")
minified_bytes = minified_html.encode('utf-8')
gzipped_bytes = gzip.compress(minified_bytes, compresslevel=9)
gzip_size = len(gzipped_bytes)
# Compress with brotli (if available)
brotli_size = None
brotli_bytes = None
try:
print("Compressing with brotli (level 11)...")
brotli_bytes = brotli.compress(minified_bytes, quality=11)
brotli_size = len(brotli_bytes)
except Exception as e:
print(f"Brotli compression not available: {e}")
# Generate C headers
print("\nGenerating C header files...")
# Gzip version
with open("webpage_gzip.h", "w") as fout:
fout.write(generate_c_header(gzipped_bytes, "html_content_gz", use_progmem=True))
print("Saved: webpage_gzip.h")
# Brotli version (if available)
if brotli_bytes:
with open("webpage_brotli.h", "w") as fout:
fout.write(generate_c_header(brotli_bytes, "html_content_br", use_progmem=True))
print("Saved: webpage_brotli.h")
# Also generate the old format for compatibility
with open("webpage.h", "w") as fout:
fout.write("const char html_content[] = {")
fout.write(','.join(f'0x{byte:02x}' for byte in gzipped_bytes))
fout.write("};\n\n")
fout.write(f"const unsigned int html_content_len = {len(gzipped_bytes)};\n")
print("Saved: webpage.h (legacy format)")
# Print statistics
print_compression_stats(original_size, minified_size, gzip_size, brotli_size)
# Recommendations
print("RECOMMENDATIONS:")
print("-" * 60)
if brotli_size and brotli_size < gzip_size:
savings = gzip_size - brotli_size
print(f"Use Brotli compression (saves {savings} bytes vs gzip)")
print(f" Include: webpage_brotli.h")
else:
print(f"Use Gzip compression")
print(f" Include: webpage_gzip.h")
if not HAS_RJSMIN and not HAS_JSMIN:
print("\nInstall rjsmin for better JS compression:")
print(" pip install rjsmin --break-system-packages")
print("-" * 60)
if __name__ == "__main__":
main()

256
main/webpage_gzip.h Normal file
View File

@@ -0,0 +1,256 @@
#ifndef HTML_CONTENT_GZ_H
#define HTML_CONTENT_GZ_H
#include <Arduino.h>
const unsigned char PROGMEM html_content_gz[] = {
0x1f, 0x8b, 0x08, 0x00, 0xed, 0x82, 0x54, 0x69, 0x02, 0xff, 0xbd, 0x1a, 0xfd, 0x77, 0xda, 0x46,
0xf2, 0xf7, 0xfc, 0x15, 0x1b, 0x27, 0xe7, 0x4a, 0x89, 0x10, 0x60, 0x3b, 0x69, 0x22, 0x2c, 0xdc,
0xc4, 0x71, 0x9a, 0xf6, 0x12, 0xdb, 0xcf, 0x1f, 0xbd, 0x77, 0xe7, 0xf2, 0xac, 0x05, 0x2d, 0xa0,
0x5a, 0xd2, 0x52, 0x69, 0x31, 0xe6, 0x88, 0xfe, 0xf7, 0x9b, 0xd9, 0x5d, 0x7d, 0x00, 0x32, 0xce,
0xa5, 0x77, 0x8e, 0x5f, 0x40, 0x5a, 0xcd, 0xce, 0xcc, 0xce, 0xf7, 0x8c, 0xd8, 0x7f, 0xea, 0xf3,
0x81, 0x98, 0x4f, 0x18, 0x19, 0x8b, 0x28, 0xec, 0xee, 0x8b, 0x40, 0x84, 0xac, 0x7b, 0xc8, 0x63,
0x91, 0xf0, 0x90, 0x9c, 0xd2, 0x98, 0x85, 0xfb, 0x4d, 0xb5, 0xb8, 0x1f, 0x31, 0x41, 0xc9, 0x00,
0x1e, 0xb1, 0x58, 0xb8, 0x5b, 0xb3, 0xc0, 0x17, 0x63, 0xd7, 0x67, 0xb7, 0xc1, 0x80, 0x35, 0xe4,
0x8d, 0x15, 0xc4, 0x81, 0x08, 0x68, 0xd8, 0x48, 0x07, 0x34, 0x64, 0x6e, 0xdb, 0x6e, 0x6d, 0x91,
0x98, 0x46, 0xcc, 0xbd, 0x0d, 0xd8, 0x6c, 0xc2, 0x13, 0xd1, 0xdd, 0x4f, 0xc5, 0x1c, 0x30, 0x3d,
0x9b, 0x25, 0x74, 0x32, 0x61, 0xc9, 0x42, 0xb0, 0x3b, 0xd1, 0xa0, 0x61, 0x30, 0x8a, 0x9d, 0x01,
0x20, 0x65, 0x49, 0xa7, 0xcf, 0xef, 0x1a, 0x69, 0xf0, 0xef, 0x20, 0x1e, 0x39, 0x7d, 0x9e, 0xf8,
0x2c, 0x69, 0xc0, 0x4a, 0xf6, 0x4c, 0x53, 0x5d, 0x44, 0xf4, 0x4e, 0xd1, 0x72, 0x5e, 0xb5, 0x5a,
0x93, 0xbb, 0x4e, 0x44, 0x93, 0x51, 0x10, 0x3b, 0x74, 0x2a, 0x78, 0x67, 0x42, 0x7d, 0x1f, 0xf7,
0xb5, 0x48, 0x1b, 0x1e, 0x65, 0x7d, 0xee, 0xcf, 0x6b, 0x08, 0xe8, 0x1d, 0xad, 0x12, 0x3c, 0x7b,
0xb1, 0x18, 0xf0, 0x90, 0x27, 0xce, 0xb3, 0x9d, 0x21, 0xfe, 0x75, 0xfa, 0x74, 0x70, 0x33, 0x4a,
0xf8, 0x34, 0xf6, 0x1b, 0xfa, 0xc1, 0x70, 0x38, 0xec, 0x0c, 0x81, 0x85, 0xc6, 0x90, 0x46, 0x41,
0x38, 0x77, 0x8e, 0xb9, 0xe0, 0xe4, 0x9c, 0xc6, 0xa9, 0xf5, 0x1b, 0x4b, 0x7c, 0x1a, 0x53, 0x2b,
0x85, 0x9b, 0x46, 0xca, 0x92, 0x40, 0x03, 0xc2, 0x19, 0x98, 0xd3, 0xb6, 0x77, 0x12, 0x16, 0x65,
0x41, 0x3c, 0x99, 0x0a, 0xab, 0x3f, 0x15, 0x82, 0xc7, 0x55, 0x8e, 0x92, 0x60, 0x34, 0x16, 0xf5,
0x27, 0xae, 0xe1, 0x81, 0x0d, 0x99, 0xcf, 0xde, 0x76, 0x14, 0x8c, 0xd3, 0x9e, 0xdc, 0x91, 0x94,
0x87, 0x81, 0x4f, 0x9e, 0xf5, 0xe9, 0xdb, 0xd7, 0xaf, 0xfa, 0xfa, 0x41, 0x23, 0xa1, 0x7e, 0x30,
0x4d, 0x9d, 0x57, 0x20, 0x1c, 0x25, 0xa8, 0x76, 0xab, 0xf5, 0x37, 0xc5, 0xc2, 0x15, 0xea, 0xd9,
0x45, 0x06, 0x7a, 0x56, 0x65, 0x21, 0x9e, 0x46, 0x7d, 0x96, 0xf4, 0x16, 0xd5, 0x03, 0x46, 0x3c,
0xe6, 0xe9, 0x84, 0x0e, 0x58, 0xb6, 0xce, 0xb6, 0x12, 0x64, 0x66, 0x0f, 0xc6, 0x34, 0x1e, 0x31,
0xdf, 0x02, 0xe5, 0x44, 0x51, 0x20, 0xae, 0xfb, 0x22, 0x5e, 0x94, 0xf2, 0x7a, 0x1a, 0x44, 0xa8,
0x72, 0x1a, 0x8b, 0x9a, 0xb3, 0xec, 0xd0, 0xbd, 0xb7, 0xbb, 0x7e, 0x09, 0x92, 0x2d, 0xe1, 0x98,
0x26, 0x29, 0x00, 0x4d, 0x78, 0xa0, 0x2d, 0x42, 0x1e, 0x38, 0xe6, 0x31, 0xab, 0x9c, 0x48, 0xeb,
0xb1, 0x21, 0xf8, 0xc4, 0x41, 0x75, 0x17, 0xea, 0x94, 0x37, 0xf2, 0x28, 0x33, 0x86, 0xf2, 0x75,
0x7e, 0x6c, 0xb5, 0xaa, 0xe8, 0xaf, 0xfc, 0x20, 0xa5, 0xfd, 0x90, 0xf9, 0xbd, 0x9c, 0xd9, 0x37,
0x6f, 0xde, 0x74, 0x34, 0xcd, 0x98, 0xe3, 0x21, 0x43, 0x3e, 0x63, 0x7e, 0x0d, 0xd7, 0x7b, 0x7b,
0x7b, 0x15, 0x96, 0x05, 0x62, 0x59, 0x68, 0xa9, 0x03, 0x44, 0x48, 0x27, 0x29, 0x73, 0xf2, 0x8b,
0x4e, 0x45, 0x60, 0x21, 0x1b, 0x8a, 0xaa, 0x32, 0x84, 0xbf, 0x28, 0x34, 0x0d, 0xc2, 0x8d, 0xaa,
0xca, 0xd4, 0x5a, 0xce, 0x4f, 0xf3, 0x06, 0x0c, 0x39, 0x9d, 0x46, 0x70, 0xd8, 0x25, 0x5b, 0x96,
0x18, 0x2b, 0xb6, 0xb9, 0xce, 0xeb, 0x8f, 0x3b, 0xbb, 0x35, 0x16, 0x91, 0xa3, 0xb5, 0x77, 0xc1,
0x2e, 0xd7, 0xa4, 0x64, 0x0f, 0xa2, 0x9c, 0x33, 0x25, 0xee, 0xaa, 0x25, 0xbf, 0x42, 0x4b, 0x7e,
0x16, 0xa5, 0xa3, 0x1a, 0x53, 0x18, 0xb7, 0x17, 0x25, 0xe8, 0x8e, 0x02, 0xfd, 0x29, 0x62, 0x7e,
0x40, 0x49, 0x3a, 0x48, 0x18, 0x8b, 0x09, 0x8d, 0x7d, 0x62, 0x48, 0x11, 0xec, 0xbb, 0xbb, 0xaf,
0x40, 0x45, 0xe6, 0xa2, 0xc6, 0xa7, 0xa5, 0x62, 0x4b, 0x37, 0x06, 0x8e, 0x95, 0x94, 0x89, 0x48,
0x88, 0x14, 0x5a, 0x9d, 0xa7, 0x54, 0xb6, 0x82, 0x6a, 0x27, 0x21, 0x9d, 0x3b, 0xfd, 0x90, 0x0f,
0x6e, 0x8a, 0xad, 0x0b, 0x6d, 0x2a, 0xb9, 0xb0, 0xd1, 0x40, 0x96, 0x21, 0xb3, 0xfd, 0xa6, 0x0a,
0x4c, 0xfb, 0xcd, 0x31, 0xa3, 0x7e, 0x77, 0x1f, 0x63, 0x47, 0x77, 0xdf, 0x0f, 0x6e, 0x49, 0xe0,
0xbb, 0x3a, 0x58, 0x15, 0xf7, 0x9a, 0xef, 0xee, 0xfe, 0xb8, 0xdd, 0x3d, 0x0c, 0xa7, 0x29, 0x48,
0xe0, 0x10, 0xcc, 0x0b, 0x8e, 0x08, 0xdb, 0xdb, 0x10, 0x42, 0x91, 0x2e, 0x7c, 0xc1, 0x0e, 0x81,
0xb8, 0xa4, 0x03, 0x11, 0x1e, 0x0f, 0xc2, 0x60, 0x70, 0xe3, 0x6e, 0xa5, 0x2c, 0xf6, 0x35, 0xbc,
0xf1, 0x43, 0x2a, 0x68, 0x22, 0x7e, 0x30, 0xb7, 0xc8, 0x20, 0xa4, 0x69, 0xea, 0x82, 0x02, 0xba,
0xe7, 0x17, 0xef, 0xce, 0x2e, 0xf6, 0x9b, 0x6a, 0x1b, 0x70, 0x84, 0x38, 0xbe, 0x01, 0x0f, 0x9f,
0x2c, 0xa1, 0x21, 0xf2, 0x40, 0xee, 0x43, 0x36, 0x02, 0xd4, 0x4e, 0x4e, 0xff, 0x5b, 0x62, 0x80,
0x82, 0x2f, 0xf3, 0x7c, 0x79, 0xfc, 0xe1, 0x64, 0x05, 0x4b, 0x13, 0xcf, 0xdf, 0xcc, 0x65, 0x51,
0x15, 0x09, 0xa4, 0x90, 0x10, 0x62, 0x4b, 0xec, 0xee, 0x76, 0xf7, 0x65, 0x18, 0x42, 0xa1, 0x82,
0x61, 0x91, 0x04, 0x64, 0xcf, 0xe3, 0x70, 0x5e, 0xc5, 0xb0, 0x61, 0x4b, 0x10, 0x5f, 0x8b, 0x20,
0x62, 0xc8, 0xa4, 0x8c, 0x44, 0x2e, 0xe8, 0xf9, 0xe6, 0x50, 0x05, 0x25, 0x43, 0x8c, 0x83, 0xd4,
0x04, 0x21, 0xb0, 0x89, 0xdb, 0x26, 0x32, 0xcc, 0xf9, 0x54, 0x30, 0x84, 0x6f, 0x80, 0xca, 0x69,
0xd8, 0x25, 0xf9, 0x19, 0x01, 0x53, 0xcc, 0x67, 0x18, 0x1a, 0x8a, 0xe3, 0xa6, 0x4c, 0x5c, 0x00,
0xe4, 0x05, 0x3f, 0xe6, 0x33, 0xc3, 0xec, 0x9e, 0xcf, 0xe3, 0x01, 0xc1, 0x85, 0xba, 0x23, 0x6a,
0x35, 0x9f, 0x0f, 0xc6, 0xcc, 0x9f, 0x82, 0xbd, 0x9d, 0xa3, 0x46, 0x4b, 0x41, 0x96, 0x07, 0xe4,
0xb7, 0xec, 0x5a, 0xaa, 0xbb, 0x64, 0x58, 0x7d, 0xe5, 0x5b, 0x35, 0xcf, 0x2a, 0x48, 0x03, 0xb5,
0x4d, 0x54, 0x8e, 0xd0, 0xd8, 0xea, 0x69, 0x80, 0xa6, 0xfe, 0x02, 0x85, 0x67, 0xe4, 0x0b, 0x20,
0x49, 0x9b, 0x1f, 0xe8, 0xbc, 0x86, 0x00, 0xa4, 0x8a, 0x6b, 0x24, 0x92, 0x92, 0x28, 0x88, 0xdd,
0xd6, 0xb7, 0xd0, 0x51, 0xd9, 0xa5, 0x86, 0xd2, 0x19, 0x8b, 0x68, 0x10, 0xdb, 0xe4, 0x43, 0x00,
0x52, 0x89, 0x07, 0x8c, 0x18, 0x43, 0x61, 0xd6, 0xd0, 0x4c, 0x24, 0x1c, 0x38, 0xfd, 0x35, 0x38,
0xad, 0xd8, 0xa4, 0xed, 0xcd, 0xf4, 0xf0, 0x5c, 0x0f, 0x12, 0xf3, 0x93, 0x00, 0x44, 0x28, 0x09,
0xfd, 0xf5, 0x13, 0xfe, 0x0a, 0x1e, 0x47, 0x3e, 0xc9, 0xf8, 0x4a, 0x8c, 0x20, 0xae, 0xa3, 0xf7,
0x07, 0x80, 0xfc, 0xaf, 0xc8, 0xbd, 0xa7, 0x02, 0x42, 0xd1, 0x9c, 0x18, 0xbf, 0xd5, 0x51, 0xba,
0xe5, 0xa1, 0xa0, 0x23, 0xb6, 0xc1, 0xc9, 0xba, 0xa7, 0x09, 0x1f, 0x25, 0x34, 0x22, 0x67, 0x1f,
0x09, 0x28, 0x87, 0x0b, 0x76, 0x6f, 0x3c, 0x98, 0x28, 0xc8, 0xb3, 0x8f, 0xe7, 0xec, 0xcf, 0x29,
0x03, 0x79, 0x82, 0x97, 0xe4, 0xbb, 0xdf, 0x85, 0x21, 0x79, 0x2f, 0xc1, 0xd3, 0x4d, 0x21, 0x41,
0x63, 0xcc, 0xb3, 0xb1, 0x0a, 0xac, 0x79, 0x92, 0x2e, 0x08, 0xa9, 0xa5, 0x53, 0x0a, 0x88, 0x53,
0xf4, 0x44, 0x0a, 0x3a, 0x54, 0x4a, 0xaf, 0x20, 0xef, 0x27, 0xea, 0xbf, 0x0f, 0xf5, 0x69, 0x10,
0xa6, 0x50, 0x65, 0xaa, 0x8c, 0xd9, 0xfd, 0xf0, 0xee, 0xf8, 0xe7, 0xa3, 0x33, 0xf2, 0xaf, 0x93,
0xe3, 0x23, 0x88, 0xf0, 0x7a, 0x91, 0xac, 0x04, 0xe8, 0x43, 0x48, 0x65, 0xfd, 0x84, 0x8a, 0x80,
0xc7, 0xf7, 0xc7, 0xbf, 0x81, 0x06, 0x62, 0xc6, 0x0f, 0xa8, 0x32, 0x88, 0x7e, 0x4a, 0xbb, 0x4b,
0x9b, 0x35, 0x3f, 0x64, 0xd3, 0x6e, 0x69, 0x60, 0xb8, 0xfd, 0x03, 0x5e, 0xd4, 0xee, 0x5f, 0x57,
0xcc, 0xc7, 0x20, 0x89, 0x66, 0x34, 0x61, 0xab, 0x6a, 0xa5, 0x83, 0x01, 0x9b, 0x08, 0xd7, 0xee,
0x07, 0x32, 0x8c, 0x0d, 0x35, 0xd8, 0xf5, 0x30, 0xc0, 0xc4, 0x87, 0xc6, 0x82, 0x57, 0x4b, 0xa1,
0x6e, 0x3a, 0x09, 0x39, 0xf5, 0x97, 0x64, 0xac, 0x96, 0x72, 0x1a, 0x20, 0xe5, 0x4b, 0xb9, 0x40,
0x4a, 0xaa, 0xf7, 0x32, 0xf6, 0x99, 0x8f, 0x00, 0x2c, 0x5c, 0x37, 0x14, 0xa0, 0x14, 0xf2, 0xd1,
0x12, 0x19, 0x9f, 0xcf, 0x62, 0xc4, 0x0b, 0x7b, 0x70, 0x0b, 0xd0, 0xf9, 0xa0, 0x57, 0x08, 0x2c,
0x6d, 0x30, 0x15, 0xad, 0x30, 0xc4, 0xa9, 0x35, 0x57, 0x3c, 0xd8, 0x98, 0xa6, 0x12, 0xd6, 0xe7,
0x5c, 0x7c, 0x57, 0x56, 0x3c, 0x3b, 0x7a, 0x7f, 0x72, 0x52, 0x4d, 0xc2, 0x85, 0x69, 0x35, 0xa1,
0x08, 0xc8, 0x3f, 0xa1, 0xb6, 0x09, 0x26, 0xa2, 0x1b, 0x32, 0x41, 0x26, 0x68, 0xa1, 0xbf, 0xd1,
0x70, 0xca, 0x52, 0xf7, 0xaa, 0x67, 0xc9, 0xdb, 0x63, 0x68, 0x7d, 0xca, 0xbb, 0x4b, 0xe8, 0x8d,
0xf0, 0x0e, 0xca, 0xb6, 0x18, 0xdc, 0x1d, 0x5c, 0x1c, 0xce, 0xd3, 0x85, 0xe6, 0x6b, 0x1a, 0x41,
0x31, 0x61, 0x8f, 0x98, 0x38, 0x0a, 0x19, 0x5e, 0xbe, 0x9f, 0xff, 0xe2, 0x1b, 0x81, 0x6f, 0x76,
0x68, 0x8a, 0x79, 0x67, 0x38, 0x8d, 0x07, 0x68, 0x1e, 0xa4, 0x7a, 0x36, 0x38, 0x0a, 0x62, 0x37,
0x17, 0xfa, 0xc2, 0x75, 0x5d, 0x4f, 0xe6, 0x16, 0x6f, 0x7b, 0xfb, 0x29, 0x10, 0x40, 0x4b, 0x30,
0xbc, 0x7f, 0x04, 0xe0, 0x8a, 0x7d, 0x06, 0xb5, 0x0f, 0x81, 0xa0, 0x0d, 0x11, 0x94, 0x34, 0xc8,
0x24, 0x64, 0x34, 0x65, 0x44, 0xc3, 0xd8, 0x9e, 0xf9, 0xf5, 0x6b, 0x05, 0x87, 0x12, 0xd9, 0x12,
0x92, 0x0f, 0xb2, 0xc1, 0x23, 0x33, 0xc4, 0xa5, 0x1e, 0x03, 0x96, 0x01, 0x60, 0x49, 0x10, 0xe1,
0x00, 0xeb, 0x27, 0x59, 0xdd, 0xf9, 0x3a, 0xb2, 0xda, 0xe4, 0x5d, 0xc2, 0xc8, 0x9c, 0x4f, 0x49,
0x3a, 0x4d, 0xd8, 0x01, 0x12, 0xa0, 0x33, 0x1a, 0x08, 0x32, 0x64, 0x62, 0x30, 0x36, 0x3c, 0xbb,
0x09, 0xf4, 0x3c, 0x6b, 0x01, 0xcd, 0xe4, 0x98, 0xfb, 0x8e, 0x77, 0x7a, 0x72, 0x7e, 0xe1, 0x59,
0x58, 0x76, 0xb1, 0x24, 0x75, 0x16, 0x5b, 0x87, 0xaa, 0xba, 0x6a, 0x5c, 0x80, 0xf9, 0x6e, 0x39,
0x1e, 0x94, 0x5e, 0xa0, 0x5a, 0xe9, 0x20, 0xcd, 0x3f, 0x52, 0x1e, 0x7b, 0x99, 0x85, 0xc5, 0x99,
0xf3, 0xeb, 0xf9, 0xc9, 0xb1, 0x9d, 0x0a, 0x64, 0x22, 0x18, 0xce, 0x0d, 0x14, 0x84, 0xa3, 0x0f,
0x92, 0x99, 0xf0, 0xb7, 0x22, 0xbc, 0xd2, 0x03, 0xe9, 0x1d, 0x44, 0xd2, 0xc5, 0x63, 0xb1, 0xe4,
0x01, 0xe1, 0xeb, 0xe7, 0x0b, 0x24, 0x9a, 0xa9, 0xec, 0xef, 0x21, 0x7b, 0x1d, 0xb4, 0x19, 0x1a,
0x09, 0x0c, 0xa4, 0xd1, 0x44, 0x18, 0xde, 0x69, 0xc2, 0xd2, 0x94, 0x14, 0xe6, 0x8c, 0xfa, 0x62,
0x89, 0x4d, 0x96, 0x96, 0xe9, 0x08, 0xf2, 0x20, 0x81, 0xc6, 0x13, 0x8b, 0x3d, 0x12, 0x08, 0x9b,
0x5c, 0x8c, 0x59, 0x6c, 0x49, 0x47, 0x27, 0xf0, 0x84, 0x0e, 0xc4, 0x94, 0x86, 0x50, 0xf0, 0x42,
0x90, 0x0c, 0x31, 0xa4, 0xe6, 0x2a, 0x21, 0x63, 0x96, 0x48, 0x88, 0x00, 0xb2, 0x0b, 0x4b, 0x1d,
0xcf, 0xec, 0x04, 0x43, 0xe3, 0x69, 0x90, 0x1e, 0xd3, 0x63, 0x03, 0x8c, 0x33, 0x65, 0x1f, 0xc1,
0x0d, 0x85, 0x01, 0x0c, 0x99, 0xa6, 0xb9, 0x40, 0xde, 0x80, 0xee, 0x04, 0xec, 0x94, 0xb9, 0x8f,
0x2a, 0x28, 0x70, 0x02, 0x25, 0x1e, 0x60, 0x2f, 0xe7, 0xc0, 0xe6, 0x37, 0x8a, 0x25, 0xa8, 0xdf,
0xa8, 0x66, 0xa7, 0x78, 0x86, 0x58, 0x0d, 0xf0, 0x14, 0x10, 0x2f, 0x9a, 0xaf, 0x0c, 0xae, 0xde,
0x81, 0x51, 0x2d, 0x0d, 0x46, 0xcc, 0xf0, 0xa0, 0x52, 0x7c, 0xed, 0x99, 0xa6, 0x7d, 0x8b, 0x0e,
0x8a, 0x85, 0x20, 0xb5, 0x59, 0x13, 0x4e, 0x6b, 0xd5, 0x00, 0xfe, 0xb8, 0x02, 0x28, 0x10, 0xf0,
0x05, 0x74, 0xf2, 0xa6, 0x53, 0x03, 0xfd, 0xa6, 0x0e, 0x3a, 0xcb, 0xb2, 0xc2, 0xf0, 0xaa, 0x7b,
0x58, 0x68, 0x2e, 0x12, 0x26, 0xa6, 0x49, 0x4c, 0x58, 0x68, 0xcb, 0xa0, 0xf4, 0x19, 0x54, 0x64,
0x43, 0xc3, 0x63, 0x78, 0xba, 0x9b, 0xf6, 0x4c, 0x0b, 0x51, 0x97, 0xa9, 0xd0, 0x33, 0xed, 0x3c,
0x47, 0xba, 0x4f, 0xdb, 0x16, 0x0b, 0x4b, 0xdc, 0x82, 0x7f, 0x0c, 0xee, 0x00, 0xaf, 0x9a, 0x2f,
0xc4, 0x4a, 0x4c, 0x50, 0x1e, 0xb8, 0x15, 0x9d, 0xca, 0x67, 0x66, 0x47, 0x93, 0x55, 0x2a, 0x07,
0x10, 0xf3, 0x20, 0x9e, 0x86, 0xa1, 0x73, 0x2c, 0x6b, 0x09, 0x5c, 0xb0, 0x73, 0x64, 0xb1, 0xb9,
0xe6, 0x3c, 0x52, 0xfb, 0x50, 0xd7, 0x8a, 0x29, 0xe4, 0xe0, 0x85, 0x80, 0x56, 0x74, 0x93, 0x89,
0xa4, 0x12, 0x50, 0xdb, 0x58, 0x55, 0x8b, 0x8a, 0x87, 0xce, 0x03, 0xba, 0x84, 0x5d, 0x18, 0x21,
0x79, 0xc8, 0x6c, 0xc8, 0x20, 0x06, 0x42, 0x9a, 0x96, 0x92, 0x6d, 0x80, 0x11, 0x4f, 0x6f, 0x67,
0xae, 0xd1, 0x7c, 0x41, 0x7e, 0xba, 0xbe, 0x3e, 0xbd, 0x3c, 0x3b, 0xba, 0xbe, 0x26, 0x2f, 0x9a,
0x24, 0x66, 0x33, 0xf2, 0x01, 0x5d, 0xbc, 0x80, 0x7e, 0xd1, 0x66, 0xbb, 0xa0, 0x1f, 0xc1, 0x7f,
0x39, 0x3f, 0x39, 0x97, 0xf6, 0x66, 0x98, 0x76, 0x0a, 0x36, 0xc9, 0x8c, 0x96, 0xd5, 0x7e, 0x6b,
0x76, 0xb4, 0x16, 0x11, 0xd6, 0xab, 0xe8, 0x91, 0x65, 0xf8, 0x40, 0x57, 0x4c, 0xc5, 0x83, 0x5c,
0x42, 0x12, 0x7d, 0x5f, 0x15, 0x5b, 0xd6, 0x8e, 0xd2, 0xd7, 0x72, 0x91, 0x5a, 0xbf, 0x65, 0x19,
0x26, 0xdf, 0x09, 0x8d, 0x8f, 0xb7, 0x64, 0x42, 0xb0, 0x60, 0x55, 0xd3, 0x89, 0x5c, 0x94, 0xcf,
0xd3, 0xaf, 0x5f, 0x97, 0x73, 0x8b, 0x7c, 0x84, 0x13, 0xb6, 0xca, 0x13, 0x95, 0x67, 0xe4, 0x93,
0x29, 0x5e, 0xca, 0x27, 0x1b, 0x4c, 0xaa, 0xa5, 0x84, 0x9b, 0x88, 0xc1, 0x35, 0xb4, 0x3d, 0x5f,
0xbf, 0x1a, 0xcb, 0x32, 0x59, 0xb1, 0x52, 0x96, 0x24, 0x3c, 0x01, 0x1b, 0x2d, 0xd2, 0xc3, 0xa1,
0x4c, 0x00, 0x31, 0x64, 0x05, 0xd8, 0x6d, 0x13, 0xd9, 0x2a, 0xcd, 0x02, 0x31, 0x26, 0x58, 0xb1,
0x12, 0x35, 0x1d, 0xfc, 0x21, 0x55, 0x79, 0x02, 0x92, 0xc1, 0xf6, 0xb6, 0xb1, 0xdc, 0x5c, 0x59,
0x8a, 0x2d, 0x5c, 0x31, 0x20, 0xf8, 0x64, 0x10, 0x2e, 0xc0, 0x8c, 0x30, 0xb3, 0x69, 0x23, 0x90,
0x14, 0x0d, 0xef, 0x08, 0xbf, 0x30, 0xcd, 0xa6, 0x98, 0x76, 0x30, 0x82, 0x78, 0x16, 0x33, 0xb3,
0x04, 0x92, 0x22, 0x4b, 0x2e, 0xf0, 0x2c, 0x86, 0x99, 0x55, 0x72, 0x25, 0x6c, 0xf7, 0xd3, 0x0b,
0xfe, 0xe9, 0xd3, 0x97, 0x2f, 0x86, 0xbe, 0xcb, 0x9d, 0xcf, 0x7b, 0xbe, 0xd0, 0xc6, 0xf0, 0x85,
0x8a, 0xb1, 0x3d, 0x0c, 0x39, 0x10, 0xd0, 0x30, 0xcd, 0xdd, 0xd7, 0xad, 0x16, 0x98, 0xcc, 0x84,
0xfa, 0xb2, 0x91, 0x33, 0x76, 0x2c, 0xaf, 0xe5, 0x99, 0x99, 0xb3, 0x61, 0xcf, 0xdf, 0x70, 0x4f,
0xf3, 0x75, 0xdd, 0x36, 0xaf, 0x64, 0x69, 0x89, 0x53, 0x69, 0xc5, 0xb2, 0x88, 0x71, 0x51, 0xdc,
0xf2, 0x0a, 0x3c, 0x66, 0x08, 0x48, 0x3b, 0xf2, 0xc6, 0x4e, 0xf8, 0x2c, 0xb5, 0x43, 0x16, 0x8f,
0xc4, 0xb8, 0xdb, 0xea, 0x98, 0x6a, 0xd1, 0x67, 0xb0, 0x8f, 0x9d, 0x81, 0xdc, 0x5a, 0x66, 0xa7,
0xb4, 0x03, 0x1b, 0xf6, 0x1d, 0x51, 0x10, 0x9b, 0x81, 0xb6, 0x60, 0x05, 0xa6, 0xdb, 0x55, 0x1e,
0xca, 0x67, 0xaa, 0x62, 0xb2, 0x03, 0x70, 0xb0, 0x44, 0xe0, 0xc6, 0x35, 0xec, 0xa6, 0x35, 0x91,
0x33, 0xda, 0x12, 0xdd, 0x55, 0xd0, 0x7b, 0xea, 0x42, 0xbf, 0x10, 0xf8, 0xa4, 0xb5, 0xbd, 0xbd,
0xba, 0x8e, 0x71, 0xe3, 0x60, 0x69, 0xd1, 0xf1, 0x70, 0xcd, 0xb3, 0x26, 0x60, 0xa4, 0x6e, 0xc5,
0x72, 0x6b, 0xf0, 0x54, 0x1f, 0x94, 0x88, 0x8a, 0x55, 0x8d, 0xa9, 0x03, 0xec, 0x01, 0xcb, 0x31,
0x4b, 0x3e, 0x5d, 0x7c, 0xf9, 0xec, 0x7a, 0x4f, 0x48, 0xcd, 0x3f, 0xac, 0x36, 0x9f, 0x2f, 0x82,
0x4c, 0xd6, 0x8b, 0x1b, 0x20, 0xe4, 0xe9, 0x1e, 0x80, 0xd2, 0xe5, 0xb4, 0xac, 0x98, 0xb7, 0x9e,
0x2f, 0xf0, 0x9b, 0x0f, 0x89, 0x3c, 0x8f, 0xeb, 0xa9, 0x7e, 0xcb, 0x3b, 0xc8, 0x2f, 0x1c, 0x0f,
0x07, 0x60, 0x5e, 0xb6, 0x85, 0x05, 0xe9, 0x16, 0x78, 0x0a, 0x72, 0xb1, 0x45, 0x94, 0x07, 0xc3,
0x6e, 0xdc, 0x06, 0xf7, 0x3c, 0x96, 0x48, 0xdd, 0xad, 0xb5, 0x3e, 0x75, 0xab, 0xfb, 0x20, 0xcf,
0x85, 0x23, 0x83, 0x50, 0xbe, 0x7e, 0xf5, 0xbc, 0x7b, 0xf8, 0x87, 0x64, 0x29, 0x6d, 0x06, 0x95,
0xad, 0x8e, 0x00, 0x6c, 0xd7, 0x94, 0x94, 0xe9, 0xfb, 0xf9, 0x05, 0x1d, 0xa1, 0xbe, 0xd0, 0xb5,
0x01, 0x0e, 0xb2, 0x96, 0xfc, 0x46, 0xa7, 0x3e, 0xba, 0x05, 0x08, 0xf4, 0x70, 0x06, 0x02, 0x87,
0x30, 0x81, 0x95, 0x34, 0xf8, 0x16, 0xd8, 0x10, 0xb3, 0xc1, 0x96, 0x01, 0x8b, 0x9d, 0x82, 0xdd,
0x0d, 0x84, 0x81, 0x99, 0x19, 0xcd, 0xb5, 0x98, 0x02, 0x14, 0x81, 0xab, 0xaa, 0xc6, 0xb6, 0x0a,
0x37, 0xe5, 0xbc, 0xa3, 0x80, 0x5a, 0xf6, 0xca, 0xea, 0x9e, 0x9d, 0x9e, 0x59, 0x6e, 0x02, 0x47,
0xf9, 0x86, 0x2d, 0xbb, 0x7a, 0x4b, 0xd9, 0xb1, 0xd7, 0x72, 0xb3, 0xa7, 0xb8, 0x29, 0xfa, 0xec,
0x5a, 0xa0, 0x57, 0xbd, 0xd2, 0x4f, 0x57, 0x1a, 0x6f, 0x88, 0x44, 0x90, 0x91, 0x96, 0xb2, 0xb8,
0x69, 0x81, 0x43, 0xf9, 0xae, 0x32, 0x0d, 0x2d, 0x08, 0x88, 0x6b, 0x3a, 0x6e, 0xb6, 0x0b, 0x0a,
0x4c, 0x7d, 0xd7, 0x15, 0x19, 0x00, 0x64, 0x96, 0x68, 0xaa, 0xa2, 0x42, 0xc7, 0xbd, 0x1a, 0xf3,
0x69, 0x92, 0x5a, 0x51, 0x10, 0x4f, 0x05, 0x4b, 0x7b, 0x39, 0x22, 0x3b, 0x85, 0x72, 0x0a, 0x6a,
0x45, 0xa8, 0xdf, 0xec, 0x88, 0x4e, 0x0c, 0x95, 0xbc, 0x8b, 0x24, 0xb6, 0x53, 0x10, 0x96, 0xdb,
0x5f, 0x60, 0x54, 0x7a, 0xa9, 0x71, 0xbc, 0x78, 0xdd, 0xaa, 0x63, 0x03, 0xb6, 0x98, 0x19, 0x1c,
0x6f, 0x89, 0x11, 0x29, 0xfe, 0xef, 0x67, 0x63, 0xf7, 0xbf, 0x67, 0x63, 0x17, 0xd9, 0xc8, 0x79,
0xa8, 0xe8, 0xb3, 0x14, 0xea, 0xde, 0xb7, 0x08, 0x75, 0x6f, 0x49, 0xa8, 0xa5, 0xc6, 0x4b, 0x34,
0xaf, 0xbe, 0x05, 0xcd, 0x2b, 0x44, 0x53, 0x4d, 0x25, 0xd5, 0x74, 0x25, 0xe3, 0xaa, 0x0a, 0xda,
0x45, 0x8e, 0xec, 0xac, 0x59, 0x87, 0xa2, 0x71, 0x7f, 0x81, 0x22, 0x6b, 0x92, 0xcf, 0x38, 0x86,
0x64, 0x3a, 0xab, 0x78, 0xe9, 0x6d, 0xe3, 0xfc, 0xc8, 0x5b, 0xef, 0x5b, 0x2a, 0xd9, 0x51, 0xea,
0x04, 0xab, 0x93, 0x53, 0xb0, 0x14, 0x0b, 0x69, 0xe3, 0x45, 0xcf, 0xad, 0x29, 0x62, 0x72, 0x1d,
0x5d, 0x40, 0xaa, 0xbe, 0x9a, 0x43, 0xaf, 0x66, 0x45, 0x50, 0x9a, 0x8f, 0x21, 0xd5, 0xcf, 0x7b,
0x6e, 0x8e, 0x22, 0x07, 0x6a, 0x2c, 0x2b, 0xd2, 0x92, 0x7a, 0xd7, 0x6a, 0xb7, 0x94, 0x03, 0xba,
0xad, 0x9e, 0x9b, 0x13, 0xbc, 0x47, 0xff, 0x16, 0x9b, 0xf0, 0xc1, 0xd8, 0xad, 0xa4, 0x47, 0x3c,
0xaa, 0x7d, 0x79, 0x71, 0x68, 0x94, 0x0c, 0x34, 0xda, 0xc8, 0x82, 0xb5, 0x4e, 0xc0, 0x6c, 0x62,
0xa9, 0xd6, 0x31, 0xd6, 0x6a, 0xc9, 0xbf, 0xde, 0x6d, 0x48, 0xbe, 0x40, 0xde, 0x79, 0x01, 0x98,
0x81, 0xf4, 0xf9, 0xcd, 0xf6, 0xf6, 0x7d, 0x75, 0x0e, 0x94, 0x69, 0xe0, 0x06, 0xd5, 0x82, 0xbc,
0x88, 0xa8, 0x7f, 0x4e, 0xa1, 0xe4, 0x3b, 0x97, 0xc1, 0x90, 0x27, 0xef, 0xc2, 0x50, 0x47, 0x53,
0xbb, 0x00, 0xd5, 0x39, 0x15, 0xec, 0xaf, 0x75, 0xb0, 0xa9, 0xe6, 0x72, 0x36, 0xd5, 0xf8, 0xf5,
0x36, 0x90, 0xcf, 0xc0, 0x16, 0x9b, 0xf0, 0xca, 0xe2, 0x5a, 0x73, 0xf3, 0x0b, 0xb2, 0x06, 0x95,
0xe0, 0x37, 0x33, 0x6f, 0xa5, 0x13, 0x77, 0x91, 0xad, 0x27, 0x94, 0x25, 0x7c, 0x26, 0x84, 0x0b,
0xb5, 0x4f, 0xb9, 0x59, 0x21, 0x41, 0xa5, 0xb9, 0xaa, 0xbd, 0x76, 0x58, 0x98, 0x42, 0xdb, 0xb9,
0x0c, 0xbf, 0x5a, 0x28, 0x4b, 0x87, 0xba, 0xab, 0x76, 0x2c, 0xf7, 0x97, 0xd3, 0xeb, 0xf6, 0xf1,
0xff, 0x6b, 0x47, 0x57, 0x38, 0xb0, 0xa0, 0xad, 0x73, 0xee, 0xb2, 0x25, 0xe3, 0x59, 0x63, 0x72,
0x83, 0x0d, 0x65, 0xab, 0xb2, 0xb0, 0x65, 0xbc, 0x4f, 0xff, 0x01, 0xa5, 0xb2, 0x34, 0x43, 0x4f,
0x37, 0xde, 0xf2, 0xbd, 0x46, 0x0e, 0xa2, 0x1c, 0x0d, 0x9e, 0x41, 0x52, 0xed, 0xa4, 0x93, 0xab,
0xc0, 0xef, 0xe9, 0xa7, 0x2a, 0x7a, 0xa9, 0x6b, 0x59, 0xb6, 0x94, 0x85, 0x0a, 0x96, 0xd8, 0x6b,
0xa0, 0x32, 0xde, 0xcc, 0x58, 0x72, 0x48, 0x53, 0xd0, 0x8c, 0x82, 0x86, 0x4a, 0x4b, 0x75, 0x81,
0xab, 0xed, 0xa2, 0x96, 0xb6, 0x99, 0x9d, 0xf4, 0xff, 0x00, 0x6b, 0xb1, 0x6f, 0xd8, 0x3c, 0x05,
0x9c, 0xb9, 0x75, 0x43, 0xed, 0x06, 0xf5, 0x9c, 0xb1, 0xe6, 0xab, 0x93, 0xff, 0xb9, 0x2a, 0x80,
0xa6, 0x12, 0xf8, 0xc1, 0x92, 0x0d, 0x16, 0xf5, 0xae, 0xaa, 0xb0, 0xba, 0x8b, 0x5c, 0x62, 0x4f,
0x2b, 0x06, 0xb9, 0xbd, 0xad, 0xcd, 0x7b, 0x83, 0x52, 0xcc, 0x8d, 0x7e, 0x68, 0x5a, 0x95, 0x13,
0xe6, 0xed, 0xef, 0xaa, 0x73, 0xae, 0x0e, 0x4f, 0xa5, 0x12, 0x71, 0xea, 0x2a, 0x59, 0x95, 0xb1,
0x79, 0x69, 0x2c, 0xab, 0xfb, 0xe2, 0x02, 0xc2, 0xc6, 0xab, 0xa2, 0x16, 0x5f, 0x40, 0x46, 0x80,
0xee, 0xc1, 0x3b, 0xe6, 0x12, 0x07, 0x51, 0x85, 0x17, 0xf2, 0xaa, 0x3b, 0xf8, 0x2c, 0x47, 0xef,
0xae, 0x60, 0xb8, 0x6a, 0xf5, 0x3a, 0x0f, 0x75, 0xe6, 0x5c, 0xd0, 0xef, 0x53, 0x11, 0x07, 0x1e,
0x44, 0x03, 0xf4, 0xc2, 0x68, 0x94, 0xab, 0x0a, 0xa9, 0x66, 0xc8, 0x56, 0xd1, 0xe0, 0x1f, 0x68,
0xe6, 0xf5, 0xf8, 0x38, 0x9d, 0x0e, 0x06, 0x2c, 0x4d, 0x87, 0xd3, 0xd0, 0x26, 0x7a, 0x88, 0x18,
0xd1, 0xb9, 0x9e, 0x21, 0xda, 0x9e, 0xe9, 0x2c, 0x83, 0x0f, 0x29, 0x20, 0xf4, 0x1d, 0xe2, 0xbd,
0x2c, 0x50, 0xaa, 0x49, 0x82, 0xee, 0x09, 0x0b, 0xd1, 0x30, 0x31, 0xe3, 0xc9, 0x0d, 0x91, 0x7d,
0x21, 0xf1, 0xa7, 0x72, 0x0c, 0xa9, 0xb4, 0x00, 0x1a, 0x2d, 0xf3, 0x76, 0xf1, 0x8a, 0xc2, 0x08,
0xcc, 0xc5, 0x63, 0x04, 0x8c, 0x21, 0xd8, 0x3f, 0x9a, 0x56, 0xcc, 0x42, 0x27, 0xa8, 0x9b, 0x41,
0xd6, 0xbc, 0x34, 0x91, 0xea, 0x52, 0xe3, 0x3d, 0x3d, 0x2d, 0xf6, 0x3e, 0xf2, 0x04, 0x8c, 0x05,
0xb8, 0xf4, 0xce, 0xd8, 0x2d, 0xb0, 0xc5, 0xe0, 0xea, 0x12, 0x50, 0x7b, 0x38, 0x2d, 0xf7, 0x7a,
0x16, 0x4e, 0x5e, 0x63, 0xe6, 0x1f, 0x72, 0x1f, 0xc1, 0xd1, 0x7f, 0xad, 0xe5, 0x8f, 0x9e, 0x34,
0xb0, 0xa2, 0x41, 0xbf, 0xc0, 0x3e, 0x5c, 0x4e, 0x6f, 0x35, 0x7d, 0x42, 0xe1, 0x7a, 0x0f, 0x5f,
0xf2, 0x24, 0xf2, 0x25, 0x8f, 0xa6, 0x9f, 0xe2, 0x80, 0x30, 0xd5, 0x9c, 0xd9, 0x4f, 0x9e, 0xa8,
0xd1, 0xe3, 0xc9, 0xdf, 0x71, 0xe0, 0x28, 0x67, 0xc8, 0x16, 0xb4, 0xf4, 0x2c, 0x26, 0x43, 0x8e,
0xbf, 0x8f, 0xc0, 0x6b, 0xa2, 0x86, 0x97, 0x29, 0xe8, 0x32, 0x9f, 0xed, 0x3c, 0x5e, 0x78, 0x1e,
0x5e, 0xcb, 0x19, 0xf4, 0xb5, 0x60, 0xd1, 0x44, 0xce, 0x0c, 0xad, 0xc7, 0xa4, 0xad, 0xa3, 0x84,
0x1a, 0x56, 0x16, 0x09, 0xd3, 0x6d, 0x75, 0x82, 0xfd, 0xbd, 0x4e, 0xf0, 0xf2, 0xa5, 0xb9, 0xa8,
0x9a, 0x9f, 0x66, 0x0d, 0xcb, 0xbf, 0x53, 0x10, 0x59, 0x00, 0x21, 0x18, 0x84, 0xcb, 0xc3, 0x5b,
0x68, 0xb2, 0x74, 0x79, 0xc9, 0xa7, 0x22, 0x5f, 0xb3, 0xda, 0x38, 0x81, 0xb0, 0xb4, 0xb9, 0xab,
0x37, 0x69, 0x04, 0x7a, 0xcc, 0x97, 0xed, 0xac, 0xb9, 0xe7, 0xc0, 0x55, 0xc5, 0x5e, 0xa0, 0x3d,
0xcc, 0x7e, 0x8f, 0x7f, 0x8f, 0x95, 0xb2, 0x50, 0x27, 0x6b, 0x8f, 0x2b, 0x43, 0xe5, 0x39, 0x94,
0x5d, 0xb9, 0xd2, 0x63, 0x68, 0xb1, 0xcb, 0x9d, 0xa0, 0xe6, 0x19, 0x2a, 0xd7, 0xe7, 0x31, 0x23,
0x06, 0xf8, 0xd5, 0x1f, 0xd3, 0x54, 0x80, 0x7e, 0x4b, 0x13, 0x00, 0x61, 0xdf, 0x32, 0x32, 0x8d,
0xf5, 0xb9, 0x22, 0xe6, 0x9b, 0xa0, 0x77, 0xab, 0x3c, 0x66, 0xa3, 0x6d, 0xea, 0x00, 0x54, 0xda,
0x27, 0xd0, 0x77, 0x55, 0x9a, 0x30, 0x1e, 0x53, 0x3b, 0x7a, 0x02, 0xa9, 0xb2, 0xb5, 0x1a, 0x2b,
0x42, 0x72, 0xd6, 0x0c, 0x3d, 0x30, 0x61, 0x82, 0xbe, 0x6f, 0x70, 0x83, 0x21, 0x05, 0xfc, 0x43,
0xe1, 0x71, 0x70, 0xd0, 0x64, 0xad, 0x1e, 0xab, 0xd1, 0xce, 0x56, 0x97, 0x5c, 0x58, 0xdc, 0xde,
0x7e, 0xd4, 0x83, 0x32, 0xa1, 0x1c, 0x00, 0x2a, 0x01, 0x9f, 0xdd, 0x39, 0x81, 0x85, 0xa7, 0x74,
0x80, 0x37, 0x0c, 0x3f, 0xb5, 0x76, 0x59, 0x54, 0x76, 0x79, 0xdb, 0xf0, 0x7c, 0xf1, 0xf6, 0x65,
0x90, 0x61, 0x5a, 0xc2, 0x55, 0xc8, 0xeb, 0x95, 0x12, 0xc0, 0x5d, 0x39, 0xe2, 0x52, 0xbb, 0xa4,
0x26, 0xcb, 0xa6, 0xcc, 0x48, 0x2b, 0x95, 0x63, 0x85, 0x20, 0x94, 0x22, 0x80, 0xbf, 0xb7, 0x8a,
0x09, 0x63, 0xd4, 0x63, 0x16, 0x10, 0x90, 0x02, 0xbe, 0x4b, 0x1a, 0x0f, 0xd7, 0x10, 0xdf, 0xd5,
0x1c, 0xe8, 0x96, 0xf4, 0xbe, 0x32, 0x1e, 0x52, 0xc7, 0x23, 0x5a, 0x11, 0x8b, 0xcb, 0x58, 0x26,
0x95, 0xa9, 0x5e, 0x94, 0xbb, 0x5e, 0xf1, 0x3b, 0x00, 0xa2, 0xdf, 0xed, 0x47, 0xe8, 0x18, 0x87,
0x10, 0xf4, 0x71, 0x0c, 0xf9, 0xf4, 0xc9, 0x13, 0xaf, 0x56, 0xe5, 0x75, 0x7e, 0x71, 0xa0, 0x91,
0xbe, 0x74, 0xbd, 0xb5, 0x08, 0xe5, 0x90, 0x63, 0x2e, 0x48, 0x19, 0x58, 0x7e, 0x8f, 0x3d, 0x67,
0x23, 0xf8, 0xf3, 0xd5, 0x20, 0x03, 0x31, 0xd0, 0xeb, 0xa8, 0x80, 0xa9, 0x37, 0x7e, 0x53, 0xed,
0xb6, 0xf6, 0x46, 0xfa, 0xc1, 0x77, 0x1b, 0x21, 0x1f, 0xd5, 0xbc, 0xd8, 0x10, 0xe3, 0x04, 0x32,
0xe2, 0x91, 0x0a, 0x23, 0x79, 0x7d, 0x92, 0x03, 0x90, 0x19, 0x4d, 0xe5, 0x7c, 0x9c, 0xdf, 0x78,
0x4a, 0xbe, 0xfd, 0x90, 0xf7, 0x57, 0x5f, 0x7e, 0xe0, 0x9a, 0x61, 0x5a, 0x10, 0x95, 0xdd, 0xfb,
0xa6, 0x06, 0x16, 0xc8, 0x3a, 0xc2, 0xb7, 0x0e, 0x3e, 0xde, 0xb9, 0xe5, 0x14, 0x1b, 0x43, 0xf9,
0x88, 0x89, 0x7c, 0xb2, 0xb0, 0x3a, 0x83, 0x7e, 0xbe, 0xb8, 0xf2, 0x7e, 0x7d, 0x77, 0x0c, 0x15,
0xc4, 0xc7, 0xa3, 0xf7, 0xf0, 0xf9, 0xe5, 0xdd, 0x19, 0x7c, 0xbe, 0x3b, 0x3d, 0x93, 0xd7, 0xff,
0x84, 0xcf, 0x5f, 0x2f, 0x8f, 0xe5, 0xe7, 0x67, 0x5c, 0xbf, 0xfc, 0x19, 0x3e, 0xcf, 0x8f, 0x4e,
0xe1, 0xf3, 0xe4, 0x10, 0xcc, 0xcc, 0x3b, 0x3e, 0xf9, 0x0d, 0xab, 0x8f, 0xa3, 0x43, 0xaf, 0x77,
0xa5, 0x49, 0x7d, 0xc1, 0x5e, 0xde, 0x30, 0x7b, 0x80, 0x5b, 0xaf, 0x7c, 0x84, 0xc2, 0xe3, 0x9f,
0xa0, 0x14, 0x10, 0x72, 0x63, 0x95, 0xb1, 0x4f, 0x38, 0x07, 0xaa, 0xe7, 0x6c, 0x19, 0xf0, 0x8b,
0x9a, 0x12, 0xd5, 0x81, 0x7a, 0xd6, 0x34, 0x09, 0xdd, 0xcb, 0xb3, 0xcf, 0xf6, 0x00, 0x8a, 0x50,
0xc1, 0x54, 0x67, 0x02, 0xf7, 0x06, 0x4a, 0x0e, 0xb4, 0x5d, 0xf6, 0xb9, 0x0a, 0x40, 0x4f, 0x3e,
0x0d, 0x8f, 0x82, 0xd4, 0xa9, 0x3d, 0x4e, 0xd8, 0xd0, 0x05, 0x14, 0x16, 0xb5, 0x73, 0xad, 0xe3,
0x1b, 0x73, 0x9e, 0xd0, 0x11, 0x03, 0x86, 0x97, 0x44, 0x9b, 0xe1, 0xef, 0x29, 0xbc, 0xb2, 0xeb,
0x47, 0xe7, 0xb1, 0xf1, 0x27, 0x80, 0xb1, 0x7f, 0x38, 0x0e, 0x42, 0xdf, 0xa0, 0x40, 0xcf, 0x96,
0x73, 0x52, 0xc3, 0x5c, 0x01, 0x53, 0xf1, 0xa1, 0x00, 0x43, 0x86, 0x13, 0x76, 0xcb, 0x6f, 0x2a,
0x0c, 0x03, 0x17, 0xc5, 0x6b, 0x0e, 0x34, 0x99, 0xb5, 0x44, 0x54, 0xfc, 0x2c, 0x42, 0x97, 0xc4,
0x90, 0x7f, 0x24, 0x5c, 0x96, 0xcd, 0x20, 0xcc, 0x83, 0xa8, 0xb8, 0xe2, 0xbf, 0x62, 0xdb, 0x9d,
0xfd, 0xa6, 0xfe, 0x31, 0xc2, 0x7e, 0x53, 0xfd, 0x76, 0xb1, 0x29, 0x7f, 0xce, 0xfd, 0x1f, 0x3e,
0xec, 0xfa, 0xfe, 0xde, 0x2d, 0x00, 0x00,
};
const unsigned int html_content_gz_len = 3911;
#endif // HTML_CONTENT_GZ_H

File diff suppressed because one or more lines are too long

View File

@@ -469,22 +469,32 @@ static esp_err_t cmd_post_handler(httpd_req_t *req) {
rf_433_cancel_learn_keycode();
}
} else if (strcmp(cmd->valuestring, "rf_status") == 0) {
// Return current RF button codes (just the 32-bit values)
// Return current temp RF button codes (from temp storage, not params)
int head = 0;
head += sprintf(httpBuffer, "{\"codes\":[");
for (uint8_t i = 0; i < NUM_RF_BUTTONS; i++) {
if (i > 0) head += sprintf(httpBuffer+head, ",");
int64_t code = get_param_value_t(PARAM_KEYCODE_0 + i).i64;
// Return just the code as uint32
head += sprintf(httpBuffer+head, "%lu", (unsigned long)(uint32_t)code);
int64_t code = rf_433_get_temp_keycode(i);
head += sprintf(httpBuffer+head, "%ld", (long)code);
}
head += sprintf(httpBuffer+head, "]}");
httpd_resp_set_type(req, "application/json");
return httpd_resp_send(req, httpBuffer, head);
} else if (strcmp(cmd->valuestring, "rf_clear_temp") == 0) {
rf_433_clear_temp_keycodes();
ESP_LOGI(TAG, "RF temp keycodes cleared");
} else if (strcmp(cmd->valuestring, "rf_set_temp") == 0) {
// Set a temp keycode (for skipping)
cJSON *index = cJSON_GetObjectItem(root, "index");
cJSON *code = cJSON_GetObjectItem(root, "code");
if (cJSON_IsNumber(index) && cJSON_IsNumber(code)) {
rf_433_set_temp_keycode(index->valueint, (int64_t)code->valuedouble);
ESP_LOGI(TAG, "RF temp keycode %d set to %ld", index->valueint, (long)(int64_t)code->valuedouble);
}
} else if (strcmp(cmd->valuestring, "rf_disable") == 0) {
rf_433_disable_controls();
ESP_LOGI(TAG, "RF controls disabled");