Browse Source

Merge branch 'dev' into softcfg

v2
Xose Pérez 6 years ago
parent
commit
2e7e03a1df
39 changed files with 1660 additions and 1349 deletions
  1. +2
    -2
      .github/stale.yml
  2. +1
    -1
      README.md
  3. +21
    -10
      code/build.sh
  4. +76
    -59
      code/espurna/api.ino
  5. +1
    -1
      code/espurna/config/all.h
  6. +2
    -1
      code/espurna/config/arduino.h
  7. +1
    -1
      code/espurna/config/defaults.h
  8. +24
    -4
      code/espurna/config/general.h
  9. +92
    -8
      code/espurna/config/hardware.h
  10. +19
    -12
      code/espurna/config/progmem.h
  11. +2
    -0
      code/espurna/config/prototypes.h
  12. +44
    -24
      code/espurna/config/sensors.h
  13. +32
    -33
      code/espurna/config/types.h
  14. +1
    -1
      code/espurna/config/version.h
  15. BIN
      code/espurna/data/index.all.html.gz
  16. BIN
      code/espurna/data/index.sensor.html.gz
  17. +1
    -1
      code/espurna/eeprom.ino
  18. +1
    -1
      code/espurna/hardware.ino
  19. +4
    -4
      code/espurna/homeassistant.ino
  20. +2
    -2
      code/espurna/i2c.ino
  21. +58
    -55
      code/espurna/ir.ino
  22. +1
    -1
      code/espurna/led.ino
  23. +8
    -2
      code/espurna/ota.ino
  24. +9
    -10
      code/espurna/relay.ino
  25. +106
    -78
      code/espurna/sensor.ino
  26. +6
    -6
      code/espurna/sensors/BaseSensor.h
  27. +1
    -1
      code/espurna/sensors/DHTSensor.h
  28. +3
    -3
      code/espurna/sensors/EmonSensor.h
  29. +29
    -12
      code/espurna/sensors/EventSensor.h
  30. +38
    -11
      code/espurna/sensors/PMSX003Sensor.h
  31. +39
    -32
      code/espurna/sensors/SonarSensor.h
  32. +1
    -1
      code/espurna/ssdp.ino
  33. +655
    -655
      code/espurna/static/index.all.html.gz.h
  34. +298
    -298
      code/espurna/static/index.sensor.html.gz.h
  35. +27
    -5
      code/espurna/web.ino
  36. +4
    -1
      code/extra_scripts.py
  37. +4
    -3
      code/html/custom.js
  38. +2
    -4
      code/memanalyzer.py
  39. +45
    -6
      code/platformio.ini

+ 2
- 2
.github/stale.yml View File

@ -1,9 +1,9 @@
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 120
daysUntilStale: 60
# Number of days of inactivity before a stale Issue or Pull Request is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 30
daysUntilClose: 7
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:


+ 1
- 1
README.md View File

