mirror of
https://github.com/beestat/app.git
synced 2025-05-24 02:14:03 -04:00
Completed #141 - Display current outdoor weather
Current weather is now displayed on the System card and available in detail in a modal.
This commit is contained in:
parent
81928fbf0c
commit
260d29e3f6
@ -211,6 +211,7 @@ class ecobee_thermostat extends cora\crud {
|
||||
$attributes['property'] = $this->get_property($thermostat, $ecobee_thermostat);
|
||||
$attributes['filters'] = $this->get_filters($thermostat, $ecobee_thermostat);
|
||||
$attributes['json_alerts'] = $this->get_alerts($thermostat, $ecobee_thermostat);
|
||||
$attributes['weather'] = $this->get_weather($thermostat, $ecobee_thermostat);
|
||||
|
||||
$detected_system_type = $this->get_detected_system_type($thermostat, $ecobee_thermostat);
|
||||
if($thermostat['system_type'] === null) {
|
||||
@ -719,4 +720,145 @@ class ecobee_thermostat extends cora\crud {
|
||||
return $detected_system_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current weather status.
|
||||
*
|
||||
* @param array $thermostat
|
||||
* @param array $ecobee_thermostat
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_weather($thermostat, $ecobee_thermostat) {
|
||||
$weather = [
|
||||
'station' => null,
|
||||
'dew_point' => null,
|
||||
'barometric_pressure' => null,
|
||||
'humidity_relative' => null,
|
||||
'temperature_high' => null,
|
||||
'temperature_low' => null,
|
||||
'temperature' => null,
|
||||
'wind_bearing' => null,
|
||||
'wind_speed' => null,
|
||||
'condition' => null
|
||||
];
|
||||
|
||||
if(isset($ecobee_thermostat['json_weather']['weatherStation']) === true) {
|
||||
$weather['station'] = $ecobee_thermostat['json_weather']['weatherStation'];
|
||||
}
|
||||
|
||||
if(
|
||||
isset($ecobee_thermostat['json_weather']['forecasts']) === true &&
|
||||
isset($ecobee_thermostat['json_weather']['forecasts'][0]) === true
|
||||
) {
|
||||
$ecobee_weather = $ecobee_thermostat['json_weather']['forecasts'][0];
|
||||
|
||||
if(isset($ecobee_weather['dewpoint']) === true) {
|
||||
$weather['dew_point'] = ($ecobee_weather['dewpoint'] / 10);
|
||||
}
|
||||
|
||||
// Returned in MB (divide by 33.864 to get inHg)
|
||||
if(isset($ecobee_weather['pressure']) === true) {
|
||||
$weather['barometric_pressure'] = $ecobee_weather['pressure'];
|
||||
}
|
||||
|
||||
if(isset($ecobee_weather['relativeHumidity']) === true) {
|
||||
$weather['humidity_relative'] = $ecobee_weather['relativeHumidity'];
|
||||
}
|
||||
|
||||
if(isset($ecobee_weather['tempHigh']) === true) {
|
||||
$weather['temperature_high'] = ($ecobee_weather['tempHigh'] / 10);
|
||||
}
|
||||
|
||||
if(isset($ecobee_weather['tempLow']) === true) {
|
||||
$weather['temperature_low'] = ($ecobee_weather['tempLow'] / 10);
|
||||
}
|
||||
|
||||
if(isset($ecobee_weather['temperature']) === true) {
|
||||
$weather['temperature'] = ($ecobee_weather['temperature'] / 10);
|
||||
}
|
||||
|
||||
if(isset($ecobee_weather['windBearing']) === true) {
|
||||
$weather['wind_bearing'] = $ecobee_weather['windBearing'];
|
||||
}
|
||||
|
||||
// mph
|
||||
if(isset($ecobee_weather['windSpeed']) === true) {
|
||||
$weather['wind_speed'] = $ecobee_weather['windSpeed'];
|
||||
}
|
||||
|
||||
if(isset($ecobee_weather['weatherSymbol']) === true) {
|
||||
switch($ecobee_weather['weatherSymbol']) {
|
||||
case 0:
|
||||
$weather['condition'] = 'sunny';
|
||||
break;
|
||||
case 1:
|
||||
$weather['condition'] = 'few_clouds';
|
||||
break;
|
||||
case 2:
|
||||
$weather['condition'] = 'partly_cloudy';
|
||||
break;
|
||||
case 3:
|
||||
$weather['condition'] = 'mostly_cloudy';
|
||||
break;
|
||||
case 4:
|
||||
$weather['condition'] = 'overcast';
|
||||
break;
|
||||
case 5:
|
||||
$weather['condition'] = 'drizzle';
|
||||
break;
|
||||
case 6:
|
||||
$weather['condition'] = 'rain';
|
||||
break;
|
||||
case 7:
|
||||
$weather['condition'] = 'freezing_rain';
|
||||
break;
|
||||
case 8:
|
||||
$weather['condition'] = 'showers';
|
||||
break;
|
||||
case 9:
|
||||
$weather['condition'] = 'hail';
|
||||
break;
|
||||
case 10:
|
||||
$weather['condition'] = 'snow';
|
||||
break;
|
||||
case 11:
|
||||
$weather['condition'] = 'flurries';
|
||||
break;
|
||||
case 12:
|
||||
$weather['condition'] = 'freezing_snow';
|
||||
break;
|
||||
case 13:
|
||||
$weather['condition'] = 'blizzard';
|
||||
break;
|
||||
case 14:
|
||||
$weather['condition'] = 'pellets';
|
||||
break;
|
||||
case 15:
|
||||
$weather['condition'] = 'thunderstorm';
|
||||
break;
|
||||
case 16:
|
||||
$weather['condition'] = 'windy';
|
||||
break;
|
||||
case 17:
|
||||
$weather['condition'] = 'tornado';
|
||||
break;
|
||||
case 18:
|
||||
$weather['condition'] = 'fog';
|
||||
break;
|
||||
case 19:
|
||||
$weather['condition'] = 'haze';
|
||||
break;
|
||||
case 20:
|
||||
$weather['condition'] = 'smoke';
|
||||
break;
|
||||
case 21:
|
||||
$weather['condition'] = 'dust';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $weather;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -33,6 +33,9 @@ class thermostat extends cora\crud {
|
||||
],
|
||||
'system_type' => [
|
||||
'type' => 'json'
|
||||
],
|
||||
'weather' => [
|
||||
'type' => 'json'
|
||||
]
|
||||
];
|
||||
|
||||
|
@ -380,6 +380,19 @@ a.inverted:active {
|
||||
.icon.zigbee:before { content: "\FD1D"; }
|
||||
.icon.basket_fill:before { content: "\F077"; }
|
||||
.icon.basket_unfill:before { content: "\F078"; }
|
||||
.icon.weather_sunny:before { content: "\F599"; }
|
||||
.icon.weather_partly_cloudy:before { content: "\F595"; }
|
||||
.icon.weather_cloudy:before { content: "\F590"; }
|
||||
.icon.weather_pouring:before { content: "\F596"; }
|
||||
.icon.weather_hail:before { content: "\F592"; }
|
||||
.icon.weather_snowy:before { content: "\F598"; }
|
||||
.icon.weather_snowy_heavy:before { content: "\FF53"; }
|
||||
.icon.weather_lightning_rainy:before { content: "\F67D"; }
|
||||
.icon.weather_windy:before { content: "\F59D"; }
|
||||
.icon.weather_fog:before { content: "\F591"; }
|
||||
.icon.weather_hazy:before { content: "\FF4D"; }
|
||||
.icon.weather_tornado:before { content: "\FF55"; }
|
||||
.icon.cloud_question:before { content: "\FA38"; }
|
||||
|
||||
.icon.f16:before { font-size: 16px; }
|
||||
.icon.f24:before { font-size: 24px; }
|
||||
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 3.8 MiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -15,6 +15,7 @@ beestat.extend(beestat.component.card.system, beestat.component.card);
|
||||
|
||||
beestat.component.card.system.prototype.decorate_contents_ = function(parent) {
|
||||
this.decorate_circle_(parent);
|
||||
this.decorate_weather_(parent);
|
||||
this.decorate_equipment_(parent);
|
||||
this.decorate_climate_(parent);
|
||||
};
|
||||
@ -78,6 +79,72 @@ beestat.component.card.system.prototype.decorate_circle_ = function(parent) {
|
||||
);
|
||||
};
|
||||
|
||||
beestat.component.card.system.prototype.decorate_weather_ = function(parent) {
|
||||
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
|
||||
|
||||
var temperature = beestat.temperature(thermostat.weather.temperature);
|
||||
var temperature_whole = Math.floor(temperature);
|
||||
|
||||
var circle = $.createElement('div')
|
||||
.style({
|
||||
'padding': (beestat.style.size.gutter / 2),
|
||||
'border-radius': '50%',
|
||||
'background': beestat.style.color.bluegray.light,
|
||||
'height': '66px',
|
||||
'width': '66px',
|
||||
'text-align': 'center',
|
||||
'text-shadow': '1px 1px 1px rgba(0, 0, 0, 0.2)',
|
||||
'position': 'absolute',
|
||||
'top': '90px',
|
||||
'left': '50%',
|
||||
'margin-left': '40px',
|
||||
'cursor': 'pointer',
|
||||
'transition': 'background 200ms ease'
|
||||
});
|
||||
parent.appendChild(circle);
|
||||
|
||||
circle
|
||||
.addEventListener('mouseover', function() {
|
||||
circle.style('background', beestat.style.color.gray.dark);
|
||||
})
|
||||
.addEventListener('mouseout', function() {
|
||||
circle.style('background', beestat.style.color.bluegray.light);
|
||||
})
|
||||
.addEventListener('click', function() {
|
||||
(new beestat.component.modal.weather()).render();
|
||||
});
|
||||
|
||||
var temperature_container = $.createElement('div');
|
||||
circle.appendChild(temperature_container);
|
||||
|
||||
var temperature_whole_container = $.createElement('span')
|
||||
.style({
|
||||
'font-size': '22px',
|
||||
'font-weight': beestat.style.font_weight.light
|
||||
})
|
||||
.innerHTML(temperature_whole);
|
||||
temperature_container.appendChild(temperature_whole_container);
|
||||
|
||||
var humidity_container = $.createElement('div')
|
||||
.style({
|
||||
'display': 'inline-flex',
|
||||
'align-items': 'center'
|
||||
});
|
||||
circle.appendChild(humidity_container);
|
||||
|
||||
(new beestat.component.icon('water_percent')
|
||||
.set_size(16)
|
||||
).render(humidity_container);
|
||||
|
||||
humidity_container.appendChild(
|
||||
$.createElement('span')
|
||||
.innerHTML(thermostat.weather.humidity_relative + '%')
|
||||
.style({
|
||||
'font-size': '10px'
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decorate the running equipment list on the bottom left.
|
||||
*
|
||||
|
245
js/component/modal/weather.js
Normal file
245
js/component/modal/weather.js
Normal file
@ -0,0 +1,245 @@
|
||||
/**
|
||||
* Current weather.
|
||||
*/
|
||||
beestat.component.modal.weather = function() {
|
||||
var self = this;
|
||||
|
||||
beestat.dispatcher.addEventListener(
|
||||
'cache.thermostat',
|
||||
function() {
|
||||
self.rerender();
|
||||
}
|
||||
);
|
||||
|
||||
beestat.component.modal.apply(this, arguments);
|
||||
};
|
||||
beestat.extend(beestat.component.modal.weather, beestat.component.modal);
|
||||
|
||||
beestat.component.modal.weather.prototype.decorate_contents_ = function(parent) {
|
||||
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
|
||||
|
||||
var icon;
|
||||
var icon_color;
|
||||
switch (thermostat.weather.condition) {
|
||||
case 'sunny':
|
||||
icon = 'weather_sunny';
|
||||
icon_color = beestat.style.color.yellow.base;
|
||||
break;
|
||||
case 'few_clouds':
|
||||
case 'partly_cloudy':
|
||||
icon = 'weather_partly_cloudy';
|
||||
icon_color = beestat.style.color.gray.base;
|
||||
break;
|
||||
case 'mostly_cloudy':
|
||||
case 'overcast':
|
||||
icon = 'weather_cloudy';
|
||||
icon_color = beestat.style.color.gray.base;
|
||||
break;
|
||||
case 'drizzle':
|
||||
case 'rain':
|
||||
case 'showers':
|
||||
icon = 'weather_pouring';
|
||||
icon_color = beestat.style.color.blue.light;
|
||||
break;
|
||||
case 'freezing_rain':
|
||||
case 'hail':
|
||||
case 'pellets':
|
||||
icon_color = beestat.style.color.lightblue.base;
|
||||
icon = 'weather_hail';
|
||||
break;
|
||||
case 'snow':
|
||||
case 'flurries':
|
||||
case 'freezing_snow':
|
||||
icon_color = beestat.style.color.lightblue.light;
|
||||
icon = 'weather_snowy';
|
||||
break;
|
||||
case 'blizzard':
|
||||
icon = 'weather_snowy_heavy';
|
||||
icon_color = beestat.style.color.lightblue.light;
|
||||
break;
|
||||
case 'thunderstorm':
|
||||
icon = 'weather_lightning_rainy';
|
||||
icon_color = beestat.style.color.red.base;
|
||||
break;
|
||||
case 'windy':
|
||||
icon = 'weather_windy';
|
||||
icon_color = beestat.style.color.gray.base;
|
||||
break;
|
||||
case 'tornado':
|
||||
icon = 'weather_tornado';
|
||||
icon_color = beestat.style.color.gray.base;
|
||||
break;
|
||||
case 'fog':
|
||||
icon = 'weather_fog';
|
||||
icon_color = beestat.style.color.gray.base;
|
||||
break;
|
||||
case 'haze':
|
||||
case 'smoke':
|
||||
case 'dust':
|
||||
icon = 'weather_hazy';
|
||||
icon_color = beestat.style.color.gray.base;
|
||||
break;
|
||||
default:
|
||||
icon = 'cloud_question';
|
||||
icon_color = beestat.style.color.gray.base;
|
||||
break;
|
||||
}
|
||||
|
||||
var condition = thermostat.weather.condition.replace('_', ' ');
|
||||
condition = condition.charAt(0).toUpperCase() + condition.slice(1);
|
||||
|
||||
var tr;
|
||||
var td;
|
||||
|
||||
var table = $.createElement('table');
|
||||
|
||||
tr = $.createElement('tr');
|
||||
table.appendChild(tr);
|
||||
|
||||
td = $.createElement('td')
|
||||
.setAttribute('rowspan', '2')
|
||||
.style({
|
||||
'padding-right': beestat.style.size.gutter
|
||||
});
|
||||
(new beestat.component.icon(icon))
|
||||
.set_size(64)
|
||||
.set_color(icon_color)
|
||||
.render(td);
|
||||
tr.appendChild(td);
|
||||
|
||||
td = $.createElement('td');
|
||||
td.appendChild(
|
||||
$.createElement('span')
|
||||
.innerText(
|
||||
beestat.temperature({
|
||||
'round': 0,
|
||||
'units': true,
|
||||
'temperature': thermostat.weather.temperature
|
||||
})
|
||||
)
|
||||
.style({
|
||||
'font-size': '24px'
|
||||
})
|
||||
);
|
||||
td.appendChild(
|
||||
$.createElement('span')
|
||||
.innerText(condition)
|
||||
.style({
|
||||
'font-size': '18px',
|
||||
'padding-left': (beestat.style.size.gutter / 2)
|
||||
})
|
||||
);
|
||||
tr.appendChild(td);
|
||||
|
||||
tr = $.createElement('tr').style('color', beestat.style.color.gray.base);
|
||||
table.appendChild(tr);
|
||||
|
||||
td = $.createElement('td');
|
||||
// Low
|
||||
td.appendChild($.createElement('span').innerText('Low: '));
|
||||
td.appendChild(
|
||||
$.createElement('span')
|
||||
.innerText(
|
||||
beestat.temperature({
|
||||
'round': 0,
|
||||
'units': false,
|
||||
'temperature': thermostat.weather.temperature_low
|
||||
})
|
||||
)
|
||||
.style({
|
||||
'padding-right': (beestat.style.size.gutter / 2)
|
||||
})
|
||||
);
|
||||
// High
|
||||
td.appendChild($.createElement('span').innerText('High: '));
|
||||
td.appendChild(
|
||||
$.createElement('span')
|
||||
.innerText(
|
||||
beestat.temperature({
|
||||
'round': 0,
|
||||
'units': false,
|
||||
'temperature': thermostat.weather.temperature_high
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
tr.appendChild(td);
|
||||
|
||||
parent.appendChild(table);
|
||||
|
||||
var container = $.createElement('div')
|
||||
.style({
|
||||
'display': 'grid',
|
||||
'grid-template-columns': 'repeat(auto-fill, minmax(120px, 1fr))',
|
||||
'margin': '0 0 16px -16px'
|
||||
});
|
||||
parent.appendChild(container);
|
||||
|
||||
var bearings = [
|
||||
'N',
|
||||
'NNE',
|
||||
'NE',
|
||||
'ENE',
|
||||
'E',
|
||||
'ESE',
|
||||
'SE',
|
||||
'SSE',
|
||||
'S',
|
||||
'SSW',
|
||||
'SW',
|
||||
'WSW',
|
||||
'W',
|
||||
'WNW',
|
||||
'NW',
|
||||
'NNW'
|
||||
];
|
||||
|
||||
var fields = [
|
||||
{
|
||||
'name': 'Humidity',
|
||||
'value': thermostat.weather.humidity_relative + '%'
|
||||
},
|
||||
{
|
||||
'name': 'Dew Point',
|
||||
'value': beestat.temperature({
|
||||
'round': 0,
|
||||
'units': true,
|
||||
'temperature': thermostat.weather.dew_point
|
||||
})
|
||||
},
|
||||
{
|
||||
'name': 'Wind',
|
||||
'value': thermostat.weather.wind_speed === 0
|
||||
? '0mph'
|
||||
: thermostat.weather.wind_speed + 'mph ' + bearings[Math.floor(((thermostat.weather.wind_bearing / 22.5) + 0.5) % 16)]
|
||||
},
|
||||
{
|
||||
'name': 'Pressure',
|
||||
'value': thermostat.weather.barometric_pressure + 'mb'
|
||||
},
|
||||
{
|
||||
'name': 'Station',
|
||||
'value': thermostat.weather.station
|
||||
}
|
||||
];
|
||||
|
||||
fields.forEach(function(field) {
|
||||
var div = $.createElement('div')
|
||||
.style({
|
||||
'padding': '16px 0 0 16px'
|
||||
});
|
||||
container.appendChild(div);
|
||||
|
||||
div.appendChild($.createElement('div')
|
||||
.style({
|
||||
'font-weight': beestat.style.font_weight.bold,
|
||||
'margin-bottom': (beestat.style.size.gutter / 4)
|
||||
})
|
||||
.innerHTML(field.name));
|
||||
div.appendChild($.createElement('div').innerHTML(field.value));
|
||||
});
|
||||
};
|
||||
|
||||
beestat.component.modal.weather.prototype.get_title_ = function() {
|
||||
return 'Weather';
|
||||
};
|
@ -83,6 +83,7 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
|
||||
echo '<script src="/js/component/modal/patreon_hide.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/modal/thermostat_info.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/modal/help_score.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/modal/weather.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/input.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/input/text.js"></script>' . PHP_EOL;
|
||||
echo '<script src="/js/component/button.js"></script>' . PHP_EOL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user