mirror of
https://github.com/arendst/Tasmota.git
synced 2026-10-26 22:11:22 +00:00
Decode the 13-byte body composition record the scale broadcasts as service data for UUID 0x181B (also sent as 0x2A9C notifications), and register the scale as MI32 device type MIBCS with fake product ID 0x181b. Per weighing session the driver publishes the weight once when the scale's stable flag is set and the impedance once when the impedance stable flag is set (repeating the weight so the message is self contained). If the user steps off before a usable impedance arrives, ImpedanceFailed:1 is published instead. A session ends on the finished flag or after 10 s of silence, so repeated broadcasts of the final record do not produce duplicate messages. Overload readings (0xFFF0) and the impedance sentinels 0xFFFE/0xFFFD are ignored. The unit (kg, lb, jin) is derived from the flag bits and published alongside. Web UI: weight and impedance rows on the main page; with USE_MI_EXT_GUI a dashboard tile with a 24 h weight history graph (kept in kg). Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
1181 lines
53 KiB
C++
1181 lines
53 KiB
C++
/*
|
|
xsns_62_esp32_mi.h - MI-BLE-sensors via ESP32 support for Tasmota
|
|
|
|
Copyright (C) 2021 Christian Baars and Theo Arends
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
#ifdef USE_MI_ESP32
|
|
|
|
#pragma once
|
|
|
|
#include <NimBLEDevice.h>
|
|
|
|
/*********************************************************************************************\
|
|
* structs and types
|
|
\*********************************************************************************************/
|
|
#pragma pack(1) // byte-aligned structures to read the sensor data
|
|
|
|
struct frame_crtl_t{
|
|
uint16_t reserved1:1;
|
|
uint16_t reserved2:1;
|
|
uint16_t reserved3:1;
|
|
uint16_t isEncrypted:1;
|
|
uint16_t includesMAC:1;
|
|
uint16_t includesCapability:1;
|
|
uint16_t includesObj:1;
|
|
uint16_t MESH:1;
|
|
uint16_t registered:1;
|
|
uint16_t solicited:1;
|
|
uint16_t AuthMode:2;
|
|
uint16_t version:4;
|
|
};
|
|
|
|
struct mi_payload_t{
|
|
uint16_t type;
|
|
uint8_t size;
|
|
union {
|
|
struct{ //0d
|
|
int16_t temp;
|
|
uint16_t hum;
|
|
}HT;
|
|
uint8_t bat; //0a
|
|
int16_t temp; //04
|
|
uint16_t hum; //06
|
|
uint32_t lux; //07
|
|
uint8_t moist; //08
|
|
uint16_t fert; //09
|
|
uint8_t leak; //14
|
|
uint32_t NMT; //17
|
|
uint8_t door; //19
|
|
uint16_t objID; //0x0002
|
|
struct{ //01
|
|
uint8_t num;
|
|
uint8_t value;
|
|
uint8_t type;
|
|
}Btn;
|
|
};
|
|
uint8_t padding[12]; //for decryption
|
|
};
|
|
|
|
struct mi_beacon_t{
|
|
frame_crtl_t frame;
|
|
uint16_t productID;
|
|
uint8_t counter;
|
|
uint8_t MAC[6];
|
|
uint8_t capability;
|
|
mi_payload_t payload;
|
|
};
|
|
|
|
|
|
struct cg_packet_t {
|
|
uint16_t frameID;
|
|
uint8_t MAC[6];
|
|
uint16_t mode;
|
|
union {
|
|
struct {
|
|
int16_t temp; // -9 - 59 °C
|
|
uint16_t hum;
|
|
};
|
|
uint8_t bat;
|
|
};
|
|
};
|
|
|
|
struct encPacket_t{
|
|
// the packet is longer, but this part is enough to decrypt
|
|
uint16_t PID;
|
|
uint8_t frameCnt;
|
|
uint8_t MAC[6];
|
|
uint8_t payload[16]; // only a pointer to the address, size is variable
|
|
};
|
|
|
|
struct berryAdvPacket_t{
|
|
uint8_t MAC[6];
|
|
uint8_t addressType;
|
|
uint8_t RSSI;
|
|
uint8_t length; // length of payload
|
|
#ifdef CONFIG_BT_NIMBLE_EXT_ADV
|
|
uint8_t payload[255];
|
|
#else
|
|
uint8_t payload[62]; // legacy advertisement plus scan response
|
|
#endif
|
|
};
|
|
|
|
|
|
union mi_bindKey_t{
|
|
struct{
|
|
uint8_t key[16];
|
|
uint8_t MAC[6];
|
|
};
|
|
uint8_t buf[22];
|
|
};
|
|
|
|
struct ATCPacket_t{ //and PVVX
|
|
uint8_t MAC[6];
|
|
union {
|
|
struct{
|
|
uint16_t temp; //sadly this is in wrong endianess
|
|
uint8_t hum;
|
|
uint8_t batPer;
|
|
uint16_t batMV;
|
|
uint8_t frameCnt;
|
|
} A; //ATC
|
|
struct{
|
|
int16_t temp;
|
|
uint16_t hum; // x 0.01 %
|
|
uint16_t batMV;
|
|
uint8_t batPer;
|
|
uint8_t frameCnt;
|
|
struct {
|
|
uint8_t reed:1;
|
|
uint8_t TRGval:1;
|
|
uint8_t TRGcrtl:1;
|
|
uint8_t tempTrig:1;
|
|
uint8_t humTrig:1;
|
|
uint8_t spare:3;
|
|
};
|
|
}P; //PVVX
|
|
};
|
|
};
|
|
|
|
// Xiaomi Mi Body Composition Scale (MIBCS/MIBFS), service data of UUID 0x181B, 13 bytes, little endian
|
|
struct MiScalePacket_t {
|
|
uint8_t flagsA; // bit0: unit lb, bit2: "part"/partial result
|
|
uint8_t flagsB; // bit1: impedance stable, bit5: weight stable, bit6: unit jin, bit7: finished (user stepped off)
|
|
uint16_t year;
|
|
uint8_t month;
|
|
uint8_t day;
|
|
uint8_t hour;
|
|
uint8_t minute;
|
|
uint8_t second;
|
|
uint16_t impedance; // ohms; 0xFFFE = measuring, 0xFFFD = failed
|
|
uint16_t weight; // raw; /200 for kg, /100 for lb and jin; 0xFFF0 = overload
|
|
} __attribute__((packed));
|
|
|
|
union BTHome_info_t{
|
|
struct{
|
|
uint8_t encrypted:1;
|
|
uint8_t reserved:1;
|
|
uint8_t triggered:1;
|
|
uint8_t reserved2:2;
|
|
uint8_t version:2;
|
|
};
|
|
char byte_value;
|
|
};
|
|
|
|
struct BLERingBufferItem_t{
|
|
uint16_t returnCharUUID;
|
|
uint16_t handle;
|
|
uint32_t type;
|
|
uint8_t length;
|
|
};
|
|
|
|
#pragma pack(0)
|
|
|
|
|
|
struct MI32connectionContextBerry_t{
|
|
NimBLEUUID serviceUUID;
|
|
NimBLEUUID charUUID;
|
|
uint16_t returnCharUUID;
|
|
uint16_t handle;
|
|
uint16_t itvl_min;
|
|
uint16_t itvl_max;
|
|
uint8_t * buffer;
|
|
// Reverse-role client (peripheral side). Singleton owned by NimBLEServer
|
|
// (do NOT pass to NimBLEDevice::deleteClient). Use only for server-side
|
|
// ACNS-style queries toward the connected central. Set in
|
|
// MI32ServerCallbacks::onConnect, cleared (not freed) in onDisconnect.
|
|
NimBLEClient * serverPeer = nullptr;
|
|
uint8_t MAC[6];
|
|
uint8_t operation;
|
|
uint8_t addrType;
|
|
int error;
|
|
int32_t arg1;
|
|
uint32_t pin;
|
|
bool hasArg1;
|
|
bool oneOp;
|
|
bool response;
|
|
};
|
|
|
|
struct {
|
|
// uint32_t period; // set manually in addition to TELE-period, is set to TELE-period after start
|
|
TaskHandle_t ScanTask = nullptr;
|
|
TaskHandle_t ConnTask = nullptr;
|
|
MI32connectionContextBerry_t *conCtx = nullptr;
|
|
uint16_t connID;
|
|
union {
|
|
struct {
|
|
uint32_t init:1;
|
|
uint32_t connected:1;
|
|
uint32_t autoScan:1;
|
|
// uint32_t canScan:1;
|
|
uint32_t runningScan:1;
|
|
uint32_t updateScan:1;
|
|
uint32_t deleteScanTask:1;
|
|
uint32_t IRKinCfg:1;
|
|
|
|
|
|
uint32_t canConnect:1;
|
|
uint32_t willConnect:1;
|
|
|
|
uint32_t shallTriggerTele:1;
|
|
uint32_t triggeredTele:1;
|
|
uint32_t shallShowStatusInfo:1; // react to amount of found sensors via RULES
|
|
uint32_t didGetConfig:1;
|
|
|
|
uint32_t triggerBerryAdvCB:1;
|
|
uint32_t triggerBerryConnCB:1;
|
|
uint32_t triggerNextJob:1;
|
|
uint32_t readyForNextJob:1;
|
|
uint32_t discoverAttributes:1;
|
|
|
|
uint32_t deleteConnectionTask:1; // request server-task teardown (renamed from deleteServerTask)
|
|
};
|
|
uint32_t all = 0;
|
|
} mode;
|
|
struct {
|
|
uint8_t sensor; // points to to the number 0...255
|
|
} state;
|
|
struct {
|
|
uint32_t allwaysAggregate:1; // always show all known values of one sensor in brdigemode
|
|
uint32_t noSummary:1; // no sensor values at TELE-period
|
|
uint32_t directBridgeMode:1; // send every received BLE-packet as a MQTT-message in real-time
|
|
uint32_t activeScan:1;
|
|
uint32_t ignoreBogusBattery:1;
|
|
uint32_t handleEveryDevice:1;
|
|
} option;
|
|
#ifdef USE_MI_EXT_GUI
|
|
uint32_t widgetSlot = 0;
|
|
#ifdef USE_ENERGY_SENSOR
|
|
uint8_t energy_history[24];
|
|
#endif //USE_ENERGY_SENSOR
|
|
#endif //USE_MI_EXT_GUI
|
|
|
|
void *beConnCB;
|
|
void *beAdvCB;
|
|
uint8_t *beAdvBuf;
|
|
uint16_t queueDrops = 0;
|
|
uint8_t role = 0; // bitfield of MI32Role values (concurrently active roles)
|
|
} MI32;
|
|
|
|
struct mi_sensor_t{
|
|
uint8_t type; //Flora = 1; MI-HT_V1=2; LYWSD02=3; LYWSD03=4; CGG1=5; CGD1=6
|
|
uint8_t lastCnt; //device generated counter of the packet
|
|
uint8_t shallSendMQTT;
|
|
uint8_t MAC[6];
|
|
uint16_t PID;
|
|
uint8_t *key = nullptr;
|
|
char *name = nullptr;
|
|
union {
|
|
struct {
|
|
uint32_t needsKey:1;
|
|
uint32_t temp:1;
|
|
uint32_t hum:1;
|
|
uint32_t tempHum:1; //every hum sensor has temp too, easier to use Tasmota dew point functions
|
|
uint32_t lux:1;
|
|
uint32_t moist:1;
|
|
uint32_t fert:1;
|
|
uint32_t bat:1;
|
|
uint32_t NMT:1;
|
|
uint32_t motion:1;
|
|
uint32_t Btn:1;
|
|
uint32_t knob:1;
|
|
uint32_t door:1;
|
|
uint32_t leak:1;
|
|
uint32_t payload:1;
|
|
uint32_t weight:1; // body composition scale
|
|
uint32_t impedance:1; // body composition scale
|
|
};
|
|
uint32_t raw = 0;
|
|
} feature;
|
|
union {
|
|
struct {
|
|
uint32_t temp:1;
|
|
uint32_t hum:1;
|
|
uint32_t tempHum:1; //can be combined from the sensor
|
|
uint32_t lux:1;
|
|
uint32_t moist:1;
|
|
uint32_t fert:1;
|
|
uint32_t bat:1;
|
|
uint32_t NMT:1;
|
|
uint32_t motion:1;
|
|
uint32_t noMotion:1;
|
|
uint32_t Btn:1;
|
|
uint32_t knob:1;
|
|
uint32_t longpress:1; //needs no extra feature bit, because knob is sufficient
|
|
uint32_t door:1;
|
|
uint32_t leak:1;
|
|
uint32_t payload:1;
|
|
uint32_t weight:1; // stable weight available
|
|
uint32_t impedance:1; // stable impedance available
|
|
uint32_t impedanceFailed:1; // session ended without a usable impedance
|
|
};
|
|
uint32_t raw = 0;
|
|
} eventType;
|
|
union{
|
|
struct{
|
|
uint8_t hasWrongKey:1;
|
|
uint8_t isUnbounded:1;
|
|
};
|
|
uint8_t raw = 0;
|
|
} status;
|
|
|
|
int RSSI = 0;
|
|
uint32_t lastTime = 0;
|
|
uint32_t lux;
|
|
uint8_t lux_history[24];
|
|
float temp; //Flora, MJ_HT_V1, LYWSD0x, CGx
|
|
uint8_t temp_history[24];
|
|
union {
|
|
struct {
|
|
uint8_t moisture;
|
|
uint16_t fertility;
|
|
char firmware[6]; // actually only for FLORA but hopefully we can add for more devices
|
|
}; // Flora
|
|
struct {
|
|
float hum;
|
|
uint8_t hum_history[24];
|
|
};
|
|
struct { // MIBCS / MIBFS body composition scale
|
|
float weight; // in the unit the scale reports (see weightUnit)
|
|
uint16_t impedance; // ohms, 0 = not measured
|
|
uint8_t weightUnit; // 0 = kg, 1 = lb, 2 = jin
|
|
uint8_t scaleState; // session bookkeeping, see MI32_SCALE_* flags
|
|
uint32_t scaleLastSeen; // uptime of last packet, for session timeout
|
|
uint8_t weight_history[24];
|
|
};
|
|
struct {
|
|
uint16_t events; //"alarms" since boot
|
|
uint32_t NMT; // no motion time in seconds for the MJYD2S and NLIGHT
|
|
};
|
|
struct {
|
|
uint8_t Btn; // number starting with 0
|
|
uint8_t BtnType; // 0 -single, 1 - double, 2 - hold
|
|
uint8_t leak; // the leak sensor is the only non-RC device so far with a button fuctionality, so we handle it here
|
|
int8_t dimmer;
|
|
uint8_t pressed; // dimmer knob pressed while rotating
|
|
uint8_t longpress; // dimmer knob pressed without rotating
|
|
};
|
|
uint8_t door;
|
|
|
|
};
|
|
union {
|
|
uint8_t bat; // many values seem to be hard-coded garbage (LYWSD0x, GCD1)
|
|
};
|
|
struct {
|
|
uint8_t * payload = nullptr;
|
|
uint8_t payload_len;
|
|
};
|
|
};
|
|
|
|
/*********************************************************************************************\
|
|
* constants
|
|
\*********************************************************************************************/
|
|
|
|
#define D_CMND_MI32 "MI32"
|
|
|
|
const char kMI32_Commands[] PROGMEM = D_CMND_MI32 "|Key|Name|Cfg|Option";
|
|
|
|
void (*const MI32_Commands[])(void) PROGMEM = {&CmndMi32Key, &CmndMi32Name,&CmndMi32Cfg, &CmndMi32Option };
|
|
|
|
#define UNKNOWN_MI 0
|
|
#define FLORA 1
|
|
#define MJ_HT_V1 2
|
|
#define LYWSD02 3
|
|
#define LYWSD03MMC 4
|
|
#define CGG1 5
|
|
#define CGD1 6
|
|
#define NLIGHT 7
|
|
#define MJYD2S 8
|
|
#define YLYK01 9
|
|
#define MHOC401 10
|
|
#define MHOC303 11
|
|
#define ATC 12
|
|
#define MCCGQ02 13
|
|
#define SJWS01L 14
|
|
#define PVVX 15
|
|
#define YLKG08 16
|
|
#define YLAI003 17
|
|
#define BTHOME 18
|
|
#define MIBCS 19
|
|
|
|
#define MI32_TYPES 19 //count this manually
|
|
|
|
const uint16_t kMI32DeviceID[MI32_TYPES]={ 0x0098, // Flora
|
|
0x01aa, // MJ_HT_V1
|
|
0x045b, // LYWSD02
|
|
0x055b, // LYWSD03
|
|
0x0347, // CGG1
|
|
0x0576, // CGD1
|
|
0x03dd, // NLIGHT
|
|
0x07f6, // MJYD2S
|
|
0x0153, // YLYK01, old name yee-rc
|
|
0x0387, // MHO-C401
|
|
0x06d3, // MHO-C303
|
|
0x0a1c, // ATC -> this is a fake ID
|
|
0x098b, // MCCGQ02
|
|
0x0863, // SJWS01L
|
|
0x944a, // PVVX -> this is a fake ID
|
|
0x03b6, // YLKG08 and YLKG07 - version w/wo mains
|
|
0x07bf, // YLAI003
|
|
0xb770, // BTHome -> fake ID
|
|
0x181b, // MIBCS/MIBFS body composition scale -> fake ID (service UUID)
|
|
};
|
|
|
|
const char kMI32DeviceType[] PROGMEM = {"Flora|MJ_HT_V1|LYWSD02|LYWSD03|CGG1|CGD1|NLIGHT|MJYD2S|YLYK01|MHOC401|MHOC303|ATC|MCCGQ02|SJWS01L|PVVX|YLKG08|YLAI003|BTHOME|MIBCS"};
|
|
|
|
const char kMI32_ScaleUnit[] PROGMEM = "kg|lb|jin";
|
|
|
|
// scaleState flags
|
|
#define MI32_SCALE_WEIGHT_SENT 0x01
|
|
#define MI32_SCALE_IMPEDANCE_SENT 0x02
|
|
#define MI32_SCALE_FAILED_SENT 0x04
|
|
#define MI32_SCALE_FINISHED 0x08
|
|
#define MI32_SCALE_SESSION_TIMEOUT 10 // seconds of silence that end a weighing session
|
|
|
|
const char kMI32_ButtonMsg[] PROGMEM = "Single|Double|Hold"; //mapping: in Tasmota: 1,2,3 ; for HomeKit and Xiaomi 0,1,2
|
|
/*********************************************************************************************\
|
|
* enumerations
|
|
\*********************************************************************************************/
|
|
|
|
enum MI32_Commands { // commands useable in console or rules
|
|
CMND_MI32_KEY, // add bind key to a mac for packet decryption
|
|
CMND_MI32_CFG, // save config file as JSON with all sensors w/o keys to mi32cfg
|
|
CMND_MI32_OPTION // change driver options at runtime
|
|
};
|
|
|
|
enum MI32_TASK {
|
|
MI32_TASK_SCAN = 0,
|
|
};
|
|
|
|
enum BLE_CLIENT_OP {
|
|
BLE_OP_READ = 1,
|
|
BLE_OP_WRITE,
|
|
BLE_OP_SUBSCRIBE,
|
|
BLE_OP_UNSUBSCRIBE,
|
|
BLE_OP_DISCONNECT,
|
|
BLE_OP_GET_NOTIFICATION = 103,
|
|
};
|
|
|
|
enum BLE_SERVER_OP {
|
|
//commands
|
|
BLE_OP_SET_ADV = 201,
|
|
BLE_OP_SET_SCAN_RESP,
|
|
BLE_OP_SET_CHARACTERISTIC = 211,
|
|
//response
|
|
BLE_OP_ON_READ = 221,
|
|
BLE_OP_ON_WRITE,
|
|
BLE_OP_ON_UNSUBSCRIBE,
|
|
BLE_OP_ON_SUBSCRIBE_TO_NOTIFICATIONS,
|
|
BLE_OP_ON_SUBSCRIBE_TO_INDICATIONS,
|
|
BLE_OP_ON_SUBSCRIBE_TO_NOTIFICATIONS_AND_INDICATIONS,
|
|
BLE_OP_ON_CONNECT,
|
|
BLE_OP_ON_DISCONNECT,
|
|
BLE_OP_ON_STATUS,
|
|
BLE_OP_ON_AUTHENTICATED
|
|
};
|
|
|
|
enum MI32_ConnErrorMsg {
|
|
MI32_CONN_NO_ERROR = 0,
|
|
MI32_CONN_NO_CONNECT,
|
|
MI32_CONN_DID_DISCCONNECT,
|
|
MI32_CONN_NO_SERVICE,
|
|
MI32_CONN_NO_CHARACTERISTIC,
|
|
MI32_CONN_CAN_NOT_READ,
|
|
MI32_CONN_CAN_NOT_NOTIFY,
|
|
MI32_CONN_CAN_NOT_WRITE,
|
|
MI32_CONN_DID_NOT_WRITE,
|
|
MI32_CONN_NOTIFY_TIMEOUT
|
|
};
|
|
|
|
// MI32.role bit layout (concurrently-active roles, not mutually exclusive)
|
|
enum MI32Role : uint8_t {
|
|
MI32_ROLE_NONE = 0x00,
|
|
MI32_ROLE_SCAN = 0x01,
|
|
MI32_ROLE_CLIENT = 0x02,
|
|
MI32_ROLE_SERVER = 0x04,
|
|
MI32_ROLE_ADVERTISER = 0x08,
|
|
};
|
|
|
|
/*********************************************************************************************\
|
|
* extended web gui
|
|
\*********************************************************************************************/
|
|
|
|
#ifdef USE_WEBSERVER
|
|
#ifdef USE_MI_EXT_GUI
|
|
const char HTTP_BTN_MENU_MI32[] PROGMEM = "<p></p><form action='m32' method='get'><button>Dashboard</button></form>";
|
|
|
|
const char HTTP_MI32_BOOTSTRAP[] PROGMEM =
|
|
"wl(_=>fetch('/m32?wi=0').then(r=>r.text()).then(t=>{"
|
|
"d=document;" // this is global now
|
|
"x=d.createElement('div');"
|
|
"x.innerHTML=t;" // was global already
|
|
"x.querySelectorAll('style').forEach(n=>d.head.appendChild(n.cloneNode(1)));"
|
|
"x.querySelectorAll('script').forEach(n=>{s=d.createElement('script');s.textContent=n.textContent;d.body.appendChild(s)});"
|
|
"eb('m').innerHTML=(x.querySelector('body')||x).innerHTML;"
|
|
"}));";
|
|
|
|
const char HTTP_MI32_WIDGET[] PROGMEM =
|
|
"<div class='box' id='box%u' style='opacity:%u.5;'>MAC:%s RSSI:%d %s<br>"
|
|
"<small>‌%s</small>"
|
|
"<h2 style='margin-top:0em;'>%s"
|
|
"{ci}" // circle animation
|
|
"</h2>";
|
|
|
|
#ifdef USE_MI_ESP32_ENERGY
|
|
const char HTTP_MI32_POWER_WIDGET[] PROGMEM =
|
|
"<div class='box' id='box%u'>"
|
|
"<h2 style='margin-top:0em;'>Energy"
|
|
"</h2>"
|
|
"<p>" D_VOLTAGE ": %s " D_UNIT_VOLT "</p>"
|
|
"<p>" D_CURRENT ": %s " D_UNIT_AMPERE "</p>";
|
|
#endif //USE_MI_ESP32_ENERGY
|
|
|
|
/*
|
|
STATIC_PAGE MI32_STATIC_PAGE
|
|
<style>
|
|
body {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
code {
|
|
word-break: break-all;
|
|
}
|
|
.parent {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill,350px);
|
|
grid-template-rows: repeat(auto-fill,220px);
|
|
grid-auto-rows: 220px;
|
|
grid-auto-columns: 350px;
|
|
gap: 1rem;
|
|
justify-content: center;
|
|
}
|
|
svg {
|
|
float: inline-end;
|
|
}
|
|
svg text {
|
|
font-size: 0.95em;
|
|
fill: currentColor;
|
|
}
|
|
.box {
|
|
padding: 10px;
|
|
border-radius: 0.8rem;
|
|
background-color: rgba(221,221,221,0.2);
|
|
overflow-y: auto;
|
|
}
|
|
.box svg {
|
|
max-width: 100%;
|
|
}
|
|
.box.w1 { grid-column: span 1; }
|
|
.box.w2 { grid-column: span 2; }
|
|
.box.w3 { grid-column: span 3; }
|
|
.box.h1 { grid-row: span 1; }
|
|
.box.h2 { grid-row: span 2; }
|
|
.box.h3 { grid-row: span 3; }
|
|
@media (width < 720px) {
|
|
.box.w2, .box.w3 { grid-column: span 1; }
|
|
.box.h3 { grid-row: span 2; }
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
let sz=[], u=Date.now(); // sizes, count-up timestamp
|
|
//global vars from tasmota header script for local reuse:
|
|
// x,lt,to,tp,pc
|
|
// d = document from the bootstrap script
|
|
// we also have:
|
|
// eb=s=>document.getElementById(s);
|
|
// qs=s=>document.querySelector(s);
|
|
// wl=f=>window.addEventListener('load',f);
|
|
|
|
function pulse(s) { // size
|
|
sz.push(s);
|
|
if (sz.length > 60) sz.shift();
|
|
lt = "(0,200,0):" + sz.join(",");
|
|
pc = `{l,250,20,${lt}}`;
|
|
eb('pulse').innerHTML = "AJAX: " + render(pc);
|
|
}
|
|
|
|
function setUp() {
|
|
setInterval(cU, 1000); // countUp
|
|
update();
|
|
}
|
|
|
|
function cU() {
|
|
let n = Date.now(), s = Math.floor((n - u) / 1000); // now, elapsed seconds
|
|
if (s > 0) {
|
|
u += s * 1000;
|
|
d.querySelectorAll('.Ti').forEach(e => e.textContent = +e.textContent + s);
|
|
}
|
|
x = eb('clock');
|
|
if (x) x.innerHTML = Date().slice(4,24);
|
|
}
|
|
|
|
function updateMetrics(m) {
|
|
let fk = +(m[3] / 1024).toFixed(1); // freeKB
|
|
let tk = +(m[4] / 1024).toFixed(1); // totalKB
|
|
let fp = +(m[7] / 1024).toFixed(0); // freePSRAM
|
|
let tp = +(m[6] / 1024).toFixed(0); // totalPSRAM
|
|
let fh = +(m[5]); // fragHeap
|
|
|
|
eb('r').innerHTML = 'RSSI: ' + m[0] + ' dBm';
|
|
eb('mo').innerHTML = 'Mode: ' + ['Low Rate','802.11b','802.11g','HT20 (11n)','HT40 (11n)','HE20 (11ax)'][m[2]] + ' / Channel: ' + m[1];
|
|
eb('heap_gauge').innerHTML = render(`{g,50,50,${fk},0,${tk},255,102,102,0,255,255,153,40,0,200,0,80,kB}`);
|
|
eb('psram_gauge').innerHTML = render(`{g,50,50,${fp},0,${tp},255,102,102,0,255,255,153,100,0,200,0,250,kB}`);
|
|
eb('heap').innerHTML = 'Heap free: ' + fk + '/' + tk + ' kB<br>(frag. ' + fh + '%)';
|
|
eb('psram').innerHTML = 'PSRAM free: ' + fp + '/' + tp + ' kB';
|
|
eb('ut').innerHTML = 'Uptime: ' + m[8] + ' sec';
|
|
eb('ro').innerHTML = 'BLE role: ' + ['none','observer','peripheral','central'][m[9]];
|
|
eb('sd').innerHTML = 'MI32 sensors: ' + m[10];
|
|
}
|
|
|
|
function update() {
|
|
if (d.hidden) {
|
|
d.addEventListener('visibilitychange', update, {once:true});
|
|
return;
|
|
}
|
|
fetch('/m32?wi=1').then(r => r.text()).then(html => {
|
|
x = html.length; // number of characters ≈ bytes
|
|
pulse(x); // pass size instead of true/false
|
|
if (!html) {
|
|
return;
|
|
}
|
|
let parts = html.trim().split(/[\n\r,]+/);
|
|
if (parts.length === 11 && parts.every(p => /^-?\d+$/.test(p))) {
|
|
updateMetrics(parts.map(Number));
|
|
return;
|
|
}
|
|
|
|
let ciSVG =
|
|
"<svg height='24' width='24' >" // style='float:right;'
|
|
+ "<circle cx='11' cy='11' r='0' fill='#90ee90' opacity='0'>"
|
|
+ "<animate attributeName='r' from='11' to='0' dur='9s' repeatCount='1'/>"
|
|
+ "<animate attributeName='opacity' from='1' to='0' dur='9s' repeatCount='1'/>"
|
|
+ "</circle></svg>";
|
|
|
|
let replaced = html
|
|
.replace(/{ci}/g, ciSVG)
|
|
.replace(/\{[lLhHgG],[^}]+\}/g, match => {
|
|
try { return render(match); }
|
|
catch (e) {
|
|
console.warn("DSL render error:", e);
|
|
return "<small>graph unavailable</small>";
|
|
}
|
|
});
|
|
|
|
x = d.createElement('div');
|
|
x.innerHTML = replaced.trim();
|
|
|
|
lt = Array.from(x.getElementsByTagName('script'));
|
|
lt.forEach(el => el.remove());
|
|
|
|
while (tp = x.firstElementChild) {
|
|
to = eb(tp.id); // old element
|
|
if (to) to.parentNode.replaceChild(tp, to);
|
|
else eb('pr').appendChild(tp);
|
|
}
|
|
|
|
lt.forEach(el => {
|
|
let sc = d.createElement('script');
|
|
sc.textContent = el.textContent;
|
|
d.body.appendChild(sc).remove();
|
|
});
|
|
}).catch(e => {
|
|
// console.warn("update error:", e);
|
|
}).then(_ => setTimeout(update, 200));
|
|
}
|
|
|
|
setTimeout(setUp, 500);
|
|
|
|
// Dispatcher for compact DSL only: {type,w,h,(r,g,b):v1,v2…[|…]}
|
|
// Uppercase ⇒ WITH grid; lowercase ⇒ WITHOUT grid
|
|
function render(payload) {
|
|
let s = String(payload).trim();
|
|
if (!s.startsWith("{") || !s.endsWith("}")) return "";
|
|
let inner = s.slice(1, -1);
|
|
|
|
// First char = type
|
|
let typeChar = inner[0];
|
|
let showGrid = typeChar === typeChar.toUpperCase();
|
|
let type = typeChar.toLowerCase();
|
|
|
|
// Handle line/histogram with series syntax
|
|
if ("lh".includes(type)) {
|
|
let m = inner.match(/^([lLhH]),(\d+),(\d+),(.+)$/);
|
|
if (!m) return "";
|
|
|
|
let [, , wStr, hStr, sStr] = m;
|
|
let w = +wStr; // width
|
|
let h = +hStr; // height
|
|
|
|
// Extract xl: parameter if present
|
|
let xl = null; // xLabels - custom X-axis labels
|
|
let seg = sStr.split("|");
|
|
for (let i = 0; i < seg.length; i++) {
|
|
if (seg[i].startsWith("xl:")) {
|
|
xl = seg[i].substring(3).split(",");
|
|
seg.splice(i, 1); // remove xl: segment from array
|
|
break;
|
|
}
|
|
}
|
|
|
|
let sl = seg.map(seg => { // sl = seriesList
|
|
let mm = seg.match(/^\((\d+),(\d+),(\d+)\):(.*)$/);
|
|
if (!mm) return null;
|
|
return {
|
|
rgb: [+mm[1], +mm[2], +mm[3]],
|
|
values: mm[4].split(",").map(v => Number(v.trim()))
|
|
};
|
|
}).filter(Boolean);
|
|
|
|
switch (type) {
|
|
case "l":
|
|
return renderLG(sl, w, h, showGrid, xl);
|
|
break;
|
|
case "h":
|
|
if (sl.length === 1)
|
|
return renderH(sl[0].values, sl[0].rgb, w, h, showGrid, xl);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Handle gauge DSL separately
|
|
// Gauge DSL: {g,w,h,val,min,max,r1,g1,b1,threshold1,r2,g2,b2,threshold2,...,unit}
|
|
// Example: {g,200,140,75,0,100,0,200,0,0,200,160,0,40,200,0,0,75,%}
|
|
// Stops: RGB triplet + threshold value, repeating. Unit string at end.
|
|
if (type === "g") {
|
|
let p = inner.split(',');
|
|
let w = +p[1], h = +p[2], val = +p[3], min = +p[4], max = +p[5];
|
|
let stops = [];
|
|
for (let i = 6; i < p.length - 1; i += 4) {
|
|
stops.push({
|
|
value: +p[i+3],
|
|
color: `rgb(${p[i]},${p[i+1]},${p[i+2]})`
|
|
});
|
|
}
|
|
let unit = p[p.length - 1];
|
|
let showValue = (typeChar === "G");
|
|
return renderG(val, min, max, w, h, stops, unit, showValue);
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
function buildGrid(w, h, mv, dL, yt = 4, cX = null) { // maxVal, dataLength, yTicks, customXLabels
|
|
let ln = [], lb = [], xl = []; // lines, labels, xLabels
|
|
let nm = Math.ceil(mv / 10) * 10; // niceMax
|
|
let ti = nm / yt; // tickInterval
|
|
if (ti <= 5) ti = 5;
|
|
else if (ti <= 10) ti = 10;
|
|
else if (ti <= 25) ti = 25;
|
|
else ti = Math.ceil(ti / 50) * 50;
|
|
nm = Math.ceil(mv / ti) * ti;
|
|
let at = Math.ceil(nm / ti); // actualTicks
|
|
for (let i = 0; i <= at; i++) {
|
|
let v = i * ti;
|
|
let y = h - (v * h / nm);
|
|
ln.push(`<line x1="0" y1="${y}" x2="${w}" y2="${y}" stroke="#ddd" stroke-width="1"/>`);
|
|
if (i < at) lb.push(`<text x="-5" y="${y+4}" text-anchor="end">${v}</text>`);
|
|
}
|
|
if (cX && cX.length > 0) { // X-axis labels - use custom if provided, otherwise default numeric
|
|
let xs = cX.length - 1; // xSteps
|
|
for (let i = 0; i < cX.length; i++) {
|
|
let x = xs > 0 ? i * (w / xs) : w / 2;
|
|
xl.push(`<text x="${x}" y="${h+20}" text-anchor="middle">${cX[i]}</text>`);
|
|
}
|
|
} else {
|
|
let xs = 4; // xSteps
|
|
for (let i = 0; i <= xs; i++) {
|
|
let x = i * (w / xs);
|
|
let xi = Math.round(i * (dL - 1) / xs);
|
|
xl.push(`<text x="${x}" y="${h+20}" text-anchor="middle">${xi}</text>`);
|
|
}
|
|
}
|
|
return { lines: ln.join(""), labels: lb.join(""), xl: xl.join("") };
|
|
}
|
|
|
|
function renderG(v, mn, mx, w, h, st, u = "", sv = true) { // value, min, max, stops, unit, showValue
|
|
let cl = x => Math.max(mn, Math.min(mx, x)); // clamp
|
|
let vl = cl(v); // val
|
|
let sp = mx - mn || 1; // span
|
|
let t = (vl - mn) / sp;
|
|
let cx = w / 2, cy = h / 2;
|
|
let ro = Math.min(w, h) * 0.45; // rOuter
|
|
let ri = ro * 0.75; // rInner
|
|
let so = ro * 0.06, si = ro * 0.35; // swOuter, swInner
|
|
let gd = 2; // gapDeg
|
|
let sd = -135 + gd, ed = 135 - gd, swd = ed - sd; // startDeg, endDeg, sweepDeg
|
|
|
|
function polar(cx, cy, r, d) { // deg
|
|
let rd = (d - 90) * Math.PI / 180; // rad
|
|
return { x: cx + r * Math.cos(rd), y: cy + r * Math.sin(rd) };
|
|
}
|
|
function arcPath(cx, cy, r, a0, a1) {
|
|
let la = Math.abs(a1 - a0) > 180 ? 1 : 0; // largeArc
|
|
let sw = a1 > a0 ? 1 : 0; // sweep
|
|
let p0 = polar(cx, cy, r, a0);
|
|
let p1 = polar(cx, cy, r, a1);
|
|
return `M ${p0.x},${p0.y} A ${r},${r} 0 ${la} ${sw} ${p1.x},${p1.y}`;
|
|
}
|
|
function colorFor(v) {
|
|
if (!st.length) return "rgb(120,120,120)";
|
|
let c = st[0].color;
|
|
for (let i = 0; i < st.length; i++) {
|
|
if (v >= st[i].value) c = st[i].color;
|
|
else break;
|
|
}
|
|
return c;
|
|
}
|
|
let os = ""; // outerSegs
|
|
for (let i = 0; i < st.length; i++) {
|
|
let fr = (st[i].value - mn) / sp; // from
|
|
let to = (i + 1 < st.length) ? (st[i+1].value - mn) / sp : 1;
|
|
let a0 = sd + swd * fr, a1 = sd + swd * to;
|
|
if (a1 <= a0) continue;
|
|
os += `<path d="${arcPath(cx, cy, ro, a0, a1)}" stroke="${st[i].color}" stroke-width="${so}" fill="none"/>`;
|
|
}
|
|
let bt = `<path d="${arcPath(cx, cy, ri, sd, ed)}" stroke="rgba(120,120,120,0.25)" stroke-width="${si}" fill="none"/>`; // bgTrack
|
|
let pc = colorFor(vl); // progColor
|
|
let pe = sd + swd * t; // progEnd
|
|
let ia = t > 0 ? `<path d="${arcPath(cx, cy, ri, sd, pe)}" stroke="${pc}" stroke-width="${si}" fill="none"/>` : ""; // innerArc
|
|
let tx = ""; // text
|
|
if (sv) {
|
|
let fs = Math.round(Math.min(w, h) * 0.18); // fontSize
|
|
tx = `<text x="${cx}" y="${cy}" text-anchor="middle" dominant-baseline="middle" font-size="${fs}" fill="${pc}" font-weight="600">${vl}${u}</text>`;
|
|
}
|
|
return `<svg width="${w}" height="${h}" viewBox="0 0 ${w} ${h}">${os}${bt}${ia}${tx}</svg>`.trim();
|
|
}
|
|
|
|
function renderLG(sl, w, h, sg = true, customXL = null) { // showGrid, customXLabels
|
|
let mv = Math.max(...sl.flatMap(s => s.values), 1); // maxVal
|
|
let gd = sg ? buildGrid(w, h, mv, sl[0].values.length, 4, customXL) : { lines: "", labels: "", xl: "" }; // grid
|
|
let clipId = `clip_${Math.random().toString(36).slice(2)}`; // Clip path to hide vertical edges at x=0 and x=w
|
|
let clip = `<clipPath id="${clipId}"><rect x="0" y="0" width="${w}" height="${h}"/></clipPath>`;
|
|
let df = [], ly = []; // defs, layers
|
|
sl.forEach((s, i) => {
|
|
let gi = `g${i}_${Math.random().toString(36).slice(2)}`; // gradId
|
|
df.push(`<linearGradient id="${gi}" x1="0" y1="0" x2="0" y2="${h}" gradientUnits="userSpaceOnUse"><stop offset="0%" stop-color="rgba(${s.rgb[0]},${s.rgb[1]},${s.rgb[2]},0.35)"/><stop offset="100%" stop-color="rgba(${s.rgb[0]},${s.rgb[1]},${s.rgb[2]},0)"/></linearGradient>`);
|
|
let pt = s.values.map((v, j) => { // points
|
|
let x = s.values.length > 1 ? (j * w) / (s.values.length - 1) : 0;
|
|
let y = v <= 0 ? h : h - (v / mv) * h;
|
|
return `${x},${y}`;
|
|
}).join(" ");
|
|
ly.push(`<polyline points="-20,${h} ${pt} ${w+20},${h}" fill="url(#${gi})" stroke="rgb(${s.rgb[0]},${s.rgb[1]},${s.rgb[2]})" stroke-width="2" clip-path="url(#${clipId})"/>`);
|
|
});
|
|
return `<svg width="${w}" height="${h+30}" viewBox="-50 0 ${w+100} ${h+40}">${gd.lines}${gd.labels}${gd.xl}<defs>${clip}${df.join("")}</defs>${ly.join("")}</svg>`.trim();
|
|
}
|
|
|
|
function renderH(vs, rgb, w, h, sg = true, cX = null) { // values, showGrid, customXLabels
|
|
let mv = Math.max(...vs, 1); // maxVal
|
|
let sc = mv > h ? h / mv : 1; // scale
|
|
let gp = 2; // gap
|
|
let tg = (vs.length - 1) * gp; // totalGaps
|
|
let bw = (w - tg) / vs.length; // barW
|
|
let gi = "hg_" + (Math.random()*1e9|0); // gradId
|
|
let df = `<linearGradient id="${gi}" x1="0%" y1="0%" x2="0%" y2="${h}" gradientUnits="userSpaceOnUse"><stop offset="0%" stop-color="rgba(${rgb[0]},${rgb[1]},${rgb[2]},1)"/><stop offset="100%" stop-color="rgba(${rgb[0]},${rgb[1]},${rgb[2]},0.1)"/></linearGradient>`; // defs
|
|
let rs = ''; // rects
|
|
vs.forEach((v, i) => {
|
|
let bh = Math.min(v * sc, h); // barH
|
|
let y = h - bh;
|
|
let x = i * (bw + gp);
|
|
rs += `<rect x="${x}" y="${y}" width="${bw}" height="${bh}" fill="url(#${gi})"/>`;
|
|
});
|
|
if (!sg) return `<svg width="${w}" height="${h}"><defs>${df}</defs>${rs}</svg>`;
|
|
let gd = buildGrid(w, h, mv, vs.length, 4, cX); // grid
|
|
return `<svg width="${w}" height="${h+30}" viewBox="-50 0 ${w+100} ${h+40}">${gd.lines}${gd.labels}${gd.xl}<defs>${df}</defs>${rs}</svg>`.trim();
|
|
}
|
|
</script>
|
|
|
|
<div>
|
|
<div class="parent" id="pr">
|
|
<div class="box h2" id="info">
|
|
<h2 id="clock"></h2>
|
|
<p id="ut"></p>
|
|
<p id="ro"></p>
|
|
<p id="sd"></p><br>
|
|
|
|
<p id="r"></p>
|
|
<p id="mo"></p>
|
|
<p id="pulse"></p><br>
|
|
|
|
<div id="heap_gauge"></div>
|
|
<p id="heap"></p>
|
|
<div id="psram_gauge"></div>
|
|
<p id="psram"></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
END_STATIC_PAGE
|
|
*/
|
|
|
|
|
|
const char MI32_STATIC_PAGE[] PROGMEM = {
|
|
/* AUTO-GENERATED (BEGIN) */
|
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc5, 0x3a, 0x6b, 0x93, 0xdb, 0x36,
|
|
0x92, 0xdf, 0xf3, 0x2b, 0x18, 0xc6, 0x8e, 0x88, 0x11, 0x45, 0x91, 0x9a, 0x19, 0xc7, 0x96, 0x04,
|
|
0xcd, 0xd9, 0x8e, 0xd7, 0xf6, 0xd5, 0x38, 0x97, 0x8a, 0xed, 0x5d, 0x57, 0x8d, 0x95, 0x0c, 0x45,
|
|
0x42, 0x24, 0x63, 0xbe, 0x8e, 0x80, 0x24, 0x2a, 0x32, 0xff, 0xfb, 0x75, 0x03, 0x20, 0x45, 0x8d,
|
|
0x1f, 0xe7, 0xbb, 0xdd, 0xaa, 0xad, 0xf2, 0x90, 0x40, 0x77, 0xa3, 0xd1, 0xe8, 0x37, 0x28, 0xcf,
|
|
0xb9, 0xd8, 0xa7, 0x6c, 0xb1, 0x2a, 0xc2, 0xfd, 0x21, 0x4c, 0x78, 0x99, 0xfa, 0xfb, 0xe9, 0x3a,
|
|
0x65, 0xf5, 0x0c, 0x1f, 0xa3, 0x30, 0xa9, 0x58, 0x20, 0x92, 0x22, 0x9f, 0x06, 0x45, 0xba, 0xc9,
|
|
0xf2, 0x26, 0x28, 0x42, 0x76, 0xd8, 0x15, 0x55, 0x38, 0x5a, 0x55, 0xcc, 0xff, 0x30, 0x95, 0xcf,
|
|
0x91, 0x9f, 0xa6, 0x8d, 0x53, 0xfa, 0x15, 0xcb, 0x45, 0xc7, 0x24, 0xaa, 0x92, 0x70, 0x86, 0x8f,
|
|
0x91, 0x60, 0x19, 0x40, 0x04, 0x1b, 0x29, 0x1e, 0x7c, 0x5a, 0xb1, 0x92, 0xf9, 0xc2, 0xf2, 0x37,
|
|
0xa2, 0x18, 0xad, 0x93, 0x34, 0xb5, 0xcf, 0x2f, 0xdd, 0xb2, 0x26, 0x77, 0xa8, 0xab, 0x62, 0xf7,
|
|
0x19, 0xd2, 0xc9, 0xe4, 0x48, 0x2a, 0xa1, 0x92, 0x4c, 0x42, 0x7b, 0xc0, 0x76, 0x27, 0xc9, 0x78,
|
|
0x16, 0xf9, 0xe5, 0xd4, 0xab, 0x58, 0x36, 0xfb, 0x73, 0xc3, 0x45, 0xb2, 0xde, 0x03, 0x3a, 0x17,
|
|
0x20, 0xeb, 0x34, 0x80, 0x07, 0xab, 0x1a, 0xbe, 0x8d, 0x0e, 0xeb, 0xb4, 0xf0, 0xc5, 0x34, 0xc9,
|
|
0xd3, 0x24, 0x67, 0x23, 0x96, 0x87, 0x08, 0x34, 0x04, 0xab, 0xc5, 0x61, 0x0d, 0xc4, 0x23, 0x9e,
|
|
0xfc, 0xc5, 0xa6, 0xae, 0xf3, 0xe8, 0x12, 0xb8, 0xa0, 0x1c, 0xd3, 0x60, 0x53, 0xe1, 0x71, 0x9f,
|
|
0x16, 0x69, 0x51, 0x35, 0xce, 0xaa, 0xa8, 0x0f, 0xa5, 0x1f, 0x86, 0x49, 0x1e, 0x4d, 0x3d, 0xdc,
|
|
0x72, 0x05, 0x2a, 0x62, 0xd5, 0xa8, 0xf2, 0xc3, 0x64, 0xc3, 0x61, 0xe1, 0x43, 0xdc, 0x7e, 0xe5,
|
|
0x07, 0x1f, 0xa2, 0xaa, 0xd8, 0xe4, 0x21, 0x0a, 0x58, 0x54, 0xd3, 0x2a, 0x5a, 0xf9, 0xd6, 0x64,
|
|
0xe2, 0xd9, 0xed, 0x9f, 0xeb, 0x4c, 0xc8, 0xac, 0xd8, 0xb2, 0x0a, 0xc4, 0xd9, 0x8d, 0xf6, 0x53,
|
|
0x3c, 0x8c, 0xe4, 0x6e, 0xa0, 0x8c, 0x99, 0x5f, 0x8f, 0x76, 0x49, 0x28, 0x62, 0xd8, 0xc3, 0xbd,
|
|
0x2f, 0xe1, 0xce, 0xce, 0x3b, 0xc8, 0x63, 0xab, 0x13, 0x4f, 0x79, 0xe9, 0xe7, 0x86, 0xa7, 0x51,
|
|
0x93, 0x4f, 0x51, 0x13, 0x8d, 0x3a, 0xff, 0x14, 0x75, 0xae, 0x50, 0xb1, 0x66, 0x08, 0x7a, 0x3d,
|
|
0xe1, 0x16, 0x4f, 0xee, 0xc0, 0x35, 0xab, 0xf8, 0xfc, 0x0e, 0xfc, 0xbc, 0xf9, 0x8f, 0x8c, 0x85,
|
|
0x89, 0x6f, 0x58, 0x52, 0x56, 0x63, 0x6e, 0xfc, 0x24, 0x6d, 0x76, 0xd0, 0x42, 0xd9, 0x5f, 0x94,
|
|
0xc0, 0xfb, 0x02, 0xc7, 0x49, 0xd3, 0xcc, 0xc7, 0xca, 0x4f, 0xe7, 0x3c, 0xa8, 0x92, 0x52, 0x2c,
|
|
0x52, 0x26, 0x0c, 0xfe, 0x17, 0xbd, 0x59, 0xda, 0x1b, 0xfa, 0x33, 0x78, 0x8b, 0x93, 0x17, 0x3b,
|
|
0x8b, 0xcc, 0xd6, 0x9b, 0x5c, 0xba, 0xab, 0x51, 0x6e, 0x52, 0xce, 0x2c, 0x4e, 0x0e, 0xfc, 0x2f,
|
|
0xa7, 0xdc, 0xf0, 0x18, 0x86, 0xb3, 0x64, 0x6d, 0xc1, 0x2c, 0x65, 0x79, 0x24, 0xe2, 0xc5, 0x03,
|
|
0x97, 0xc0, 0x84, 0xc7, 0xc9, 0x5a, 0xc0, 0xba, 0x54, 0x50, 0xd3, 0x72, 0xed, 0x89, 0xeb, 0xda,
|
|
0x2e, 0x99, 0x9a, 0x43, 0x40, 0xfd, 0x59, 0x24, 0xb9, 0x65, 0xda, 0x26, 0x99, 0x95, 0x01, 0xbd,
|
|
0x3d, 0x80, 0xe7, 0x5d, 0x22, 0x81, 0x7d, 0xef, 0x90, 0x8a, 0xa6, 0xb9, 0x9d, 0xb1, 0x95, 0x35,
|
|
0x90, 0xbb, 0x0c, 0x88, 0x93, 0xe4, 0x39, 0xab, 0x5e, 0xbc, 0x79, 0x75, 0x4d, 0xcd, 0xc7, 0xff,
|
|
0xf9, 0xf8, 0xdd, 0xd4, 0x30, 0x87, 0xe0, 0x1c, 0xe0, 0x00, 0x56, 0x19, 0x90, 0x59, 0xf3, 0x5d,
|
|
0x27, 0x16, 0x67, 0xe2, 0x6d, 0x69, 0x81, 0x54, 0x4c, 0xbc, 0x44, 0xd7, 0xdb, 0xfa, 0xa9, 0x15,
|
|
0xbc, 0xb5, 0xc1, 0x9c, 0x2e, 0x99, 0x6d, 0xca, 0x10, 0x4e, 0x62, 0x9d, 0x2c, 0x08, 0xde, 0x02,
|
|
0x35, 0x1e, 0x36, 0xef, 0x1d, 0xd3, 0xe6, 0xf4, 0x95, 0x2f, 0x62, 0x07, 0x9c, 0xa4, 0xa8, 0x2c,
|
|
0x2b, 0x1f, 0x6d, 0xc8, 0x58, 0xb1, 0xc0, 0x23, 0x2e, 0x5c, 0x72, 0xd8, 0x0c, 0x29, 0x3f, 0x43,
|
|
0xd0, 0x2c, 0x74, 0xfe, 0x7b, 0xc3, 0xaa, 0xfd, 0x6b, 0x96, 0x42, 0x20, 0x17, 0xd5, 0xe3, 0x34,
|
|
0xb5, 0x06, 0xce, 0x9b, 0x04, 0x84, 0x5e, 0x17, 0xd5, 0x33, 0x3f, 0x88, 0x2d, 0x46, 0x17, 0xcc,
|
|
0x41, 0x4f, 0x7f, 0xaa, 0xa2, 0x82, 0x0e, 0x4f, 0xa6, 0x43, 0x8e, 0x02, 0xd5, 0x14, 0xcf, 0x1b,
|
|
0xa4, 0x45, 0xf0, 0x61, 0x20, 0xb7, 0xa9, 0x49, 0xdd, 0x3b, 0xf6, 0xcf, 0x52, 0x70, 0x87, 0xa7,
|
|
0x49, 0xc0, 0xac, 0x0b, 0x7b, 0x72, 0x71, 0x72, 0x08, 0x75, 0xb0, 0x57, 0x4c, 0x54, 0x49, 0xc0,
|
|
0xad, 0x4c, 0x1d, 0x68, 0xfd, 0x81, 0x0e, 0xad, 0xec, 0xe6, 0x7c, 0x09, 0xa2, 0x03, 0xbd, 0x23,
|
|
0x8a, 0xbf, 0x25, 0x35, 0x0b, 0x2d, 0x0f, 0xac, 0x01, 0x68, 0xa1, 0xd0, 0x17, 0x5f, 0x40, 0xaf,
|
|
0x4b, 0x89, 0xfe, 0xe9, 0x2e, 0xda, 0xd5, 0xab, 0x15, 0xfa, 0xc1, 0x17, 0xd0, 0xeb, 0x58, 0xa2,
|
|
0x2f, 0x97, 0x44, 0x9a, 0xb1, 0x3a, 0x31, 0xe1, 0xe0, 0xb7, 0xd7, 0xaf, 0x5f, 0x4e, 0x8d, 0xc1,
|
|
0x30, 0xbb, 0x71, 0x97, 0xc3, 0x81, 0x11, 0x3e, 0xc9, 0x06, 0x92, 0x2c, 0x2b, 0x4e, 0xe9, 0x5e,
|
|
0x41, 0x2e, 0x44, 0xba, 0x9b, 0xc1, 0x75, 0xb1, 0x33, 0x7e, 0x83, 0x23, 0x0e, 0xec, 0xc1, 0x43,
|
|
0x77, 0xe2, 0x78, 0xde, 0xaa, 0x1b, 0x45, 0x30, 0x7a, 0xf1, 0x66, 0xe2, 0x1a, 0x96, 0xe7, 0xe5,
|
|
0x44, 0x4e, 0x2e, 0x7a, 0x93, 0x67, 0x0a, 0xe3, 0xd7, 0x64, 0xb0, 0xbc, 0xc9, 0x6e, 0x26, 0x4b,
|
|
0xdc, 0x71, 0x6c, 0x3c, 0x8d, 0x7d, 0xd8, 0x27, 0x55, 0x52, 0x78, 0x4b, 0xb9, 0x7d, 0xcc, 0xfc,
|
|
0xf2, 0x8f, 0xc8, 0xdf, 0x44, 0xa7, 0x1e, 0xa7, 0x1d, 0xed, 0xf6, 0x10, 0xd9, 0xe0, 0xa0, 0x97,
|
|
0xe8, 0xa0, 0xeb, 0x0f, 0x8d, 0x8d, 0x6f, 0x01, 0xef, 0xc9, 0xe5, 0x25, 0xb8, 0xd7, 0x44, 0xfe,
|
|
0xb9, 0x72, 0x26, 0x21, 0x97, 0xe7, 0xf6, 0x85, 0x6b, 0x6b, 0x8f, 0xb7, 0x1f, 0xba, 0xf6, 0x87,
|
|
0x27, 0xcd, 0xad, 0xd2, 0x46, 0xc9, 0x2b, 0x3f, 0xfb, 0xc6, 0x8d, 0x4a, 0xbd, 0x51, 0xf9, 0xb5,
|
|
0x8d, 0x3c, 0xf7, 0xb8, 0x13, 0x06, 0xd1, 0x71, 0x2b, 0x3c, 0xd2, 0xa9, 0x4e, 0x5f, 0x00, 0xc4,
|
|
0x58, 0x57, 0x4c, 0x2a, 0x76, 0xfd, 0x61, 0x38, 0x18, 0x0f, 0x86, 0x02, 0x5e, 0xc6, 0x87, 0x27,
|
|
0xf3, 0x55, 0xb5, 0xb0, 0xd6, 0x95, 0x1f, 0x39, 0x88, 0x8a, 0x87, 0x83, 0xfb, 0x64, 0x70, 0x14,
|
|
0xf8, 0x94, 0xcd, 0xaf, 0xaf, 0x7f, 0x7b, 0xfc, 0xea, 0xc8, 0xa7, 0x54, 0x7c, 0x4a, 0xc9, 0x47,
|
|
0x2d, 0xda, 0x88, 0xd3, 0x15, 0x6f, 0x4b, 0x91, 0x64, 0x4c, 0x29, 0xfc, 0x21, 0x1a, 0x81, 0xb3,
|
|
0x40, 0x51, 0x56, 0x77, 0xcc, 0xfe, 0xe4, 0xfa, 0x99, 0x51, 0x15, 0xa9, 0x36, 0x7d, 0x5e, 0xe4,
|
|
0x68, 0xf6, 0x62, 0xc5, 0x21, 0x9a, 0x59, 0x05, 0xc3, 0x92, 0x41, 0x86, 0x8a, 0x59, 0xe5, 0xa7,
|
|
0x30, 0xc1, 0x0a, 0x83, 0x23, 0x34, 0xee, 0xa3, 0xa5, 0x32, 0x24, 0x0f, 0xef, 0xf8, 0xd1, 0xcb,
|
|
0xf3, 0x09, 0x6c, 0x97, 0xf3, 0xa2, 0xe2, 0xda, 0xe2, 0xee, 0xf2, 0xd3, 0xf8, 0x81, 0x44, 0x00,
|
|
0x71, 0x17, 0x3a, 0x71, 0x12, 0x86, 0x2c, 0x27, 0x87, 0xd0, 0x81, 0x82, 0xf3, 0x6c, 0x0b, 0x1b,
|
|
0x5c, 0x27, 0x1c, 0x22, 0x15, 0x6c, 0x33, 0xd8, 0x26, 0x3c, 0x59, 0x25, 0x69, 0x22, 0xf6, 0x01,
|
|
0x78, 0x10, 0x18, 0xd0, 0x56, 0x6b, 0xed, 0x43, 0x91, 0x07, 0x6c, 0x2a, 0xaa, 0x0d, 0x6b, 0xc8,
|
|
0xac, 0x62, 0x62, 0x53, 0xe5, 0xb8, 0x03, 0x13, 0x90, 0x00, 0x06, 0xe3, 0xec, 0x7c, 0x72, 0xb5,
|
|
0x4b, 0xa8, 0x07, 0x72, 0x89, 0x98, 0xe5, 0x56, 0x45, 0x17, 0x95, 0xcc, 0x01, 0x16, 0xd1, 0x90,
|
|
0x58, 0x64, 0x29, 0x5d, 0x1c, 0x6a, 0x8a, 0x03, 0x9d, 0x43, 0x67, 0x2a, 0xc9, 0xd6, 0x32, 0x1f,
|
|
0x7c, 0x8f, 0x08, 0x72, 0xe8, 0x58, 0x63, 0x98, 0x41, 0x47, 0x20, 0xb8, 0x5a, 0x01, 0xa1, 0x9f,
|
|
0x61, 0x82, 0x28, 0x41, 0x36, 0x6b, 0x7c, 0xf3, 0x3e, 0x7f, 0x5f, 0xd9, 0xcb, 0xe1, 0x58, 0x2e,
|
|
0x95, 0x64, 0x9a, 0x27, 0xa5, 0xd4, 0xf3, 0x7e, 0xfc, 0x51, 0x81, 0x18, 0x28, 0x74, 0x6f, 0x95,
|
|
0x74, 0x31, 0xfe, 0x7d, 0x74, 0xf5, 0x3e, 0x1c, 0xde, 0x1b, 0x83, 0x50, 0x5c, 0x58, 0x25, 0x21,
|
|
0x90, 0xe2, 0x4e, 0x92, 0x8a, 0x5a, 0x90, 0xf9, 0xa5, 0xf5, 0xcb, 0x26, 0x5b, 0xb1, 0x8a, 0xf4,
|
|
0x4e, 0x89, 0xa2, 0x04, 0xc9, 0xeb, 0xbf, 0x3f, 0xa7, 0xe6, 0x1c, 0xab, 0x7a, 0xcc, 0x92, 0x28,
|
|
0x16, 0x74, 0x30, 0xb9, 0x18, 0x18, 0xb2, 0x44, 0xa9, 0xe1, 0xc2, 0xfc, 0x6e, 0x68, 0xce, 0x83,
|
|
0xa4, 0x0a, 0x52, 0x66, 0x04, 0x35, 0x1d, 0x78, 0xde, 0xc0, 0x08, 0xf6, 0xea, 0x5d, 0xd1, 0x81,
|
|
0x3b, 0x30, 0xb0, 0xf2, 0xd3, 0xc1, 0x0f, 0x8f, 0x5c, 0xc6, 0x1e, 0xc1, 0xb4, 0x28, 0xfd, 0x00,
|
|
0x54, 0x8d, 0x28, 0xb5, 0xd8, 0xcf, 0x93, 0x0c, 0x84, 0x32, 0x7c, 0x01, 0x52, 0xad, 0x36, 0x82,
|
|
0xfd, 0xe2, 0x67, 0x8c, 0x42, 0x7e, 0x01, 0x57, 0x2c, 0x32, 0xc5, 0x49, 0x14, 0x92, 0x55, 0xb8,
|
|
0x01, 0x96, 0x8f, 0x38, 0x70, 0x96, 0x1d, 0xce, 0x53, 0xe8, 0x0a, 0x40, 0x24, 0x6f, 0x30, 0xfe,
|
|
0x2a, 0x27, 0xbd, 0x63, 0xc7, 0xef, 0x5b, 0xd9, 0x8d, 0xd5, 0xb1, 0x16, 0x50, 0x46, 0xb7, 0xd1,
|
|
0xc2, 0x94, 0x49, 0x10, 0x28, 0x53, 0x3f, 0x60, 0xa1, 0x32, 0x90, 0x9e, 0x59, 0xe3, 0x43, 0x90,
|
|
0x34, 0xe3, 0xc8, 0x96, 0x0a, 0x23, 0x47, 0xf0, 0xfb, 0xc3, 0x4d, 0x7a, 0x1d, 0xbf, 0x88, 0x9e,
|
|
0x2f, 0xed, 0x9b, 0xdf, 0x9b, 0xe5, 0xf0, 0x3d, 0x12, 0x81, 0x88, 0x41, 0x0c, 0x6e, 0x21, 0xaa,
|
|
0xbd, 0xb6, 0xbc, 0xa1, 0xb3, 0x84, 0xc4, 0x60, 0x11, 0x08, 0x70, 0x60, 0x31, 0x72, 0x80, 0x9e,
|
|
0x8b, 0x43, 0xd4, 0x38, 0x3b, 0xbf, 0x82, 0xba, 0xfa, 0xf3, 0xeb, 0x6b, 0x4d, 0x6a, 0xb0, 0xaa,
|
|
0x82, 0x56, 0xc8, 0xb4, 0x59, 0x6b, 0x32, 0xb0, 0x52, 0x06, 0x1d, 0xe5, 0x22, 0xaa, 0xfc, 0x32,
|
|
0x36, 0x36, 0xb9, 0xbf, 0xf5, 0x93, 0xd4, 0x5f, 0xa5, 0x0c, 0xa4, 0x97, 0x08, 0x73, 0xd6, 0x80,
|
|
0x17, 0xd7, 0x34, 0x74, 0x02, 0x68, 0x3f, 0x05, 0x7b, 0x96, 0xb2, 0x0c, 0xc2, 0xc0, 0x1a, 0x84,
|
|
0xc9, 0x16, 0xaa, 0x53, 0x7d, 0x92, 0xb4, 0xd4, 0x21, 0xb5, 0x03, 0x62, 0xa1, 0x7f, 0x5c, 0x55,
|
|
0xfe, 0xde, 0x41, 0x05, 0x5a, 0xb5, 0x13, 0x31, 0xa1, 0x57, 0xf3, 0x27, 0xfb, 0x37, 0x7e, 0x84,
|
|
0x6a, 0x86, 0x08, 0x95, 0x4d, 0xc6, 0x80, 0x20, 0xfd, 0xb1, 0x4e, 0x42, 0x00, 0x30, 0x54, 0x54,
|
|
0x06, 0x0d, 0x1a, 0x04, 0xc6, 0x6c, 0x17, 0x27, 0x29, 0xb3, 0xa0, 0xd4, 0xd4, 0xce, 0x3a, 0xa9,
|
|
0x78, 0xcb, 0xe8, 0x29, 0x80, 0x43, 0x72, 0x00, 0xc3, 0x40, 0xb0, 0x8b, 0xd2, 0x49, 0x42, 0xe9,
|
|
0xe5, 0xa2, 0x20, 0xa2, 0xd0, 0x4d, 0xf2, 0x2f, 0x50, 0x39, 0x5a, 0xd5, 0x4a, 0x72, 0xa0, 0xb3,
|
|
0x81, 0x60, 0xc6, 0x20, 0xa0, 0x0c, 0x99, 0xd3, 0xb0, 0x26, 0xf9, 0x65, 0x09, 0x2a, 0x6a, 0x09,
|
|
0x50, 0x9b, 0x77, 0xc4, 0x91, 0x85, 0x94, 0x07, 0x9f, 0x2a, 0xa2, 0x3d, 0xc0, 0x8c, 0x07, 0x27,
|
|
0xa5, 0x1d, 0xe4, 0xef, 0x4d, 0xa1, 0x39, 0xc0, 0xbe, 0xff, 0x64, 0x1f, 0x1e, 0x90, 0xee, 0x88,
|
|
0xb3, 0x06, 0xff, 0x39, 0xda, 0x84, 0xb0, 0x5d, 0xa3, 0xb3, 0xc1, 0x1f, 0x74, 0x01, 0x1d, 0xcc,
|
|
0x1b, 0x48, 0x98, 0xc5, 0x46, 0x58, 0x3a, 0xc5, 0x40, 0x82, 0x27, 0x28, 0x63, 0x0f, 0x23, 0xdb,
|
|
0x1d, 0x28, 0x15, 0x6e, 0xaf, 0x33, 0x6b, 0x1b, 0x23, 0x7f, 0x0f, 0x1d, 0x77, 0xa8, 0x7a, 0x01,
|
|
0x4e, 0x5f, 0x83, 0x7d, 0xf2, 0xa8, 0x83, 0xb6, 0xe6, 0xc2, 0xc4, 0xc2, 0x1d, 0x2e, 0x30, 0xba,
|
|
0xff, 0x91, 0x88, 0xd8, 0x32, 0x0f, 0x26, 0xf9, 0xf8, 0x11, 0x60, 0xc0, 0x45, 0x43, 0x1a, 0x93,
|
|
0x10, 0xed, 0x38, 0xca, 0xb1, 0xa5, 0xf5, 0x29, 0xd7, 0xdd, 0x88, 0x67, 0x8f, 0xda, 0x96, 0x62,
|
|
0x5f, 0x82, 0xb6, 0xfd, 0x8a, 0x4a, 0x02, 0x28, 0xee, 0x12, 0xca, 0xe3, 0x62, 0xf7, 0x1c, 0xda,
|
|
0x4d, 0xda, 0xa1, 0x69, 0x37, 0x84, 0xbe, 0xe1, 0x2d, 0xe8, 0xa6, 0x7a, 0xea, 0x73, 0x54, 0x47,
|
|
0xcb, 0xa4, 0x8f, 0x87, 0xd2, 0xdf, 0xe1, 0x41, 0x5a, 0x33, 0x8d, 0x4d, 0x70, 0xbf, 0x20, 0xdd,
|
|
0x84, 0x8c, 0x5b, 0x48, 0x47, 0xd4, 0x11, 0x33, 0xb5, 0xab, 0x23, 0x03, 0xc3, 0x1a, 0xff, 0x6e,
|
|
0xc9, 0x70, 0x5a, 0x12, 0xdb, 0x82, 0xc4, 0xd6, 0x3d, 0x9d, 0x21, 0xb9, 0xa7, 0x92, 0xe2, 0xf7,
|
|
0xd9, 0xc9, 0xa1, 0x6e, 0x6c, 0x7b, 0x07, 0x3a, 0xb2, 0x63, 0x7c, 0x70, 0x78, 0x2c, 0x69, 0x26,
|
|
0xe5, 0xd9, 0xd1, 0x21, 0x22, 0xe4, 0x18, 0xba, 0x9a, 0xb8, 0x1d, 0xd7, 0x29, 0xcd, 0x37, 0x69,
|
|
0xaa, 0x8e, 0xc8, 0x22, 0x8a, 0x6b, 0x74, 0xfa, 0x35, 0x3f, 0x42, 0x53, 0x0b, 0x6e, 0x64, 0x49,
|
|
0x65, 0x51, 0x77, 0x96, 0xcc, 0x81, 0xa2, 0x4d, 0xea, 0xc9, 0x70, 0x28, 0x0b, 0x0d, 0x80, 0x6e,
|
|
0x92, 0xe5, 0x89, 0xee, 0xeb, 0x74, 0x0a, 0xba, 0x3e, 0x00, 0xeb, 0x16, 0xb9, 0x59, 0x71, 0x65,
|
|
0xb8, 0xf3, 0x36, 0xb7, 0xcb, 0x8e, 0x19, 0xd9, 0xe1, 0x14, 0xd4, 0x9f, 0xd8, 0xa0, 0x7d, 0x79,
|
|
0x4b, 0x84, 0xa0, 0x95, 0xa9, 0x98, 0xcb, 0xe5, 0x32, 0x57, 0xa3, 0x60, 0xca, 0x89, 0xb3, 0x4c,
|
|
0x03, 0x95, 0x76, 0xde, 0x5b, 0x27, 0x6a, 0xc1, 0xe7, 0x7b, 0x32, 0xb5, 0x9c, 0xb3, 0xa3, 0x7a,
|
|
0x5a, 0xfd, 0x18, 0xf2, 0x98, 0x6a, 0x7c, 0x80, 0x0b, 0xd5, 0xf4, 0x66, 0x98, 0x61, 0xcf, 0x64,
|
|
0xe3, 0x6b, 0xa2, 0x5e, 0xe7, 0xcb, 0xa5, 0x0d, 0xad, 0xf6, 0x86, 0xf1, 0x69, 0x86, 0x3d, 0x65,
|
|
0x4f, 0x56, 0x29, 0xc7, 0x96, 0x2e, 0x54, 0xd9, 0xb0, 0xb6, 0xda, 0xf3, 0x08, 0x69, 0xd0, 0xf5,
|
|
0x21, 0xe1, 0x43, 0x97, 0x6e, 0x3d, 0x29, 0x20, 0x73, 0xf9, 0x39, 0x1c, 0x6c, 0x97, 0xa0, 0x80,
|
|
0xd2, 0xae, 0x87, 0x00, 0xac, 0x6e, 0xa6, 0xe6, 0xf4, 0x24, 0xf3, 0x5d, 0x3f, 0xb7, 0x78, 0x6a,
|
|
0xef, 0xec, 0xd8, 0x6e, 0x1d, 0xcb, 0xae, 0xd3, 0x56, 0x03, 0x72, 0x45, 0x6c, 0x4e, 0x51, 0xbd,
|
|
0x69, 0xaf, 0xe2, 0x91, 0xef, 0x4e, 0x78, 0xbc, 0x00, 0x2c, 0xb8, 0xa7, 0xa3, 0x44, 0xb6, 0xd5,
|
|
0x04, 0x8e, 0xf6, 0x25, 0xb6, 0xa0, 0x58, 0x4c, 0x30, 0xe8, 0x99, 0x94, 0x9a, 0x91, 0xa9, 0x3c,
|
|
0xae, 0xd4, 0x1e, 0xa7, 0xce, 0x0a, 0xbd, 0x08, 0x69, 0x1d, 0xa6, 0x44, 0xf5, 0xc4, 0xf8, 0x9e,
|
|
0x48, 0xbd, 0xe0, 0xe8, 0x7c, 0x69, 0x67, 0x49, 0x8e, 0xa3, 0x0b, 0x18, 0xf9, 0x35, 0x8e, 0x2e,
|
|
0x75, 0x84, 0x88, 0xa2, 0xe4, 0x70, 0xd5, 0xea, 0xf9, 0xcc, 0x03, 0xf0, 0x99, 0x52, 0x1f, 0x60,
|
|
0xe4, 0x81, 0xcf, 0xd0, 0x0b, 0xb8, 0xd4, 0x20, 0x9d, 0xba, 0x6d, 0x1d, 0xa4, 0xe8, 0x53, 0xe0,
|
|
0x91, 0x0c, 0x81, 0xb3, 0xba, 0xed, 0xde, 0xc2, 0x11, 0xac, 0x7b, 0x07, 0x80, 0x2d, 0x1b, 0x5b,
|
|
0xbe, 0x87, 0x5e, 0x37, 0x9a, 0x2c, 0x1b, 0x72, 0xdb, 0x10, 0x5d, 0xae, 0x37, 0x79, 0x22, 0x68,
|
|
0x79, 0x73, 0xdc, 0xe2, 0x18, 0xab, 0x7f, 0x47, 0xce, 0xd4, 0xea, 0x45, 0xab, 0xf9, 0xdc, 0x6c,
|
|
0x4b, 0x87, 0x56, 0xe0, 0x73, 0x0b, 0xf6, 0xc7, 0xf3, 0xe0, 0x49, 0x94, 0xd6, 0x50, 0x36, 0x1b,
|
|
0xd9, 0xda, 0x1d, 0x13, 0xdc, 0xac, 0x8b, 0xb1, 0x5e, 0xbb, 0xb5, 0xda, 0x40, 0x22, 0x44, 0x15,
|
|
0x5b, 0xb8, 0x32, 0xdb, 0xda, 0xe1, 0xb5, 0xbd, 0x17, 0xf4, 0xc2, 0x0e, 0xde, 0xc9, 0x98, 0x52,
|
|
0xea, 0x4d, 0x73, 0xbc, 0x7d, 0xa6, 0x2b, 0x7c, 0x42, 0x44, 0xdc, 0x28, 0x09, 0xf3, 0x4c, 0x5d,
|
|
0xcd, 0x02, 0x96, 0xa4, 0x56, 0xb6, 0x85, 0xeb, 0x07, 0x81, 0x7b, 0x98, 0xca, 0x1c, 0x09, 0xcd,
|
|
0xb3, 0xf1, 0x5e, 0xc8, 0x62, 0x90, 0xcc, 0xe9, 0x25, 0x01, 0xc8, 0xa5, 0x4a, 0xf9, 0x1a, 0x04,
|
|
0xd4, 0x00, 0x03, 0xfa, 0x3e, 0x70, 0x22, 0x09, 0x27, 0x9a, 0x12, 0x86, 0xc7, 0x0d, 0x44, 0x32,
|
|
0xbe, 0x84, 0x0d, 0x2e, 0xdd, 0xd9, 0xdd, 0x7d, 0x45, 0x42, 0xce, 0x44, 0x22, 0xf7, 0xf5, 0x45,
|
|
0x0f, 0x05, 0x12, 0x00, 0xea, 0x4e, 0xf4, 0x53, 0x5f, 0xa8, 0xb0, 0x47, 0xd0, 0x96, 0x26, 0xed,
|
|
0xca, 0x3d, 0x8d, 0x47, 0xd6, 0xf6, 0x2c, 0x1e, 0xe7, 0x19, 0xf8, 0x4e, 0xae, 0x4c, 0x7b, 0x3b,
|
|
0xc7, 0x4f, 0x24, 0x46, 0xed, 0x51, 0xd3, 0x35, 0x8d, 0x3d, 0xbc, 0xee, 0x1d, 0xf6, 0x8d, 0x69,
|
|
0xd4, 0x13, 0x1c, 0xed, 0x60, 0xb4, 0x9f, 0xb4, 0x30, 0x48, 0x0e, 0xc5, 0x07, 0x46, 0xcd, 0x1f,
|
|
0xc2, 0x30, 0x6c, 0x67, 0xea, 0x0b, 0x06, 0x35, 0x3d, 0x73, 0xbc, 0xb8, 0x95, 0xb1, 0x9c, 0xcc,
|
|
0x7d, 0x41, 0xd2, 0x55, 0xcb, 0x1e, 0x0b, 0x94, 0x51, 0x53, 0x73, 0x74, 0x09, 0xac, 0x24, 0xa7,
|
|
0xe1, 0x05, 0xf0, 0x42, 0xf0, 0xc8, 0xcf, 0x83, 0xb8, 0xa8, 0xa8, 0x09, 0x56, 0x36, 0x17, 0xf7,
|
|
0x0e, 0xdb, 0x66, 0x3e, 0x46, 0x38, 0x32, 0x92, 0x31, 0x10, 0xbc, 0xfb, 0xf1, 0xc7, 0xe0, 0x5d,
|
|
0x7b, 0xc7, 0x77, 0xd5, 0x89, 0x6a, 0x4e, 0x3b, 0x18, 0x38, 0xeb, 0xe9, 0xd9, 0x3b, 0xcc, 0x51,
|
|
0x03, 0x35, 0xad, 0xe1, 0x12, 0x7d, 0x95, 0x9c, 0x59, 0xbb, 0x71, 0xcd, 0xc9, 0x74, 0x37, 0x9e,
|
|
0xcc, 0xea, 0xf4, 0xae, 0x78, 0xf7, 0x0e, 0x75, 0xa3, 0x05, 0x8c, 0x87, 0x13, 0xf7, 0xae, 0x84,
|
|
0x19, 0x74, 0xe9, 0x29, 0x43, 0x21, 0x83, 0x77, 0xe8, 0xf0, 0x3d, 0x41, 0x1b, 0x34, 0x64, 0x2b,
|
|
0xd9, 0xc5, 0x5d, 0x5b, 0xd4, 0xbc, 0x2f, 0x49, 0x2b, 0x84, 0xca, 0xe9, 0xda, 0xf6, 0xf2, 0x13,
|
|
0x92, 0x05, 0xa8, 0xf0, 0x1a, 0x6a, 0x9b, 0x44, 0xff, 0x13, 0xf2, 0xd5, 0xc9, 0x89, 0x70, 0x3a,
|
|
0x24, 0x0e, 0x68, 0x65, 0x3e, 0x05, 0xab, 0xab, 0x0f, 0x21, 0x26, 0xb1, 0xa1, 0x07, 0x03, 0xc9,
|
|
0xa7, 0x60, 0xa9, 0x0e, 0x04, 0x15, 0x01, 0x76, 0x6e, 0xa7, 0x4d, 0x3f, 0x8a, 0xba, 0x48, 0xb4,
|
|
0x33, 0x08, 0xc3, 0x36, 0x0a, 0xed, 0x0d, 0x35, 0x4d, 0x9b, 0x6f, 0x29, 0x5e, 0x45, 0xd4, 0x21,
|
|
0x83, 0x94, 0xd6, 0x74, 0x21, 0x0f, 0x06, 0xd1, 0x6a, 0x01, 0xb5, 0x1a, 0x03, 0x4f, 0x58, 0x56,
|
|
0x13, 0x75, 0xf6, 0x6d, 0x4a, 0x83, 0xd4, 0xda, 0xaa, 0x09, 0x2f, 0x69, 0x56, 0x8f, 0xb2, 0xfc,
|
|
0xe3, 0x47, 0x4f, 0x85, 0x16, 0xb5, 0xb6, 0x29, 0xcc, 0xc9, 0x98, 0x97, 0x12, 0x00, 0xed, 0x3b,
|
|
0x58, 0xcd, 0x86, 0xee, 0x3d, 0x06, 0xe3, 0xc9, 0x6e, 0xb7, 0xa0, 0x1d, 0x5b, 0x10, 0x85, 0x9c,
|
|
0xb9, 0xce, 0xc5, 0xa5, 0xc2, 0x24, 0xb4, 0x2a, 0x60, 0xfa, 0x93, 0x9a, 0xf2, 0x42, 0x4d, 0xdd,
|
|
0x07, 0x36, 0xd7, 0x98, 0x73, 0x85, 0x89, 0x42, 0xaa, 0x78, 0xf1, 0x90, 0x8e, 0xbc, 0xf3, 0xcb,
|
|
0x61, 0x14, 0xda, 0xd0, 0x3e, 0xc3, 0x68, 0x04, 0x23, 0xbe, 0x0b, 0x29, 0x0b, 0x47, 0x3c, 0xec,
|
|
0x7d, 0x84, 0x2a, 0x52, 0xbf, 0xb2, 0x82, 0x1a, 0xe4, 0xb0, 0x2b, 0x5b, 0xf7, 0x3a, 0x55, 0x48,
|
|
0xad, 0x70, 0xf4, 0x08, 0xc2, 0x56, 0xca, 0xf3, 0xeb, 0xcb, 0xb1, 0xf7, 0xd0, 0x6d, 0xeb, 0x57,
|
|
0x3d, 0x0d, 0xea, 0x61, 0xa5, 0x30, 0x41, 0xc1, 0xad, 0x2a, 0x24, 0xf6, 0x7e, 0x1a, 0xec, 0x5b,
|
|
0x18, 0x07, 0xe9, 0x01, 0x76, 0xa2, 0x68, 0xbf, 0x0a, 0x7e, 0x05, 0x5c, 0xb7, 0x8f, 0xef, 0xda,
|
|
0xbe, 0xa7, 0x73, 0x94, 0xaf, 0x0e, 0xed, 0xaf, 0xb8, 0xe5, 0x7b, 0x23, 0xdf, 0x25, 0x0b, 0xd8,
|
|
0xec, 0xca, 0x9b, 0xaa, 0x8c, 0xc4, 0x77, 0xd4, 0xf7, 0x16, 0xfe, 0x11, 0x50, 0xba, 0xf4, 0x54,
|
|
0x66, 0x5f, 0x7f, 0x30, 0x29, 0xbd, 0xbb, 0x08, 0xaf, 0x4d, 0xb9, 0xb7, 0xaf, 0x0c, 0xc8, 0xe0,
|
|
0xae, 0x53, 0xcb, 0x4c, 0xee, 0x3a, 0xfb, 0xc6, 0x78, 0x0c, 0x90, 0x0a, 0xa7, 0x55, 0x63, 0xb8,
|
|
0x30, 0x4e, 0xfd, 0x06, 0x9e, 0x7c, 0x87, 0xcf, 0xd2, 0xd3, 0x94, 0x1e, 0x50, 0xde, 0x9e, 0x7c,
|
|
0xea, 0xc2, 0x22, 0xf1, 0x37, 0x08, 0x86, 0xad, 0xec, 0x3f, 0xbe, 0xe7, 0x42, 0x47, 0x66, 0xdb,
|
|
0x08, 0x61, 0xf9, 0xf0, 0x26, 0xae, 0xad, 0xff, 0x88, 0xea, 0xf6, 0x02, 0xca, 0x05, 0xd6, 0x47,
|
|
0xb9, 0xfc, 0x6e, 0x5b, 0x23, 0xee, 0x76, 0x35, 0xdb, 0x05, 0x92, 0x27, 0xba, 0xb6, 0x92, 0x40,
|
|
0xcf, 0xd4, 0x62, 0x99, 0x60, 0x75, 0x49, 0x6d, 0x2b, 0x72, 0xa0, 0x2b, 0x52, 0xc1, 0xc1, 0x71,
|
|
0xbf, 0xce, 0x5e, 0x7e, 0x59, 0xaa, 0xa8, 0xd5, 0xdb, 0xa0, 0xef, 0x93, 0x70, 0x21, 0xb0, 0xa0,
|
|
0xe2, 0x1d, 0x57, 0x91, 0x2b, 0x49, 0x0a, 0x45, 0xf0, 0x84, 0x78, 0xaa, 0x7c, 0xda, 0x77, 0x29,
|
|
0x0f, 0x87, 0xe0, 0x55, 0x67, 0x6b, 0x54, 0x77, 0x3b, 0x11, 0x05, 0xa6, 0x4c, 0xdf, 0x83, 0xa4,
|
|
0xed, 0x12, 0xfc, 0x8e, 0x9d, 0xe4, 0x1b, 0x36, 0x2b, 0xf8, 0x90, 0xde, 0xce, 0x4b, 0xb0, 0xb5,
|
|
0x11, 0x62, 0xc4, 0xf7, 0x7c, 0x02, 0xae, 0xb0, 0x36, 0x78, 0xbf, 0x0d, 0x0c, 0xe1, 0xcf, 0x23,
|
|
0xbd, 0xb4, 0x0c, 0x36, 0x39, 0x9e, 0xbe, 0xb9, 0x9b, 0xa0, 0x01, 0x5b, 0x00, 0x50, 0xde, 0x79,
|
|
0x4d, 0xfc, 0xcc, 0x81, 0x09, 0x5b, 0x6b, 0x63, 0x25, 0xbe, 0xbe, 0x5d, 0x62, 0x43, 0x90, 0xd8,
|
|
0x06, 0x0b, 0xfb, 0xdb, 0xc9, 0xaf, 0xdd, 0x3d, 0x03, 0xe2, 0xd7, 0xee, 0x4b, 0xf2, 0x99, 0x6d,
|
|
0x93, 0x4f, 0xb7, 0x95, 0x4e, 0x18, 0xd0, 0xa3, 0x8f, 0xa4, 0xda, 0x31, 0x59, 0xa7, 0x18, 0xd5,
|
|
0xfb, 0xfb, 0x54, 0x40, 0xee, 0xfe, 0x16, 0xe1, 0xa0, 0x85, 0x3b, 0xd1, 0x45, 0x19, 0x34, 0xdf,
|
|
0x24, 0xcb, 0x54, 0x5f, 0x33, 0x44, 0x8d, 0x1e, 0x81, 0xad, 0xdc, 0x56, 0xdb, 0x9e, 0xf7, 0xd3,
|
|
0xf3, 0xdd, 0x6c, 0xe3, 0x3d, 0x24, 0x33, 0x58, 0xd2, 0x4f, 0xd0, 0x41, 0x97, 0xa1, 0x83, 0xfd,
|
|
0x17, 0xf2, 0xb3, 0x11, 0x16, 0xc0, 0xc3, 0xcf, 0xc5, 0x68, 0x05, 0xbd, 0x23, 0xe6, 0xe4, 0x23,
|
|
0xaa, 0xfb, 0x61, 0x02, 0x39, 0xac, 0x79, 0x27, 0xa8, 0x3e, 0x8a, 0x44, 0xef, 0xd4, 0xb7, 0x0e,
|
|
0xf3, 0x81, 0xeb, 0xca, 0x82, 0x99, 0x36, 0xf7, 0x0e, 0x9b, 0x2e, 0xdf, 0x77, 0x6e, 0x7e, 0x2b,
|
|
0x3f, 0x8c, 0x74, 0xa7, 0xc6, 0x2a, 0xae, 0xbf, 0x92, 0x60, 0xf9, 0x80, 0xd9, 0x36, 0x61, 0xbb,
|
|
0x27, 0x05, 0x48, 0xed, 0xca, 0x88, 0x96, 0xa1, 0x0c, 0x70, 0x60, 0x59, 0x70, 0x60, 0xb9, 0x12,
|
|
0xf0, 0x48, 0x7c, 0x78, 0x88, 0xba, 0x51, 0x1f, 0x19, 0x6e, 0xdb, 0x3b, 0xdc, 0x27, 0x35, 0xa1,
|
|
0xd7, 0x22, 0x47, 0xb2, 0x0e, 0xd8, 0xc1, 0x06, 0xfa, 0xb3, 0xec, 0xdd, 0x75, 0xaf, 0xbd, 0xca,
|
|
0xb6, 0xb4, 0x2b, 0x09, 0x8e, 0x03, 0x77, 0x39, 0x67, 0x9d, 0xfa, 0xe2, 0x15, 0x5e, 0x1a, 0xe0,
|
|
0xf2, 0xa9, 0x5b, 0x63, 0x62, 0xeb, 0xab, 0x1d, 0xa4, 0x66, 0x1e, 0x5d, 0x7d, 0xd2, 0xb8, 0xf5,
|
|
0xdb, 0x68, 0x1d, 0x74, 0xf6, 0x45, 0xb7, 0x1b, 0x99, 0xea, 0x22, 0x07, 0x15, 0x49, 0xd7, 0x36,
|
|
0x18, 0xe1, 0x25, 0xc7, 0x6c, 0x54, 0x6a, 0x49, 0x93, 0xf2, 0x65, 0x48, 0x6f, 0xf1, 0xfd, 0xc7,
|
|
0xbd, 0x83, 0x32, 0xae, 0x9f, 0x83, 0x49, 0x2c, 0xfc, 0xa4, 0xac, 0xef, 0xac, 0xe7, 0x0f, 0xda,
|
|
0x0f, 0xdf, 0x13, 0xd2, 0xdc, 0x76, 0x0b, 0xc1, 0xd2, 0xf8, 0x42, 0xd7, 0x33, 0x12, 0xe9, 0x88,
|
|
0x8a, 0x1d, 0x28, 0x6d, 0x8e, 0x3f, 0xaa, 0xa1, 0x0b, 0xb8, 0xd2, 0xfc, 0xf0, 0xfc, 0xb2, 0xe6,
|
|
0xc7, 0x8b, 0xf9, 0xb8, 0xe5, 0xa3, 0xe3, 0x20, 0x5c, 0xcb, 0xce, 0x73, 0x8f, 0x3d, 0x27, 0xea,
|
|
0x45, 0x7f, 0x10, 0xb0, 0xb8, 0x9d, 0x10, 0x7d, 0x9d, 0x8a, 0x12, 0x7a, 0x1b, 0x81, 0x45, 0x9a,
|
|
0x6f, 0x16, 0x3b, 0x5c, 0xf7, 0xdb, 0x3b, 0xbf, 0x7a, 0x8e, 0x3f, 0x5d, 0xb1, 0x5c, 0x68, 0xd9,
|
|
0x23, 0x8c, 0x83, 0x5e, 0xcf, 0xe7, 0xaa, 0x86, 0xcf, 0x6d, 0xbb, 0x3d, 0xf4, 0x91, 0x48, 0x2f,
|
|
0x79, 0x0b, 0x5d, 0x36, 0x64, 0xcb, 0x0d, 0x67, 0xd5, 0xeb, 0xd2, 0x0f, 0xd8, 0x7f, 0xe5, 0x6f,
|
|
0xe1, 0xda, 0xb3, 0x98, 0x63, 0x0f, 0x6e, 0x14, 0xeb, 0x35, 0x67, 0x70, 0x38, 0xf7, 0xbe, 0x29,
|
|
0x2f, 0x16, 0xea, 0x97, 0x30, 0x9d, 0x1c, 0x20, 0xde, 0xf0, 0x9e, 0x03, 0x46, 0xc3, 0x12, 0xa1,
|
|
0xc6, 0x5e, 0x6f, 0x0c, 0x97, 0x04, 0x1b, 0xcb, 0x31, 0x41, 0xb5, 0x9c, 0xb0, 0xc3, 0x1f, 0xc4,
|
|
0xfe, 0xbf, 0x0c, 0x25, 0xb7, 0xf1, 0xe9, 0xb1, 0xb1, 0x17, 0x92, 0xf9, 0x45, 0xd0, 0xd6, 0xd9,
|
|
0xe4, 0x4d, 0x11, 0xda, 0x99, 0x3f, 0x5b, 0x25, 0xd7, 0x47, 0x94, 0x6e, 0x38, 0xbd, 0x2b, 0xeb,
|
|
0xcf, 0xb3, 0x1d, 0x19, 0x5b, 0x77, 0x10, 0xd0, 0xa5, 0xe9, 0x0a, 0xbb, 0xa7, 0xdb, 0x39, 0x75,
|
|
0xaf, 0xe2, 0x29, 0x76, 0xd6, 0xe3, 0x6c, 0x4b, 0xce, 0xe2, 0xb6, 0x8e, 0x62, 0xc3, 0x66, 0x63,
|
|
0xdf, 0x7c, 0x8b, 0x37, 0x4f, 0xd5, 0x53, 0x19, 0x70, 0xb3, 0x49, 0xf7, 0xad, 0x65, 0xa0, 0x04,
|
|
0xef, 0x65, 0xf3, 0x5d, 0x02, 0x12, 0x55, 0x3c, 0x92, 0xbf, 0x47, 0xc5, 0xb2, 0xae, 0x0a, 0x7c,
|
|
0xee, 0xb0, 0xd3, 0xb3, 0x95, 0x39, 0x54, 0x32, 0xd8, 0x54, 0xa9, 0xf5, 0x83, 0xb4, 0x1f, 0x39,
|
|
0xc9, 0xc4, 0xdf, 0xa2, 0x9a, 0x4f, 0x72, 0xf3, 0xc4, 0x94, 0xae, 0x3d, 0xc2, 0xe4, 0xda, 0xb1,
|
|
0xd6, 0x6e, 0x4d, 0x54, 0x3f, 0xdf, 0x7d, 0x5e, 0xfe, 0x7a, 0x4a, 0x19, 0x9e, 0xbb, 0xfd, 0xac,
|
|
0x32, 0xba, 0xd4, 0x79, 0x65, 0x08, 0x86, 0x94, 0xb9, 0x65, 0x78, 0xe1, 0xca, 0xf4, 0x12, 0x85,
|
|
0x8e, 0x0c, 0xd2, 0x46, 0x0d, 0x65, 0x98, 0xaa, 0x71, 0x9d, 0x36, 0xf3, 0x90, 0xad, 0xf9, 0x42,
|
|
0x89, 0x00, 0x40, 0xf0, 0xe1, 0xae, 0x15, 0x9d, 0x8f, 0x35, 0x0e, 0xd4, 0xd7, 0x03, 0x7e, 0x3d,
|
|
0x33, 0xbd, 0xb0, 0xb6, 0xdc, 0xee, 0x2e, 0xda, 0x6d, 0x72, 0x7a, 0xf7, 0xe5, 0xb4, 0x04, 0xe4,
|
|
0x3a, 0x03, 0xf1, 0x80, 0x66, 0xdb, 0x45, 0x7c, 0x15, 0x83, 0x51, 0x75, 0x05, 0x8f, 0x4a, 0xdd,
|
|
0x2f, 0x8a, 0x08, 0xfa, 0xd3, 0x9e, 0x2f, 0x9c, 0x45, 0xaa, 0x23, 0x58, 0xed, 0xa8, 0xb5, 0x1b,
|
|
0x89, 0x88, 0x8c, 0x3b, 0xec, 0x4c, 0x47, 0xaf, 0x19, 0x47, 0x7f, 0x98, 0x43, 0xeb, 0x24, 0x76,
|
|
0xcf, 0x3c, 0xf6, 0xe8, 0xa3, 0x6e, 0xc8, 0x20, 0x07, 0xfc, 0xaf, 0x91, 0x7a, 0x5f, 0x87, 0xea,
|
|
0x7d, 0x1d, 0xab, 0xf7, 0xff, 0xd5, 0xc1, 0x7a, 0x74, 0x9f, 0xa3, 0xf3, 0xb4, 0x51, 0xe5, 0xfd,
|
|
0x1f, 0x62, 0xf4, 0x6b, 0x7c, 0xa0, 0x70, 0x7e, 0x3e, 0x3e, 0x55, 0xef, 0xce, 0xe9, 0x60, 0x30,
|
|
0x03, 0xed, 0x75, 0x49, 0x70, 0x7b, 0x4c, 0x82, 0xab, 0xf8, 0xd8, 0xf2, 0x6f, 0xcf, 0x78, 0x00,
|
|
0x75, 0xb8, 0xbb, 0xd6, 0xae, 0x94, 0xa6, 0xe5, 0x05, 0x6b, 0xb5, 0x1b, 0x46, 0x25, 0xb8, 0xad,
|
|
0xec, 0xa1, 0xda, 0xd4, 0xdc, 0xbb, 0x3e, 0x61, 0x6d, 0xee, 0xfc, 0x78, 0x75, 0xea, 0xc8, 0xab,
|
|
0xcf, 0x47, 0x9a, 0xec, 0x94, 0xf4, 0xe7, 0xcb, 0x88, 0x7c, 0x5b, 0x8d, 0x5d, 0xb4, 0xde, 0x1c,
|
|
0xae, 0x8f, 0xde, 0x5b, 0xf1, 0xd6, 0x69, 0xdb, 0x3a, 0xf7, 0x49, 0x91, 0xdb, 0xf6, 0x4b, 0xdb,
|
|
0xbb, 0x7f, 0x47, 0xf8, 0x7d, 0x5e, 0xe0, 0x2e, 0xca, 0x60, 0xae, 0x7e, 0xb4, 0x9f, 0x87, 0xc9,
|
|
0x56, 0x3e, 0x20, 0x8b, 0xf8, 0x9c, 0x53, 0xf5, 0x31, 0x1c, 0xfd, 0xb6, 0xac, 0xfa, 0x70, 0x13,
|
|
0xff, 0xc3, 0x43, 0x0c, 0xc9, 0x06, 0x30, 0x49, 0xbe, 0x2e, 0x16, 0xf3, 0x78, 0x82, 0x63, 0xf9,
|
|
0xf3, 0x33, 0xb8, 0x42, 0x3c, 0x59, 0xcc, 0x4b, 0x04, 0x6c, 0x80, 0xe7, 0xb8, 0xd4, 0x93, 0xaa,
|
|
0xe8, 0x4d, 0x78, 0xa8, 0x26, 0xab, 0xaa, 0xc5, 0xf6, 0x90, 0x59, 0x9f, 0x52, 0xfe, 0x88, 0x75,
|
|
0x24, 0x46, 0x29, 0x00, 0x7a, 0xfc, 0xb1, 0x15, 0x50, 0x52, 0xec, 0xb2, 0x05, 0x2b, 0x5a, 0x4d,
|
|
0xd7, 0xfb, 0xb1, 0xf4, 0x84, 0x50, 0xc2, 0x15, 0xa5, 0x82, 0xf6, 0x9e, 0xff, 0x03, 0xd2, 0x55,
|
|
0x50, 0x4a, 0x73, 0x23, 0x00, 0x00
|
|
/* AUTO-GENERATED (END) */
|
|
};
|
|
constexpr unsigned int MI32_STATIC_PAGE_len = sizeof(MI32_STATIC_PAGE);
|
|
|
|
|
|
#endif //USE_MI_EXT_GUI
|
|
#endif // USE_WEBSERVER
|
|
|
|
#endif //USE_MI_ESP32
|