Added step control (all / individual)

Added status LEDs
Added start of location code (geocode latlong request crashes at the moment)
This commit is contained in:
Mark van Renswoude 2018-01-07 23:12:42 +01:00
parent 272535006b
commit 5d6c5f7b74
24 changed files with 4425 additions and 2407 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
bin bin
*.sublime-workspace *.sublime-workspace
node_modules node_modules
src/secret.h

View File

@ -5,8 +5,11 @@
* https://git.x2software.net/pub/Stairs * https://git.x2software.net/pub/Stairs
*/ */
const express = require('express'); const express = require('express');
const bodyParser = require('body-parser');
const app = express(); const app = express();
app.use(bodyParser.json());
app.use(express.static('web')); app.use(express.static('web'));
app.use(express.static('web/dist')); app.use(express.static('web/dist'));
@ -53,6 +56,33 @@ app.post('/api/connection', function(req, res)
res.sendStatus(200); res.sendStatus(200);
}); });
app.post('/api/firmware', function(req, res)
{
res.sendStatus(200);
});
var steps = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
app.get('/api/steps', function(req, res)
{
res.send(steps);
});
app.post('/api/steps', function(req, res)
{
var body = req.body;
if (body && body.hasOwnProperty('values'))
{
for (var i = 0; i < Math.min(steps.length, body.values.length); i++)
steps[i] = parseInt(body.values[i], 10) || 0;
res.sendStatus(200);
}
else
res.sendStatus(400);
});
app.listen(3000, function() app.listen(3000, function()
{ {
console.log('Development server listening on port 3000') console.log('Development server listening on port 3000')

View File

@ -15,6 +15,7 @@
"license": "Unlicense", "license": "Unlicense",
"devDependencies": { "devDependencies": {
"axios": "^0.17.1", "axios": "^0.17.1",
"body-parser": "^1.18.2",
"child_process": "^1.0.2", "child_process": "^1.0.2",
"express": "^4.16.2", "express": "^4.16.2",
"gulp": "^3.9.1", "gulp": "^3.9.1",

View File

@ -18,3 +18,4 @@ lib_deps =
ESP Async WebServer ESP Async WebServer
NTPClient NTPClient
Time Time
build_flags = -D ASYNC_TCP_SSL_ENABLED=1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,249 @@
/**
* The standard ESP8266HTTPClient requires a fingerprint for certificate
* validation as discussed in this issue, starting October 12:
* https://github.com/esp8266/Arduino/issues/1941
*
* This is a modified version which removes validation entirely. It's not
* secure, but for our purpose it will do just fine and prevents
* complicated configuration because we're talking to a Google service
* for which we don't control the certificates.
*
* If there is a proper way to do validation without hardcoding the
* fingerprint (root certificate validation?), remove this.
*
* I've surrounded the customizations with ""//>> h4xx0red" comments.
*/
/**
* ESP8266HTTPClient.h
*
* Created on: 02.11.2015
*
* Copyright (c) 2015 Markus Sattler. All rights reserved.
* This file is part of the ESP8266HTTPClient for Arduino.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef ESP8266HTTPClient_H_
#define ESP8266HTTPClient_H_
#include <memory>
#include <Arduino.h>
#include <WiFiClient.h>
#ifdef DEBUG_ESP_HTTP_CLIENT
#ifdef DEBUG_ESP_PORT
#define DEBUG_HTTPCLIENT(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ )
#endif
#endif
#ifndef DEBUG_HTTPCLIENT
#define DEBUG_HTTPCLIENT(...)
#endif
#define HTTPCLIENT_DEFAULT_TCP_TIMEOUT (5000)
/// HTTP client errors
#define HTTPC_ERROR_CONNECTION_REFUSED (-1)
#define HTTPC_ERROR_SEND_HEADER_FAILED (-2)
#define HTTPC_ERROR_SEND_PAYLOAD_FAILED (-3)
#define HTTPC_ERROR_NOT_CONNECTED (-4)
#define HTTPC_ERROR_CONNECTION_LOST (-5)
#define HTTPC_ERROR_NO_STREAM (-6)
#define HTTPC_ERROR_NO_HTTP_SERVER (-7)
#define HTTPC_ERROR_TOO_LESS_RAM (-8)
#define HTTPC_ERROR_ENCODING (-9)
#define HTTPC_ERROR_STREAM_WRITE (-10)
#define HTTPC_ERROR_READ_TIMEOUT (-11)
/// size for the stream handling
#define HTTP_TCP_BUFFER_SIZE (1460)
/// HTTP codes see RFC7231
typedef enum {
HTTP_CODE_CONTINUE = 100,
HTTP_CODE_SWITCHING_PROTOCOLS = 101,
HTTP_CODE_PROCESSING = 102,
HTTP_CODE_OK = 200,
HTTP_CODE_CREATED = 201,
HTTP_CODE_ACCEPTED = 202,
HTTP_CODE_NON_AUTHORITATIVE_INFORMATION = 203,
HTTP_CODE_NO_CONTENT = 204,
HTTP_CODE_RESET_CONTENT = 205,
HTTP_CODE_PARTIAL_CONTENT = 206,
HTTP_CODE_MULTI_STATUS = 207,
HTTP_CODE_ALREADY_REPORTED = 208,
HTTP_CODE_IM_USED = 226,
HTTP_CODE_MULTIPLE_CHOICES = 300,
HTTP_CODE_MOVED_PERMANENTLY = 301,
HTTP_CODE_FOUND = 302,
HTTP_CODE_SEE_OTHER = 303,
HTTP_CODE_NOT_MODIFIED = 304,
HTTP_CODE_USE_PROXY = 305,
HTTP_CODE_TEMPORARY_REDIRECT = 307,
HTTP_CODE_PERMANENT_REDIRECT = 308,
HTTP_CODE_BAD_REQUEST = 400,
HTTP_CODE_UNAUTHORIZED = 401,
HTTP_CODE_PAYMENT_REQUIRED = 402,
HTTP_CODE_FORBIDDEN = 403,
HTTP_CODE_NOT_FOUND = 404,
HTTP_CODE_METHOD_NOT_ALLOWED = 405,
HTTP_CODE_NOT_ACCEPTABLE = 406,
HTTP_CODE_PROXY_AUTHENTICATION_REQUIRED = 407,
HTTP_CODE_REQUEST_TIMEOUT = 408,
HTTP_CODE_CONFLICT = 409,
HTTP_CODE_GONE = 410,
HTTP_CODE_LENGTH_REQUIRED = 411,
HTTP_CODE_PRECONDITION_FAILED = 412,
HTTP_CODE_PAYLOAD_TOO_LARGE = 413,
HTTP_CODE_URI_TOO_LONG = 414,
HTTP_CODE_UNSUPPORTED_MEDIA_TYPE = 415,
HTTP_CODE_RANGE_NOT_SATISFIABLE = 416,
HTTP_CODE_EXPECTATION_FAILED = 417,
HTTP_CODE_MISDIRECTED_REQUEST = 421,
HTTP_CODE_UNPROCESSABLE_ENTITY = 422,
HTTP_CODE_LOCKED = 423,
HTTP_CODE_FAILED_DEPENDENCY = 424,
HTTP_CODE_UPGRADE_REQUIRED = 426,
HTTP_CODE_PRECONDITION_REQUIRED = 428,
HTTP_CODE_TOO_MANY_REQUESTS = 429,
HTTP_CODE_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
HTTP_CODE_INTERNAL_SERVER_ERROR = 500,
HTTP_CODE_NOT_IMPLEMENTED = 501,
HTTP_CODE_BAD_GATEWAY = 502,
HTTP_CODE_SERVICE_UNAVAILABLE = 503,
HTTP_CODE_GATEWAY_TIMEOUT = 504,
HTTP_CODE_HTTP_VERSION_NOT_SUPPORTED = 505,
HTTP_CODE_VARIANT_ALSO_NEGOTIATES = 506,
HTTP_CODE_INSUFFICIENT_STORAGE = 507,
HTTP_CODE_LOOP_DETECTED = 508,
HTTP_CODE_NOT_EXTENDED = 510,
HTTP_CODE_NETWORK_AUTHENTICATION_REQUIRED = 511
} t_http_codes;
typedef enum {
HTTPC_TE_IDENTITY,
HTTPC_TE_CHUNKED
} transferEncoding_t;
class TransportTraits;
typedef std::unique_ptr<TransportTraits> TransportTraitsPtr;
class HTTPClient
{
public:
HTTPClient();
~HTTPClient();
bool begin(String url);
//>> h4xx0red: renamed to beginSecure, removed fingerprint parameter
bool beginSecure(String url);
//<< h4xx0red
bool begin(String host, uint16_t port, String uri = "/");
bool begin(String host, uint16_t port, String uri, String httpsFingerprint);
// deprecated, use the overload above instead
bool begin(String host, uint16_t port, String uri, bool https, String httpsFingerprint) __attribute__ ((deprecated));
void end(void);
bool connected(void);
void setReuse(bool reuse); /// keep-alive
void setUserAgent(const String& userAgent);
void setAuthorization(const char * user, const char * password);
void setAuthorization(const char * auth);
void setTimeout(uint16_t timeout);
void useHTTP10(bool usehttp10 = true);
/// request handling
int GET();
int POST(uint8_t * payload, size_t size);
int POST(String payload);
int PUT(uint8_t * payload, size_t size);
int PUT(String payload);
int PATCH(uint8_t * payload, size_t size);
int PATCH(String payload);
int sendRequest(const char * type, String payload);
int sendRequest(const char * type, uint8_t * payload = NULL, size_t size = 0);
int sendRequest(const char * type, Stream * stream, size_t size = 0);
void addHeader(const String& name, const String& value, bool first = false, bool replace = true);
/// Response handling
void collectHeaders(const char* headerKeys[], const size_t headerKeysCount);
String header(const char* name); // get request header value by name
String header(size_t i); // get request header value by number
String headerName(size_t i); // get request header name by number
int headers(); // get header count
bool hasHeader(const char* name); // check if header exists
int getSize(void);
WiFiClient& getStream(void);
WiFiClient* getStreamPtr(void);
int writeToStream(Stream* stream);
String getString(void);
static String errorToString(int error);
protected:
struct RequestArgument {
String key;
String value;
};
bool beginInternal(String url, const char* expectedProtocol);
void clear();
int returnError(int error);
bool connect(void);
bool sendHeader(const char * type);
int handleHeaderResponse();
int writeToStreamDataBlock(Stream * stream, int len);
TransportTraitsPtr _transportTraits;
std::unique_ptr<WiFiClient> _tcp;
/// request handling
String _host;
uint16_t _port = 0;
bool _reuse = false;
uint16_t _tcpTimeout = HTTPCLIENT_DEFAULT_TCP_TIMEOUT;
bool _useHTTP10 = false;
String _uri;
String _protocol;
String _headers;
String _userAgent = "ESP8266HTTPClient";
String _base64Authorization;
/// Response handling
RequestArgument* _currentHeaders = nullptr;
size_t _headerKeysCount = 0;
int _returnCode = 0;
int _size = -1;
bool _canReuse = false;
transferEncoding_t _transferEncoding = HTTPC_TE_IDENTITY;
};
#endif /* ESP8266HTTPClient_H_ */

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -4,10 +4,10 @@
const uint8_t VersionMajor = 2; const uint8_t VersionMajor = 2;
const uint8_t VersionMinor = 0; const uint8_t VersionMinor = 0;
const uint8_t VersionPatch = 0; const uint8_t VersionPatch = 0;
const uint8_t VersionMetadata = 9; const uint8_t VersionMetadata = 10;
const char VersionBranch[] = "release/2.0"; const char VersionBranch[] = "release/2.0";
const char VersionSemVer[] = "2.0.0-beta.1"; const char VersionSemVer[] = "2.0.0-beta.1";
const char VersionFullSemVer[] = "2.0.0-beta.1+9"; const char VersionFullSemVer[] = "2.0.0-beta.1+10";
const char VersionCommitDate[] = "2018-01-05"; const char VersionCommitDate[] = "2018-01-07";
#endif #endif

View File

@ -11,10 +11,10 @@
void CharProperties::assignChar(char** field, const char* newValue) void CharProperties::assignChar(char** field, const char* newValue)
{ {
if (*field != NULL) if (*field != nullptr)
delete *field; delete *field;
if (newValue != NULL) if (newValue != nullptr)
{ {
// Include the terminating null character // Include the terminating null character
size_t length = strlen(newValue) + 1; size_t length = strlen(newValue) + 1;
@ -22,5 +22,5 @@ void CharProperties::assignChar(char** field, const char* newValue)
strncpy(*field, newValue, length); strncpy(*field, newValue, length);
} }
else else
*field = NULL; *field = nullptr;
} }

View File

@ -17,6 +17,13 @@ static const uint32_t StationModeTimeout = 30000;
static const char* StepSettingsFile = "/stepsettings"; static const char* StepSettingsFile = "/stepsettings";
// TODO make these configurable through the web interface?
static const uint8_t PinLEDAP = 4;
static const uint8_t PinLEDSTA = 5;
static const uint8_t PinAPButton = 2;
// Pins for the I2C bus // Pins for the I2C bus
static const uint8_t PinSDA = 13; static const uint8_t PinSDA = 13;
static const uint8_t PinSCL = 12; static const uint8_t PinSCL = 12;

View File

@ -25,6 +25,7 @@ extern "C" {
#include "server/settings.h" #include "server/settings.h"
#include "server/firmware.h" #include "server/firmware.h"
#include "server/api.h" #include "server/api.h"
#include "server/geocode.h"
ADC_MODE(ADC_VCC); ADC_MODE(ADC_VCC);
@ -47,13 +48,25 @@ AsyncWebServer server(80);
PCA9685* pwmDriver; PCA9685* pwmDriver;
WiFiUDP ntpUDP; WiFiUDP ntpUDP;
NTPClient* ntpClient = NULL; NTPClient* ntpClient = nullptr;
bool accessPoint = false; bool accessPoint = false;
bool stationMode = false; bool stationMode = false;
bool forceAccessPoint = false; bool forceAccessPoint = false;
uint32_t stationModeStart = 0; uint32_t stationModeStart = 0;
uint32_t blinkOnTime = 0;
enum LEDState
{
Off,
BlinkLow,
BlinkHigh,
On
};
bool ledAP = false;
LEDState ledWiFi = Off;
#ifdef SerialDebug #ifdef SerialDebug
uint32_t debugStatusTime = 0; uint32_t debugStatusTime = 0;
@ -65,6 +78,7 @@ void setup()
_dinit(); _dinit();
currentTime = millis(); currentTime = millis();
blinkOnTime = currentTime;
if (!SPIFFS.begin()) if (!SPIFFS.begin())
_dln("Setup :: failed to mount file system"); _dln("Setup :: failed to mount file system");
@ -73,6 +87,11 @@ void setup()
stepsSettings->read(); stepsSettings->read();
pinMode(PinAPButton, INPUT_PULLUP);
pinMode(PinLEDAP, OUTPUT);
pinMode(PinLEDSTA, OUTPUT);
_dln("Setup :: initializing PCA9685"); _dln("Setup :: initializing PCA9685");
pwmDriver = new PCA9685(); pwmDriver = new PCA9685();
pwmDriver->setAddress(PWMDriverAddress, PinSDA, PinSCL); pwmDriver->setAddress(PWMDriverAddress, PinSDA, PinSCL);
@ -120,6 +139,7 @@ void setup()
registerSettingsRoutes(&server); registerSettingsRoutes(&server);
registerFirmwareRoutes(&server); registerFirmwareRoutes(&server);
registerAPIRoutes(&server); registerAPIRoutes(&server);
registerGeocodeRoutes(&server);
_dln("Setup :: starting HTTP server"); _dln("Setup :: starting HTTP server");
server.onNotFound(handleNotFound); server.onNotFound(handleNotFound);
@ -181,8 +201,12 @@ void loop()
} }
} }
// TODO check AP button
updateLED(); updateLED();
updateNTPClient(); updateNTPClient();
// TODO check for triggers every 10 seconds or so
stairs->tick(); stairs->tick();
} }
@ -193,7 +217,7 @@ void initWiFi()
WiFi.softAPdisconnect(); WiFi.softAPdisconnect();
accessPoint = connectionSettings->flag(AccessPoint) || forceAccessPoint; accessPoint = connectionSettings->flag(AccessPoint) || forceAccessPoint;
stationMode = connectionSettings->flag(StationMode) && connectionSettings->ssid() != NULL; stationMode = connectionSettings->flag(StationMode) && connectionSettings->ssid() != nullptr;
WiFi.mode(accessPoint && stationMode ? WIFI_AP_STA : WiFi.mode(accessPoint && stationMode ? WIFI_AP_STA :
accessPoint ? WIFI_AP : accessPoint ? WIFI_AP :
@ -275,7 +299,7 @@ void updateDebugStatus()
_d("Status :: available heap: "); _d("Status :: available heap: ");
_dln(ESP.getFreeHeap()); _dln(ESP.getFreeHeap());
if (ntpClient != NULL) if (ntpClient != nullptr)
{ {
_d("Status :: time: "); _d("Status :: time: ");
uint32_t time = ntpClient->getEpochTime(); uint32_t time = ntpClient->getEpochTime();
@ -289,27 +313,66 @@ void updateDebugStatus()
void updateLED() void updateLED()
{ {
/* uint8_t value = (currentTime - blinkOnTime >= 1000) ? LOW : HIGH;
// Pulsate the bottom step while WiFi is connecting
uint16_t brightness = 0;
uint16_t speed = 16;
while (WiFi.status() != WL_CONNECTED) WiFiMode_t mode = WiFi.getMode();
if (mode == WIFI_AP_STA || mode == WIFI_AP)
{ {
brightness += speed; if (!ledAP)
if (brightness <= 0 || brightness >= 1024) {
speed = -speed; digitalWrite(PinLEDAP, HIGH);
ledAP = true;
stairs->set(0, brightness);
delay(16);
} }
*/ }
else
{
if (ledAP)
{
digitalWrite(PinLEDAP, LOW);
ledAP = false;
}
}
if (mode == WIFI_AP_STA || mode == WIFI_STA)
{
wl_status_t status = WiFi.status();
if (status == WL_CONNECTED)
{
if (ledWiFi != On)
{
digitalWrite(PinLEDSTA, HIGH);
ledWiFi = On;
}
}
else
{
LEDState expectedState = value == HIGH ? BlinkHigh : BlinkLow;
if (ledWiFi != expectedState)
{
digitalWrite(PinLEDSTA, value);
ledWiFi = expectedState;
}
}
}
else
{
if (ledWiFi != Off)
{
digitalWrite(PinLEDSTA, LOW);
ledWiFi = Off;
}
}
if (currentTime - blinkOnTime >= 2000)
blinkOnTime = currentTime;
} }
void updateNTPClient() void updateNTPClient()
{ {
if (ntpClient == NULL && WiFi.status() == WL_CONNECTED) if (ntpClient == nullptr && WiFi.status() == WL_CONNECTED)
{ {
_dln("NTP :: initializing NTP client"); _dln("NTP :: initializing NTP client");
@ -319,11 +382,8 @@ void updateNTPClient()
} }
if (ntpClient != NULL) if (ntpClient != nullptr)
{
ntpClient->update(); ntpClient->update();
// TODO check for triggers every 10 seconds or so
}
} }

22
src/secret.default.h Normal file
View File

@ -0,0 +1,22 @@
#ifndef __secret
#define __secret
// Copy this file to 'secret.h' and customize the constants.
// It is included in .gitignore by default so that you won't
// accidentally commit the dark secrets hidden within.
#define SecretsPresent
// They're not really that dark though.
// Used for the Geocode API to get the local timezone
// Register for a Google API key at:
// https://console.developers.google.com/
//
// ...and be sure to enable "Google Maps Geocoding API" for
// your project.
static const char* GoogleAPIKey = "";
#endif

200
src/server/geocode.cpp Normal file
View File

@ -0,0 +1,200 @@
/*
* Stairs
* Copyright 2017 (c) Mark van Renswoude
*
* https://git.x2software.net/pub/Stairs
*/
#include "geocode.h"
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#include "../debug.h"
#include "../secret.h"
struct ResponseBuffer
{
void* data;
size_t length;
ResponseBuffer* next;
};
String urlencode(const String url)
{
String encoded;
for (int i = 0; i < url.length(); i++)
{
char c = url.charAt(i);
if (c == 0x20)
encoded += "%20";
else if (isalnum(c))
encoded += c;
else
{
encoded += "%";
if (c < 0x10) encoded += "0";
encoded += String(c, HEX);
}
}
return encoded;
}
void memcpy_unaligned(void* dest, void* source, size_t length)
{
uint8_t* destChar = (uint8_t*)dest;
uint8_t* sourceChar = (uint8_t*)source;
while (length > 0)
{
*destChar = *sourceChar;
sourceChar++;
destChar++;
length--;
}
}
void handleGetLatLong(AsyncWebServerRequest *request)
{
_dln("API :: get lat long");
AsyncWebParameter* addressParam = request->getParam("address");
if (addressParam == nullptr)
{
request->send(400);
return;
}
String address = addressParam->value();
if (!address.length())
{
request->send(400);
return;
}
AsyncClient* httpClient = new AsyncClient();
httpClient->onError([&](void* arg, AsyncClient* client, int error)
{
_dln("API :: get lat long: OnError");
request->send(500);
delete client;
});
httpClient->onConnect([&](void * arg, AsyncClient* client)
{
client->onError(nullptr, nullptr);
ResponseBuffer* responseData = nullptr;
client->onData([&](void* arg, AsyncClient* c, void* data, size_t len)
{
_dln("> OnData");
// Store all received chunks in a linked list
ResponseBuffer* next = new ResponseBuffer;
next->data = malloc(len);
memcpy_unaligned(next->data, data, len);
next->length = len;
next->next = nullptr;
if (responseData == nullptr)
responseData = next;
else
{
ResponseBuffer* prev = responseData;
while (prev->next != nullptr)
prev = prev->next;
prev->next = next;
}
_dln("< OnData");
});
client->onDisconnect([&](void* arg, AsyncClient* c)
{
_dln("> OnDisconnect");
if (responseData == nullptr)
{
request->send(500);
return;
}
// Send back the linked list using a chunked response
ResponseBuffer* sendChunk = responseData;
size_t sendOffset = 0;
AsyncWebServerResponse *response = request->beginChunkedResponse("application/json", [&](uint8_t *buffer, size_t maxLen, size_t index) -> size_t
{
_dln("> ChunkedResponse");
if (sendOffset >= sendChunk->length)
{
// End of the chunk, go to the next one
sendChunk = sendChunk->next;
sendOffset = 0;
}
if (sendChunk == nullptr)
{
// We sent the last one, clean up the linked list
ResponseBuffer* next;
while (responseData != nullptr)
{
next = responseData->next;
free(responseData->data);
delete responseData;
responseData = next;
}
return 0;
}
if (maxLen >= sendChunk->length - sendOffset)
{
// Send the remainder of the chunk
memcpy_unaligned(buffer, (uint8_t*)sendChunk->data + sendOffset, sendChunk->length - sendOffset);
sendOffset = sendChunk->length;
}
else
{
memcpy_unaligned(buffer, (uint8_t*)sendChunk->data + sendOffset, maxLen);
sendOffset += maxLen;
}
_dln("< ChunkedResponse");
});
request->send(response);
delete c;
_dln("< OnDisconnect");
});
#ifdef SecretsPresent
String url = "/maps/api/geocode/json?address=" + urlencode(address) + "&key=" + urlencode(GoogleAPIKey);
#else
String url = "/maps/api/geocode/json?address=" + urlencode(address);
#endif
client->write(String("GET " + url + " HTTP/1.0\r\nHost: maps.googleapis.com\n\r\n").c_str());
});
if (!httpClient->connect("maps.googleapis.com", 443, true))
{
_dln("API :: get lat long: failed to connect to Google API");
delete httpClient;
request->send(500);
}
}
void registerGeocodeRoutes(AsyncWebServer* server)
{
server->on("/api/geo/latlong", HTTP_GET, handleGetLatLong);
}

13
src/server/geocode.h Normal file
View File

@ -0,0 +1,13 @@
/*
* Stairs
* Copyright 2017 (c) Mark van Renswoude
*
* https://git.x2software.net/pub/Stairs
*/
#ifndef __server_geocode
#define __server_geocode
#include <ESPAsyncWebServer.h>
void registerGeocodeRoutes(AsyncWebServer* server);
#endif

View File

@ -84,13 +84,13 @@ void ConnectionSettings::toJson(Print &print)
bool ConnectionSettings::fromJson(char* data) bool ConnectionSettings::fromJson(char* data)
{ {
return fromJson(data, NULL); return fromJson(data, nullptr);
} }
bool ConnectionSettings::fromJson(char* data, bool* changed) bool ConnectionSettings::fromJson(char* data, bool* changed)
{ {
if (changed != NULL) if (changed != nullptr)
*changed = false; *changed = false;
DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(9) + 250); DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(9) + 250);
@ -113,9 +113,9 @@ bool ConnectionSettings::fromJson(char* data, bool* changed)
const char* jsonSubnetMaskText = root["subnetmask"]; const char* jsonSubnetMaskText = root["subnetmask"];
const char* jsonGatewayText = root["gateway"]; const char* jsonGatewayText = root["gateway"];
if (jsonIPText == NULL || !jsonIP.fromString(jsonIPText)) jsonIP = emptyIP; if (jsonIPText == nullptr || !jsonIP.fromString(jsonIPText)) jsonIP = emptyIP;
if (jsonSubnetMaskText == NULL || !jsonSubnetMask.fromString(jsonSubnetMaskText)) jsonSubnetMask = emptyIP; if (jsonSubnetMaskText == nullptr || !jsonSubnetMask.fromString(jsonSubnetMaskText)) jsonSubnetMask = emptyIP;
if (jsonGatewayText == NULL || !jsonGateway.fromString(jsonGatewayText)) jsonGateway = emptyIP; if (jsonGatewayText == nullptr || !jsonGateway.fromString(jsonGatewayText)) jsonGateway = emptyIP;
if (!(jsonAccessPoint || jsonStation)) if (!(jsonAccessPoint || jsonStation))
@ -141,7 +141,7 @@ bool ConnectionSettings::fromJson(char* data, bool* changed)
subnetMask(jsonSubnetMask); subnetMask(jsonSubnetMask);
gateway(jsonGateway); gateway(jsonGateway);
if (changed != NULL) if (changed != nullptr)
*changed = true; *changed = true;
} }

View File

@ -24,10 +24,10 @@ enum ConnectionSettingsFlags
class ConnectionSettings : CharProperties class ConnectionSettings : CharProperties
{ {
private: private:
char* mHostname = NULL; char* mHostname = nullptr;
uint8_t mFlags = AccessPoint | DHCP; uint8_t mFlags = AccessPoint | DHCP;
char* mSSID = NULL; char* mSSID = nullptr;
char* mPassword = NULL; char* mPassword = nullptr;
IPAddress mIP = (uint32_t)0; IPAddress mIP = (uint32_t)0;
IPAddress mSubnetMask = (uint32_t)0; IPAddress mSubnetMask = (uint32_t)0;
IPAddress mGateway = (uint32_t)0; IPAddress mGateway = (uint32_t)0;

View File

@ -14,6 +14,7 @@ function startApp()
data: { data: {
loading: true, loading: true,
saving: false, saving: false,
savingSteps: false,
loadingIndicator: '|', loadingIndicator: '|',
uploadProgress: false, uploadProgress: false,
@ -36,6 +37,15 @@ function startApp()
} }
}, },
searchingLocation: false,
triggers: {
time: {
latlong: '',
location: ''
}
},
connection: { connection: {
hostname: null, hostname: null,
accesspoint: true, accesspoint: true,
@ -48,22 +58,9 @@ function startApp()
gateway: null gateway: null
}, },
steps: [ allSteps: true,
{ value: 50 }, allStepsValue: 0,
{ value: 0 }, steps: []
{ value: 0 },
{ value: 0 },
{ value: 0 },
{ value: 70 },
{ value: 0 },
{ value: 0 },
{ value: 0 },
{ value: 0 },
{ value: 25 },
{ value: 0 },
{ value: 0 },
{ value: 0 }
]
}, },
created: function() created: function()
@ -71,10 +68,16 @@ function startApp()
var self = this; var self = this;
document.title = i18n.t('title'); document.title = i18n.t('title');
self.startLoadingIndicator(); var hash = window.location.hash.substr(1);
if (hash)
self.activeTab = hash;
self.startLoadingIndicator();
self.updateWiFiStatus(); self.updateWiFiStatus();
self.disableStepsChanged = false;
self.savingStepsTimer = false;
axios.get('/api/version') axios.get('/api/version')
.then(function(response) .then(function(response)
{ {
@ -96,18 +99,38 @@ function startApp()
.catch(function(error) .catch(function(error)
{ {
console.log(error); console.log(error);
})/*, }),
axios.get('/api/actions') axios.get('/api/steps')
.then(function(response) .then(function(response)
{ {
if (typeof response.data == 'object') if (Array.isArray(response.data))
self.actions = response.data;
})
.catch(function(error)
{ {
console.log(error); var allSteps = true;
})*/ var allStepsValue = false;
var total = 0;
var steps = [];
for (var i = 0; i < response.data.length; i++)
{
var value = response.data[i];
if (allStepsValue === false)
allStepsValue = value;
else if (value !== allStepsValue)
allSteps = false;
steps.push({ value: value });
total += value;
}
self.steps = steps;
self.allStepsValue = Math.floor(total / steps.length);
self.allSteps = allSteps;
}
})
]) ])
.then(axios.spread(function(acct, perms) { .then(axios.spread(function(acct, perms) {
self.stopLoadingIndicator(); self.stopLoadingIndicator();
@ -291,6 +314,114 @@ function startApp()
document.getElementById('firmware').reset(); document.getElementById('firmware').reset();
}); });
},
stepsChanged: function()
{
var self = this;
if (self.loading || self.disableStepsChanged) return;
if (self.savingStepsTimer === false)
self.savingStepsTimer = setTimeout(function() { self.updateSteps(); }, 200);
},
updateSteps: function()
{
var self = this;
self.savingSteps = true;
self.savingStepsTimer = false;
self.disableStepsChanged = true;
if (self.allSteps)
{
var newSteps = [];
for (var i = 0; i < self.steps.length; i++)
newSteps.push({ value: self.allStepsValue });
self.steps = newSteps;
}
else
{
var total = 0;
for (var i = 0; i < self.steps.length; i++)
total += self.steps[i].value;
self.allStepsValue = Math.floor(total / self.steps.length);
}
var steps = [];
for (var i = 0; i < self.steps.length; i++)
steps.push(self.steps[i].value);
self.disableStepsChanged = false;
axios.post('/api/steps', {
// TODO configurable
transitionTime: 1000,
values: steps
})
.then(function(response)
{
})
.catch(function(error)
{
console.log(error);
})
.then(function()
{
self.savingSteps = false;
});
},
searchLocation: function()
{
var self = this;
if (!self.triggers.time.location) return;
self.searchingLocation = true;
axios.get('http://maps.googleapis.com/maps/api/geocode/json', { params: { address: self.triggers.time.location }})
.then(function(response)
{
alert(response.data);
})
.catch(function(error)
{
console.log(error);
})
.then(function()
{
self.searchingLocation = false;
});
}
},
watch: {
// The sync: true ensures we can wrap the internal updates with disableStepsChanged
allSteps: {
handler: function() { this.stepsChanged(); },
sync: true
},
allStepsValue: {
handler: function() { this.stepsChanged(); },
sync: true
},
steps: {
handler: function() { this.stepsChanged(); },
deep: true,
sync: true
},
activeTab: function(newValue)
{
console.log(newValue);
window.location.hash = '#' + newValue;
} }
} }
}); });