@ -3,7 +3,7 @@
ESPurna ("spark" in Catalan) is a custom firmware for ESP8285/ESP8266 based smart switches, lights and sensors.
It uses the Arduino Core for ESP8266 framework and a number of 3rd party libraries.
[![version](https://img.shields.io/badge/version-1.13.2a-brightgreen.svg)](CHANGELOG.md)
[![version](https://img.shields.io/badge/version-1.13.2c-brightgreen.svg)](CHANGELOG.md)
[![branch](https://img.shields.io/badge/branch-softcfg-orange.svg)](https://github.com/xoseperez/espurna/tree/softcfg/)
[![travis](https://travis-ci.org/xoseperez/espurna.svg?branch=softcfg)](https://travis-ci.org/xoseperez/espurna)
[![codacy](https://img.shields.io/codacy/grade/c9496e25cf07434cba786b462cb15f49/softcfg.svg)](https://www.codacy.com/app/xoseperez/espurna/dashboard)


+ 21
- 10
code/build.sh View File

@ -1,19 +1,26 @@
#!/bin/bash
set -e
# Utility
is_git() {
command -v git >/dev/null 2>&1 || return 1
command git rev-parse >/dev/null 2>&1 || return 1
return 0
}
# Script settings
version=$(grep APP_VERSION espurna/config/version.h | awk '{print $3}' | sed 's/"//g')
(command -v git && git rev-parse --is-inside-work-tree) 2>&1>/dev/null
if [ $? -eq 0 ]; then
if is_git; then
git_revision=$(git rev-parse --short HEAD)
git_version=$(git describe --tags)
git_version=${version}-${git_revision}
else
git_revision=
git_version=$version
fi
par_build=0
par_build=false
par_thread=${BUILDER_THREAD:-0}
par_total_threads=${BUILDER_TOTAL_THREADS:-4}
if [ ${par_thread} -ne ${par_thread} -o \
@ -27,8 +34,12 @@ if [ ${par_thread} -ge ${par_total_threads} ]; then
fi
# Available environments
travis=$(grep env: platformio.ini | grep travis | sed 's/\[env://' | sed 's/\]/ /' | sort)
available=$(grep env: platformio.ini | grep -v ota | grep -v ssl | grep -v travis | sed 's/\[env://' | sed 's/\]/ /' | sort)
list_envs() {
grep env: platformio.ini | sed 's/\[env:\(.*\)\]/\1/g'
}
travis=$(list_envs | grep travis | sort)
available=$(list_envs | grep -Ev -- '-ota$|-ssl$|^travis' | sort)
# Build tools settings
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DAPP_REVISION='\"$git_revision\"'"
@ -52,7 +63,7 @@ print_environments() {
set_default_environments() {
# Hook to build in parallel when using travis
if [[ "${TRAVIS_BUILD_STAGE_NAME}" = "Release" ]] && [ ${par_build} ]; then
if [[ "${TRAVIS_BUILD_STAGE_NAME}" = "Release" ]] && ${par_build}; then
environments=$(echo ${available} | \
awk -v par_thread=${par_thread} -v par_total_threads=${par_total_threads} \
'{ for (i = 1; i <= NF; i++) if (++j % par_total_threads == par_thread ) print $i; }')
@ -90,7 +101,7 @@ build_environments() {
for environment in $environments; do
echo -n "* espurna-$version-$environment.bin --- "
platformio run --silent --environment $environment || exit 1
platformio run --silent --environment $environment 2>/dev/null || exit 1
stat -c %s .pioenvs/$environment/firmware.bin
[[ "${TRAVIS_BUILD_STAGE_NAME}" = "Test" ]] || \
mv .pioenvs/$environment/firmware.bin ../firmware/espurna-$version/espurna-$version-$environment.bin
@ -106,7 +117,7 @@ while getopts "lp" opt; do
exit
;;
p)
par_build=1
par_build=true
;;
esac
done
@ -125,7 +136,7 @@ if [ $# -eq 0 ]; then
set_default_environments
fi
if [[ "${CI}" = true ]]; then
if ${CI:-false}; then
print_environments
fi


+ 76
- 59
code/espurna/api.ino View File

@ -72,52 +72,6 @@ bool _asJson(AsyncWebServerRequest *request) {
return asJson;
}
ArRequestHandlerFunction _bindAPI(unsigned int apiID) {
return [apiID](AsyncWebServerRequest *request) {
webLog(request);
if (!_authAPI(request)) return;
web_api_t api = _apis[apiID];
// Check if its a PUT
if (api.putFn != NULL) {
if (request->hasParam("value", request->method() == HTTP_PUT)) {
AsyncWebParameter* p = request->getParam("value", request->method() == HTTP_PUT);
(api.putFn)((p->value()).c_str());
}
}
// Get response from callback
char value[API_BUFFER_SIZE] = {0};
(api.getFn)(value, API_BUFFER_SIZE);
// The response will be a 404 NOT FOUND if the resource is not available
if (0 == value[0]) {
DEBUG_MSG_P(PSTR("[API] Sending 404 response\n"));
request->send(404);
return;
}
DEBUG_MSG_P(PSTR("[API] Sending response '%s'\n"), value);
// Format response according to the Accept header
if (_asJson(request)) {
char buffer[64];
if (isNumber(value)) {
snprintf_P(buffer, sizeof(buffer), PSTR("{ \"%s\": %s }"), api.key, value);
} else {
snprintf_P(buffer, sizeof(buffer), PSTR("{ \"%s\": \"%s\" }"), api.key, value);
}
request->send(200, "application/json", buffer);
} else {
request->send(200, "text/plain", value);
}
};
}
void _onAPIs(AsyncWebServerRequest *request) {
webLog(request);
@ -174,35 +128,98 @@ void _onRPC(AsyncWebServerRequest *request) {
}
bool _apiRequestCallback(AsyncWebServerRequest *request) {
String url = request->url();
// Main API entry point
if (url.equals("/api") || url.equals("/apis")) {
_onAPIs(request);
return true;
}
// Main RPC entry point
if (url.equals("/rpc")) {
_onRPC(request);
return true;
}
// Not API request
if (!url.startsWith("/api/")) return false;
for (unsigned char i=0; i < _apis.size(); i++) {
// Search API url
web_api_t api = _apis[i];
if (!url.endsWith(api.key)) continue;
// Log and check credentials
webLog(request);
if (!_authAPI(request)) return false;
// Check if its a PUT
if (api.putFn != NULL) {
if (request->hasParam("value", request->method() == HTTP_PUT)) {
AsyncWebParameter* p = request->getParam("value", request->method() == HTTP_PUT);
(api.putFn)((p->value()).c_str());
}
}
// Get response from callback
char value[API_BUFFER_SIZE] = {0};
(api.getFn)(value, API_BUFFER_SIZE);
// The response will be a 404 NOT FOUND if the resource is not available
if (0 == value[0]) {
DEBUG_MSG_P(PSTR("[API] Sending 404 response\n"));
request->send(404);
return false;
}
DEBUG_MSG_P(PSTR("[API] Sending response '%s'\n"), value);
// Format response according to the Accept header
if (_asJson(request)) {
char buffer[64];
if (isNumber(value)) {
snprintf_P(buffer, sizeof(buffer), PSTR("{ \"%s\": %s }"), api.key, value);
} else {
snprintf_P(buffer, sizeof(buffer), PSTR("{ \"%s\": \"%s\" }"), api.key, value);
}
request->send(200, "application/json", buffer);
} else {
request->send(200, "text/plain", value);
}
return true;
}
return false;
}
// -----------------------------------------------------------------------------
void apiRegister(const char * key, api_get_callback_f getFn, api_put_callback_f putFn) {
// Store it
web_api_t api;
char buffer[40];
snprintf_P(buffer, sizeof(buffer), PSTR("/api/%s"), key);
api.key = strdup(key);
api.getFn = getFn;
api.putFn = putFn;
_apis.push_back(api);
// Bind call
unsigned int methods = HTTP_GET;
if (putFn != NULL) methods += HTTP_PUT;
webServer()->on(buffer, methods, _bindAPI(_apis.size() - 1));
}
bool apiRealTime() {
return getSetting("apiRealTime", API_REAL_TIME_VALUES).toInt() == 1;
}
void apiSetup() {
webServer()->on("/apis", HTTP_GET, _onAPIs);
webServer()->on("/rpc", HTTP_GET, _onRPC);
wsOnSendRegister(_apiWebSocketOnSend);
settingsRegisterKeyCheck(_apiKeyCheck);
}
bool apiRealTime() {
return getSetting("apiRealTime", API_REAL_TIME_VALUES).toInt() == 1;
webRequestRegister(_apiRequestCallback);
wsOnSendRegister(_apiWebSocketOnSend);
}
#endif // WEB_SUPPORT

+ 1
- 1
code/espurna/config/all.h View File

@ -29,9 +29,9 @@
#include "hardware.h"
#include "defaults.h"
#include "general.h"
#include "dependencies.h"
#include "prototypes.h"
#include "sensors.h"
#include "dependencies.h"
#include "progmem.h"
#include "debug.h"


+ 2
- 1
code/espurna/config/arduino.h View File

@ -8,6 +8,7 @@
//--------------------------------------------------------------------------------
//#define NODEMCU_LOLIN
//#define WEMOS_D1_MINI
//#define WEMOS_D1_MINI_RELAYSHIELD
//#define TINKERMAN_ESPURNA_H06
//#define TINKERMAN_ESPURNA_H08
@ -140,7 +141,6 @@
//#define EMON_ANALOG_SUPPORT 1
//#define EVENTS_SUPPORT 1
//#define GUVAS12SD_SUPPORT 1
//#define HCSR04_SUPPORT 1
//#define HLW8012_SUPPORT 1
//#define MHZ19_SUPPORT 1
//#define NTC_SUPPORT 1
@ -148,6 +148,7 @@
//#define PZEM004T_SUPPORT 1
//#define SHT3X_I2C_SUPPORT 1
//#define SI7021_SUPPORT 1
//#define SONAR_SUPPORT 1
//#define TMP3X_SUPPORT 1
//#define V9261F_SUPPORT 1
//#define GEIGER_SUPPORT 1

+ 1
- 1
code/espurna/config/defaults.h View File

@ -2,7 +2,7 @@
// Hardware default values
// -----------------------------------------------------------------------------
#define GPIO_NONE 0x99
#define GPIO_NONE 0xFF
// -----------------------------------------------------------------------------
// Buttons


+ 24
- 4
code/espurna/config/general.h View File

@ -259,6 +259,14 @@
#define RELAY_SAVE_DELAY 1000
#endif
// Configure the MQTT payload for ON/OFF
#ifndef RELAY_MQTT_ON
#define RELAY_MQTT_ON "1"
#endif
#ifndef RELAY_MQTT_OFF
#define RELAY_MQTT_OFF "0"
#endif
// -----------------------------------------------------------------------------
// WIFI
// -----------------------------------------------------------------------------
@ -693,6 +701,7 @@
#define MQTT_TOPIC_BOARD "board"
#define MQTT_TOPIC_PULSE "pulse"
#define MQTT_TOPIC_SPEED "speed"
#define MQTT_TOPIC_IR "ir"
// Light module
#define MQTT_TOPIC_CHANNEL "channel"
@ -865,6 +874,14 @@
#define HOMEASSISTANT_ENABLED 0 // Integration not enabled by default
#define HOMEASSISTANT_PREFIX "homeassistant" // Default MQTT prefix
#ifndef HOMEASSISTANT_PAYLOAD_ON
#define HOMEASSISTANT_PAYLOAD_ON "1" // Payload for ON and available messages
#endif
#ifndef HOMEASSISTANT_PAYLOAD_OFF
#define HOMEASSISTANT_PAYLOAD_OFF "0" // Payload for OFF and unavailable messages
#endif
// -----------------------------------------------------------------------------
// INFLUXDB
// -----------------------------------------------------------------------------
@ -1020,7 +1037,6 @@
#define RF_RECEIVE_DELAY 500 // Interval between recieving in ms (avoid debouncing)
#endif
#ifndef RF_RAW_SUPPORT
#define RF_RAW_SUPPORT 0 // RF raw codes require a specific firmware for the EFM8BB1
// https://github.com/rhx/RF-Bridge-EFM8BB1
@ -1035,8 +1051,8 @@
#define IR_SUPPORT 0 // Do not build with IR support by default (10.25Kb)
#endif
#ifndef IR_PIN
#define IR_PIN 4 // IR LED
#ifndef IR_RECEIVER_PIN
#define IR_RECEIVER_PIN 4 // IR LED
#endif
// 24 Buttons Set of the IR Remote
@ -1044,6 +1060,10 @@
#define IR_BUTTON_SET 1 // IR button set to use (see below)
#endif
#ifndef IR_DEBOUNCE
#define IR_DEBOUNCE 500 // IR debounce time in milliseconds
#endif
//Remote Buttons SET 1 (for the original Remote shipped with the controller)
#if IR_SUPPORT
#if IR_BUTTON_SET == 1
@ -1066,7 +1086,7 @@
#define IR_BUTTON_COUNT 24
const unsigned long IR_BUTTON[IR_BUTTON_COUNT][3] PROGMEM = {
const uint32_t IR_BUTTON[IR_BUTTON_COUNT][3] PROGMEM = {
{ 0xFF906F, IR_BUTTON_MODE_BRIGHTER, 1 },
{ 0xFFB847, IR_BUTTON_MODE_BRIGHTER, 0 },


+ 92
- 8
code/espurna/config/hardware.h View File

@ -65,6 +65,26 @@
#include "devices/002_nodemcu_lolin.json.h"
#elif defined(WEMOS_D1_MINI)
// Info
#define MANUFACTURER "WEMOS"
#define DEVICE "D1_MINI"
// Buttons
// No buttons on the D1 MINI alone, but defining it without adding a button doen't create problems
#define BUTTON1_PIN 0 // Connect a pushbutton between D3 and GND,
// it's the same as using a Wemos one button shield
#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
#define BUTTON1_RELAY 1
// LEDs
#define LED1_PIN 2
#define LED1_PIN_INVERSE 1
#define I2C_SDA_PIN 4 // D2
#define I2C_SCL_PIN 5 // D1
#elif defined(WEMOS_D1_MINI_RELAYSHIELD)
#include "devices/003_wemos_d1_mini_relayshield.json.h"
@ -982,7 +1002,7 @@
// IR
#define IR_SUPPORT 1
#define IR_PIN 4
#define IR_RECEIVER_PIN 4
#define IR_BUTTON_SET 1
#elif defined(MAGICHOME_LED_CONTROLLER_20)
@ -1011,7 +1031,7 @@
// IR
#define IR_SUPPORT 1
#define IR_PIN 4
#define IR_RECEIVER_PIN 4
#define IR_BUTTON_SET 1
// -----------------------------------------------------------------------------
@ -2109,7 +2129,7 @@
#define BUTTON1_PIN 12
#define BUTTON1_RELAY 1
#define BUTTON1_MODE BUTTON_SWITCH | BUTTON_DEFAULT_HIGH //Hardware Pullup
#define BUTTON1_PRESS BUTTON_MODE_NONE
#define BUTTON1_CLICK BUTTON_MODE_TOGGLE
#define BUTTON1_DBLCLICK BUTTON_MODE_NONE
@ -2318,6 +2338,60 @@
#define HLW8012_POWER_RATIO 3414290
#define HLW8012_INTERRUPT_ON FALLING
// ----------------------------------------------------------------------------------------
// Homecube 16A is similar but some pins differ and it also has RGB LEDs
// https://www.amazon.de/gp/product/B07D7RVF56/ref=oh_aui_detailpage_o00_s01?ie=UTF8&psc=1
// ----------------------------------------------------------------------------------------
#elif defined(HOMECUBE_16A)
// Info
#define MANUFACTURER "HOMECUBE"
#define DEVICE "16A"
// Buttons
#define BUTTON1_PIN 13
#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
#define BUTTON1_RELAY 1
// Relays
#define RELAY1_PIN 15
#define RELAY1_TYPE RELAY_TYPE_NORMAL
// LEDs
//LED Pin 4 - ESP8266 onboard LED
//Red LED: 0
//Green LED: 12
//Blue LED: 2
// Blue
#define LED1_PIN 2
#define LED1_PIN_INVERSE 0
// Green
#define LED2_PIN 12
#define LED2_PIN_INVERSE 1
#define LED2_MODE LED_MODE_RELAY
// Red
#define LED3_PIN 0
#define LED3_PIN_INVERSE 0
#define LED2_MODE LED_MODE_OFF
// HJL01 / BL0937
#ifndef HLW8012_SUPPORT
#define HLW8012_SUPPORT 1
#endif
#define HLW8012_SEL_PIN 16
#define HLW8012_CF1_PIN 14
#define HLW8012_CF_PIN 5
#define HLW8012_SEL_CURRENT LOW
#define HLW8012_CURRENT_RATIO 25740
#define HLW8012_VOLTAGE_RATIO 313400
#define HLW8012_POWER_RATIO 3414290
#define HLW8012_INTERRUPT_ON FALLING
// -----------------------------------------------------------------------------
// VANZAVANZU Smart Outlet Socket (based on BL0937 or HJL-01)
// https://www.amazon.com/Smart-Plug-Wifi-Mini-VANZAVANZU/dp/B078PHD6S5
@ -2506,6 +2580,11 @@
#define MANUFACTURER "TravisCI"
#define DEVICE "Virtual board 02"
// Some buttons - pin 0
#define BUTTON1_PIN 0
#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
#define BUTTON1_RELAY 1
// A bit of CSE7766 - pin 1
#ifndef CSE7766_SUPPORT
#define CSE7766_SUPPORT 1
@ -2521,7 +2600,7 @@
// IR - pin 4
#define IR_SUPPORT 1
#define IR_PIN 4
#define IR_RECEIVER_PIN 4
#define IR_BUTTON_SET 1
// A bit of DHT - pin 5
@ -2537,10 +2616,10 @@
#define EVENTS_SUPPORT 1
#define EVENTS_PIN 6
// HC-RS04
#define HCSR04_SUPPORT 1
#define HCSR04_TRIGGER 7
#define HCSR04_ECHO 8
// Sonar
#define SONAR_SUPPORT 1
#define SONAR_TRIGGER 7
#define SONAR_ECHO 8
// MHZ19
#define MHZ19_SUPPORT 1
@ -2573,6 +2652,11 @@
#define MANUFACTURER "TravisCI"
#define DEVICE "Virtual board 03"
// Some buttons - pin 0
#define BUTTON1_PIN 0
#define BUTTON1_MODE BUTTON_PUSHBUTTON | BUTTON_DEFAULT_HIGH
#define BUTTON1_RELAY 1
// MY9231 Light - pins 1,2
#define RELAY_PROVIDER RELAY_PROVIDER_LIGHT
#define LIGHT_PROVIDER LIGHT_PROVIDER_MY92XX


+ 19
- 12
code/espurna/config/progmem.h View File

@ -58,6 +58,9 @@ PROGMEM const char espurna_modules[] =
#if INFLUXDB_SUPPORT
"INFLUXDB "
#endif
#if IR_SUPPORT
"IR "
#endif
#if LLMNR_SUPPORT
"LLMNR "
#endif
@ -166,8 +169,8 @@ PROGMEM const char espurna_sensors[] =
#if GUVAS12SD_SUPPORT
"GUVAS12SD "
#endif
#if HCSR04_SUPPORT
"HCSR04 "
#if SONAR_SUPPORT
"SONAR "
#endif
#if HLW8012_SUPPORT
"HLW8012 "
@ -204,12 +207,13 @@ PROGMEM const char espurna_sensors[] =
PROGMEM const unsigned char magnitude_decimals[] = {
0,
1, 0, 2,
3, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0,
0, 0, 0,
0, 0, 3, 3,
4, 4 // Geiger Counter decimals
1, 0, 2, // THP
3, 0, 0, 0, 0, 0, 0, 0, // Power decimals
0, 0, 0, // analog, digital, event
0, 0, 0, // PM
0, 0, 3, 3, 0,
4, 4, // Geiger Counter decimals
0
};
PROGMEM const char magnitude_unknown_topic[] = "unknown";
@ -226,7 +230,7 @@ PROGMEM const char magnitude_energy_topic[] = "energy";
PROGMEM const char magnitude_energy_delta_topic[] = "energy_delta";
PROGMEM const char magnitude_analog_topic[] = "analog";
PROGMEM const char magnitude_digital_topic[] = "digital";
PROGMEM const char magnitude_events_topic[] = "events";
PROGMEM const char magnitude_event_topic[] = "event";
PROGMEM const char magnitude_pm1dot0_topic[] = "pm1dot0";
PROGMEM const char magnitude_pm2dot5_topic[] = "pm2dot5";
PROGMEM const char magnitude_pm10_topic[] = "pm10";
@ -237,17 +241,19 @@ PROGMEM const char magnitude_distance_topic[] = "distance";
PROGMEM const char magnitude_hcho_topic[] = "hcho";
PROGMEM const char magnitude_geiger_cpm_topic[] = "ldr_cpm"; // local dose rate [Counts per minute]
PROGMEM const char magnitude_geiger_sv_topic[] = "ldr_uSvh"; // local dose rate [µSievert per hour]
PROGMEM const char magnitude_count_topic[] = "count";
PROGMEM const char* const magnitude_topics[] = {
magnitude_unknown_topic, magnitude_temperature_topic, magnitude_humidity_topic,
magnitude_pressure_topic, magnitude_current_topic, magnitude_voltage_topic,
magnitude_active_power_topic, magnitude_apparent_power_topic, magnitude_reactive_power_topic,
magnitude_power_factor_topic, magnitude_energy_topic, magnitude_energy_delta_topic,
magnitude_analog_topic, magnitude_digital_topic, magnitude_events_topic,
magnitude_analog_topic, magnitude_digital_topic, magnitude_event_topic,
magnitude_pm1dot0_topic, magnitude_pm2dot5_topic, magnitude_pm10_topic,
magnitude_co2_topic, magnitude_lux_topic, magnitude_uv_topic,
magnitude_distance_topic, magnitude_hcho_topic,
magnitude_geiger_cpm_topic, magnitude_geiger_sv_topic // Geiger Counter topics
magnitude_geiger_cpm_topic, magnitude_geiger_sv_topic,
magnitude_count_topic
};
PROGMEM const char magnitude_empty[] = "";
@ -280,7 +286,8 @@ PROGMEM const char* const magnitude_units[] = {
magnitude_ugm3, magnitude_ugm3, magnitude_ugm3,
magnitude_ppm, magnitude_lux, magnitude_uv,
magnitude_distance, magnitude_mgm3,
magnitude_geiger_cpm, magnitude_geiger_sv // Geiger counter units
magnitude_geiger_cpm, magnitude_geiger_sv, // Geiger counter units
magnitude_empty
};
#endif

+ 2
- 0
code/espurna/config/prototypes.h View File

@ -144,6 +144,8 @@ void nice_delay(unsigned long ms);
#define AsyncWebSocket void
#define AwsEventType void *
#endif
typedef std::function<bool(AsyncWebServerRequest *request)> web_request_callback_f;
void webRequestRegister(web_request_callback_f callback);
// -----------------------------------------------------------------------------
// WebSockets


+ 44
- 24
code/espurna/config/sensors.h View File

@ -281,6 +281,11 @@
#define EVENTS_SUPPORT 0 // Do not build with counter support by default
#endif
#ifndef EVENTS_TRIGGER
#define EVENTS_TRIGGER 1 // 1 to trigger callback on events,
// 0 to only count them and report periodically
#endif
#ifndef EVENTS_PIN
#define EVENTS_PIN 2 // GPIO to monitor
#endif
@ -337,23 +342,6 @@
#define GUVAS12SD_PIN 14
#endif
//------------------------------------------------------------------------------
// HC-SR04
// Enable support by passing HCSR04_SUPPORT=1 build flag
//------------------------------------------------------------------------------
#ifndef HCSR04_SUPPORT
#define HCSR04_SUPPORT 0
#endif
#ifndef HCSR04_TRIGGER
#define HCSR04_TRIGGER 12 // GPIO for the trigger pin (output)
#endif
#ifndef HCSR04_ECHO
#define HCSR04_ECHO 14 // GPIO for the echo pin (input)
#endif
//------------------------------------------------------------------------------
// HLW8012 Energy monitor IC
// Enable support by passing HLW8012_SUPPORT=1 build flag
@ -504,14 +492,21 @@
#define PMS_SMART_SLEEP 0
#endif
#ifndef PMS_USE_SOFT
#define PMS_USE_SOFT 0 // If PMS_USE_SOFT == 1, DEBUG_SERIAL_SUPPORT must be 0
#endif
#ifndef PMS_RX_PIN
#define PMS_RX_PIN 13
#define PMS_RX_PIN 13 // Software serial RX GPIO (if PMS_USE_SOFT == 1)
#endif
#ifndef PMS_TX_PIN
#define PMS_TX_PIN 15
#define PMS_TX_PIN 15 // Software serial TX GPIO (if PMS_USE_SOFT == 1)
#endif
#ifndef PMS_HW_PORT
#define PMS_HW_PORT Serial // Hardware serial port (if PMS_USE_SOFT == 0)
#endif
//------------------------------------------------------------------------------
// PZEM004T based power monitor
// Enable support by passing PZEM004T_SUPPORT=1 build flag
@ -563,6 +558,31 @@
#define SI7021_ADDRESS 0x00 // 0x00 means auto
#endif
//------------------------------------------------------------------------------
// Sonar
// Enable support by passing SONAR_SUPPORT=1 build flag
//------------------------------------------------------------------------------
#ifndef SONAR_SUPPORT
#define SONAR_SUPPORT 0
#endif
#ifndef SONAR_TRIGGER
#define SONAR_TRIGGER 12 // GPIO for the trigger pin (output)
#endif
#ifndef SONAR_ECHO
#define SONAR_ECHO 14 // GPIO for the echo pin (input)
#endif
#ifndef SONAR_MAX_DISTANCE
#define SONAR_MAX_DISTANCE MAX_SENSOR_DISTANCE // Max sensor distance in cm
#endif
#ifndef SONAR_ITERATIONS
#define SONAR_ITERATIONS 5 // Number of iterations to ping for
#endif // error correction.
//------------------------------------------------------------------------------
// TMP3X analog temperature sensor
// Enable support by passing TMP3X_SUPPORT=1 build flag
@ -623,7 +643,6 @@
EVENTS_SUPPORT || \
GEIGER_SUPPORT || \
GUVAS12SD_SUPPORT || \
HCSR04_SUPPORT || \
HLW8012_SUPPORT || \
MHZ19_SUPPORT || \
NTC_SUPPORT || \
@ -632,6 +651,7 @@
PZEM004T_SUPPORT || \
SHT3X_I2C_SUPPORT || \
SI7021_SUPPORT || \
SONAR_SUPPORT || \
TMP3X_SUPPORT || \
V9261F_SUPPORT \
)
@ -743,10 +763,6 @@
#include "../sensors/GUVAS12SDSensor.h"
#endif
#if HCSR04_SUPPORT
#include "../sensors/HCSR04Sensor.h"
#endif
#if HLW8012_SUPPORT
#include <HLW8012.h>
#include "../sensors/HLW8012Sensor.h"
@ -785,6 +801,10 @@
#include "../sensors/SHT3XI2CSensor.h"
#endif
#if SONAR_SUPPORT
#include "../sensors/SonarSensor.h"
#endif
#if TMP3X_SUPPORT
#include "../sensors/TMP3XSensor.h"
#endif


+ 32
- 33
code/espurna/config/types.h View File

@ -84,36 +84,36 @@
//------------------------------------------------------------------------------
// Priority codes:
#define SYSLOG_EMERG 0 /* system is unusable */
#define SYSLOG_ALERT 1 /* action must be taken immediately */
#define SYSLOG_CRIT 2 /* critical conditions */
#define SYSLOG_ERR 3 /* error conditions */
#define SYSLOG_WARNING 4 /* warning conditions */
#define SYSLOG_NOTICE 5 /* normal but significant condition */
#define SYSLOG_INFO 6 /* informational */
#define SYSLOG_DEBUG 7 /* debug-level messages */
#define SYSLOG_EMERG 0 /* system is unusable */
#define SYSLOG_ALERT 1 /* action must be taken immediately */
#define SYSLOG_CRIT 2 /* critical conditions */
#define SYSLOG_ERR 3 /* error conditions */
#define SYSLOG_WARNING 4 /* warning conditions */
#define SYSLOG_NOTICE 5 /* normal but significant condition */
#define SYSLOG_INFO 6 /* informational */
#define SYSLOG_DEBUG 7 /* debug-level messages */
// Facility codes:
#define SYSLOG_KERN (0<<3) /* kernel messages */
#define SYSLOG_USER (1<<3) /* random user-level messages */
#define SYSLOG_MAIL (2<<3) /* mail system */
#define SYSLOG_DAEMON (3<<3) /* system daemons */
#define SYSLOG_AUTH (4<<3) /* security/authorization messages */
#define SYSLOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
#define SYSLOG_LPR (6<<3) /* line printer subsystem */
#define SYSLOG_NEWS (7<<3) /* network news subsystem */
#define SYSLOG_UUCP (8<<3) /* UUCP subsystem */
#define SYSLOG_CRON (9<<3) /* clock daemon */
#define SYSLOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
#define SYSLOG_FTP (11<<3) /* ftp daemon */
#define SYSLOG_LOCAL0 (16<<3) /* reserved for local use */
#define SYSLOG_LOCAL1 (17<<3) /* reserved for local use */
#define SYSLOG_LOCAL2 (18<<3) /* reserved for local use */
#define SYSLOG_LOCAL3 (19<<3) /* reserved for local use */
#define SYSLOG_LOCAL4 (20<<3) /* reserved for local use */
#define SYSLOG_LOCAL5 (21<<3) /* reserved for local use */
#define SYSLOG_LOCAL6 (22<<3) /* reserved for local use */
#define SYSLOG_LOCAL7 (23<<3) /* reserved for local use */
#define SYSLOG_KERN (0<<3) /* kernel messages */
#define SYSLOG_USER (1<<3) /* random user-level messages */
#define SYSLOG_MAIL (2<<3) /* mail system */
#define SYSLOG_DAEMON (3<<3) /* system daemons */
#define SYSLOG_AUTH (4<<3) /* security/authorization messages */
#define SYSLOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
#define SYSLOG_LPR (6<<3) /* line printer subsystem */
#define SYSLOG_NEWS (7<<3) /* network news subsystem */
#define SYSLOG_UUCP (8<<3) /* UUCP subsystem */
#define SYSLOG_CRON (9<<3) /* clock daemon */
#define SYSLOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */
#define SYSLOG_FTP (11<<3) /* ftp daemon */
#define SYSLOG_LOCAL0 (16<<3) /* reserved for local use */
#define SYSLOG_LOCAL1 (17<<3) /* reserved for local use */
#define SYSLOG_LOCAL2 (18<<3) /* reserved for local use */
#define SYSLOG_LOCAL3 (19<<3) /* reserved for local use */
#define SYSLOG_LOCAL4 (20<<3) /* reserved for local use */
#define SYSLOG_LOCAL5 (21<<3) /* reserved for local use */
#define SYSLOG_LOCAL6 (22<<3) /* reserved for local use */
#define SYSLOG_LOCAL7 (23<<3) /* reserved for local use */
//------------------------------------------------------------------------------
// MQTT
@ -267,7 +267,7 @@
#define SENSOR_GUVAS12SD_ID 0x20
#define SENSOR_CSE7766_ID 0x21
#define SENSOR_TMP3X_ID 0x22
#define SENSOR_HCSR04_ID 0x23
#define SENSOR_SONAR_ID 0x23
#define SENSOR_SENSEAIR_ID 0x24
#define SENSOR_GEIGER_ID 0x25
#define SENSOR_NTC_ID 0x26
@ -290,7 +290,7 @@
#define MAGNITUDE_ENERGY_DELTA 11
#define MAGNITUDE_ANALOG 12
#define MAGNITUDE_DIGITAL 13
#define MAGNITUDE_EVENTS 14
#define MAGNITUDE_EVENT 14
#define MAGNITUDE_PM1dot0 15
#define MAGNITUDE_PM2dot5 16
#define MAGNITUDE_PM10 17
@ -301,14 +301,13 @@
#define MAGNITUDE_HCHO 22
#define MAGNITUDE_GEIGER_CPM 23
#define MAGNITUDE_GEIGER_SIEVERT 24
#define MAGNITUDE_COUNT 25
#define MAGNITUDE_MAX 25
#define MAGNITUDE_MAX 26
//--------------------------------------------------------------------------------
// GPIO
//--------------------------------------------------------------------------------
#define GPIO_NONE 0xFF
#define GPIO_LOGIC_DIRECT 0
#define GPIO_LOGIC_INVERSE 1

+ 1
- 1
code/espurna/config/version.h View File

@ -1,5 +1,5 @@
#define APP_NAME "ESPURNA"
#define APP_VERSION "1.13.2a"
#define APP_VERSION "1.13.2c"
#define APP_AUTHOR "xose.perez@gmail.com"
#define APP_WEBSITE "http://tinkerman.cat"
#define CFG_VERSION 4

BIN
code/espurna/data/index.all.html.gz View File


BIN
code/espurna/data/index.sensor.html.gz View File


+ 1
- 1
code/espurna/eeprom.ino View File

@ -12,7 +12,7 @@ Module key prefix: eep
// -----------------------------------------------------------------------------
bool eepromRotate(bool value) {
void eepromRotate(bool value) {
// Enable/disable EEPROM rotation only if we are using more sectors than the
// reserved by the memory layout
if (EEPROMr.size() > EEPROMr.reserved()) {


+ 1
- 1
code/espurna/hardware.ino View File

@ -1876,7 +1876,7 @@ void _hardwareSpecific() {
// These devices use the hardware UART
// to communicate to secondary microcontrollers
#if defined(ITEAD_SONOFF_RFBRIDGE) || defined(ITEAD_SONOFF_DUAL) || defined(STM_RELAY)
#if defined(ITEAD_SONOFF_RFBRIDGE) || defined(ITEAD_SONOFF_DUAL) || (RELAY_PROVIDER == RELAY_PROVIDER_STM)
Serial.begin(DEBUG_SERIAL_SPEED);
#endif


+ 4
- 4
code/espurna/homeassistant.ino View File

@ -75,11 +75,11 @@ void _haSendSwitch(unsigned char i, JsonObject& config) {
if (relayCount()) {
config["state_topic"] = mqttTopic(MQTT_TOPIC_RELAY, i, false);
config["command_topic"] = mqttTopic(MQTT_TOPIC_RELAY, i, true);
config["payload_on"] = String("1");
config["payload_off"] = String("0");
config["payload_on"] = String(HOMEASSISTANT_PAYLOAD_ON);
config["payload_off"] = String(HOMEASSISTANT_PAYLOAD_OFF);
config["availability_topic"] = mqttTopic(MQTT_TOPIC_STATUS, false);
config["payload_available"] = String("1");
config["payload_not_available"] = String("0");
config["payload_available"] = String(HOMEASSISTANT_PAYLOAD_ON);
config["payload_not_available"] = String(HOMEASSISTANT_PAYLOAD_OFF);
}
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE


+ 2
- 2
code/espurna/i2c.ino View File

@ -236,7 +236,7 @@ uint16_t i2c_read_uint16(uint8_t address, uint8_t reg) {
void i2c_read_buffer(uint8_t address, uint8_t * buffer, size_t len) {
Wire.beginTransmission((uint8_t) address);
Wire.requestFrom(address, (uint8_t) len);
for (int i=0; i<len; i++) buffer[i] = Wire.read();
for (size_t i=0; i<len; i++) buffer[i] = Wire.read();
Wire.endTransmission();
}
@ -338,7 +338,7 @@ unsigned char i2cFind(size_t size, unsigned char * addresses) {
unsigned char i2cFindAndLock(size_t size, unsigned char * addresses) {
unsigned char start = 0;
unsigned char address = 0;
while (address = i2cFind(size, addresses, start)) {
while ((address = i2cFind(size, addresses, start))) {
if (i2cGetLock(address)) break;
start++;
}


+ 58
- 55
code/espurna/ir.ino View File

@ -22,80 +22,84 @@ unsigned long _ir_last_toggle = 0;
// PRIVATE
// -----------------------------------------------------------------------------
void _irProcessCode(unsigned long code) {
void _irProcessCode(unsigned long code, unsigned char type) {
static unsigned long last_code;
boolean found = false;
// Check valid code
unsigned long last_code = 0;
unsigned long last_time = 0;
if (code == 0xFFFFFFFF) return;
if (type == 0xFF) return;
if ((last_code == code) && (millis() - last_time < IR_DEBOUNCE)) return;
last_code = code;
DEBUG_MSG_P(PSTR("[IR] Received 0x%08X (%d)\n"), code, type);
// Repeat last valid code
DEBUG_MSG_P(PSTR("[IR] Received 0x%06X\n"), code);
if (code == 0xFFFFFFFF) {
DEBUG_MSG_P(PSTR("[IR] Processing 0x%06X\n"), code);
code = last_code;
}
#if IR_BUTTON_SET > 0
for (unsigned char i = 0; i < IR_BUTTON_COUNT ; i++) {
boolean found = false;
unsigned long button_code = pgm_read_dword(&IR_BUTTON[i][0]);
if (code == button_code) {
for (unsigned char i = 0; i < IR_BUTTON_COUNT ; i++) {
unsigned long button_mode = pgm_read_dword(&IR_BUTTON[i][1]);
unsigned long button_value = pgm_read_dword(&IR_BUTTON[i][2]);
uint32_t button_code = pgm_read_dword(&IR_BUTTON[i][0]);
if (code == button_code) {
if (button_mode == IR_BUTTON_MODE_STATE) {
relayStatus(0, button_value);
}
unsigned long button_mode = pgm_read_dword(&IR_BUTTON[i][1]);
unsigned long button_value = pgm_read_dword(&IR_BUTTON[i][2]);
if (button_mode == IR_BUTTON_MODE_TOGGLE) {
if (button_mode == IR_BUTTON_MODE_STATE) {
relayStatus(0, button_value);
}
if (millis() - _ir_last_toggle > 250){
if (button_mode == IR_BUTTON_MODE_TOGGLE) {
relayToggle(button_value);
_ir_last_toggle = millis();
} else {
DEBUG_MSG_P(PSTR("[IR] Ignoring repeated code\n"));
}
}
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
#if LIGHT_PROVIDER != LIGHT_PROVIDER_NONE
if (button_mode == IR_BUTTON_MODE_BRIGHTER) {
lightBrightnessStep(button_value ? 1 : -1);
nice_delay(150); //debounce
}
if (button_mode == IR_BUTTON_MODE_BRIGHTER) {
lightBrightnessStep(button_value ? 1 : -1);
nice_delay(150); //debounce
}
if (button_mode == IR_BUTTON_MODE_RGB) {
lightColor(button_value);
}
if (button_mode == IR_BUTTON_MODE_RGB) {
lightColor(button_value);
}
/*
#if LIGHT_PROVIDER == LIGHT_PROVIDER_FASTLED
if (button_mode == IR_BUTTON_MODE_EFFECT) {
_buttonAnimMode(button_value);
/*
#if LIGHT_PROVIDER == LIGHT_PROVIDER_FASTLED
if (button_mode == IR_BUTTON_MODE_EFFECT) {
_buttonAnimMode(button_value);
}
#endif
*/
/*
if (button_mode == IR_BUTTON_MODE_HSV) {
lightColor(button_value);
}
#endif
*/
*/
/*
if (button_mode == IR_BUTTON_MODE_HSV) {
lightColor(button_value);
}
*/
lightUpdate(true, true);
lightUpdate(true, true);
#endif
#endif
found = true;
break;
found = true;
last_code = code;
break;
}
}
}
}
if (!found) {
DEBUG_MSG_P(PSTR("[IR] Ignoring code\n"));
}
if (!found) {
DEBUG_MSG_P(PSTR("[IR] Ignoring code\n"));
}
#endif
#if MQTT_SUPPORT
char buffer[16];
snprintf_P(buffer, sizeof(buffer), "0x%08X", code);
mqttSend(MQTT_TOPIC_IR, buffer);
#endif
}
@ -109,7 +113,7 @@ bool _irKeyCheck(const char * key) {
void irSetup() {
_ir_recv = new IRrecv(IR_PIN);
_ir_recv = new IRrecv(IR_RECEIVER_PIN);
_ir_recv->enableIRIn();
// Key Check
@ -122,8 +126,7 @@ void irSetup() {
void irLoop() {
if (_ir_recv->decode(&_ir_results)) {
unsigned long code = _ir_results.value;
_irProcessCode(code);
_irProcessCode(_ir_results.value, _ir_results.decode_type);
_ir_recv->resume(); // Receive the next value
}
}


+ 1
- 1
code/espurna/led.ino View File

@ -304,4 +304,4 @@ void ledSetup() {
}
#endif LED_SUPPORT
#endif // LED_SUPPORT

+ 8
- 2
code/espurna/ota.ino View File

@ -246,8 +246,14 @@ void otaSetup() {
deferredReset(100, CUSTOM_RESET_OTA);
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
DEBUG_MSG_P(PSTR("[OTA] Progress: %u%%\r"), (progress / (total / 100)));
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
static unsigned int _progOld;
unsigned int _prog = (progress / (total / 100));
if (_prog != _progOld) {
DEBUG_MSG_P(PSTR("[OTA] Progress: %u%%\r"), _prog);
_progOld = _prog;
}
});
ArduinoOTA.onError([](ota_error_t error) {


+ 9
- 10
code/espurna/relay.ino View File

@ -101,7 +101,7 @@ void _relayProviderStatus(unsigned char id, bool status) {
if (_relays.size() == lightChannels()) {
lightState(id, status);
lightState(true);
} else if (_relays.size() == lightChannels() + 1) {
} else if (_relays.size() == (lightChannels() + 1u)) {
if (id == 0) {
lightState(status);
} else {
@ -561,6 +561,8 @@ void _relayConfigure() {
pinMode(pin, OUTPUT);
unsigned char type = getSetting("rlyType", index, RELAY_TYPE_NORMAL).toInt();
if (RELAY_TYPE_INVERSE == type) digitalWrite(pin, HIGH);
unsigned char reset = getSetting("rlyResetGPIO", index, GPIO_NONE).toInt();
if (GPIO_NONE != reset) pinMode(reset, OUTPUT);
@ -568,7 +570,7 @@ void _relayConfigure() {
unsigned long delay_off = getSetting("rlyDelayOff", index, 0).toInt();
unsigned char pulse = getSetting("rlyPulse", index, RELAY_PULSE_MODE).toInt();
float pulse_ms = 1000 * getSetting("rlyTime", index, RELAY_PULSE_TIME).toFloat();
unsigned long pulse_ms = 1000 * getSetting("rlyTime", index, RELAY_PULSE_TIME).toFloat();
_relays.push_back((relay_t) { pin, type, reset, delay_on, delay_off, pulse, pulse_ms });
++index;
@ -678,11 +680,11 @@ void relaySetupWS() {
void relaySetupAPI() {
char key[20];
// API entry points (protected with apikey)
for (unsigned int relayID=0; relayID<relayCount(); relayID++) {
char key[20];
snprintf_P(key, sizeof(key), PSTR("%s/%d"), MQTT_TOPIC_RELAY, relayID);
apiRegister(key,
[relayID](char * buffer, size_t len) {
@ -726,9 +728,6 @@ void relaySetupAPI() {
_relays[relayID].pulse = relayStatus(relayID) ? RELAY_PULSE_ON : RELAY_PULSE_OFF;
relayToggle(relayID, true, false);
return;
}
);
@ -764,7 +763,7 @@ void relayMQTT(unsigned char id) {
// Send state topic
if (_relays[id].report) {
_relays[id].report = false;
mqttSend(MQTT_TOPIC_RELAY, id, _relays[id].current_status ? "1" : "0");
mqttSend(MQTT_TOPIC_RELAY, id, _relays[id].current_status ? RELAY_MQTT_ON : RELAY_MQTT_OFF);
}
// Check group topic
@ -774,7 +773,7 @@ void relayMQTT(unsigned char id) {
if (t.length() > 0) {
bool status = relayStatus(id);
if (getSetting("mqttGroupInv", id, 0).toInt() == 1) status = !status;
mqttSendRaw(t.c_str(), status ? "1" : "0");
mqttSendRaw(t.c_str(), status ? RELAY_MQTT_ON : RELAY_MQTT_OFF);
}
}
@ -789,7 +788,7 @@ void relayMQTT(unsigned char id) {
void relayMQTT() {
for (unsigned int id=0; id < _relays.size(); id++) {
mqttSend(MQTT_TOPIC_RELAY, id, _relays[id].current_status ? "1" : "0");
mqttSend(MQTT_TOPIC_RELAY, id, _relays[id].current_status ? RELAY_MQTT_ON : RELAY_MQTT_OFF);
}
}


+ 106
- 78
code/espurna/sensor.ino View File

@ -109,6 +109,8 @@ void _sensorWebSocketSendData(JsonObject& root) {
for (unsigned char i=0; i<_magnitudes.size(); i++) {
sensor_magnitude_t magnitude = _magnitudes[i];
if (magnitude.type == MAGNITUDE_EVENT) continue;
unsigned char decimals = _magnitudeDecimals(magnitude.type);
dtostrf(magnitude.current, 1-sizeof(buffer), decimals, buffer);
@ -440,7 +442,8 @@ void _sensorLoad() {
{
EventSensor * sensor = new EventSensor();
sensor->setGPIO(EVENTS_PIN);
sensor->setMode(EVENTS_PIN_MODE);
sensor->setTrigger(EVENTS_TRIGGER);
sensor->setPinMode(EVENTS_PIN_MODE);
sensor->setDebounceTime(EVENTS_DEBOUNCE);
sensor->setInterruptMode(EVENTS_INTERRUPT_MODE);
_sensors.push_back(sensor);
@ -467,11 +470,13 @@ void _sensorLoad() {
}
#endif
#if HCSR04_SUPPORT
#if SONAR_SUPPORT
{
HCSR04Sensor * sensor = new HCSR04Sensor();
sensor->setTrigger(HCSR04_TRIGGER);
sensor->setEcho(HCSR04_ECHO);
SonarSensor * sensor = new SonarSensor();
sensor->setEcho(SONAR_ECHO);
sensor->setIterations(SONAR_ITERATIONS);
sensor->setMaxDistance(SONAR_MAX_DISTANCE);
sensor->setTrigger(SONAR_TRIGGER);
_sensors.push_back(sensor);
}
#endif
@ -522,8 +527,12 @@ void _sensorLoad() {
#if PMSX003_SUPPORT
{
PMSX003Sensor * sensor = new PMSX003Sensor();
sensor->setRX(PMS_RX_PIN);
sensor->setTX(PMS_TX_PIN);
#if PMS_USE_SOFT
sensor->setRX(PMS_RX_PIN);
sensor->setTX(PMS_TX_PIN);
#else
sensor->setSerial(& PMS_HW_PORT);
#endif
sensor->setType(PMS_TYPE);
_sensors.push_back(sensor);
}
@ -577,8 +586,17 @@ void _sensorLoad() {
}
void _sensorCallback(unsigned char i, unsigned char type, const char * payload) {
DEBUG_MSG_P(PSTR("[SENSOR] Sensor #%u callback, type %u, payload: '%s'\n"), i, type, payload);
void _sensorCallback(unsigned char i, unsigned char type, double value) {
DEBUG_MSG_P(PSTR("[SENSOR] Sensor #%u callback, type %u, payload: '%s'\n"), i, type, String(value).c_str());
for (unsigned char k=0; k<_magnitudes.size(); k++) {
if ((_sensors[i] == _magnitudes[k].sensor) && (type == _magnitudes[k].type)) {
_sensorReport(k, value);
return;
}
}
}
void _sensorInit() {
@ -615,7 +633,7 @@ void _sensorInit() {
new_magnitude.min_change = 0;
if (type == MAGNITUDE_DIGITAL) {
new_magnitude.filter = new MaxFilter();
} else if (type == MAGNITUDE_EVENTS || type == MAGNITUDE_GEIGER_CPM|| type == MAGNITUDE_GEIGER_SIEVERT) { // For geiger counting moving average filter is the most appropriate if needed at all.
} else if (type == MAGNITUDE_COUNT || type == MAGNITUDE_GEIGER_CPM|| type == MAGNITUDE_GEIGER_SIEVERT) { // For geiger counting moving average filter is the most appropriate if needed at all.
new_magnitude.filter = new MovingAverageFilter();
} else {
new_magnitude.filter = new MedianFilter();
@ -630,8 +648,8 @@ void _sensorInit() {
}
// Hook callback
_sensors[i]->onEvent([i](unsigned char type, const char * payload) {
_sensorCallback(i, type, payload);
_sensors[i]->onEvent([i](unsigned char type, double value) {
_sensorCallback(i, type, value);
});
// Custom initializations
@ -714,7 +732,7 @@ void _sensorConfigure() {
double value;
EmonAnalogSensor * sensor = (EmonAnalogSensor *) _sensors[i];
if (value = getSetting("pwrExpected", 0).toInt()) {
if ((value = getSetting("pwrExpected", 0).toInt())) {
sensor->expectedPower(0, value);
setSetting("curRatio", sensor->getCurrentRatio(0));
}
@ -801,17 +819,17 @@ void _sensorConfigure() {
double value;
CSE7766Sensor * sensor = (CSE7766Sensor *) _sensors[i];
if (value = getSetting("curExpected", 0).toFloat()) {
if ((value = getSetting("curExpected", 0).toFloat())) {
sensor->expectedCurrent(value);
setSetting("curRatio", sensor->getCurrentRatio());
}
if (value = getSetting("volExpected", 0).toInt()) {
if ((value = getSetting("volExpected", 0).toInt())) {
sensor->expectedVoltage(value);
setSetting("volRatio", sensor->getVoltageRatio());
}
if (value = getSetting("pwrExpected", 0).toInt()) {
if ((value = getSetting("pwrExpected", 0).toInt())) {
sensor->expectedPower(value);
setSetting("pwrRatio", sensor->getPowerRatio());
}
@ -887,6 +905,73 @@ void _sensorBackwards() {
moveSetting("pwrExpectedV", "volExpected"); // 1.14.0 - 2018-06-26
moveSetting("pwrResetCalibration", "snsResetCalibration"); // 1.14.0 - 2018-06-26
moveSetting("pwrResetE", "eneReset"); // 1.14.0 - 2018-06-26
}
void _sensorReport(unsigned char index, double value) {
sensor_magnitude_t magnitude = _magnitudes[index];
unsigned char decimals = _magnitudeDecimals(magnitude.type);
char buffer[10];
dtostrf(value, 1-sizeof(buffer), decimals, buffer);
#if BROKER_SUPPORT
brokerPublish(magnitudeTopic(magnitude.type).c_str(), magnitude.local, buffer);
#endif
#if MQTT_SUPPORT
mqttSend(magnitudeTopicIndex(index).c_str(), buffer);
#if SENSOR_PUBLISH_ADDRESSES
char topic[32];
snprintf(topic, sizeof(topic), "%s/%s", SENSOR_ADDRESS_TOPIC, magnitudeTopic(magnitude.type).c_str());
if (SENSOR_USE_INDEX || (_counts[magnitude.type] > 1)) {
mqttSend(topic, magnitude.global, magnitude.sensor->address(magnitude.local).c_str());
} else {
mqttSend(topic, magnitude.sensor->address(magnitude.local).c_str());
}
#endif // SENSOR_PUBLISH_ADDRESSES
#endif // MQTT_SUPPORT
#if INFLUXDB_SUPPORT
if (SENSOR_USE_INDEX || (_counts[magnitude.type] > 1)) {
idbSend(magnitudeTopic(magnitude.type).c_str(), magnitude.global, buffer);
} else {
idbSend(magnitudeTopic(magnitude.type).c_str(), buffer);
}
#endif // INFLUXDB_SUPPORT
#if THINGSPEAK_SUPPORT
tspkEnqueueMeasurement(index, buffer);
#endif
#if DOMOTICZ_SUPPORT
{
char key[15];
snprintf_P(key, sizeof(key), PSTR("dczMagnitude%d"), index);
if (magnitude.type == MAGNITUDE_HUMIDITY) {
int status;
if (value > 70) {
status = HUMIDITY_WET;
} else if (value > 45) {
status = HUMIDITY_COMFORTABLE;
} else if (value > 30) {
status = HUMIDITY_NORMAL;
} else {
status = HUMIDITY_DRY;
}
char status_buf[5];
itoa(status, status_buf, 10);
domoticzSend(key, buffer, status_buf);
} else {
domoticzSend(key, 0, buffer);
}
}
#endif // DOMOTICZ_SUPPORT
}
// -----------------------------------------------------------------------------
@ -1026,7 +1111,6 @@ void sensorLoop() {
double current;
double filtered;
char buffer[64];
// Pre-read hook
_sensorPre();
@ -1062,19 +1146,18 @@ void sensorLoop() {
magnitude.filter->add(current);
// Special case
if (magnitude.type == MAGNITUDE_EVENTS) {
if (magnitude.type == MAGNITUDE_COUNT) {
current = magnitude.filter->result();
}
current = _magnitudeProcess(magnitude.type, current);
_magnitudes[i].current = current;
unsigned char decimals = _magnitudeDecimals(magnitude.type);
// Debug
#if SENSOR_DEBUG
{
dtostrf(current, 1-sizeof(buffer), decimals, buffer);
char buffer[64];
dtostrf(current, 1-sizeof(buffer), _magnitudeDecimals(magnitude.type), buffer);
DEBUG_MSG_P(PSTR("[SENSOR] %s - %s: %s%s\n"),
magnitude.sensor->slot(magnitude.local).c_str(),
magnitudeTopic(magnitude.type).c_str(),
@ -1096,63 +1179,8 @@ void sensorLoop() {
if (fabs(filtered - magnitude.reported) >= magnitude.min_change) {
_magnitudes[i].reported = filtered;
dtostrf(filtered, 1-sizeof(buffer), decimals, buffer);
#if BROKER_SUPPORT
brokerPublish(magnitudeTopic(magnitude.type).c_str(), magnitude.local, buffer);
#endif
#if MQTT_SUPPORT
mqttSend(magnitudeTopicIndex(i).c_str(), buffer);
#if SENSOR_PUBLISH_ADDRESSES
char topic[32];
snprintf(topic, sizeof(topic), "%s/%s", SENSOR_ADDRESS_TOPIC, magnitudeTopic(magnitude.type).c_str());
if (SENSOR_USE_INDEX || (_counts[magnitude.type] > 1)) {
mqttSend(topic, magnitude.global, magnitude.sensor->address(magnitude.local).c_str());
} else {
mqttSend(topic, magnitude.sensor->address(magnitude.local).c_str());
}
#endif // SENSOR_PUBLISH_ADDRESSES
#endif // MQTT_SUPPORT
#if INFLUXDB_SUPPORT
if (SENSOR_USE_INDEX || (_counts[magnitude.type] > 1)) {
idbSend(magnitudeTopic(magnitude.type).c_str(), magnitude.global, buffer);
} else {
idbSend(magnitudeTopic(magnitude.type).c_str(), buffer);
}
#endif // INFLUXDB_SUPPORT
#if THINGSPEAK_SUPPORT
tspkEnqueueMeasurement(i, buffer);
#endif
#if DOMOTICZ_SUPPORT
{
char key[15];
snprintf_P(key, sizeof(key), PSTR("dczMagnitude%d"), i);
if (magnitude.type == MAGNITUDE_HUMIDITY) {
int status;
if (filtered > 70) {
status = HUMIDITY_WET;
} else if (filtered > 45) {
status = HUMIDITY_COMFORTABLE;
} else if (filtered > 30) {
status = HUMIDITY_NORMAL;
} else {
status = HUMIDITY_DRY;
}
char status_buf[5];
itoa(status, status_buf, 10);
domoticzSend(key, buffer, status_buf);
} else {
domoticzSend(key, 0, buffer);
}
}
#endif // DOMOTICZ_SUPPORT
_sensorReport(i, filtered);
} // if (fabs(filtered - magnitude.reported) >= magnitude.min_change)
} // if (report_count == 0)


+ 6
- 6
code/espurna/sensors/BaseSensor.h View File

@ -21,7 +21,7 @@
#define SENSOR_ERROR_CALIBRATION 8 // Calibration error or Not calibrated
#define SENSOR_ERROR_OTHER 99 // Any other error
typedef std::function<void(unsigned char, const char *)> TSensorCallback;
typedef std::function<void(unsigned char, double)> TSensorCallback;
class BaseSensor {
@ -46,19 +46,19 @@ class BaseSensor {
virtual void post() {}
// Descriptive name of the sensor
virtual String description() {}
virtual String description() = 0;
// Address of the sensor (it could be the GPIO or I2C address)
virtual String address(unsigned char index) {}
virtual String address(unsigned char index) = 0;
// Descriptive name of the slot # index
virtual String slot(unsigned char index) {};
virtual String slot(unsigned char index) = 0;
// Type for slot # index
virtual unsigned char type(unsigned char index) {}
virtual unsigned char type(unsigned char index) = 0;
// Current value for slot # index
virtual double value(unsigned char index) {}
virtual double value(unsigned char index) = 0;
// Retrieve current instance configuration
virtual void getConfig(JsonObject& root) {};


+ 1
- 1
code/espurna/sensors/DHTSensor.h View File

@ -221,7 +221,7 @@ class DHTSensor : public BaseSensor {
}
unsigned long _signal(int usTimeOut, bool state) {
unsigned long _signal(unsigned long usTimeOut, bool state) {
unsigned long uSec = 1;
while (digitalRead(_gpio) == state) {
if (++uSec > usTimeOut) return 0;


+ 3
- 3
code/espurna/sensors/EmonSensor.h View File

@ -146,7 +146,7 @@ class EmonSensor : public I2CSensor {
#endif
}
virtual unsigned int readADC(unsigned char channel) {}
virtual unsigned int readADC(unsigned char channel) = 0;
void calculateFactors(unsigned char channel) {
@ -154,8 +154,8 @@ class EmonSensor : public I2CSensor {
unsigned int s = 1;
unsigned int i = 1;
unsigned int m = s * i;
unsigned int multiplier;
unsigned int m = 1;
unsigned int multiplier = 1;
while (m * _current_factor[channel] < 1) {
multiplier = m;
i = (i == 1) ? 2 : (i == 2) ? 5 : 1;


+ 29
- 12
code/espurna/sensors/EventSensor.h View File

@ -33,12 +33,16 @@ class EventSensor : public BaseSensor {
_gpio = gpio;
}
void setMode(unsigned char mode) {
_mode = mode;
void setTrigger(bool trigger) {
_trigger = trigger;
}
void setInterruptMode(unsigned char mode) {
_interrupt_mode = mode;
void setPinMode(unsigned char pin_mode) {
_pin_mode = pin_mode;
}
void setInterruptMode(unsigned char interrupt_mode) {
_interrupt_mode = interrupt_mode;
}
void setDebounceTime(unsigned long debounce) {
@ -51,8 +55,12 @@ class EventSensor : public BaseSensor {
return _gpio;
}
unsigned char getMode() {
return _mode;
bool getTrigger() {
return _trigger;
}
unsigned char getPinMode() {
return _pin_mode;
}
unsigned char getInterruptMode() {
@ -70,8 +78,9 @@ class EventSensor : public BaseSensor {
// Initialization method, must be idempotent
// Defined outside the class body
void begin() {
pinMode(_gpio, _mode);
pinMode(_gpio, _pin_mode);
_enableInterrupts(true);
_count = _trigger ? 2 : 1;
_ready = true;
}
@ -94,7 +103,8 @@ class EventSensor : public BaseSensor {
// Type for slot # index
unsigned char type(unsigned char index) {
if (index == 0) return MAGNITUDE_EVENTS;
if (index == 0) return MAGNITUDE_COUNT;
if (index == 1) return MAGNITUDE_EVENT;
return MAGNITUDE_NONE;
}
@ -113,8 +123,14 @@ class EventSensor : public BaseSensor {
(void) gpio;
static unsigned long last = 0;
if (millis() - last > _debounce) {
_events = _events + 1;
last = millis();
_events = _events + 1;
if (_trigger) {
if (_callback) _callback(MAGNITUDE_EVENT, digitalRead(gpio));
}
}
}
@ -148,9 +164,10 @@ class EventSensor : public BaseSensor {
volatile unsigned long _events = 0;
unsigned long _debounce = EVENTS_DEBOUNCE;
unsigned char _gpio;
unsigned char _mode;
unsigned char _interrupt_mode;
unsigned char _gpio = GPIO_NONE;
bool _trigger = false;
unsigned char _pin_mode = INPUT;
unsigned char _interrupt_mode = RISING;
};


+ 38
- 11
code/espurna/sensors/PMSX003Sensor.h View File

@ -12,7 +12,12 @@
#include "Arduino.h"
#include "BaseSensor.h"
#if PMS_USE_SOFT
#include <SoftwareSerial.h>
#endif
// Generic data
#define PMS_BAUD_RATE 9600
// Type of sensor
#define PMS_TYPE_X003 0
@ -46,7 +51,7 @@ const static struct {
class PMSX003 {
protected:
SoftwareSerial *_serial = NULL; // Should initialized by child class
Stream *_serial = NULL; // Should initialized by child class
public:
@ -175,7 +180,13 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
_dirty = true;
}
// Should call setType after constrcutor immediately to enable corresponding slot count
void setSerial(HardwareSerial * serial) {
_soft = false;
_serial = serial;
_dirty = true;
}
// Should call setType after constructor immediately to enable corresponding slot count
void setType(unsigned char type) {
_type = type;
_count = pms_specs[_type].slot_count;
@ -204,30 +215,45 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
if (!_dirty) return;
if (_serial) delete _serial;
if (_soft) {
if (_serial) delete _serial;
_serial = new SoftwareSerial(_pin_rx, _pin_tx, false, 64);
static_cast<SoftwareSerial*>(_serial)->enableIntTx(false);
}
if (_soft) {
static_cast<SoftwareSerial*>(_serial)->begin(PMS_BAUD_RATE);
} else {
static_cast<HardwareSerial*>(_serial)->begin(PMS_BAUD_RATE);
}
_serial = new SoftwareSerial(_pin_rx, _pin_tx, false, 64);
_serial->enableIntTx(false);
_serial->begin(9600);
passiveMode();
_startTime = millis();
_ready = true;
_dirty = false;
}
// Descriptive name of the sensor
String description() {
char buffer[28];
snprintf(buffer, sizeof(buffer), "%s @ SwSerial(%u,%u)", pms_specs[_type].name, _pin_rx, _pin_tx);
if (_soft) {
snprintf(buffer, sizeof(buffer), "%s @ SwSerial(%u,%u)", pms_specs[_type].name, _pin_rx, _pin_tx);
} else {
snprintf(buffer, sizeof(buffer), "%s @ HwSerial", pms_specs[_type].name);
}
return String(buffer);
}
// Descriptive name of the slot # index
String slot(unsigned char index) {
char buffer[36] = {0};
snprintf(buffer, sizeof(buffer), "%d @ %s @ SwSerial(%u,%u)", int(index + 1), pms_specs[_type].name, _pin_rx, _pin_tx);
if (_soft) {
snprintf(buffer, sizeof(buffer), "%d @ %s @ SwSerial(%u,%u)", int(index + 1), pms_specs[_type].name, _pin_rx, _pin_tx);
} else {
snprintf(buffer, sizeof(buffer), "%d @ %s @ HwSerial", int(index + 1), pms_specs[_type].name);
}
return String(buffer);
}
@ -301,7 +327,7 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
#endif
requestRead();
}
// Current value for slot # index
@ -310,6 +336,7 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
}
protected:
bool _soft = true;
unsigned int _pin_rx;
unsigned int _pin_tx;
unsigned long _startTime;
@ -322,4 +349,4 @@ class PMSX003Sensor : public BaseSensor, PMSX003 {
};
#endif // SENSOR_SUPPORT && PMS_SUPPORT
#endif // SENSOR_SUPPORT && PMSX003_SUPPORT

code/espurna/sensors/HCSR04Sensor.h → code/espurna/sensors/SonarSensor.h View File

@ -1,16 +1,18 @@
// -----------------------------------------------------------------------------
// HC-SR04 Ultrasonic sensor
// HC-SR04, SRF05, SRF06, DYP-ME007, JSN-SR04T & Parallax PING)))
// Copyright (C) 2018 by Xose Pérez <xose dot perez at gmail dot com>
// Enhancements by Rui Marinho
// -----------------------------------------------------------------------------
#if SENSOR_SUPPORT && HCSR04_SUPPORT
#if SENSOR_SUPPORT && SONAR_SUPPORT
#pragma once
#include "Arduino.h"
#include "BaseSensor.h"
#include "NewPing.h"
class HCSR04Sensor : public BaseSensor {
class SonarSensor : public BaseSensor {
public:
@ -18,17 +20,30 @@ class HCSR04Sensor : public BaseSensor {
// Public
// ---------------------------------------------------------------------
HCSR04Sensor(): BaseSensor() {
SonarSensor(): BaseSensor() {
_count = 1;
_sensor_id = SENSOR_HCSR04_ID;
_sensor_id = SENSOR_SONAR_ID;
}
// ---------------------------------------------------------------------
// Echo pin.
void setEcho(unsigned char echo) {
_echo = echo;
}
// Number of iterations to ping in order to filter out erroneous readings
// using a digital filter.
void setIterations(unsigned int iterations) {
_iterations = iterations;
}
// Max sensor distance in centimeters.
void setMaxDistance(unsigned int distance) {
_max_distance = distance;
}
// Trigger pin.
void setTrigger(unsigned char trigger) {
_trigger = trigger;
}
@ -43,22 +58,28 @@ class HCSR04Sensor : public BaseSensor {
return _trigger;
}
unsigned int getMaxDistance() {
return _max_distance;
}
unsigned int getIterations() {
return _iterations;
}
// ---------------------------------------------------------------------
// Sensor API
// ---------------------------------------------------------------------
// Initialization method, must be idempotent
void begin() {
pinMode(_echo, INPUT);
pinMode(_trigger, OUTPUT);
digitalWrite(_trigger, LOW);
_sonar = new NewPing(getTrigger(), getEcho(), getMaxDistance());
_ready = true;
}
// Descriptive name of the sensor
String description() {
char buffer[24];
snprintf(buffer, sizeof(buffer), "HCSR04 @ GPIO(%u, %u)", _trigger, _echo);
char buffer[23];
snprintf(buffer, sizeof(buffer), "Sonar @ GPIO(%u, %u)", _trigger, _echo);
return String(buffer);
}
@ -80,28 +101,11 @@ class HCSR04Sensor : public BaseSensor {
// Current value for slot # index
double value(unsigned char index) {
if (index == 0) {
// Trigger pulse
digitalWrite(_trigger, HIGH);
delayMicroseconds(10);
digitalWrite(_trigger, LOW);
// Wait for echo pulse low-high-low
while ( digitalRead(_echo) == 0 ) yield();
unsigned long start = micros();
while ( digitalRead(_echo) == 1 ) yield();
unsigned long travel_time = micros() - start;
// Assuming a speed of sound of 340m/s
// Dividing by 2 since it is a round trip
return 340.0 * (double) travel_time / 1000000.0 / 2;
if (index != 0) return 0;
if (getIterations() > 0) {
return NewPing::convert_cm(_sonar->ping_median(getIterations())) / 100.0;
}
return 0;
return _sonar->ping_cm() / 100.0;
}
@ -113,7 +117,10 @@ class HCSR04Sensor : public BaseSensor {
unsigned char _trigger;
unsigned char _echo;
unsigned int _max_distance;
unsigned int _iterations;
NewPing * _sonar = NULL;
};
#endif // SENSOR_SUPPORT && HCSR04_SUPPORT
#endif // SENSOR_SUPPORT && SONAR_SUPPORT

+ 1
- 1
code/espurna/ssdp.ino View File

@ -48,7 +48,7 @@ void ssdpSetup() {
char response[strlen_P(_ssdp_template) + 100];
snprintf_P(response, sizeof(response), _ssdp_template,
WiFi.localIP().toString().c_str(), // ip
ip.toString().c_str(), // ip
webPort(), // port
SSDP_DEVICE_TYPE, // device type
getHostname().c_str(), // friendlyName


+ 655
- 655
code/espurna/static/index.all.html.gz.h
File diff suppressed because it is too large
View File


+ 298
- 298
code/espurna/static/index.sensor.html.gz.h View File

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

+ 27
- 5
code/espurna/web.ino View File

@ -47,6 +47,8 @@ char _last_modified[50];
std::vector<uint8_t> * _webConfigBuffer;
bool _webConfigSuccess = false;
std::vector<web_request_callback_f> _web_request_callbacks;
// -----------------------------------------------------------------------------
// HOOKS
// -----------------------------------------------------------------------------
@ -93,7 +95,9 @@ void _onGetConfig(AsyncWebServerRequest *request) {
response->printf("{\n\"app\": \"%s\"", APP_NAME);
response->printf(",\n\"version\": \"%s\"", APP_VERSION);
response->printf(",\n\"backup\": \"1\"");
response->printf(",\n\"timestamp\": \"%s\"", ntpDateTime().c_str());
#if NTP_SUPPORT
response->printf(",\n\"timestamp\": \"%s\"", ntpDateTime().c_str());
#endif
// Write the keys line by line (not sorted)
unsigned long count = settingsKeyCount();
@ -330,6 +334,19 @@ bool _webKeyCheck(const char * key) {
return (strncmp(key, "web", 3) == 0);
}
void _onRequest(AsyncWebServerRequest *request){
// Send request to subscribers
for (unsigned char i = 0; i < _web_request_callbacks.size(); i++) {
bool response = (_web_request_callbacks[i])(request);
if (response) return;
}
// No subscriber handled the request, return a 404
request->send(404);
}
// -----------------------------------------------------------------------------
bool webAuthenticate(AsyncWebServerRequest *request) {
@ -349,6 +366,10 @@ AsyncWebServer * webServer() {
return _server;
}
void webRequestRegister(web_request_callback_f callback) {
_web_request_callbacks.push_back(callback);
}
unsigned int webPort() {
#if ASYNC_TCP_SSL_ENABLED & WEB_SSL_ENABLED
return 443;
@ -385,6 +406,8 @@ void webSetup() {
#if WEB_EMBEDDED
_server->on("/index.html", HTTP_GET, _onHome);
#endif
// Other entry points
_server->on("/reset", HTTP_GET, _onReset);
_server->on("/config", HTTP_GET, _onGetConfig);
_server->on("/config", HTTP_POST | HTTP_PUT, _onPostConfig, _onPostConfigData);
@ -401,10 +424,8 @@ void webSetup() {
});
#endif
// 404
_server->onNotFound([](AsyncWebServerRequest *request){
request->send(404);
});
// Handle other requests, including 404
_server->onNotFound(_onRequest);
// Run server
#if ASYNC_TCP_SSL_ENABLED & WEB_SSL_ENABLED
@ -413,6 +434,7 @@ void webSetup() {
#else
_server->begin();
#endif
DEBUG_MSG_P(PSTR("[WEBSERVER] Webserver running on port %u\n"), port);
// Websocket Callbacks


+ 4
- 1
code/extra_scripts.py View File

@ -10,7 +10,7 @@ from platformio import util
import distutils.spawn
Import("env")
Import("env", "projenv")
# ------------------------------------------------------------------------------
# Utils
@ -86,6 +86,9 @@ def check_size(source, target, env):
# Hooks
# ------------------------------------------------------------------------------
# Always show warnings for project code
projenv.ProcessUnFlags("-w")
remove_float_support()
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", check_size)

+ 4
- 3
code/html/custom.js View File

@ -46,7 +46,7 @@ function sensorName(id) {
"HLW8012", "V9261F", "ECH1560", "Analog", "Digital",
"Events", "PMSX003", "BMX280", "MHZ19", "SI7021",
"SHT3X I2C", "BH1750", "PZEM004T", "AM2320 I2C", "GUVAS12SD",
"TMP3X", "HC-SR04", "SenseAir", "GeigerTicks", "GeigerCPM"
"TMP3X", "Sonar", "SenseAir", "GeigerTicks", "GeigerCPM"
];
if (1 <= id && id <= names.length) {
return names[id - 1];
@ -59,9 +59,10 @@ function magnitudeType(type) {
"Temperature", "Humidity", "Pressure",
"Current", "Voltage", "Active Power", "Apparent Power",
"Reactive Power", "Power Factor", "Energy", "Energy (delta)",
"Analog", "Digital", "Events",
"Analog", "Digital", "Event",
"PM1.0", "PM2.5", "PM10", "CO2", "Lux", "UV", "Distance" , "HCHO",
"Local Dose Rate", "Local Dose Rate"
"Local Dose Rate", "Local Dose Rate",
"Count"
];
if (1 <= type && type <= types.length) {
return types[type - 1];


+ 2
- 4
code/memanalyzer.py View File

@ -55,7 +55,7 @@ def file_size(file):
def analyse_memory(elf_file):
command = "%s -t '%s' " % (objdump_binary, elf_file)
command = "%s -t '%s'" % (objdump_binary, elf_file)
response = subprocess.check_output(shlex.split(command))
if isinstance(response, bytes):
response = response.decode('utf-8')
@ -102,7 +102,7 @@ def run(env_, modules_):
flags = ""
for item in modules_.items():
flags += "-D%s_SUPPORT=%d " % item
command = "export ESPURNA_BOARD=\"WEMOS_D1_MINI_RELAYSHIELD\"; export ESPURNA_FLAGS=\"%s\"; platformio run --silent --environment %s" % (flags, env_)
command = "ESPURNA_BOARD=\"WEMOS_D1_MINI_RELAYSHIELD\" ESPURNA_FLAGS=\"%s\" platformio run --silent --environment %s 2>/dev/null" % (flags, env_)
subprocess.check_call(command, shell=True)
@ -251,6 +251,4 @@ try:
except:
raise
subprocess.check_call("export ESPURNA_BOARD=\"\"; export ESPURNA_FLAGS=\"\"", shell=True)
print("\n")

+ 45
- 6
code/platformio.ini View File

@ -38,7 +38,7 @@ debug_flags = -DDEBUG_ESP_CORE -DDEBUG_ESP_SSL -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP
# -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY = v2 Lower Memory
# -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH = v2 Higher Bandwidth
# ------------------------------------------------------------------------------
build_flags = -g -w -DMQTT_MAX_PACKET_SIZE=400 -DNO_GLOBAL_EEPROM ${env.ESPURNA_FLAGS} -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
build_flags = -g -w -DMQTT_MAX_PACKET_SIZE=400 -DNO_GLOBAL_EEPROM ${sysenv.ESPURNA_FLAGS} -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
build_flags_512k = ${common.build_flags} -Wl,-Teagle.flash.512k0m1s.ld
build_flags_1m0m = ${common.build_flags} -Wl,-Teagle.flash.1m0m1s.ld
build_flags_4m1m = ${common.build_flags} -Wl,-Teagle.flash.4m1m4s.ld
@ -47,8 +47,8 @@ build_flags_4m3m = ${common.build_flags} -Wl,-Teagle.flash.4m3m4s.ld
# ------------------------------------------------------------------------------
# OTA:
# ------------------------------------------------------------------------------
upload_port = "${env.ESPURNA_IP}"
upload_flags = --auth=${env.ESPURNA_AUTH} --port 8266
upload_port = "${sysenv.ESPURNA_IP}"
upload_flags = --auth="${sysenv.ESPURNA_AUTH}"
# ------------------------------------------------------------------------------
# OTHER SETTINGS:
@ -90,6 +90,7 @@ lib_deps =
rc-switch
https://github.com/LowPowerLab/RFM69#1.1.3
https://github.com/xoseperez/Time
NewPing
lib_ignore =
# ------------------------------------------------------------------------------
@ -129,7 +130,7 @@ board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -D${env.ESPURNA_BOARD}
build_flags = ${common.build_flags_1m0m} -D${sysenv.ESPURNA_BOARD}
upload_speed = ${common.upload_speed}
upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags}
@ -142,7 +143,7 @@ board = ${common.board_4m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_4m1m} -D${env.ESPURNA_BOARD}
build_flags = ${common.build_flags_4m1m} -D${sysenv.ESPURNA_BOARD}
upload_speed = ${common.upload_speed}
upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags}
@ -188,6 +189,18 @@ extra_scripts = ${common.extra_scripts}
# DEVELOPMENT BOARDS
# ------------------------------------------------------------------------------
[env:wemos-d1mini]
platform = ${common.platform}
framework = ${common.framework}
board = d1_mini
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags} -DWEMOS_D1_MINI -DDEBUG_FAUXMO=Serial -DNOWSAUTH
upload_speed = ${common.upload_speed_fast}
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:wemos-d1mini-relayshield]
platform = ${common.platform}
framework = ${common.framework}
@ -535,7 +548,7 @@ lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DITEAD_SONOFF_DUAL_R2
extra_scripts = ${common.extra_scripts}
[env:itead-sonoff-dual-ota-r2]
[env:itead-sonoff-dual-r2-ota]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
@ -2348,6 +2361,32 @@ upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags}
extra_scripts = ${common.extra_scripts}
[env:homecube-16a]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DHOMECUBE_16A
upload_speed = ${common.upload_speed}
monitor_speed = ${common.monitor_speed}
extra_scripts = ${common.extra_scripts}
[env:homecube-16a-ota]
platform = ${common.platform}
framework = ${common.framework}
board = ${common.board_1m}
board_build.flash_mode = ${common.flash_mode}
lib_deps = ${common.lib_deps}
lib_ignore = ${common.lib_ignore}
build_flags = ${common.build_flags_1m0m} -DHOMECUBE_16A
upload_speed = ${common.upload_speed}
monitor_speed = ${common.monitor_speed}
upload_port = ${common.upload_port}
upload_flags = ${common.upload_flags}
extra_scripts = ${common.extra_scripts}
[env:bh-onofre]
platform = ${common.platform}
framework = ${common.framework}


Loading…
Cancel
Save