1
0
mirror of https://github.com/beestat/app.git synced 2026-02-26 13:10:23 -05:00
This commit is contained in:
Jon Ziebell 2026-02-22 08:53:07 -05:00
parent 410f775cb1
commit 236bf6caa5
10 changed files with 521 additions and 612 deletions

View File

@ -1,5 +1,62 @@
beestat.floor_plan = {};
/**
* Pending save timeouts keyed by floor_plan_id.
*
* @type {Object<string, number>}
*/
beestat.floor_plan.data_save_timeouts_ = {};
/**
* Queue a floor plan data save, debounced per floor plan.
*
* @param {number} floor_plan_id
* @param {number} delay_ms
*/
beestat.floor_plan.queue_data_save_ = function(floor_plan_id, delay_ms = 300) {
if (floor_plan_id === undefined || floor_plan_id === null || floor_plan_id === '') {
return;
}
const normalized_floor_plan_id = Number(floor_plan_id);
if (Number.isFinite(normalized_floor_plan_id) !== true || normalized_floor_plan_id <= 0) {
return;
}
let normalized_delay_ms = Number(delay_ms);
if (Number.isFinite(normalized_delay_ms) !== true || normalized_delay_ms < 0) {
normalized_delay_ms = 0;
}
normalized_delay_ms = Math.round(normalized_delay_ms);
if (beestat.floor_plan.data_save_timeouts_[normalized_floor_plan_id] !== undefined) {
window.clearTimeout(beestat.floor_plan.data_save_timeouts_[normalized_floor_plan_id]);
}
beestat.floor_plan.data_save_timeouts_[normalized_floor_plan_id] = window.setTimeout(function() {
delete beestat.floor_plan.data_save_timeouts_[normalized_floor_plan_id];
const floor_plan = beestat.cache.floor_plan[normalized_floor_plan_id];
if (floor_plan === undefined || floor_plan.data === undefined) {
return;
}
new beestat.api()
.add_call(
'floor_plan',
'update',
{
'attributes': {
'floor_plan_id': normalized_floor_plan_id,
'data': beestat.clone(floor_plan.data)
}
},
'update_floor_plan'
)
.send();
}, normalized_delay_ms);
};
/**
* Get the area of an entire floor plan.
*

View File

@ -76,18 +76,12 @@ beestat.setting = function(argument_1, opt_value, opt_callback) {
.format('MM/DD/YYYY'),
'visualize.heat_map_values': 'dynamic',
'visualize.heat_map_static.temperature.min': 70,
'visualize.heat_map_static.temperature.max': 80,
'visualize.heat_map_static.occupancy.min': 0,
'visualize.heat_map_static.occupancy.max': 100,
'visualize.hide_affiliate': false,
'visualize.three_d.show_labels': true,
'visualize.three_d.auto_rotate': false,
'visualize.three_d.show_walls': false,
'visualize.three_d.show_roof': false,
'visualize.three_d.show_environment': true,
'visualize.three_d.weather_mode': 'sunny',
'date_format': 'M/D/YYYY',
'visualize.heat_map_static.temperature.max': 80,
'visualize.heat_map_static.occupancy.min': 0,
'visualize.heat_map_static.occupancy.max': 100,
'visualize.hide_affiliate': false,
'date_format': 'M/D/YYYY',
'units.currency': 'usd',

406
js/beestat/weather.js Normal file
View File

@ -0,0 +1,406 @@
beestat.weather = {};
/**
* Unified weather settings keyed by condition.
*
* Field meanings:
* `condition`: Canonical condition string stored in floor-plan scene data.
* `icon`: MDI icon id used by weather UI controls/modals.
* `icon_color`: UI accent color for the weather icon.
* `cloud_density`: Controls cloud particle count/intensity in the scene.
* `cloud_darkness`: Controls cloud shading/dimming (0 clear -> 2 very dark).
* `rain_density`: Controls rain particle count/intensity.
* `snow_density`: Controls snow particle count/intensity and snow-cover blend.
* `lightning_frequency`: Controls frequency/intensity of lightning effects.
* `wind_speed`: Controls animation strength for wind-affected scene elements.
*
* Density/intensity fields are tuned for roughly 0..2 in current scene logic.
*/
beestat.weather.settings_ = {
'sunny': {
'condition': 'sunny',
'icon': 'weather_sunny',
'icon_color': beestat.style.color.yellow.base,
'cloud_density': 0.03,
'cloud_darkness': 0,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.4
},
'few_clouds': {
'condition': 'few_clouds',
'icon': 'weather_partly_cloudy',
'icon_color': beestat.style.color.gray.base,
'cloud_density': 0.18,
'cloud_darkness': 0,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.45
},
'partly_cloudy': {
'condition': 'partly_cloudy',
'icon': 'weather_partly_cloudy',
'icon_color': beestat.style.color.gray.base,
'cloud_density': 0.3,
'cloud_darkness': 0.1,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.55
},
'mostly_cloudy': {
'condition': 'mostly_cloudy',
'icon': 'weather_cloudy',
'icon_color': beestat.style.color.gray.base,
'cloud_density': 0.75,
'cloud_darkness': 0.45,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.7
},
'overcast': {
'condition': 'overcast',
'icon': 'weather_cloudy',
'icon_color': beestat.style.color.gray.base,
'cloud_density': 0.5,
'cloud_darkness': 0.4,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.8
},
'drizzle': {
'condition': 'drizzle',
'icon': 'weather_pouring',
'icon_color': beestat.style.color.blue.light,
'cloud_density': 0.9,
'cloud_darkness': 0.7,
'rain_density': 0.35,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.75
},
'rain': {
'condition': 'rain',
'icon': 'weather_pouring',
'icon_color': beestat.style.color.blue.light,
'cloud_density': 1,
'cloud_darkness': 1,
'rain_density': 1,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.8
},
'showers': {
'condition': 'showers',
'icon': 'weather_pouring',
'icon_color': beestat.style.color.blue.light,
'cloud_density': 1.2,
'cloud_darkness': 1.1,
'rain_density': 1.2,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 1
},
'freezing_rain': {
'condition': 'freezing_rain',
'icon': 'weather_hail',
'icon_color': beestat.style.color.lightblue.base,
'cloud_density': 1.2,
'cloud_darkness': 1.2,
'rain_density': 1.1,
'snow_density': 0.2,
'lightning_frequency': 0,
'wind_speed': 1
},
'hail': {
'condition': 'hail',
'icon': 'weather_hail',
'icon_color': beestat.style.color.lightblue.base,
'cloud_density': 1.25,
'cloud_darkness': 1.25,
'rain_density': 1.2,
'snow_density': 0.15,
'lightning_frequency': 0.1,
'wind_speed': 1.1
},
'pellets': {
'condition': 'pellets',
'icon': 'weather_hail',
'icon_color': beestat.style.color.lightblue.base,
'cloud_density': 1.25,
'cloud_darkness': 1.25,
'rain_density': 1.2,
'snow_density': 0.15,
'lightning_frequency': 0.1,
'wind_speed': 1.1
},
'snow': {
'condition': 'snow',
'icon': 'weather_snowy',
'icon_color': beestat.style.color.lightblue.light,
'cloud_density': 1,
'cloud_darkness': 1,
'rain_density': 0,
'snow_density': 1,
'lightning_frequency': 0,
'wind_speed': 0.4
},
'flurries': {
'condition': 'flurries',
'icon': 'weather_snowy',
'icon_color': beestat.style.color.lightblue.light,
'cloud_density': 0.85,
'cloud_darkness': 0.7,
'rain_density': 0,
'snow_density': 0.55,
'lightning_frequency': 0,
'wind_speed': 0.65
},
'freezing_snow': {
'condition': 'freezing_snow',
'icon': 'weather_snowy',
'icon_color': beestat.style.color.lightblue.light,
'cloud_density': 1.1,
'cloud_darkness': 1,
'rain_density': 0.05,
'snow_density': 1.1,
'lightning_frequency': 0,
'wind_speed': 0.7
},
'blizzard': {
'condition': 'blizzard',
'icon': 'weather_snowy_heavy',
'icon_color': beestat.style.color.lightblue.light,
'cloud_density': 1.4,
'cloud_darkness': 1.5,
'rain_density': 0.1,
'snow_density': 1.8,
'lightning_frequency': 0,
'wind_speed': 1.6
},
'thunderstorm': {
'condition': 'thunderstorm',
'icon': 'weather_lightning_rainy',
'icon_color': beestat.style.color.red.base,
'cloud_density': 1.5,
'cloud_darkness': 2,
'rain_density': 2,
'snow_density': 0,
'lightning_frequency': 1,
'wind_speed': 1.6
},
'windy': {
'condition': 'windy',
'icon': 'weather_windy',
'icon_color': beestat.style.color.gray.base,
'cloud_density': 0.55,
'cloud_darkness': 0.3,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 1.5
},
'tornado': {
'condition': 'tornado',
'icon': 'weather_tornado',
'icon_color': beestat.style.color.gray.base,
'cloud_density': 1.35,
'cloud_darkness': 1.6,
'rain_density': 1.3,
'snow_density': 0,
'lightning_frequency': 0.5,
'wind_speed': 2
},
'fog': {
'condition': 'fog',
'icon': 'weather_fog',
'icon_color': beestat.style.color.gray.base,
'cloud_density': 0.6,
'cloud_darkness': 0.2,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.25
},
'haze': {
'condition': 'haze',
'icon': 'weather_hazy',
'icon_color': beestat.style.color.gray.base,
'cloud_density': 0.45,
'cloud_darkness': 0.35,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.6
},
'smoke': {
'condition': 'smoke',
'icon': 'weather_hazy',
'icon_color': beestat.style.color.gray.base,
'cloud_density': 0.45,
'cloud_darkness': 0.35,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.6
},
'dust': {
'condition': 'dust',
'icon': 'weather_hazy',
'icon_color': beestat.style.color.gray.base,
'cloud_density': 0.45,
'cloud_darkness': 0.35,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.6
}
};
/**
* Fallback settings for unknown conditions.
* Used when a condition string is missing or unsupported.
*/
beestat.weather.default_settings_ = {
'condition':'sunny',
'icon': 'cloud_question',
'icon_color': beestat.style.color.gray.base,
'cloud_density': 0.03,
'cloud_darkness': 0,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.4
};
/**
* Find weather settings by condition.
* Returns a full weather row; falls back to `default_settings_`.
*
* @param {string} condition
*/
beestat.weather.get_settings_ = function(condition) {
if (beestat.weather.settings_[condition] !== undefined) {
return beestat.weather.settings_[condition];
}
return beestat.weather.default_settings_;
};
/**
* Get UI icon id for a weather condition.
*
* @param {string} condition
*
* @return {string}
*/
beestat.weather.get_icon = function(condition) {
return beestat.weather.get_settings_(condition).icon;
};
/**
* Get UI icon color for a weather condition.
*
* @param {string} condition
*
* @return {string}
*/
beestat.weather.get_icon_color = function(condition) {
return beestat.weather.get_settings_(condition).icon_color;
};
/**
* Get cloud density for a condition.
* Higher values increase cloud population and perceived overcast coverage.
*
* @param {string} condition
*
* @return {number}
*/
beestat.weather.get_cloud_density = function(condition) {
return beestat.weather.get_settings_(condition).cloud_density;
};
/**
* Get cloud darkness for a condition.
* Higher values darken clouds and dim overall sky illumination.
*
* @param {string} condition
*
* @return {number}
*/
beestat.weather.get_cloud_darkness = function(condition) {
return beestat.weather.get_settings_(condition).cloud_darkness;
};
/**
* Get rain density for a condition.
* Higher values increase rain particle count and rainfall intensity.
*
* @param {string} condition
*
* @return {number}
*/
beestat.weather.get_rain_density = function(condition) {
return beestat.weather.get_settings_(condition).rain_density;
};
/**
* Get snow density for a condition.
* Higher values increase snow particle count and snow-cover blending.
*
* @param {string} condition
*
* @return {number}
*/
beestat.weather.get_snow_density = function(condition) {
return beestat.weather.get_settings_(condition).snow_density;
};
/**
* Get lightning frequency for a condition.
* Higher values produce more frequent/intense lightning events.
*
* @param {string} condition
*
* @return {number}
*/
beestat.weather.get_lightning_frequency = function(condition) {
return beestat.weather.get_settings_(condition).lightning_frequency;
};
/**
* Get wind speed for a condition.
* Higher values increase wind-driven animation (trees/precipitation behavior).
*
* @param {string} condition
*
* @return {number}
*/
beestat.weather.get_wind_speed = function(condition) {
return beestat.weather.get_settings_(condition).wind_speed;
};
/**
* Convert condition into a title-case label.
*
* @param {string} condition
*
* @return {string}
*/
beestat.weather.get_condition_label = function(condition) {
const value = typeof condition === 'string' && condition.length > 0
? condition
: 'unknown';
return value
.split('_')
.map(function(part) {
return part.charAt(0).toUpperCase() + part.slice(1);
})
.join(' ');
};