2
web/dist/bundle.css vendored

File diff suppressed because one or more lines are too long

2
web/dist/bundle.js vendored

File diff suppressed because one or more lines are too long

View File

@ -40,19 +40,61 @@
</div> </div>
<div v-if="activeTab == 'status'"> <div v-if="activeTab == 'status'">
<!--
Status tab
-->
<h3>{{ $t('status.title') }}</h3> <h3>{{ $t('status.title') }}</h3>
<div class="slidecontainer" v-for="(step, index) in steps"> <div>
{{ index + 1 }} <input type="radio" name="allSteps" :value="true" v-model="allSteps" id="allStepsTrue">
<input type="range" min="0" max="100" class="slider" v-model="step.value"> <label class="label-inline" for="allStepsTrue">{{ $t('status.allStepsTrue') }}</label>
{{ step.value }} </div>
<div>
<input type="radio" name="allSteps" :value="false" v-model="allSteps" id="allStepsFalse">
<label class="label-inline" for="allStepsFalse">{{ $t('status.allStepsFalse') }}</label>
</div>
<div class="sliders">
<div class="step" v-if="allSteps">
<span class="value">{{ Math.floor(allStepsValue / 255 * 100) }}%</span>
<div class="slidercontainer">
<input type="range" min="0" max="255" class="slider" v-model.number="allStepsValue">
</div>
</div>
<div class="step" v-if="!allSteps" v-for="(step, index) in steps">
<span class="value">{{ Math.floor(step.value / 255 * 100) }}%</span>
<div class="slidercontainer">
<input type="range" min="0" max="255" class="slider" v-model.number="step.value">
</div>
</div>
</div> </div>
</div> </div>
<div v-if="activeTab == 'triggers'"> <div v-if="activeTab == 'triggers'">
<!--
Triggers tab
-->
<form @submit.prevent="applyTriggers"> <form @submit.prevent="applyTriggers">
<fieldset> <fieldset>
<h3>{{ $t('triggers.timeTitle') }}</h3> <h3>{{ $t('triggers.timeTitle') }}</h3>
<div class="warning" v-if="!wifiStatus.station.enabled || wifiStatus.station.status != 3">
{{ $t('triggers.timeInternet') }}
</div>
<label for="latlong">{{ $t('triggers.timeLatLong') }}</label>
<input type="text" id="latlong" v-model="triggers.time.latlong">
<label for="location" class="label-inline">{{ $t('triggers.timeLocation') }}</label>
<input type="text" id="location" v-model="triggers.time.location">
<button class="button" @click.prevent="searchLocation" :disabled="searchingLocation">{{ $t('triggers.timeLocationSearch') }}</button>
</fieldset> </fieldset>
<fieldset> <fieldset>
@ -62,6 +104,11 @@
</div> </div>
<div v-if="activeTab == 'connection'"> <div v-if="activeTab == 'connection'">
<!--
Connection tab
-->
<form @submit.prevent="applyConnection"> <form @submit.prevent="applyConnection">
<fieldset> <fieldset>
<h3>{{ $t('connection.title') }}</h3> <h3>{{ $t('connection.title') }}</h3>
@ -108,6 +155,11 @@
</div> </div>
<div v-if="activeTab == 'firmware'"> <div v-if="activeTab == 'firmware'">
<!--
Firmware tab
-->
<form @submit.prevent="uploadFirmware" id="firmware"> <form @submit.prevent="uploadFirmware" id="firmware">
<fieldset> <fieldset>
<h3>{{ $t('firmware.title') }}</h3> <h3>{{ $t('firmware.title') }}</h3>

