diff --git a/api/thermostat_group.php b/api/thermostat_group.php index 97b7201..865423c 100644 --- a/api/thermostat_group.php +++ b/api/thermostat_group.php @@ -29,6 +29,9 @@ class thermostat_group extends cora\crud { public static $converged = [ 'temperature_profile' => [ 'type' => 'json' + ], + 'weather' => [ + 'type' => 'json' ] ]; @@ -314,7 +317,8 @@ class thermostat_group extends cora\crud { 'property_age', 'property_square_feet', 'property_stories', - 'property_structure_type' + 'property_structure_type', + 'weather' ]; $thermostats = $this->api( @@ -377,6 +381,11 @@ class thermostat_group extends cora\crud { $final_attributes[$attribute] = $system_type; } break; + default: + // Stuff that doesn't really matter (weather); just pick the last + // one. + $final_attributes[$attribute] = $thermostat[$attribute]; + break; } } } diff --git a/js/beestat/setting.js b/js/beestat/setting.js index e767a39..0a7de74 100644 --- a/js/beestat/setting.js +++ b/js/beestat/setting.js @@ -21,7 +21,9 @@ beestat.setting = function(key, opt_value, opt_callback) { 'runtime_thermostat_summary_gap_fill': true, 'comparison_region': 'global', - 'comparison_property_type': 'similar' + 'comparison_property_type': 'similar', + + 'temperature_unit': '°F' }; if (user.json_settings === null) { diff --git a/js/beestat/style.js b/js/beestat/style.js index 740f7ff..c88c69a 100644 --- a/js/beestat/style.js +++ b/js/beestat/style.js @@ -279,3 +279,22 @@ beestat.series.calendar_event_other = { 'name': 'Other', 'color': beestat.style.color.gray.base }; + +// Temperature Profiles +beestat.series.indoor_heat_delta = { + 'name': 'Indoor Heat Δ', + 'color': beestat.series.compressor_heat_1.color +}; +beestat.series.indoor_heat_delta_raw = beestat.series.indoor_heat_delta; + +beestat.series.indoor_cool_delta = { + 'name': 'Indoor Cool Δ', + 'color': beestat.series.compressor_cool_1.color +}; +beestat.series.indoor_cool_delta_raw = beestat.series.indoor_cool_delta; + +beestat.series.indoor_resist_delta = { + 'name': 'Indoor Δ', + 'color': beestat.style.color.gray.dark +}; +beestat.series.indoor_resist_delta_raw = beestat.series.indoor_resist_delta; diff --git a/js/component/card/runtime_thermostat_summary.js b/js/component/card/runtime_thermostat_summary.js index 35f056a..1a26f90 100755 --- a/js/component/card/runtime_thermostat_summary.js +++ b/js/component/card/runtime_thermostat_summary.js @@ -50,10 +50,7 @@ beestat.extend(beestat.component.card.runtime_thermostat_summary, beestat.compon */ beestat.component.card.runtime_thermostat_summary.prototype.decorate_contents_ = function(parent) { var data = this.get_data_(); - this.chart_ = new beestat.component.chart2.runtime_thermostat_summary( - this.thermostat_id_, - data - ); + this.chart_ = new beestat.component.chart2.runtime_thermostat_summary(data); this.chart_.render(parent); var sync_progress = beestat.get_sync_progress(this.thermostat_id_); @@ -117,7 +114,11 @@ beestat.component.card.runtime_thermostat_summary.prototype.get_data_ = function 'x': [], 'series': {}, 'metadata': { - 'series': {} + 'series': {}, + 'chart': { + 'title': this.get_title_(), + 'subtitle': this.get_subtitle_() + } } }; diff --git a/js/component/card/temperature_profiles.js b/js/component/card/temperature_profiles.js index 5a9ddfb..3b5fe4c 100644 --- a/js/component/card/temperature_profiles.js +++ b/js/component/card/temperature_profiles.js @@ -1,7 +1,12 @@ /** * Temperature profiles. + * + * @param {number} thermostat_group_id The thermostat_group_id this card is + * displaying data for. */ -beestat.component.card.temperature_profiles = function() { +beestat.component.card.temperature_profiles = function(thermostat_group_id) { + this.thermostat_group_id_ = thermostat_group_id; + beestat.component.card.apply(this, arguments); }; beestat.extend(beestat.component.card.temperature_profiles, beestat.component.card); @@ -12,15 +17,36 @@ beestat.extend(beestat.component.card.temperature_profiles, beestat.component.ca * @param {rocket.Elements} parent */ beestat.component.card.temperature_profiles.prototype.decorate_contents_ = function(parent) { - var self = this; + var data = this.get_data_(); + this.chart_ = new beestat.component.chart2.temperature_profiles(data); + this.chart_.render(parent); +}; - var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')]; +/** + * Get all of the series data. + * + * @return {object} The series data. + */ +beestat.component.card.temperature_profiles.prototype.get_data_ = function() { var thermostat_group = beestat.cache.thermostat_group[ - thermostat.thermostat_group_id + this.thermostat_group_id_ ]; - this.chart_ = new beestat.component.chart(); - this.chart_.options.chart.height = 300; + var data = { + 'x': [], + 'series': {}, + 'metadata': { + 'series': {}, + 'chart': { + 'title': this.get_title_(), + 'subtitle': this.get_subtitle_(), + 'outdoor_temperature': beestat.temperature({ + 'temperature': (thermostat_group.weather.temperature / 10), + 'round': 0 + }) + } + } + }; if ( thermostat_group.temperature_profile === null @@ -28,10 +54,6 @@ beestat.component.card.temperature_profiles.prototype.decorate_contents_ = funct this.chart_.render(parent); this.show_loading_('Calculating'); } else { - // var x_categories = []; - var trendlines = {}; - var raw = {}; - // Global x range. var x_min = Infinity; var x_max = -Infinity; @@ -69,8 +91,8 @@ beestat.component.card.temperature_profiles.prototype.decorate_contents_ = funct x_min = Math.min(x_min, this_x_min); x_max = Math.max(x_max, this_x_max); - trendlines[type] = []; - raw[type] = []; + data.series['trendline_' + type] = []; + data.series['raw_' + type] = []; /** * Data is stored internally as °F with 1 value per degree. That data @@ -87,7 +109,7 @@ beestat.component.card.temperature_profiles.prototype.decorate_contents_ = funct */ var increment; var fixed; - if (thermostat.temperature_unit === '°F') { + if (beestat.setting('temperature_unit') === '°F') { increment = 1; fixed = 0; } else { @@ -99,240 +121,27 @@ beestat.component.card.temperature_profiles.prototype.decorate_contents_ = funct var y = (linear_trendline.slope * x_fixed) + linear_trendline.intercept; - trendlines[type].push([ + data.series['trendline_' + type].push([ parseFloat(x_fixed), y ]); if (profile.deltas[x_fixed] !== undefined) { - raw[type].push([ + data.series['raw_' + type].push([ parseFloat(x_fixed), profile.deltas[x_fixed] ]); y_min = Math.min(y_min, profile.deltas[x_fixed]); y_max = Math.max(y_max, profile.deltas[x_fixed]); } + + data.metadata.chart.y_min = y_min; + data.metadata.chart.y_max = y_max; } } } - - /* - * Set y_min and y_max to be equal but opposite so the graph is always - * centered. - */ - var absolute_y_max = Math.max(Math.abs(y_min), Math.abs(y_max)); - y_min = absolute_y_max * -1; - y_max = absolute_y_max; - - // Chart - this.chart_.options.exporting.chartOptions.title.text = this.get_title_(); - this.chart_.options.exporting.chartOptions.subtitle.text = this.get_subtitle_(); - - this.chart_.options.chart.backgroundColor = beestat.style.color.bluegray.base; - this.chart_.options.exporting.filename = 'Temperature Profiles'; - this.chart_.options.chart.zoomType = null; - this.chart_.options.plotOptions.series.connectNulls = true; - this.chart_.options.legend = {'enabled': false}; - - this.chart_.options.xAxis = { - 'lineWidth': 0, - 'tickLength': 0, - 'tickInterval': 5, - 'gridLineWidth': 1, - 'gridLineColor': beestat.style.color.bluegray.light, - 'gridLineDashStyle': 'longdash', - 'labels': { - 'style': {'color': beestat.style.color.gray.base}, - 'formatter': function() { - return this.value + thermostat.temperature_unit; - } - }, - 'plotLines': [ - { - 'color': beestat.series.outdoor_temperature.color, - 'dashStyle': 'ShortDash', - 'width': 1, - 'value': beestat.temperature(thermostat.weather.temperature), - 'zIndex': 2 - } - ] - }; - - this.chart_.options.yAxis = [ - { - 'alignTicks': false, - 'gridLineColor': beestat.style.color.bluegray.light, - 'gridLineDashStyle': 'longdash', - 'title': {'text': null}, - 'labels': { - 'style': {'color': beestat.style.color.gray.base}, - 'formatter': function() { - return this.value + thermostat.temperature_unit; - } - }, - 'min': y_min, - 'max': y_max, - 'plotLines': [ - { - 'color': beestat.style.color.bluegray.light, - 'dashStyle': 'solid', - 'width': 3, - 'value': 0, - 'zIndex': 1 - } - ] - } - ]; - - this.chart_.options.tooltip = { - 'shared': true, - 'useHTML': true, - 'borderWidth': 0, - 'shadow': false, - 'backgroundColor': null, - 'followPointer': true, - 'crosshairs': { - 'width': 1, - 'zIndex': 100, - 'color': beestat.style.color.gray.light, - 'dashStyle': 'shortDot', - 'snap': false - }, - 'positioner': function(tooltip_width, tooltip_height, point) { - return beestat.component.chart.tooltip_positioner( - self.chart_.get_chart(), - tooltip_width, - tooltip_height, - point - ); - }, - 'formatter': function() { - var sections = []; - var section = []; - this.points.forEach(function(point) { - var series = point.series; - - var value = beestat.temperature({ - 'temperature': point.y, - 'units': true, - 'convert': false, - 'delta': true, - 'type': 'string' - }) + ' / hour'; - - if (series.name.indexOf('Raw') === -1) { - section.push({ - 'label': series.name, - 'value': value, - 'color': series.color - }); - } - }); - sections.push(section); - - return beestat.component.chart.tooltip_formatter( - 'Outdoor Temp: ' + - beestat.temperature({ - 'temperature': this.x, - 'round': 0, - 'units': true, - 'convert': false - }), - sections - ); - } - }; - - this.chart_.options.series = []; - - // Trendline data - this.chart_.options.series.push({ - 'data': trendlines.heat, - 'name': 'Indoor Heat Δ', - 'color': beestat.series.compressor_heat_1.color, - 'marker': { - 'enabled': false, - 'states': {'hover': {'enabled': false}} - }, - 'type': 'line', - 'lineWidth': 2, - 'states': {'hover': {'lineWidthPlus': 0}} - }); - - // Trendline data - this.chart_.options.series.push({ - 'data': trendlines.cool, - 'name': 'Indoor Cool Δ', - 'color': beestat.series.compressor_cool_1.color, - 'marker': { - 'enabled': false, - 'states': {'hover': {'enabled': false}} - }, - 'type': 'line', - 'lineWidth': 2, - 'states': {'hover': {'lineWidthPlus': 0}} - }); - - // Trendline data - this.chart_.options.series.push({ - 'data': trendlines.resist, - 'name': 'Indoor Δ', - 'color': beestat.style.color.gray.dark, - 'marker': { - 'enabled': false, - 'states': {'hover': {'enabled': false}} - }, - 'type': 'line', - 'lineWidth': 2, - 'states': {'hover': {'lineWidthPlus': 0}} - }); - - // Raw data - this.chart_.options.series.push({ - 'data': raw.heat, - 'name': 'Heat Raw', - 'color': beestat.series.compressor_heat_1.color, - 'dashStyle': 'ShortDot', - 'marker': { - 'enabled': false, - 'states': {'hover': {'enabled': false}} - }, - 'type': 'spline', - 'lineWidth': 1, - 'states': {'hover': {'lineWidthPlus': 0}} - }); - - // Raw data - this.chart_.options.series.push({ - 'data': raw.cool, - 'name': 'Cool Raw', - 'color': beestat.series.compressor_cool_1.color, - 'dashStyle': 'ShortDot', - 'marker': { - 'enabled': false, - 'states': {'hover': {'enabled': false}} - }, - 'type': 'spline', - 'lineWidth': 1, - 'states': {'hover': {'lineWidthPlus': 0}} - }); - - // Raw data - this.chart_.options.series.push({ - 'data': raw.resist, - 'name': 'Resist Raw', - 'color': beestat.style.color.gray.dark, - 'dashStyle': 'ShortDot', - 'marker': { - 'enabled': false, - 'states': {'hover': {'enabled': false}} - }, - 'type': 'spline', - 'lineWidth': 1, - 'states': {'hover': {'lineWidthPlus': 0}} - }); - - this.chart_.render(parent); } + + return data; }; /** diff --git a/js/component/chart/runtime_thermostat_summary.js b/js/component/chart/runtime_thermostat_summary.js index 0cc1b92..567b941 100755 --- a/js/component/chart/runtime_thermostat_summary.js +++ b/js/component/chart/runtime_thermostat_summary.js @@ -1,14 +1,12 @@ /** * Runtime thermostat summary chart. * - * @param {number} thermostat_id The thermostat_id this chart is showing data - * for. * @param {object} data The chart data. */ -beestat.component.chart2.runtime_thermostat_summary = function(thermostat_id, data) { - beestat.component.chart2.apply(this, arguments); - this.thermostat_id_ = thermostat_id; +beestat.component.chart2.runtime_thermostat_summary = function(data) { this.data_ = data; + + beestat.component.chart2.apply(this, arguments); }; beestat.extend(beestat.component.chart2.runtime_thermostat_summary, beestat.component.chart2); @@ -189,7 +187,7 @@ beestat.component.chart2.runtime_thermostat_summary.prototype.get_options_yAxis_ 'color': beestat.style.color.gray.base }, 'formatter': function() { - return this.value + beestat.cache.thermostat[self.thermostat_id_].temperature_unit; + return this.value + beestat.setting('temperature_unit'); } } } diff --git a/js/component/chart/temperature_profiles.js b/js/component/chart/temperature_profiles.js new file mode 100644 index 0000000..b0dd31e --- /dev/null +++ b/js/component/chart/temperature_profiles.js @@ -0,0 +1,287 @@ +/** + * Temperature profiles chart. + * + * @param {object} data The chart data. + */ +beestat.component.chart2.temperature_profiles = function(data) { + this.data_ = data; + + beestat.component.chart2.apply(this, arguments); +}; +beestat.extend(beestat.component.chart2.temperature_profiles, beestat.component.chart2); + +/** + * Override for get_options_xAxis_labels_formatter_. + * + * @return {Function} xAxis labels formatter. + */ +beestat.component.chart2.temperature_profiles.prototype.get_options_xAxis_labels_formatter_ = function() { + return function() { + return this.value + beestat.setting('temperature_unit'); + }; +}; + +/** + * Override for get_options_series_. + * + * @return {Array} All of the series to display on the chart. + */ +beestat.component.chart2.temperature_profiles.prototype.get_options_series_ = function() { + var series = []; + + // Trendline data + series.push({ + 'data': this.data_.series.trendline_heat, + 'name': 'indoor_heat_delta', + 'color': beestat.series.compressor_heat_1.color, + 'marker': { + 'enabled': false, + 'states': {'hover': {'enabled': false}} + }, + 'type': 'line', + 'lineWidth': 2, + 'states': {'hover': {'lineWidthPlus': 0}} + }); + + // Trendline data + series.push({ + 'data': this.data_.series.trendline_cool, + 'name': 'indoor_cool_delta', + 'color': beestat.series.compressor_cool_1.color, + 'marker': { + 'enabled': false, + 'states': {'hover': {'enabled': false}} + }, + 'type': 'line', + 'lineWidth': 2, + 'states': {'hover': {'lineWidthPlus': 0}} + }); + + // Trendline data + series.push({ + 'data': this.data_.series.trendline_resist, + 'name': 'indoor_resist_delta', + 'color': beestat.style.color.gray.dark, + 'marker': { + 'enabled': false, + 'states': {'hover': {'enabled': false}} + }, + 'type': 'line', + 'lineWidth': 2, + 'states': {'hover': {'lineWidthPlus': 0}} + }); + + // Raw data + series.push({ + 'data': this.data_.series.raw_heat, + 'name': 'indoor_heat_delta_raw', + 'color': beestat.series.compressor_heat_1.color, + 'dashStyle': 'ShortDot', + 'marker': { + 'enabled': false, + 'states': {'hover': {'enabled': false}} + }, + 'type': 'spline', + 'lineWidth': 1, + 'states': {'hover': {'lineWidthPlus': 0}} + }); + + // Raw data + series.push({ + 'data': this.data_.series.raw_cool, + 'name': 'indoor_cool_delta_raw', + 'color': beestat.series.compressor_cool_1.color, + 'dashStyle': 'ShortDot', + 'marker': { + 'enabled': false, + 'states': {'hover': {'enabled': false}} + }, + 'type': 'spline', + 'lineWidth': 1, + 'states': {'hover': {'lineWidthPlus': 0}} + }); + + // Raw data + series.push({ + 'data': this.data_.series.raw_resist, + 'name': 'indoor_resist_delta_raw', + 'color': beestat.style.color.gray.dark, + 'dashStyle': 'ShortDot', + 'marker': { + 'enabled': false, + 'states': {'hover': {'enabled': false}} + }, + 'type': 'spline', + 'lineWidth': 1, + 'states': {'hover': {'lineWidthPlus': 0}} + }); + + return series; +}; + +/** + * Override for get_options_yAxis_. + * + * @return {Array} The y-axis options. + */ +beestat.component.chart2.temperature_profiles.prototype.get_options_yAxis_ = function() { + var absolute_y_max = Math.max( + Math.abs(this.data_.metadata.chart.y_min), + Math.abs(this.data_.metadata.chart.y_max) + ); + + var y_min = absolute_y_max * -1; + var y_max = absolute_y_max; + + return [ + { + 'alignTicks': false, + 'gridLineColor': beestat.style.color.bluegray.light, + 'gridLineDashStyle': 'longdash', + 'title': {'text': null}, + 'labels': { + 'style': {'color': beestat.style.color.gray.base}, + 'formatter': function() { + return this.value + beestat.setting('temperature_unit'); + } + }, + 'min': y_min, + 'max': y_max, + 'plotLines': [ + { + 'color': beestat.style.color.bluegray.light, + 'dashStyle': 'solid', + 'width': 3, + 'value': 0, + 'zIndex': 1 + } + ] + } + ]; +}; + +/** + * Override for get_options_tooltip_formatter_. + * + * @return {Function} The tooltip formatter. + */ +beestat.component.chart2.temperature_profiles.prototype.get_options_tooltip_formatter_ = function() { + var self = this; + + return function() { + var sections = []; + var section = []; + this.points.forEach(function(point) { + var series = point.series; + + var value = beestat.temperature({ + 'temperature': point.y, + 'units': true, + 'convert': false, + 'delta': true, + 'type': 'string' + }) + ' / h'; + + if (series.name.indexOf('raw') === -1) { + section.push({ + 'label': beestat.series[series.name].name, + 'value': value, + 'color': series.color + }); + } + }); + sections.push(section); + + return self.tooltip_formatter_helper_( + 'Outdoor Temp: ' + + beestat.temperature({ + 'temperature': this.x, + 'round': 0, + 'units': true, + 'convert': false + }), + sections + ); + }; +}; + +/** + * Override for get_options_chart_zoomType_. + * + * @return {string} The zoom type. + */ +beestat.component.chart2.temperature_profiles.prototype.get_options_chart_zoomType_ = function() { + return null; +}; + +/** + * Override for get_options_legend_. + * + * @return {object} The legend options. + */ +beestat.component.chart2.temperature_profiles.prototype.get_options_legend_ = function() { + return { + 'enabled': false + }; +}; + +/** + * Override for get_options_xAxis_. + * + * @return {object} The xAxis options. + */ +beestat.component.chart2.temperature_profiles.prototype.get_options_xAxis_ = function() { + return { + 'lineWidth': 0, + 'tickLength': 0, + 'tickInterval': 5, + 'gridLineWidth': 1, + 'gridLineColor': beestat.style.color.bluegray.light, + 'gridLineDashStyle': 'longdash', + 'labels': { + 'style': { + 'color': beestat.style.color.gray.base + }, + 'formatter': this.get_options_xAxis_labels_formatter_() + }, + 'plotLines': [ + { + 'color': beestat.series.outdoor_temperature.color, + 'dashStyle': 'ShortDash', + 'width': 1, + 'label': { + 'style': { + 'color': beestat.series.outdoor_temperature.color + }, + 'useHTML': true, + 'text': 'Now: ' + beestat.temperature({ + 'temperature': this.data_.metadata.chart.outdoor_temperature, + 'convert': false, + 'units': true, + 'round': 0 + }) + }, + 'value': this.data_.metadata.chart.outdoor_temperature, + 'zIndex': 2 + } + ] + }; +}; + +/** + * Override for get_options_chart_height_. + * + * @return {number} The height of the chart. + */ +beestat.component.chart2.temperature_profiles.prototype.get_options_chart_height_ = function() { + return 300; +}; + +/** + * Override for get_options_plotOptions_series_connectNulls_. + * + * @return {boolean} Whether or not to connect nulls. + */ +beestat.component.chart2.temperature_profiles.prototype.get_options_plotOptions_series_connectNulls_ = function() { + return true; +}; diff --git a/js/component/chart2.js b/js/component/chart2.js index da7f5ca..d29358b 100755 --- a/js/component/chart2.js +++ b/js/component/chart2.js @@ -105,7 +105,8 @@ beestat.component.chart2.prototype.get_options_plotOptions_ = function() { 'inactive': { 'opacity': 1 } - } + }, + 'connectNulls': this.get_options_plotOptions_series_connectNulls_() }, 'column': { 'pointPadding': 0, @@ -118,6 +119,15 @@ beestat.component.chart2.prototype.get_options_plotOptions_ = function() { }; }; +/** + * Get whether or not to connect nulls. + * + * @return {boolean} Whether or not to connect nulls. + */ +beestat.component.chart2.prototype.get_options_plotOptions_series_connectNulls_ = function() { + return false; +}; + /** * Get the title options. * @@ -156,7 +166,7 @@ beestat.component.chart2.prototype.get_options_chart_ = function() { 0, 0 ], - 'zoomType': 'x', + 'zoomType': this.get_options_chart_zoomType_(), 'panning': true, 'panKey': 'ctrl', 'backgroundColor': beestat.style.color.bluegray.base, @@ -164,10 +174,29 @@ beestat.component.chart2.prototype.get_options_chart_ = function() { 'theme': { 'display': 'none' } - } + }, + 'height': this.get_options_chart_height_() }; }; +/** + * Get the height of the chart. + * + * @return {number} The height of the chart. + */ +beestat.component.chart2.prototype.get_options_chart_height_ = function() { + return null; +}; + +/** + * Get the zoomType option. Return null for no zoom. + * + * @return {string} The zoom type. + */ +beestat.component.chart2.prototype.get_options_chart_zoomType_ = function() { + return 'x'; +}; + /** * Get the export options. * @@ -178,14 +207,14 @@ beestat.component.chart2.prototype.get_options_exporting_ = function() { 'enabled': false, 'sourceWidth': 980, 'scale': 1, - 'filename': 'beestat', + 'filename': this.get_options_exporting_filename_(), 'chartOptions': { 'credits': { 'text': 'beestat.io' }, 'title': { 'align': 'left', - 'text': null, + 'text': this.get_options_exporting_chartOptions_title_text_(), 'margin': beestat.style.size.gutter, 'style': { 'color': '#fff', @@ -195,7 +224,7 @@ beestat.component.chart2.prototype.get_options_exporting_ = function() { }, 'subtitle': { 'align': 'left', - 'text': null, + 'text': this.get_options_exporting_chartOptions_subtitle_text_(), 'style': { 'color': '#fff', 'font-weight': beestat.style.font_weight.light, @@ -217,6 +246,50 @@ beestat.component.chart2.prototype.get_options_exporting_ = function() { }; }; +/** + * Get the exported chart title. + * + * @return {string} The exported chart title. + */ +beestat.component.chart2.prototype.get_options_exporting_chartOptions_title_text_ = function() { + return this.data_.metadata.chart.title; +}; + +/** + * Get the exported chart subtitle. + * + * @return {string} The exported chart subtitle. + */ +beestat.component.chart2.prototype.get_options_exporting_chartOptions_subtitle_text_ = function() { + return this.data_.metadata.chart.subtitle; +}; + +/** + * Get the exported chart filename. + * + * @return {string} The exported chart filename. + */ +beestat.component.chart2.prototype.get_options_exporting_filename_ = function() { + var title = this.get_options_exporting_chartOptions_title_text_(); + var subtitle = this.get_options_exporting_chartOptions_subtitle_text_(); + + var filename = []; + if (title !== null) { + filename.push(title); + } + + if (subtitle !== null) { + filename.push('-'); + filename.push(subtitle); + } + + if (filename.length === 0) { + filename.push('beestat'); + } + + return filename.join(' '); +}; + /** * Get the credits options. * diff --git a/js/js.php b/js/js.php index 23a771a..939b260 100755 --- a/js/js.php +++ b/js/js.php @@ -61,6 +61,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; + echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; echo '' . PHP_EOL; diff --git a/js/layer/home_comparisons.js b/js/layer/home_comparisons.js index 5dbf621..d2a6846 100644 --- a/js/layer/home_comparisons.js +++ b/js/layer/home_comparisons.js @@ -82,7 +82,7 @@ beestat.layer.home_comparisons.prototype.decorate_ = function(parent) { cards.push([ { - 'card': new beestat.component.card.temperature_profiles(), + 'card': new beestat.component.card.temperature_profiles(thermostat_group.thermostat_group_id), 'size': 12 } ]); diff --git a/js/layer/load.js b/js/layer/load.js index ebafc0d..ec5b8b4 100644 --- a/js/layer/load.js +++ b/js/layer/load.js @@ -175,6 +175,9 @@ beestat.layer.load.prototype.decorate_ = function(parent) { thermostat.ecobee_thermostat_id ]; + // Set the active temperature unit. + beestat.setting('temperature_unit', thermostat.temperature_unit); + // Rename series if only one stage is available. if (ecobee_thermostat.json_settings.coolStages === 1) { beestat.series.sum_compressor_cool_1.name = 'Cool';