diff --git a/_deploy b/_deploy
index 808cc75f125..15c089a2afd 160000
--- a/_deploy
+++ b/_deploy
@@ -1 +1 @@
-Subproject commit 808cc75f125cebf5adbb07c2123a85dcf313fc7a
+Subproject commit 15c089a2afd31668d0d3662c8498998b9814ebe9
diff --git a/source/demo/favicon-192x192.png b/source/demo/favicon-192x192.png
new file mode 100644
index 00000000000..2959efdf89d
Binary files /dev/null and b/source/demo/favicon-192x192.png differ
diff --git a/source/demo/favicon-apple-180x180.png b/source/demo/favicon-apple-180x180.png
new file mode 100644
index 00000000000..20117d00f22
Binary files /dev/null and b/source/demo/favicon-apple-180x180.png differ
diff --git a/source/demo/favicon.ico b/source/demo/favicon.ico
new file mode 100644
index 00000000000..6d12158c18b
Binary files /dev/null and b/source/demo/favicon.ico differ
diff --git a/source/demo/frontend.html b/source/demo/frontend.html
index 975b286b776..763effc6616 100644
--- a/source/demo/frontend.html
+++ b/source/demo/frontend.html
@@ -1,25 +1,25431 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /* Palette generated by Material Palette - materialpalette.com/light-blue/orange */ .dark-primary-color { background: #0288D1; } .default-primary-color { background: #03A9F4; } .light-primary-color { background: #B3E5FC; } .text-primary-color { color: #FFFFFF; } .accent-color { background: #FF9800; } .primary-text-color { color: #212121; } .secondary-text-color { color: #727272; } .divider-color { border-color: #B6B6B6; } /* extra */ .accent-text-color { color: #FF9800; } body { color: #212121; } a { color: #FF9800; text-decoration: none; } @-webkit-keyframes ha-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } @keyframes ha-spin { 0% { -webkit-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); transform: rotate(359deg); } } .ha-spin { -webkit-animation: ha-spin 2s infinite linear; animation: ha-spin 2s infinite linear; } :host { font-family: RobotoDraft, 'Helvetica Neue', Helvetica, Arial; min-width: 350px; max-width: 700px; /* First two are from core-transition-bottom */ transition: transform 0.2s ease-in-out, opacity 0.2s ease-in, top .3s, left .3s !important; } :host .sidebar { margin-left: 30px; } @media all and (max-width: 620px) { :host.two-column { margin: 0; width: 100%; max-height: calc(100% - 64px); bottom: 0px; left: 0px; right: 0px; } :host .sidebar { display: none; } } @media all and (max-width: 464px) { :host { margin: 0; width: 100%; max-height: calc(100% - 64px); bottom: 0px; left: 0px; right: 0px; } } html /deep/ .ha-form paper-input { display: block; } html /deep/ .ha-form paper-input:first-child { padding-top: 0; } .data-entry { margin-bottom: 8px; } .data-entry:last-child { margin-bottom: 0; } .data-entry .key { margin-right: 8px; } .data-entry .value { text-align: right; word-break: break-all; } paper-toggle-button::shadow .toggle-ink { color: #039be5; } paper-toggle-button::shadow [checked] .toggle-bar { background-color: #039be5; } paper-toggle-button::shadow [checked] .toggle-button { background-color: #039be5; }
{{label}}
{{label}}
.label-text, .error { color: {{g.paperInput.labelColor}}; } ::-webkit-input-placeholder { color: {{g.paperInput.labelColor}}; } ::-moz-placeholder { color: {{g.paperInput.labelColor}}; } :-ms-input-placeholder { color: {{g.paperInput.labelColor}}; } .unfocused-underline { background-color: {{g.paperInput.labelColor}}; } :host([focused]) .floated-label .label-text { color: {{g.paperInput.focusedColor}}; } .focused-underline { background-color: {{g.paperInput.focusedColor}}; } :host(.invalid) .floated-label .label-text, .error { color: {{g.paperInput.invalidColor}}; } :host(.invalid) .unfocused-underline, :host(.invalid) .focused-underline { background-color: {{g.paperInput.invalidColor}}; } {{label}}
Home Assistant
{{label}}
{{ relativeTime }} {{stateObj.entityDisplay}}
{{stateObj.stateDisplay}}
{{stateObj.stateDisplay}}
Currently: {{stateObj.attributes.current_temperature}} {{stateObj.attributes.unit_of_measurement}}
{{headerTitle}} {{finalTranscript}}
{{interimTranscript}} Hi there! It looks like we have nothing to show you right now. It could be that we have not yet discovered all your devices but it is more likely that you have not configured Home Assistant yet.
Please see the Getting Started section on how to setup your devices.
History
{{ time }} {{entryObj.name}} {{entryObj.name}} {{entryObj.message}}
Logbook
Fire Event {{label}}
Call Service Set State {{heading}}
{{key}}
{{stateObj.attributes[key]}}
Rising
{{stateObj.attributes.next_rising | HATimeStripDate}}
Setting
{{stateObj.attributes.next_setting | HATimeStripDate}}
{{stateObj.attributes.description}}
{{stateObj.attributes.errors}}
{{stateObj.attributes.submit_caption || "Set configuration"}} Configuring…
Last Action
{{stateObj.attributes.last_action}}
Home Assistant
\ No newline at end of file
+ sto = window.setTimeout,
+
+ addEvent = function(el, e, callback, capture)
+ {
+ if (hasEventListeners) {
+ el.addEventListener(e, callback, !!capture);
+ } else {
+ el.attachEvent('on' + e, callback);
+ }
+ },
+
+ removeEvent = function(el, e, callback, capture)
+ {
+ if (hasEventListeners) {
+ el.removeEventListener(e, callback, !!capture);
+ } else {
+ el.detachEvent('on' + e, callback);
+ }
+ },
+
+ fireEvent = function(el, eventName, data)
+ {
+ var ev;
+
+ if (document.createEvent) {
+ ev = document.createEvent('HTMLEvents');
+ ev.initEvent(eventName, true, false);
+ ev = extend(ev, data);
+ el.dispatchEvent(ev);
+ } else if (document.createEventObject) {
+ ev = document.createEventObject();
+ ev = extend(ev, data);
+ el.fireEvent('on' + eventName, ev);
+ }
+ },
+
+ trim = function(str)
+ {
+ return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g,'');
+ },
+
+ hasClass = function(el, cn)
+ {
+ return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1;
+ },
+
+ addClass = function(el, cn)
+ {
+ if (!hasClass(el, cn)) {
+ el.className = (el.className === '') ? cn : el.className + ' ' + cn;
+ }
+ },
+
+ removeClass = function(el, cn)
+ {
+ el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' '));
+ },
+
+ isArray = function(obj)
+ {
+ return (/Array/).test(Object.prototype.toString.call(obj));
+ },
+
+ isDate = function(obj)
+ {
+ return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime());
+ },
+
+ isWeekend = function(date)
+ {
+ var day = date.getDay();
+ return day === 0 || day === 6;
+ },
+
+ isLeapYear = function(year)
+ {
+ // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951
+ return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
+ },
+
+ getDaysInMonth = function(year, month)
+ {
+ return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
+ },
+
+ setToStartOfDay = function(date)
+ {
+ if (isDate(date)) date.setHours(0,0,0,0);
+ },
+
+ compareDates = function(a,b)
+ {
+ // weak date comparison (use setToStartOfDay(date) to ensure correct result)
+ return a.getTime() === b.getTime();
+ },
+
+ extend = function(to, from, overwrite)
+ {
+ var prop, hasProp;
+ for (prop in from) {
+ hasProp = to[prop] !== undefined;
+ if (hasProp && typeof from[prop] === 'object' && from[prop] !== null && from[prop].nodeName === undefined) {
+ if (isDate(from[prop])) {
+ if (overwrite) {
+ to[prop] = new Date(from[prop].getTime());
+ }
+ }
+ else if (isArray(from[prop])) {
+ if (overwrite) {
+ to[prop] = from[prop].slice(0);
+ }
+ } else {
+ to[prop] = extend({}, from[prop], overwrite);
+ }
+ } else if (overwrite || !hasProp) {
+ to[prop] = from[prop];
+ }
+ }
+ return to;
+ },
+
+ adjustCalendar = function(calendar) {
+ if (calendar.month < 0) {
+ calendar.year -= Math.ceil(Math.abs(calendar.month)/12);
+ calendar.month += 12;
+ }
+ if (calendar.month > 11) {
+ calendar.year += Math.floor(Math.abs(calendar.month)/12);
+ calendar.month -= 12;
+ }
+ return calendar;
+ },
+
+ /**
+ * defaults and localisation
+ */
+ defaults = {
+
+ // bind the picker to a form field
+ field: null,
+
+ // automatically show/hide the picker on `field` focus (default `true` if `field` is set)
+ bound: undefined,
+
+ // position of the datepicker, relative to the field (default to bottom & left)
+ // ('bottom' & 'left' keywords are not used, 'top' & 'right' are modifier on the bottom/left position)
+ position: 'bottom left',
+
+ // automatically fit in the viewport even if it means repositioning from the position option
+ reposition: true,
+
+ // the default output format for `.toString()` and `field` value
+ format: 'YYYY-MM-DD',
+
+ // the initial date to view when first opened
+ defaultDate: null,
+
+ // make the `defaultDate` the initial selected value
+ setDefaultDate: false,
+
+ // first day of week (0: Sunday, 1: Monday etc)
+ firstDay: 0,
+
+ // the minimum/earliest date that can be selected
+ minDate: null,
+ // the maximum/latest date that can be selected
+ maxDate: null,
+
+ // number of years either side, or array of upper/lower range
+ yearRange: 10,
+
+ // show week numbers at head of row
+ showWeekNumber: false,
+
+ // used internally (don't config outside)
+ minYear: 0,
+ maxYear: 9999,
+ minMonth: undefined,
+ maxMonth: undefined,
+
+ isRTL: false,
+
+ // Additional text to append to the year in the calendar title
+ yearSuffix: '',
+
+ // Render the month after year in the calendar title
+ showMonthAfterYear: false,
+
+ // how many months are visible
+ numberOfMonths: 1,
+
+ // when numberOfMonths is used, this will help you to choose where the main calendar will be (default `left`, can be set to `right`)
+ // only used for the first display or when a selected date is not visible
+ mainCalendar: 'left',
+
+ // Specify a DOM element to render the calendar in
+ container: undefined,
+
+ // internationalization
+ i18n: {
+ previousMonth : 'Previous Month',
+ nextMonth : 'Next Month',
+ months : ['January','February','March','April','May','June','July','August','September','October','November','December'],
+ weekdays : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'],
+ weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
+ },
+
+ // callback function
+ onSelect: null,
+ onOpen: null,
+ onClose: null,
+ onDraw: null
+ },
+
+
+ /**
+ * templating functions to abstract HTML rendering
+ */
+ renderDayName = function(opts, day, abbr)
+ {
+ day += opts.firstDay;
+ while (day >= 7) {
+ day -= 7;
+ }
+ return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day];
+ },
+
+ renderDay = function(d, m, y, isSelected, isToday, isDisabled, isEmpty)
+ {
+ if (isEmpty) {
+ return ' ';
+ }
+ var arr = [];
+ if (isDisabled) {
+ arr.push('is-disabled');
+ }
+ if (isToday) {
+ arr.push('is-today');
+ }
+ if (isSelected) {
+ arr.push('is-selected');
+ }
+ return '' +
+ '' +
+ d +
+ ' ' +
+ ' ';
+ },
+
+ renderWeek = function (d, m, y) {
+ // Lifted from http://javascript.about.com/library/blweekyear.htm, lightly modified.
+ var onejan = new Date(y, 0, 1),
+ weekNum = Math.ceil((((new Date(y, m, d) - onejan) / 86400000) + onejan.getDay()+1)/7);
+ return '' + weekNum + ' ';
+ },
+
+ renderRow = function(days, isRTL)
+ {
+ return '' + (isRTL ? days.reverse() : days).join('') + ' ';
+ },
+
+ renderBody = function(rows)
+ {
+ return '' + rows.join('') + ' ';
+ },
+
+ renderHead = function(opts)
+ {
+ var i, arr = [];
+ if (opts.showWeekNumber) {
+ arr.push(' ');
+ }
+ for (i = 0; i < 7; i++) {
+ arr.push('' + renderDayName(opts, i, true) + ' ');
+ }
+ return '' + (opts.isRTL ? arr.reverse() : arr).join('') + ' ';
+ },
+
+ renderTitle = function(instance, c, year, month, refYear)
+ {
+ var i, j, arr,
+ opts = instance._o,
+ isMinYear = year === opts.minYear,
+ isMaxYear = year === opts.maxYear,
+ html = '',
+ monthHtml,
+ yearHtml,
+ prev = true,
+ next = true;
+
+ for (arr = [], i = 0; i < 12; i++) {
+ arr.push('
opts.maxMonth) ? 'disabled' : '') + '>' +
+ opts.i18n.months[i] + ' ');
+ }
+ monthHtml = '
' + opts.i18n.months[month] + '' + arr.join('') + '
';
+
+ if (isArray(opts.yearRange)) {
+ i = opts.yearRange[0];
+ j = opts.yearRange[1] + 1;
+ } else {
+ i = year - opts.yearRange;
+ j = 1 + year + opts.yearRange;
+ }
+
+ for (arr = []; i < j && i <= opts.maxYear; i++) {
+ if (i >= opts.minYear) {
+ arr.push('
' + (i) + ' ');
+ }
+ }
+ yearHtml = '
' + year + opts.yearSuffix + '' + arr.join('') + '
';
+
+ if (opts.showMonthAfterYear) {
+ html += yearHtml + monthHtml;
+ } else {
+ html += monthHtml + yearHtml;
+ }
+
+ if (isMinYear && (month === 0 || opts.minMonth >= month)) {
+ prev = false;
+ }
+
+ if (isMaxYear && (month === 11 || opts.maxMonth <= month)) {
+ next = false;
+ }
+
+ if (c === 0) {
+ html += '
' + opts.i18n.previousMonth + ' ';
+ }
+ if (c === (instance._o.numberOfMonths - 1) ) {
+ html += '
' + opts.i18n.nextMonth + ' ';
+ }
+
+ return html += '
';
+ },
+
+ renderTable = function(opts, data)
+ {
+ return '' + renderHead(opts) + renderBody(data) + '
';
+ },
+
+
+ /**
+ * Pikaday constructor
+ */
+ Pikaday = function(options)
+ {
+ var self = this,
+ opts = self.config(options);
+
+ self._onMouseDown = function(e)
+ {
+ if (!self._v) {
+ return;
+ }
+ e = e || window.event;
+ var target = e.target || e.srcElement;
+ if (!target) {
+ return;
+ }
+
+ if (!hasClass(target, 'is-disabled')) {
+ if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty')) {
+ self.setDate(new Date(target.getAttribute('data-pika-year'), target.getAttribute('data-pika-month'), target.getAttribute('data-pika-day')));
+ if (opts.bound) {
+ sto(function() {
+ self.hide();
+ if (opts.field) {
+ opts.field.blur();
+ }
+ }, 100);
+ }
+ return;
+ }
+ else if (hasClass(target, 'pika-prev')) {
+ self.prevMonth();
+ }
+ else if (hasClass(target, 'pika-next')) {
+ self.nextMonth();
+ }
+ }
+ if (!hasClass(target, 'pika-select')) {
+ if (e.preventDefault) {
+ e.preventDefault();
+ } else {
+ e.returnValue = false;
+ return false;
+ }
+ } else {
+ self._c = true;
+ }
+ };
+
+ self._onChange = function(e)
+ {
+ e = e || window.event;
+ var target = e.target || e.srcElement;
+ if (!target) {
+ return;
+ }
+ if (hasClass(target, 'pika-select-month')) {
+ self.gotoMonth(target.value);
+ }
+ else if (hasClass(target, 'pika-select-year')) {
+ self.gotoYear(target.value);
+ }
+ };
+
+ self._onInputChange = function(e)
+ {
+ var date;
+
+ if (e.firedBy === self) {
+ return;
+ }
+ if (hasMoment) {
+ date = moment(opts.field.value, opts.format);
+ date = (date && date.isValid()) ? date.toDate() : null;
+ }
+ else {
+ date = new Date(Date.parse(opts.field.value));
+ }
+ self.setDate(isDate(date) ? date : null);
+ if (!self._v) {
+ self.show();
+ }
+ };
+
+ self._onInputFocus = function()
+ {
+ self.show();
+ };
+
+ self._onInputClick = function()
+ {
+ self.show();
+ };
+
+ self._onInputBlur = function()
+ {
+ // IE allows pika div to gain focus; catch blur the input field
+ var pEl = document.activeElement;
+ do {
+ if (hasClass(pEl, 'pika-single')) {
+ return;
+ }
+ }
+ while ((pEl = pEl.parentNode));
+
+ if (!self._c) {
+ self._b = sto(function() {
+ self.hide();
+ }, 50);
+ }
+ self._c = false;
+ };
+
+ self._onClick = function(e)
+ {
+ e = e || window.event;
+ var target = e.target || e.srcElement,
+ pEl = target;
+ if (!target) {
+ return;
+ }
+ if (!hasEventListeners && hasClass(target, 'pika-select')) {
+ if (!target.onchange) {
+ target.setAttribute('onchange', 'return;');
+ addEvent(target, 'change', self._onChange);
+ }
+ }
+ do {
+ if (hasClass(pEl, 'pika-single') || pEl === opts.trigger) {
+ return;
+ }
+ }
+ while ((pEl = pEl.parentNode));
+ if (self._v && target !== opts.trigger && pEl !== opts.trigger) {
+ self.hide();
+ }
+ };
+
+ self.el = document.createElement('div');
+ self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : '');
+
+ addEvent(self.el, 'mousedown', self._onMouseDown, true);
+ addEvent(self.el, 'change', self._onChange);
+
+ if (opts.field) {
+ if (opts.container) {
+ opts.container.appendChild(self.el);
+ } else if (opts.bound) {
+ document.body.appendChild(self.el);
+ } else {
+ opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling);
+ }
+ addEvent(opts.field, 'change', self._onInputChange);
+
+ if (!opts.defaultDate) {
+ if (hasMoment && opts.field.value) {
+ opts.defaultDate = moment(opts.field.value, opts.format).toDate();
+ } else {
+ opts.defaultDate = new Date(Date.parse(opts.field.value));
+ }
+ opts.setDefaultDate = true;
+ }
+ }
+
+ var defDate = opts.defaultDate;
+
+ if (isDate(defDate)) {
+ if (opts.setDefaultDate) {
+ self.setDate(defDate, true);
+ } else {
+ self.gotoDate(defDate);
+ }
+ } else {
+ self.gotoDate(new Date());
+ }
+
+ if (opts.bound) {
+ this.hide();
+ self.el.className += ' is-bound';
+ addEvent(opts.trigger, 'click', self._onInputClick);
+ addEvent(opts.trigger, 'focus', self._onInputFocus);
+ addEvent(opts.trigger, 'blur', self._onInputBlur);
+ } else {
+ this.show();
+ }
+ };
+
+
+ /**
+ * public Pikaday API
+ */
+ Pikaday.prototype = {
+
+
+ /**
+ * configure functionality
+ */
+ config: function(options)
+ {
+ if (!this._o) {
+ this._o = extend({}, defaults, true);
+ }
+
+ var opts = extend(this._o, options, true);
+
+ opts.isRTL = !!opts.isRTL;
+
+ opts.field = (opts.field && opts.field.nodeName) ? opts.field : null;
+
+ opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field);
+
+ opts.trigger = (opts.trigger && opts.trigger.nodeName) ? opts.trigger : opts.field;
+
+ opts.disableWeekends = !!opts.disableWeekends;
+
+ opts.disableDayFn = (typeof opts.disableDayFn) == "function" ? opts.disableDayFn : null;
+
+ var nom = parseInt(opts.numberOfMonths, 10) || 1;
+ opts.numberOfMonths = nom > 4 ? 4 : nom;
+
+ if (!isDate(opts.minDate)) {
+ opts.minDate = false;
+ }
+ if (!isDate(opts.maxDate)) {
+ opts.maxDate = false;
+ }
+ if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) {
+ opts.maxDate = opts.minDate = false;
+ }
+ if (opts.minDate) {
+ setToStartOfDay(opts.minDate);
+ opts.minYear = opts.minDate.getFullYear();
+ opts.minMonth = opts.minDate.getMonth();
+ }
+ if (opts.maxDate) {
+ setToStartOfDay(opts.maxDate);
+ opts.maxYear = opts.maxDate.getFullYear();
+ opts.maxMonth = opts.maxDate.getMonth();
+ }
+
+ if (isArray(opts.yearRange)) {
+ var fallback = new Date().getFullYear() - 10;
+ opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback;
+ opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback;
+ } else {
+ opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange;
+ if (opts.yearRange > 100) {
+ opts.yearRange = 100;
+ }
+ }
+
+ return opts;
+ },
+
+ /**
+ * return a formatted string of the current selection (using Moment.js if available)
+ */
+ toString: function(format)
+ {
+ return !isDate(this._d) ? '' : hasMoment ? moment(this._d).format(format || this._o.format) : this._d.toDateString();
+ },
+
+ /**
+ * return a Moment.js object of the current selection (if available)
+ */
+ getMoment: function()
+ {
+ return hasMoment ? moment(this._d) : null;
+ },
+
+ /**
+ * set the current selection from a Moment.js object (if available)
+ */
+ setMoment: function(date, preventOnSelect)
+ {
+ if (hasMoment && moment.isMoment(date)) {
+ this.setDate(date.toDate(), preventOnSelect);
+ }
+ },
+
+ /**
+ * return a Date object of the current selection
+ */
+ getDate: function()
+ {
+ return isDate(this._d) ? new Date(this._d.getTime()) : null;
+ },
+
+ /**
+ * set the current selection
+ */
+ setDate: function(date, preventOnSelect)
+ {
+ if (!date) {
+ this._d = null;
+
+ if (this._o.field) {
+ this._o.field.value = '';
+ fireEvent(this._o.field, 'change', { firedBy: this });
+ }
+
+ return this.draw();
+ }
+ if (typeof date === 'string') {
+ date = new Date(Date.parse(date));
+ }
+ if (!isDate(date)) {
+ return;
+ }
+
+ var min = this._o.minDate,
+ max = this._o.maxDate;
+
+ if (isDate(min) && date < min) {
+ date = min;
+ } else if (isDate(max) && date > max) {
+ date = max;
+ }
+
+ this._d = new Date(date.getTime());
+ setToStartOfDay(this._d);
+ this.gotoDate(this._d);
+
+ if (this._o.field) {
+ this._o.field.value = this.toString();
+ fireEvent(this._o.field, 'change', { firedBy: this });
+ }
+ if (!preventOnSelect && typeof this._o.onSelect === 'function') {
+ this._o.onSelect.call(this, this.getDate());
+ }
+ },
+
+ /**
+ * change view to a specific date
+ */
+ gotoDate: function(date)
+ {
+ var newCalendar = true;
+
+ if (!isDate(date)) {
+ return;
+ }
+
+ if (this.calendars) {
+ var firstVisibleDate = new Date(this.calendars[0].year, this.calendars[0].month, 1),
+ lastVisibleDate = new Date(this.calendars[this.calendars.length-1].year, this.calendars[this.calendars.length-1].month, 1),
+ visibleDate = date.getTime();
+ // get the end of the month
+ lastVisibleDate.setMonth(lastVisibleDate.getMonth()+1);
+ lastVisibleDate.setDate(lastVisibleDate.getDate()-1);
+ newCalendar = (visibleDate < firstVisibleDate.getTime() || lastVisibleDate.getTime() < visibleDate);
+ }
+
+ if (newCalendar) {
+ this.calendars = [{
+ month: date.getMonth(),
+ year: date.getFullYear()
+ }];
+ if (this._o.mainCalendar === 'right') {
+ this.calendars[0].month += 1 - this._o.numberOfMonths;
+ }
+ }
+
+ this.adjustCalendars();
+ },
+
+ adjustCalendars: function() {
+ this.calendars[0] = adjustCalendar(this.calendars[0]);
+ for (var c = 1; c < this._o.numberOfMonths; c++) {
+ this.calendars[c] = adjustCalendar({
+ month: this.calendars[0].month + c,
+ year: this.calendars[0].year
+ });
+ }
+ this.draw();
+ },
+
+ gotoToday: function()
+ {
+ this.gotoDate(new Date());
+ },
+
+ /**
+ * change view to a specific month (zero-index, e.g. 0: January)
+ */
+ gotoMonth: function(month)
+ {
+ if (!isNaN(month)) {
+ this.calendars[0].month = parseInt(month, 10);
+ this.adjustCalendars();
+ }
+ },
+
+ nextMonth: function()
+ {
+ this.calendars[0].month++;
+ this.adjustCalendars();
+ },
+
+ prevMonth: function()
+ {
+ this.calendars[0].month--;
+ this.adjustCalendars();
+ },
+
+ /**
+ * change view to a specific full year (e.g. "2012")
+ */
+ gotoYear: function(year)
+ {
+ if (!isNaN(year)) {
+ this.calendars[0].year = parseInt(year, 10);
+ this.adjustCalendars();
+ }
+ },
+
+ /**
+ * change the minDate
+ */
+ setMinDate: function(value)
+ {
+ this._o.minDate = value;
+ },
+
+ /**
+ * change the maxDate
+ */
+ setMaxDate: function(value)
+ {
+ this._o.maxDate = value;
+ },
+
+ /**
+ * refresh the HTML
+ */
+ draw: function(force)
+ {
+ if (!this._v && !force) {
+ return;
+ }
+ var opts = this._o,
+ minYear = opts.minYear,
+ maxYear = opts.maxYear,
+ minMonth = opts.minMonth,
+ maxMonth = opts.maxMonth,
+ html = '';
+
+ if (this._y <= minYear) {
+ this._y = minYear;
+ if (!isNaN(minMonth) && this._m < minMonth) {
+ this._m = minMonth;
+ }
+ }
+ if (this._y >= maxYear) {
+ this._y = maxYear;
+ if (!isNaN(maxMonth) && this._m > maxMonth) {
+ this._m = maxMonth;
+ }
+ }
+
+ for (var c = 0; c < opts.numberOfMonths; c++) {
+ html += '' + renderTitle(this, c, this.calendars[c].year, this.calendars[c].month, this.calendars[0].year) + this.render(this.calendars[c].year, this.calendars[c].month) + '
';
+ }
+
+ this.el.innerHTML = html;
+
+ if (opts.bound) {
+ if(opts.field.type !== 'hidden') {
+ sto(function() {
+ opts.trigger.focus();
+ }, 1);
+ }
+ }
+
+ if (typeof this._o.onDraw === 'function') {
+ var self = this;
+ sto(function() {
+ self._o.onDraw.call(self);
+ }, 0);
+ }
+ },
+
+ adjustPosition: function()
+ {
+ if (this._o.container) return;
+ var field = this._o.trigger, pEl = field,
+ width = this.el.offsetWidth, height = this.el.offsetHeight,
+ viewportWidth = window.innerWidth || document.documentElement.clientWidth,
+ viewportHeight = window.innerHeight || document.documentElement.clientHeight,
+ scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop,
+ left, top, clientRect;
+
+ if (typeof field.getBoundingClientRect === 'function') {
+ clientRect = field.getBoundingClientRect();
+ left = clientRect.left + window.pageXOffset;
+ top = clientRect.bottom + window.pageYOffset;
+ } else {
+ left = pEl.offsetLeft;
+ top = pEl.offsetTop + pEl.offsetHeight;
+ while((pEl = pEl.offsetParent)) {
+ left += pEl.offsetLeft;
+ top += pEl.offsetTop;
+ }
+ }
+
+ // default position is bottom & left
+ if ((this._o.reposition && left + width > viewportWidth) ||
+ (
+ this._o.position.indexOf('right') > -1 &&
+ left - width + field.offsetWidth > 0
+ )
+ ) {
+ left = left - width + field.offsetWidth;
+ }
+ if ((this._o.reposition && top + height > viewportHeight + scrollTop) ||
+ (
+ this._o.position.indexOf('top') > -1 &&
+ top - height - field.offsetHeight > 0
+ )
+ ) {
+ top = top - height - field.offsetHeight;
+ }
+
+ this.el.style.cssText = [
+ 'position: absolute',
+ 'left: ' + left + 'px',
+ 'top: ' + top + 'px'
+ ].join(';');
+ },
+
+ /**
+ * render HTML for a particular month
+ */
+ render: function(year, month)
+ {
+ var opts = this._o,
+ now = new Date(),
+ days = getDaysInMonth(year, month),
+ before = new Date(year, month, 1).getDay(),
+ data = [],
+ row = [];
+ setToStartOfDay(now);
+ if (opts.firstDay > 0) {
+ before -= opts.firstDay;
+ if (before < 0) {
+ before += 7;
+ }
+ }
+ var cells = days + before,
+ after = cells;
+ while(after > 7) {
+ after -= 7;
+ }
+ cells += 7 - after;
+ for (var i = 0, r = 0; i < cells; i++)
+ {
+ var day = new Date(year, month, 1 + (i - before)),
+ isSelected = isDate(this._d) ? compareDates(day, this._d) : false,
+ isToday = compareDates(day, now),
+ isEmpty = i < before || i >= (days + before),
+ isDisabled = (opts.minDate && day < opts.minDate) ||
+ (opts.maxDate && day > opts.maxDate) ||
+ (opts.disableWeekends && isWeekend(day)) ||
+ (opts.disableDayFn && opts.disableDayFn(day));
+
+ row.push(renderDay(1 + (i - before), month, year, isSelected, isToday, isDisabled, isEmpty));
+
+ if (++r === 7) {
+ if (opts.showWeekNumber) {
+ row.unshift(renderWeek(i - before, month, year));
+ }
+ data.push(renderRow(row, opts.isRTL));
+ row = [];
+ r = 0;
+ }
+ }
+ return renderTable(opts, data);
+ },
+
+ isVisible: function()
+ {
+ return this._v;
+ },
+
+ show: function()
+ {
+ if (!this._v) {
+ removeClass(this.el, 'is-hidden');
+ this._v = true;
+ this.draw();
+ if (this._o.bound) {
+ addEvent(document, 'click', this._onClick);
+ this.adjustPosition();
+ }
+ if (typeof this._o.onOpen === 'function') {
+ this._o.onOpen.call(this);
+ }
+ }
+ },
+
+ hide: function()
+ {
+ var v = this._v;
+ if (v !== false) {
+ if (this._o.bound) {
+ removeEvent(document, 'click', this._onClick);
+ }
+ this.el.style.cssText = '';
+ addClass(this.el, 'is-hidden');
+ this._v = false;
+ if (v !== undefined && typeof this._o.onClose === 'function') {
+ this._o.onClose.call(this);
+ }
+ }
+ },
+
+ /**
+ * GAME OVER
+ */
+ destroy: function()
+ {
+ this.hide();
+ removeEvent(this.el, 'mousedown', this._onMouseDown, true);
+ removeEvent(this.el, 'change', this._onChange);
+ if (this._o.field) {
+ removeEvent(this._o.field, 'change', this._onInputChange);
+ if (this._o.bound) {
+ removeEvent(this._o.trigger, 'click', this._onInputClick);
+ removeEvent(this._o.trigger, 'focus', this._onInputFocus);
+ removeEvent(this._o.trigger, 'blur', this._onInputBlur);
+ }
+ }
+ if (this.el.parentNode) {
+ this.el.parentNode.removeChild(this.el);
+ }
+ }
+
+ };
+
+ return Pikaday;
+
+}));
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Home Assistant
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [[relativeTime]]
+
+
+
+
+
+
+
+
+
+
+
+
+
[[stateObj.entityDisplay]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[[stateObj.stateDisplay]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[[stateObj.stateDisplay]]
+
+
+ Currently:
+ [[stateObj.attributes.current_temperature]]
+
+ [[stateObj.attributes.unit_of_measurement]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[[computePrimaryText(stateObj, isPlaying)]]
+
[[computeSecondaryText(stateObj, isPlaying)]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Hi there!
+
+ It looks like we have nothing to show you right now. It could be that we have not yet discovered all your devices but it is more likely that you have not configured Home Assistant yet.
+
+
+ Please see the Getting Started section on how to setup your devices.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [[computeHeaderTitle(filter)]]
+
+
+
+
+
+
+
+
+
{{finalTranscript}}
+
[[interimTranscript]]
+
+
+
+
+ Hi there!
+
+ It looks like we have nothing to show you right now. It could be that we have not yet discovered all your devices but it is more likely that you have not configured Home Assistant yet.
+
+
+ Please see the Getting Started section on how to setup your devices.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [[_charCounterStr]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [[label]]
+
+
+
+
+ [[errorMessage]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [[computeTime(dateObj)]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ No logbook entries found.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Logbook
+
+
+
+
+
+
+
+
Loading logbook entries
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Updating history data
+
+
+
+
+ No state history found.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ History
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ [[label]]
+
+
+
+
+ [[errorMessage]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Call Service
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Fire Event
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Set State
+
+
+
+
+
+
+
+
+
+
+
+ [[_text]]
+
+
+
+
+
+
+
+ {{text}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
[[attribute]]
+
[[getAttributeValue(stateObj, attribute)]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Rising
+
+
[[risingTime]]
+
+
+
+
+ Setting
+
+
[[settingTime]]
+
+
+
+
+
+
+
+
+
+
+
+ [[stateObj.attributes.description]]
+
+ [[stateObj.attributes.errors]]
+
+
+
+
+
+
+ [[submitCaption]]
+
+ Configuring
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Target Temperature
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Last Action
+
[[stateObj.attributes.last_action]]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+