View File

@ -29,12 +29,20 @@ var messages = {
status: { status: {
tabTitle: 'Status', tabTitle: 'Status',
title: 'Current status' title: 'Current status',
allStepsTrue: 'Set intensity for all steps',
allStepsFalse: 'Set intensity individually'
}, },
triggers: { triggers: {
tabTitle: 'Triggers', tabTitle: 'Triggers',
timeTitle: 'Time', timeTitle: 'Time',
timeInternet: 'Please note that time triggers require an internet connection.',
timeLatLong: 'Latitude / longitude',
timeLocation: 'Get latitude / longitude from location',
timeLocationSearch: 'Search',
motionTitle: 'Motion' motionTitle: 'Motion'
}, },
@ -97,12 +105,20 @@ var messages = {
status: { status: {
tabTitle: 'Status', tabTitle: 'Status',
title: 'Huidige status' title: 'Huidige status',
allStepsTrue: 'Alle treden dezelfde intensiteit',
allStepsFalse: 'Treden individueel instellen'
}, },
triggers: { triggers: {
tabTitle: 'Triggers', tabTitle: 'Triggers',
timeTitle: 'Tijd', timeTitle: 'Tijd',
timeInternet: 'Let op dat voor tijd triggers een internetverbinding vereist is.',
timeLatLong: 'Breedtegraad / lengtegraad',
timeLocation: 'Breedtegraad / lengtegraad ophalen op basis van locatie',
timeLocationSearch: 'Zoeken',
motionTitle: 'Beweging' motionTitle: 'Beweging'
}, },

View File

@ -17,6 +17,10 @@ $sliderBarColor: #404040;
$sliderBarSize: .5rem; $sliderBarSize: .5rem;
$sliderThumbColor: #fcf6cf; $sliderThumbColor: #fcf6cf;
$sliderThumbSize: 2rem; $sliderThumbSize: 2rem;
$sliderValueColor: #808080;
$warningColor: #302f28;
$warningBorderColor: #000000;
$smallScreen: "screen and (min-width: 768px)"; $smallScreen: "screen and (min-width: 768px)";
@ -191,6 +195,33 @@ input[disabled]
} }
.sliders
{
margin-top: 2rem;
}
.step
{
margin-left: 3rem;
margin-right: 3rem;
position: relative;
.slidercontainer
{
margin-right: 4em;
}
.value
{
position: absolute;
right: 0;
top: .1rem;
color: $sliderValueColor;
}
}
.slider .slider
{ {
-webkit-appearance: none; -webkit-appearance: none;
@ -220,3 +251,12 @@ input[disabled]
cursor: pointer; cursor: pointer;
} }
} }
.warning
{
background: $warningColor;
border: solid 1px $warningBorderColor;
padding: .5em;
margin-bottom: 2rem;
}