Move most of settings to new page in /ui to save memory (#1028)

This commit is contained in:
Darrell 2023-09-02 22:47:31 -04:00 committed by GitHub
parent cb710a4c69
commit 41403b4b07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 2474 additions and 1439 deletions

View File

@ -18,7 +18,7 @@ check_skip_packages = yes
extends = env
platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.07.00/platform-espressif32.zip
platform_packages =
debug_build_flags = -O0 -ggdb3 -g3 -DDEBUG_TLS_MEM
debug_build_flags = -Og -ggdb3 -g3 -DDEBUG_TLS_MEM
build_flags =
-free
-fipa-pta

View File

@ -41,7 +41,6 @@ namespace AHTX0
void ConnectToWifi()
{
AsyncWiFiSettings.html("h4", "AHTX0 - Temperature + Humidity Sensor:");
AHTX0_I2c_Bus = AsyncWiFiSettings.integer("AHTX0_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
AHTX0_I2c = AsyncWiFiSettings.string("AHTX0_I2c", "", "I2C address (0x38 or 0x39)");
}

View File

@ -74,7 +74,6 @@ namespace BH1750
void ConnectToWifi()
{
AsyncWiFiSettings.html("h4", "BH1750 - Ambient Light Sensor:");
BH1750_I2c_Bus = AsyncWiFiSettings.integer("BH1750_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
BH1750_I2c = AsyncWiFiSettings.string("BH1750_I2c", "", "I2C address (0x23 or 0x5C)");
}

View File

@ -52,7 +52,6 @@ namespace BME280
void ConnectToWifi()
{
AsyncWiFiSettings.html("h4", "BME280 - Humidity + Temp + Pressure Sensor:");
BME280_I2c_Bus = AsyncWiFiSettings.integer("BME280_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
BME280_I2c = AsyncWiFiSettings.string("BME280_I2c", "", "I2C address (0x76 or 0x77)");
}

View File

@ -39,7 +39,6 @@ namespace BMP180
void ConnectToWifi()
{
AsyncWiFiSettings.html("h4", "BMP085/BMP180 - Barometric Pressure + Temperature:");
BMP180_I2c_Bus = AsyncWiFiSettings.integer("BMP180_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
BMP180_I2c = AsyncWiFiSettings.string("BMP180_I2c", "", "I2C address (0x77)");
}

View File

@ -48,7 +48,6 @@ namespace BMP280
void ConnectToWifi()
{
AsyncWiFiSettings.html("h4", "BMP280 - Barometric Pressure + Temperature Sensor:");
BMP280_I2c_Bus = AsyncWiFiSettings.integer("BMP280_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
BMP280_I2c = AsyncWiFiSettings.string("BMP280_I2c", "", "I2C address (0x76 or 0x77)");
}

View File

@ -30,14 +30,12 @@ void Setup() {
}
void ConnectToWifi() {
AsyncWiFiSettings.html("h4", "Button One:");
std::vector<String> pinTypes = {"Pullup", "Pullup Inverted", "Pulldown", "Pulldown Inverted", "Floating", "Floating Inverted"};
button_1Type = AsyncWiFiSettings.dropdown("button_1_type", pinTypes, 0, "Button One pin type");
button_1Pin = AsyncWiFiSettings.integer("button_1_pin", -1, "Button One pin (-1 for disable)");
button_1Timeout = AsyncWiFiSettings.floating("button_1_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Button One timeout (in seconds)");
button_1Detected = button_1Type & 0x01 ? LOW : HIGH;
AsyncWiFiSettings.html("h4", "Button Two:");
button_2Type = AsyncWiFiSettings.dropdown("button_2_type", pinTypes, 0, "Button Two pin type");
button_2Pin = AsyncWiFiSettings.integer("button_2_pin", -1, "Button Two pin (-1 for disable)");
button_2Timeout = AsyncWiFiSettings.floating("button_2_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Button Two timeout (in seconds)");

View File

@ -106,7 +106,6 @@ namespace DHT
void ConnectToWifi()
{
AsyncWiFiSettings.html("h4", "DHT:");
dht11Pin = AsyncWiFiSettings.integer("dht11_pin", -1, "DHT11 sensor pin (-1 for disable)");
dht22Pin = AsyncWiFiSettings.integer("dht22_pin", -1, "DHT22 sensor pin (-1 for disable)");
dhtTempOffset = AsyncWiFiSettings.floating("dhtTemp_offset", -40, 125, 0.0, "DHT temperature offset");

View File

@ -13,7 +13,7 @@
#include <Ticker.h>
namespace DS18B20
namespace DS18B20
{
int ds18b20Pin = -1;
float dsTempOffset;
@ -108,7 +108,6 @@ namespace DS18B20
void ConnectToWifi()
{
AsyncWiFiSettings.html("h4", "DS18B20:");
ds18b20Pin = AsyncWiFiSettings.integer("ds18b20_pin", -1, "DS18B20 sensor pin (-1 for disable)");
dsTempOffset = AsyncWiFiSettings.floating("dsTemp_offset", -40, 125, 0.0, "DS18B20 temperature offset");
}

View File

@ -26,7 +26,6 @@ namespace HX711
void ConnectToWifi()
{
AsyncWiFiSettings.html("h4", "HX711 - Weight Sensor:");
sckPin = AsyncWiFiSettings.integer("HX711_sckPin", 0, "HX711 SCK (Clock) pin");
doutPin = AsyncWiFiSettings.integer("HX711_doutPin", 0, "HX711 DOUT (Data) pin");
}

View File

@ -20,13 +20,9 @@ int I2C_Bus_2_SCL = 0;
void ConnectToWifi() {
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#i2c-settings' target='_blank'>I2C Settings</a>", false);
AsyncWiFiSettings.html("h4", "Bus 1:");
I2C_Bus_1_SDA = AsyncWiFiSettings.integer("I2C_Bus_1_SDA", -1, 39, DEFAULT_I2C_BUS_1_SDA, "SDA pin (-1 to disable)");
I2C_Bus_1_SCL = AsyncWiFiSettings.integer("I2C_Bus_1_SCL", -1, 39, DEFAULT_I2C_BUS_1_SCL, "SCL pin (-1 to disable)");
AsyncWiFiSettings.html("h4", "Bus 2:");
I2C_Bus_2_SDA = AsyncWiFiSettings.integer("I2C_Bus_2_SDA", -1, 39, DEFAULT_I2C_BUS_2_SDA, "SDA pin (-1 to disable)");
I2C_Bus_2_SCL = AsyncWiFiSettings.integer("I2C_Bus_2_SCL", -1, 39, DEFAULT_I2C_BUS_2_SCL, "SCL pin (-1 to disable)");

View File

@ -36,22 +36,16 @@ void ConnectToWifi() {
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#leds' target='_blank'>LEDs</a>", false);
AsyncWiFiSettings.html("h4", "LED 1:");
led_1_type = AsyncWiFiSettings.dropdown("led_1_type", ledTypes, DEFAULT_LED1_TYPE, "LED Type");
led_1_pin = AsyncWiFiSettings.integer("led_1_pin", -1, 39, DEFAULT_LED1_PIN, "Pin (-1 to disable)");
led_1_cnt = AsyncWiFiSettings.integer("led_1_cnt", -1, 39, DEFAULT_LED1_CNT, "Count (only applies to Addressable LEDs)");
led_1_cntrl = (ControlType)AsyncWiFiSettings.dropdown("led_1_cntrl", ledControlTypes, DEFAULT_LED1_CNTRL, "LED Control");
AsyncWiFiSettings.html("h4", "LED 2:");
led_2_type = AsyncWiFiSettings.dropdown("led_2_type", ledTypes, 0, "LED Type");
led_2_pin = AsyncWiFiSettings.integer("led_2_pin", -1, 39, -1, "Pin (-1 to disable)");
led_2_cnt = AsyncWiFiSettings.integer("led_2_cnt", -1, 39, 1, "Count (only applies to Addressable LEDs)");
led_2_cntrl = (ControlType)AsyncWiFiSettings.dropdown("led_2_cntrl", ledControlTypes, 0, "LED Control");
AsyncWiFiSettings.html("h4", "LED 3:");
led_3_type = AsyncWiFiSettings.dropdown("led_3_type", ledTypes, 0, "LED Type");
led_3_pin = AsyncWiFiSettings.integer("led_3_pin", -1, 39, -1, "Pin (-1 to disable)");
led_3_cnt = AsyncWiFiSettings.integer("led_3_cnt", -1, 39, 1, "Count (only applies to Addressable LEDs)");

View File

@ -30,14 +30,12 @@ void Setup() {
}
void ConnectToWifi() {
AsyncWiFiSettings.html("h4", "PIR:");
std::vector<String> pinTypes = {"Pullup", "Pullup Inverted", "Pulldown", "Pulldown Inverted", "Floating", "Floating Inverted"};
pirType = AsyncWiFiSettings.dropdown("pir_type", pinTypes, 0, "PIR motion pin type");
pirPin = AsyncWiFiSettings.integer("pir_pin", -1, "PIR motion pin (-1 for disable)");
pirTimeout = AsyncWiFiSettings.floating("pir_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "PIR motion timeout (in seconds)");
pirDetected = pirType & 0x01 ? LOW : HIGH;
AsyncWiFiSettings.html("h4", "Radar:");
radarType = AsyncWiFiSettings.dropdown("radar_type", pinTypes, 0, "Radar motion pin type");
radarPin = AsyncWiFiSettings.integer("radar_pin", -1, "Radar motion pin (-1 for disable)");
radarTimeout = AsyncWiFiSettings.floating("radar_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Radar motion timeout (in seconds)");

View File

@ -30,7 +30,6 @@ void Setup() {
}
void ConnectToWifi() {
AsyncWiFiSettings.html("h4", "SHTC1/3, SHTW1/2, SHT3x/4x, SHT85 - Temperature and Humidity Sensor:");
bus = AsyncWiFiSettings.integer("SHT_I2c_Bus", 1, 2, -1, "I2C Bus (-1 to disable)");
}

View File

@ -37,7 +37,6 @@ void Setup() {
}
void ConnectToWifi() {
AsyncWiFiSettings.html("h4", "SGP30 - Air Quality Sensor:");
SGP30_I2c_Bus = AsyncWiFiSettings.integer("SGP30_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
SGP30_I2c = AsyncWiFiSettings.string("SGP30_I2c", "", "I2C address (0x58)");
}

View File

@ -30,14 +30,12 @@ void Setup() {
}
void ConnectToWifi() {
AsyncWiFiSettings.html("h4", "Switch One:");
std::vector<String> pinTypes = {"Pullup", "Pullup Inverted", "Pulldown", "Pulldown Inverted", "Floating", "Floating Inverted"};
switch_1Type = AsyncWiFiSettings.dropdown("switch_1_type", pinTypes, 0, "Switch One pin type");
switch_1Pin = AsyncWiFiSettings.integer("switch_1_pin", -1, "Switch One pin (-1 for disable)");
switch_1Timeout = AsyncWiFiSettings.floating("switch_1_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Switch One timeout (in seconds)");
switch_1Detected = switch_1Type & 0x01 ? LOW : HIGH;
AsyncWiFiSettings.html("h4", "Switch Two:");
switch_2Type = AsyncWiFiSettings.dropdown("switch_2_type", pinTypes, 0, "Switch Two pin type");
switch_2Pin = AsyncWiFiSettings.integer("switch_2_pin", -1, "Switch Two pin (-1 for disable)");
switch_2Timeout = AsyncWiFiSettings.floating("switch_2_timeout", 0, 300, DEFAULT_DEBOUNCE_TIMEOUT, "Switch Two timeout (in seconds)");

View File

@ -23,7 +23,6 @@ namespace TSL2561
void ConnectToWifi()
{
AsyncWiFiSettings.html("h4", "TSL2561 - Ambient Light Sensor:");
TSL2561_I2c_Bus = AsyncWiFiSettings.integer("TSL2561_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
TSL2561_I2c = AsyncWiFiSettings.string("TSL2561_I2c", "", "I2C address (0x39, 0x49 or 0x29)");
TSL2561_I2c_Gain = AsyncWiFiSettings.string("TSL2561_I2c_Gain", DEFAULT_TSL2561_I2C_GAIN, "Gain (auto, 1x or 16x)");

View File

@ -7,7 +7,7 @@
// Number of seconds to wait for a Station Wifi connection to be established
#ifndef DEFAULT_WIFI_TIMEOUT
#define DEFAULT_WIFI_TIMEOUT 120
#define DEFAULT_WIFI_TIMEOUT 60
#endif
// Number of seconds to keep up captive portal (SoftAP) before rebooting

View File

@ -146,34 +146,33 @@ void setupNetwork() {
discovery = AsyncWiFiSettings.checkbox("discovery", true, "Send to discovery topic");
homeAssistantDiscoveryPrefix = AsyncWiFiSettings.string("discovery_prefix", DEFAULT_HA_DISCOVERY_PREFIX, "Home Assistant discovery topic prefix");
publishTele = AsyncWiFiSettings.checkbox("pub_tele", true, "Send to telemetry topic");
publishRooms = AsyncWiFiSettings.checkbox("pub_rooms", true, "Send to rooms topic");
publishRooms = AsyncWiFiSettings.checkbox("pub_rooms_dep", true, "Send to rooms topic (deprecated in v4)");
publishDevices = AsyncWiFiSettings.checkbox("pub_devices", true, "Send to devices topic");
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#updating' target='_blank'>Updating</a>", false);
Updater::ConnectToWifi();
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#scanning' target='_blank'>Scanning</a>", false);
AsyncWiFiSettings.info("<a href='ui/#settings' target='_blank'>Click here to edit other settings!</a>", false);
AsyncWiFiSettings.markExtra();
BleFingerprintCollection::knownMacs = AsyncWiFiSettings.string("known_macs", "", "Known BLE mac addresses (no colons, space seperated)");
BleFingerprintCollection::knownIrks = AsyncWiFiSettings.string("known_irks", "", "Known BLE identity resolving keys, should be 32 hex chars space seperated");
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#querying' target='_blank'>Querying</a>", false);
BleFingerprintCollection::query = AsyncWiFiSettings.string("query", DEFAULT_QUERY, "Query device ids for characteristics (eg. flora:)");
BleFingerprintCollection::requeryMs = AsyncWiFiSettings.integer("requery_ms", 30, 3600, 300, "Requery interval in seconds") * 1000;
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#counting' target='_blank'>Counting</a>", false);
BleFingerprintCollection::countIds = AsyncWiFiSettings.string("count_ids", "", "Include id prefixes (space seperated)");
BleFingerprintCollection::countEnter = AsyncWiFiSettings.floating("count_enter", 0, 100, 2, "Start counting devices less than distance (in meters)");
BleFingerprintCollection::countExit = AsyncWiFiSettings.floating("count_exit", 0, 100, 4, "Stop counting devices greater than distance (in meters)");
BleFingerprintCollection::countMs = AsyncWiFiSettings.integer("count_ms", 0, 3000000, 30000, "Include devices with age less than (in ms)");
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#filtering' target='_blank'>Filtering</a>", false);
BleFingerprintCollection::include = AsyncWiFiSettings.string("include", DEFAULT_INCLUDE, "Include only sending these ids to mqtt (eg. apple:iphone10-6 apple:iphone13-2)");
BleFingerprintCollection::exclude = AsyncWiFiSettings.string("exclude", DEFAULT_EXCLUDE, "Exclude sending these ids to mqtt (eg. exp:20 apple:iphone10-6)");
BleFingerprintCollection::maxDistance = AsyncWiFiSettings.floating("max_dist", 0, 100, DEFAULT_MAX_DISTANCE, "Maximum distance to report (in meters)");
BleFingerprintCollection::skipDistance = AsyncWiFiSettings.floating("skip_dist", 0, 10, DEFAULT_SKIP_DISTANCE, "Report early if beacon has moved more than this distance (in meters)");
BleFingerprintCollection::skipMs = AsyncWiFiSettings.integer("skip_ms", 0, 3000000, DEFAULT_SKIP_MS, "Skip reporting if message age is less that this (in milliseconds)");
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#calibration' target='_blank'>Calibration</a>", false);
BleFingerprintCollection::rxRefRssi = AsyncWiFiSettings.integer("ref_rssi", -100, 100, DEFAULT_RX_REF_RSSI, "Rssi expected from a 0dBm transmitter at 1 meter (NOT used for iBeacons or Eddystone)");
BleFingerprintCollection::rxAdjRssi = AsyncWiFiSettings.integer("rx_adj_rssi", -100, 100, 0, "Rssi adjustment for receiver (use only if you know this device has a weak antenna)");
BleFingerprintCollection::absorption = AsyncWiFiSettings.floating("absorption", -100, 100, DEFAULT_ABSORPTION, "Factor used to account for absorption, reflection, or diffraction");
@ -182,8 +181,6 @@ void setupNetwork() {
GUI::ConnectToWifi();
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#gpio-sensors' target='_blank'>GPIO Sensors</a>", false);
BleFingerprintCollection::ConnectToWifi();
Motion::ConnectToWifi();
Switch::ConnectToWifi();
@ -193,8 +190,6 @@ void setupNetwork() {
DHT::ConnectToWifi();
I2C::ConnectToWifi();
AsyncWiFiSettings.heading("<a href='https://espresense.com/configuration/settings#i2c-sensors' target='_blank'>I2C Sensors</a>", false);
AHTX0::ConnectToWifi();
BH1750::ConnectToWifi();
BME280::ConnectToWifi();
@ -205,7 +200,6 @@ void setupNetwork() {
SensirionSGP30::ConnectToWifi();
HX711::ConnectToWifi();
DS18B20::ConnectToWifi();
#endif
unsigned int connectProgress = 0;

View File

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

View File

@ -4,24 +4,24 @@
*/
// Autogenerated do not edit!!
const uint16_t INDEX_HTML_L = 247;
const uint16_t INDEX_HTML_L = 242;
const uint8_t INDEX_HTML[] PROGMEM = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x4d, 0x50, 0x3d, 0x53, 0xc3, 0x30,
0x0c, 0xdd, 0xfb, 0x2b, 0x84, 0x66, 0xd2, 0xc0, 0xc6, 0x71, 0x76, 0x16, 0x5a, 0x56, 0x7a, 0x47,
0x19, 0x18, 0x5d, 0x5b, 0x60, 0x81, 0xe3, 0xe4, 0x6c, 0x91, 0x36, 0xff, 0x1e, 0x3b, 0x81, 0x83,
0x49, 0x1f, 0xef, 0xe9, 0x3d, 0x49, 0xea, 0x6a, 0xf7, 0xf4, 0x70, 0x7c, 0x3d, 0xec, 0xc1, 0x4b,
0x1f, 0xba, 0x8d, 0xaa, 0x01, 0x82, 0x89, 0xef, 0x1a, 0x29, 0x62, 0xb7, 0x01, 0x50, 0x9e, 0x8c,
0xab, 0x49, 0x49, 0x7b, 0x12, 0x03, 0xd6, 0x9b, 0x94, 0x49, 0x34, 0xbe, 0x1c, 0x1f, 0x9b, 0x3b,
0x84, 0xf6, 0x3f, 0x18, 0x4d, 0x4f, 0x1a, 0x27, 0xa6, 0xf3, 0x38, 0x24, 0x41, 0xb0, 0x43, 0x14,
0x8a, 0x85, 0x7c, 0x66, 0x27, 0x5e, 0x3b, 0x9a, 0xd8, 0x52, 0xb3, 0x14, 0xd7, 0xc0, 0x91, 0x85,
0x4d, 0x68, 0xb2, 0x35, 0x81, 0xf4, 0xed, 0xf6, 0xe6, 0x4f, 0x4c, 0x58, 0x02, 0x75, 0xfb, 0xe7,
0x43, 0xa2, 0x4c, 0x31, 0xd3, 0x3d, 0xec, 0x96, 0xd1, 0xac, 0xda, 0x15, 0xaa, 0x9b, 0x05, 0x8e,
0x9f, 0x90, 0x28, 0x68, 0xcc, 0x32, 0x07, 0xca, 0x9e, 0xa8, 0x58, 0xca, 0x3c, 0x96, 0x15, 0x84,
0x2e, 0xd2, 0xda, 0x9c, 0x11, 0x7c, 0xa2, 0x37, 0x8d, 0xa7, 0xaf, 0xe8, 0x02, 0x6d, 0x6b, 0xa7,
0x9c, 0xd9, 0xfe, 0x1e, 0xa5, 0x4e, 0x83, 0x9b, 0x7f, 0x3c, 0x1d, 0x4f, 0xc0, 0x4e, 0xa3, 0x19,
0x47, 0xec, 0x54, 0x5b, 0xca, 0x85, 0x91, 0x6d, 0xe2, 0x51, 0x00, 0x72, 0xb2, 0x1a, 0x39, 0x3a,
0xba, 0x6c, 0x3f, 0x72, 0x25, 0xac, 0x40, 0x55, 0x5b, 0x45, 0x8a, 0xea, 0xf2, 0xc4, 0x6f, 0xaf,
0xf4, 0x09, 0x10, 0x55, 0x01, 0x00, 0x00
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x13, 0x4d, 0x50, 0x31, 0x52, 0xc4, 0x30,
0x0c, 0xec, 0xef, 0x15, 0x42, 0x35, 0x49, 0xa0, 0xa3, 0xb0, 0xd3, 0xc0, 0xd1, 0x72, 0x33, 0x1c,
0x05, 0xa5, 0xcf, 0x16, 0x58, 0xe0, 0x38, 0x19, 0x5b, 0xe4, 0x2e, 0xbf, 0xc7, 0x4e, 0x60, 0xa0,
0xd2, 0x6a, 0xb5, 0xb3, 0x2b, 0x49, 0x5d, 0x3d, 0x3c, 0xdd, 0x1f, 0x5f, 0x0f, 0x7b, 0xf0, 0x32,
0x84, 0x7e, 0xa7, 0x6a, 0x81, 0x60, 0xe2, 0xbb, 0x46, 0x8a, 0xd8, 0xef, 0x00, 0x94, 0x27, 0xe3,
0x2a, 0x28, 0x70, 0x20, 0x31, 0x60, 0xbd, 0x49, 0x99, 0x44, 0xe3, 0xcb, 0xf1, 0xb1, 0xb9, 0x43,
0xe8, 0xfe, 0x0f, 0xa3, 0x19, 0x48, 0xe3, 0xcc, 0x74, 0x9e, 0xc6, 0x24, 0x08, 0x76, 0x8c, 0x42,
0xb1, 0x88, 0xcf, 0xec, 0xc4, 0x6b, 0x47, 0x33, 0x5b, 0x6a, 0xd6, 0xe6, 0x1a, 0x38, 0xb2, 0xb0,
0x09, 0x4d, 0xb6, 0x26, 0x90, 0xbe, 0x6d, 0x6f, 0xfe, 0xcc, 0x84, 0x25, 0x50, 0xbf, 0x7f, 0x3e,
0x24, 0xca, 0x14, 0x33, 0xa9, 0x6e, 0x63, 0xea, 0x42, 0x81, 0xe3, 0x27, 0x24, 0x0a, 0x1a, 0xb3,
0x2c, 0x81, 0xb2, 0x27, 0x2a, 0x49, 0xb2, 0x4c, 0x25, 0x59, 0xe8, 0x22, 0x9d, 0xcd, 0x19, 0xc1,
0x27, 0x7a, 0xd3, 0x78, 0xfa, 0x8a, 0x2e, 0x50, 0x5b, 0x99, 0x72, 0x5d, 0xf7, 0x7b, 0x8b, 0x3a,
0x8d, 0x6e, 0xf9, 0x89, 0x72, 0x3c, 0x03, 0x3b, 0x8d, 0x66, 0x9a, 0xb0, 0x57, 0x5d, 0x69, 0x57,
0x45, 0xb6, 0x89, 0x27, 0x01, 0xc8, 0xc9, 0x6a, 0xe4, 0xe8, 0xe8, 0xd2, 0x7e, 0xe4, 0x2a, 0xd8,
0x06, 0xd5, 0x6d, 0x33, 0x29, 0xae, 0xeb, 0xef, 0xbe, 0x01, 0xc3, 0xc9, 0x3d, 0xf3, 0x4c, 0x01,
0x00, 0x00
};
void serveIndexHtml(AsyncWebServerRequest* request) {

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ESPresense</title>
</head>
<body>

View File

@ -1,16 +1,20 @@
<script>
import Router from "svelte-spa-router";
import Sidebar from "./components/Sidebar.svelte";
import routes from "./routes";
import Router, { push } from "svelte-spa-router";
import Sidebar from "./components/Sidebar.svelte";
import routes from "./routes";
function routeLoaded(event) {
if (event.detail.route == "/") push("/settings");
}
</script>
<div>
<div class="flex">
<nav>
<Sidebar />
</nav>
<main class="max-w-7xl mx-auto py-8 sm:py-10 md:py-12 sm:px-10 lg:px-12">
<Router {routes} />
</main>
</div>
<div class="flex">
<nav>
<Sidebar />
</nav>
<main class="max-w-7xl mx-auto py-8 sm:py-10 md:py-12 sm:px-10 lg:px-12">
<Router {routes} on:routeLoaded={routeLoaded} />
</main>
</div>
</div>

View File

@ -15,11 +15,11 @@
<path d="M116.3 165.3a62.5 62.5 0 0 0 35.2-102l-13.4 13.1a43.8 43.8 0 0 1 6.4 44.6 13 13 0 0 1-16.6 19.7 43.7 43.7 0 1 1 4.2-70.4l13.1-13.4a62.4 62.4 0 0 0-82.7.6 13 13 0 0 1 1.4 6 13.1 13.1 0 0 1-13 13 13.4 13.4 0 0 1-2.7-.2 62.5 62.5 0 0 0 43.5 89 13 13 0 0 1 24.6 0z"/>
<path d="M112.2 101.9a7.9 7.9 0 0 1 .3 2.1 8.3 8.3 0 1 1-8.3-8.3 8.5 8.5 0 0 1 2.5.4l19.4-19.6a35.1 35.1 0 1 0-3.7 57.6 13 13 0 0 1 12.2-17.7 12.8 12.8 0 0 1 2.5.2 35.1 35.1 0 0 0-5-34.1z"/>
</svg>
<span class="text-gray-900 dark:text-gray-100 ml-2 text-3xl font-thin"> ESPresense </span>
<span class="text-gray-900 dark:text-gray-100 ml-2 text-3xl font-thin">ESPresense</span>
</div>
<nav class="mt-10 px-6 ">
<SidebarItem icon="device" title="Devices" href="/" />
<SidebarItem icon="contact" title="Settings" href="/settings" />
<SidebarItem icon="device" title="Devices" href="/devices" />
<SidebarItem icon="fingerprint" title="Fingerprints" href="/fingerprints" />
</nav>
</div>

View File

@ -1,22 +1,2 @@
<section class="text-gray-600 body-font">
<!--div class="container px-5 py-24 mx-auto">
<div class="flex flex-wrap -m-4 text-center">
<div class="p-4 sm:w-1/4 w-1/2">
<h2 class="title-font font-medium sm:text-4xl text-3xl text-gray-900">2.7K</h2>
<p class="leading-relaxed">Users</p>
</div>
<div class="p-4 sm:w-1/4 w-1/2">
<h2 class="title-font font-medium sm:text-4xl text-3xl text-gray-900">1.8K</h2>
<p class="leading-relaxed">Subscribes</p>
</div>
<div class="p-4 sm:w-1/4 w-1/2">
<h2 class="title-font font-medium sm:text-4xl text-3xl text-gray-900">35</h2>
<p class="leading-relaxed">Downloads</p>
</div>
<div class="p-4 sm:w-1/4 w-1/2">
<h2 class="title-font font-medium sm:text-4xl text-3xl text-gray-900">4</h2>
<p class="leading-relaxed">Products</p>
</div>
</div>
</div-->
</section>

View File

@ -1,10 +1,13 @@
import Home from './routes/Home.svelte';
import Fingerprints from './routes/Fingerprints.svelte';
import Devices from './routes/Devices.svelte';
import Settings from './routes/Settings.svelte';
import NotFound from './routes/NotFound.svelte';
export default {
'/': Home,
'/fingerprints': Devices,
'/': Settings,
'/settings': Settings,
'/devices': Devices,
'/fingerprints': Fingerprints,
// The catch-all route must always be last
'*': NotFound
};

View File

@ -1,144 +1,28 @@
<script>
import { devices } from '../stores';
import SvelteTable from "svelte-table";
import { devices, events, enroll } from "../stores";
let name;
var filterSelections = { };
var sortBy = "distance"
var sortOrder = 1;
var selectedRowIds = []
const columns = [
{
key: "distance",
title: "Dist",
value: v => v.distance,
renderValue: v => `${v.distance.toLocaleString(undefined, { minimumFractionDigits: 2 })}m`,
sortable: true,
class:"px-0 py-0 whitespace-nowrap"
},
{
key: "id",
title: "ID",
value: v => v.id,
sortable: true,
filterOptions: rows => {
const prefixes = new Set()
rows.forEach(row => {
var prefix = row.id.substring(0, row.id.indexOf(":")+1);
if (prefix.length > 0) {
prefixes.add(prefix);
}
});
return Array.from(prefixes).sort().map(a=>({"name": a, "value": a}));
},
filterValue: v => v.id.substring(0, v.id.indexOf(":")+1),
headerClass: "text-left px-6 py-3",
},
{
key: "name",
title: "Name",
value: v => v.name ?? "",
sortable: true,
filterOptions: rows => {
let letrs = {};
rows.forEach(row => {
let letr = row.name?.charAt(0);
if (letr && letrs[letr] === undefined)
letrs[letr] = {
name: `${letr.toUpperCase()}`,
value: letr.toLowerCase(),
};
});
// fix order
letrs = Object.entries(letrs)
.sort()
.reduce((o, [k, v]) => ((o[k] = v), o), {});
return Object.values(letrs);
},
filterValue: v => v.name?.charAt(0).toLowerCase(),
headerClass: "text-left px-6 py-3",
},
{
key: "mac",
title: "MAC",
value: v => v.mac,
sortable: true,
filterOptions: rows => {
// use first letter of last_name to generate filter
let letrs = {};
rows.forEach(row => {
let letr = row.mac.charAt(0);
if (letrs[letr] === undefined)
letrs[letr] = {
name: `${letr.toUpperCase()}`,
value: letr.toLowerCase(),
};
});
// fix order
letrs = Object.entries(letrs)
.sort()
.reduce((o, [k, v]) => ((o[k] = v), o), {});
return Object.values(letrs);
},
filterValue: v => v.mac.charAt(0).toLowerCase(),
headerClass: "text-left px-6 py-3",
},
{
key: "rssi",
title: "Rssi",
value: v => v.rssi,
renderValue: v => v.rssi + "dBm",
sortable: true,
headerClass: "text-left px-6 py-3",
},
{
key: "rssi@1m",
title: "Rssi@1m",
value: v => v["rssi@1m"],
renderValue: v => v["rssi@1m"] + "dBm",
sortable: true,
headerClass: "text-left px-6 py-3",
},
{
key: "interval",
title: "Interval",
value: v => v.interval,
renderValue: v => v.interval + "ms",
sortable: true,
headerClass: "text-left px-6 py-3",
},
];
function classNameRow(event) { event.close ? "bg-yellow-100 row" : "row"; }
function slugify(name) {
return name
.toString()
.normalize("NFD") // split an accented letter in the base letter and the acent
.replace(/[\u0300-\u036f]/g, "") // remove all previously split accents
.toLowerCase()
.trim()
.replace(/[^a-z0-9 ]/g, "") // remove all chars not letters, numbers and spaces (to be replaced)
.replace(/\s+/g, "-"); // separator
}
</script>
<main>
{#if $events?.state != null}
<label for="name">Name</label>
<input id="name" type="text" class="bg-gray-200 relative" placeholder="Name" bind:value={name} />
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:opacity-50 disabled:cursor-not-allowed" disabled={$events.state.enrolling} on:click={() => enroll(name)}> Enroll </button>
{#if $devices?.devices != null }
<SvelteTable columns="{columns}" rows="{$devices.devices}" rowKey="mac"
bind:filterSelections="{filterSelections}"
bind:sortBy="{sortBy}"
bind:sortOrder="{sortOrder}"
selectSingle="{true}"
selectOnClick="{true}"
selected={selectedRowIds}
classNameTable="min-w-full divide-y divide-gray-200 table-auto"
classNameThead="whitespace-nowrap text-left text-xs font-medium text-gray-500 uppercase"
classNameTbody="bg-white divide-y divide-gray-200"
classNameRow="{classNameRow}"
classNameRowSelected="bg-blue-100"
classNameCell="px-3 py-1 whitespace-no-wrap text-sm leading-5 font-light text-gray-900"
classNameInput="px-1 py-1 border rounded-md text-sm leading-5 font-medium text-gray-900 placeholder-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5"
classNameSelect="px-1 py-1 border rounded-md text-sm leading-5 font-medium text-gray-900 placeholder-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5"
></SvelteTable>
{:else}
<h1>Loading fingerprints...</h1>
{#if $events?.state?.enrolling}
<p>
You can now use the Bluetooth settings on your device and pair it with the ESPresense device. Once paired your device will be shown with the name: <span class="bg-gray-200 relative whitespace-nowrap">{slugify(name)}</span>
in the fingerprint page as well as on mqtt.
</p>
{/if}
{/if}
</main>
<style>
main {
padding: 1rem;
}
h1 {
text-align: center;
}
</style>

View File

@ -0,0 +1,144 @@
<script>
import { devices } from '../stores';
import SvelteTable from "svelte-table";
var filterSelections = { };
var sortBy = "distance"
var sortOrder = 1;
var selectedRowIds = []
const columns = [
{
key: "distance",
title: "Dist",
value: v => v.distance,
renderValue: v => `${v.distance.toLocaleString(undefined, { minimumFractionDigits: 2 })}m`,
sortable: true,
class:"px-0 py-0 whitespace-nowrap"
},
{
key: "id",
title: "ID",
value: v => v.id,
sortable: true,
filterOptions: rows => {
const prefixes = new Set()
rows.forEach(row => {
var prefix = row.id.substring(0, row.id.indexOf(":")+1);
if (prefix.length > 0) {
prefixes.add(prefix);
}
});
return Array.from(prefixes).sort().map(a=>({"name": a, "value": a}));
},
filterValue: v => v.id.substring(0, v.id.indexOf(":")+1),
headerClass: "text-left px-6 py-3",
},
{
key: "name",
title: "Name",
value: v => v.name ?? "",
sortable: true,
filterOptions: rows => {
let letrs = {};
rows.forEach(row => {
let letr = row.name?.charAt(0);
if (letr && letrs[letr] === undefined)
letrs[letr] = {
name: `${letr.toUpperCase()}`,
value: letr.toLowerCase(),
};
});
// fix order
letrs = Object.entries(letrs)
.sort()
.reduce((o, [k, v]) => ((o[k] = v), o), {});
return Object.values(letrs);
},
filterValue: v => v.name?.charAt(0).toLowerCase(),
headerClass: "text-left px-6 py-3",
},
{
key: "mac",
title: "MAC",
value: v => v.mac,
sortable: true,
filterOptions: rows => {
// use first letter of last_name to generate filter
let letrs = {};
rows.forEach(row => {
let letr = row.mac.charAt(0);
if (letrs[letr] === undefined)
letrs[letr] = {
name: `${letr.toUpperCase()}`,
value: letr.toLowerCase(),
};
});
// fix order
letrs = Object.entries(letrs)
.sort()
.reduce((o, [k, v]) => ((o[k] = v), o), {});
return Object.values(letrs);
},
filterValue: v => v.mac.charAt(0).toLowerCase(),
headerClass: "text-left px-6 py-3",
},
{
key: "rssi",
title: "Rssi",
value: v => v.rssi,
renderValue: v => v.rssi + "dBm",
sortable: true,
headerClass: "text-left px-6 py-3",
},
{
key: "rssi@1m",
title: "Rssi@1m",
value: v => v["rssi@1m"],
renderValue: v => v["rssi@1m"] + "dBm",
sortable: true,
headerClass: "text-left px-6 py-3",
},
{
key: "interval",
title: "Interval",
value: v => v.interval,
renderValue: v => v.interval + "ms",
sortable: true,
headerClass: "text-left px-6 py-3",
},
];
function classNameRow(event) { event.close ? "bg-yellow-100 row" : "row"; }
</script>
<main>
{#if $devices?.devices != null }
<SvelteTable columns="{columns}" rows="{$devices.devices}" rowKey="mac"
bind:filterSelections="{filterSelections}"
bind:sortBy="{sortBy}"
bind:sortOrder="{sortOrder}"
selectSingle="{true}"
selectOnClick="{true}"
selected={selectedRowIds}
classNameTable="min-w-full divide-y divide-gray-200 table-auto"
classNameThead="whitespace-nowrap text-left text-xs font-medium text-gray-500 uppercase"
classNameTbody="bg-white divide-y divide-gray-200"
classNameRow="{classNameRow}"
classNameRowSelected="bg-blue-100"
classNameCell="px-3 py-1 whitespace-no-wrap text-sm leading-5 font-light text-gray-900"
classNameInput="px-1 py-1 border rounded-md text-sm leading-5 font-medium text-gray-900 placeholder-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5"
classNameSelect="px-1 py-1 border rounded-md text-sm leading-5 font-medium text-gray-900 placeholder-gray-500 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 focus:z-10 sm:text-sm sm:leading-5"
></SvelteTable>
{:else}
<h1>Loading fingerprints...</h1>
{/if}
</main>
<style>
main {
padding: 1rem;
}
h1 {
text-align: center;
}
</style>

View File

@ -1,30 +0,0 @@
<script>
import { devices, events, enroll } from "../stores";
import Stats from "../components/Stats.svelte";
let name;
function slugify(name) {
return name
.toString()
.normalize("NFD") // split an accented letter in the base letter and the acent
.replace(/[\u0300-\u036f]/g, "") // remove all previously split accents
.toLowerCase()
.trim()
.replace(/[^a-z0-9 ]/g, "") // remove all chars not letters, numbers and spaces (to be replaced)
.replace(/\s+/g, "-"); // separator
}
</script>
<Stats />
{#if $events?.state != null}
<label for="name">Name</label>
<input id="name" type="text" class="bg-gray-200 relative" placeholder="Name" bind:value={name} />
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded disabled:opacity-50 disabled:cursor-not-allowed" disabled={$events.state.enrolling} on:click={() => enroll(name)}> Enroll </button>
{#if $events?.state?.enrolling}
<p>
You can now use the Bluetooth settings on your device and pair it with the ESPresense device. Once paired your device will be shown with the name: <span class="bg-gray-200 relative whitespace-nowrap">{slugify(name)}</span>
in the fingerprint page as well as on mqtt.
</p>
{/if}
{/if}

View File

@ -0,0 +1,218 @@
<script>
import { extras } from "../stores";
let r = false;
async function restart() {
r = true;
await fetch("/restart", { method: "POST" });
while (true) {
try {
const res = await fetch("/");
if (res.ok) break;
} catch (err) {}
await new Promise((r) => setTimeout(r, 1000));
}
r = false;
}
let s = false;
async function save(event) {
s = true;
const formData = new FormData(event.target);
await fetch("/extras", { method: "POST", body: new URLSearchParams(formData), redirect: 'manual' });
s = false;
}
</script>
<div class="form">
{#if $extras != null }
<form action="/extras" method="post" id="extras" on:submit|preventDefault={save}>
<h2><a href="https://espresense.com/configuration/settings#scanning" target="_blank">Scanning</a></h2>
<p><label>Known BLE mac addresses (no colons, space seperated):<br /><input name="known_macs" bind:value={$extras.known_macs}/></label></p>
<p><label>Known BLE identity resolving keys, should be 32 hex chars space seperated:<br /><input name="known_irks" bind:value={$extras.known_irks}/></label></p>
<h2><a href="https://espresense.com/configuration/settings#querying" target="_blank">Querying</a></h2>
<p><label>Query device ids for characteristics (eg. flora:):<br /><input name="query" bind:value={$extras.query}/></label></p>
<p><label>Requery interval in seconds:<br /><input type="number" step="1" min="30" max="3600" name="requery_ms" placeholder="300" bind:value={$extras.requery_ms}/></label></p>
<h2><a href="https://espresense.com/configuration/settings#counting" target="_blank">Counting</a></h2>
<p><label>Include id prefixes (space seperated):<br /><input name="count_ids" bind:value={$extras.count_ids}/></label></p>
<p><label>Start counting devices less than distance (in meters):<br /><input type="number" step="0.01" min="0" max="100" name="count_enter" placeholder="2.00" bind:value={$extras.count_enter}/></label></p>
<p><label>Stop counting devices greater than distance (in meters):<br /><input type="number" step="0.01" min="0" max="100" name="count_exit" placeholder="4.00" bind:value={$extras.count_exit}/></label></p>
<p><label>Include devices with age less than (in ms):<br /><input type="number" step="1" min="0" max="3000000" name="count_ms" placeholder="30000" bind:value={$extras.count_ms}/></label></p>
<h2><a href="https://espresense.com/configuration/settings#filtering" target="_blank">Filtering</a></h2>
<p><label>Include only sending these ids to mqtt (eg. apple:iphone10-6 apple:iphone13-2):<br /><input name="include" bind:value={$extras.include}/></label></p>
<p><label>Exclude sending these ids to mqtt (eg. exp:20 apple:iphone10-6):<br /><input name="exclude" bind:value={$extras.exclude}/></label></p>
<p><label>Maximum distance to report (in meters):<br /><input type="number" step="0.01" min="0" max="100" name="max_dist" placeholder="16.00" bind:value={$extras.max_dist}/></label></p>
<p><label>Report early if beacon has moved more than this distance (in meters):<br /><input type="number" step="0.01" min="0" max="10" name="skip_dist" placeholder="0.50" bind:value={$extras.skip_dist}/></label></p>
<p><label>Skip reporting if message age is less that this (in milliseconds):<br /><input type="number" step="1" min="0" max="3000000" name="skip_ms" placeholder="5000" bind:value={$extras.skip_ms}/></label></p>
<h2><a href="https://espresense.com/configuration/settings#calibration" target="_blank">Calibration</a></h2>
<p><label>Rssi expected from a 0dBm transmitter at 1 meter (NOT used for iBeacons or Eddystone):<br /><input type="number" step="1" min="-100" max="100" name="ref_rssi" placeholder="-65" bind:value={$extras.ref_rssi}/></label></p>
<p><label>Rssi adjustment for receiver (use only if you know this device has a weak antenna):<br /><input type="number" step="1" min="-100" max="100" name="rx_adj_rssi" placeholder="0" bind:value={$extras.rx_adj_rssi}/></label></p>
<p><label>Factor used to account for absorption, reflection, or diffraction:<br /><input type="number" step="0.01" min="-100" max="100" name="absorption" placeholder="3.50" bind:value={$extras.absorption}/></label></p>
<p><label>Forget beacon if not seen for (in milliseconds):<br /><input type="number" step="1" min="0" max="3000000" name="forget_ms" placeholder="150000" bind:value={$extras.forget_ms}/></label></p>
<p><label>Rssi expected from this tx power at 1m (used for node iBeacon):<br /><input type="number" step="1" min="-100" max="100" name="tx_ref_rssi" placeholder="-59" bind:value={$extras.tx_ref_rssi}/></label></p>
<h2><a href="https://espresense.com/configuration/settings#leds" target="_blank">LEDs</a></h2>
<h4>LED 1:</h4>
<p><label>LED Type:<br /><select name="led_1_type" bind:value={$extras.led_1_type}><option disabled selected hidden>PWM</option><option value="0">PWM</option><option value="1">PWM Inverted</option><option value="2">Addressable GRB</option><option value="3">Addressable GRBW</option><option value="4">Addressable RGB</option><option value="5">Addressable RGBW</option></select></label></p>
<p><label>Pin (-1 to disable):<br /><input type="number" step="1" min="-1" max="39" name="led_1_pin" placeholder="2" bind:value={$extras.led_1_pin}/></label></p>
<p><label>Count (only applies to Addressable LEDs):<br /><input type="number" step="1" min="-1" max="39" name="led_1_cnt" placeholder="1" bind:value={$extras.led_1_cnt}/></label></p>
<p><label>LED Control:<br /><select name="led_1_cntrl" bind:value={$extras.led_1_cntrl}><option disabled selected hidden>Status</option><option value="0">MQTT</option><option value="1">Status</option><option value="2">Motion</option><option value="3">Count</option></select></label></p>
<h4>LED 2:</h4>
<p><label>LED Type:<br /><select name="led_2_type" bind:value={$extras.led_2_type}><option disabled selected hidden>PWM</option><option value="0">PWM</option><option value="1">PWM Inverted</option><option value="2">Addressable GRB</option><option value="3">Addressable GRBW</option><option value="4">Addressable RGB</option><option value="5">Addressable RGBW</option></select></label></p>
<p><label>Pin (-1 to disable):<br /><input type="number" step="1" min="-1" max="39" name="led_2_pin" placeholder="-1" bind:value={$extras.led_2_pin}/></label></p>
<p><label>Count (only applies to Addressable LEDs):<br /><input type="number" step="1" min="-1" max="39" name="led_2_cnt" placeholder="1" bind:value={$extras.led_2_cnt}/></label></p>
<p><label>LED Control:<br /><select name="led_2_cntrl" bind:value={$extras.led_2_cntrl}><option disabled selected hidden>MQTT</option><option value="0">MQTT</option><option value="1">Status</option><option value="2">Motion</option><option value="3">Count</option></select></label></p>
<h4>LED 3:</h4>
<p><label>LED Type:<br /><select name="led_3_type" bind:value={$extras.led_3_type}><option disabled selected hidden>PWM</option><option value="0">PWM</option><option value="1">PWM Inverted</option><option value="2">Addressable GRB</option><option value="3">Addressable GRBW</option><option value="4">Addressable RGB</option><option value="5">Addressable RGBW</option></select></label></p>
<p><label>Pin (-1 to disable):<br /><input type="number" step="1" min="-1" max="39" name="led_3_pin" placeholder="-1" bind:value={$extras.led_3_pin}/></label></p>
<p><label>Count (only applies to Addressable LEDs):<br /><input type="number" step="1" min="-1" max="39" name="led_3_cnt" placeholder="1" bind:value={$extras.led_3_cnt}/></label></p>
<p><label>LED Control:<br /><select name="led_3_cntrl" bind:value={$extras.led_3_cntrl}><option disabled selected hidden>MQTT</option><option value="0">MQTT</option><option value="1">Status</option><option value="2">Motion</option><option value="3">Count</option></select></label></p>
<h2><a href="https://espresense.com/configuration/settings#gpio-sensors" target="_blank">GPIO Sensors</a></h2>
<h4>PIR:</h4>
<p><label>PIR motion pin type:<br /><select name="pir_type" bind:value={$extras.pir_type}><option disabled selected hidden>Pullup</option><option value="0">Pullup</option><option value="1">Pullup Inverted</option><option value="2">Pulldown</option><option value="3">Pulldown Inverted</option><option value="4">Floating</option><option value="5">Floating Inverted</option></select></label></p>
<p><label>PIR motion pin (-1 for disable):<br /><input type="number" step="1" name="pir_pin" placeholder="-1" bind:value={$extras.pir_pin}/></label></p>
<p><label>PIR motion timeout (in seconds):<br /><input type="number" step="0.01" min="0" max="300" name="pir_timeout" placeholder="0.50" bind:value={$extras.pir_timeout}/></label></p>
<h4>Radar:</h4>
<p><label>Radar motion pin type:<br /><select name="radar_type" bind:value={$extras.radar_type}><option disabled selected hidden>Pullup</option><option value="0">Pullup</option><option value="1">Pullup Inverted</option><option value="2">Pulldown</option><option value="3">Pulldown Inverted</option><option value="4">Floating</option><option value="5">Floating Inverted</option></select></label></p>
<p><label>Radar motion pin (-1 for disable):<br /><input type="number" step="1" name="radar_pin" placeholder="-1" bind:value={$extras.radar_pin}/></label></p>
<p><label>Radar motion timeout (in seconds):<br /><input type="number" step="0.01" min="0" max="300" name="radar_timeout" placeholder="0.50" bind:value={$extras.radar_timeout}/></label></p>
<h4>Switch One:</h4>
<p><label>Switch One pin type:<br /><select name="switch_1_type" bind:value={$extras.switch_1_type}><option disabled selected hidden>Pullup</option><option value="0">Pullup</option><option value="1">Pullup Inverted</option><option value="2">Pulldown</option><option value="3">Pulldown Inverted</option><option value="4">Floating</option><option value="5">Floating Inverted</option></select></label></p>
<p><label>Switch One pin (-1 for disable):<br /><input type="number" step="1" name="switch_1_pin" placeholder="-1" bind:value={$extras.switch_1_pin}/></label></p>
<p><label>Switch One timeout (in seconds):<br /><input type="number" step="0.01" min="0" max="300" name="switch_1_timeout" placeholder="0.50" bind:value={$extras.switch_1_timeout}/></label></p>
<h4>Switch Two:</h4>
<p><label>Switch Two pin type:<br /><select name="switch_2_type" bind:value={$extras.switch_2_type}><option disabled selected hidden>Pullup</option><option value="0">Pullup</option><option value="1">Pullup Inverted</option><option value="2">Pulldown</option><option value="3">Pulldown Inverted</option><option value="4">Floating</option><option value="5">Floating Inverted</option></select></label></p>
<p><label>Switch Two pin (-1 for disable):<br /><input type="number" step="1" name="switch_2_pin" placeholder="-1" bind:value={$extras.switch_2_pin}/></label></p>
<p><label>Switch Two timeout (in seconds):<br /><input type="number" step="0.01" min="0" max="300" name="switch_2_timeout" placeholder="0.50" bind:value={$extras.switch_2_timeout}/></label></p>
<h4>Button One:</h4>
<p><label>Button One pin type:<br /><select name="button_1_type" bind:value={$extras.button_1_type}><option disabled selected hidden>Pullup</option><option value="0">Pullup</option><option value="1">Pullup Inverted</option><option value="2">Pulldown</option><option value="3">Pulldown Inverted</option><option value="4">Floating</option><option value="5">Floating Inverted</option></select></label></p>
<p><label>Button One pin (-1 for disable):<br /><input type="number" step="1" name="button_1_pin" placeholder="-1" bind:value={$extras.button_1_pin}/></label></p>
<p><label>Button One timeout (in seconds):<br /><input type="number" step="0.01" min="0" max="300" name="button_1_timeout" placeholder="0.50" bind:value={$extras.button_1_timeout}/></label></p>
<h4>Button Two:</h4>
<p><label>Button Two pin type:<br /><select name="button_2_type" bind:value={$extras.button_2_type}><option disabled selected hidden>Pullup</option><option value="0">Pullup</option><option value="1">Pullup Inverted</option><option value="2">Pulldown</option><option value="3">Pulldown Inverted</option><option value="4">Floating</option><option value="5">Floating Inverted</option></select></label></p>
<p><label>Button Two pin (-1 for disable):<br /><input type="number" step="1" name="button_2_pin" placeholder="-1" bind:value={$extras.button_2_pin}/></label></p>
<p><label>Button Two timeout (in seconds):<br /><input type="number" step="0.01" min="0" max="300" name="button_2_timeout" placeholder="0.50" bind:value={$extras.button_2_timeout}/></label></p>
<h4>DHT:</h4>
<p><label>DHT11 sensor pin (-1 for disable):<br /><input type="number" step="1" name="dht11_pin" placeholder="-1" bind:value={$extras.dht11_pin}/></label></p>
<p><label>DHT22 sensor pin (-1 for disable):<br /><input type="number" step="1" name="dht22_pin" placeholder="-1" bind:value={$extras.dht22_pin}/></label></p>
<p><label>DHT temperature offset:<br /><input type="number" step="0.01" min="-40" max="125" name="dhtTemp_offset" placeholder="0.00" bind:value={$extras.dhtTemp_offset}/></label></p>
<h2><a href="https://espresense.com/configuration/settings#i2c-settings" target="_blank">I2C Settings</a></h2>
<h4>Bus 1:</h4>
<p><label>SDA pin (-1 to disable):<br /><input type="number" step="1" min="-1" max="39" name="I2C_Bus_1_SDA" placeholder="21" bind:value={$extras.I2C_Bus_1_SDA}/></label></p>
<p><label>SCL pin (-1 to disable):<br /><input type="number" step="1" min="-1" max="39" name="I2C_Bus_1_SCL" placeholder="22" bind:value={$extras.I2C_Bus_1_SCL}/></label></p>
<h4>Bus 2:</h4>
<p><label>SDA pin (-1 to disable):<br /><input type="number" step="1" min="-1" max="39" name="I2C_Bus_2_SDA" placeholder="-1" bind:value={$extras.I2C_Bus_2_SDA}/></label></p>
<p><label>SCL pin (-1 to disable):<br /><input type="number" step="1" min="-1" max="39" name="I2C_Bus_2_SCL" placeholder="-1" bind:value={$extras.I2C_Bus_2_SCL}/></label></p>
<p><label class="c"><input type="checkbox" name="I2CDebug" bind:value={$extras.I2CDebug}/> Debug I2C addreses. Look at the serial log to get the correct address (default: &#x2610;)</label></p>
<h2><a href="https://espresense.com/configuration/settings#i2c-sensors" target="_blank">I2C Sensors</a></h2>
<h4>AHTX0 - Temperature + Humidity Sensor:</h4>
<p><label>I2C Bus:<br /><input type="number" step="1" min="1" max="2" name="AHTX0_I2c_Bus" placeholder="1" bind:value={$extras.AHTX0_I2c_Bus}/></label></p>
<p><label>I2C address (0x38 or 0x39):<br /><input name="AHTX0_I2c" bind:value={$extras.AHTX0_I2c}/></label></p>
<h4>BH1750 - Ambient Light Sensor:</h4>
<p><label>I2C Bus:<br /><input type="number" step="1" min="1" max="2" name="BH1750_I2c_Bus" placeholder="1" bind:value={$extras.BH1750_I2c_Bus}/></label></p>
<p><label>I2C address (0x23 or 0x5C):<br /><input name="BH1750_I2c" bind:value={$extras.BH1750_I2c}/></label></p>
<h4>BME280 - Humidity + Temp + Pressure Sensor:</h4>
<p><label>I2C Bus:<br /><input type="number" step="1" min="1" max="2" name="BME280_I2c_Bus" placeholder="1" bind:value={$extras.BME280_I2c_Bus}/></label></p>
<p><label>I2C address (0x76 or 0x77):<br /><input name="BME280_I2c" bind:value={$extras.BME280_I2c}/></label></p>
<h4>BMP085/BMP180 - Barometric Pressure + Temperature:</h4>
<p><label>I2C Bus:<br /><input type="number" step="1" min="1" max="2" name="BMP180_I2c_Bus" placeholder="1" bind:value={$extras.BMP180_I2c_Bus}/></label></p>
<p><label>I2C address (0x77):<br /><input name="BMP180_I2c" bind:value={$extras.BMP180_I2c}/></label></p>
<h4>BMP280 - Barometric Pressure + Temperature Sensor:</h4>
<p><label>I2C Bus:<br /><input type="number" step="1" min="1" max="2" name="BMP280_I2c_Bus" placeholder="1" bind:value={$extras.BMP280_I2c_Bus}/></label></p>
<p><label>I2C address (0x76 or 0x77):<br /><input name="BMP280_I2c" bind:value={$extras.BMP280_I2c}/></label></p>
<h4>SHTC1/3, SHTW1/2, SHT3x/4x, SHT85 - Temperature and Humidity Sensor:</h4>
<p><label>I2C Bus (-1 to disable):<br /><input type="number" step="1" min="1" max="2" name="SHT_I2c_Bus" placeholder="-1" bind:value={$extras.SHT_I2c_Bus}/></label></p>
<h4>TSL2561 - Ambient Light Sensor:</h4>
<p><label>I2C Bus:<br /><input type="number" step="1" min="1" max="2" name="TSL2561_I2c_Bus" placeholder="1" bind:value={$extras.TSL2561_I2c_Bus}/></label></p>
<p><label>I2C address (0x39, 0x49 or 0x29):<br /><input name="TSL2561_I2c" bind:value={$extras.TSL2561_I2c}/></label></p>
<p><label>Gain (auto, 1x or 16x):<br /><input name="TSL2561_I2c_Gain" placeholder="auto" bind:value={$extras.TSL2561_I2c_Gain}/></label></p>
<h4>SGP30 - Air Quality Sensor:</h4>
<p><label>I2C Bus:<br /><input type="number" step="1" min="1" max="2" name="SGP30_I2c_Bus" placeholder="1" bind:value={$extras.SGP30_I2c_Bus}/></label></p>
<p><label>I2C address (0x58):<br /><input name="SGP30_I2c" bind:value={$extras.SGP30_I2c}/></label></p>
<h4>HX711 - Weight Sensor:</h4>
<p><label>HX711 SCK (Clock) pin:<br /><input type="number" step="1" name="HX711_sckPin" placeholder="0" bind:value={$extras.HX711_sckPin}/></label></p>
<p><label>HX711 DOUT (Data) pin:<br /><input type="number" step="1" name="HX711_doutPin" placeholder="0" bind:value={$extras.HX711_doutPin}/></label></p>
<h4>DS18B20:</h4>
<p><label>DS18B20 sensor pin (-1 for disable):<br /><input type="number" step="1" name="ds18b20_pin" placeholder="-1" bind:value={$extras.ds18b20_pin}/></label></p>
<p><label>DS18B20 temperature offset:<br /><input type="number" step="0.01" min="-40" max="125" name="dsTemp_offset" placeholder="0.00" bind:value={$extras.dsTemp_offset}/></label></p>
<div class="bc"><button class="btn left" on:click|preventDefault={restart}>{r ? "Restarting..." : "Restart"}</button><input class="btn right" type="submit" value={s ? "Saving..." : "Save"} /></div>
</form>
{/if}
</div>
<style>
.form {
padding: 1em;
background: #ccc;
max-width: 40em;
margin: 0;
position: relative;
}
* {
box-sizing: border-box;
}
h2 {
margin-top: 1em;
margin-bottom: 1em;
font: 1.5em sans-serif;
}
h4 {
margin-top: 1em;
margin-bottom: 1em;
font: 1.25em sans-serif;
}
a:link {
color: #000;
text-decoration: none;
}
label {
clear: both;
}
select,
input:not([type^="c"]) {
display: block;
width: 100%;
border: 1px solid #444;
padding: 0.3ex;
}
input[type^="c"] {
float: left;
margin-top: 0.5em;
margin-left: -1.5em;
}
:not([type^="s"]):focus {
outline: 2px solid #de1;
}
p::before {
margin-left: -2em;
float: left;
padding-top: 1ex;
}
.c {
display: block;
padding-left: 2em;
}
.bc {
position: sticky;
bottom: 0;
width: 100%;
display: flex;
justify-content: space-between;
margin-top: 1em;
}
.btn {
background: #de1;
font-size: 1.5em;
width: 8em !important;
padding: 0.5em !important;
border: 1px solid #000;
border-radius: 1ex;
justify-content: space-between;
}
.left {
left: 0;
}
.right {
right: 0;
}
</style>

View File

@ -1,6 +1,18 @@
import { readable } from 'svelte/store';
import { writable } from 'svelte/store';
export const extras = writable([], function start(set) {
fetch(`/extras`)
.then(d => d.json())
.then(r => {
set(r);
})
.catch((ex) => {
set(null);
console.log(ex);
});
});
export const devices = readable([], function start(set) {
var errors = 0;
var outstanding = false;

View File

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ESPresense: Devices</title>
<title>ESPresense</title>
</head>
<body>
<div id="app"></div>

View File

@ -6,13 +6,13 @@ export default defineConfig({
plugins: [svelte()],
server: {
proxy: {
'^/json': {
target: 'http://192.168.128.186/',
'^/(json|extras|restart)': {
target: 'http://192.168.128.134/',
changeOrigin: true,
rewrite: (path) => path
},
'^/ws': {
target: 'ws://192.168.128.186/',
target: 'ws://192.168.128.134/',
changeOrigin: true,
rewrite: (path) => path
},