THB2/bthome_phy6222/web/PHY62x2BTHome.html
2024-12-08 19:47:13 +03:00

2656 lines
220 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<html class="phy6222Class"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PHY62x2 BTHome v1.7</title>
<!--<link rel="stylesheet" type="text/css" href="styles.css" />
<link rel="stylesheet" type="text/css" href="chart.css" />
<script type="text/javascript" src="dygraph.min.js" /></script> /-->
<!--link rel="stylesheet" type="text/css" href="https://dygraphs.com/dist/dygraph.min.css /-->
<!--script type="text/javascript" src="https://dygraphs.com/dist/dygraph.min.js" /></script-->
<style type="text/css">
/* basic sytles */
body {
font-family: Arial, 'Open Sans', sans-serif;
color: #204056;
}
h1 {
font-size: 28px;
font-weight: 400;
text-align: center;
margin-top: 12px;
margin-bottom: 18px;
}
hr {
height: 10px;
border: 0;
box-shadow: 0 10px 10px -10px #8c8b8b inset;
}
span#info {
font-style: italic;
}
.button, [type='button'] {
background-color: #1a73e8;
border: none;
border-radius: 4px;
color: white;
padding: 8px 24px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 14px;
margin: 6px 6px;
cursor: pointer;
box-shadow: 0 3px 1px -2px #0003, 0 2px 2px #00000024, 0 1px 5px #0000001f;
}
.button, [type='button'].ok {
background-color: #4CAF50; /* Green */
color: white;
border-color: #4CAF50;
}
.button, [type='button'].danger {
background-color: #f44336; /* Red */
color: white;
border-color: #f44336;
}
.button, [type='button']:disabled {
cursor: not-allowed;
opacity: 0.6;
}
input[type="checkbox"] + label {
margin-right: 8px;
}
div#div_v {
height:400px;
margin-top: 16px;
margin-bottom: 16px;
}
div#labdiv {
margin-top: 16px;
margin-bottom: 16px;
}
div#log {
padding: 12px;
font-style: italic;
font-size: 16px;
}
div#MAC {
font-style: smaller;
margin: 8px;
}
div#txtStatus {
font-style: italic;
font-size: 16px;
text-align: center;
background-color: #eef6fc;
padding-top: 5px;
padding-bottom: 5px;
margin-top: 8px;
}
div#tempHumiData{
text-align: center;
background-color: #eef6fc;
padding-top: 5px;
padding-bottom: 5px;
}
input {
padding: 4px;
margin: 4px;
}
select {
padding: 4px;
}
/* menu */
.navbar {
width: 95%;
/* box-shadow: 0 1px 4px rgb(146 161 176 / 15%);*/
position: absolute;
top: 0;
}
.nav-container {
display: flex;
justify-content: space-between;
align-items: center;
height: 62px;
}
.navbar .menu-items {
display: flex;
}
.navbar .nav-container li {
list-style: none;
}
.navbar .nav-container a {
font-size: 1.0rem;
font-weight: 400;
}
.navbar .nav-container a:hover{
font-weight: bolder;
}
.nav-container {
display: block;
position: relative;
height: 60px;
}
.nav-container .checkbox {
position: absolute;
display: block;
height: 32px;
width: 32px;
top: 20px;
left: 20px;
z-index: 5;
opacity: 0;
cursor: pointer;
}
.nav-container .hamburger-lines {
display: block;
height: 26px;
width: 32px;
position: absolute;
top: 17px;
left: 20px;
z-index: 2;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.nav-container .hamburger-lines .line {
display: block;
height: 4px;
width: 100%;
border-radius: 10px;
background: #0e2431;
}
.nav-container .hamburger-lines .line1 {
transform-origin: 0% 0%;
transition: transform 0.4s ease-in-out;
}
.nav-container .hamburger-lines .line2 {
transition: transform 0.2s ease-in-out;
}
.nav-container .hamburger-lines .line3 {
transform-origin: 0% 100%;
transition: transform 0.4s ease-in-out;
}
.navbar .menu-items {
position: relative;
padding-top: 55px;
box-shadow: 5px 3px 13px 0px rgb(204 204 204 / 80%);
min-height: 100vh;
width: 60%;
transform: translate(-150%);
display: flex;
flex-direction: column;
transition: transform 0.5s ease-in-out;
text-align: center;
z-index: 1;
background: white;
}
.navbar .menu-items li {
margin-bottom: 12px;
font-size: 1.2rem;
font-weight: 800;
}
.nav-container input[type="checkbox"]:checked ~ .menu-items {
transform: translateX(0);
}
.nav-container input[type="checkbox"]:checked ~ .hamburger-lines .line1 {
transform: rotate(45deg);
}
.nav-container input[type="checkbox"]:checked ~ .hamburger-lines .line2 {
transform: scaleY(0);
}
.nav-container input[type="checkbox"]:checked ~ .hamburger-lines .line3 {
transform: rotate(-45deg);
}
.nav-container input[type="checkbox"]:checked ~ .logo{
display: none;
}
.shadowbox {
width: 15em;
border: 1px solid #333;
box-shadow: 8px 8px 5px #444;
padding: 8px 12px;
background-image: linear-gradient(180deg, #fff, #ddd 40%, #ccc);
}
.shadowprogress {
width: 15em;
border: 1px solid #333;
/* box-shadow: 8px 8px 5px #444; */
padding: 8px 12px;
/* background-image: linear-gradient(180deg, #fff, #ddd 40%, #ccc); */
}
.shadowerror {
color: red;
width: 15em;
border: 1px solid #333;
box-shadow: 8px 8px 5px #444;
padding: 8px 12px;
background-image: linear-gradient(180deg, #fff, #ddd 40%, #ccc);
}
/* Style the tab */
.tab {
overflow: hidden;
border: 1px solid #ccc;
background-color: #f1f1f1;
}
/* Style the buttons inside the tab */
.tab button {
background-color: inherit;
float: left;
border: none;
border-radius: 4px;
outline: none;
cursor: pointer;
padding: 10px 20px;
transition: 0.3s;
font-size: 14px;
}
/* Change background color of buttons on hover */
.tab button:hover {
/* background-color: #ddd; */
background-color: #1a73e8;
}
/* Create an active/current tablink class */
.tab button.active {
/* background-color: #ccc; */
background-color: #4aa3ff;
}
/* Style the tab content */
.tabcontent {
display: none;
padding: 6px 12px;
border: 1px solid #ccc;
border-top: none;
}
/* Create equal columns that floats next to each other */
.column {
float: left;
padding: 5px;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/**
* Default styles for the dygraphs charting library.
*/
.dygraph-legend {
position: relative;
font-size: 12px;
z-index: 10;
width: 250px; /* divLabelsWidth */
/*
dygraphs determines these based on the presence of chart labels.
It might make more sense to create a wrapper div around the chart proper.
top: 0px;
right: 2px;
*/
background: white;
line-height: normal;
text-align: center;
overflow: hidden;
}
/* styles for a solid line in the legend */
.dygraph-legend-line {
display: inline-block;
position: relative;
bottom: .5ex;
padding-left: 1em;
height: 1px;
border-bottom-width: 2px;
border-bottom-style: solid;
/* border-bottom-color is set based on the series color */
}
/* styles for a dashed line in the legend, e.g. when strokePattern is set */
.dygraph-legend-dash {
display: inline-block;
position: relative;
bottom: .5ex;
height: 1px;
border-bottom-width: 2px;
border-bottom-style: solid;
/* border-bottom-color is set based on the series color */
/* margin-right is set based on the stroke pattern */
/* padding-left is set based on the stroke pattern */
}
.dygraph-roller {
position: absolute;
z-index: 10;
}
/* This class is shared by all annotations, including those with icons */
.dygraph-annotation {
position: absolute;
z-index: 10;
overflow: hidden;
}
/* This class only applies to annotations without icons */
/* Old class name: .dygraphDefaultAnnotation */
.dygraph-default-annotation {
border: 1px solid black;
background-color: white;
text-align: center;
}
.dygraph-axis-label {
/* position: absolute; */
/* font-size: 14px; */
z-index: 10;
line-height: normal;
overflow: hidden;
color: black; /* replaces old axisLabelColor option */
}
.dygraph-axis-label-x {
}
.dygraph-axis-label-y {
color: green;
}
.dygraph-axis-label-y2 {
color: blue;
}
.dygraph-title {
font-weight: bold;
z-index: 10;
text-align: center;
/* font-size: based on titleHeight option */
}
.dygraph-xlabel {
text-align: center;
/* font-size: based on xLabelHeight option */
}
/* For y-axis label */
.dygraph-label-rotate-left {
text-align: center;
/* See http://caniuse.com/#feat=transforms2d */
transform: rotate(90deg);
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-o-transform: rotate(90deg);
-ms-transform: rotate(90deg);
}
/* For y2-axis label */
.dygraph-label-rotate-right {
text-align: center;
/* See http://caniuse.com/#feat=transforms2d */
transform: rotate(-90deg);
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
}
div#divChart {
height: 100%;
width: 100%;
margin-top: 16px;
margin-bottom: 16px;
}
</style>
</head>
<body>
<script>
const i18n = (() => {
const lang = getUserLang();
const tags = {
PREFIX: { en: 'Prefix named after devices(а)' },
CONNECT: { en: 'Connect' },
DISCONNECT: { en: 'Disconnect', ru: 'Отключение' },
RECONNECT: { en: 'Reconnect', ru: 'Переподключение' },
TIME: { en: 'Time' },
TEMPERATURE: { en: 'Temperature', ru: 'Температура' },
HUMIDITY: { en: 'Humidity', ru: 'Влажность' },
BATTERYSTATE: { en: 'Battery level' },
SHOW_TIME: { en: 'Show time' },
SHOW_SMILEY: { en: 'Show smiley' },
SHOW_TRIGGER: { en: 'Show trigger' },
DISCONNECT_DISPLAY: { en: 'Disconnect display' },
ENCRYPTED_AD: { en: 'Encrypted advertising' },
MS: { en: 'ms' },
AD_INTERVAL: { en: 'Advertizing interval' },
MEASUREMENT_STEP: { en: 'Measurement step' },
BAT_INTERVAL: { en: 'Battery survey interval' },
HISTORY_INTERVAL: { en: 'History interval' },
READ: { en: 'Read' },
WRITE: { en: 'Write' },
RESTORE: { en: 'Restore' },
GET_DEVICETIME: { en: 'Get device time' },
SET_DEVICETIME: { en: 'Set device time', ru: 'Авто установка часов устройства' },
COMFORT: { en: 'Comfort' },
TRIGGER: { en: 'Trigger' },
HYSTERESIS: { en: 'Hysteresis' },
OUTPUT_INVERTED: { en: 'Inverted output' },
SENSOR_PARAMS: { en: 'Sensor parameters' },
CORRECTION_COEFF: { en: 'Correction coefficients' },
CORRECTION_DISPLAY: { en: 'Display correction' },
FILE: { en: 'File', ru: 'Файл' },
NO_FILE: { en: '(no file)', ru: 'не загружен' },
SELECT_UPLOAD: { en: 'Select OTA file' },
START: { en: 'Start', ru: 'Старт' },
START_OTA: { en: 'Start OTA flashing', ru: 'Старт программирования' },
SHOW_HISTORY: { en: 'Show stored history' },
MEM_RW: { en: 'Read / write memory' },
ADDRESS: { en: 'Address', ru: 'адрес' },
DATA: { en: 'Data' },
COMMAND: { en: 'Command' },
SEND: { en: 'Send' },
DEVICENAME: { en: 'Device name', ru: 'Имя устройства' },
CLEAN_LOG: { en: 'Purge log file' },
BASIC_INST: { en: 'Basic configuration' },
FROMTO_FROM: { en: 'from', ru: 'из' },
FROMTO_TO: { en: 'to' },
CONNECTION_FAILED: { en: 'Connection failed', ru: 'Подключиться не удалось' },
SEARCH_DEVICES: { en: 'Searching for devices', ru: 'Поиск устройств' },
FOUND: { en: 'Found', ru: 'Найден' },
UNKNOWN_RESPONSE: { en: 'Unknown resonse from device', ru: 'Странный ответ устройства' },
CONNECTED: { en: 'Connected', ru: 'Устройство подключено' },
NOT_CONNECTED: { en: 'Not connected', ru: 'Не подключено' },
MODE: { en: 'Mode', ru: 'Режим' },
SWITCH_TO: { en: 'Switch to', ru: 'Переключение на' },
WAIT_CON_TO: { en: 'Waiting for connection to', ru: 'Ожидание соединения с' },
SERVER: { en: 'server', ru: 'сервер' },
WRONG_DEVICE: { en: 'Wrong device selected', ru: 'Выбрано неверное устройтво' },
DEVICE_DISABLED: { en: 'Device is disconnected', ru: 'Устройство отключено' },
STATE: { en: 'State', ru: 'Состояние' },
ERROR: { en: 'Error', ru: 'Ошибка' },
IMPROPER_FIRMWARE_SIZE: { en: 'Improper size of binary firmware', ru: 'Неправильный размер двоичной прошивки' },
FIRMWARE_TOO_BIG: { en: 'Firmware is bigger than %s', ru: 'Размер прошивки более %s кбайт' },
IMPROPER_FIRMWARE: { en: 'Inappropriate format of the firmware file size', ru: 'Неверный формат размера файла для прошивки' },
SPECIAL_FIRMWARE: { en: 'Special firmware', ru: 'специальная прошивка' },
SEGMENTS: { en: 'Segments', ru: 'Сегментов' },
SIZE: { en: 'Size', ru: 'Размер' },
WRONG_NUMOF_SEGMENTS: { en: 'Wrong number of segments', ru: 'Неверное количество сегментов в заголовке' },
WRONG_HEADER_SIZE: { en: 'Wrong header size', ru: 'Неверный размер в заголовке' },
FILE_CRC_ERROR: { en: 'CRC error in file', ru: '' },
CALCULATED: { en: 'calculated', ru: 'Расчет' },
NOT_UPLOADED: { en: 'not uploaded', ru: 'не загружен' },
FILESIZE: { en: 'Filesize', ru: 'Размер файла' },
BYTES: { en: 'bytes', ru: 'байт' },
COUNTER: { en: 'Counter', ru: 'Счетчик' },
BLOCKS: { en: 'blocks', ru: 'блоков' },
WRONG_COMMAND: { en: 'Wrong command', ru: 'Неверная команда' },
START_NOT_SET: { en: 'Start not set', ru: 'Не задан старт' },
PARAMS_NOT_SET: { en: 'Parameters not set', ru: 'Не заданы параметры' },
WRONG_PARAMS: { en: 'Wrong parameters', ru: 'Неверные параметры' },
WRONG_PACKET_SIZE: { en: 'Wrong packet size', ru: 'Неправильный размер пакета' },
PACKAGE_CRC_ERROR: { en: 'Package CRC Error', ru: 'Ошибка CRC16 пакета' },
PACKAGE_LOSS: { en: 'Package loss', ru: 'Потеря пакетов' },
FLASH_WRITE_ERROR: { en: 'Flash write error', ru: 'Ошибка записи в Flash' },
PACKAGE_SIZE_ERROR: { en: 'Package size error', ru: 'Ошибка в номере пакета' },
IDENTIFIER_ERROR: { en: 'identifier error in program file', ru: 'Ошибка идентификатора в файле программы' },
PROGRAM_CRC_ERROR: { en: 'CRC Error in program file', ru: 'Ошибка CRC32 переданной программы' },
UNKNOWN_ERROR: { en: 'Enknown error', ru: 'Неизвестная ошибка' },
NO_FILE_ERROR: { en: 'Error: No file selected', ru: '"Не выбран файл' },
FLASH_FINISHED: { en: 'Flash finished in %s seconds', ru: 'Программирование завершено за %s секунды' },
RELOAD_COMMAND_FAILED: { en: 'Reload command failed', ru: 'Ошибка передачи команды перезагрузки после ' },
ON_BLOCK: { en: 'during block transmission', ru: 'на передаче блока' },
SUCCEEDED: { en: 'succeeded', ru: 'успеха' },
SECONDS: { en: 'seconds', ru: 'сек' },
MINUTES: { en: 'minutes', ru: 'минут' },
TOTAL_TIME: { en: 'total time', ru: 'время от старта' },
BLOCK_TRANSFERRED: { en: 'Block transferred', ru: 'Передан блок' },
ERROR_SENDING_DATA: { en: 'Error sending data', ru: 'Ошибка при отправке данных' },
READING_BYTES: { en: 'Reading %s bytes at', ru: 'Чтение %s байт по адресу' },
WRITING_BYTES: { en: 'Writing %s bytes at', ru: 'Запись %s байт по адресу' },
BLOCK_LENGTH_RANGE: { en: 'Block length must be 1 to 16 bytes', ru: 'длина блока от 1 до 16 байт' },
COMMAND_LENGTH_RANGE: { en: 'Command length must be 1 to MTU bytes', ru: 'длина команды от 1 до MTU байт' },
BATTERY: { en: 'Battery', ru: 'Батарея' },
MILLIVOLT: { en: 'mV', ru: 'мВ' },
MEMO_EMPTY: { en: 'Memo is empty', ru: 'Пока нет истории' },
NO_MEMO_SERVICE: { en: 'No memo service', ru: 'Нет сервиса записи истории' },
FLAGS: { en: 'flags', ru: 'флаги' },
TIME_ON_DEVICE: { en: 'Time on device', ru: 'Время на устройстве' },
DIFFERENCE: { en: 'Difference', ru: 'Уход' },
CONFIG_DATA: { en: 'Configuration data', ru: 'Строка конфигурации' },
DATA_AT_ADDRESS: { en: 'Data at address', ru: 'Данные по адресу' },
REGISTER_AT_ADDRESS: { en: 'Register at address', ru: 'Регистр по адресу' },
SERIALNUM: { en: 'Serial number', ru: 'Серийный номер' },
READ_ERROR: { en: 'Read error', ru: 'Ошибка чтения' },
NOT_SUPPORTED: { en: 'Not supported', ru: 'Не поддерживается' },
LAST_TIME_SETTING: { en: 'Last time setting', ru: 'Последняя установка времени' },
PASSED_ON_DEVICE: { en: 'Passed on device', ru: 'Прошло на устройстве' },
MIN_TIME_CALC: { en: 'Minimum time period is 3 hours', ru: 'Минимальный перод для расчета ухода часов 3 часа' },
CLOCK_ADVANCE_ERR: { en: 'The clock must be set in advance', ru: 'Часы необходимо настроить заранее' },
UPDATE: { en: 'Update', ru: 'Обновление' },
TRIGGER_DATA: { en: 'Trigger settings line', ru: 'Строка настроек триггера' },
COMFORT_TEMPERATURE: { en: 'Comfort temperature', ru: 'Комфорт Температура' },
DEVICE: { en: 'Device MAC', ru: 'MAC устройства' },
COMMAND_RESPONSE: { en: 'Command response', ru: 'Ответ на команду' },
SET_DEVICE_TIME: { en: 'Set device time', ru: 'Установка времени на устройстве' },
TIME_IS_SYNCED: { en: 'Device time is synchronized', ru: 'Время на устройстве синхронизировано' },
SENDING_NEW_MAC: { en: 'Sending new MAC address', ru: 'Передача нового MAC' },
INVALID_MAC_LENGTH: { en: 'MAX length must be 6 bytes (hex)', ru: 'Строка MAC должна быть 6 байт в HEX виде' },
DEPRECATED_FIRMWARE: { en: 'Firware versions below 1.1 are not supported', ru: 'Версия прошивки с номером менее 1.1 не поддерживается' },
CORRECT_DEVICENAME_LENGTH: { en: 'Save DeviceName...', ru: 'Сохранение имени устройства...' },
INVALID_DEVICENAME_LENGTH: { en: 'Devicename length must be 1 to 19 bytes (UTF-8 characters consume 2 bytes)', ru: 'Имя устройства должно быть от 1 до 19 символов, включая кодирование UTF-8' },
INVALID_BINDKEY_LENGTH: { en: 'Bindkey must be 16 bytes, hex encoded (=32 characters)', ru: 'BindKey должен соднержать 16 байт в HEX виде (32 символа)' },
INVALID_FINDMYKEY_LENGTH: { en: 'FindMyKey must be 22 bytes, hex encoded (=44 characters)', ru: 'BindKey должен соднержать 22 байта в HEX виде (44 символа)' },
UPLOAD_FIRMWARE: { en: 'Download firmware file', ru: 'Загрузка firmware файла' },
WARNING_BOOT_FW: { en: 'Attention!: Uploading boot FW is not safe. In order to avoid firmware failure use a fresh battery!', ru: 'Внимание!: Обновление Boot fw не безопасно. Во избежание сбоя прошивки желательно использование полной батареи!' },
MEMO_OFF: {en: 'Disabled', ru: 'Отключено'},
SHOW_TEMPF: {en: 'Show Temperature in Fahrenheit', ru: 'Показывать температуру в градусах Фаренгейта'},
};
function getUserLang() {
const userLang = window.navigator.language.toLowerCase();
if (userLang === 'ru') {
return 'ru';
}
return 'en';
}
function getTag(tagName) {
const entry = tags[tagName];
if(!entry) {
console.error(`Unknown i18n tag "${tagName}"`);
}
return entry && entry[lang] ? entry[lang] : '';
}
function updatePage() {
for (const element of document.querySelectorAll('[data-i18ntag]')) {
const newText = getTag(element.getAttribute('data-i18ntag'));
if (newText) {
element.innerHTML = newText;
}
}
}
return {
getTag,
updatePage
};
})();
//BLE values
const FLASH_SIZE = 0x80000;
const OTA_MAX_SIZE = 0x30000; // 196608
const SERVICE_OTA = 0x00000001; // funtion OTA
const SERVICE_OTA_EXT = 0x00000002; // expanded function OTA
const SERVICE_PINCODE = 0x00000004; // installation pin-code
const SERVICE_BINDKEY = 0x00000008; // encryption
const SERVICE_HISTORY = 0x00000010; // Record of history
const SERVICE_SCREEN = 0x00000020; // screen
const SERVICE_LE_LR = 0x00000040; // Advertising support in LE Long Range
const SERVICE_THS = 0x00000080; // temperature and humidity sensor
const SERVICE_RDS = 0x00000100; // Serving Hocon/Impulse accounts
const SERVICE_KEY = 0x00000200; // button
const SERVICE_OUTS = 0x00000400; // The service of the output for Pins
const SERVICE_INS = 0x00000800; // Maintenance of input pins
const SERVICE_TIME_ADJUST = 0x00001000; // Time account correction function
const SERVICE_HARD_CLOC = 0x00002000; // Real hours RTC
const SERVICE_TH_TRG = 0x00004000; // temperature and humidity
const SERVICE_BUTTON = 0x00200000 // кнопка, активность только при нажатии
var bluetoothDevice, gattServer, otaCharacteristic, cmdCharacteristic, infoService;
var hwver_id = null;
var otafiles = { loaded: false };
var devInfo = {};
var devSrv = { services: 0 };
var devCfg = {};
var devSens = {};
var devTrig = {};
var devTime = {};
var devKeys = {};
var devName = "";
var isConnected = false;
var isChartEnabled = true;
var isMemoActive = false;
var startTime = 0;
var memoCount = 0;
var ota = {
fwArray: null,
fwname: "",
fwsize: 0,
// fwmaxsize: 196608,
ext_flg: false,
blockCount: 0,
program_offset: 0x11010000
};
var flashBuffer = null;
//Connection values
var connectRetries = 0;
var $ = function(id) { return document.getElementById(id);}
const isEmpty = str => !str.trim().length;
function resetVariables() {
gattServer = null;
hwver_id = null;
mainService = null;
otaCharacteristic = null;
cmdCharacteristic = null;
$('btnDisconnect').disabled = true;
$('btnStartDFU').disabled = true;
}
function handleError(text) {
showError(text);
resetVariables();
if ((bluetoothDevice != null) && (connectRetries < 5)) {
addLog(`${i18n.getTag('RECONNECT')} ${connectRetries} / 5`)
$('btnDisconnect').disabled = true;
$('btnReconnect').disabled = true;
connectRetries++;
doConnect();
} else {
addLog(`${i18n.getTag('CONNECTION_FAILED')}!`);
connectRetries = 0;
$('btnConnect').disabled = false;
}
}
function connect() {
var deviceOptions = {
optionalServices: [0x1800, 0x180a, 0x180f, 0x181a, 0xfcd2],
services: [0x1800, 0x180a, 0x180f, 0x181a, 0xfcd2],
acceptAllDevices: true };
const namePrefix = $('inpNamePrefix').value;
if (namePrefix) {
deviceOptions.acceptAllDevices = false;
deviceOptions.filters = namePrefix.split(",")
.map((x) => ({ namePrefix: x }));
}
console.log(deviceOptions);
if (bluetoothDevice != null) bluetoothDevice.gatt.disconnect();
chartData.length = 0;
resetVariables();
bluetoothDevice = null;
$('btnReconnect').disabled = true;
$('tabConfig').style.display = "none";
if(typeof(navigator.bluetooth) != "undefined") {
$('btnConnect').disabled = true;
showState(i18n.getTag('SEARCH_DEVICES'));
connectRetries = 0;
//console.log()
navigator.bluetooth.requestDevice(deviceOptions).then(device => {
bluetoothDevice = device;
bluetoothDevice.addEventListener('gattserverdisconnected', onDisconnected);
//addLog("Connecting to: " + bluetoothDevice.name);
doConnect();
}).catch(handleError);
} else {
showError("Browser doesn't support BLE API");
}
}
function disconnect() {
addLog(i18n.getTag('DISCONNECT'));
isConnected = false;
if (bluetoothDevice != null)
bluetoothDevice.gatt.disconnect();
}
function reconnect() {
addLog(i18n.getTag('RECONNECT'));
if (bluetoothDevice != null) {
bluetoothDevice.gatt.disconnect();
isConnected = false;
}
$('btnConnect').disabled = true;
$('btnReconnect').disabled = true;
connectRetries = 0;
doConnect();
}
function getStrCharacteristic(infosrv, suuid) {
return new Promise((resolve, reject) => {
infosrv.getCharacteristic(suuid).then(characteristic => {
characteristic.readValue().then(value => {
return resolve(new TextDecoder("utf-8").decode(value));
}).catch(error => {console.log(error); return resolve(null); });
}).catch(error => {console.log(error); return resolve(null); });
})};
function getDevInfo(devInfEnabled) {
return new Promise((resolve, reject) => {
devInfo.nrstr = null;
devInfo.srstr = null;
devInfo.frstr = null;
devInfo.hrstr = null;
devInfo.vrstr = null;
if (devInfEnabled == true) {
gattServer.getPrimaryService(0x180a).then(service => {
console.log(`${i18n.getTag('FOUND')} Device Information Service`);
infoService = service;
return getStrCharacteristic(infoService, 0x2a24).then(value => {
devInfo.nrstr = value;
//DOMException: getCharacteristic(s) called with blocklisted UUID. https://goo.gl/4NeimX
//return getStrCharacteristic(infoService, 0x2a25).then(value => {
// devInfo.srstr = value;
return getStrCharacteristic(infoService, 0x2a26).then(value => {
devInfo.frstr = value;
return getStrCharacteristic(infoService, 0x2a27).then(value => {
devInfo.hrstr = value;
return getStrCharacteristic(infoService, 0x2a28).then(value => {
devInfo.vrstr = value;
return resolve(devInfo.flg);
}).catch(error => { console.log(error); return resolve(null);});
}).catch(error => { console.log(error); return resolve(null);});
}).catch(error => { console.log(error); return resolve(null);});
//}).catch(error => { console.log(error); return resolve(null);});
}).catch(error => { console.log(error); return resolve(null);});
}).catch(error => { console.log(error); return resolve(null);});
} else return resolve(null);
}).catch(error => { console.log(error); return resolve(null);});
}
function linkOta() {
return new Promise((resolve, reject) => {
mainService.getCharacteristic(0xfff3).catch(error => { console.log(error); return resolve(null);})
.then(characteristic => {
console.log(`${i18n.getTag('FOUND')} OTA Characteristic`);
otaCharacteristic = characteristic;
return otaCharacteristic.addEventListener('characteristicvaluechanged', event => parseBlkOTA(event.target.value));
}).then(_ => {
return otaCharacteristic.readValue();
}).then(value => {
if(value.byteLength > 1) {
addLog("OTA ver: "+ hex(value.getUint8(1),2));
$("btnStartDFU").value = i18n.getTag('START_OTA');
}
return resolve(null);});
}).catch(error => { console.log(error); return resolve(null);});
}
function phyConnect(info_flg) {
return getDevInfo(info_flg).then(_ => {
if(devInfo.nrstr != null)
addLog("Model: "+devInfo.nrstr);
if(devInfo.srstr != null)
addLog("Serial: "+devInfo.srstr);
if(devInfo.frstr != null)
addLog("Firmware: "+devInfo.frstr);
if(devInfo.hrstr != null)
addLog("Hardware: "+devInfo.hrstr);
if(devInfo.vrstr != null)
addLog("Software: "+devInfo.vrstr);
return gattServer.getPrimaryService(0xfcd2);
}).then(service => {
console.log(`${i18n.getTag('FOUND')} Main Service`);
mainService = service;
cmdCharacteristic = null;
return mainService.getCharacteristic(0xfff4);
}).then(characteristic => {
console.log(`${i18n.getTag('FOUND')} CMD Characteristic`);
cmdCharacteristic = characteristic;
return cmdCharacteristic.addEventListener('characteristicvaluechanged', event => parseBlkCustom(event.target.value));
}).then(_ => {
return cmdCharacteristic.startNotifications();
}).then(_ => {
return cmdCharacteristic.readValue();
}).then(value => {
if(value.byteLength >= 10)
if(value.getUint8(0) != 0)
addLog(`${i18n.getTag('UNKNOWN_RESPONSE')}!`);
else if((value.getUint32(8, true) & 1) != 0) // SERVICE_OTA ?
return linkOta();
otaCharacteristic = null;
}).then(_ => {
showState(`${i18n.getTag('CONNECTED')}.`);
isConnected = true;
// $('btnConnect').disabled = true;
$('btnDisconnect').disabled = false;
// $('btnReconnect').disabled = false;
disableControls(false);
// selectConfigTab();
// $('tabConfig').style.display = "block";
let el = $('btnStartDFU');
if (otaCharacteristic != null) {
el.disabled = ota.fwArray == null;
el.innerHTML = i18n.getTag('START');
el.title = i18n.getTag('START_OTA');
} else {
el.innerHTML = `${i18n.getTag('MODE')} OTA`;
el.title = `${i18n.getTag('SWITCH_TO')} BootLoader ...`
}
return cmdCharacteristic.writeValue(new Uint8Array([0x33])); // get measure
}).catch(handleError);
}
function doConnect() {
isConnected = false;
showState(`${i18n.getTag('WAIT_CON_TO')} ${bluetoothDevice.name}`)
return bluetoothDevice.gatt.connect().then(server => {
console.log(`${i18n.getTag('FOUND')} GATT ${i18n.getTag('SERVER')}`);
gattServer = server;
gattServer.getPrimaryServices().then(services => {
let phy = false;
let info = false;
for (var i = 0; i < services.length; i++) {
console.log("Services: " + services[i].uuid);
if (services[i].uuid == "0000180a-0000-1000-8000-00805f9b34fb")
info = true;
else if (services[i].uuid == "0000fcd2-0000-1000-8000-00805f9b34fb")
phy = true;
}
if(phy)
return phyConnect(true);
addLog(`${i18n.getTag('WRONG_DEVICE')}!`);
bluetoothDevice.gatt.disconnect();
connectRetries = 10;
return null;
}).catch(handleError);
}).catch(handleError);
}
function auxControls(state)
{
if (devSrv.services & SERVICE_SCREEN) {
$('tblChkCfg').style.display = "block";
$('tblComfort').style.display = "block";
} else {
$('tblChkCfg').style.display = "none";
$('tblComfort').style.display = "none";
}
if (devSrv.services & SERVICE_BINDKEY) {
$('labBindKey').style.display = "block";
$('divBindKey').style.display = "block";
} else {
$('labBindKey').style.display = "none";
$('divBindKey').style.display = "none";
}
if (devSrv.services & SERVICE_TH_TRG)
$('tblTrigger').style.display = "block";
else
$('tblTrigger').style.display = "none";
if (devSrv.services & (SERVICE_SCREEN | SERVICE_TH_TRG)) {
$('tblTriggerKeys').style.display = "block";
$('hrPres').style.display = "block";
} else {
$('tblTriggerKeys').style.display = "none";
$('hrPres').style.display = "none";
}
if (devSrv.services & SERVICE_THS) {
$('tblSensorTH').style.display = "block";
} else {
$('tblSensorTH').style.display = "none";
}
if (devSrv.services & SERVICE_BUTTON) {
$('tblButton').style.display = "block";
$('trMeasStep').style.display = "none";
$('divFindMyKey').style.display = "block";
} else {
$('tblButton').style.display = "none";
$('trMeasStep').style.display = "block";
$('divFindMyKey').style.display = "none";
}
if (devSrv.services & SERVICE_HISTORY) {
$('trHistStep').style.display = "block";
} else {
$('trHistStep').style.display = "none";
}
}
function disableControls(state)
{
//--debug devSrv.services = SERVICE_SCREEN|SERVICE_TH_TRG;
auxControls(state);
if(state) { // hide
$('hrSensorData').style.display = "none";
$('tblSensorData').style.display = "none";
} else { // show
$('hrSensorData').style.display = "block";
$('tblSensorData').style.display = "block";
}
$('btnGetDev').disabled = state;
$('btnSetDev').disabled = state;
$('btnRstDev').disabled = state;
$('btnGetSens').disabled = state;
$('btnSetSens').disabled = state;
$('btnRstSens').disabled = state;
$('btnGetDevTime').disabled = state;
$('btnSetDevTime').disabled = state;
$('btnReadAddr').disabled = state;
$('btnWriteAddr').disabled = state;
$('btnSendCommand').disabled = state;
$('btnGetMAC').disabled = state;
$('btnSetMAC').disabled = state;
$('btnGetName').disabled = state;
$('btnSetName').disabled = state;
$('btnRstName').disabled = state;
}
function onDisconnected() {
isConnected = false;
resetVariables();
showState(`${i18n.getTag('DEVICE_DISABLED')}.`);
$('btnConnect').disabled = false;
$('btnReconnect').disabled = false;
// $('tabConfig').style.display = "none";
disableControls(true);
}
function startDFU() {
if(otaCharacteristic != null && ota.ind.version == 1 && (devSrv.services & SERVICE_OTA) == SERVICE_OTA) {
addLog(`${i18n.getTag('START_OTA')}...`);
updateBegin();
} else {
addLog(`${i18n.getTag('SWITCH_TO')}...`);
if(cmdCharacteristic != null) {
cmdCharacteristic.writeValue(new Uint8Array([0x72,0x55])).then(_ => {
console.log('Reboot command sent to bootloader');
reconnect();
}).catch(error => { addLog(error); });
}
}
}
function addLog(logTXT) {
console.log(logTXT)
var time = new Date().toLocaleTimeString();
var logString = time + ": " + logTXT;
$("log").innerHTML += logString + "<br>";
}
function showState(text) {
let s = `${i18n.getTag('STATE')}: ${text}`;
$("lblStatus").className = "shadowbox";
$("lblStatus").innerHTML = s;
addLog(text);
}
function showError(text) {
let s = `${i18n.getTag('ERROR')}: ${text}`;
$("lblStatus").className = "shadowerror";
$("lblStatus").innerHTML = s;
addLog(text);
}
function showProgress(text) {
$("lblStatus").className = "shadowprogress";
$("lblStatus").innerHTML = text;
}
function clearLog() {
$("log").innerHTML = "";
}
function updateFail(err) {
let s = "OTA: " + err;
showError(s);
}
function decimalToHex(d, padding) {
var hex = Number(d).toString(16);
while (hex.length < 4) {
hex = "0" + hex;
}
return hex;
}
function hexToBytes(hex) {
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return new Uint8Array(bytes);
}
function bytesToHex(data) {
return new Uint8Array(data).reduce(function(memo, i) {
return memo + ("0" + i.toString(16)).slice(-2);
}, "");
}
function makeRandomID(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return bytesToHex(new TextEncoder("utf-8").encode(result));
}
function hex(number, len) {
var str = (number.toString(16)).toUpperCase();
while (str.length < len) str = '0' + str;
return str;
}
function hexToBytes(hex) {
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return new Uint8Array(bytes);
}
function dump(ar, len) {
let s = '';
for(let i=0; i < len; i++) {
s += hex(ar[i],2);
}
return s;
}
function dump8(ar, len) {
let s = '';
for(let i=0; i < len; i++) {
s += hex(ar.getUint8(i),2);
}
return s;
}
function hex2ascii(hexx) {
var hex = hexx.toString();
var str = '';
for (var i = 0;
(i < hex.length && hex.substr(i, 2) !== '00'); i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}
function crc16_modbus(buffer) {
var crc = 0xFFFF;
var odd;
for (var i = 0; i < buffer.length; i++) {
crc = crc ^ buffer[i];
for (var j = 0; j < 8; j++) {
odd = crc & 0x0001;
crc = crc >> 1;
if (odd) crc = crc ^ 0xA001;
}
}
return crc;
};
function getHexCRC(data) {
var tempCRC = decimalToHex(crc16_modbus(hexToBytes(data)));
return tempCRC.substring(2, 4) + tempCRC.substring(0, 2);
}
var crc32 = (function() {
let table = new Uint32Array(256);
for(var i=256; i--;) {
let tmp = i;
for(let k=8; k--;) {
tmp = tmp & 1 ? 0xEDB88320 ^ tmp >>> 1 : tmp >>> 1;
}
table[i] = tmp;
}
return function( data ) {
let crc = -1;
let l = data.length;
for(let i=0; i<l; i++) {
crc = crc >>> 8 ^ table[ crc & 255 ^ data[i] ];
}
return (crc >>> 0);
};
})();
function testFwOTA(data) {
ota.fwsize = 0;
let fsize = data.byteLength;
console.log("File size = 0x"+ fsize.toString(16));
if (fsize < 20)
return `${i18n.getTag('IMPROPER_FIRMWARE_SIZE')} PHY6 OTA!`;
if(fsize > OTA_MAX_SIZE)
return `${i18n.getTag('FIRMWARE_TOO_BIG').replace('%s', (OTA_MAX_SIZE/1024).toFixed(1))}!`;
if(fsize != (fsize & 0x1ffff0) + 4)
return `${i18n.getTag('IMPROPER_FIRMWARE')} PHY6 OTA!`;
ota.fwsize = fsize;
let head = new DataView(data, 0, 16);
ota.h = {};
ota.h.id = head.getUint32(0, true);
ota.h.segs = head.getUint32(4, true);
ota.h.start = head.getUint32(8, true);
ota.h.size = head.getUint32(12, true);
if(ota.h.id != 0x36594850) { // "PHY6"
ota.ext_flg = true;
ota.h.size = fsize - 4;
ota.h.start = ota.program_offset;
addLog(`${i18n.getTag('FILE')} id:${hex(ota.h.id, 4)} , ${i18n.getTag('SPECIAL_FIRMWARE')}.`);
return "Расширенный формат OTA пока не поддерживается!";
} else {
ota.ext_flg = false;
addLog(`${i18n.getTag('FILE')} id:PHY6, ${i18n.getTag('SEGMENTS')}: ${ota.h.segs}, ${i18n.getTag('START')}: 0x"${hex(ota.h.start, 8)}, ${i18n.getTag('Size')}: ${ota.h.size}`);
if(ota.h.segs > 16)
return `${i18n.getTag('WRONG_NUMOF_SEGMENTS')} PHY6 OTA!`;
if(ota.h.size + 4 != ota.fwsize)
return `${i18n.getTag('WRONG_HEADER_SIZE')} PHY6 OTA!`;
}
let crc = crc32(new Uint8Array(data.slice(0, ota.h.size)));
let x = new DataView(data, ota.h.size, 4);
ota.fcrc = x.getUint32(0, true);
console.log(`${i18n.getTag('FILE')} CRC = 0x${ota.fcrc.toString(16)}, ${i18n.getTag('CALCULATED')} CRC = 0x${crc.toString(16)}`);
if(ota.fcrc != crc) {
return `${i18n.getTag('FILE_CRC_ERROR')} OTA!`;
}
return "OK";
}
function getFwArray(data, filename) {
addLog(`${i18n.getTag('FILE')}: ${filename}`);
let s = testFwOTA(data);
if(s != "OK") {
$('btnStartDFU').disabled = true;
addLog(s);
ota.blockCount = 0;
ota.fwArray = null;
fwname = "";
alert(s);
showError(`OTA ${i18n.getTag('FILE')}: ${filename} ${i18n.getTag('NOT_UPLOADED')}`);
$('lblFile').innerHTML = i18n.getTag('NO_FILE');
return;
}
ota.fwArray = bytesToHex(data);
addLog(`${i18n.getTag('FILESIZE')}: ${(ota.fwArray.length/2).toString(10)} ${i18n.getTag('BYTES')}`);
if (ota.fwArray.length % 32 !== 0) { // pad last block to 16bytes
var padHex = "ffffffffffffffffffffffffffffffff";
ota.fwArray += padHex.substr(0, 32 - ota.fwArray.length % 32);
}
ota.blockCount = ota.fwArray.length / 32;
addLog(`${i18n.getTag('COUNTER')}: ${ota.blockCount} ${i18n.getTag('BLOCKS')}`);
ota.fwname = filename;
showProgress(`OTA ${i18n.getTag('FILE')}: ${filename}`);
if(isConnected)
$('btnStartDFU').disabled = false;
}
var otaErrStrs = [
'OK',
i18n.getTag('WRONG_COMMAND'),
i18n.getTag('START_NOT_SET'),
i18n.getTag('PARAMS_NOT_SET'),
i18n.getTag('WRONG_PARAMS'),
i18n.getTag('WRONG_PACKET_SIZE'),
i18n.getTag('PACKAGE_CRC_ERROR'),
i18n.getTag('PACKAGE_LOSS'),
i18n.getTag('FLASH_WRITE_ERROR'),
i18n.getTag('PACKAGE_SIZE_ERROR'),
i18n.getTag('IDENTIFIER_ERROR'),
i18n.getTag('PROGRAM_CRC_ERROR')
];
function get_msg_ota_err(err) {
if(err == 0)
return "OK";
if(err == 255)
return "OTA end";
if(err <= 11)
return otaErrStrs[err];
return i18n.getTag('UNKNOWN_ERROR');
}
function parseBlkOTA(value) {
if(value.byteLength < 20) return;
ota.ind = {};
ota.ind.err_flag = value.getUint8(0);
ota.ind.version = value.getUint8(1);
ota.ind.start_flag = value.getUint8(2);
ota.ind.debug_flag = value.getUint8(3);
ota.ind.prg_offset = value.getUint32(4,true);
ota.ind.pkt_index = value.getUint16(8,true);
ota.ind.pkt_total = value.getUint16(10,true);
ota.ind.fw_value = value.getUint32(12,true);
ota.ind.crc32 = value.getUint32(16,true);
//console.log('otablk: '+dump8(value, value.byteLength));
console.log('OTA read: ver: ' + hex(ota.ind.version,2)
+ ', err: ' + ota.ind.err_flag + ' - ' + get_msg_ota_err(ota.ind.err_flag)
+ ', dbg: ' + ota.ind.debug_flag
+ ', start: '+ota.ind.start_flag
+ ', offs: 0x'+hex(ota.ind.prg_offset,8)
+ ', idx: 0x'+hex(ota.ind.pkt_index,4)
+ ', total: 0x'+hex(ota.ind.pkt_total,4)
+ ', crc: 0x'+hex(ota.ind.crc32,8));
}
function updateBegin() {
if (ota.blockCount <= 0) {
showError(`${i18n.getTag('NO_FILE_ERROR')}!`);
return;
}
setTimeout(function() {
sendCharOTA("00ff").then(_ => { otaCharacteristic.readValue().then(value => {
let cmd = "01ff";
// TODO
// if(ota.ext_flg) {
// cmd += ota.fwArray.substring(16,24); // program_offset
// cmd += ota.fwArray.substring(0,8); // fw_id
// cmd += hex((ota.blockCount >> 8) | ((ota.blockCount & 0xff) << 8),4); // pkt_total
// }
sendCharOTA(cmd).then(_ => { otaCharacteristic.readValue().then(value => {
if(value.byteLength >= 2 && value.getUint8(0) == 0) {
setTimeout(function() {
startTime = new Date().getTime();
sendBlkOTA(0);
}, 50);
} else
showError("Error "+value.getUint8(0)+" OTA!");
})//.catch(function(err) {updateFail(err); });
})//.catch(function(err) {updateFail(err); });
})//.catch(function(err) {updateFail(err); });
}).catch(function(err) {updateFail(err); });
}, 50);
}
function sendLastOTA() {
otaCharacteristic.readValue().then(value => {
if(value.byteLength >= 1 && value.getUint8(0) == 0xff) {
return sendCharOTA("02ff").then(_ => {
let s = `${i18n.getTag('FLASH_FINISHED').replace('%s', (new Date().getTime() - startTime) / 1000)}`;
showProgress(s);
addLog(s);
}).catch(function(err) {
updateFail(`${i18n.getTag('RELOAD_COMMAND_FAILED')} OTA`);
});
} else
showError(`${i18n.getTag('ERROR')} (${value.getUint8(0)}) ${i18n.getTag('ON_BLOCK')} ${blockNr} OTA: ${s}`);
}).catch(function(err) { updateFail(err); });
}
function sendBlkOTA(blockNr) {
if (blockNr >= ota.blockCount) {
return sendLastOTA();
}
showProgress(`${i18n.getTag('BLOCK_TRANSFERRED')} ${blockNr} ${i18n.getTag('FROMTO_FROM')} ${ota.blockCount}, ${Math.floor(blockNr / (ota.blockCount * 1.0) * 100)}% ${i18n.getTag('SUCCEEDED')}, ${i18n.getTag('TOTAL_TIME')} ${(new Date().getTime() - startTime) / 1000.0} ${i18n.getTag('SECONDS')}`);
var blockNrString = getHexBLockCount(blockNr);
var blockString = blockNrString + ota.fwArray.substring(blockNr * 32, blockNr * 32 + 32);
var blockCRC = getHexCRC(blockString);
sendCharOTA(blockString + blockCRC).then(_ => {
if (blockNr >= ota.blockCount - 1) {
return sendLastOTA();
}
setTimeout(function() {
if ((blockNr + 1) % 16 == 0) {
otaCharacteristic.readValue().then(value => {
if(value.byteLength >= 20 && value.getUint8(0) == 0)
sendBlkOTA(blockNr + 1);
else {
let s = get_msg_ota_err(value.getUint8(0));
if(s != "OK")
showError(`${i18n.getTag('ERROR')} (${value.getUint8(0)}) ${i18n.getTag('ON_BLOCK')} ${blockNr} OTA: ${s}`);
}
}).catch(function(err) { updateFail(err); });
} else
sendBlkOTA(blockNr + 1);
}, 0);
}).catch(function(err) {
updateFail(err);
});
}
function getHexBLockCount(count) {
var tempHEX = decimalToHex(count);
return tempHEX.substring(2, 4) + tempHEX.substring(0, 2);
}
var sendCharOTA = function(data) {
return new Promise(function(resolve, reject) {
//console.log("OTA send: " + data);
otaCharacteristic.writeValue(hexToBytes(data)).then(function(character) {
resolve("OK");
}).catch(function(err) {
reject(i18n.getTag('ERROR_SENDING_DATA'));
});
});
}
var sendCharMain = function(data, characteristic) {
return new Promise(function(resolve, reject) {
console.log("Send: " + data);
characteristic.writeValue(hexToBytes(data)).then(function(character) {
resolve("OK");
}).catch(function(err) {
reject(i18n.getTag('ERROR_SENDING_DATA'));
});
});
}
function readAddr(addr) {
if (cmdCharacteristic) {
let blk = new Uint8Array([0xdb, addr&0xff, (addr>>8)&0xff, (addr>>16)&0xff, (addr>>24)&0xff]);
cmdCharacteristic.writeValue(blk).then(_ => {
startTime = new Date().getTime();
showState(`${i18n.getTag('READING_BYTES').replace('%s','16')} 0x${hex(addr,8)}`);
});
}
}
function writeAddr(addr, data) {
if (cmdCharacteristic) {
len = data.length;
if(len != 0 && len <= 16) {
let blk = new Uint8Array(len + 5);
blk.set([0xdb, addr&0xff, (addr>>8)&0xff, (addr>>16)&0xff, (addr>>24)&0xff]);
blk.set(data, 5);
console.log(blk);
cmdCharacteristic.writeValue(blk);
showState(`${i18n.getTag('WRITING_BYTES').replace('%s','16')} 0x${hex(addr,8)}`);
} else {
console.log(data);
showError(`${i18n.getTag('ERROR')}: ${i18n.getTag('BLOCK_LENGTH_RANGE')}!`);
}
}
}
function writeCmd(data) {
if(cmdCharacteristic) {
len = data.length;
if((len > 0) && (len <= 40)) { // TODO: MTU
let blk = new Uint8Array(data);
cmdCharacteristic.writeValue(blk);
} else
showError(`${i18n.getTag('ERROR')}: ${i18n.getTag('COMMAND_LENGTH_RANGE')}!`);
}
}
function readAddress() {
if(cmdCharacteristic) {
let faddr = parseInt($('inpAddr').value, 16);
readAddr(faddr);
}
}
function writeAddress() {
let addr = parseInt($('inpAddr').value, 16);
let data = hexToBytes($('inpData').value);
if(data.length != 0 && data.length <= 16)
writeAddr(addr, data);
else
console.log(`${i18n.getTag('ERROR')}: ${i18n.getTag('BLOCK_LENGTH_RANGE')}!`);
}
function sendCommand() {
let data = hexToBytes($('inpCmdData').value);
if(data.length != 0 && data.length <= 40) // TODO:MTU
writeCmd(data);
else
console.log(`${i18n.getTag('ERROR')}: ${i18n.getTag('COMMAND_LENGTH_RANGE')}!`);
}
function showConfig() {
$('chkCfgNotify').checked = (devCfg.flg & 1) != 0;
$('chkCfgClock').checked = (devCfg.flg & 2) != 0;
$('chkCfgSmiley').checked = (devCfg.flg & 4) != 0;
$('chkCfgTrg').checked = (devCfg.flg & 8) != 0;
$('chkCfgLcdOff').checked = (devCfg.flg & 16) != 0;
$('chkCfgBindKey').checked = (devCfg.flg & 32) != 0;
$('chkCfgFahrenheit').checked = (devCfg.flg & 64) != 0;
$('chkCfgFindMy').checked = (devCfg.flg & 128) != 0;
let txPwr = 31;
el = $('selTxPwr');
for(let n = 0; n < el.options.length; n++) if(el.options[n].value >= devCfg.tx_power) txPwr = el.options[n].value;
el.value = txPwr;
$('inpLat').value = (devCfg.connect_latency + 1)*30; // = (connect_latency + 1)*30 ms
let advi = devCfg.advertising_interval*62.5;
$('inpAdvInt').value = advi.toFixed(1); // интервала рекламы в ms
$('inpMeasInt').value = devCfg.measure_interval; // опрос датчика в ms, value минимум = 2 (интервала рекламы)
let msri = advi*devCfg.measure_interval;
$('lblMeasInt').innerHTML = "= " + msri.toFixed(1) + ` ${i18n.getTag('MS')}`;
$('inpAverInt').value = devCfg.averaging_measurements; // запись истории: при 0 - отключена, 1...255 * шаг опроса датчика = интерал записи истории
if(devCfg.averaging_measurements == 0)
$('lblAverInt').innerHTML = ` ${i18n.getTag('MEMO_OFF')}`;
else {
let hsti = (msri*devCfg.averaging_measurements)/1000.0;
if(hsti > 60) {
hsti /= 60.0;
$('lblAverInt').innerHTML = "= " + hsti.toFixed(1) + ` ${i18n.getTag('MINUTES')}`;
} else
$('lblAverInt').innerHTML = "= " + hsti.toFixed(1) + ` ${i18n.getTag('SECONDS')}`;
}
$('inpBatInt').value = devCfg.batt_interval; // в секундах, минимум 2 секунды, но кратно интервалу рекламы
$('inpEvAdvCnt').value = devCfg.event_adv_count;
}
function parseBlkCustom(value) {
let len = value.byteLength;
if(len == 0) return;
let blkId = value.getUint8(0);
if((blkId == 0x00) && (len >= 12)) {
// CMD_ID_DEVID Get dev id, version, services
devSrv.revision = value.getUint8(1);
devSrv.hw_version = value.getUint16(2, true);
if(devSrv.hw_version >= 19 && devSrv.hw_version < 128) {
hwver_id = devSrv.hw_version - 19;
console.log("Set hwver_id: " + hwver_id);
menuOtaUpgrade();
}
devSrv.sw_version = value.getUint16(4, true);
devSrv.dev_spec_data = value.getUint16(6, true);
devSrv.services = value.getUint32(8, true);
auxControls(false);
addLog("Device info # hw: " + hex(devSrv.hw_version,4)
+ ", sw: " + hex(devSrv.sw_version,4)
+ ", services: " + hex(devSrv.services,8)
+ ", sd: " + hex(devSrv.dev_spec_data, 4));
} else if(blkId == 0x35) {
if(isMemoActive) {
if(len >= 12) {
let cnt = value.getUint16(1, true);
let tc = value.getUint32(3, true);
let tm = value.getInt16(7, true) / 100.0;
let hm = value.getUint16(9, true) / 100.0;
let vb = value.getUint16(11, true);
let dt = new Date(tc*1000);
addLog(`${((dt.toISOString().slice(0, -1)).replace('T',' ')).replace('.000','')} # ${i18n.getTag('BATTERY')}: ${vb} ${i18n.getTag('MILLIVOLT')} , ${i18n.getTag('TEMPERATURE')}: ${tm}°C, ${i18n.getTag('HUMIDITY')}: ${hm}%, ${i18n.getTag('COUNTER')}: ${cnt}`);
memoCount = cnt;
} else if(len == 3) {
let flg = value.getUint16(1, true);
console.log('Memo End: '+flg);
if(memoCount == 0)
addLog(`${i18n.getTag('MEMO_EMPTY')}!`);
isMemoActive = false;
} else if(len == 2) {
addLog(`${i18n.getTag('NO_MEMO_SERVICE')}!`);
isMemoActive = false;
} else {
console.log('blk: ' + dump8(value, value.byteLength));
isMemoActive = false;
}
}
} else if(blkId == 0x33 && len >= 10) {
let count = value.getUint16(1, true);
let temp = value.getInt16(3, true) / 100.0;
let humi = value.getInt16(5, true) / 100.0;
let vbat = value.getUint16(7, true);
let pbat = value.getUint8(9);
let flg = 0;
let rds_count = 0;
let delta = 0;
let s = `${i18n.getTag('TEMPERATURE')}: ${temp.toFixed(2)} °C,
${i18n.getTag('HUMIDITY')}: ${humi.toFixed(2)}%,
${i18n.getTag('BATTERY')}: ${vbat} ${i18n.getTag('MILLIVOLT')},
ID: ${count}
`;
$('lblTemp').innerHTML = temp + ' °C';
$('lblHumi').innerHTML = humi + ' %RH';
$('lblBat').innerHTML = pbat + ' % (' + vbat / 1000 + ' V)';
let so = "";
if(len > 10) {
flg = value.getUint8(10) + ", " + i18n.getTag('FLAGS')
s += ": 0x" + hex(flg,2);
so = "In: " + (flg&1)
+ ", Out: " + ((flg&2)? 1:0)
+ ", Cmf: " + ((flg&4)? 1:0)
+ ", Te: " + ((flg&16)? 1:0)
+ ", He: " + ((flg&32)? 1:0);
if(len > 14) {
devTime.cur = value.getUint32(11,true);
//console.log('Device Time: 0x' + hex(devtime.cur, 8));
let dt = new Date(devTime.cur * 1000);
let sDateTime = (dt.toISOString().slice(0, -5)).replace('T',' ');
$('lblTime').innerHTML = sDateTime;
let time = Date.now() / 1000 - (new Date()).getTimezoneOffset() * 60;
delta = devTime.cur - time;
console.log(`${i18n.getTag('TIME_ON_DEVICE')}: ${sDateTime}, ${i18n.getTag('DIFFERENCE')}: ${Math.round(delta)} ${i18n.getTag('SECONDS')}`);
$('lbDeltaTime').innerHTML = `${i18n.getTag('DIFFERENCE')}: ${Math.round(delta)} ${i18n.getTag('SECONDS')}`;
if(len > 18) {
rds_count = value.getUint32(15,true);
s += ", rds: " + rds_count;
so += ", rds: " + rds_count;
}
}
}
$('lblTrg').innerHTML = so;
console.log(s);
addChartData(temp, humi);
if(isChartEnabled)
chart.updateOptions(
{
file: chartData,
axes: {
y: { 'valueRange': rangeT },
y2: { 'valueRange': rangeH }
}
}
);
//if(len < 15) getDevTime();
if(delta > 86400 || delta < -86400) {
addLog(`${i18n.getTag('SET_DEVICETIME')}...`);
setDevTime();
}
} else if((blkId == 0x25 || blkId == 0x26) && (len > 12)) {
// CMD_ID_CFS Get/Set sensor config
devSens.temp_k = value.getUint32(1, true);
devSens.humi_k = value.getUint32(5, true);
devSens.temp_z = value.getInt16(9, true);
devSens.humi_z = value.getInt16(11, true);
$('inpTempK').value = devSens.temp_k;
$('inpHumK').value = devSens.humi_k;
$('inpTempZ').value = devSens.temp_z;
$('inpHumZ').value = devSens.humi_z;
addLog("Device Sensor "
+ "# Kt: " + devSens.temp_k
+ ", Kh: " + devSens.humi_k
+ ", Zt: " + devSens.temp_z
+ ", Zh: " + devSens.humi_z);
if (len > 17) {
devSens.mid = value.getUint16(13, false);
devSens.vid = value.getUint16(15, false);
devSens.i2c_addr = value.getUint8(17);
s = "???";
if(devSens.mid == 0x5959)
s = "CHT"+hex(devSens.vid,4);
else if(devSens.mid == 0 && devSens.vid == 0xaaaa)
s = "AHT20";
$('lblSensor').innerHTML = `${s}, I2C ${i18n.getTag('ADDRESS')}: 0x${hex(devSens.i2c_addr,2)}`;
addLog("Device sensor # id: "+hex(devSens.mid,4)+"-"+hex(devSens.vid,4)+", i2c_addr: 0x"+hex(devSens.i2c_addr,2));
}
} else if((blkId == 0x55 || blkId == 0x56) && (len > 12)) {
// CMD_ID_CFG Get/Set device config
devCfg.flg = value.getUint32(1, true);
// bit0 - measure notify enable
// bit1 - lcd chow time enable
devCfg.tx_power = value.getUint8(5);
devCfg.advertising_interval = value.getUint8(6);
devCfg.connect_latency = value.getUint8(7);
devCfg.event_adv_count = value.getUint8(8);
devCfg.measure_interval = value.getUint8(9);
devCfg.batt_interval = value.getUint8(10);
devCfg.averaging_measurements = value.getUint8(11);
devCfg.reserved2 = value.getUint8(12);
showConfig();
console.log("Dev config # flg: " + hex(devCfg.flg,8)
+ ", tx: " + devCfg.tx_power
+ ", adi: " + devCfg.advertising_interval
+ ", cli: " + devCfg.connect_latency
+ ", eac: " + devCfg.event_adv_count
+" , msi: " + devCfg.measure_interval
+ ", bti: " + devCfg.batt_interval
+ ", avi: " + devCfg.averaging_measurements);
addLog(`${i18n.getTag('CONFIG_DATA')}: ${bytesToHex(value.buffer)}`);
} else if((blkId == 0xdb) && (len > 4)) {
// CMD_ID_MEM_RW Read/Write memory
len -= 4;
let addr = value.getUint32(1,true);
let s = bytesToHex(value.buffer.slice(5), len);
$('inpData').value = s;
addLog(`${i18n.getTag('DATA_AT_ADDRESS')} 0x${hex(addr,8)}: ${s}`);
} else if((blkId == 0xda) && (len > 8)) {
let addr = value.getUint32(1,true);
let reg_data = value.getUint32(5,true);
addLog(`${i18n.getTag('REGISTER_AT_ADDRESS')} 0x${hex(addr,8)} = 0x${hex(reg_data,8)}`);
} else if((blkId == 0x07) && (len > 1)) {
// CMD_ID_SERIAL Get serial string
let s = new TextDecoder("utf-8").decode(value.buffer.slice(1));
addLog(`${i18n.getTag('SERIALNUM')}: ${s}`)
} else if((blkId == 0x06) && (len > 3)) {
// CMD_ID_FLASH_ID Get Flash JEDEC ID
addLog("Flash id: " + bytesToHex(value.buffer.slice(1,4)));
} else if(blkId == 0x60 && len >= 6) {
s = 'LCD data # '+bytesToHex(value.buffer.slice(1));
addLog(s);
} else if(blkId == 0x18 && len >= 1) { // Get/set beacon bkey in EEP
if(len > 16) {
devKeys.cbindkey = value.buffer.slice(1,17);
let s = bytesToHex(devKeys.cbindkey,16);
addLog("Bindkey # "+ s);
$("inpBindKey").value = s;
} else {
addLog(`${i18n.getTag('READ_ERROR')} Bindkey!`);
console.log('blk: ' + dump8(value, value.byteLength));
$("inpBindKey").value = i18n.getTag('NOT_SUPPORTED');
}
} else if(blkId == 0x19 && len >= 1) { // Get/set findmy bkey in EEP
if(len > 22) {
devKeys.cfindmykey = value.buffer.slice(1,23);
let s = bytesToHex(devKeys.cfindmykey,22);
addLog("FindMy key # "+ s);
$("inpFindMyKey").value = s;
} else {
addLog(`${i18n.getTag('READ_ERROR')} FindMy key!`);
console.log('blk: ' + dump8(value, value.byteLength));
$("inpFindMyKey").value = "none";
}
} else if(blkId == 0x23 && len >= 4) {
devTime.cur = value.getUint32(1,true);
console.log('Device Time: 0x' + hex(devTime.cur, 8));
let dt = new Date(devTime.cur * 1000);
let sDateTime = (dt.toISOString().slice(0, -5)).replace('T',' ');
$('lblTime').innerHTML = sDateTime
let time = Date.now() / 1000 - (new Date()).getTimezoneOffset() * 60;
let delta = devTime.cur - time;
console.log(`${i18n.getTag('TIME_ON_DEVICE')}: ${sDateTime}, ${i18n.getTag('DIFFERENCE')}: ${Math.round(delta)} ${i18n.getTag('SECONDS')}`);
$('lbDeltaTime').innerHTML = `${i18n.getTag('DIFFERENCE')}: ${Math.round(delta)} ${i18n.getTag('SECONDS')}`;
if(len >= 8) {
devTime.set = value.getUint32(5,true);
console.log(`${i18n.getTag('LAST_TIME_SETTING')}: 0x${hex(devTime.set,8)}`);
if(devTime.step == 1) {
if(devTime.set > 0x60000000) {
devTime.period = devTime.cur - devTime.set;
devTime.cmp = time;
let odt = new Date(devTime.set * 1000);
addLog(`${i18n.getTag('LAST_TIME_SETTING')}: ${(odt.toISOString().slice(0, -5)).replace('T',' ')}`);
console.log(`${i18n.getTag('PASSED_ON_DEVICE')}: ${devTime.period.toFixed(1)} ${i18n.getTag('SECONDS')}`);
let rp = devTime.cmp - devTime.set;
let delta = rp - devTime.period;
console.log('Прошло реально: ' + rp.toFixed(1) + ' секунд, разница: ' + delta.toFixed(1) + ' секунд');
if(rp >= 10800) { // 10800
devTime.step = 2;
console.log("Send cmd Get StepTimeSec...");
settingsCharacteristics.writeValue(new Uint8Array([0x24])).then(_ => {
console.log('Get StepTimeSec...');
});
} else {
devTime.step = 0;
addLog(`${i18n.getTag('MIN_TIME_CALC')}`);
}
} else {
devTime.step = 0;
addLog(`${i18n.getTag('CLOCK_ADVANCE_ERR')}`);
}
}
}
} else if((blkId == 0x44) && (len > 8)) {
if(len != 9) {
devTrig.temp_min = value.getInt16(1, true);
devTrig.temp_max = value.getInt16(3, true);
devTrig.humi_min = value.getInt16(5, true);
devTrig.humi_max = value.getInt16(7, true);
if ( devSrv.services & SERVICE_SCREEN ) {
$("inpTempMin").value = (devTrig.temp_min/100.0).toFixed(2);
$("inpTempMax").value = (devTrig.temp_max/100.0).toFixed(2);
$("inpHumiMin").value = (devTrig.humi_min/100.0).toFixed(2);
$("inpHumiMax").value = (devTrig.humi_max/100.0).toFixed(2);
}
}
let x = 0;
if(len == 10) x = 1;
else if(len >= 18) x = 9;
if(x > 0) {
devTrig.temp_threshold = value.getInt16(x, true);
devTrig.humi_threshold = value.getInt16(x+2, true);
devTrig.temp_hysteresis = value.getInt16(x+4, true);
devTrig.humi_hysteresis = value.getInt16(x+6, true);
devTrig.flg = value.getUint8(x+8);
if( devSrv.services & SERVICE_TH_TRG ) { //
$("chkInvOut").checked = (devTrig.flg & 1) != 0;
$("inpTempThr").value = (devTrig.temp_threshold/100.0).toFixed(2);
$("inpHumiThr").value = (devTrig.humi_threshold/100.0).toFixed(2);
$("inpTempHsr").value = (devTrig.temp_hysteresis/100.0).toFixed(2);
$("inpHumiHsr").value = (devTrig.humi_hysteresis/100.0).toFixed(2);
}
}
addLog(`${i18n.getTag('TRIGGER_DATA')}: ${bytesToHex(value.buffer)}`);
} else if(blkId == 0x20 && len >= 8) {
devcmf.tmp_lo = value.getInt16(1, true); // temp lo
devcmf.tmp_hi = value.getInt16(3, true); // temp hi
devcmf.hm_lo = value.getUint16(5, true); // humi lo
devcmf.hm_hi = value.getUint16(7, true); // humi lo
let s = i18n.getTag('COMFORT_TEMPERATURE') + (devcmf.tmp_lo/100.0).toFixed(2) + '..' + (devcmf.tmp_hi/100.0).toFixed(2) + '°C'
+ `, ${i18n.getTag('HUMIDITY')}: ` + (devcmf.hm_lo/100.0).toFixed(2) + '..' + (devcmf.hm_hi/100.0).toFixed(2) + '%';
addLog(s); // UpdCmf();
} else if(blkId == 0x01 && len >= 1) {
devName = new TextDecoder("utf-8").decode(value.buffer.slice(1));
$("inpDevName").value = devName;
addLog(`${i18n.getTag('DEVICENAME')}: ${devName}`);
} else if(blkId == 0x10 && len > 6) {
let mac = new Uint8Array(6);
mac[0] = value.getUint8(6);
mac[1] = value.getUint8(5);
mac[2] = value.getUint8(4);
mac[3] = value.getUint8(3);
mac[4] = value.getUint8(2);
mac[5] = value.getUint8(1);
let mac_txt = bytesToHex(mac);
$("inpDevMAC").value = mac_txt;
addLog(`${i18n.getTag('DEVICE_MAC')}: ${mac_txt}`);
} else if(blkId == 0x71 && len >= 1) {
devInfo.mtu = value.getUint8(1);
if(devInfo.mtu == 255 || devInfo.mtu == 0)
addLog('Error set MTU size!');
else
addLog('MTU size: ' + devInfo.mtu);
} else {
console.log('blk: ' + dump8(value, value.byteLength));
addLog(`${i18n.getTag('COMMAND_RESPONSE')} (${hex(blkId,2)}): ${bytesToHex(value.buffer.slice(1))}`);
}
}
function getMemo(num) {
if(cmdCharacteristic != null) {
//addLog("getSensCfg...");
isMemoActive = true;
memoCount = 0;
cmdCharacteristic.writeValue(new Uint8Array([0x35, num&0xff, (num>>8)&0xff])).catch(error => { addLog("getMemo() Error: " + error); });
}
}
function getDevCfg() {
if(cmdCharacteristic != null) {
//addLog("getDevCfg...");
cmdCharacteristic.writeValue(new Uint8Array([0x55])).catch(error => { addLog("getDevCfg() Error: " + error) });
}
}
function getSensCfg() {
if(cmdCharacteristic != null) {
//addLog("getSensCfg...");
cmdCharacteristic.writeValue(new Uint8Array([0x25])).catch(error => { addLog("getSensCfg() Error: " + error); });
}
}
function getDevTime() {
if(cmdCharacteristic != null) {
// addLog("Получить время от устройства...");
cmdCharacteristic.writeValue(new Uint8Array([0x23])).then(_ => { console.log('Send GetDevTime ok'); })
.catch(error => { addLog("getDevTime() Error: " + error); });
}
}
function getDevMAC() {
if(cmdCharacteristic != null) {
cmdCharacteristic.writeValue(new Uint8Array([0x10])).catch(error => { addLog("getMAC() Error: " + error); });
}
}
function getTrgCfg() {
if(cmdCharacteristic != null) {
cmdCharacteristic.writeValue(new Uint8Array([0x44])).catch(error => { addLog("getTrgCfg() Error: " + error); });
}
}
function getDevName() {
if(cmdCharacteristic != null) {
cmdCharacteristic.writeValue(new Uint8Array([0x01])).catch(error => { addLog("getDevName() Error: " + error); });
}
}
function chkDevCfg() {
if(devCfg.flg == null) return;
devCfg.flg &= 0xffffff00;
devCfg.flg |= ($('chkCfgNotify').checked) ? 1 : 0;
devCfg.flg |= ($('chkCfgClock').checked) ? 2 : 0;
devCfg.flg |= ($('chkCfgSmiley').checked) ? 4 : 0;
devCfg.flg |= ($('chkCfgTrg').checked) ? 8 : 0;
devCfg.flg |= ($('chkCfgLcdOff').checked) ? 16 : 0;
devCfg.flg |= ($('chkCfgBindKey').checked) ? 32 : 0;
devCfg.flg |= ($('chkCfgFahrenheit').checked) ? 64 : 0;
devCfg.flg |= ($('chkCfgFindMy').checked) ? 128 : 0;
devCfg.tx_power = $('selTxPwr').value & 0x3f; // 0..0x1f -> -20..+5 dBm ? нелинейное 0x1f = +0 дБм
let connect_latency = parseInt($('inpLat').value); // = (connect_latency + 1)*30 ms
if (connect_latency < 0) {
connect_latency = 0;
} else if (connect_latency <= 7680) {
connect_latency = (connect_latency/30) - 1;
} else
connect_latency = 255;
devCfg.connect_latency = connect_latency & 0xff;
let advertising_interval = parseFloat($("inpAdvInt").value);
if(advertising_interval <= 62.5)
advertising_interval = 1;
else if(advertising_interval >= 15937.5)
advertising_interval = 255;
else
advertising_interval = advertising_interval / 62.5;
devCfg.advertising_interval = Math.round(advertising_interval) & 0xff;
devCfg.measure_interval = parseInt($('inpMeasInt').value);
if(devCfg.measure_interval < 2) // опрос датчика в интервалах рекламы, value минимум = 2 (интервала рекламы)
devCfg.measure_interval = 2;
else if(devCfg.measure_interval > 255)
devCfg.measure_interval = 255
devCfg.averaging_measurements = parseInt($('inpAverInt').value);
if(devCfg.averaging_measurements < 0) // запись истории: при 0 - отключена, 1...255 * шаг опроса датчика = интерал записи истории
devCfg.averaging_measurements = 0;
if(devCfg.averaging_measurements > 255)
devCfg.averaging_measurements = 255;
devCfg.event_adv_count = parseInt($('inpEvAdvCnt').value);
if(devCfg.event_adv_count < 6)
devCfg.event_adv_count = 6;
if(devCfg.event_adv_count > 255)
devCfg.event_adv_count = 255;
devCfg.batt_interval = parseInt($('inpBatInt').value);
if(devCfg.batt_interval < 2) // в секундах, минимум 2 секунды, но кратно интервалу рекламы
devCfg.batt_interval = 2;
if(devCfg.batt_interval > 255)
devCfg.batt_interval = 255;
showConfig();
}
function setDevCfg() {
if(cmdCharacteristic != null) {
chkDevCfg();
blk = new Uint8Array([0x55,
devCfg.flg & 0xff, (devCfg.flg>>8) & 0xff, (devCfg.flg>>16) & 0xff, (devCfg.flg>>24) & 0xff,
devCfg.tx_power,
devCfg.advertising_interval,
devCfg.connect_latency,
devCfg.event_adv_count,
devCfg.measure_interval,
devCfg.batt_interval,
devCfg.averaging_measurements,
devCfg.reserved2
]);
cmdCharacteristic.writeValue(blk).catch(error => { addLog("setDevCfg() Error: " + error);});
}
}
function setSensCfg() {
if(cmdCharacteristic != null) {
addLog("setSensCfg...");
devSens.temp_k = parseInt($('inpTempK').value);
devSens.humi_k = parseInt($('inpHumK').value);
devSens.temp_z = parseInt($('inpTempZ').value);
devSens.humi_z = parseInt($('inpHumZ').value);
blk = new Uint8Array([0x25,
devSens.temp_k & 0xff, (devSens.temp_k >> 8) & 0xff, (devSens.temp_k >> 16) & 0xff, (devSens.temp_k >> 24) & 0xff,
devSens.humi_k & 0xff, (devSens.humi_k >> 8) & 0xff, (devSens.humi_k >> 16) & 0xff, (devSens.humi_k >> 24) & 0xff,
devSens.temp_z & 0xff, (devSens.temp_z >> 8) & 0xff,
devSens.humi_z & 0xff, (devSens.humi_z >> 8) & 0xff
]);
cmdCharacteristic.writeValue(blk).catch(error => { addLog("setSensCfg() Error: " + error); });
}
}
function setDevTime() {
let time = Date.now()/1000;
time -= (new Date()).getTimezoneOffset() * 60;
blk = new Uint8Array(5);
blk[0] = 0x23;
blk[1] = time & 0xff;
blk[2] = (time >> 8) & 0xff;
blk[3] = (time >> 16) & 0xff;
blk[4] = (time >> 24) & 0xff;
addLog(`${i18n.getTag('SET_DEVICE_TIME')} (${dump(blk, blk.length)})...`);
cmdCharacteristic.writeValue(blk).then(_ => {
console.log(i18n.getTag('TIME_IS_SYNCED'));
}).catch(error => { addLog("setDevTime() Error: " + error); });
}
function setDevMAC() {
if(cmdCharacteristic != null) {
let el = $("inpDevMAC").value;
let len = el.length;
if(len == 12) {
let mac = hexToBytes(el);
len = mac.length;
if(len == 6 || len == 8) {
let blk = new Uint8Array(len+2);
blk[0] = 0x10;
blk[1] = mac[5];
blk[2] = mac[4];
blk[3] = mac[3];
blk[4] = mac[2];
blk[5] = mac[1];
blk[6] = mac[0];
if(len == 8) {
blk[7] = mac[7];
blk[8] = mac[6];
}
console.log("Send cmd New MAC ("+dump(blk, blk.length)+")...");
cmdCharacteristic.writeValue(blk).then(_ => {
s = `${i18n.getTag('SENDING_NEW_MAC')} ${dump(mac, 6)}`;
if(len == 8)
s += " RAND:" +dump(mac.slice(6), 2);
addLog(s+" ok");
});
return;
}
}
addLog(`${i18n.getTag('INVALID_MAC_LENGTH')}!`);
return;
}
}
function setTrgCfg() {
if(cmdCharacteristic != null) {
let len = 0;
if((devSrv.services & SERVICE_SCREEN) != 0) len = 8;
if((devSrv.services & SERVICE_TH_TRG) != 0) len += 9;
if(len > 0) {
let blk = new Uint8Array(len + 1);
blk[0] = 0x44;
let idx = 1;
if(len != 9) {
devTrig.temp_min = Math.round($("inpTempMin").value * 100);
devTrig.temp_max = Math.round($("inpTempMax").value * 100);
devTrig.humi_min = Math.round($("inpHumiMin").value * 100);
devTrig.humi_max = Math.round($("inpHumiMax").value * 100);
blk[1] = devTrig.temp_min & 0xff;
blk[2] = (devTrig.temp_min >> 8) & 0xff;
blk[3] = devTrig.temp_max & 0xff;
blk[4] = (devTrig.temp_max >> 8) & 0xff;
blk[5] = devTrig.humi_min & 0xff;
blk[6] = (devTrig.humi_min >> 8) & 0xff;
blk[7] = devTrig.humi_max & 0xff;
blk[8] = (devTrig.humi_max >> 8) & 0xff;
idx = 9;
}
if(len > 8) {
devTrig.temp_threshold = Math.round($("inpTempThr").value * 100);
devTrig.humi_threshold = Math.round($("inpHumiThr").value * 100);
devTrig.temp_hysteresis = Math.round($("inpTempHsr").value * 100);
devTrig.humi_hysteresis = Math.round($("inpHumiHsr").value * 100);
devTrig.flg = ($("chkInvOut").checked)? 1: 0;
blk[idx+0] = devTrig.temp_threshold & 0xff;
blk[idx+1] = (devTrig.temp_threshold >> 8) & 0xff;
blk[idx+2] = devTrig.humi_threshold & 0xff;
blk[idx+3] = (devTrig.humi_threshold >> 8) & 0xff;
blk[idx+4] = devTrig.temp_hysteresis & 0xff;
blk[idx+5] = (devTrig.temp_hysteresis >> 8) & 0xff;
blk[idx+6] = devTrig.humi_hysteresis & 0xff;
blk[idx+7] = (devTrig.humi_hysteresis >> 8) & 0xff;
blk[idx+8] = devTrig.flg & 0xff;
}
cmdCharacteristic.writeValue(blk).catch(error => { addLog("setTrgCfg() Error: " + error); });
}
}
}
function setDevName(flg) {
if(cmdCharacteristic != null) {
if(devSrv.sw_version < 0x11) {
addLog(`${i18n.getTag('DEPRECATED_FIRMWARE')}!`);
return;
}
if(flg) {
let eltxt = $("inpDevName").value;
let len = eltxt.length;
if(len > 0 && len < 20) {
let nm = new Uint8Array((new TextEncoder()).encode(eltxt));
len = nm.length;
if(len > 0 && len < 20) {
addLog(`${i18n.getTag('CORRECT_DEVICENAME_LENGTH')}`);
}
let blk = new Uint8Array(1 + len);
blk[0] = 0x01;
blk.set(nm, 1);
console.log(blk);
cmdCharacteristic.writeValue(blk).catch(error => { addLog("setDevName() Error: " + error); });
} else
addLog(`${i18n.getTag('INVALID_DEVICENAME_LENGTH')}`);
} else
cmdCharacteristic.writeValue(new Uint8Array([0x01, 0])).catch(error => { addLog("setDevName() Error: "+ error); });
}
}
function resetDevCfg() {
if(cmdCharacteristic != null) {
addLog("Restore connection default settings...");
cmdCharacteristic.writeValue(new Uint8Array([0x56])).catch(error => { addLog("resetDevCfg() Error: " + error); });
}
}
function resetSensCfg() {
if(cmdCharacteristic != null) {
addLog("Restore sensor default settings...");
cmdCharacteristic.writeValue(new Uint8Array([0x26])).catch(error => { addLog("resetSensCfg() Error: " + error); });
}
}
function getGetBindKey() {
if(cmdCharacteristic != null) {
//addLog("Get bindkey...");
cmdCharacteristic.writeValue(new Uint8Array([0x18])).catch(error => { addLog("getGetBindKey() Error: " + error); });
}
}
function setBindKey() {
if(cmdCharacteristic != null) {
let bk = $("inpBindKey").value;
if(bk.length == 32) {
let bkey = hexToBytes(bk);
if(bkey.length == 16) {
let blk = new Uint8Array(17);
blk.set(bkey,1);
blk[0] = 0x18;
//console.log("Send bindkey...");
addLog(`${i18n.getTag('WRITE')} BindKey: ${bytesToHex(blk.slice(1))}`);
cmdCharacteristic.writeValue(blk).catch(error => { addLog("setBindKey() Error: " + error); });
return;
}
}
addLog(`${i18n.getTag('INVALID_BINDKEY_LENGTH')}!`)
}
}
function getGetFindMyKey() {
if(cmdCharacteristic != null) {
cmdCharacteristic.writeValue(new Uint8Array([0x19])).catch(error => { addLog("getFindmyKey() Error: " + error); });
}
}
function setFindMyKey() {
if(cmdCharacteristic != null) {
let bk = $("inpFindMyKey").value;
if(bk.length == 44) {
let bkey = hexToBytes(bk);
if(bkey.length == 22) {
let blk = new Uint8Array(23);
blk.set(bkey,1);
blk[0] = 0x19;
addLog(`${i18n.getTag('WRITE')} FindMy: ${bytesToHex(blk.slice(1))}`);
cmdCharacteristic.writeValue(blk).catch(error => { addLog("setFindMyKey() Error: " + error); });
return;
}
}
addLog(`${i18n.getTag('INVALID_FINDMYKEY_LENGTH')}!`)
}
}
function setMaxMTU() {
if(cmdCharacteristic != null)
cmdCharacteristic.writeValue(new Uint8Array([0x71,240])).catch(error => { addLog("setMaxMTU() Error: " + error); });
}
function readFile(file) {
var reader = new FileReader();
if (file != null) {
reader.fname = file.name;
reader.readAsArrayBuffer(file);
} else {
$('lblFile').innerHTML = i18n.getTag('NO_FILE');
showError(i18n.getTag('NOT_UPLOADED'));
}
reader.onload = function() {
getFwArray(this.result, this.fname);
if (ota.fwsize > 0) {
// regex = /[^\\]+$/;
// text = fname.match(regex);
$('lblFile').innerHTML = this.fname;
}
}
reader.onerror = function() {
console.log(this.error);
};
}
// var url;
function download(data, path, type) {
var file = new Blob([data], {type: type} );
if (window.navigator.msSaveOrOpenBlob) { // ie10+
window.navigator.msSaveOrOpenBlob(file, path);
} else { // ff, chrome
url = URL.createObjectURL(file);
let link = document.createElement("a");
link.href = path;
link.download = url;
document.body.appendChild(link);
link.click();
setTimeout( function() {
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
}, 0);
URL.revokeObjectURL(url);
}
}
function ajax_file(filename, fn, rawurl = "https://raw.githubusercontent.com/pvvx/THB2/master/") {
let xhr;
if(window.XMLHttpRequest) xhr = new XMLHttpRequest();
else if(window.ActiveXObject) xhr = new ActiveXObject("Microsoft.XMLHTTP")
if (!xhr) { addClog(msg("Your browser does not support AJAX!")); fn(); return;};
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (xhr.status == 200) fn(xhr.response, filename);
else { console.log('XMLHttpRequest: response ' + xhr.status); fn();}
xhr.abort();
xhr = null;
}
};
xhr.ontimeout = function() { console.log('XMLHttpRequest: timeout'); fn();};
xhr.onerror = function () { console.log('XMLHttpRequest error!'); fn();};
xhr.open('GET', rawurl+filename, true);
xhr.timeout = 10000;
xhr.responseType = "arraybuffer";
xhr.send();
}
function FirmwareCustom() {
if(hwver_id != null) {
let fn = otafiles.custom[hwver_id];
let fnn = fn.split("/").pop();
$('lblFile').innerHTML = fnn;
addLog(`${i18n.getTag('UPLOAD_FIRMWARE')} '${fnn}'...`);
ajax_file(fn, getFwArray);
}
}
function FirmwareBeta() {
if(hwver_id != null) {
let fn = otafiles.betafw[hwver_id];
let fnn = fn.split("/").pop();
$('lblFile').innerHTML = fnn;
addLog(`${i18n.getTag('UPLOAD_FIRMWARE')} '${fnn}'...`);
ajax_file(fn, getFwArray);
}
}
function FirmwareBoot() {
if(!confirm(i18n.getTag('WARNING_BOOT_FW')))
return;
if(hwver_id != null) {
let fn = otafiles.updateboot[hwver_id];
let fnn = fn.split("/").pop();
$('lblFile').innerHTML = fnn;
addLog(`${i18n.getTag('UPLOAD_FIRMWARE')} '${fnn}'...`);
ajax_file(fn, getFwArray);
}
}
function getOtaJson(d, name) {
if (!d) {
console.log("No load index file!");
} else {
let str = '';
if (typeof d === 'string')
str = d;
else
str = new TextDecoder("utf-8").decode(d);
let x = JSON.parse(str);
if(x.custom) {
otafiles = x;
otafiles.loaded = true;
console.log(otafiles);
}
}
}
function menuOtaUpgrade() {
let is = "";
if(hwver_id != null) {
if(otafiles.loaded) {
if(otafiles.custom != null) {
let fn = otafiles.custom[hwver_id];
if(fn != null && fn != "" && fn != "?" && fn != "/") {
try {
if(fn.slice(0,6) == "https:")
fn = (new URL(fn)).pathname.split("/").pop();
} catch (error) {
console.log(error);
}
fn = fn.substring(fn.lastIndexOf('/')+1);
is += '<button type="button" id="btFwCustom" onclick="FirmwareCustom();">APP Firmware: ' + fn + '</button>';
}
}
if(otafiles.betafw != null) {
let fn = otafiles.betafw[hwver_id];
if(fn != null && fn != "" && fn != "?" && fn != "/") {
try {
if(fn.slice(0,6) == "https:")
fn = (new URL(fn)).pathname.split("/").pop();
} catch (error) {
console.log(error);
}
fn = fn.substring(fn.lastIndexOf('/')+1);
is += ' <button type="button" id="btFwBeta" onclick="FirmwareBeta();">Beta Firmware: ' + fn + '</button><br>';
}
}
if(otafiles.updateboot != null) {
let fn = otafiles.updateboot[hwver_id];
if(fn != null && fn != "" && fn != "?" && fn != "/") {
try {
if(fn.slice(0,6) == "https:")
fn = (new URL(fn)).pathname.split("/").pop();
} catch (error) {
console.log(error);
}
fn = fn.substring(fn.lastIndexOf('/')+1);
is +=` <button type="button" id="btFwBoot" onclick="FirmwareBoot();">${i18n.getTag('UPDATE')} Boot: ${fn}</button><br>`;
}
}
}
}
if(is != "") is += '<br>';
$("divOTA").innerHTML = is;
}
var chart = null;
function openTab(evt, tabName) {
var i, tabcontent, tablinks;
tabcontent = document.getElementsByClassName("tabcontent");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
$(tabName).style.display = "block";
if (!isConnected) $('tabConfig').style.display = "none";
if (evt != 0) {
evt.currentTarget.className += " active";
// console.log(evt.currentTarget.className);
}
if (tabName == 'tabCharts') {
if ((chartData.length > 0) && (chart != null))
chart.updateOptions({'file': chartData});
resizeChart();
isChartEnabled = true;
} else {
isChartEnabled = false;
}
}
function selectConfigTab() {
openTab(0, "tabConfig");
tablinks = document.getElementsByClassName("tablinks");
tablinks[0].className += " active";
}
// Буфер входящих данных
var chart = null;
var chartData = [];
var rslT = 1;
var rslH = 1;
var rangeT = [15, 25]; // y: { valueRange: [15, 25] },
var rangeH = [25, 85]; // y2: { valueRange: [25, 85] }
const arrayColumn = (arr, n) => arr.map(x => x[n]);
function addChartData(temp, humi) {
let dt = new Date();
chartData.push([dt, temp, humi]);
if(chartData.length >= 1000) chartData.shift();
//console.log(arrayColumn(a, 1));
//console.log(Math.min(...arrayColumn(a, 1)));
//console.log(Math.max(...arrayColumn(a, 1)));
let yMin = Math.min(...arrayColumn(chartData, 1));
let yMax = Math.max(...arrayColumn(chartData, 1));
let xMin = Math.floor(yMin / rslT);
let xMax = Math.floor(yMax / rslT) + 1;
rangeT = [xMin*rslT, xMax*rslT];
yMin = Math.min(...arrayColumn(chartData, 2));
yMax = Math.max(...arrayColumn(chartData, 2));
xMin = Math.floor(yMin / rslH);
xMax = Math.floor(yMax / rslH) + 1;
rangeH = [xMin*rslH, xMax*rslH];
//console.log(rangeT, rangeH);
}
function resizeChart() {
if (chart == null) return;
// console.log('resize однако');
var element = $('divChart');
var positionInfo = element.getBoundingClientRect();
// console.log(positionInfo);
// var width = positionInfo.width;
// var height = positionInfo.height;
var width = $('tabCharts').clientWidth;
var height = $('tabCharts').clientHeight;
// console.log(width, height);
if (height < (320 + 100))
height = 320;
else
height -= 100;
if (width < (480 + 40))
width = 480;
else
width -= 40;
chart.resize(width, height);
// console.log(width, height);
}
window.onload = function() {
console.log("Load index file 'fw.json'...");
ajax_file('fw.json', getOtaJson);
document.querySelector("#inpFile").addEventListener("change", function() {
var file = this.files[0];
if (file != null) {
text = i18n.getTag('NOT_UPLOADED');
readFile(file);
} else {
$('lblFile').innerHTML = i18n.getTag('NOT_UPLOADED');
}
}, false);
showState(i18n.getTag('NOT_CONNECTED'));
disableControls(true);
selectConfigTab();
chart = new Dygraph(
$('divChart'),
[],
{
axes: {
y: { valueRange: rangeT },
y2: { valueRange: rangeH }
},
colors: ['green', 'blue'],
series : { 'RH(%)': { axis: 'y2' } },
labels: ['T(сек)', 'T(°C)', 'RH(%)'],
legend: 'always', // "follow"
digitsAfterDecimal: 2,
}
);
addEventListener("resize", resizeChart);
i18n.updatePage();
};
/*! @license https://github.com/danvk/dygraphs/blob/v2.2.1/LICENSE.txt (MIT) */
!function(t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Dygraph=t()}(function(){var t=function n(i,r,o){function s(e,t){if(!r[e]){if(!i[e]){var a="function"==typeof require&&require;if(!t&&a)return a(e,!0);if(l)return l(e,!0);throw(t=new Error("Cannot find module '"+e+"'")).code="MODULE_NOT_FOUND",t}a=r[e]={exports:{}},i[e][0].call(a.exports,function(t){return s(i[e][1][t]||t)},a,a.exports,n,i,r,o)}return r[e].exports}for(var l="function"==typeof require&&require,t=0;t<o.length;t++)s(o[t]);return s}({"dygraphs/src/datahandler/bars-custom.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;t=(t=t("./bars"))&&t.__esModule?t:{default:t};function n(){}(n.prototype=new t.default).extractSeries=function(t,e,a){for(var n,i,r,o=[],s=a.get("labels")[e],l=a.getForSeries("logscale",s),h=0;h<t.length;h++)n=t[h][0],r=t[h][e],null!==(r=l&&null!==r&&(r[0]<=0||r[1]<=0||r[2]<=0)?null:r)?null===(i=r[1])||isNaN(i)?o.push([n,i,[i,i]]):o.push([n,i,[r[0],r[2]]]):o.push([n,null,[null,null]]);return o},n.prototype.rollingAverage=function(t,e,a,n){e=Math.min(e,t.length);var i=[],r=0,o=0,s=0,l=0;for(n=0;n<t.length;n++){var h=t[n][1],d=t[n][2];i[n]=t[n],null===h||isNaN(h)||(r+=d[0],o+=h,s+=d[1],l+=1),0<=n-e&&(null===(h=t[n-e])[1]||isNaN(h[1])||(r-=h[2][0],o-=h[1],s-=h[2][1],--l)),i[n]=l?[t[n][0],+o/l,[+r/l,+s/l]]:[t[n][0],null,[null,null]]}return i},a.default=n,e.exports=a.default},{"./bars":"dygraphs/src/datahandler/bars.js"}],"dygraphs/src/datahandler/bars-error.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;t=(t=t("./bars"))&&t.__esModule?t:{default:t};function n(){}(n.prototype=new t.default).extractSeries=function(t,e,a){for(var n,i,r,o,s=[],l=a.get("labels")[e],h=a.getForSeries("logscale",l),d=a.getForSeries("sigma",l),u=0;u<t.length;u++)n=t[u][0],o=t[u][e],null!==(o=h&&null!==o&&(o[0]<=0||o[0]-d*o[1]<=0)?null:o)?null===(i=o[0])||isNaN(i)?s.push([n,i,[i,i,i]]):(r=d*o[1],s.push([n,i,[i-r,i+r,o[1]]])):s.push([n,null,[null,null,null]]);return s},n.prototype.rollingAverage=function(t,e,a,n){e=Math.min(e,t.length);var i,r,o,s,l,h,d,u=[],c=a.get("labels")[n],p=a.getForSeries("sigma",c);for(n=0;n<t.length;n++){for(s=h=o=0,i=Math.max(0,n-e+1);i<n+1;i++)null===(r=t[i][1])||isNaN(r)||(s++,o+=r,h+=Math.pow(t[i][2][2],2));s?(l=Math.sqrt(h)/s,u[n]=[t[n][0],d=o/s,[d-p*l,d+p*l]]):(d=1==e?t[n][1]:null,u[n]=[t[n][0],d,[d,d]])}return u},a.default=n,e.exports=a.default},{"./bars":"dygraphs/src/datahandler/bars.js"}],"dygraphs/src/datahandler/bars-fractions.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;t=(t=t("./bars"))&&t.__esModule?t:{default:t};function n(){}(n.prototype=new t.default).extractSeries=function(t,e,a){for(var n,i,r,o,s,l=[],h=a.get("labels")[e],d=a.getForSeries("logscale",h),u=a.getForSeries("sigma",h),c=0;c<t.length;c++)n=t[c][0],r=t[c][e],null!==(r=d&&null!==r&&(r[0]<=0||r[1]<=0)?null:r)?(i=r[0],r=r[1],null===i||isNaN(i)?l.push([n,i,[i,i,i,r]]):(o=r?i/r:0,s=r?u*Math.sqrt(o*(1-o)/r):1,l.push([n,o=100*o,[o-(s=100*s),o+s,i,r]]))):l.push([n,null,[null,null,null,null]]);return l},n.prototype.rollingAverage=function(t,e,a,n){e=Math.min(e,t.length);var i=[],r=a.get("labels")[n],o=a.getForSeries("sigma",r),s=a.getForSeries("wilsonInterval",r),l=0,h=0;for(n=0;n<t.length;n++){l+=t[n][2][2],h+=t[n][2][3],0<=n-e&&(l-=t[n-e][2][2],h-=t[n-e][2][3]);var d,u,c,p=t[n][0],g=h?l/h:0;s?h?(d=g<0?0:g,u=h,u=o*Math.sqrt(d*(1-d)/u+o*o/(4*u*u)),i[n]=[p,100*d,[100*((d+o*o/(2*h)-u)/(c=1+o*o/h)),100*((d+o*o/(2*h)+u)/c)]]):i[n]=[p,0,[0,0]]:(d=h?o*Math.sqrt(g*(1-g)/h):1,i[n]=[p,100*g,[100*(g-d),100*(g+d)]])}return i},a.default=n,e.exports=a.default},{"./bars":"dygraphs/src/datahandler/bars.js"}],"dygraphs/src/datahandler/bars.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var r=n(t("./datahandler")),o=n(t("../dygraph-layout"));function n(t){return t&&t.__esModule?t:{default:t}}function i(){r.default.call(this)}(i.prototype=new r.default).extractSeries=function(t,e,a){},i.prototype.rollingAverage=function(t,e,a,n){},i.prototype.onPointsCreated_=function(t,e){for(var a=0;a<t.length;++a){var n=t[a],i=e[a];i.y_top=NaN,i.y_bottom=NaN,i.yval_minus=r.default.parseFloat(n[2][0]),i.yval_plus=r.default.parseFloat(n[2][1])}},i.prototype.getExtremeYValues=function(t,e,a){for(var n,i,r,o=null,s=null,l=t.length-1,h=0;h<=l;h++)null!==(r=t[h][1])&&!isNaN(r)&&(r<(n=t[h][2][0])&&(n=r),(i=t[h][2][1])<r&&(i=r),(null===s||s<i)&&(s=i),null===o||n<o)&&(o=n);return[o,s]},i.prototype.onLineEvaluated=function(t,e,a){for(var n,i=0;i<t.length;i++)(n=t[i]).y_top=o.default.calcYNormal_(e,n.yval_minus,a),n.y_bottom=o.default.calcYNormal_(e,n.yval_plus,a)},a.default=i,e.exports=a.default},{"../dygraph-layout":"dygraphs/src/dygraph-layout.js","./datahandler":"dygraphs/src/datahandler/datahandler.js"}],"dygraphs/src/datahandler/datahandler.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;function n(){}var s=n;s.X=0,s.Y=1,s.EXTRAS=2,s.prototype.extractSeries=function(t,e,a){},s.prototype.seriesToPoints=function(t,e,a){for(var n=[],i=0;i<t.length;++i){var r=t[i],o=r[1],o=null===o?null:s.parseFloat(o),r={x:NaN,y:NaN,xval:s.parseFloat(r[0]),yval:o,name:e,idx:i+a,canvasx:NaN,canvasy:NaN};n.push(r)}return this.onPointsCreated_(t,n),n},s.prototype.onPointsCreated_=function(t,e){},s.prototype.rollingAverage=function(t,e,a,n){},s.prototype.getExtremeYValues=function(t,e,a){},s.prototype.onLineEvaluated=function(t,e,a){},s.parseFloat=function(t){return null===t?NaN:t},a.default=n,e.exports=a.default},{}],"dygraphs/src/datahandler/default-fractions.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;n(t("./datahandler"));t=n(t("./default"));function n(t){return t&&t.__esModule?t:{default:t}}function i(){}(i.prototype=new t.default).extractSeries=function(t,e,a){for(var n,i,r,o=[],s=a.get("labels")[e],l=a.getForSeries("logscale",s),h=0;h<t.length;h++)n=t[h][0],r=t[h][e],null!==(r=l&&null!==r&&(r[0]<=0||r[1]<=0)?null:r)?(i=r[0],r=r[1],null===i||isNaN(i)?o.push([n,i,[i,r]]):o.push([n,100*(r?i/r:0),[i,r]])):o.push([n,null,[null,null]]);return o},i.prototype.rollingAverage=function(t,e,a,n){e=Math.min(e,t.length);var i=[],r=0,o=0;for(n=0;n<t.length;n++){r+=t[n][2][0],o+=t[n][2][1],0<=n-e&&(r-=t[n-e][2][0],o-=t[n-e][2][1]);var s=t[n][0];i[n]=[s,100*(o?r/o:0)]}return i},a.default=i,e.exports=a.default},{"./datahandler":"dygraphs/src/datahandler/datahandler.js","./default":"dygraphs/src/datahandler/default.js"}],"dygraphs/src/datahandler/default.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;t=(t=t("./datahandler"))&&t.__esModule?t:{default:t};function n(){}(n.prototype=new t.default).extractSeries=function(t,e,a){for(var n=[],i=a.get("labels")[e],r=a.getForSeries("logscale",i),o=0;o<t.length;o++){var s=t[o][0],l=t[o][e];n.push([s,l=r&&l<=0?null:l])}return n},n.prototype.rollingAverage=function(t,e,a,n){var i,r,o,s,l=[];if(1==(e=Math.min(e,t.length)))return t;for(n=0;n<t.length;n++){for(s=o=0,i=Math.max(0,n-e+1);i<n+1;i++)null===(r=t[i][1])||isNaN(r)||(s++,o+=t[i][1]);l[n]=s?[t[n][0],o/s]:[t[n][0],null]}return l},n.prototype.getExtremeYValues=function(t,e,a){for(var n,i=null,r=null,o=t.length-1,s=0;s<=o;s++)null!==(n=t[s][1])&&!isNaN(n)&&((null===r||r<n)&&(r=n),null===i||n<i)&&(i=n);return[i,r]},a.default=n,e.exports=a.default},{"./datahandler":"dygraphs/src/datahandler/datahandler.js"}],"dygraphs/src/dygraph-canvas.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var T=function(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=o(e);if(e&&e.has(t))return e.get(t);var a,n={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t){var r;"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((r=i?Object.getOwnPropertyDescriptor(t,a):null)&&(r.get||r.set)?Object.defineProperty(n,a,r):n[a]=t[a])}n.default=t,e&&e.set(t,n);return n}(t("./dygraph-utils")),D=(t=t("./dygraph"))&&t.__esModule?t:{default:t};function o(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(o=function(t){return t?a:e})(t))}function E(t,e,a,n){if(this.dygraph_=t,this.layout=n,this.element=e,this.elementContext=a,this.height=t.height_,this.width=t.width_,!T.isCanvasSupported(this.element))throw"Canvas is not supported.";this.area=n.getPlotArea(),(e=this.dygraph_.canvas_ctx_).beginPath(),e.rect(this.area.x,this.area.y,this.area.w,this.area.h),e.clip(),(e=this.dygraph_.hidden_ctx_).beginPath(),e.rect(this.area.x,this.area.y,this.area.w,this.area.h),e.clip()}E.prototype.clear=function(){this.elementContext.clearRect(0,0,this.width,this.height)},E.prototype.render=function(){this._updatePoints(),this._renderLineChart()},E._getIteratorPredicate=function(t){return t?E._predicateThatSkipsEmptyPoints:null},E._predicateThatSkipsEmptyPoints=function(t,e){return null!==t[e].yval},E._drawStyledLine=function(t,e,a,n,i,r,o){var s=t.dygraph,l=s.getBooleanOption("stepPlot",t.setName),h=(T.isArrayLike(n)||(n=null),s.getBooleanOption("drawGapEdgePoints",t.setName)),d=t.points,u=t.setName,d=T.createIterator(d,0,d.length,E._getIteratorPredicate(s.getBooleanOption("connectSeparatedPoints",u))),s=n&&2<=n.length,u=t.drawingContext,n=(u.save(),s&&u.setLineDash&&u.setLineDash(n),E._drawSeries(t,d,a,o,i,h,l,e));E._drawPointsOnLine(t,n,r,e,o),s&&u.setLineDash&&u.setLineDash([]),u.restore()},E._drawSeries=function(t,e,a,n,i,r,o,s){for(var l,h,d,u=null,c=null,p=[],g=!0,f=t.drawingContext,_=(f.beginPath(),f.strokeStyle=s,f.lineWidth=a,e.array_),y=e.end_,v=e.predicate_,x=e.start_;x<y;x++){if(l=_[x],v){for(;x<y&&!v(_,x);)x++;if(x==y)break;l=_[x]}null===l.canvasy||l.canvasy!=l.canvasy?(o&&null!==u&&(f.moveTo(u,c),f.lineTo(l.canvasx,c)),u=c=null):(d=!1,(r||null===u)&&(e.nextIdx_=x,e.next(),h=null===(h=e.hasNext?e.peek.canvasy:null)||h!=h,d=null===u&&h,r)&&(!g&&null===u||e.hasNext&&h)&&(d=!0),null!==u?a&&(o&&(f.moveTo(u,c),f.lineTo(l.canvasx,c)),f.lineTo(l.canvasx,l.canvasy)):f.moveTo(l.canvasx,l.canvasy),(i||d)&&p.push([l.canvasx,l.canvasy,l.idx]),u=l.canvasx,c=l.canvasy),g=!1}return f.stroke(),p},E._drawPointsOnLine=function(t,e,a,n,i){for(var r=t.drawingContext,o=0;o<e.length;o++){var s=e[o];r.save(),a.call(t.dygraph,t.dygraph,t.setName,r,s[0],s[1],n,i,s[2]),r.restore()}},E.prototype._updatePoints=function(){for(var t=this.layout.points,e=t.length;e--;)for(var a=t[e],n=a.length;n--;){var i=a[n];i.canvasx=this.area.w*i.x+this.area.x,i.canvasy=this.area.h*i.y+this.area.y}},E.prototype._renderLineChart=function(t,e){for(var a=e||this.elementContext,n=this.layout.points,i=this.layout.setNames,r=(this.colors=this.dygraph_.colorsMap_,this.dygraph_.getOption("plotter")),o=r,s=(T.isArrayLike(o)||(o=[o]),{}),l=0;l<i.length;l++){var h=i[l],d=this.dygraph_.getOption("plotter",h);d!=r&&(s[h]=d)}for(l=0;l<o.length;l++)for(var u=o[l],c=l==o.length-1,p=0;p<n.length;p++)if(h=i[p],!t||h==t){var g=n[p],f=u;if(h in s){if(!c)continue;f=s[h]}var _=this.colors[h],y=this.dygraph_.getOption("strokeWidth",h);a.save(),a.strokeStyle=_,a.lineWidth=y,f({points:g,setName:h,drawingContext:a,color:_,strokeWidth:y,dygraph:this.dygraph_,axis:this.dygraph_.axisPropertiesForSeries(h),plotArea:this.area,seriesIndex:p,seriesCount:n.length,singleSeriesName:t,allSeriesPoints:n}),a.restore()}},E._Plotters={linePlotter:function(t){E._linePlotter(t)},fillPlotter:function(t){E._fillPlotter(t)},errorPlotter:function(t){E._errorPlotter(t)}},E._linePlotter=function(t){var e=t.dygraph,a=t.setName,n=t.strokeWidth,i=e.getNumericOption("strokeBorderWidth",a),r=e.getOption("drawPointCallback",a)||T.Circles.DEFAULT,o=e.getOption("strokePattern",a),s=e.getBooleanOption("drawPoints",a),l=e.getNumericOption("pointSize",a);i&&n&&E._drawStyledLine(t,e.getOption("strokeBorderColor",a),n+2*i,o,s,r,l),E._drawStyledLine(t,t.color,n,o,s,r,l)},E._errorPlotter=function(t){var e=t.dygraph,a=t.setName;if(e.getBooleanOption("errorBars")||e.getBooleanOption("customBars")){e.getBooleanOption("fillGraph",a)&&console.warn("Can't use fillGraph option with customBars or errorBars option");for(var n,i=t.drawingContext,r=t.color,o=e.getNumericOption("fillAlpha",a),s=e.getBooleanOption("stepPlot",a),l=t.points,h=T.createIterator(l,0,l.length,E._getIteratorPredicate(e.getBooleanOption("connectSeparatedPoints",a))),d=NaN,u=NaN,c=[-1,-1],l=T.toRGB_(r),e="rgba("+l.r+","+l.g+","+l.b+","+o+")",p=(i.fillStyle=e,i.beginPath(),function(t){return null==t||isNaN(t)});h.hasNext;){var g=h.next();!s&&p(g.y)||s&&!isNaN(u)&&p(u)?d=NaN:(n=[g.y_bottom,g.y_top],s&&(u=g.y),isNaN(n[0])&&(n[0]=g.y),isNaN(n[1])&&(n[1]=g.y),n[0]=t.plotArea.h*n[0]+t.plotArea.y,n[1]=t.plotArea.h*n[1]+t.plotArea.y,isNaN(d)||(s?(i.moveTo(d,c[0]),i.lineTo(g.canvasx,c[0]),i.lineTo(g.canvasx,c[1])):(i.moveTo(d,c[0]),i.lineTo(g.canvasx,n[0]),i.lineTo(g.canvasx,n[1])),i.lineTo(d,c[1]),i.closePath()),c=n,d=g.canvasx)}i.fill()}},E._fastCanvasProxy=function(i){function r(t){c(t);for(var e=0,a=h.length;e<a;e++){var n=h[e];n[0]==d?i.lineTo(n[1],n[2]):n[0]==u&&i.moveTo(n[1],n[2])}h.length&&(s=h[h.length-1][1]),l+=h.length,h=[]}function a(t,e,a){var n=Math.round(e);null!==o&&n==o||(r(1<o-s||1<n-o),o=n),h.push([t,e,a])}var h=[],o=null,s=null,d=1,u=2,l=0,c=function(t){if(!(h.length<=1)){for(var e,a=h.length-1;0<a;a--)(n=h[a])[0]==u&&(e=h[a-1])[1]==n[1]&&e[2]==n[2]&&h.splice(a,1);for(a=0;a<h.length-1;)(n=h[a])[0]==u&&h[a+1][0]==u?h.splice(a,1):a++;if(2<h.length&&!t){for(var n,i,t=0,r=(h[0][0]==u&&t++,null),o=null,a=t;a<h.length;a++)(n=h[a])[0]==d&&(null===r&&null===o?o=r=a:(i=n[2])<h[r][2]?r=a:i>h[o][2]&&(o=a));var s=h[r],l=h[o];h.splice(t,h.length-t),r<o?(h.push(s),h.push(l)):(o<r&&h.push(l),h.push(s))}}};return{moveTo:function(t,e){a(u,t,e)},lineTo:function(t,e){a(d,t,e)},stroke:function(){r(!0),i.stroke()},fill:function(){r(!0),i.fill()},beginPath:function(){r(!0),i.beginPath()},closePath:function(){r(!0),i.closePath()},_count:function(){return l}}},E._fillPlotter=function(t){if(!t.singleSeriesName&&0===t.seriesIndex){for(var e=t.dygraph,a=e.getLabels().slice(1),n=a.length;0<=n;n--)e.visibility()[n]||a.splice(n,1);if(function(){for(var t=0;t<a.length;t++)if(e.getBooleanOption("fillGraph",a[t]))return!0;return!1}())for(var i,r=t.plotArea,o=t.allSeriesPoints,s=o.length,l=e.getBooleanOption("stackedGraph"),h=e.getColors(),d={},u=function(t,e,a,n){if(t.lineTo(e,a),l)for(var i=n.length-1;0<=i;i--){var r=n[i];t.lineTo(r[0],r[1])}},c=s-1;0<=c;c--){var p=t.drawingContext,g=a[c];if(e.getBooleanOption("fillGraph",g)){var f=e.getNumericOption("fillAlpha",g),_=e.getBooleanOption("stepPlot",g),y=h[c],v=e.axisPropertiesForSeries(g),x=1+v.minyval*v.yscale,v=(x<0?x=0:1<x&&(x=1),x=r.h*x+r.y,o[c]),m=T.createIterator(v,0,v.length,E._getIteratorPredicate(e.getBooleanOption("connectSeparatedPoints",g))),b=NaN,w=[-1,-1],g=T.toRGB_(y),y="rgba("+g.r+","+g.g+","+g.b+","+f+")";p.fillStyle=y,p.beginPath();for(var O,A=!0,P=((v.length>2*e.width_||D.default.FORCE_FAST_PROXY)&&(p=E._fastCanvasProxy(p)),[]);m.hasNext;)if(O=m.next(),T.isOK(O.y)||_){if(l){if(!A&&L==O.xval)continue;var S,A=!1,L=O.xval,M=void 0===(S=d[O.canvasx])?x:i?S[0]:S,C=[O.canvasy,M];_?-1===w[0]?d[O.canvasx]=[O.canvasy,x]:d[O.canvasx]=[O.canvasy,w[0]]:d[O.canvasx]=O.canvasy}else C=isNaN(O.canvasy)&&_?[r.y+r.h,x]:[O.canvasy,x];isNaN(b)?(p.moveTo(O.canvasx,C[1]),p.lineTo(O.canvasx,C[0])):(_&&p.lineTo(O.canvasx,w[0]),p.lineTo(O.canvasx,C[0]),l&&(P.push([b,w[1]]),i&&S?P.push([O.canvasx,S[1]]):P.push([O.canvasx,C[1]]))),w=C,b=O.canvasx}else u(p,b,w[1],P),P=[],b=NaN,null===O.y_stacked||isNaN(O.y_stacked)||(d[O.canvasx]=r.h*O.y_stacked+r.y);i=_,C&&O&&(u(p,O.canvasx,C[1],P),P=[]),p.fill()}}}},a.default=E,e.exports=a.default},{"./dygraph":"dygraphs/src/dygraph.js","./dygraph-utils":"dygraphs/src/dygraph-utils.js"}],"dygraphs/src/dygraph-default-attrs.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var n=l(t("./dygraph-tickers")),i=o(t("./dygraph-interaction-model")),r=o(t("./dygraph-canvas")),t=l(t("./dygraph-utils"));function o(t){return t&&t.__esModule?t:{default:t}}function s(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(s=function(t){return t?a:e})(t))}function l(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=s(e);if(e&&e.has(t))return e.get(t);var a,n,i={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t)"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((n=r?Object.getOwnPropertyDescriptor(t,a):null)&&(n.get||n.set)?Object.defineProperty(i,a,n):i[a]=t[a]);return i.default=t,e&&e.set(t,i),i}i={highlightCircleSize:3,highlightSeriesOpts:null,highlightSeriesBackgroundAlpha:.5,highlightSeriesBackgroundColor:"rgb(255, 255, 255)",labelsSeparateLines:!1,labelsShowZeroValues:!0,labelsKMB:!1,labelsKMG2:!1,showLabelsOnHighlight:!0,digitsAfterDecimal:2,maxNumberWidth:6,sigFigs:null,strokeWidth:1,strokeBorderWidth:0,strokeBorderColor:"white",axisTickSize:3,axisLabelFontSize:14,rightGap:5,showRoller:!1,xValueParser:void 0,delimiter:",",sigma:2,errorBars:!1,fractions:!1,wilsonInterval:!0,customBars:!1,fillGraph:!1,fillAlpha:.15,connectSeparatedPoints:!1,stackedGraph:!1,stackedGraphNaNFill:"all",hideOverlayOnMouseOut:!0,resizable:"no",legend:"onmouseover",legendFollowOffsetX:50,legendFollowOffsetY:-50,stepPlot:!1,xRangePad:0,yRangePad:null,drawAxesAtZero:!1,titleHeight:28,xLabelHeight:18,yLabelWidth:18,axisLineColor:"black",axisLineWidth:.3,gridLineWidth:.3,axisLabelWidth:50,gridLineColor:"rgb(128,128,128)",interactionModel:i.default.defaultModel,animatedZooms:!1,animateBackgroundFade:!0,showRangeSelector:!1,rangeSelectorHeight:40,rangeSelectorPlotStrokeColor:"#808FAB",rangeSelectorPlotFillGradientColor:"white",rangeSelectorPlotFillColor:"#A7B1C4",rangeSelectorBackgroundStrokeColor:"gray",rangeSelectorBackgroundLineWidth:1,rangeSelectorPlotLineWidth:1.5,rangeSelectorForegroundStrokeColor:"black",rangeSelectorForegroundLineWidth:1,rangeSelectorAlpha:.6,showInRangeSelector:null,plotter:[r.default._fillPlotter,r.default._errorPlotter,r.default._linePlotter],plugins:[],axes:{x:{pixelsPerLabel:70,axisLabelWidth:60,axisLabelFormatter:t.dateAxisLabelFormatter,valueFormatter:t.dateValueFormatter,drawGrid:!0,drawAxis:!0,independentTicks:!0,ticker:n.dateTicker},y:{axisLabelWidth:50,pixelsPerLabel:30,valueFormatter:t.numberValueFormatter,axisLabelFormatter:t.numberAxisLabelFormatter,drawGrid:!0,drawAxis:!0,independentTicks:!0,ticker:n.numericTicks},y2:{axisLabelWidth:50,pixelsPerLabel:30,valueFormatter:t.numberValueFormatter,axisLabelFormatter:t.numberAxisLabelFormatter,drawAxis:!0,drawGrid:!1,independentTicks:!1,ticker:n.numericTicks}}};a.default=i,e.exports=a.default},{"./dygraph-canvas":"dygraphs/src/dygraph-canvas.js","./dygraph-interaction-model":"dygraphs/src/dygraph-interaction-model.js","./dygraph-tickers":"dygraphs/src/dygraph-tickers.js","./dygraph-utils":"dygraphs/src/dygraph-utils.js"}],"dygraphs/src/dygraph-gviz.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var n=(t=t("./dygraph"))&&t.__esModule?t:{default:t};function i(t){this.container=t}i.prototype.draw=function(t,e){this.container.innerHTML="",void 0!==this.date_graph&&this.date_graph.destroy(),this.date_graph=new n.default(this.container,t,e)},i.prototype.setSelection=function(t){var e=!1;t.length&&(e=t[0].row),this.date_graph.setSelection(e)},i.prototype.getSelection=function(){var t=[],e=this.date_graph.getSelection();if(!(e<0))for(var a=this.date_graph.layout_.points,n=0;n<a.length;++n)t.push({row:e,column:n+1});return t},a.default=i,e.exports=a.default},{"./dygraph":"dygraphs/src/dygraph.js"}],"dygraphs/src/dygraph-interaction-model.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var g=function(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=o(e);if(e&&e.has(t))return e.get(t);var a,n={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t){var r;"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((r=i?Object.getOwnPropertyDescriptor(t,a):null)&&(r.get||r.set)?Object.defineProperty(n,a,r):n[a]=t[a])}n.default=t,e&&e.set(t,n);return n}(t("./dygraph-utils"));function o(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(o=function(t){return t?a:e})(t))}var s={maybeTreatMouseOpAsClick:function(t,e,a){a.dragEndX=g.dragGetX_(t,a),a.dragEndY=g.dragGetY_(t,a);var n=Math.abs(a.dragEndX-a.dragStartX),i=Math.abs(a.dragEndY-a.dragStartY);n<2&&i<2&&void 0!==e.lastx_&&null!==e.lastx_&&s.treatMouseOpAsClick(e,t,a),a.regionWidth=n,a.regionHeight=i},startPan:function(t,e,a){a.isPanning=!0;var n=e.xAxisRange();if(e.getOptionForAxis("logscale","x")?(a.initialLeftmostDate=g.log10(n[0]),a.dateRange=g.log10(n[1])-g.log10(n[0])):(a.initialLeftmostDate=n[0],a.dateRange=n[1]-n[0]),a.xUnitsPerPixel=a.dateRange/(e.plotter_.area.w-1),e.getNumericOption("panEdgeFraction")){for(var n=e.width_*e.getNumericOption("panEdgeFraction"),i=e.xAxisExtremes(),r=e.toDomXCoord(i[0])-n,i=e.toDomXCoord(i[1])+n,n=e.toDataXCoord(r),r=e.toDataXCoord(i),o=(a.boundedDates=[n,r],[]),s=e.height_*e.getNumericOption("panEdgeFraction"),l=0;l<e.axes_.length;l++){var h,d=(h=e.axes_[l]).extremeRange,u=e.toDomYCoord(d[0],l)+s,d=e.toDomYCoord(d[1],l)-s,u=e.toDataYCoord(u,l),d=e.toDataYCoord(d,l);o[l]=[u,d]}a.boundedValues=o}else a.boundedDates=null,a.boundedValues=null;for(a.is2DPan=!1,a.axes=[],l=0;l<e.axes_.length;l++){h=e.axes_[l];var c={},p=e.yAxisRange(l);e.attributes_.getForAxis("logscale",l)?(c.initialTopValue=g.log10(p[1]),c.dragValueRange=g.log10(p[1])-g.log10(p[0])):(c.initialTopValue=p[1],c.dragValueRange=p[1]-p[0]),c.unitsPerPixel=c.dragValueRange/(e.plotter_.area.h-1),a.axes.push(c),h.valueRange&&(a.is2DPan=!0)}},movePan:function(t,e,a){a.dragEndX=g.dragGetX_(t,a),a.dragEndY=g.dragGetY_(t,a);var t=a.initialLeftmostDate-(a.dragEndX-a.dragStartX)*a.xUnitsPerPixel,n=(t=a.boundedDates?Math.max(t,a.boundedDates[0]):t)+a.dateRange;if(a.boundedDates&&n>a.boundedDates[1]&&(n=(t-=n-a.boundedDates[1])+a.dateRange),e.getOptionForAxis("logscale","x")?e.dateWindow_=[Math.pow(g.LOG_SCALE,t),Math.pow(g.LOG_SCALE,n)]:e.dateWindow_=[t,n],a.is2DPan)for(var i=a.dragEndY-a.dragStartY,r=0;r<e.axes_.length;r++){var o=e.axes_[r],s=a.axes[r],l=i*s.unitsPerPixel,h=a.boundedValues?a.boundedValues[r]:null,l=s.initialTopValue+l,d=(l=h?Math.min(l,h[1]):l)-s.dragValueRange;h&&d<h[0]&&(d=(l-=d-h[0])-s.dragValueRange),e.attributes_.getForAxis("logscale",r)?o.valueRange=[Math.pow(g.LOG_SCALE,d),Math.pow(g.LOG_SCALE,l)]:o.valueRange=[d,l]}e.drawGraph_(!1)}},l=(s.endPan=s.maybeTreatMouseOpAsClick,s.startZoom=function(t,e,a){a.isZooming=!0,a.zoomMoved=!1},s.moveZoom=function(t,e,a){a.zoomMoved=!0,a.dragEndX=g.dragGetX_(t,a),a.dragEndY=g.dragGetY_(t,a);var t=Math.abs(a.dragStartX-a.dragEndX),n=Math.abs(a.dragStartY-a.dragEndY);a.dragDirection=t<n/2?g.VERTICAL:g.HORIZONTAL,e.drawZoomRect_(a.dragDirection,a.dragStartX,a.dragEndX,a.dragStartY,a.dragEndY,a.prevDragDirection,a.prevEndX,a.prevEndY),a.prevEndX=a.dragEndX,a.prevEndY=a.dragEndY,a.prevDragDirection=a.dragDirection},s.treatMouseOpAsClick=function(t,e,a){for(var n=t.getFunctionOption("clickCallback"),i=t.getFunctionOption("pointClickCallback"),r=null,o=-1,s=Number.MAX_VALUE,l=0;l<t.selPoints_.length;l++){var h=t.selPoints_[l],h=Math.pow(h.canvasx-a.dragEndX,2)+Math.pow(h.canvasy-a.dragEndY,2);!isNaN(h)&&(-1==o||h<s)&&(s=h,o=l)}var d=t.getNumericOption("highlightCircleSize")+2;if(r=s<=d*d?t.selPoints_[o]:r){var u={cancelable:!0,point:r,canvasx:a.dragEndX,canvasy:a.dragEndY};if(t.cascadeEvents_("pointClick",u))return;i&&i.call(t,e,r)}u={cancelable:!0,xval:t.lastx_,pts:t.selPoints_,canvasx:a.dragEndX,canvasy:a.dragEndY};t.cascadeEvents_("click",u)||n&&n.call(t,e,t.lastx_,t.selPoints_)},s.endZoom=function(t,e,a){e.clearZoomRect_(),a.isZooming=!1,s.maybeTreatMouseOpAsClick(t,e,a);var n,i,t=e.getArea();10<=a.regionWidth&&a.dragDirection==g.HORIZONTAL?(n=Math.min(a.dragStartX,a.dragEndX),i=Math.max(a.dragStartX,a.dragEndX),(n=Math.max(n,t.x))<(i=Math.min(i,t.x+t.w))&&e.doZoomX_(n,i),a.cancelNextDblclick=!0):10<=a.regionHeight&&a.dragDirection==g.VERTICAL&&(n=Math.min(a.dragStartY,a.dragEndY),i=Math.max(a.dragStartY,a.dragEndY),(n=Math.max(n,t.y))<(i=Math.min(i,t.y+t.h))&&e.doZoomY_(n,i),a.cancelNextDblclick=!0),a.dragStartX=null,a.dragStartY=null},s.startTouch=function(t,e,a){t.preventDefault(),1<t.touches.length&&(a.startTimeForDoubleTapMs=null);for(var n,i=[],r=0;r<t.touches.length;r++){var o=t.touches[r],s=o.target.getBoundingClientRect();i.push({pageX:o.pageX,pageY:o.pageY,dataX:e.toDataXCoord(o.clientX-s.left),dataY:e.toDataYCoord(o.clientY-s.top)})}1==(a.initialTouches=i).length?(a.initialPinchCenter=i[0],a.touchDirections={x:!0,y:!0}):2<=i.length&&(a.initialPinchCenter={pageX:.5*(i[0].pageX+i[1].pageX),pageY:.5*(i[0].pageY+i[1].pageY),dataX:.5*(i[0].dataX+i[1].dataX),dataY:.5*(i[0].dataY+i[1].dataY)},n=180/Math.PI*Math.atan2(a.initialPinchCenter.pageY-i[0].pageY,i[0].pageX-a.initialPinchCenter.pageX),n=Math.abs(n),a.touchDirections={x:(n=90<n?90-n:n)<67.5,y:22.5<n}),a.initialRange={x:e.xAxisRange(),y:e.yAxisRange()}},s.moveTouch=function(t,e,a){a.startTimeForDoubleTapMs=null;for(var n=[],i=0;i<t.touches.length;i++){var r=t.touches[i];n.push({pageX:r.pageX,pageY:r.pageY})}var o,s,l=a.initialTouches,h=a.initialPinchCenter,d=1==n.length?n[0]:{pageX:.5*(n[0].pageX+n[1].pageX),pageY:.5*(n[0].pageY+n[1].pageY)},u={pageX:d.pageX-h.pageX,pageY:d.pageY-h.pageY},c=a.initialRange.x[1]-a.initialRange.x[0],p=a.initialRange.y[0]-a.initialRange.y[1],g=(u.dataX=u.pageX/e.plotter_.area.w*c,u.dataY=u.pageY/e.plotter_.area.h*p,1==n.length?s=o=1:2<=n.length&&(c=l[1].pageX-h.pageX,o=(n[1].pageX-d.pageX)/c,p=l[1].pageY-h.pageY,s=(n[1].pageY-d.pageY)/p),o=Math.min(8,Math.max(.125,o)),s=Math.min(8,Math.max(.125,s)),!1);if(a.touchDirections.x&&(f=h.dataX-u.dataX/o,e.dateWindow_=[f+(a.initialRange.x[0]-h.dataX)/o,f+(a.initialRange.x[1]-h.dataX)/o],g=!0),a.touchDirections.y)for(i=0;i<1;i++){var f,_=e.axes_[i];e.attributes_.getForAxis("logscale",i)||(f=h.dataY-u.dataY/s,_.valueRange=[f+(a.initialRange.y[0]-h.dataY)/s,f+(a.initialRange.y[1]-h.dataY)/s],g=!0)}e.drawGraph_(!1),g&&1<n.length&&e.getFunctionOption("zoomCallback")&&(c=e.xAxisRange(),e.getFunctionOption("zoomCallback").call(e,c[0],c[1],e.yAxisRanges()))},s.endTouch=function(t,e,a){var n;0!==t.touches.length?s.startTouch(t,e,a):1==t.changedTouches.length&&(n=(new Date).getTime(),t=t.changedTouches[0],a.startTimeForDoubleTapMs&&n-a.startTimeForDoubleTapMs<500&&a.doubleTapX&&Math.abs(a.doubleTapX-t.screenX)<50&&a.doubleTapY&&Math.abs(a.doubleTapY-t.screenY)<50?e.resetZoom():(a.startTimeForDoubleTapMs=n,a.doubleTapX=t.screenX,a.doubleTapY=t.screenY))},function(t,e,a){return t<e?e-t:a<t?t-a:0});s.defaultModel={mousedown:function(t,i,r){var a;t.button&&2==t.button||(r.initializeMouseDown(t,i,r),t.altKey||t.shiftKey?s.startPan(t,i,r):s.startZoom(t,i,r),a=function(t){var e,a,n;r.isZooming?(e=t,a=i,n={left:(n=g.findPos(a.canvas_)).x,right:n.x+a.canvas_.offsetWidth,top:n.y,bottom:n.y+a.canvas_.offsetHeight},a={x:g.pageX(e),y:g.pageY(e)},e=l(a.x,n.left,n.right),a=l(a.y,n.top,n.bottom),Math.max(e,a)<100?s.moveZoom(t,i,r):null!==r.dragEndX&&(r.dragEndX=null,r.dragEndY=null,i.clearZoomRect_())):r.isPanning&&s.movePan(t,i,r)},t=function t(e){r.isZooming?null!==r.dragEndX?s.endZoom(e,i,r):s.maybeTreatMouseOpAsClick(e,i,r):r.isPanning&&s.endPan(e,i,r),g.removeEvent(document,"mousemove",a),g.removeEvent(document,"mouseup",t),r.destroy()},i.addAndTrackEvent(document,"mousemove",a),i.addAndTrackEvent(document,"mouseup",t))},willDestroyContextMyself:!0,touchstart:function(t,e,a){s.startTouch(t,e,a)},touchmove:function(t,e,a){s.moveTouch(t,e,a)},touchend:function(t,e,a){s.endTouch(t,e,a)},dblclick:function(t,e,a){a.cancelNextDblclick?a.cancelNextDblclick=!1:(a={canvasx:a.dragEndX,canvasy:a.dragEndY,cancelable:!0},e.cascadeEvents_("dblclick",a)||t.altKey||t.shiftKey||e.resetZoom())}},s.nonInteractiveModel_={mousedown:function(t,e,a){a.initializeMouseDown(t,e,a)},mouseup:s.maybeTreatMouseOpAsClick},s.dragIsPanInteractionModel={mousedown:function(t,e,a){a.initializeMouseDown(t,e,a),s.startPan(t,e,a)},mousemove:function(t,e,a){a.isPanning&&s.movePan(t,e,a)},mouseup:function(t,e,a){a.isPanning&&s.endPan(t,e,a)}},a.default=s,e.exports=a.default},{"./dygraph-utils":"dygraphs/src/dygraph-utils.js"}],"dygraphs/src/dygraph-layout.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var i=function(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=o(e);if(e&&e.has(t))return e.get(t);var a,n={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t){var r;"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((r=i?Object.getOwnPropertyDescriptor(t,a):null)&&(r.get||r.set)?Object.defineProperty(n,a,r):n[a]=t[a])}n.default=t,e&&e.set(t,n);return n}(t("./dygraph-utils"));function o(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(o=function(t){return t?a:e})(t))}function u(t){this.dygraph_=t,this.points=[],this.setNames=[],this.annotations=[],this.yAxes_=null,this.xTicks_=null,this.yTicks_=null}u.prototype.addDataset=function(t,e){this.points.push(e),this.setNames.push(t)},u.prototype.getPlotArea=function(){return this.area_},u.prototype.computePlotArea=function(){var a={x:0,y:0},t=(a.w=this.dygraph_.width_-a.x-this.dygraph_.getOption("rightGap"),a.h=this.dygraph_.height_,{chart_div:this.dygraph_.graphDiv,reserveSpaceLeft:function(t){var e={x:a.x,y:a.y,w:t,h:a.h};return a.x+=t,a.w-=t,e},reserveSpaceRight:function(t){var e={x:a.x+a.w-t,y:a.y,w:t,h:a.h};return a.w-=t,e},reserveSpaceTop:function(t){var e={x:a.x,y:a.y,w:a.w,h:t};return a.y+=t,a.h-=t,e},reserveSpaceBottom:function(t){var e={x:a.x,y:a.y+a.h-t,w:a.w,h:t};return a.h-=t,e},chartRect:function(){return{x:a.x,y:a.y,w:a.w,h:a.h}}});this.dygraph_.cascadeEvents_("layout",t),this.area_=a},u.prototype.setAnnotations=function(t){this.annotations=[];for(var e=this.dygraph_.getOption("xValueParser")||function(t){return t},a=0;a<t.length;a++){var n={};if(!t[a].xval&&void 0===t[a].x)return void console.error("Annotations must have an 'x' property");if(t[a].icon&&(!t[a].hasOwnProperty("width")||!t[a].hasOwnProperty("height")))return void console.error("Must set width and height when setting annotation.icon property");i.update(n,t[a]),n.xval||(n.xval=e(n.x)),this.annotations.push(n)}},u.prototype.setXTicks=function(t){this.xTicks_=t},u.prototype.setYAxes=function(t){this.yAxes_=t},u.prototype.evaluate=function(){this._xAxis={},this._evaluateLimits(),this._evaluateLineCharts(),this._evaluateLineTicks(),this._evaluateAnnotations()},u.prototype._evaluateLimits=function(){var t=this.dygraph_.xAxisRange(),t=(this._xAxis.minval=t[0],this._xAxis.maxval=t[1],t[1]-t[0]);this._xAxis.scale=0!=t?1/t:1,this.dygraph_.getOptionForAxis("logscale","x")&&(this._xAxis.xlogrange=i.log10(this._xAxis.maxval)-i.log10(this._xAxis.minval),this._xAxis.xlogscale=0!==this._xAxis.xlogrange?1/this._xAxis.xlogrange:1);for(var e=0;e<this.yAxes_.length;e++){var a=this.yAxes_[e];a.minyval=a.computedValueRange[0],a.maxyval=a.computedValueRange[1],a.yrange=a.maxyval-a.minyval,a.yscale=0!==a.yrange?1/a.yrange:1,(this.dygraph_.getOption("logscale")||a.logscale)&&(a.ylogrange=i.log10(a.maxyval)-i.log10(a.minyval),a.ylogscale=0!==a.ylogrange?1/a.ylogrange:1,isFinite(a.ylogrange)&&!isNaN(a.ylogrange)||console.error("axis "+e+" of graph at "+a.g+" can't be displayed in log scale for range ["+a.minyval+" - "+a.maxyval+"]"))}},u.calcXNormal_=function(t,e,a){return a?(i.log10(t)-i.log10(e.minval))*e.xlogscale:(t-e.minval)*e.scale},u.calcYNormal_=function(t,e,a){return a?(a=1-(i.log10(e)-i.log10(t.minyval))*t.ylogscale,isFinite(a)?a:NaN):1-(e-t.minyval)*t.yscale},u.prototype._evaluateLineCharts=function(){for(var t=this.dygraph_.getOption("stackedGraph"),e=this.dygraph_.getOptionForAxis("logscale","x"),a=0;a<this.points.length;a++){for(var n=this.points[a],i=this.setNames[a],r=this.dygraph_.getOption("connectSeparatedPoints",i),o=this.dygraph_.axisPropertiesForSeries(i),s=this.dygraph_.attributes_.getForSeries("logscale",i),l=0;l<n.length;l++){var h=n[l],d=(h.x=u.calcXNormal_(h.xval,this._xAxis,e),h.yval);t&&(h.y_stacked=u.calcYNormal_(o,h.yval_stacked,s),null===d||isNaN(d)||(d=h.yval_stacked)),null===d&&(d=NaN,r||(h.yval=NaN)),h.y=u.calcYNormal_(o,d,s)}this.dygraph_.dataHandler_.onLineEvaluated(n,o,s)}},u.prototype._evaluateLineTicks=function(){var t,e,a,n,i,r;for(this.xticks=[],t=0;t<this.xTicks_.length;t++)a=(e=this.xTicks_[t]).label,i=(r=!("label_v"in e))?e.v:e.label_v,0<=(n=this.dygraph_.toPercentXCoord(i))&&n<1&&this.xticks.push({pos:n,label:a,has_tick:r});for(this.yticks=[],t=0;t<this.yAxes_.length;t++)for(var o=this.yAxes_[t],s=0;s<o.ticks.length;s++)a=(e=o.ticks[s]).label,i=(r=!("label_v"in e))?e.v:e.label_v,0<(n=this.dygraph_.toPercentYCoord(i,t))&&n<=1&&this.yticks.push({axis:t,pos:n,label:a,has_tick:r})},u.prototype._evaluateAnnotations=function(){var t={};for(i=0;i<this.annotations.length;i++){var e=this.annotations[i];t[e.xval+","+e.series]=e}if(this.annotated_points=[],this.annotations&&this.annotations.length)for(var a=0;a<this.points.length;a++)for(var n=this.points[a],i=0;i<n.length;i++){var r=n[i],o=r.xval+","+r.name;o in t&&(r.annotation=t[o],this.annotated_points.push(r),delete t[o])}},u.prototype.removeAllDatasets=function(){delete this.points,delete this.setNames,delete this.setPointsLengths,delete this.setPointsOffsets,this.points=[],this.setNames=[],this.setPointsLengths=[],this.setPointsOffsets=[]},a.default=u,e.exports=a.default},{"./dygraph-utils":"dygraphs/src/dygraph-utils.js"}],"dygraphs/src/dygraph-options-reference.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var n=null;a.default=n,e.exports=a.default},{}],"dygraphs/src/dygraph-options.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var o=function(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=s(e);if(e&&e.has(t))return e.get(t);var a,n={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t){var r;"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((r=i?Object.getOwnPropertyDescriptor(t,a):null)&&(r.get||r.set)?Object.defineProperty(n,a,r):n[a]=t[a])}n.default=t,e&&e.set(t,n);return n}(t("./dygraph-utils")),i=n(t("./dygraph-default-attrs"));n(t("./dygraph-options-reference"));function n(t){return t&&t.__esModule?t:{default:t}}function s(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(s=function(t){return t?a:e})(t))}function l(t){this.dygraph_=t,this.yAxes_=[],this.xAxis_={},this.series_={},this.global_=this.dygraph_.attrs_,this.user_=this.dygraph_.user_attrs_||{},this.labels_=[],this.highlightSeries_=this.get("highlightSeriesOpts")||{},this.reparseSeries()}l.AXIS_STRING_MAPPINGS_={y:0,Y:0,y1:0,Y1:0,y2:1,Y2:1},l.axisToIndex_=function(t){if("string"==typeof t){if(l.AXIS_STRING_MAPPINGS_.hasOwnProperty(t))return l.AXIS_STRING_MAPPINGS_[t];throw"Unknown axis : "+t}if("number"==typeof t){if(0===t||1===t)return t;throw"Dygraphs only supports two y-axes, indexed from 0-1."}if(t)throw"Unknown axis : "+t;return 0},l.prototype.reparseSeries=function(){var t=this.get("labels");if(t){this.labels_=t.slice(1),this.yAxes_=[{series:[],options:{}}],this.xAxis_={options:{}},this.series_={};for(var e=this.user_.series||{},a=0;a<this.labels_.length;a++){var n=this.labels_[a],i=e[n]||{},r=l.axisToIndex_(i.axis);this.series_[n]={idx:a,yAxis:r,options:i},this.yAxes_[r]?this.yAxes_[r].series.push(n):this.yAxes_[r]={series:[n],options:{}}}t=this.user_.axes||{};o.update(this.yAxes_[0].options,t.y||{}),1<this.yAxes_.length&&o.update(this.yAxes_[1].options,t.y2||{}),o.update(this.xAxis_.options,t.x||{})}},l.prototype.get=function(t){var e=this.getGlobalUser_(t);return null!==e?e:this.getGlobalDefault_(t)},l.prototype.getGlobalUser_=function(t){return this.user_.hasOwnProperty(t)?this.user_[t]:null},l.prototype.getGlobalDefault_=function(t){return this.global_.hasOwnProperty(t)?this.global_[t]:i.default.hasOwnProperty(t)?i.default[t]:null},l.prototype.getForAxis=function(t,e){var a;if("number"==typeof e)a=0===(n=e)?"y":"y2";else{if("y"==(e="y1"==e?"y":e))n=0;else if("y2"==e)n=1;else{if("x"!=e)throw"Unknown axis "+e;n=-1}a=e}var n=-1==n?this.xAxis_:this.yAxes_[n];if(n){n=n.options;if(n.hasOwnProperty(t))return n[t]}if("x"!==e||"logscale"!==t){n=this.getGlobalUser_(t);if(null!==n)return n}e=i.default.axes[a];return e.hasOwnProperty(t)?e[t]:this.getGlobalDefault_(t)},l.prototype.getForSeries=function(t,e){if(e===this.dygraph_.getHighlightSeries()&&this.highlightSeries_.hasOwnProperty(t))return this.highlightSeries_[t];var a,n;if(this.series_.hasOwnProperty(e))return(n=(a=this.series_[e]).options).hasOwnProperty(t)?n[t]:this.getForAxis(t,a.yAxis);throw"Unknown series: "+e},l.prototype.numAxes=function(){return this.yAxes_.length},l.prototype.axisForSeries=function(t){return this.series_[t].yAxis},l.prototype.axisOptions=function(t){return this.yAxes_[t].options},l.prototype.seriesForAxis=function(t){return this.yAxes_[t].series},l.prototype.seriesNames=function(){return this.labels_},a.default=l,e.exports=a.default},{"./dygraph-default-attrs":"dygraphs/src/dygraph-default-attrs.js","./dygraph-options-reference":"dygraphs/src/dygraph-options-reference.js","./dygraph-utils":"dygraphs/src/dygraph-utils.js"}],"dygraphs/src/dygraph-tickers.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.pickDateTickGranularity=a.numericTicks=a.numericLinearTicks=a.getDateAxis=a.dateTicker=a.Granularity=void 0;var P=function(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=o(e);if(e&&e.has(t))return e.get(t);var a,n={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t){var r;"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((r=i?Object.getOwnPropertyDescriptor(t,a):null)&&(r.get||r.set)?Object.defineProperty(n,a,r):n[a]=t[a])}n.default=t,e&&e.set(t,n);return n}(t("./dygraph-utils"));function o(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(o=function(t){return t?a:e})(t))}a.numericLinearTicks=function(t,e,a,n,i,r){return s(t,e,a,function(t){return"logscale"!==t&&n(t)},i,r)};var s=function(t,e,a,n,i,r){var o=n("pixelsPerLabel"),s=[];if(r)for(A=0;A<r.length;A++)s.push({v:r[A]});else{if(n("logscale")){var l=Math.floor(a/o),h=P.binarySearch(t,M,1),d=P.binarySearch(e,M,-1),u=null;if(l/4<=(d=-1==d?M.length-1:d)-(h=-1==h?0:h)){for(var c=d;h<=c;c--){var p=M[c],g=Math.log(p/t)/Math.log(e/t)*a,f={v:p};null===u||Math.abs(g-u.pixel_coord)>=o?u={tickValue:p,pixel_coord:g}:f.label="",s.push(f)}s.reverse()}}if(0===s.length){for(var _,y,v,x,d=n("labelsKMG2")?(_=[1,2,4,8,16,32,64,128,256],16):(_=[1,2,5,10,20,50,100],10),m=Math.ceil(a/o),m=Math.abs(e-t)/m,m=Math.floor(Math.log(m)/Math.log(d)),b=Math.pow(d,m),w=0;w<_.length&&(y=b*_[w],v=Math.floor(t/y)*y,x=Math.ceil(e/y)*y,!(o<a/(l=Math.abs(x-v)/y)));w++);for(x<v&&(y*=-1),A=0;A<=l;A++)s.push({v:v+A*y})}}for(var O=n("axisLabelFormatter"),A=0;A<s.length;A++)void 0===s[A].label&&(s[A].label=O.call(i,s[A].v,0,n,i));return s},y=(a.numericTicks=s,a.dateTicker=function(t,e,a,n,i,r){a=l(t,e,a,n);return 0<=a?d(t,e,a,n,i):[]},{MILLISECONDLY:0,TWO_MILLISECONDLY:1,FIVE_MILLISECONDLY:2,TEN_MILLISECONDLY:3,FIFTY_MILLISECONDLY:4,HUNDRED_MILLISECONDLY:5,FIVE_HUNDRED_MILLISECONDLY:6,SECONDLY:7,TWO_SECONDLY:8,FIVE_SECONDLY:9,TEN_SECONDLY:10,THIRTY_SECONDLY:11,MINUTELY:12,TWO_MINUTELY:13,FIVE_MINUTELY:14,TEN_MINUTELY:15,THIRTY_MINUTELY:16,HOURLY:17,TWO_HOURLY:18,SIX_HOURLY:19,DAILY:20,TWO_DAILY:21,WEEKLY:22,MONTHLY:23,QUARTERLY:24,BIANNUAL:25,ANNUAL:26,DECADAL:27,CENTENNIAL:28,NUM_GRANULARITIES:29});a.Granularity=y;var v=0,x=1,m=2,b=3,w=4,O=5,A=6,S=7,L=[],M=(L[y.MILLISECONDLY]={datefield:A,step:1,spacing:1},L[y.TWO_MILLISECONDLY]={datefield:A,step:2,spacing:2},L[y.FIVE_MILLISECONDLY]={datefield:A,step:5,spacing:5},L[y.TEN_MILLISECONDLY]={datefield:A,step:10,spacing:10},L[y.FIFTY_MILLISECONDLY]={datefield:A,step:50,spacing:50},L[y.HUNDRED_MILLISECONDLY]={datefield:A,step:100,spacing:100},L[y.FIVE_HUNDRED_MILLISECONDLY]={datefield:A,step:500,spacing:500},L[y.SECONDLY]={datefield:O,step:1,spacing:1e3},L[y.TWO_SECONDLY]={datefield:O,step:2,spacing:2e3},L[y.FIVE_SECONDLY]={datefield:O,step:5,spacing:5e3},L[y.TEN_SECONDLY]={datefield:O,step:10,spacing:1e4},L[y.THIRTY_SECONDLY]={datefield:O,step:30,spacing:3e4},L[y.MINUTELY]={datefield:w,step:1,spacing:6e4},L[y.TWO_MINUTELY]={datefield:w,step:2,spacing:12e4},L[y.FIVE_MINUTELY]={datefield:w,step:5,spacing:3e5},L[y.TEN_MINUTELY]={datefield:w,step:10,spacing:6e5},L[y.THIRTY_MINUTELY]={datefield:w,step:30,spacing:18e5},L[y.HOURLY]={datefield:b,step:1,spacing:36e5},L[y.TWO_HOURLY]={datefield:b,step:2,spacing:72e5},L[y.SIX_HOURLY]={datefield:b,step:6,spacing:216e5},L[y.DAILY]={datefield:m,step:1,spacing:864e5},L[y.TWO_DAILY]={datefield:m,step:2,spacing:1728e5},L[y.WEEKLY]={datefield:m,step:7,spacing:6048e5},L[y.MONTHLY]={datefield:x,step:1,spacing:2629746e3},L[y.QUARTERLY]={datefield:x,step:3,spacing:7889238e3},L[y.BIANNUAL]={datefield:x,step:6,spacing:15778476e3},L[y.ANNUAL]={datefield:v,step:1,spacing:31556952e3},L[y.DECADAL]={datefield:v,step:10,spacing:31556952e4},L[y.CENTENNIAL]={datefield:v,step:100,spacing:31556952e5},function(){for(var t=[],e=-39;e<=39;e++)for(var a=Math.pow(10,e),n=1;n<=9;n++)t.push(a*n);return t}()),l=function(t,e,a,n){for(var i=n("pixelsPerLabel"),r=0;r<y.NUM_GRANULARITIES;r++)if(i<=a/h(t,e,r))return r;return-1},h=(a.pickDateTickGranularity=l,function(t,e,a){a=L[a].spacing;return Math.round((e-t)/a)}),d=function(t,e,a,n,i){var r=n("axisLabelFormatter"),o=n("labelsUTC")?P.DateAccessorsUTC:P.DateAccessorsLocal,s=L[a].datefield,l=L[a].step,h=L[a].spacing,d=new Date(t),u=[],c=(u[v]=o.getFullYear(d),u[x]=o.getMonth(d),u[m]=o.getDate(d),u[b]=o.getHours(d),u[w]=o.getMinutes(d),u[O]=o.getSeconds(d),u[A]=o.getMilliseconds(d),u[s]%l);a==y.WEEKLY&&(c=o.getDay(d)),u[s]-=c;for(var p=s+1;p<S;p++)u[p]=p===m?1:0;var g=[],f=o.makeDate.apply(null,u),_=f.getTime();if(a<=y.HOURLY)for(_<t&&(_+=h,f=new Date(_));_<=e;)g.push({v:_,label:r.call(i,f,a,n,i)}),_+=h,f=new Date(_);else for(_<t&&(u[s]+=l,_=(f=o.makeDate.apply(null,u)).getTime());_<=e;)(y.DAILY<=a||o.getHours(f)%l==0)&&g.push({v:_,label:r.call(i,f,a,n,i)}),u[s]+=l,_=(f=o.makeDate.apply(null,u)).getTime();return g};a.getDateAxis=d},{"./dygraph-utils":"dygraphs/src/dygraph-utils.js"}],"dygraphs/src/dygraph-utils.js":[function(t,F,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.HORIZONTAL=e.DateAccessorsUTC=e.DateAccessorsLocal=e.DOT_DASH_LINE=e.DOTTED_LINE=e.DASHED_LINE=e.Circles=void 0,e.Iterator=v,e.addEvent=e.VERTICAL=e.LOG_SCALE=e.LN_TEN=void 0,e.binarySearch=function t(e,a,n,i,r){null!=i&&null!=r||(i=0,r=a.length-1);if(r<i)return-1;null==n&&(n=0);var o=function(t){return 0<=t&&t<a.length};var s=parseInt((i+r)/2,10);var l=a[s];var h;{if(l==e)return s;if(e<l)return 0<n&&o(h=s-1)&&a[h]<e?s:t(e,a,n,i,s-1);if(l<e)return n<0&&o(h=s+1)&&a[h]>e?s:t(e,a,n,s+1,r)}return-1},e.cancelEvent=function(t){(t=t||window.event).stopPropagation&&t.stopPropagation();t.preventDefault&&t.preventDefault();return t.cancelBubble=!0,t.cancel=!0,t.returnValue=!1},e.clone=function t(e){var a=[];for(var n=0;n<e.length;n++)y(e[n])?a.push(t(e[n])):a.push(e[n]);return a},e.createCanvas=function(){return document.createElement("canvas")},e.createIterator=function(t,e,a,n){return new v(t,e,a,n)},e.dateAxisLabelFormatter=function(t,e,a){var a=a("labelsUTC")?p:c,n=a.getFullYear(t),i=a.getMonth(t),r=a.getDate(t),o=a.getHours(t),s=a.getMinutes(t),l=a.getSeconds(t),a=a.getMilliseconds(t);return e>=h.Granularity.DECADAL?""+n:e>=h.Granularity.MONTHLY?E[i]+"&#160;"+n:0===3600*o+60*s+l+.001*a||e>=h.Granularity.DAILY?d(r)+"&#160;"+E[i]:e<h.Granularity.SECONDLY?(t=""+a,d(l)+"."+("000"+t).substring(t.length)):e>h.Granularity.MINUTELY?g(o,s,l,0):g(o,s,l,a)},e.dateParser=function(t){var e,a;if((-1==t.search("-")||-1!=t.search("T")||-1!=t.search("Z"))&&(a=l(t))&&!isNaN(a))return a;if(-1!=t.search("-")){for(e=t.replace("-","/","g");-1!=e.search("-");)e=e.replace("-","/");a=l(e)}else a=l(t);a&&!isNaN(a)||console.error("Couldn't parse "+t+" as a date");return a},e.dateStrToMillis=l,e.dateString_=s,e.dateValueFormatter=function(t,e){return s(t,e("labelsUTC"))},e.detectLineDelimiter=function(t){for(var e=0;e<t.length;e++){var a=t.charAt(e);if("\r"===a)return e+1<t.length&&"\n"===t.charAt(e+1)?"\r\n":a;if("\n"===a)return e+1<t.length&&"\r"===t.charAt(e+1)?"\n\r":a}return null},e.dragGetX_=function(t,e){return i(t)-e.px},e.dragGetY_=function(t,e){return r(t)-e.py},e.findPos=function(t){var t=t.getBoundingClientRect(),e=window,a=document.documentElement;return{x:t.left+(e.pageXOffset||a.scrollLeft),y:t.top+(e.pageYOffset||a.scrollTop)}},e.floatFormat=u,e.getContext=void 0,e.getContextPixelRatio=function(t){try{var e=window.devicePixelRatio,a=t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1;return void 0!==e?e/a:1}catch(t){return 1}},e.hmsString_=g,e.hsvToRGB=function(t,e,a){var n,i,r;if(0===e)r=i=n=a;else{var o=Math.floor(6*t),t=6*t-o,s=a*(1-e),l=a*(1-e*t),h=a*(1-e*(1-t));switch(o){case 1:n=l,i=a,r=s;break;case 2:n=s,i=a,r=h;break;case 3:n=s,i=l,r=a;break;case 4:n=h,i=s,r=a;break;case 5:n=a,i=s,r=l;break;case 6:case 0:n=a,i=h,r=s}}return n=Math.floor(255*n+.5),i=Math.floor(255*i+.5),r=Math.floor(255*r+.5),"rgb("+n+","+i+","+r+")"},e.isArrayLike=y,e.isCanvasSupported=function(t){try{(t||document.createElement("canvas")).getContext("2d")}catch(t){return!1}return!0},e.isDateLike=function(t){return null!==t&&"object"==typeof t&&"function"==typeof t.getTime},e.isNodeContainedBy=function(t,e){if(null===e||null===t)return!1;var a=t;for(;a&&a!==e;)a=a.parentNode;return a===e},e.isOK=function(t){return!!t&&!isNaN(t)},e.isPixelChangingOptionList=function(t,e){var a={};if(t)for(var n=1;n<t.length;n++)a[t[n]]=!0;function i(t){for(var e in t)if(t.hasOwnProperty(e)&&!m[e])return 1}for(var r in e)if(e.hasOwnProperty(r))if("highlightSeriesOpts"==r||a[r]&&!e.series){if(i(e[r]))return!0}else if("series"==r||"axes"==r){var o,s=e[r];for(o in s)if(s.hasOwnProperty(o)&&i(s[o]))return!0}else if(!m[r])return!0;return!1},e.isValidPoint=function(t,e){return!!t&&null!==t.yval&&null!==t.x&&void 0!==t.x&&null!==t.y&&void 0!==t.y&&!(isNaN(t.x)||!e&&isNaN(t.y))},e.logRangeFraction=e.log10=void 0,e.numberAxisLabelFormatter=function(t,e,a){return D.call(this,t,a)},e.numberValueFormatter=D,e.pageX=i,e.pageY=r,e.parseFloat_=function(t,e,a){var n=parseFloat(t);if(!isNaN(n))return n;if(!/^ *$/.test(t)){if(/^ *nan *$/i.test(t))return NaN;n="Unable to parse '"+t+"' as a number";void 0!==a&&void 0!==e&&(n+=" on line "+(1+(e||0))+" ('"+a+"') of CSV."),console.error(n)}return null},e.pow=b,e.removeEvent=function(t,e,a){t.removeEventListener(e,a,!1)},e.repeatAndCleanup=function(a,t,n,i){var r,o,s=0,l=(new Date).getTime();a(s),(1==t?i:(o=t-1,function e(){t<=s||x.call(window,function(){var t=(new Date).getTime(),t=(r=s,(s=Math.floor((t-l)/n))-r);(o<s+t||o<=s?(a(o),i):(0!=t&&a(s),e))()})}))()},e.requestAnimFrame=void 0,e.round_=f,e.setupDOMready_=function(a){{var n;"undefined"!=typeof document&&(n=function(){if(!k){k=!0,a.onDOMready=R,document.removeEventListener("DOMContentLoaded",n,!1),window.removeEventListener("load",n,!1);for(var t=0;t<N.length;++t)N[t]();N=null}},a.onDOMready=function(t){var e;return("complete"===document.readyState?a.onDOMready=R:(a.onDOMready=e=function(t){return"function"==typeof t&&N.push(t),!1},document.addEventListener("DOMContentLoaded",n,!1),window.addEventListener("load",n,!1),"complete"===document.readyState?(n(),a.onDOMready=R):e))(t)})}},e.toRGB_=function(t){var e=A(t);return e||((e=document.createElement("div")).style.backgroundColor=t,e.style.visibility="hidden",document.body.appendChild(e),t=window.getComputedStyle(e,null).backgroundColor,document.body.removeChild(e),A(t))},e.type=function(t){return null===t?"null":typeof t},e.typeArrayLike=function(t){var e;return null===t?"null":("object"==(e=typeof t)||"function"==e&&"function"==typeof t.item)&&"number"==typeof t.length&&3!==t.nodeType&&4!==t.nodeType?"array":e},e.update=function(t,e){if(null!=e)for(var a in e)e.hasOwnProperty(a)&&(t[a]=e[a]);return t},e.updateDeep=function t(e,a){if(null!=a)for(var n in a){var i;a.hasOwnProperty(n)&&(null===(i=a[n])?e[n]=null:y(i)?e[n]=i.slice():!_(i)&&"object"==typeof i?("object"==typeof e[n]&&null!==e[n]||(e[n]={}),t(e[n],i)):e[n]=i)}return e},e.zeropad=d;var h=function(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=o(e);if(e&&e.has(t))return e.get(t);var a,n={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t){var r;"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((r=i?Object.getOwnPropertyDescriptor(t,a):null)&&(r.get||r.set)?Object.defineProperty(n,a,r):n[a]=t[a])}n.default=t,e&&e.set(t,n);return n}(t("./dygraph-tickers"));function o(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(o=function(t){return t?a:e})(t))}function n(t){return Math.log(t)/a}e.LOG_SCALE=10;var a=Math.log(10);e.LN_TEN=a,e.log10=n,e.logRangeFraction=function(t,e,a){t=n(t),e=n(e);return Math.pow(10,t+a*(e-t))},e.DOTTED_LINE=[2,2],e.DASHED_LINE=[7,3],e.DOT_DASH_LINE=[7,2,2,2],e.HORIZONTAL=1,e.VERTICAL=2,e.getContext=function(t){return t.getContext("2d")};function i(t){return!t.pageX||t.pageX<0?0:t.pageX}function r(t){return!t.pageY||t.pageY<0?0:t.pageY}function u(t,e){e=Math.min(Math.max(1,e||2),21);return Math.abs(t)<.001&&0!==t?t.toExponential(e-1):t.toPrecision(e)}function d(t){return t<10?"0"+t:""+t}e.addEvent=function(t,e,a){t.addEventListener(e,a,!1)};var c={getFullYear:function(t){return t.getFullYear()},getMonth:function(t){return t.getMonth()},getDate:function(t){return t.getDate()},getHours:function(t){return t.getHours()},getMinutes:function(t){return t.getMinutes()},getSeconds:function(t){return t.getSeconds()},getMilliseconds:function(t){return t.getMilliseconds()},getDay:function(t){return t.getDay()},makeDate:function(t,e,a,n,i,r,o){return new Date(t,e,a,n,i,r,o)}},p=(e.DateAccessorsLocal=c,{getFullYear:function(t){return t.getUTCFullYear()},getMonth:function(t){return t.getUTCMonth()},getDate:function(t){return t.getUTCDate()},getHours:function(t){return t.getUTCHours()},getMinutes:function(t){return t.getUTCMinutes()},getSeconds:function(t){return t.getUTCSeconds()},getMilliseconds:function(t){return t.getUTCMilliseconds()},getDay:function(t){return t.getUTCDay()},makeDate:function(t,e,a,n,i,r,o){return new Date(Date.UTC(t,e,a,n,i,r,o))}});function g(t,e,a,n){t=d(t)+":"+d(e);return a&&(t+=":"+d(a),n)&&(t+="."+("000"+(e=""+n)).substring(e.length)),t}function s(t,e){var e=e?p:c,t=new Date(t),a=e.getFullYear(t),n=e.getMonth(t),i=e.getDate(t),r=e.getHours(t),o=e.getMinutes(t),s=e.getSeconds(t),e=e.getMilliseconds(t),t=""+a+"/"+d(n+1)+"/"+d(i);return 3600*r+60*o+s+.001*e&&(t+=" "+g(r,o,s,e)),t}function f(t,e){e=Math.pow(10,e);return Math.round(t*e)/e}function l(t){return new Date(t).getTime()}e.DateAccessorsUTC=p;var _="undefined"!=typeof Node&&null!==Node&&"object"==typeof Node?function(t){return t instanceof Node}:function(t){return"object"==typeof t&&"number"==typeof t.nodeType&&"string"==typeof t.nodeName};function y(t){var e=typeof t;return null!==t&&("object"==e||"function"==e&&"function"==typeof t.item)&&"number"==typeof t.length&&3!==t.nodeType&&4!==t.nodeType}function v(t,e,a,n){e=e||0,a=a||t.length,this.hasNext=!0,this.peek=null,this.start_=e,this.array_=t,this.predicate_=n,this.end_=Math.min(t.length,e+a),this.nextIdx_=e-1,this.next()}v.prototype.next=function(){if(!this.hasNext)return null;for(var t=this.peek,e=this.nextIdx_+1,a=!1;e<this.end_;){if(!this.predicate_||this.predicate_(this.array_,e)){this.peek=this.array_[e],a=!0;break}e++}return this.nextIdx_=e,a||(this.hasNext=!1,this.peek=null),t};var x=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){window.setTimeout(t,1e3/60)};e.requestAnimFrame=x;var m={annotationClickHandler:!0,annotationDblClickHandler:!0,annotationMouseOutHandler:!0,annotationMouseOverHandler:!0,axisLineColor:!0,axisLineWidth:!0,clickCallback:!0,drawCallback:!0,drawHighlightPointCallback:!0,drawPoints:!0,drawPointCallback:!0,drawGrid:!0,fillAlpha:!0,gridLineColor:!0,gridLineWidth:!0,hideOverlayOnMouseOut:!0,highlightCallback:!0,highlightCircleSize:!0,interactionModel:!0,labelsDiv:!0,labelsKMB:!0,labelsKMG2:!0,labelsSeparateLines:!0,labelsShowZeroValues:!0,legend:!0,panEdgeFraction:!0,pixelsPerYLabel:!0,pointClickCallback:!0,pointSize:!0,rangeSelectorPlotFillColor:!0,rangeSelectorPlotFillGradientColor:!0,rangeSelectorPlotStrokeColor:!0,rangeSelectorBackgroundStrokeColor:!0,rangeSelectorBackgroundLineWidth:!0,rangeSelectorPlotLineWidth:!0,rangeSelectorForegroundStrokeColor:!0,rangeSelectorForegroundLineWidth:!0,rangeSelectorAlpha:!0,showLabelsOnHighlight:!0,showRoller:!0,strokeWidth:!0,underlayCallback:!0,unhighlightCallback:!0,zoomCallback:!0};function b(t,e){return e<0?1/Math.pow(t,-e):Math.pow(t,e)}e.Circles={DEFAULT:function(t,e,a,n,i,r,o){a.beginPath(),a.fillStyle=r,a.arc(n,i,o,0,2*Math.PI,!1),a.fill()}};var w=/^#([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})?$/,O=/^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})(?:,\s*([01](?:\.\d+)?))?\)$/;function A(t){var e,a,n,i,r=null;if(e=w.exec(t))a=parseInt(e[1],16),n=parseInt(e[2],16),i=parseInt(e[3],16),e[4]&&(r=parseInt(e[4],16));else{if(!(e=O.exec(t)))return null;a=parseInt(e[1],10),n=parseInt(e[2],10),i=parseInt(e[3],10),e[4]&&(r=parseFloat(e[4]))}return null!==r?{r:a,g:n,b:i,a:r}:{r:a,g:n,b:i}}var P=["k","M","G","T","P","E","Z","Y"],S=["m","Вµ","n","p","f","a","z","y"],L=["Ki","Mi","Gi","Ti","Pi","Ei","Zi","Yi"],M=["p-10","p-20","p-30","p-40","p-50","p-60","p-70","p-80"],C=["K","M","G","T","P","E","Z","Y"],T=S;function D(t,e){var a=e("sigFigs");if(null!==a)return u(t,a);if(0===t)return"0";var n=e("digitsAfterDecimal"),i=e("maxNumberWidth"),a=e("labelsKMB"),e=e("labelsKMG2"),r=Math.abs(t);if(a||e){var o,s,l,h=[],d=[];if(a&&(o=1e3,h=P,d=S),e&&(o=1024,h=L,d=M,a)&&(h=C,d=T),o<=r){for(l=h.length;0<l;)if(s=b(o,l),--l,s<=r)return r/s>=Math.pow(10,i)?t.toExponential(n):f(t/s,n)+h[l]}else if(r<1){for(l=0;l<d.length&&!(1<=r*(s=b(o,++l))););return r*s<Math.pow(10,-n)?t.toExponential(n):f(t*s,n)+d[l-1]}}return r>=Math.pow(10,i)||r<Math.pow(10,-n)?t.toExponential(n):""+f(t,n)}var E=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];var N=[],k=!1;function R(t){return"function"==typeof t&&t(),!0}},{"./dygraph-tickers":"dygraphs/src/dygraph-tickers.js"}],"dygraphs/src/dygraph.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var i=A(t("./dygraph-layout")),r=A(t("./dygraph-canvas")),u=A(t("./dygraph-options")),n=A(t("./dygraph-interaction-model")),v=O(t("./dygraph-tickers")),M=O(t("./dygraph-utils")),c=A(t("./dygraph-default-attrs")),o=(A(t("./dygraph-options-reference")),A(t("./iframe-tarp"))),s=A(t("./datahandler/default")),l=A(t("./datahandler/bars-error")),h=A(t("./datahandler/bars-custom")),d=A(t("./datahandler/default-fractions")),p=A(t("./datahandler/bars-fractions")),g=A(t("./datahandler/bars")),f=A(t("./plugins/annotations")),_=A(t("./plugins/axes")),y=A(t("./plugins/chart-labels")),x=A(t("./plugins/grid")),m=A(t("./plugins/legend")),b=A(t("./plugins/range-selector")),t=A(t("./dygraph-gviz"));function w(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(w=function(t){return t?a:e})(t))}function O(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=w(e);if(e&&e.has(t))return e.get(t);var a,n,i={},r=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t)"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((n=r?Object.getOwnPropertyDescriptor(t,a):null)&&(n.get||n.set)?Object.defineProperty(i,a,n):i[a]=t[a]);return i.default=t,e&&e.set(t,i),i}function A(t){return t&&t.__esModule?t:{default:t}}function P(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var a=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=a){var n,i,r,o,s=[],l=!0,h=!1;try{if(r=(a=a.call(t)).next,0===e){if(Object(a)!==a)return;l=!1}else for(;!(l=(n=r.call(a)).done)&&(s.push(n.value),s.length!==e);l=!0);}catch(t){h=!0,i=t}finally{try{if(!l&&null!=a.return&&(o=a.return(),Object(o)!==o))return}finally{if(h)throw i}}return s}}(t,e)||function(t,e){var a;if(t)return"string"==typeof t?S(t,e):"Map"===(a="Object"===(a=Object.prototype.toString.call(t).slice(8,-1))&&t.constructor?t.constructor.name:a)||"Set"===a?Array.from(t):"Arguments"===a||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?S(t,e):void 0}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function S(t,e){(null==e||e>t.length)&&(e=t.length);for(var a=0,n=new Array(e);a<e;a++)n[a]=t[a];return n}function L(t,e,a){this.__init__(t,e,a)}L.NAME="Dygraph",L.VERSION="2.2.2-alpha.0";var C={};(L._require=function(t){return t in C?C[t]:L._require._b(t)})._b=null,L._require.add=function(t,e){C[t]=e},L.DEFAULT_ROLL_PERIOD=1,L.DEFAULT_WIDTH=480,L.DEFAULT_HEIGHT=320,L.ANIMATION_STEPS=12,L.ANIMATION_DURATION=200,L.Plotters=r.default._Plotters,L.addedAnnotationCSS=!1,L.prototype.__init__=function(t,e,a){if(this.is_initial_draw_=!0,this.readyFns_=[],a=L.copyUserAttrs_(a=null==a?{}:a),!(t="string"==typeof t?document.getElementById(t):t))throw new Error("Constructing dygraph with a non-existent div!");this.maindiv_=t,this.file_=e,this.rollPeriod_=a.rollPeriod||L.DEFAULT_ROLL_PERIOD,this.previousVerticalX_=-1,this.fractions_=a.fractions||!1,this.dateWindow_=a.dateWindow||null,this.annotations_=[],t.innerHTML="";for(var e=window.getComputedStyle(t,null),n=("0px"===e.paddingLeft&&"0px"===e.paddingRight&&"0px"===e.paddingTop&&"0px"===e.paddingBottom||console.error("Main div contains padding; graph will misbehave"),""===t.style.width&&a.width&&(t.style.width=a.width+"px"),""===t.style.height&&a.height&&(t.style.height=a.height+"px"),""===t.style.height&&0===t.clientHeight&&(t.style.height=L.DEFAULT_HEIGHT+"px",""===t.style.width)&&(t.style.width=L.DEFAULT_WIDTH+"px"),this.width_=t.clientWidth||a.width||0,this.height_=t.clientHeight||a.height||0,a.stackedGraph&&(a.fillGraph=!0),this.user_attrs_={},M.update(this.user_attrs_,a),this.attrs_={},M.updateDeep(this.attrs_,c.default),this.boundaryIds_=[],this.setIndexByName_={},this.datasetIndex_=[],this.registeredEvents_=[],this.eventListeners_={},this.attributes_=new u.default(this),this.createInterface_(),this.plugins_=[],L.PLUGINS.concat(this.getOption("plugins"))),i=0;i<n.length;i++){var r=n[i],r=void 0!==r.activate?r:new r,o={plugin:r,events:{},options:{},pluginOptions:{}},s=r.activate(this);for(l in s)s.hasOwnProperty(l)&&(o.events[l]=s[l]);this.plugins_.push(o)}for(i=0;i<this.plugins_.length;i++){var l,h,d=this.plugins_[i];for(l in d.events)d.events.hasOwnProperty(l)&&(h=d.events[l],h=[d.plugin,h],l in this.eventListeners_?this.eventListeners_[l].push(h):this.eventListeners_[l]=[h])}this.createDragInterface_(),this.start_()},L.prototype.cascadeEvents_=function(t,e){if(!(t in this.eventListeners_))return!1;var a={dygraph:this,cancelable:!1,defaultPrevented:!1,preventDefault:function(){if(!a.cancelable)throw"Cannot call preventDefault on non-cancelable event.";a.defaultPrevented=!0},propagationStopped:!1,stopPropagation:function(){a.propagationStopped=!0}},n=(M.update(a,e),this.eventListeners_[t]);if(n)for(var i=n.length-1;0<=i;i--){var r=n[i][0];if(n[i][1].call(r,a),a.propagationStopped)break}return a.defaultPrevented},L.prototype.getPluginInstance_=function(t){for(var e=0;e<this.plugins_.length;e++){var a=this.plugins_[e];if(a.plugin instanceof t)return a.plugin}return null},L.prototype.isZoomed=function(t){var e=!!this.dateWindow_;if("x"===t)return e;var a=0<=this.axes_.map(function(t){return!!t.valueRange}).indexOf(!0);if(null==t)return e||a;if("y"===t)return a;throw new Error("axis parameter is [".concat(t,"] must be null, 'x' or 'y'."))},L.prototype.toString=function(){var t=this.maindiv_;return"[Dygraph "+(t&&t.id?t.id:t)+"]"},L.prototype.attr_=function(t,e){return e?this.attributes_.getForSeries(t,e):this.attributes_.get(t)},L.prototype.getOption=function(t,e){return this.attr_(t,e)},L.prototype.getNumericOption=function(t,e){return this.getOption(t,e)},L.prototype.getStringOption=function(t,e){return this.getOption(t,e)},L.prototype.getBooleanOption=function(t,e){return this.getOption(t,e)},L.prototype.getFunctionOption=function(t,e){return this.getOption(t,e)},L.prototype.getOptionForAxis=function(t,e){return this.attributes_.getForAxis(t,e)},L.prototype.optionsViewForAxis_=function(a){var n=this;return function(t){var e=n.user_attrs_.axes;return e&&e[a]&&e[a].hasOwnProperty(t)?e[a][t]:("x"!==a||"logscale"!==t)&&(void 0!==n.user_attrs_[t]?n.user_attrs_[t]:(e=n.attrs_.axes)&&e[a]&&e[a].hasOwnProperty(t)?e[a][t]:"y"==a&&n.axes_[0].hasOwnProperty(t)?n.axes_[0][t]:"y2"==a&&n.axes_[1].hasOwnProperty(t)?n.axes_[1][t]:n.attr_(t))}},L.prototype.rollPeriod=function(){return this.rollPeriod_},L.prototype.xAxisRange=function(){return this.dateWindow_||this.xAxisExtremes()},L.prototype.xAxisExtremes=function(){var t,e,a,n=this.getNumericOption("xRangePad")/this.plotter_.area.w;return 0===this.numRows()?[0-n,1+n]:(t=this.rawData_[0][0],e=this.rawData_[this.rawData_.length-1][0],n&&(t-=(a=e-t)*n,e+=a*n),[t,e])},L.prototype.yAxisExtremes=function(){var t=this.gatherDatasets_(this.rolledSeries_,null).extremes,e=this.axes_,t=(this.computeYAxisRanges_(t),this.axes_);return this.axes_=e,t.map(function(t){return t.extremeRange})},L.prototype.yAxisRange=function(t){return(t=void 0===t?0:t)<0||t>=this.axes_.length?null:[(t=this.axes_[t]).computedValueRange[0],t.computedValueRange[1]]},L.prototype.yAxisRanges=function(){for(var t=[],e=0;e<this.axes_.length;e++)t.push(this.yAxisRange(e));return t},L.prototype.toDomCoords=function(t,e,a){return[this.toDomXCoord(t),this.toDomYCoord(e,a)]},L.prototype.toDomXCoord=function(t){var e,a;return null===t?null:(e=this.plotter_.area,a=this.xAxisRange(),e.x+(t-a[0])/(a[1]-a[0])*e.w)},L.prototype.toDomYCoord=function(t,e){t=this.toPercentYCoord(t,e);return null===t?null:(e=this.plotter_.area).y+t*e.h},L.prototype.toDataCoords=function(t,e,a){return[this.toDataXCoord(t),this.toDataYCoord(e,a)]},L.prototype.toDataXCoord=function(t){var e,a,n;return null===t?null:(e=this.plotter_.area,a=this.xAxisRange(),this.attributes_.getForAxis("logscale","x")?(n=(t-e.x)/e.w,M.logRangeFraction(a[0],a[1],n)):a[0]+(t-e.x)/e.w*(a[1]-a[0]))},L.prototype.toDataYCoord=function(t,e){var a,n;return null===t?null:(a=this.plotter_.area,n=this.yAxisRange(e),this.attributes_.getForAxis("logscale",e=void 0===e?0:e)?(e=(t-a.y)/a.h,M.logRangeFraction(n[1],n[0],e)):n[0]+(a.y+a.h-t)/a.h*(n[1]-n[0]))},L.prototype.toPercentYCoord=function(t,e){var a,n;return null===t?null:(a=this.yAxisRange(e=void 0===e?0:e),this.attributes_.getForAxis("logscale",e)?(e=M.log10(a[0]),((n=M.log10(a[1]))-M.log10(t))/(n-e)):(a[1]-t)/(a[1]-a[0]))},L.prototype.toPercentXCoord=function(t){var e,a,n;return null===t?null:(e=this.xAxisRange(),!0===this.attributes_.getForAxis("logscale","x")?(a=M.log10(e[0]),n=M.log10(e[1]),(M.log10(t)-a)/(n-a)):(t-e[0])/(e[1]-e[0]))},L.prototype.numColumns=function(){return this.rawData_?(this.rawData_[0]||this.attr_("labels")).length:0},L.prototype.numRows=function(){return this.rawData_?this.rawData_.length:0},L.prototype.getValue=function(t,e){return t<0||t>=this.rawData_.length||e<0||e>=this.rawData_[t].length?null:this.rawData_[t][e]},L.prototype.createInterface_=function(){var t,e=this.maindiv_,n=(this.graphDiv=document.createElement("div"),this.graphDiv.style.textAlign="left",this.graphDiv.style.position="relative",e.appendChild(this.graphDiv),this.canvas_=M.createCanvas(),this.canvas_.style.position="absolute",this.canvas_.style.top=0,this.canvas_.style.left=0,this.hidden_=this.createPlotKitCanvas_(this.canvas_),this.canvas_ctx_=M.getContext(this.canvas_),this.hidden_ctx_=M.getContext(this.hidden_),this.resizeElements_(),this.graphDiv.appendChild(this.hidden_),this.graphDiv.appendChild(this.canvas_),this.mouseEventElement_=this.createMouseEventElement_(),this.layout_=new i.default(this),this);this.mouseMoveHandler_=function(t){n.mouseMove_(t)},this.mouseOutHandler_=function(t){var e=t.target||t.fromElement,a=t.relatedTarget||t.toElement;M.isNodeContainedBy(e,n.graphDiv)&&!M.isNodeContainedBy(a,n.graphDiv)&&n.mouseOut_(t)},this.addAndTrackEvent(window,"mouseout",this.mouseOutHandler_),this.addAndTrackEvent(this.mouseEventElement_,"mousemove",this.mouseMoveHandler_),this.resizeHandler_||(this.resizeHandler_=function(t){n.resize()},this.addAndTrackEvent(window,"resize",this.resizeHandler_),this.resizeObserver_=null,t=this.getStringOption("resizable"),"undefined"==typeof ResizeObserver&&"no"!==t&&(console.error("ResizeObserver unavailable; ignoring resizable property"),t="no"),"horizontal"===t||"vertical"===t||"both"===t?e.style.resize=t:"passive"!==t&&(t="no"),"no"!==t&&(window.getComputedStyle(e).overflow,"visible"===window.getComputedStyle(e).overflow&&(e.style.overflow="hidden"),this.resizeObserver_=new ResizeObserver(this.resizeHandler_),this.resizeObserver_.observe(e)))},L.prototype.resizeElements_=function(){this.graphDiv.style.width=this.width_+"px",this.graphDiv.style.height=this.height_+"px";var t=this.getNumericOption("pixelRatio"),e=t||M.getContextPixelRatio(this.canvas_ctx_),e=(this.canvas_.width=this.width_*e,this.canvas_.height=this.height_*e,this.canvas_.style.width=this.width_+"px",this.canvas_.style.height=this.height_+"px",1!==e&&this.canvas_ctx_.scale(e,e),t||M.getContextPixelRatio(this.hidden_ctx_));this.hidden_.width=this.width_*e,this.hidden_.height=this.height_*e,this.hidden_.style.width=this.width_+"px",this.hidden_.style.height=this.height_+"px",1!==e&&this.hidden_ctx_.scale(e,e)},L.prototype.destroy=function(){this.canvas_ctx_.restore(),this.hidden_ctx_.restore();for(var t=this.plugins_.length-1;0<=t;t--){var e=this.plugins_.pop();e.plugin.destroy&&e.plugin.destroy()}function a(t){for(;t.hasChildNodes();)a(t.firstChild),t.removeChild(t.firstChild)}function n(t){for(var e in t)"object"==typeof t[e]&&(t[e]=null)}this.removeTrackedEvents_(),M.removeEvent(window,"mouseout",this.mouseOutHandler_),M.removeEvent(this.mouseEventElement_,"mousemove",this.mouseMoveHandler_),this.resizeObserver_&&(this.resizeObserver_.disconnect(),this.resizeObserver_=null),M.removeEvent(window,"resize",this.resizeHandler_),this.resizeHandler_=null,a(this.maindiv_);n(this.layout_),n(this.plotter_),n(this)},L.prototype.createPlotKitCanvas_=function(t){var e=M.createCanvas();return e.style.position="absolute",e.style.top=t.style.top,e.style.left=t.style.left,e.width=this.width_,e.height=this.height_,e.style.width=this.width_+"px",e.style.height=this.height_+"px",e},L.prototype.createMouseEventElement_=function(){return this.canvas_},L.prototype.setColors_=function(){for(var t,e,a,n=this.getLabels(),i=n.length-1,r=(this.colors_=[],this.colorsMap_={},this.getNumericOption("colorSaturation")||1),o=this.getNumericOption("colorValue")||.5,s=Math.ceil(i/2),l=this.getOption("colors"),h=this.visibility(),d=0;d<i;d++)h[d]&&(t=n[d+1],a=(a=this.attributes_.getForSeries("color",t))||(l?l[d%l.length]:(e=d%2?s+(d+1)/2:Math.ceil((d+1)/2),M.hsvToRGB(+e/(1+i),r,o))),this.colors_.push(a),this.colorsMap_[t]=a)},L.prototype.getColors=function(){return this.colors_},L.prototype.getPropertiesForSeries=function(t){for(var e=-1,a=this.getLabels(),n=1;n<a.length;n++)if(a[n]==t){e=n;break}return-1==e?null:{name:t,column:e,visible:this.visibility()[e-1],color:this.colorsMap_[t],axis:1+this.attributes_.axisForSeries(t)}},L.prototype.createRollInterface_=function(){var t=this.roller_,e=(t||(this.roller_=t=document.createElement("input"),t.type="text",t.style.display="none",t.className="dygraph-roller",this.graphDiv.appendChild(t)),this.getBooleanOption("showRoller")?"block":"none"),a=this.getArea(),a={top:a.y+a.h-25+"px",left:a.x+1+"px",display:e},n=(t.size="2",t.value=this.rollPeriod_,M.update(t.style,a),this);t.onchange=function(){return n.adjustRoll(t.value)}},L.prototype.createDragInterface_=function(){var t,a={isZooming:!1,isPanning:!1,is2DPan:!1,dragStartX:null,dragStartY:null,dragEndX:null,dragEndY:null,dragDirection:null,prevEndX:null,prevEndY:null,prevDragDirection:null,cancelNextDblclick:!1,initialLeftmostDate:null,xUnitsPerPixel:null,dateRange:null,px:0,py:0,boundedDates:null,boundedValues:null,tarp:new o.default,initializeMouseDown:function(t,e,a){t.preventDefault?t.preventDefault():(t.returnValue=!1,t.cancelBubble=!0);e=M.findPos(e.canvas_);a.px=e.x,a.py=e.y,a.dragStartX=M.dragGetX_(t,a),a.dragStartY=M.dragGetY_(t,a),a.cancelNextDblclick=!1,a.tarp.cover()},destroy:function(){var t=this;if((t.isZooming||t.isPanning)&&(t.isZooming=!1,t.dragStartX=null,t.dragStartY=null),t.isPanning){t.isPanning=!1,t.draggingDate=null,t.dateRange=null;for(var e=0;e<n.axes_.length;e++)delete n.axes_[e].draggingValue,delete n.axes_[e].dragValueRange}t.tarp.uncover()}},e=this.getOption("interactionModel"),n=this;for(t in e)e.hasOwnProperty(t)&&this.addAndTrackEvent(this.mouseEventElement_,t,function(e){return function(t){e(t,n,a)}}(e[t]));e.willDestroyContextMyself||this.addAndTrackEvent(document,"mouseup",function(t){a.destroy()})},L.prototype.drawZoomRect_=function(t,e,a,n,i,r,o,s){var l=this.canvas_ctx_;r==M.HORIZONTAL?l.clearRect(Math.min(e,o),this.layout_.getPlotArea().y,Math.abs(e-o),this.layout_.getPlotArea().h):r==M.VERTICAL&&l.clearRect(this.layout_.getPlotArea().x,Math.min(n,s),this.layout_.getPlotArea().w,Math.abs(n-s)),t==M.HORIZONTAL?a&&e&&(l.fillStyle="rgba(128,128,128,0.33)",l.fillRect(Math.min(e,a),this.layout_.getPlotArea().y,Math.abs(a-e),this.layout_.getPlotArea().h)):t==M.VERTICAL&&i&&n&&(l.fillStyle="rgba(128,128,128,0.33)",l.fillRect(this.layout_.getPlotArea().x,Math.min(n,i),this.layout_.getPlotArea().w,Math.abs(i-n)))},L.prototype.clearZoomRect_=function(){this.currentZoomRectArgs_=null,this.canvas_ctx_.clearRect(0,0,this.width_,this.height_)},L.prototype.doZoomX_=function(t,e){this.currentZoomRectArgs_=null;t=this.toDataXCoord(t),e=this.toDataXCoord(e);this.doZoomXDates_(t,e)},L.prototype.doZoomXDates_=function(t,e){var a=this.xAxisRange(),n=[t,e],i=this.getFunctionOption("zoomCallback"),r=this;this.doAnimatedZoom(a,n,null,null,function(){i&&i.call(r,t,e,r.yAxisRanges())})},L.prototype.doZoomY_=function(t,e){this.currentZoomRectArgs_=null;for(var a=this.yAxisRanges(),n=[],i=0;i<this.axes_.length;i++){var r=this.toDataYCoord(t,i),o=this.toDataYCoord(e,i);n.push([o,r])}var s=this.getFunctionOption("zoomCallback"),l=this;this.doAnimatedZoom(null,null,a,n,function(){var t,e;s&&(t=(e=P(l.xAxisRange(),2))[0],e=e[1],s.call(l,t,e,l.yAxisRanges()))})},L.zoomAnimationFunction=function(t,e){return(1-Math.pow(1.5,-t))/(1-Math.pow(1.5,-e))},L.prototype.resetZoom=function(){var t,e,a,n,i,r,o,s=this.isZoomed("x"),l=this.isZoomed("y"),h=s||l;this.clearSelection(),h&&(h=P(this.xAxisExtremes(),2),t=h[0],e=h[1],h=this.getBooleanOption("animatedZooms"),a=this.getFunctionOption("zoomCallback"),h?(r=i=n=h=null,s&&(h=this.xAxisRange(),n=[t,e]),l&&(i=this.yAxisRanges(),r=this.yAxisExtremes()),(o=this).doAnimatedZoom(h,n,i,r,function(){o.dateWindow_=null,o.axes_.forEach(function(t){t.valueRange&&delete t.valueRange}),a&&a.call(o,t,e,o.yAxisRanges())})):(this.dateWindow_=null,this.axes_.forEach(function(t){t.valueRange&&delete t.valueRange}),this.drawGraph_(),a&&a.call(this,t,e,this.yAxisRanges())))},L.prototype.doAnimatedZoom=function(t,e,a,n,i){var r,o=this.getBooleanOption("animatedZooms")?L.ANIMATION_STEPS:1,s=[],l=[];if(null!==t&&null!==e)for(r=1;r<=o;r++)h=L.zoomAnimationFunction(r,o),s[r-1]=[t[0]*(1-h)+h*e[0],t[1]*(1-h)+h*e[1]];if(null!==a&&null!==n)for(r=1;r<=o;r++){for(var h=L.zoomAnimationFunction(r,o),d=[],u=0;u<this.axes_.length;u++)d.push([a[u][0]*(1-h)+h*n[u][0],a[u][1]*(1-h)+h*n[u][1]]);l[r-1]=d}var c=this;M.repeatAndCleanup(function(t){if(l.length)for(var e=0;e<c.axes_.length;e++){var a=l[t][e];c.axes_[e].valueRange=[a[0],a[1]]}s.length&&(c.dateWindow_=s[t]),c.drawGraph_()},o,L.ANIMATION_DURATION/o,i)},L.prototype.getArea=function(){return this.plotter_.area},L.prototype.eventToDomCoords=function(t){var e;return t.offsetX&&t.offsetY?[t.offsetX,t.offsetY]:(e=M.findPos(this.mouseEventElement_),[M.pageX(t)-e.x,M.pageY(t)-e.y])},L.prototype.findClosestRow=function(t){for(var e=1/0,a=-1,n=this.layout_.points,i=0;i<n.length;i++)for(var r=n[i],o=r.length,s=0;s<o;s++){var l,h=r[s];M.isValidPoint(h,!0)&&(l=Math.abs(h.canvasx-t))<e&&(e=l,a=h.idx)}return a},L.prototype.findClosestPoint=function(t,e){for(var a,n,i,r,o,s=1/0,l=this.layout_.points.length-1;0<=l;--l)for(var h=this.layout_.points[l],d=0;d<h.length;++d)n=h[d],M.isValidPoint(n)&&(a=(a=n.canvasx-t)*a+(a=n.canvasy-e)*a)<s&&(s=a,r=l,o=(i=n).idx);return{row:o,seriesName:this.layout_.setNames[r],point:i}},L.prototype.findStackedPoint=function(t,e){for(var a,n,i=this.findClosestRow(t),r=0;r<this.layout_.points.length;++r){var o,s,l,h,d=i-this.getLeftBoundary_(r),u=this.layout_.points[r];d>=u.length||(o=u[d],M.isValidPoint(o)&&(s=o.canvasy,t>o.canvasx&&1+d<u.length?(l=u[1+d],M.isValidPoint(l)&&0<(h=l.canvasx-o.canvasx)&&(s+=(t-o.canvasx)/h*(l.canvasy-o.canvasy))):t<o.canvasx&&0<d&&(l=u[d-1],M.isValidPoint(l))&&0<(h=o.canvasx-l.canvasx)&&(s+=(o.canvasx-t)/h*(l.canvasy-o.canvasy)),0===r||s<e)&&(a=o,n=r))}return{row:i,seriesName:this.layout_.setNames[n],point:a}},L.prototype.mouseMove_=function(t){var e,a,n=this.layout_.points;null!=n&&(a=(n=this.eventToDomCoords(t))[0],n=n[1],e=!1,e=this.getOption("highlightSeriesOpts")&&!this.isSeriesLocked()?(n=this.getBooleanOption("stackedGraph")?this.findStackedPoint(a,n):this.findClosestPoint(a,n),this.setSelection(n.row,n.seriesName)):(n=this.findClosestRow(a),this.setSelection(n)),a=this.getFunctionOption("highlightCallback"))&&e&&a.call(this,t,this.lastx_,this.selPoints_,this.lastRow_,this.highlightSet_)},L.prototype.getLeftBoundary_=function(t){if(this.boundaryIds_[t])return this.boundaryIds_[t][0];for(var e=0;e<this.boundaryIds_.length;e++)if(void 0!==this.boundaryIds_[e])return this.boundaryIds_[e][0];return 0},L.prototype.animateSelection_=function(e){void 0===this.fadeLevel&&(this.fadeLevel=0),void 0===this.animateId&&(this.animateId=0);var a,n,t=this.fadeLevel,t=e<0?t:10-t;t<=0?this.fadeLevel&&this.updateSelection_(1):(a=++this.animateId,n=this,M.repeatAndCleanup(function(t){n.animateId==a&&(n.fadeLevel+=e,0===n.fadeLevel?n.clearSelection():n.updateSelection_(n.fadeLevel/10))},t,30,function(){0!==n.fadeLevel&&e<0&&(n.fadeLevel=0,n.clearSelection())}))},L.prototype.updateSelection_=function(t){this.cascadeEvents_("select",{selectedRow:-1===this.lastRow_?void 0:this.lastRow_,selectedX:null===this.lastx_?void 0:this.lastx_,selectedPoints:this.selPoints_});var e=this.canvas_ctx_;if(this.getOption("highlightSeriesOpts")){e.clearRect(0,0,this.width_,this.height_);var a=1-this.getNumericOption("highlightSeriesBackgroundAlpha"),n=M.toRGB_(this.getOption("highlightSeriesBackgroundColor"));if(a){if(this.getBooleanOption("animateBackgroundFade")){if(void 0===t)return void this.animateSelection_(1);a*=t}e.fillStyle="rgba("+n.r+","+n.g+","+n.b+","+a+")",e.fillRect(0,0,this.width_,this.height_)}this.plotter_._renderLineChart(this.highlightSet_,e)}else if(0<=this.previousVerticalX_){for(var i=0,r=this.attr_("labels"),o=1;o<r.length;o++){var s=this.getNumericOption("highlightCircleSize",r[o]);i<s&&(i=s)}t=this.previousVerticalX_;e.clearRect(t-i-1,0,2*i+2,this.height_)}if(0<this.selPoints_.length){var l=this.selPoints_[0].canvasx;for(e.save(),o=0;o<this.selPoints_.length;o++){var h,d,u,c=this.selPoints_[o];isNaN(c.canvasy)||(h=this.getNumericOption("highlightCircleSize",c.name),u=this.getFunctionOption("drawHighlightPointCallback",c.name),d=this.plotter_.colors[c.name],u=u||M.Circles.DEFAULT,e.lineWidth=this.getNumericOption("strokeWidth",c.name),e.strokeStyle=d,e.fillStyle=d,u.call(this,this,c.name,e,l,c.canvasy,d,h,c.idx))}e.restore(),this.previousVerticalX_=l}},L.prototype.setSelection=function(t,e,a,n){var i=!(this.selPoints_=[]);if(!1!==t&&0<=t){t!=this.lastRow_&&(i=!0),this.lastRow_=t;for(var r=0;r<this.layout_.points.length;++r){var o=this.layout_.points[r],s=t-this.getLeftBoundary_(r);if(0<=s&&s<o.length&&o[s].idx==t)null!==(l=o[s]).yval&&this.selPoints_.push(l);else for(var l,h=0;h<o.length;++h)if((l=o[h]).idx==t){null!==l.yval&&this.selPoints_.push(l);break}}}else 0<=this.lastRow_&&(i=!0),this.lastRow_=-1;return this.selPoints_.length?this.lastx_=this.selPoints_[0].xval:this.lastx_=null,void 0!==e&&(this.highlightSet_!==e&&(i=!0),this.highlightSet_=e),void 0!==a&&(this.lockedSet_=a),i&&(this.updateSelection_(void 0),n)&&(e=this.getFunctionOption("highlightCallback"))&&e.call(this,{},this.lastx_,this.selPoints_,this.lastRow_,this.highlightSet_),i},L.prototype.mouseOut_=function(t){this.getFunctionOption("unhighlightCallback")&&this.getFunctionOption("unhighlightCallback").call(this,t),this.getBooleanOption("hideOverlayOnMouseOut")&&!this.lockedSet_&&this.clearSelection()},L.prototype.clearSelection=function(){this.cascadeEvents_("deselect",{}),this.lockedSet_=!1,this.fadeLevel?this.animateSelection_(-1):(this.canvas_ctx_.clearRect(0,0,this.width_,this.height_),this.fadeLevel=0,this.selPoints_=[],this.lastx_=null,this.lastRow_=-1,this.highlightSet_=null)},L.prototype.getSelection=function(){if(this.selPoints_&&!(this.selPoints_.length<1))for(var t=0;t<this.layout_.points.length;t++)for(var e=this.layout_.points[t],a=0;a<e.length;a++)if(e[a].x==this.selPoints_[0].x)return e[a].idx;return-1},L.prototype.getHighlightSeries=function(){return this.highlightSet_},L.prototype.isSeriesLocked=function(){return this.lockedSet_},L.prototype.loadedEvent_=function(t){this.rawData_=this.parseCSV_(t),this.cascadeDataDidUpdateEvent_(),this.predraw_()},L.prototype.addXTicks_=function(){var t=this.dateWindow_?[this.dateWindow_[0],this.dateWindow_[1]]:this.xAxisExtremes(),e=this.optionsViewForAxis_("x"),t=e("ticker")(t[0],t[1],this.plotter_.area.w,e,this);this.layout_.setXTicks(t)},L.prototype.getHandlerClass_=function(){var t=this.attr_("dataHandler")?this.attr_("dataHandler"):(this.fractions_?this.getBooleanOption("errorBars")?p:d:this.getBooleanOption("customBars")?h:this.getBooleanOption("errorBars")?l:s).default;return t},L.prototype.predraw_=function(){var t=new Date;this.dataHandler_=new(this.getHandlerClass_()),this.layout_.computePlotArea(),this.computeYAxes_(),this.is_initial_draw_||(this.canvas_ctx_.restore(),this.hidden_ctx_.restore()),this.canvas_ctx_.save(),this.hidden_ctx_.save(),this.plotter_=new r.default(this,this.hidden_,this.hidden_ctx_,this.layout_),this.createRollInterface_(),this.cascadeEvents_("predraw"),this.rolledSeries_=[null];for(var e=1;e<this.numColumns();e++){var a=this.dataHandler_.extractSeries(this.rawData_,e,this.attributes_);1<this.rollPeriod_&&(a=this.dataHandler_.rollingAverage(a,this.rollPeriod_,this.attributes_,e)),this.rolledSeries_.push(a)}this.drawGraph_();var n=new Date;this.drawingTimeMs_=n-t},L.PointType=void 0,L.stackPoints_=function(t,e,a,n){for(var i=null,r=null,o=null,s=-1,l=0;l<t.length;++l){var h=t[l],d=h.xval,u=(void 0===e[d]&&(e[d]=0),h.yval);if(isNaN(u)||null===u)if("none"==n)u=0;else{p=void 0;var c=l;if(!(c<=s))for(var p=c;p<t.length;++p)if(o=null,!isNaN(t[p].yval)&&null!==t[p].yval){o=t[s=p];break}u=r&&o&&"none"!=n?r.yval+(o.yval-r.yval)*((d-r.xval)/(o.xval-r.xval)):r&&"all"==n?r.yval:o&&"all"==n?o.yval:0}else r=h;c=e[d];i!=d&&(c+=u,e[d]=c),i=d,(h.yval_stacked=c)>a[1]&&(a[1]=c),c<a[0]&&(a[0]=c)}},L.prototype.gatherDatasets_=function(t,e){for(var a,n=[],i=[],r=[],o={},s=t.length-1;1<=s;s--)if(this.visibility()[s-1]){if(e){for(var l=t[s],h=e[0],d=e[1],u=null,c=null,p=0;p<l.length;p++)l[p][0]>=h&&null===u&&(u=p),l[p][0]<=d&&(c=p);for(var g=u=null===u?0:u,f=!0;f&&0<g;)f=null===l[--g][1];for(var _=c=null===c?l.length-1:c,f=!0;f&&_<l.length-1;)f=null===l[++_][1];g!==u&&(u=g),_!==c&&(c=_),n[s-1]=[u,c],l=l.slice(u,c+1)}else l=t[s],n[s-1]=[0,l.length-1];var y=this.attr_("labels")[s],v=this.dataHandler_.getExtremeYValues(l,e,this.getBooleanOption("stepPlot",y)),x=this.dataHandler_.seriesToPoints(l,y,n[s-1][0]);this.getBooleanOption("stackedGraph")&&(void 0===r[a=this.attributes_.axisForSeries(y)]&&(r[a]=[]),L.stackPoints_(x,r[a],v,this.getBooleanOption("stackedGraphNaNFill"))),o[y]=v,i[s]=x}return{points:i,extremes:o,boundaryIds:n}},L.prototype.drawGraph_=function(){for(var t=new Date,e=this.is_initial_draw_,a=(this.is_initial_draw_=!1,this.layout_.removeAllDatasets(),this.setColors_(),this.attrs_.pointSize=.5*this.getNumericOption("highlightCircleSize"),this.gatherDatasets_(this.rolledSeries_,this.dateWindow_)),n=a.points,i=a.extremes,r=(this.boundaryIds_=a.boundaryIds,this.setIndexByName_={},this.attr_("labels")),o=0,s=1;s<n.length;s++)this.visibility()[s-1]&&(this.layout_.addDataset(r[s],n[s]),this.datasetIndex_[s]=o++);for(s=0;s<r.length;s++)this.setIndexByName_[r[s]]=s;this.computeYAxisRanges_(i),this.layout_.setYAxes(this.axes_),this.addXTicks_(),this.layout_.evaluate(),this.renderGraph_(e),this.getStringOption("timingName")&&(a=new Date,console.log(this.getStringOption("timingName")+" - drawGraph: "+(a-t)+"ms"))},L.prototype.renderGraph_=function(t){this.cascadeEvents_("clearChart"),this.plotter_.clear();var e=this.getFunctionOption("underlayCallback"),e=(e&&e.call(this,this.hidden_ctx_,this.layout_.getPlotArea(),this,this),{canvas:this.hidden_,drawingContext:this.hidden_ctx_}),e=(this.cascadeEvents_("willDrawChart",e),this.plotter_.render(),this.cascadeEvents_("didDrawChart",e),this.lastRow_=-1,this.canvas_.getContext("2d").clearRect(0,0,this.width_,this.height_),this.getFunctionOption("drawCallback"));if(null!==e&&e.call(this,this,t),t)for(this.readyFired_=!0;0<this.readyFns_.length;)this.readyFns_.pop()(this)},L.prototype.computeYAxes_=function(){var t,e,a,n;for(this.axes_=[],t=0;t<this.attributes_.numAxes();t++)M.update(e={g:this},this.attributes_.axisOptions(t)),this.axes_[t]=e;for(t=0;t<this.axes_.length;t++)0===t?(a=(e=this.optionsViewForAxis_("y"+(t?"2":"")))("valueRange"))&&(this.axes_[t].valueRange=a):(n=this.user_attrs_.axes)&&n.y2&&(a=n.y2.valueRange)&&(this.axes_[t].valueRange=a)},L.prototype.numAxes=function(){return this.attributes_.numAxes()},L.prototype.axisPropertiesForSeries=function(t){return this.axes_[this.attributes_.axisForSeries(t)]},L.prototype.computeYAxisRanges_=function(t){for(var e,a,n=function(t){return isNaN(parseFloat(t))},i=this.attributes_.numAxes(),r=0;r<i;r++){var o,s,l=this.axes_[r],h=this.attributes_.getForAxis("logscale",r),d=this.attributes_.getForAxis("includeZero",r),u=this.attributes_.getForAxis("independentTicks",r),c=this.attributes_.seriesForAxis(r),p=!0,g=.1,f=this.getNumericOption("yRangePad");if(null!==f&&(p=!1,g=f/this.plotter_.area.h),0===c.length)l.extremeRange=[0,1];else{for(var _,y=1/0,v=-1/0,x=0;x<c.length;x++)t.hasOwnProperty(c[x])&&(null!==(_=t[c[x]][0])&&(y=Math.min(_,y)),null!==(_=t[c[x]][1]))&&(v=Math.max(_,v));0===(e=(v=(v=d&&!h&&(0<y&&(y=0),v<0)?0:v)==-1/0?1:v)-(y=y==1/0?0:y))&&(e=0!==v?Math.abs(v):v=1);var f=v,d=y;p&&(h?(f=v+g*e,d=y):((d=y-g*e)<0&&0<=y&&(d=0),0<(f=v+g*e)&&v<=0&&(f=0))),l.extremeRange=[d,f]}l.valueRange?(o=(n(l.valueRange[0])?l.extremeRange:l.valueRange)[0],s=(n(l.valueRange[1])?l.extremeRange:l.valueRange)[1],l.computedValueRange=[o,s]):l.computedValueRange=l.extremeRange,p||((o=l.computedValueRange[0])===(s=l.computedValueRange[1])&&(0===o?s=1:(o-=d=Math.abs(o/10),s+=d)),h?(f=(g-1)/(2*g-1),l.computedValueRange[0]=M.logRangeFraction(o,s,g/(2*g-1)),l.computedValueRange[1]=M.logRangeFraction(o,s,f)):(l.computedValueRange[0]=o-(e=s-o)*g,l.computedValueRange[1]=s+e*g)),u&&(l.independentTicks=u,b=(m=this.optionsViewForAxis_("y"+(r?"2":"")))("ticker"),l.ticks=b(l.computedValueRange[0],l.computedValueRange[1],this.plotter_.area.h,m,this),a=a||l)}if(void 0===a)throw'Configuration Error: At least one axis has to have the "independentTicks" option activated.';for(r=0;r<i;r++)if(!(l=this.axes_[r]).independentTicks){for(var m,b=(m=this.optionsViewForAxis_("y"+(r?"2":"")))("ticker"),w=a.ticks,O=a.computedValueRange[1]-a.computedValueRange[0],A=l.computedValueRange[1]-l.computedValueRange[0],P=[],S=0;S<w.length;S++){var L=(w[S].v-a.computedValueRange[0])/O,L=l.computedValueRange[0]+L*A;P.push(L)}l.ticks=b(l.computedValueRange[0],l.computedValueRange[1],this.plotter_.area.h,m,this,P)}},L.prototype.detectTypeFromString_=function(t){var e=!1,a=t.indexOf("-");(0<a&&"e"!=t[a-1]&&"E"!=t[a-1]||0<=t.indexOf("/")||isNaN(parseFloat(t)))&&(e=!0),this.setXAxisOptions_(e)},L.prototype.setXAxisOptions_=function(t){t?(this.attrs_.xValueParser=M.dateParser,this.attrs_.axes.x.valueFormatter=M.dateValueFormatter,this.attrs_.axes.x.ticker=v.dateTicker,this.attrs_.axes.x.axisLabelFormatter=M.dateAxisLabelFormatter):(this.attrs_.xValueParser=function(t){return parseFloat(t)},this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=v.numericTicks,this.attrs_.axes.x.axisLabelFormatter=this.attrs_.axes.x.valueFormatter)},L.prototype.parseCSV_=function(t){for(var e,a,n=[],i=M.detectLineDelimiter(t),r=t.split(i||"\n"),o=this.getStringOption("delimiter"),t=(-1==r[0].indexOf(o)&&0<=r[0].indexOf("\t")&&(o="\t"),0),s=("labels"in this.user_attrs_||(t=1,this.attrs_.labels=r[0].split(o),this.attributes_.reparseSeries()),!1),l=this.attr_("labels").length,h=!1,d=t;d<r.length;d++){var u=r[d];if(0!==u.length&&"#"!=u[0]){var c=u.split(o);if(!(c.length<2)){var p=[];if(s||(this.detectTypeFromString_(c[0]),a=this.getFunctionOption("xValueParser"),s=!0),p[0]=a(c[0],this),this.fractions_)for(_=1;_<c.length;_++)2!=(e=c[_].split("/")).length?(console.error('Expected fractional "num/den" values in CSV data but found a value \''+c[_]+"' on line "+(1+d)+" ('"+u+"') which is not of this form."),p[_]=[0,0]):p[_]=[M.parseFloat_(e[0],d,u),M.parseFloat_(e[1],d,u)];else if(this.getBooleanOption("errorBars"))for(c.length%2!=1&&console.error("Expected alternating (value, stdev.) pairs in CSV data but line "+(1+d)+" has an odd number of values ("+(c.length-1)+"): '"+u+"'"),_=1;_<c.length;_+=2)p[(_+1)/2]=[M.parseFloat_(c[_],d,u),M.parseFloat_(c[_+1],d,u)];else if(this.getBooleanOption("customBars"))for(_=1;_<c.length;_++){var g=c[_];/^ *$/.test(g)?p[_]=[null,null,null]:3==(e=g.split(";")).length?p[_]=[M.parseFloat_(e[0],d,u),M.parseFloat_(e[1],d,u),M.parseFloat_(e[2],d,u)]:console.warn('When using customBars, values must be either blank or "low;center;high" tuples (got "'+g+'" on line '+(1+d)+")")}else for(_=1;_<c.length;_++)p[_]=M.parseFloat_(c[_],d,u);if(0<n.length&&p[0]<n[n.length-1][0]&&(h=!0),p.length!=l&&console.error("Number of columns in line "+d+" ("+p.length+") does not agree with number of labels ("+l+") "+u),0===d&&this.attr_("labels")){for(var f=!0,_=0;f&&_<p.length;_++)p[_]&&(f=!1);if(f){console.warn("The dygraphs 'labels' option is set, but the first row of CSV data ('"+u+"') appears to also contain labels. Will drop the CSV labels and use the option labels.");continue}}n.push(p)}}}return h&&(console.warn("CSV is out of order; order it correctly to speed loading."),n.sort(function(t,e){return t[0]-e[0]})),n},L.prototype.parseArray_=function(t){if(0===(t=0===t.length?[[0]]:t)[0].length)return console.error("Data set cannot contain an empty row"),null;var e=t,a=e[0];if("number"!=typeof(e=a[0])&&!M.isDateLike(e))throw new Error("Expected number or date but got ".concat(typeof e,": ").concat(e,"."));for(var n=1;n<a.length;n++){var i=a[n];if(null!=i&&("number"!=typeof i&&!M.isArrayLike(i)))throw new Error("Expected number or array but got ".concat(typeof i,": ").concat(i,"."))}if(null===this.attr_("labels")){for(console.warn("Using default labels. Set labels explicitly via 'labels' in the options parameter"),this.attrs_.labels=["X"],o=1;o<t[0].length;o++)this.attrs_.labels.push("Y"+o);this.attributes_.reparseSeries()}else{e=this.attr_("labels");if(e.length!=t[0].length)return console.error("Mismatch between number of labels ("+e+") and number of columns in array ("+t[0].length+")"),null}if(M.isDateLike(t[0][0])){this.attrs_.axes.x.valueFormatter=M.dateValueFormatter,this.attrs_.axes.x.ticker=v.dateTicker,this.attrs_.axes.x.axisLabelFormatter=M.dateAxisLabelFormatter;for(var r=M.clone(t),o=0;o<t.length;o++){if(0===r[o].length)return console.error("Row "+(1+o)+" of data is empty"),null;if(null===r[o][0]||"function"!=typeof r[o][0].getTime||isNaN(r[o][0].getTime()))return console.error("x value in row "+(1+o)+" is not a Date"),null;r[o][0]=r[o][0].getTime()}return r}return this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=v.numericTicks,this.attrs_.axes.x.axisLabelFormatter=M.numberAxisLabelFormatter,t},L.prototype.parseDataTable_=function(t){var e=t.getNumberOfColumns(),a=t.getNumberOfRows(),n=t.getColumnType(0);if("date"==n||"datetime"==n)this.attrs_.xValueParser=M.dateParser,this.attrs_.axes.x.valueFormatter=M.dateValueFormatter,this.attrs_.axes.x.ticker=v.dateTicker,this.attrs_.axes.x.axisLabelFormatter=M.dateAxisLabelFormatter;else{if("number"!=n)throw new Error("only 'date', 'datetime' and 'number' types are supported for column 1 of DataTable input (Got '"+n+"')");this.attrs_.xValueParser=function(t){return parseFloat(t)},this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=v.numericTicks,this.attrs_.axes.x.axisLabelFormatter=this.attrs_.axes.x.valueFormatter}for(var i,r=[],o={},s=!1,l=1;l<e;l++){var h=t.getColumnType(l);if("number"==h)r.push(l);else{if("string"!=h||!this.getBooleanOption("displayAnnotations"))throw new Error("Only 'number' is supported as a dependent type with Gviz. 'string' is only supported if displayAnnotations is true");h=r[r.length-1];o.hasOwnProperty(h)?o[h].push(l):o[h]=[l],s=!0}}var d=[t.getColumnLabel(0)];for(l=0;l<r.length;l++)d.push(t.getColumnLabel(r[l])),this.getBooleanOption("errorBars")&&(l+=1);var e=(this.attrs_.labels=d).length,u=[],c=!1,p=[];for(l=0;l<a;l++){var g=[];if(void 0===t.getValue(l,0)||null===t.getValue(l,0))console.warn("Ignoring row "+l+" of DataTable because of undefined or null first column.");else{if(g.push("date"==n||"datetime"==n?t.getValue(l,0).getTime():t.getValue(l,0)),this.getBooleanOption("errorBars"))for(i=0;i<e-1;i++)g.push([t.getValue(l,1+2*i),t.getValue(l,2+2*i)]);else{for(i=0;i<r.length;i++){var f=r[i];if(g.push(t.getValue(l,f)),s&&o.hasOwnProperty(f)&&null!==t.getValue(l,o[f][0])){var _={};_.series=t.getColumnLabel(f),_.xval=g[0],_.shortText=function(t){var e=String.fromCharCode(65+t%26);for(t=Math.floor(t/26);0<t;)e=String.fromCharCode(65+(t-1)%26)+e.toLowerCase(),t=Math.floor((t-1)/26);return e}(p.length),_.text="";for(var y=0;y<o[f].length;y++)y&&(_.text+="\n"),_.text+=t.getValue(l,o[f][y]);p.push(_)}}for(i=0;i<g.length;i++)isFinite(g[i])||(g[i]=null)}0<u.length&&g[0]<u[u.length-1][0]&&(c=!0),u.push(g)}}c&&(console.warn("DataTable is out of order; order it correctly to speed loading."),u.sort(function(t,e){return t[0]-e[0]})),this.rawData_=u,0<p.length&&this.setAnnotations(p,!0),this.attributes_.reparseSeries()},L.prototype.cascadeDataDidUpdateEvent_=function(){this.cascadeEvents_("dataDidUpdate",{})},L.prototype.start_=function(){var t,e,a=this.file_,n=("function"==typeof a&&(a=a()),M.typeArrayLike(a));"array"==n?(this.rawData_=this.parseArray_(a),this.cascadeDataDidUpdateEvent_(),this.predraw_()):"object"==n&&"function"==typeof a.getColumnRange?(this.parseDataTable_(a),this.cascadeDataDidUpdateEvent_(),this.predraw_()):"string"==n?M.detectLineDelimiter(a)?this.loadedEvent_(a):(t=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP"),e=this,t.onreadystatechange=function(){4!=t.readyState||200!==t.status&&0!==t.status||e.loadedEvent_(t.responseText)},t.open("GET",a,!0),t.send(null)):console.error("Unknown data format: "+n)},L.prototype.updateOptions=function(t,e){void 0===e&&(e=!1);var a=t.file,t=L.copyUserAttrs_(t),n=this.attributes_.numAxes(),i=("rollPeriod"in t&&(this.rollPeriod_=t.rollPeriod),"dateWindow"in t&&(this.dateWindow_=t.dateWindow),M.isPixelChangingOptionList(this.attr_("labels"),t));M.updateDeep(this.user_attrs_,t),this.attributes_.reparseSeries(),n<this.attributes_.numAxes()&&this.plotter_.clear(),a?(this.cascadeEvents_("dataWillUpdate",{}),this.file_=a,e||this.start_()):e||(i?this.predraw_():this.renderGraph_(!1))},L.copyUserAttrs_=function(t){var e,a={};for(e in t)t.hasOwnProperty(e)&&"file"!=e&&t.hasOwnProperty(e)&&(a[e]=t[e]);return a},L.prototype.resize=function(t,e){var a,n;this.resize_lock||(this.resize_lock=!0,null===t!=(null===e)&&(console.warn("Dygraph.resize() should be called with zero parameters or two non-NULL parameters. Pretending it was zero."),t=e=null),a=this.width_,n=this.height_,t?(this.maindiv_.style.width=t+"px",this.maindiv_.style.height=e+"px",this.width_=t,this.height_=e):(this.width_=this.maindiv_.clientWidth,this.height_=this.maindiv_.clientHeight),a==this.width_&&n==this.height_||(this.resizeElements_(),this.predraw_()),this.resize_lock=!1)},L.prototype.adjustRoll=function(t){this.rollPeriod_=t,this.predraw_()},L.prototype.visibility=function(){for(this.getOption("visibility")||(this.attrs_.visibility=[]);this.getOption("visibility").length<this.numColumns()-1;)this.attrs_.visibility.push(!0);return this.getOption("visibility")},L.prototype.setVisibility=function(t,e){var a=this.visibility(),n=!1;if(Array.isArray(t)||(null!==t&&"object"==typeof t?n=!0:t=[t]),n)for(var i in t)t.hasOwnProperty(i)&&(i<0||i>=a.length?console.warn("Invalid series number in setVisibility: "+i):a[i]=t[i]);else for(i=0;i<t.length;i++)"boolean"==typeof t[i]?i>=a.length?console.warn("Invalid series number in setVisibility: "+i):a[i]=t[i]:t[i]<0||t[i]>=a.length?console.warn("Invalid series number in setVisibility: "+t[i]):a[t[i]]=e;this.predraw_()},L.prototype.size=function(){return{width:this.width_,height:this.height_}},L.prototype.setAnnotations=function(t,e){this.annotations_=t,this.layout_?(this.layout_.setAnnotations(this.annotations_),e||this.predraw_()):console.warn("Tried to setAnnotations before dygraph was ready. Try setting them in a ready() block. See dygraphs.com/tests/annotation.html")},L.prototype.annotations=function(){return this.annotations_},L.prototype.getLabels=function(){var t=this.attr_("labels");return t?t.slice():null},L.prototype.indexFromSetName=function(t){return this.setIndexByName_[t]},L.prototype.getRowForX=function(t){for(var e=0,a=this.numRows()-1;e<=a;){var n=a+e>>1,i=this.getValue(n,0);if(i<t)e=1+n;else if(t<i)a=n-1;else{if(e==n)return n;a=n}}return null},L.prototype.ready=function(t){this.is_initial_draw_?this.readyFns_.push(t):t.call(this,this)},L.prototype.addAndTrackEvent=function(t,e,a){M.addEvent(t,e,a),this.registeredEvents_.push({elem:t,type:e,fn:a})},L.prototype.removeTrackedEvents_=function(){if(this.registeredEvents_)for(var t=0;t<this.registeredEvents_.length;t++){var e=this.registeredEvents_[t];M.removeEvent(e.elem,e.type,e.fn)}this.registeredEvents_=[]},L.PLUGINS=[m.default,_.default,b.default,y.default,f.default,x.default],L.GVizChart=t.default,L.DASHED_LINE=M.DASHED_LINE,L.DOT_DASH_LINE=M.DOT_DASH_LINE,L.dateAxisLabelFormatter=M.dateAxisLabelFormatter,L.toRGB_=M.toRGB_,L.findPos=M.findPos,L.pageX=M.pageX,L.pageY=M.pageY,L.dateString_=M.dateString_,L.defaultInteractionModel=n.default.defaultModel,L.nonInteractiveModel=L.nonInteractiveModel_=n.default.nonInteractiveModel_,L.Circles=M.Circles,L.Plugins={Legend:m.default,Axes:_.default,Annotations:f.default,ChartLabels:y.default,Grid:x.default,RangeSelector:b.default},L.DataHandlers={DefaultHandler:s.default,BarsHandler:g.default,CustomBarsHandler:h.default,DefaultFractionHandler:d.default,ErrorBarsHandler:l.default,FractionsBarsHandler:p.default},L.startPan=n.default.startPan,L.startZoom=n.default.startZoom,L.movePan=n.default.movePan,L.moveZoom=n.default.moveZoom,L.endPan=n.default.endPan,L.endZoom=n.default.endZoom,L.numericLinearTicks=v.numericLinearTicks,L.numericTicks=v.numericTicks,L.dateTicker=v.dateTicker,L.Granularity=v.Granularity,L.getDateAxis=v.getDateAxis,L.floatFormat=M.floatFormat,M.setupDOMready_(L),a.default=L,e.exports=a.default},{"./datahandler/bars":"dygraphs/src/datahandler/bars.js","./datahandler/bars-custom":"dygraphs/src/datahandler/bars-custom.js","./datahandler/bars-error":"dygraphs/src/datahandler/bars-error.js","./datahandler/bars-fractions":"dygraphs/src/datahandler/bars-fractions.js","./datahandler/default":"dygraphs/src/datahandler/default.js","./datahandler/default-fractions":"dygraphs/src/datahandler/default-fractions.js","./dygraph-canvas":"dygraphs/src/dygraph-canvas.js","./dygraph-default-attrs":"dygraphs/src/dygraph-default-attrs.js","./dygraph-gviz":"dygraphs/src/dygraph-gviz.js","./dygraph-interaction-model":"dygraphs/src/dygraph-interaction-model.js","./dygraph-layout":"dygraphs/src/dygraph-layout.js","./dygraph-options":"dygraphs/src/dygraph-options.js","./dygraph-options-reference":"dygraphs/src/dygraph-options-reference.js","./dygraph-tickers":"dygraphs/src/dygraph-tickers.js","./dygraph-utils":"dygraphs/src/dygraph-utils.js","./iframe-tarp":"dygraphs/src/iframe-tarp.js","./plugins/annotations":"dygraphs/src/plugins/annotations.js","./plugins/axes":"dygraphs/src/plugins/axes.js","./plugins/chart-labels":"dygraphs/src/plugins/chart-labels.js","./plugins/grid":"dygraphs/src/plugins/grid.js","./plugins/legend":"dygraphs/src/plugins/legend.js","./plugins/range-selector":"dygraphs/src/plugins/range-selector.js"}],"dygraphs/src/iframe-tarp.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var s=function(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=o(e);if(e&&e.has(t))return e.get(t);var a,n={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t){var r;"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((r=i?Object.getOwnPropertyDescriptor(t,a):null)&&(r.get||r.set)?Object.defineProperty(n,a,r):n[a]=t[a])}n.default=t,e&&e.set(t,n);return n}(t("./dygraph-utils"));function o(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(o=function(t){return t?a:e})(t))}function n(){this.tarps=[]}n.prototype.cover=function(){for(var t=document.getElementsByTagName("iframe"),e=0;e<t.length;e++){var a=t[e],n=s.findPos(a),i=n.x,n=n.y,r=a.offsetWidth,a=a.offsetHeight,o=document.createElement("div");o.style.position="absolute",o.style.left=i+"px",o.style.top=n+"px",o.style.width=r+"px",o.style.height=a+"px",o.style.zIndex=999,document.body.appendChild(o),this.tarps.push(o)}},n.prototype.uncover=function(){for(var t=0;t<this.tarps.length;t++)this.tarps[t].parentNode.removeChild(this.tarps[t]);this.tarps=[]},a.default=n,e.exports=a.default},{"./dygraph-utils":"dygraphs/src/dygraph-utils.js"}],"dygraphs/src/plugins/annotations.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;function n(){this.annotations_=[]}n.prototype.toString=function(){return"Annotations Plugin"},n.prototype.activate=function(t){return{clearChart:this.clearChart,didDrawChart:this.didDrawChart}},n.prototype.detachLabels=function(){for(var t=0;t<this.annotations_.length;t++){var e=this.annotations_[t];e.parentNode&&e.parentNode.removeChild(e),this.annotations_[t]=null}this.annotations_=[]},n.prototype.clearChart=function(t){this.detachLabels()},n.prototype.didDrawChart=function(t){var r=t.dygraph,e=r.layout_.annotated_points;if(e&&0!==e.length)for(var a=t.canvas.parentNode,n=function(a,n,i){return function(t){var e=i.annotation;e.hasOwnProperty(a)?e[a](e,i,r,t):r.getOption(n)&&r.getOption(n)(e,i,r,t)}},i=t.dygraph.getArea(),o={},s=0;s<e.length;s++){var l,h,d,u,c,p,g,f,_=e[s];_.canvasx<i.x||_.canvasx>i.x+i.w||_.canvasy<i.y||_.canvasy>i.y+i.h||(h=6,(l=_.annotation).hasOwnProperty("tickHeight")&&(h=l.tickHeight),(d=document.createElement("div")).style.fontSize=r.getOption("axisLabelFontSize")+"px",g="dygraph-annotation",l.hasOwnProperty("icon")||(g+=" dygraphDefaultAnnotation dygraph-default-annotation"),l.hasOwnProperty("cssClass")&&(g+=" "+l.cssClass),d.className=g,g=l.hasOwnProperty("width")?l.width:16,u=l.hasOwnProperty("height")?l.height:16,l.hasOwnProperty("icon")?((c=document.createElement("img")).src=l.icon,c.width=g,c.height=u,d.appendChild(c)):_.annotation.hasOwnProperty("shortText")&&d.appendChild(document.createTextNode(_.annotation.shortText)),c=_.canvasx-g/2,d.style.left=c+"px",p=0,p=l.attachAtBottom?(f=i.y+i.h-u-h,o[c]?f-=o[c]:o[c]=0,o[c]+=h+u,f):_.canvasy-u-h,d.style.top=p+"px",d.style.width=g+"px",d.style.height=u+"px",d.title=_.annotation.text,d.style.color=r.colorsMap_[_.name],d.style.borderColor=r.colorsMap_[_.name],l.div=d,r.addAndTrackEvent(d,"click",n("clickHandler","annotationClickHandler",_)),r.addAndTrackEvent(d,"mouseover",n("mouseOverHandler","annotationMouseOverHandler",_)),r.addAndTrackEvent(d,"mouseout",n("mouseOutHandler","annotationMouseOutHandler",_)),r.addAndTrackEvent(d,"dblclick",n("dblClickHandler","annotationDblClickHandler",_)),a.appendChild(d),this.annotations_.push(d),(g=t.drawingContext).save(),g.strokeStyle=l.hasOwnProperty("tickColor")?l.tickColor:r.colorsMap_[_.name],g.lineWidth=l.hasOwnProperty("tickWidth")?l.tickWidth:r.getOption("strokeWidth"),g.beginPath(),l.attachAtBottom?(g.moveTo(_.canvasx,f=p+u),g.lineTo(_.canvasx,f+h)):(g.moveTo(_.canvasx,_.canvasy),g.lineTo(_.canvasx,_.canvasy-2-h)),g.closePath(),g.stroke(),g.restore())}},n.prototype.destroy=function(){this.detachLabels()},a.default=n,e.exports=a.default},{}],"dygraphs/src/plugins/axes.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var b=function(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=o(e);if(e&&e.has(t))return e.get(t);var a,n={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t){var r;"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((r=i?Object.getOwnPropertyDescriptor(t,a):null)&&(r.get||r.set)?Object.defineProperty(n,a,r):n[a]=t[a])}n.default=t,e&&e.set(t,n);return n}(t("../dygraph-utils"));function o(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(o=function(t){return t?a:e})(t))}function n(){this.xlabels_=[],this.ylabels_=[]}n.prototype.toString=function(){return"Axes Plugin"},n.prototype.activate=function(t){return{layout:this.layout,clearChart:this.clearChart,willDrawChart:this.willDrawChart}},n.prototype.layout=function(t){var e,a,n=t.dygraph;n.getOptionForAxis("drawAxis","y")&&(a=n.getOptionForAxis("axisLabelWidth","y")+2*n.getOptionForAxis("axisTickSize","y"),t.reserveSpaceLeft(a)),n.getOptionForAxis("drawAxis","x")&&(e=n.getOption("xAxisHeight")?n.getOption("xAxisHeight"):n.getOptionForAxis("axisLabelFontSize","x")+2*n.getOptionForAxis("axisTickSize","x"),t.reserveSpaceBottom(e)),2==n.numAxes()?n.getOptionForAxis("drawAxis","y2")&&(a=n.getOptionForAxis("axisLabelWidth","y2")+2*n.getOptionForAxis("axisTickSize","y2"),t.reserveSpaceRight(a)):2<n.numAxes()&&n.error("Only two y-axes are supported at this time. (Trying to use "+n.numAxes()+")")},n.prototype.detachLabels=function(){function t(t){for(var e=0;e<t.length;e++){var a=t[e];a.parentNode&&a.parentNode.removeChild(a)}}t(this.xlabels_),t(this.ylabels_),this.xlabels_=[],this.ylabels_=[]},n.prototype.clearChart=function(t){this.detachLabels()},n.prototype.willDrawChart=function(t){var e,i,a,r,o,s,l,h,d,n,u,c,p,g,f,_,y,v=t.dygraph;function x(t){return Math.round(t)+.5}function m(t){return Math.round(t)-.5}(v.getOptionForAxis("drawAxis","x")||v.getOptionForAxis("drawAxis","y")||v.getOptionForAxis("drawAxis","y2"))&&(e=t.drawingContext,i=t.canvas.parentNode,a=v.width_,r=v.height_,h={x:(n=function(t){return{position:"absolute",fontSize:v.getOptionForAxis("axisLabelFontSize",t)+"px",width:v.getOptionForAxis("axisLabelWidth",t)+"px"}})("x"),y:n("y"),y2:n("y2")},d=function(t,e,a){var n=document.createElement("div"),i=h["y2"==a?"y2":e],i=(b.update(n.style,i),document.createElement("div"));return i.className="dygraph-axis-label dygraph-axis-label-"+e+(a?" dygraph-axis-label-"+a:""),i.innerHTML=t,n.appendChild(i),n},e.save(),n=v.layout_,u=t.dygraph.plotter_.area,t=function(e){return function(t){return v.getOptionForAxis(t,e)}},c=this,(v.getOptionForAxis("drawAxis","y")||2==v.numAxes()&&v.getOptionForAxis("drawAxis","y2"))&&(n.yticks&&0<n.yticks.length&&(p=v.numAxes(),g=[t("y"),t("y2")],n.yticks.forEach(function(t){var e,a,n;void 0!==t.label&&(s=u.x,n="y1",e=g[0],1==t.axis&&(s=u.x+u.w,n="y2",e=g[1]),e("drawAxis"))&&(a=e("axisLabelFontSize"),l=u.y+t.pos*u.h,o=d(t.label,"y",2==p?n:null),r<(n=(n=l-a/2)<0?0:n)+a+3?o.style.bottom="0":o.style.top=Math.min(n,r-2*a)+"px",0===t.axis?(o.style.left=u.x-e("axisLabelWidth")-e("axisTickSize")+"px",o.style.textAlign="right"):1==t.axis&&(o.style.left=u.x+u.w+e("axisTickSize")+"px",o.style.textAlign="left"),o.style.width=e("axisLabelWidth")+"px",i.appendChild(o),c.ylabels_.push(o))})),y=v.getOption("drawAxesAtZero")?((1<(_=v.toPercentXCoord(0))||_<0||isNaN(_))&&(_=0),x(u.x+_*u.w)):x(u.x),e.strokeStyle=v.getOptionForAxis("axisLineColor","y"),e.lineWidth=v.getOptionForAxis("axisLineWidth","y"),e.beginPath(),e.moveTo(y,m(u.y)),e.lineTo(y,m(u.y+u.h)),e.closePath(),e.stroke(),2==v.numAxes())&&v.getOptionForAxis("drawAxis","y2")&&(e.strokeStyle=v.getOptionForAxis("axisLineColor","y2"),e.lineWidth=v.getOptionForAxis("axisLineWidth","y2"),e.beginPath(),e.moveTo(m(u.x+u.w),m(u.y)),e.lineTo(m(u.x+u.w),m(u.y+u.h)),e.closePath(),e.stroke()),v.getOptionForAxis("drawAxis","x")&&(n.xticks&&(f=t("x"),n.xticks.forEach(function(t){void 0!==t.label&&(s=u.x+t.pos*u.w,l=u.y+u.h,(o=d(t.label,"x")).style.textAlign="center",o.style.top=l+f("axisTickSize")+"px",(t=s-f("axisLabelWidth")/2)+f("axisLabelWidth")>a&&(t=a-f("axisLabelWidth"),o.style.textAlign="right"),t<0&&(t=0,o.style.textAlign="left"),o.style.left=t+"px",o.style.width=f("axisLabelWidth")+"px",i.appendChild(o),c.xlabels_.push(o))})),e.strokeStyle=v.getOptionForAxis("axisLineColor","x"),e.lineWidth=v.getOptionForAxis("axisLineWidth","x"),e.beginPath(),y=v.getOption("drawAxesAtZero")?(_=v.toPercentYCoord(0,0),m(u.y+(_=1<_||_<0?1:_)*u.h)):m(u.y+u.h),e.moveTo(x(u.x),y),e.lineTo(x(u.x+u.w),y),e.closePath(),e.stroke()),e.restore())},a.default=n,e.exports=a.default},{"../dygraph-utils":"dygraphs/src/dygraph-utils.js"}],"dygraphs/src/plugins/chart-labels.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;function n(){this.title_div_=null,this.xlabel_div_=null,this.ylabel_div_=null,this.y2label_div_=null}function r(t){var e=document.createElement("div");return e.style.position="absolute",e.style.left=t.x+"px",e.style.top=t.y+"px",e.style.width=t.w+"px",e.style.height=t.h+"px",e}function o(t,e,a,n,i){var r=document.createElement("div");return r.style.position="absolute",r.style.left=1==a?"0px":e.x+"px",r.style.top=e.y+"px",r.style.width=e.w+"px",r.style.height=e.h+"px",r.style.fontSize=t.getOption("yLabelWidth")-2+"px",(t=document.createElement("div")).style.position="absolute",t.style.width=e.h+"px",t.style.height=e.w+"px",t.style.top=e.h/2-e.w/2+"px",t.style.left=e.w/2-e.h/2+"px",t.className="dygraph-label-rotate-"+(1==a?"right":"left"),(e=document.createElement("div")).className=n,e.innerHTML=i,t.appendChild(e),r.appendChild(t),r}n.prototype.toString=function(){return"ChartLabels Plugin"},n.prototype.activate=function(t){return{layout:this.layout,didDrawChart:this.didDrawChart}},n.prototype.detachLabels_=function(){for(var t=[this.title_div_,this.xlabel_div_,this.ylabel_div_,this.y2label_div_],e=0;e<t.length;e++){var a=t[e];a&&a.parentNode&&a.parentNode.removeChild(a)}this.title_div_=null,this.xlabel_div_=null,this.ylabel_div_=null,this.y2label_div_=null};n.prototype.layout=function(t){this.detachLabels_();var e,a,n=t.dygraph,i=t.chart_div;n.getOption("title")&&(a=t.reserveSpaceTop(n.getOption("titleHeight")),this.title_div_=r(a),this.title_div_.style.fontSize=n.getOption("titleHeight")-8+"px",(a=document.createElement("div")).className="dygraph-label dygraph-title",a.innerHTML=n.getOption("title"),this.title_div_.appendChild(a),i.appendChild(this.title_div_)),n.getOption("xlabel")&&(e=t.reserveSpaceBottom(n.getOption("xLabelHeight")),this.xlabel_div_=r(e),this.xlabel_div_.style.fontSize=n.getOption("xLabelHeight")-2+"px",(a=document.createElement("div")).className="dygraph-label dygraph-xlabel",a.innerHTML=n.getOption("xlabel"),this.xlabel_div_.appendChild(a),i.appendChild(this.xlabel_div_)),n.getOption("ylabel")&&(e=t.reserveSpaceLeft(0),this.ylabel_div_=o(n,e,1,"dygraph-label dygraph-ylabel",n.getOption("ylabel")),i.appendChild(this.ylabel_div_)),n.getOption("y2label")&&2==n.numAxes()&&(a=t.reserveSpaceRight(0),this.y2label_div_=o(n,a,2,"dygraph-label dygraph-y2label",n.getOption("y2label")),i.appendChild(this.y2label_div_))},n.prototype.didDrawChart=function(t){t=t.dygraph;this.title_div_&&(this.title_div_.children[0].innerHTML=t.getOption("title")),this.xlabel_div_&&(this.xlabel_div_.children[0].innerHTML=t.getOption("xlabel")),this.ylabel_div_&&(this.ylabel_div_.children[0].children[0].innerHTML=t.getOption("ylabel")),this.y2label_div_&&(this.y2label_div_.children[0].children[0].innerHTML=t.getOption("y2label"))},n.prototype.clearChart=function(){},n.prototype.destroy=function(){this.detachLabels_()},a.default=n,e.exports=a.default},{}],"dygraphs/src/plugins/grid.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;function n(){}n.prototype.toString=function(){return"Gridline Plugin"},n.prototype.activate=function(t){return{willDrawChart:this.willDrawChart}},n.prototype.willDrawChart=function(t){var a,n,e,i=t.dygraph,r=t.drawingContext,o=i.layout_,s=t.dygraph.plotter_.area;function l(t){return Math.round(t)+.5}function h(t){return Math.round(t)-.5}if(i.getOptionForAxis("drawGrid","y")){for(var d=["y","y2"],u=[],c=[],p=[],g=[],f=[],_=0;_<d.length;_++)p[_]=i.getOptionForAxis("drawGrid",d[_]),p[_]&&(u[_]=i.getOptionForAxis("gridLineColor",d[_]),c[_]=i.getOptionForAxis("gridLineWidth",d[_]),f[_]=i.getOptionForAxis("gridLinePattern",d[_]),g[_]=f[_]&&2<=f[_].length);e=o.yticks,r.save(),e.forEach(function(t){var e;t.has_tick&&(e=t.axis,p[e])&&(r.save(),g[e]&&r.setLineDash&&r.setLineDash(f[e]),r.strokeStyle=u[e],r.lineWidth=c[e],a=l(s.x),n=h(s.y+t.pos*s.h),r.beginPath(),r.moveTo(a,n),r.lineTo(a+s.w,n),r.stroke(),r.restore())}),r.restore()}i.getOptionForAxis("drawGrid","x")&&(e=o.xticks,r.save(),f=i.getOptionForAxis("gridLinePattern","x"),(g=f&&2<=f.length)&&r.setLineDash&&r.setLineDash(f),r.strokeStyle=i.getOptionForAxis("gridLineColor","x"),r.lineWidth=i.getOptionForAxis("gridLineWidth","x"),e.forEach(function(t){t.has_tick&&(a=l(s.x+t.pos*s.w),n=h(s.y+s.h),r.beginPath(),r.moveTo(a,n),r.lineTo(a,s.y),r.stroke())}),g&&r.setLineDash&&r.setLineDash([]),r.restore())},n.prototype.destroy=function(){},a.default=n,e.exports=a.default},{}],"dygraphs/src/plugins/legend.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var x=function(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=o(e);if(e&&e.has(t))return e.get(t);var a,n={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t){var r;"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((r=i?Object.getOwnPropertyDescriptor(t,a):null)&&(r.get||r.set)?Object.defineProperty(n,a,r):n[a]=t[a])}n.default=t,e&&e.set(t,n);return n}(t("../dygraph-utils"));function o(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(o=function(t){return t?a:e})(t))}function m(){this.legend_div_=null,this.is_generated_div_=!1}m.prototype.toString=function(){return"Legend Plugin"},m.prototype.activate=function(t){var e,a=t.getOption("labelsDiv");return a&&null!==a?e="string"==typeof a||a instanceof String?document.getElementById(a):a:((e=document.createElement("div")).className="dygraph-legend",t.graphDiv.appendChild(e),this.is_generated_div_=!0),this.legend_div_=e,this.one_em_width_=10,{select:this.select,deselect:this.deselect,predraw:this.predraw,didDrawChart:this.didDrawChart}};m.prototype.select=function(t){var e,a,n,i,r,o=t.selectedX,s=t.selectedPoints,l=t.selectedRow,h=t.dygraph.getOption("legend");"never"===h?this.legend_div_.style.display="none":((o=m.generateLegendHTML(t.dygraph,o,s,this.one_em_width_,l))instanceof Node&&o.nodeType===Node.DOCUMENT_FRAGMENT_NODE?(this.legend_div_.innerHTML="",this.legend_div_.appendChild(o)):this.legend_div_.innerHTML=o,this.legend_div_.style.display="","follow"===h?(i=t.dygraph.plotter_.area,r=this.legend_div_.offsetWidth,l=t.dygraph.getOptionForAxis("axisLabelWidth","y"),n=(e=t.dygraph.getHighlightSeries())&&(n=s.find(function(t){return t.name===e}))||s[0],o=t.dygraph.getNumericOption("legendFollowOffsetX"),s=t.dygraph.getNumericOption("legendFollowOffsetY"),a=n.x*i.w+o,n=n.y*i.h+s,a+r+1>i.w&&(a=a-2*o-r-(l-i.x)),this.legend_div_.style.left=l+a+"px",this.legend_div_.style.top=n+"px"):"onmouseover"===h&&this.is_generated_div_&&(i=t.dygraph.plotter_.area,r=this.legend_div_.offsetWidth,this.legend_div_.style.left=i.x+i.w-r-1+"px",this.legend_div_.style.top=i.y+"px"))},m.prototype.deselect=function(t){"always"!==t.dygraph.getOption("legend")&&(this.legend_div_.style.display="none"),a=this.legend_div_,(n=document.createElement("span")).setAttribute("style","margin: 0; padding: 0 0 0 1em; border: 0;"),a.appendChild(n),e=n.offsetWidth,a.removeChild(n);var e,a=e,n=(this.one_em_width_=a,m.generateLegendHTML(t.dygraph,void 0,void 0,a,null));n instanceof Node&&n.nodeType===Node.DOCUMENT_FRAGMENT_NODE?(this.legend_div_.innerHTML="",this.legend_div_.appendChild(n)):this.legend_div_.innerHTML=n},m.prototype.didDrawChart=function(t){this.deselect(t)},m.prototype.predraw=function(t){var e;this.is_generated_div_&&(t.dygraph.graphDiv.appendChild(this.legend_div_),t=t.dygraph.plotter_.area,e=this.legend_div_.offsetWidth,this.legend_div_.style.left=t.x+t.w-e-1+"px",this.legend_div_.style.top=t.y+"px")},m.prototype.destroy=function(){this.legend_div_=null},m.generateLegendHTML=function(t,e,a,n,i){var r={dygraph:t,x:e,i:i,series:[]},o={},s=t.getLabels();if(s)for(var l=1;l<s.length;l++){var h=t.getPropertiesForSeries(s[l]),d={dashHTML:function(t,e,a){if(!t||t.length<=1)return'<div class="dygraph-legend-line" style="border-bottom-color: '.concat(e,';"></div>');var n,i,r,o,s,l=0,h=0,d=[];for(n=0;n<=t.length;n++)l+=t[n%t.length];if(1<(s=Math.floor(a/(l-t[0])))){for(n=0;n<t.length;n++)d[n]=t[n]/a;h=d.length}else{for(s=1,n=0;n<t.length;n++)d[n]=t[n]/l;h=d.length+1}var u="";for(i=0;i<s;i++)for(n=0;n<h;n+=2)r=d[n%d.length],o=n<t.length?d[(n+1)%d.length]:0,u+='<div class="dygraph-legend-dash" style="margin-right: '.concat(o,"em; padding-left: ").concat(r,'em;"></div>');return u}(t.getOption("strokePattern",s[l]),h.color,n),label:s[l],labelHTML:s[l].replace(/&/g,"&amp;").replace(/"/g,"&#34;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),isVisible:h.visible,color:h.color};r.series.push(d),o[s[l]]=d}if(void 0!==e){for(var u=t.optionsViewForAxis_("x"),c=u("valueFormatter"),p=(r.xHTML=c.call(t,e,u,s[0],t,i,0),[]),g=t.numAxes(),l=0;l<g;l++)p[l]=t.optionsViewForAxis_("y"+(l?1+l:""));var f=t.getOption("labelsShowZeroValues"),_=t.getHighlightSeries();for(l=0;l<a.length;l++){var y,v=a[l];(d=o[v.name]).y=v.yval,0===v.yval&&!f||isNaN(v.canvasy)?d.isVisible=!1:(y=(y=p[(h=t.getPropertiesForSeries(v.name)).axis-1])("valueFormatter").call(t,v.yval,y,v.name,t,i,s.indexOf(v.name)),x.update(d,{yHTML:y}),v.name==_&&(d.isHighlighted=!0))}}return(t.getOption("legendFormatter")||m.defaultFormatter).call(t,r)},m.defaultFormatter=function(t){var e=t.dygraph;if(!0!==e.getOption("showLabelsOnHighlight"))return"";var a=e.getOption("labelsSeparateLines");if(void 0===t.x){if("always"!=e.getOption("legend"))return"";for(var n="",i=0;i<t.series.length;i++)(r=t.series[i]).isVisible&&(""!==n&&(n+=a?"<br />":" "),n+="<span style='font-weight: bold; color: ".concat(r.color,";'>").concat(r.dashHTML," ").concat(r.labelHTML,"</span>"))}else{n=t.xHTML+":";for(var r,o,i=0;i<t.series.length;i++)((r=t.series[i]).y||r.yHTML)&&r.isVisible&&(a&&(n+="<br>"),o=r.isHighlighted?' class="highlight"':"",n+="<span".concat(o,"> <b><span style='color: ").concat(r.color,";'>").concat(r.labelHTML,"</span></b>:&#160;").concat(r.yHTML,"</span>"))}return n},a.default=m,e.exports=a.default},{"../dygraph-utils":"dygraphs/src/dygraph-utils.js"}],"dygraphs/src/plugins/range-selector.js":[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0}),a.default=void 0;var O=function(t,e){if(!e&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};e=o(e);if(e&&e.has(t))return e.get(t);var a,n={},i=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(a in t){var r;"default"!==a&&Object.prototype.hasOwnProperty.call(t,a)&&((r=i?Object.getOwnPropertyDescriptor(t,a):null)&&(r.get||r.set)?Object.defineProperty(n,a,r):n[a]=t[a])}n.default=t,e&&e.set(t,n);return n}(t("../dygraph-utils")),A=n(t("../dygraph-interaction-model")),P=n(t("../iframe-tarp"));function n(t){return t&&t.__esModule?t:{default:t}}function o(t){var e,a;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=new WeakMap,(o=function(t){return t?a:e})(t))}function i(){this.hasTouchInterface_="undefined"!=typeof TouchEvent,this.isMobileDevice_=/mobile|android/gi.test(navigator.appVersion),this.interfaceCreated_=!1}i.prototype.toString=function(){return"RangeSelector Plugin"},i.prototype.activate=function(t){return this.dygraph_=t,this.getOption_("showRangeSelector")&&this.createInterface_(),{layout:this.reserveSpace_,predraw:this.renderStaticLayer_,didDrawChart:this.renderInteractiveLayer_}},i.prototype.destroy=function(){this.bgcanvas_=null,this.fgcanvas_=null,this.leftZoomHandle_=null,this.rightZoomHandle_=null},i.prototype.getOption_=function(t,e){return this.dygraph_.getOption(t,e)},i.prototype.setDefaultOption_=function(t,e){this.dygraph_.attrs_[t]=e},i.prototype.createInterface_=function(){this.createCanvases_(),this.createZoomHandles_(),this.initInteraction_(),this.getOption_("animatedZooms")&&(console.warn("Animated zooms and range selector are not compatible; disabling animatedZooms."),this.dygraph_.updateOptions({animatedZooms:!1},!0)),this.interfaceCreated_=!0,this.addToGraph_()},i.prototype.addToGraph_=function(){var t=this.graphDiv_=this.dygraph_.graphDiv;t.appendChild(this.bgcanvas_),t.appendChild(this.fgcanvas_),t.appendChild(this.leftZoomHandle_),t.appendChild(this.rightZoomHandle_)},i.prototype.removeFromGraph_=function(){var t=this.graphDiv_;t.removeChild(this.bgcanvas_),t.removeChild(this.fgcanvas_),t.removeChild(this.leftZoomHandle_),t.removeChild(this.rightZoomHandle_),this.graphDiv_=null},i.prototype.reserveSpace_=function(t){this.getOption_("showRangeSelector")&&t.reserveSpaceBottom(this.getOption_("rangeSelectorHeight")+4)},i.prototype.renderStaticLayer_=function(){this.updateVisibility_()&&(this.resize_(),this.drawStaticLayer_())},i.prototype.renderInteractiveLayer_=function(){this.updateVisibility_()&&!this.isChangingRange_&&(this.placeZoomHandles_(),this.drawInteractiveLayer_())},i.prototype.updateVisibility_=function(){var t,e=this.getOption_("showRangeSelector");return e?this.interfaceCreated_?this.graphDiv_&&this.graphDiv_.parentNode||this.addToGraph_():this.createInterface_():this.graphDiv_&&(this.removeFromGraph_(),t=this.dygraph_,setTimeout(function(){t.width_=0,t.resize()},1)),e},i.prototype.resize_=function(){function t(t,e,a,n){n=n||O.getContextPixelRatio(e);t.style.top=a.y+"px",t.style.left=a.x+"px",t.width=a.w*n,t.height=a.h*n,t.style.width=a.w+"px",t.style.height=a.h+"px",1!=n&&e.scale(n,n)}var e=this.dygraph_.layout_.getPlotArea(),a=0,a=(this.dygraph_.getOptionForAxis("drawAxis","x")&&(a=this.getOption_("xAxisHeight")||this.getOption_("axisLabelFontSize")+2*this.getOption_("axisTickSize")),this.canvasRect_={x:e.x,y:e.y+e.h+a+4,w:e.w,h:this.getOption_("rangeSelectorHeight")},this.dygraph_.getNumericOption("pixelRatio"));t(this.bgcanvas_,this.bgcanvas_ctx_,this.canvasRect_,a),t(this.fgcanvas_,this.fgcanvas_ctx_,this.canvasRect_,a)},i.prototype.createCanvases_=function(){this.bgcanvas_=O.createCanvas(),this.bgcanvas_.className="dygraph-rangesel-bgcanvas",this.bgcanvas_.style.position="absolute",this.bgcanvas_.style.zIndex=9,this.bgcanvas_ctx_=O.getContext(this.bgcanvas_),this.fgcanvas_=O.createCanvas(),this.fgcanvas_.className="dygraph-rangesel-fgcanvas",this.fgcanvas_.style.position="absolute",this.fgcanvas_.style.zIndex=9,this.fgcanvas_.style.cursor="default",this.fgcanvas_ctx_=O.getContext(this.fgcanvas_)},i.prototype.createZoomHandles_=function(){var t=new Image;t.className="dygraph-rangesel-zoomhandle",t.style.position="absolute",t.style.zIndex=10,t.style.visibility="hidden",t.style.cursor="col-resize",t.width=9,t.height=16,t.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAQCAYAAADESFVDAAAAAXNSR0IArs4c6QAAAAZiS0dEANAAzwDP4Z7KegAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB9sHGw0cMqdt1UwAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAaElEQVQoz+3SsRFAQBCF4Z9WJM8KCDVwownl6YXsTmCUsyKGkZzcl7zkz3YLkypgAnreFmDEpHkIwVOMfpdi9CEEN2nGpFdwD03yEqDtOgCaun7sqSTDH32I1pQA2Pb9sZecAxc5r3IAb21d6878xsAAAAAASUVORK5CYII=",this.isMobileDevice_&&(t.width*=2,t.height*=2),this.leftZoomHandle_=t,this.rightZoomHandle_=t.cloneNode(!1)},i.prototype.initInteraction_=function(){var i=this,e=document,r=0,n=null,o=!1,s=!1,l=!this.isMobileDevice_,a=new P.default,h=function(t){var e=i.dygraph_.xAxisExtremes(),a=(e[1]-e[0])/i.canvasRect_.w;return[e[0]+(t.leftHandlePos-i.canvasRect_.x)*a,e[0]+(t.rightHandlePos-i.canvasRect_.x)*a]},d=function(t){return O.cancelEvent(t),o=!0,r=t.clientX,n=t.target||t.srcElement,"mousedown"!==t.type&&"dragstart"!==t.type||(O.addEvent(e,"mousemove",u),O.addEvent(e,"mouseup",c)),i.fgcanvas_.style.cursor="col-resize",a.cover(),!0},u=function(t){if(!o)return!1;O.cancelEvent(t);var e,a=t.clientX-r;return Math.abs(a)<4||(r=t.clientX,t=i.getZoomHandleStatus_(),e=n==i.leftZoomHandle_?(e=t.leftHandlePos+a,e=Math.min(e,t.rightHandlePos-n.width-3),Math.max(e,i.canvasRect_.x)):(e=t.rightHandlePos+a,e=Math.min(e,i.canvasRect_.x+i.canvasRect_.w),Math.max(e,t.leftHandlePos+n.width+3)),a=n.width/2,n.style.left=e-a+"px",i.drawInteractiveLayer_(),l&&p()),!0},c=function(t){return!!o&&(o=!1,a.uncover(),O.removeEvent(e,"mousemove",u),O.removeEvent(e,"mouseup",c),i.fgcanvas_.style.cursor="default",l||p(),!0)},p=function(){try{var t,e=i.getZoomHandleStatus_();i.isChangingRange_=!0,e.isZoomed?(t=h(e),i.dygraph_.doZoomXDates_(t[0],t[1])):i.dygraph_.resetZoom()}finally{i.isChangingRange_=!1}},g=function(t){var e=i.leftZoomHandle_.getBoundingClientRect(),a=e.left+e.width/2,e=(e=i.rightZoomHandle_.getBoundingClientRect()).left+e.width/2;return t.clientX>a&&t.clientX<e},f=function(t){return!(s||!g(t)||!i.getZoomHandleStatus_().isZoomed||(O.cancelEvent(t),s=!0,r=t.clientX,"mousedown"===t.type&&(O.addEvent(e,"mousemove",_),O.addEvent(e,"mouseup",y)),0))},_=function(t){if(!s)return!1;O.cancelEvent(t);var e,a,n=t.clientX-r;return Math.abs(n)<4||(r=t.clientX,e=(t=i.getZoomHandleStatus_()).leftHandlePos,a=(t=t.rightHandlePos)-e,e+n<=i.canvasRect_.x?t=(e=i.canvasRect_.x)+a:t+n>=i.canvasRect_.x+i.canvasRect_.w?e=(t=i.canvasRect_.x+i.canvasRect_.w)-a:(e+=n,t+=n),a=i.leftZoomHandle_.width/2,i.leftZoomHandle_.style.left=e-a+"px",i.rightZoomHandle_.style.left=t-a+"px",i.drawInteractiveLayer_(),l&&v()),!0},y=function(t){return!!s&&(s=!1,O.removeEvent(e,"mousemove",_),O.removeEvent(e,"mouseup",y),l||v(),!0)},v=function(){try{i.isChangingRange_=!0,i.dygraph_.dateWindow_=h(i.getZoomHandleStatus_()),i.dygraph_.drawGraph_(!1)}finally{i.isChangingRange_=!1}},t=function(t){o||s||(t=g(t)?"move":"default")!=i.fgcanvas_.style.cursor&&(i.fgcanvas_.style.cursor=t)},x=function(t){"touchstart"==t.type&&1==t.targetTouches.length?d(t.targetTouches[0])&&O.cancelEvent(t):"touchmove"==t.type&&1==t.targetTouches.length?u(t.targetTouches[0])&&O.cancelEvent(t):c(t)},m=function(t){"touchstart"==t.type&&1==t.targetTouches.length?f(t.targetTouches[0])&&O.cancelEvent(t):"touchmove"==t.type&&1==t.targetTouches.length?_(t.targetTouches[0])&&O.cancelEvent(t):y(t)},b=function(t,e){for(var a=["touchstart","touchend","touchmove","touchcancel"],n=0;n<a.length;n++)i.dygraph_.addAndTrackEvent(t,a[n],e)},w=(this.setDefaultOption_("interactionModel",A.default.dragIsPanInteractionModel),this.setDefaultOption_("panEdgeFraction",1e-4),window.opera?"mousedown":"dragstart");this.dygraph_.addAndTrackEvent(this.leftZoomHandle_,w,d),this.dygraph_.addAndTrackEvent(this.rightZoomHandle_,w,d),this.dygraph_.addAndTrackEvent(this.fgcanvas_,"mousedown",f),this.dygraph_.addAndTrackEvent(this.fgcanvas_,"mousemove",t),this.hasTouchInterface_&&(b(this.leftZoomHandle_,x),b(this.rightZoomHandle_,x),b(this.fgcanvas_,m))},i.prototype.drawStaticLayer_=function(){var t=this.bgcanvas_ctx_;t.clearRect(0,0,this.canvasRect_.w,this.canvasRect_.h);try{this.drawMiniPlot_()}catch(t){console.warn(t)}this.bgcanvas_ctx_.lineWidth=this.getOption_("rangeSelectorBackgroundLineWidth"),t.strokeStyle=this.getOption_("rangeSelectorBackgroundStrokeColor"),t.beginPath(),t.moveTo(.5,.5),t.lineTo(.5,this.canvasRect_.h-.5),t.lineTo(this.canvasRect_.w-.5,this.canvasRect_.h-.5),t.lineTo(this.canvasRect_.w-.5,.5),t.stroke()},i.prototype.drawMiniPlot_=function(){var t=this.getOption_("rangeSelectorPlotFillColor"),e=this.getOption_("rangeSelectorPlotFillGradientColor"),a=this.getOption_("rangeSelectorPlotStrokeColor");if(t||a){var n=this.getOption_("stepPlot"),i=this.computeCombinedSeriesAndLimits_(),r=i.yMax-i.yMin,o=this.bgcanvas_ctx_,s=this.dygraph_.xAxisExtremes(),l=Math.max(s[1]-s[0],1e-30),h=(this.canvasRect_.w-.5)/l,d=(this.canvasRect_.h-.5)/r,l=this.canvasRect_.w-.5,u=this.canvasRect_.h-.5,c=null,p=null;o.beginPath(),o.moveTo(.5,u);for(var g=0;g<i.data.length;g++){var f=i.data[g],_=null!==f[0]?(f[0]-s[0])*h:NaN,f=null!==f[1]?u-(f[1]-i.yMin)*d:NaN;!n&&null!==c&&Math.round(_)==Math.round(c)||(isFinite(_)&&isFinite(f)?(null===c?o.lineTo(_,u):n&&o.lineTo(_,p),o.lineTo(_,f),c=_,p=f):(null!==c&&(n?(o.lineTo(_,p),o.lineTo(_,u)):o.lineTo(c,u)),c=p=null))}o.lineTo(l,u),o.closePath(),t&&(r=this.bgcanvas_ctx_.createLinearGradient(0,0,0,u),e&&r.addColorStop(0,e),r.addColorStop(1,t),this.bgcanvas_ctx_.fillStyle=r,o.fill()),a&&(this.bgcanvas_ctx_.strokeStyle=a,this.bgcanvas_ctx_.lineWidth=this.getOption_("rangeSelectorPlotLineWidth"),o.stroke())}},i.prototype.computeCombinedSeriesAndLimits_=function(){for(var t=this.dygraph_,e=this.getOption_("logscale"),a=t.numColumns(),n=t.getLabels(),i=new Array(a),r=!1,o=t.visibility(),s=[],l=1;l<a;l++){var h=this.getOption_("showInRangeSelector",n[l]);s.push(h),null!==h&&(r=!0)}if(r)for(l=1;l<a;l++)i[l]=s[l-1];else for(l=1;l<a;l++)i[l]=o[l-1];var d,u=[],c=t.dataHandler_,p=t.attributes_;for(l=1;l<t.numColumns();l++)i[l]&&(d=c.extractSeries(t.rawData_,l,p),1<t.rollPeriod()&&(d=c.rollingAverage(d,t.rollPeriod(),p,l)),u.push(d));var g=[];for(l=0;l<u[0].length;l++){for(var f=0,_=0,y=0;y<u.length;y++){var v=u[y][l][1];null===v||isNaN(v)||(_++,f+=v)}g.push([u[0][l][0],f/_])}var x=Number.MAX_VALUE,m=-Number.MAX_VALUE;for(l=0;l<g.length;l++){var b=g[l][1];null!==b&&isFinite(b)&&(!e||0<b)&&(x=Math.min(x,b),m=Math.max(m,b))}if(e)for(m=O.log10(m),m+=.25*m,x=O.log10(x),l=0;l<g.length;l++)g[l][1]=O.log10(g[l][1]);else{var w=m-x,w=w<=Number.MIN_VALUE?.25*m:.25*w;m+=w,x-=w}return{data:g,yMin:x,yMax:m}},i.prototype.placeZoomHandles_=function(){var t=this.dygraph_.xAxisExtremes(),e=this.dygraph_.xAxisRange(),a=t[1]-t[0],n=Math.max(0,(e[0]-t[0])/a),t=Math.max(0,(t[1]-e[1])/a),e=this.canvasRect_.x+this.canvasRect_.w*n,a=this.canvasRect_.x+this.canvasRect_.w*(1-t),n=Math.max(this.canvasRect_.y,this.canvasRect_.y+(this.canvasRect_.h-this.leftZoomHandle_.height)/2),t=this.leftZoomHandle_.width/2;this.leftZoomHandle_.style.left=e-t+"px",this.leftZoomHandle_.style.top=n+"px",this.rightZoomHandle_.style.left=a-t+"px",this.rightZoomHandle_.style.top=this.leftZoomHandle_.style.top,this.leftZoomHandle_.style.visibility="visible",this.rightZoomHandle_.style.visibility="visible"},i.prototype.drawInteractiveLayer_=function(){var t,e,a=this.fgcanvas_ctx_,n=(a.clearRect(0,0,this.canvasRect_.w,this.canvasRect_.h),this.canvasRect_.w-1),i=this.canvasRect_.h-1,r=this.getZoomHandleStatus_();a.strokeStyle=this.getOption_("rangeSelectorForegroundStrokeColor"),a.lineWidth=this.getOption_("rangeSelectorForegroundLineWidth"),r.isZoomed?(t=Math.max(1,r.leftHandlePos-this.canvasRect_.x),r=Math.min(n,r.rightHandlePos-this.canvasRect_.x),e=this.getOption_("rangeSelectorVeilColour"),a.fillStyle=e||"rgba(240, 240, 240, "+this.getOption_("rangeSelectorAlpha").toString()+")",a.fillRect(0,0,t,this.canvasRect_.h),a.fillRect(r,0,this.canvasRect_.w-r,this.canvasRect_.h),a.beginPath(),a.moveTo(1,1),a.lineTo(t,1),a.lineTo(t,i),a.lineTo(r,i),a.lineTo(r,1)):(a.beginPath(),a.moveTo(1,1),a.lineTo(1,i),a.lineTo(n,i)),a.lineTo(n,1),a.stroke()},i.prototype.getZoomHandleStatus_=function(){var t=this.leftZoomHandle_.width/2,e=parseFloat(this.leftZoomHandle_.style.left)+t,t=parseFloat(this.rightZoomHandle_.style.left)+t;return{leftHandlePos:e,rightHandlePos:t,isZoomed:e-1>this.canvasRect_.x||t+1<this.canvasRect_.x+this.canvasRect_.w}},a.default=i,e.exports=a.default},{"../dygraph-interaction-model":"dygraphs/src/dygraph-interaction-model.js","../dygraph-utils":"dygraphs/src/dygraph-utils.js","../iframe-tarp":"dygraphs/src/iframe-tarp.js"}]},{},["dygraphs/src/dygraph.js"]),e=t("dygraphs/src/dygraph.js");return e._require._b=t,e});
</script>
<h2>PHY62x2 BTHome <a href="https://github.com/pvvx/THB2"><small>&#9432;</small></a></h2>
<label for="inpNamePrefix" data-i18ntag="PREFIX">Префикс имени устройств(а)</label>
<input type="text" id="inpNamePrefix" value="" placeholder="THB, BT, TH">
<br>
<button type="button" id="btnConnect" onclick="connect()" data-i18ntag="CONNECT">Соединение</button>
<button type="button" id="btnDisconnect" onclick="disconnect()" disabled="true" data-i18ntag="DISCONNECT">Отключение</button>
<button type="button" id="btnReconnect" onclick="reconnect()" disabled="true" data-i18ntag="RECONNECT">Переподключение</button>
<hr id="hrSensorData" hidden>
<table id="tblSensorData" hidden>
<tr>
<th data-i18ntag="TIME">Время</th>
<th data-i18ntag="TEMPERATURE">Температура</th>
<th data-i18ntag="HUMIDITY">Влажность</th>
<th data-i18ntag="BATTERYSTATE">Состояние батареи</th>
</tr>
<tr align="center">
<td><label id="lblTime">---/--/-- --:--:--</label></td>
<td><label id="lblTemp">-- °C</label></td>
<td><label id="lblHumi">-- %RH</label></td>
<td><label id="lblBat">-- % (-- V)</label></td>
<td><label id="lblTrg"></label></td>
</tr>
</table>
<hr>
<div class="tab">
<button class="tablinks" onclick="openTab(event, 'tabConfig')">Config</button>
<button class="tablinks" onclick="openTab(event, 'tabOTA')">OTA</button>
<button class="tablinks" onclick="openTab(event, 'tabCharts')">Chart</button>
<button class="tablinks" onclick="openTab(event, 'tabService')">Service</button>
</div>
<div id="tabConfig" class="tabcontent">
<span data-i18ntag="BASIC_INST">Основные установки</span>
<table id="tblChkCfg">
<tr align="left">
<td><label><input type="checkbox" id="chkCfgClock"/><span data-i18ntag="SHOW_TIME">Показывать время</span></label></td>
<td><label><input type="checkbox" id="chkCfgSmiley"/><span data-i18ntag="SHOW_SMILEY">Отображать смайлик</span></label></td>
<td><label><input type="checkbox" id="chkCfgTrg"/><span data-i18ntag="SHOW_TRIGGER">Отображать триггер</span></label></td>
<td><label><input type="checkbox" id="chkCfgLcdOff"/><span data-i18ntag="DISCONNECT_DISPLAY">Отключить дисплей</span></label></td>
<td><label><input type="checkbox" id="chkCfgFahrenheit"/><span data-i18ntag="SHOW_TEMPF">Показывать температуру в градусах Фаренгейта</span></label></td>
</tr>
</table>
<table id="tblButton">
<tr>
<td><label><input type="checkbox" id="chkCfgFindMy"/>FindMy</label></td>
</tr>
</table>
<table>
<tr>
<td>
<label><input type="checkbox" id="chkCfgNotify" title="Передача измерений при соединении и включении Notification"/>Notification</label>
<label id="labBindKey"><input type="checkbox" id="chkCfgBindKey" title="Используется BindKey"/><span data-i18ntag="ENCRYPTED_AD">Шифрованная реклама</span></label></td>
</tr>
</table>
<table>
<tr>
<td>Tx Power:
<select id="selTxPwr">
<option value="63">+5 dBm</option>
<option value="31" selected>+0 dBm</option>
<option value="23">-5 dBm</option>
<option value="15">-10 dBm</option>
<option value="7">-15 dBm</option>
<option value="0">-20 dBm</option>
</select>
</td>
</tr>
<tr>
<td>Conn. Latency: <input size="4" type="text" id="inpLat" maxlength="8" title="Connect latency, Итоговый интервал = 30 * (Connect latency + 1) мс"><span data-i18ntag="MS">мс</span></td>
</tr>
<tr>
<td><span data-i18ntag="AD_INTERVAL">Период рекламы</span>:<input size="4" type="text" id="inpAdvInt" onchange="chkDevCfg()" maxlength="8" title="Интервал BLE рекламы в мс, кратность 62.5 мс"><span data-i18ntag="MS">мс</span></td>
</tr>
</table>
<table>
<tr id="trMeasStep">
<td><span data-i18ntag="MEASUREMENT_STEP">Шаг измерений</span>: <input size="4" type="text" id="inpMeasInt" onchange="chkDevCfg()" maxlength="8" title="Опрос датчика в интервалах BLE рекламы, минимум 2 интервала рекламы"><label id="lblMeasInt"></label><span data-i18ntag="MS">мс</span></td>
</tr>
<tr>
<td><span>Number of event transmissions</span>: <input size="4" type="text" id="inpEvAdvCnt" maxlength="8" title="В штуках, минимум 6, максимум 255"></td>
</tr>
<tr>
<td><span data-i18ntag="BAT_INTERVAL">Опрос батареи</span>: <input size="4" type="text" id="inpBatInt" maxlength="8" title="В секундах, обрабатывается кратно интервалу BLE рекламы, минимум 2 секунды"><span data-i18ntag="SECONDS">сек.</span></td>
</tr>
<tr id="trHistStep">
<td><span data-i18ntag="HISTORY_INTERVAL">Запись истории</span>: <input size="4" type="text" id="inpAverInt" onchange="chkDevCfg()" maxlength="8" title="Запись истории: 0 - отключена, 1...255 * шаг опроса датчика = интервал записи истории"><label id="lblAverInt"></label></td>
</tr>
</table>
<button type="button"id="btnGetDev" onclick="getDevCfg()" data-i18ntag="READ">Прочитать</button>
<button type="button"id="btnSetDev" onclick="setDevCfg()" data-i18ntag="WRITE">Записать</button>
<button type="button"id="btnRstDev" onclick="resetDevCfg()" title="Восстановить стандартные параметры связи">Default</button>
<hr>
<table id="tblTime">
<tr>
<td><button type="button" id="btnGetDevTime" onclick="getDevTime()" data-i18ntag="GET_DEVICETIME">Время устройства</button></td>
<td><button type="button" id="btnSetDevTime" onclick="setDevTime()" data-i18ntag="SET_DEVICETIME">Установить время</button></td>
<td><label id="lbDeltaTime"></label></td>
</tr>
</table>
<div id="hrPres">
<hr>
<table id="tblComfort">
<tr>
<td style="width:75px;"><b data-i18ntag="COMFORT">Комфорт</b></td>
<td><span data-i18ntag="TEMPERATURE">Температура от</span> <input size="4" type="text" id="inpTempMin" maxlength="8" title="Минимальная температура">
<span data-i18ntag="FROMTO_TO">до</span> <input size="4" type="text" id="inpTempMax" maxlength="8" title="Максимальная температура"> °C,</td>
<td><span data-i18ntag="HUMIDITY">Влажность от</span> <input size="4" type="text" id="inpHumiMin" maxlength="8" title="Минимальная влажность">
<span data-i18ntag="FROMTO_TO">до</span> <input size="4" type="text" id="inpHumiMax" maxlength="8" title="Максимальная влажность"> %RH</td>
</tr>
</table>
<table id="tblTrigger">
<tr>
<td style="width:75px;"><b data-i18ntag="TRIGGER">Триггер</b></td>
<td><span data-i18ntag="TEMPERATURE">Температура</span>: <input size="4" type="text" id="inpTempThr" maxlength="8" title="Порог температуры"> °C, </td>
<td><span data-i18ntag="HUMIDITY">Влажность</span>: <input size="4" type="text" id="inpHumiThr" maxlength="8" title="Порог влажности"> %RH, </td>
<td><span data-i18ntag="HYSTERESIS">Гистерезис</span>: <input size="4" type="text" id="inpTempHsr" maxlength="8" title="Гистерезис температуры, если =0 - обработка отключена, если отрицательный - выход включен при температуре менее заданной (нагреватель)"> °C</td>
<td><input size="4" type="text" id="inpHumiHsr" maxlength="8" title="Гистерезис влажности, если =0 - обработка отключена, если отрицательный - выход включен при влажности менее заданной (увлажнитель)"> %RH, </td>
<td><label><input type="checkbox" id="chkInvOut"/><span data-i18ntag="OUTPUT_INVERTED">Инверсия вывода</span></label></td>
</tr>
</table>
<table id="tblTriggerKeys">
<tr>
<td><button type="button"id="btnGetTrg" onclick="getTrgCfg()" data-i18ntag="READ">Прочитать</button></td>
<td><button type="button"id="btnSetTrg" onclick="setTrgCfg()" data-i18ntag="WRITE">Записать</button></td>
</tr>
</table>
<hr>
<span data-i18ntag="SENSOR_PARAMS">Параметры сенсора</span>&emsp;<b><label id="lblSensor">?</label></b>
<table id="tblSensorTH">
<tr>
<th></th>
<th data-i18ntag="TEMPERATURE">Температура</th>
<th data-i18ntag="HUMIDITY">Влажность</th>
</tr>
<tr>
<th></th>
</tr>
<tr>
<td data-i18ntag="CORRECTION_COEFF">Поправочные коэффициенты</td>
<td align="center"><input size="8" type="text" id="inpTempK" maxlength="8" title="*0.01 = Коэффициент угла наклона (линейная функция) для расчета температуры"></td>
<td align="center"><input size="8" type="text" id="inpHumK" maxlength="8" title="*0.01 = Коэффициент угла наклона (линейная функция) для расчета влажности"></td>
</tr>
<tr>
<td data-i18ntag="CORRECTION_DISPLAY">Коррекция смещения</td>
<td><input size="8" type="text" id="inpTempZ" maxlength="8" title="*0.01C = Смещение нуля с поправочным значением для расчета температуры"></td>
<td><input size="8" type="text" id="inpHumZ" maxlength="8" title="*0.01% = Смещение нуля с поправочным значением для расчета влажности"></td>
</tr>
</table>
<br>
<button type="button"id="btnGetSens" onclick="getSensCfg()" data-i18ntag="READ">Прочитать</button>
<button type="button"id="btnSetSens" onclick="setSensCfg()" data-i18ntag="WRITE">Записать</button>
<button type="button"id="btnRstSens" onclick="resetSensCfg()" title="Восстановить стандартные параметры сенсора" data-i18ntag="RESTORE">Восстановить</button>
</div>
</div>
<div id="tabOTA" class="tabcontent">
<p><span data-i18ntag="FILE">Файл(ы) прошивки</span>:
<div id="divOTA"></div>
<input type="file" hidden accept=".bin,application/octet-stream" id="inpFile">
<label id="lblFile" data-i18ntag="NO_FILE">не выбран</label>
<button type="button" onClick="$('inpFile').click()" data-i18ntag="SELECT_UPLOAD">Выбрать</button>
<div hidden>URL: <input type="text" id="inpUrl"></div>
<p>
<hr>
<button type="button" id="btnStartDFU" onclick="startDFU()" disabled="true" data-i18ntag="START_OTA">Старт</button>
</div>
<div id="tabCharts" class="tabcontent">
<div id="divChart"></div>
<!--div id="divLabels"></div-->
<p><a href="GraphMemo.html" target="_blank">Memo Chart</a> - <span data-i18ntag="SHOW_HISTORY">График истории замеров</span></p>
</div>
<div id="tabService" class="tabcontent">
<span data-i18ntag="MEM_RW">Чтение и запись памяти</span><br>
<table>
<tr>
<td style="width:100px;"><span data-i18ntag="ADDRESS">Адрес</span> (hex):</td>
<td><button type="button" id="btnReadAddr" style="width:120px;" onclick="readAddress()" data-i18ntag="READ">Прочитать</button></td>
<td><span data-i18ntag="DATA">Данные</span> (hex):</td>
</tr>
<tr>
<td><input size="8" type="text" id="inpAddr" value="11000000" maxlength="8"></td>
<td><button type="button" id="btnWriteAddr" onclick="writeAddress()" style="width:120px;" data-i18ntag="WRITE">Записать</button></td>
<td><input size="32" type="text" id="inpData" value="?" maxlength="32"></td>
</tr>
</table>
<hr>
<table>
<tr>
<td style="width:100px;"><span data-i18ntag="COMMAND">Команда</span>:</td>
<td><button type="button" id="btnSendCommand" onclick="sendCommand()" style="width:120px;" data-i18ntag="SEND">Выполнить</button></td>
<td><input type="text" id="inpCmdData" value="55" maxlength="50"></td>
</tr>
</table>
<hr>
<table>
<tr>
<td style="width:100px;">MAC <span data-i18ntag="ADDRESS">Адрес</span>:</td>
<td><button type="button" id="btnGetMAC" onclick="getDevMAC()" data-i18ntag="READ">Прочитать</button></td>
<td><input type="text" id="inpDevMAC" value="?" maxlength="16"></td>
<td><button type="button" id="btnSetMAC" onclick="setDevMAC()" data-i18ntag="WRITE">Записать</button></td>
</tr>
</table>
<hr>
<table>
<tr>
<td style="width:100px;" data-i18ntag="DEVICENAME">Имя устройства:</td>
<td><button type="button" id="btnGetName" onclick="getDevName()" data-i18ntag="READ">Прочитать</button></td>
<td><input type="text" id="inpDevName" value="" maxlength="19"></td>
<td><button type="button" id="btnSetName" onclick="setDevName(true)" data-i18ntag="WRITE">Записать</button></td>
<td><button type="button" id="btnRstName" onclick="setDevName(false)" data-i18ntag="RESTORE">По умолчанию</button></td>
</tr>
</table>
<div id="divBindKey">
<hr>
<table>
<tr>
<td style="width:100px;">BindKey:</td>
<td><button type="button" id="btnGetBindKeyy" onclick="getGetBindKey()" data-i18ntag="READ">Прочитать</button></td>
<td><input size="40" maxlength="32" title="Bind Key должен содержать 16 байт в hex виде" type="text" id="inpBindKey" value="?"></td>
<td><button type="button" id="btnBindKey" onclick="setBindKey()" data-i18ntag="WRITE">Записать</button></td>
</tr>
</table>
</div>
<div id="divFindMyKey">
<hr>
<table>
<tr>
<td style="width:100px;">FindMy Key:</td>
<td><button type="button" id="btnGetFindMyKey" onclick="getGetFindMyKey()" data-i18ntag="READ">Прочитать</button></td>
<td><input size="43" maxlength="44" title="FindMy Key должен содержать 22 байта в hex виде" type="text" id="inpFindMyKey" value="?"></td>
<td><button type="button" id="btnSetFindMyKey" onclick="setFindMyKey()" data-i18ntag="WRITE">Записать</button></td>
</tr>
</table>
</div>
<div>
<hr>
<button type="button" id="btnSetMaxMTU" onclick="setMaxMTU()">SetMaxMTU</button>
</div>
</div>
<hr>
<button type="button" onclick="clearLog()" data-i18ntag="CLEAN_LOG">Очистить лог</button>
<label id="lblStatus"></label>
<br>
<div id="log"></div>
</body>
</html>