View File

@ -2563,27 +2563,11 @@ beestat.component.card.floor_plan_editor.prototype.get_title_ = function() {
* only run so fast.
*/
beestat.component.card.floor_plan_editor.prototype.update_floor_plan_ = function() {
const self = this;
const floor_plan_id = beestat.setting('visualize.floor_plan_id');
// Fake this event since the cache is being directly modified.
beestat.dispatcher.dispatchEvent('cache.floor_plan');
window.clearTimeout(this.update_timeout_);
this.update_timeout_ = window.setTimeout(function() {
new beestat.api()
.add_call(
'floor_plan',
'update',
{
'attributes': {
'floor_plan_id': beestat.setting('visualize.floor_plan_id'),
'data': self.get_floor_plan_data_(beestat.setting('visualize.floor_plan_id'))
}
},
'update_floor_plan'
)
.send();
}, 1000);
beestat.floor_plan.queue_data_save_(floor_plan_id, 1000);
};
/**

View File

@ -86,7 +86,7 @@ beestat.component.card.three_d = function() {
this.scene_settings_values_ = undefined;
this.scene_settings_scroll_top_ = 0;
this.scene_settings_panel_content_ = undefined;
this.scene_visualize_save_timeout_ = undefined;
this.weather_values_ = ['auto', 'sunny', 'overcast', 'rain', 'thunderstorm', 'snow'];
beestat.component.card.apply(this, arguments);
};
@ -124,20 +124,6 @@ beestat.component.card.three_d.rerender_required_scene_settings = {
'light_user_enabled': true
};
/**
* Valid persisted weather values for the 3D scene.
*
* @type {!Array<string>}
*/
beestat.component.card.three_d.weather_values = [
'auto',
'sunny',
'overcast',
'rain',
'thunderstorm',
'snow'
];
/**
* Decorate
*
@ -660,27 +646,7 @@ beestat.component.card.three_d.prototype.get_scene_visualize_state_ = function()
* Persist current floor plan data after scene-visualize changes.
*/
beestat.component.card.three_d.prototype.save_scene_visualize_state_ = function() {
const self = this;
window.clearTimeout(this.scene_visualize_save_timeout_);
this.scene_visualize_save_timeout_ = window.setTimeout(function() {
const floor_plan = beestat.cache.floor_plan[self.floor_plan_id_];
if (floor_plan === undefined || floor_plan.data === undefined) {
return;
}
new beestat.api()
.add_call(
'floor_plan',
'update',
{
'attributes': {
'floor_plan_id': self.floor_plan_id_,
'data': beestat.clone(floor_plan.data)
}
},
'update_floor_plan'
)
.send();
}, 300);
beestat.floor_plan.queue_data_save_(this.floor_plan_id_, 300);
};
/**
@ -724,7 +690,7 @@ beestat.component.card.three_d.prototype.get_weather_ = function() {
return 'auto';
}
const weather = scene_visualize.weather;
if (beestat.component.card.three_d.weather_values.includes(weather) !== true) {
if (this.weather_values_.includes(weather) !== true) {
scene_visualize.weather = 'auto';
this.save_scene_visualize_state_();
return 'auto';
@ -742,7 +708,7 @@ beestat.component.card.three_d.prototype.set_weather_ = function(weather) {
if (scene_visualize === null) {
return;
}
const normalized_weather = beestat.component.card.three_d.weather_values.includes(weather)
const normalized_weather = this.weather_values_.includes(weather)
? weather
: 'auto';
scene_visualize.weather = normalized_weather;
@ -756,82 +722,21 @@ beestat.component.card.three_d.prototype.set_weather_ = function(weather) {
*/
beestat.component.card.three_d.prototype.get_auto_weather_from_thermostat_ = function() {
const thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
const condition = thermostat?.weather?.condition;
switch (condition) {
case 'sunny':
case 'few_clouds':
case 'partly_cloudy':
case 'mostly_cloudy':
case 'overcast':
case 'drizzle':
case 'rain':
case 'showers':
case 'freezing_rain':
case 'hail':
case 'pellets':
case 'snow':
case 'flurries':
case 'freezing_snow':
case 'blizzard':
case 'thunderstorm':
case 'windy':
case 'tornado':
case 'fog':
case 'haze':
case 'smoke':
case 'dust':
return condition;
default:
return 'sunny';
}
return beestat.weather.get_settings_(thermostat?.weather?.condition).condition;
};
/**
* Get weather icon from weather condition using modal weather icon mapping.
* Resolve selected weather mode into a weather condition.
*
* @param {string} condition
* @param {string} weather
*
* @return {string}
*/
beestat.component.card.three_d.prototype.get_weather_icon_from_condition_ = function(condition) {
switch (condition) {
case 'sunny':
return 'weather_sunny';
case 'few_clouds':
case 'partly_cloudy':
return 'weather_partly_cloudy';
case 'mostly_cloudy':
case 'overcast':
return 'weather_cloudy';
case 'drizzle':
case 'rain':
case 'showers':
return 'weather_pouring';
case 'freezing_rain':
case 'hail':
case 'pellets':
return 'weather_hail';
case 'snow':
case 'flurries':
case 'freezing_snow':
return 'weather_snowy';
case 'blizzard':
return 'weather_snowy_heavy';
case 'thunderstorm':
return 'weather_lightning_rainy';
case 'windy':
return 'weather_windy';
case 'tornado':
return 'weather_tornado';
case 'fog':
return 'weather_fog';
case 'haze':
case 'smoke':
case 'dust':
return 'weather_hazy';
default:
return 'cloud_question';
beestat.component.card.three_d.prototype.get_weather_condition_from_mode_ = function(weather) {
if (weather === 'auto') {
return this.get_auto_weather_from_thermostat_();
}
return beestat.weather.get_settings_(weather).condition;
};
/**
@ -842,10 +747,7 @@ beestat.component.card.three_d.prototype.get_weather_icon_from_condition_ = func
* @return {string}
*/
beestat.component.card.three_d.prototype.get_weather_icon_from_mode_ = function(weather) {
const condition = weather === 'auto'
? this.get_auto_weather_from_thermostat_()
: weather;
return this.get_weather_icon_from_condition_(condition);
return beestat.weather.get_icon(this.get_weather_condition_from_mode_(weather));
};
/**
@ -855,11 +757,11 @@ beestat.component.card.three_d.prototype.get_weather_icon_from_mode_ = function(
*/
beestat.component.card.three_d.prototype.get_weather_mode_tiles_ = function() {
return [
{'value': 'sunny', 'icon': 'weather_sunny', 'title': 'Weather: Sunny'},
{'value': 'overcast', 'icon': 'weather_cloudy', 'title': 'Weather: Overcast'},
{'value': 'rain', 'icon': 'weather_pouring', 'title': 'Weather: Rain'},
{'value': 'thunderstorm', 'icon': 'weather_lightning_rainy', 'title': 'Weather: Thunderstorm'},
{'value': 'snow', 'icon': 'weather_snowy', 'title': 'Weather: Snow'}
{'value': 'sunny', 'icon': beestat.weather.get_icon('sunny'), 'title': 'Weather: Sunny'},
{'value': 'overcast', 'icon': beestat.weather.get_icon('overcast'), 'title': 'Weather: Overcast'},
{'value': 'rain', 'icon': beestat.weather.get_icon('rain'), 'title': 'Weather: Rain'},
{'value': 'thunderstorm', 'icon': beestat.weather.get_icon('thunderstorm'), 'title': 'Weather: Thunderstorm'},
{'value': 'snow', 'icon': beestat.weather.get_icon('snow'), 'title': 'Weather: Snow'}
];
};
@ -962,186 +864,15 @@ beestat.component.card.three_d.prototype.set_show_group_ = function(group_id, vi
* }}
*/
beestat.component.card.three_d.prototype.get_weather_settings_from_weather_ = function(weather) {
const effective_weather = weather === 'auto'
? this.get_auto_weather_from_thermostat_()
: weather;
switch (effective_weather) {
case 'few_clouds':
return {
'cloud_density': 0.18,
'cloud_darkness': 0,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.45
};
case 'partly_cloudy':
return {
'cloud_density': 0.3,
'cloud_darkness': 0.1,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.55
};
case 'mostly_cloudy':
return {
'cloud_density': 0.75,
'cloud_darkness': 0.45,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.7
};
case 'drizzle':
return {
'cloud_density': 0.9,
'cloud_darkness': 0.7,
'rain_density': 0.35,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.75
};
case 'showers':
return {
'cloud_density': 1.2,
'cloud_darkness': 1.1,
'rain_density': 1.2,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 1
};
case 'freezing_rain':
return {
'cloud_density': 1.2,
'cloud_darkness': 1.2,
'rain_density': 1.1,
'snow_density': 0.2,
'lightning_frequency': 0,
'wind_speed': 1
};
case 'hail':
case 'pellets':
return {
'cloud_density': 1.25,
'cloud_darkness': 1.25,
'rain_density': 1.2,
'snow_density': 0.15,
'lightning_frequency': 0.1,
'wind_speed': 1.1
};
case 'flurries':
return {
'cloud_density': 0.85,
'cloud_darkness': 0.7,
'rain_density': 0,
'snow_density': 0.55,
'lightning_frequency': 0,
'wind_speed': 0.65
};
case 'freezing_snow':
return {
'cloud_density': 1.1,
'cloud_darkness': 1,
'rain_density': 0.05,
'snow_density': 1.1,
'lightning_frequency': 0,
'wind_speed': 0.7
};
case 'blizzard':
return {
'cloud_density': 1.4,
'cloud_darkness': 1.5,
'rain_density': 0.1,
'snow_density': 1.8,
'lightning_frequency': 0,
'wind_speed': 1.6
};
case 'thunderstorm':
return {
'cloud_density': 1.5,
'cloud_darkness': 2,
'rain_density': 2,
'snow_density': 0,
'lightning_frequency': 1,
'wind_speed': 1.6
};
case 'windy':
return {
'cloud_density': 0.55,
'cloud_darkness': 0.3,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 1.5
};
case 'tornado':
return {
'cloud_density': 1.35,
'cloud_darkness': 1.6,
'rain_density': 1.3,
'snow_density': 0,
'lightning_frequency': 0.5,
'wind_speed': 2
};
case 'fog':
return {
'cloud_density': 0.6,
'cloud_darkness': 0.2,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.25
};
case 'haze':
case 'smoke':
case 'dust':
return {
'cloud_density': 0.45,
'cloud_darkness': 0.35,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.6
};
case 'overcast':
return {
'cloud_density': 0.5,
'cloud_darkness': 0.4,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.8
};
case 'rain':
return {
'cloud_density': 1,
'cloud_darkness': 1,
'rain_density': 1,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.8
};
case 'snow':
return {
'cloud_density': 1,
'cloud_darkness': 1,
'rain_density': 0,
'snow_density': 1,
'lightning_frequency': 0,
'wind_speed': 0.4
};
case 'sunny':
default:
return {
'cloud_density': 0.03,
'cloud_darkness': 0,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.4
};
}
const condition = this.get_weather_condition_from_mode_(weather);
return {
'cloud_density': beestat.weather.get_cloud_density(condition),
'cloud_darkness': beestat.weather.get_cloud_darkness(condition),
'rain_density': beestat.weather.get_rain_density(condition),
'snow_density': beestat.weather.get_snow_density(condition),
'lightning_frequency': beestat.weather.get_lightning_frequency(condition),
'wind_speed': beestat.weather.get_wind_speed(condition)
};
};
/**
@ -2342,7 +2073,7 @@ beestat.component.card.three_d.prototype.decorate_floors_ = function(parent) {
const sorted_groups = Object.values(floor_plan.data.groups)
.sort(function(a, b) {
return a.elevation > b.elevation;
return (a.elevation || 0) - (b.elevation || 0);
});
let icon_number = 1;
@ -2843,10 +2574,6 @@ beestat.component.card.three_d.prototype.force_dispose_stale_instance_ = functio
this.rerender_timeout_id_ = undefined;
this.rerender_pending_delay_ms_ = undefined;
}
if (this.scene_visualize_save_timeout_ !== undefined) {
window.clearTimeout(this.scene_visualize_save_timeout_);
this.scene_visualize_save_timeout_ = undefined;
}
this.rerender_waiting_for_visibility_ = false;
if (this.visibility_observer_ !== undefined) {
this.visibility_observer_.disconnect();
@ -2870,10 +2597,6 @@ beestat.component.card.three_d.prototype.dispose = function() {
this.rerender_timeout_id_ = undefined;
this.rerender_pending_delay_ms_ = undefined;
}
if (this.scene_visualize_save_timeout_ !== undefined) {
window.clearTimeout(this.scene_visualize_save_timeout_);
this.scene_visualize_save_timeout_ = undefined;
}
this.rerender_waiting_for_visibility_ = false;
if (this.visibility_observer_ !== undefined) {
this.visibility_observer_.disconnect();

View File

@ -804,7 +804,7 @@ beestat.component.floor_plan.prototype.update_toolbar = function() {
const sorted_groups = Object.values(floor_plan.data.groups)
.sort(function(a, b) {
return a.elevation > b.elevation;
return (a.elevation || 0) - (b.elevation || 0);
});
let icon_number = 1;
@ -1709,7 +1709,7 @@ beestat.component.floor_plan.prototype.get_tree_group_ = function() {
const floor_plan = beestat.cache.floor_plan[this.floor_plan_id_];
const sorted_groups = Object.values(floor_plan.data.groups)
.sort(function(a, b) {
return a.elevation > b.elevation;
return (a.elevation || 0) - (b.elevation || 0);
});
const first_floor = sorted_groups.find(function(group) {

View File

@ -67,7 +67,7 @@ beestat.component.modal.update_floor_plan.prototype.decorate_contents_ = functio
const sorted_groups = Object.values(floor_plan.data.groups)
.sort(function(a, b) {
return a.elevation > b.elevation;
return (a.elevation || 0) - (b.elevation || 0);
});
sorted_groups.forEach(function(group) {

View File

@ -15,78 +15,12 @@ beestat.component.modal.weather = function() {
};
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);
beestat.component.modal.weather.prototype.decorate_contents_ = function(parent) {
var thermostat = beestat.cache.thermostat[beestat.setting('thermostat_id')];
var icon = beestat.weather.get_icon(thermostat.weather.condition);
var icon_color = beestat.weather.get_icon_color(thermostat.weather.condition);
var condition = beestat.weather.get_condition_label(thermostat.weather.condition);
var tr;
var td;

View File

@ -15,206 +15,16 @@ beestat.component.scene.prototype.set_weather = function(weather) {
if (floor_plan.data.appearance === undefined) {
floor_plan.data.appearance = {};
}
floor_plan.data.appearance.weather = weather;
// Translate weather presets to scene density values.
let weather_settings;
switch (weather) {
case 'few_clouds':
weather_settings = {
'cloud_density': 0.18,
'cloud_darkness': 0,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.45
};
break;
case 'partly_cloudy':
weather_settings = {
'cloud_density': 0.3,
'cloud_darkness': 0.1,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.55
};
break;
case 'mostly_cloudy':
weather_settings = {
'cloud_density': 0.75,
'cloud_darkness': 0.45,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.7
};
break;
case 'drizzle':
weather_settings = {
'cloud_density': 0.9,
'cloud_darkness': 0.7,
'rain_density': 0.35,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.75
};
break;
case 'showers':
weather_settings = {
'cloud_density': 1.2,
'cloud_darkness': 1.1,
'rain_density': 1.2,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 1
};
break;
case 'freezing_rain':
weather_settings = {
'cloud_density': 1.2,
'cloud_darkness': 1.2,
'rain_density': 1.1,
'snow_density': 0.2,
'lightning_frequency': 0,
'wind_speed': 1
};
break;
case 'hail':
case 'pellets':
weather_settings = {
'cloud_density': 1.25,
'cloud_darkness': 1.25,
'rain_density': 1.2,
'snow_density': 0.15,
'lightning_frequency': 0.1,
'wind_speed': 1.1
};
break;
case 'flurries':
weather_settings = {
'cloud_density': 0.85,
'cloud_darkness': 0.7,
'rain_density': 0,
'snow_density': 0.55,
'lightning_frequency': 0,
'wind_speed': 0.65
};
break;
case 'freezing_snow':
weather_settings = {
'cloud_density': 1.1,
'cloud_darkness': 1,
'rain_density': 0.05,
'snow_density': 1.1,
'lightning_frequency': 0,
'wind_speed': 0.7
};
break;
case 'blizzard':
weather_settings = {
'cloud_density': 1.4,
'cloud_darkness': 1.5,
'rain_density': 0.1,
'snow_density': 1.8,
'lightning_frequency': 0,
'wind_speed': 1.6
};
break;
case 'windy':
weather_settings = {
'cloud_density': 0.55,
'cloud_darkness': 0.3,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 1.5
};
break;
case 'tornado':
weather_settings = {
'cloud_density': 1.35,
'cloud_darkness': 1.6,
'rain_density': 1.3,
'snow_density': 0,
'lightning_frequency': 0.5,
'wind_speed': 2
};
break;
case 'fog':
weather_settings = {
'cloud_density': 0.6,
'cloud_darkness': 0.2,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.25
};
break;
case 'haze':
case 'smoke':
case 'dust':
weather_settings = {
'cloud_density': 0.45,
'cloud_darkness': 0.35,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.6
};
break;
case 'thunderstorm':
weather_settings = {
'cloud_density': 1.5,
'cloud_darkness': 2,
'rain_density': 2,
'snow_density': 0,
'lightning_frequency': 1,
'wind_speed': 1.6
};
break;
case 'snow':
weather_settings = {
'cloud_density': 1,
'cloud_darkness': 1,
'rain_density': 0,
'snow_density': 1,
'lightning_frequency': 0,
'wind_speed': 0.4
};
break;
case 'rain':
weather_settings = {
'cloud_density': 1,
'cloud_darkness': 1,
'rain_density': 1,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.8
};
break;
case 'overcast':
weather_settings = {
'cloud_density': 0.5,
'cloud_darkness': 0.4,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.8
};
break;
case 'sunny':
default:
weather_settings = {
'cloud_density': 0.03,
'cloud_darkness': 0,
'rain_density': 0,
'snow_density': 0,
'lightning_frequency': 0,
'wind_speed': 0.4
};
break;
}
const normalized_weather = beestat.weather.get_settings_(weather).condition;
floor_plan.data.appearance.weather = normalized_weather;
const weather_settings = {
'cloud_density': beestat.weather.get_cloud_density(normalized_weather),
'cloud_darkness': beestat.weather.get_cloud_darkness(normalized_weather),
'rain_density': beestat.weather.get_rain_density(normalized_weather),
'snow_density': beestat.weather.get_snow_density(normalized_weather),
'lightning_frequency': beestat.weather.get_lightning_frequency(normalized_weather),
'wind_speed': beestat.weather.get_wind_speed(normalized_weather)
};
this.set_scene_settings(weather_settings, {
'rerender': false
});

View File

@ -32,9 +32,10 @@ if($setting->get('environment') === 'dev' || $setting->get('environment') === 'd
echo '<script src="/js/beestat/debounce.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/dispatcher.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/cache.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/clone.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/style.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/api.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/clone.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/style.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/weather.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/api.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/error.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/temperature.js"></script>' . PHP_EOL;
echo '<script src="/js/beestat/distance.js"></script>' . PHP_EOL;