mirror of
https://github.com/beestat/app.git
synced 2025-05-24 02:14:03 -04:00
Added HVAC runtime to 3d visualizer
This commit is contained in:
parent
3edda2311b
commit
79667068d4
@ -282,16 +282,17 @@ input[type=range]{
|
||||
-webkit-appearance: none;
|
||||
background:transparent;
|
||||
margin-top: 5px;
|
||||
--background: #37474f;
|
||||
}
|
||||
|
||||
input[type=range]::-webkit-slider-runnable-track {
|
||||
background: #37474f;
|
||||
background: var(--background);
|
||||
height: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
input[type=range]::-moz-range-track {
|
||||
background: #37474f;
|
||||
background: var(--background);
|
||||
height: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
@ -578,7 +578,7 @@ beestat.component.card.floor_plan_editor.prototype.decorate_info_pane_room_ = fu
|
||||
const sensors = {};
|
||||
Object.values(beestat.cache.thermostat).forEach(function(thermostat) {
|
||||
const thermostat_sensors = Object.values(beestat.cache.sensor).filter(function(sensor) {
|
||||
return sensor.thermostat_id === self.thermostat_id_;
|
||||
return sensor.thermostat_id === thermostat.thermostat_id;
|
||||
})
|
||||
.sort(function(a, b) {
|
||||
return a.name.localeCompare(b.name, 'en', {'sensitivity': 'base'});
|
||||
|
@ -340,6 +340,10 @@ beestat.component.card.three_d.prototype.decorate_drawing_pane_ = function(paren
|
||||
this.get_data_()
|
||||
);
|
||||
|
||||
this.scene_.addEventListener('change_active_room', function() {
|
||||
self.update_hud_();
|
||||
});
|
||||
|
||||
// Set the initial date.
|
||||
// if (this.has_data_() === true) {
|
||||
this.update_scene_();
|
||||
@ -428,6 +432,19 @@ beestat.component.card.three_d.prototype.decorate_drawing_pane_ = function(paren
|
||||
beestat.component.card.three_d.prototype.decorate_controls_ = function(parent) {
|
||||
const self = this;
|
||||
|
||||
const active_room = this.scene_.get_active_room_();
|
||||
let thermostat_ids;
|
||||
if (
|
||||
active_room !== null &&
|
||||
active_room.sensor_id !== undefined
|
||||
) {
|
||||
thermostat_ids = [beestat.cache.sensor[active_room.sensor_id].thermostat_id];
|
||||
} else {
|
||||
thermostat_ids = Object.keys(
|
||||
beestat.floor_plan.get_thermostat_ids_map(this.floor_plan_id_)
|
||||
);
|
||||
}
|
||||
|
||||
if (parent !== undefined) {
|
||||
this.controls_container_ = parent;
|
||||
}
|
||||
@ -441,6 +458,8 @@ beestat.component.card.three_d.prototype.decorate_controls_ = function(parent) {
|
||||
const range = new beestat.component.input.range();
|
||||
const time_container = document.createElement('div');
|
||||
|
||||
range.set_background(this.get_chart_gradient_(thermostat_ids));
|
||||
|
||||
const container = document.createElement('div');
|
||||
Object.assign(container.style, {
|
||||
'display': 'flex',
|
||||
@ -555,6 +574,108 @@ beestat.component.card.three_d.prototype.decorate_controls_ = function(parent) {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get a CSS linear gradient style that represents the runtime chart.
|
||||
*
|
||||
* @param {array} thermostat_ids Which thermostat_ids to include data from.
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
beestat.component.card.three_d.prototype.get_chart_gradient_ = function(thermostat_ids) {
|
||||
const data = this.get_data_();
|
||||
|
||||
const background_color_rgb = beestat.style.hex_to_rgb(beestat.style.color.bluegray.base);
|
||||
const background_color = 'rgba(' + background_color_rgb.r + ',' + background_color_rgb.g + ',' + background_color_rgb.b + ',1)';
|
||||
|
||||
let current_color = background_color;
|
||||
const gradient = [
|
||||
{
|
||||
'color': current_color,
|
||||
'position': 0
|
||||
}
|
||||
];
|
||||
|
||||
const date_m = moment();
|
||||
for (let i = 0; i < 287; i++) {
|
||||
const minute_of_day = i * 5;
|
||||
date_m.hours(Math.floor(minute_of_day / 60));
|
||||
date_m.minutes(Math.floor(minute_of_day % 60));
|
||||
const time = date_m.format('HH:mm');
|
||||
|
||||
let red = 0;
|
||||
let green = 0;
|
||||
let blue = 0;
|
||||
let alpha = 0;
|
||||
let count = 0;
|
||||
|
||||
let this_color = background_color;
|
||||
[
|
||||
'fan',
|
||||
'compressor_heat_1',
|
||||
'compressor_heat_2',
|
||||
'auxiliary_heat_1',
|
||||
'auxiliary_heat_2',
|
||||
'compressor_cool_1',
|
||||
'compressor_cool_2'
|
||||
].forEach(function(series_code) {
|
||||
thermostat_ids.forEach(function(thermostat_id) {
|
||||
if (
|
||||
data.series[series_code][thermostat_id] !== undefined &&
|
||||
data.series[series_code][thermostat_id][time] !== undefined &&
|
||||
data.series[series_code][thermostat_id][time] > 0
|
||||
) {
|
||||
// Only resets these if there is data to override it.
|
||||
if (count > 0) {
|
||||
red = 0;
|
||||
green = 0;
|
||||
blue = 0;
|
||||
alpha = 0;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
const color = beestat.style.hex_to_rgb(beestat.series[series_code].color);
|
||||
red += color.r;
|
||||
green += color.g;
|
||||
blue += color.b;
|
||||
alpha += data.series[series_code][thermostat_id][time] / thermostat_ids.length;
|
||||
count++;
|
||||
}
|
||||
});
|
||||
|
||||
let rgb;
|
||||
if (count > 0) {
|
||||
rgb = {
|
||||
'r': red / count,
|
||||
'g': green / count,
|
||||
'b': blue / count
|
||||
};
|
||||
alpha /= count;
|
||||
this_color = 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + alpha + ')';
|
||||
} else {
|
||||
this_color = background_color;
|
||||
}
|
||||
});
|
||||
|
||||
if (this_color !== current_color) {
|
||||
gradient.push({
|
||||
'color': this_color,
|
||||
'position': Math.round(i / 288 * 100 * 10) / 10
|
||||
});
|
||||
current_color = this_color;
|
||||
}
|
||||
}
|
||||
|
||||
let gradient_string = ['90deg'];
|
||||
|
||||
for (let i = 0; i < gradient.length; i++) {
|
||||
const start = gradient[i].position + '%';
|
||||
const end = gradient[i + 1] !== undefined ? gradient[i + 1].position + '%' : '100%';
|
||||
gradient_string.push(gradient[i].color + ' ' + start + ' ' + end);
|
||||
}
|
||||
|
||||
return 'linear-gradient(' + gradient_string.join(', ') + ')';
|
||||
};
|
||||
|
||||
/**
|
||||
* Watermark.
|
||||
*
|
||||
@ -592,7 +713,7 @@ beestat.component.card.three_d.prototype.decorate_toolbar_ = function(parent) {
|
||||
// Add room
|
||||
tile_group.add_tile(new beestat.component.tile()
|
||||
.set_icon('label_off')
|
||||
.set_title('Labels')
|
||||
.set_title('Toggle Labels')
|
||||
.set_text_color(beestat.style.color.gray.light)
|
||||
.set_background_color(beestat.style.color.bluegray.base)
|
||||
.set_background_hover_color(beestat.style.color.bluegray.light)
|
||||
@ -611,7 +732,7 @@ beestat.component.card.three_d.prototype.decorate_toolbar_ = function(parent) {
|
||||
// Add room
|
||||
tile_group.add_tile(new beestat.component.tile()
|
||||
.set_icon('restart_off')
|
||||
.set_title('Auto-Rotate')
|
||||
.set_title('Toggle Auto-Rotate')
|
||||
.set_text_color(beestat.style.color.gray.light)
|
||||
.set_background_color(beestat.style.color.bluegray.base)
|
||||
.set_background_hover_color(beestat.style.color.bluegray.light)
|
||||
|
@ -79,3 +79,16 @@ beestat.component.input.range.prototype.set_max = function(max) {
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the background value of the range input.
|
||||
*
|
||||
* @param {string} background
|
||||
*
|
||||
* @return {beestat.component.input.range} This.
|
||||
*/
|
||||
beestat.component.input.range.prototype.set_background = function(background) {
|
||||
this.input_.style.setProperty('--background', background);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
@ -223,12 +223,8 @@ beestat.component.scene.prototype.mouseup_handler_ = function() {
|
||||
window.removeEventListener('touchend', this.mouseup_handler_);
|
||||
|
||||
if (this.dragged_ === false) {
|
||||
// Clear any active state
|
||||
// if (this.active_mesh_ !== undefined) {
|
||||
// this.active_mesh_.userData.outline.visible = false;
|
||||
// }
|
||||
|
||||
this.active_mesh_ = this.intersected_mesh_;
|
||||
this.dispatchEvent('change_active_room');
|
||||
this.update_();
|
||||
}
|
||||
};
|
||||
@ -364,14 +360,14 @@ beestat.component.scene.prototype.update_ = function() {
|
||||
// Set the color of each room
|
||||
floor_plan.data.groups.forEach(function(group) {
|
||||
group.rooms.forEach(function(room) {
|
||||
const value_sprite = self.rooms_[room.room_id].userData.sprites.value;
|
||||
const icon_sprite = self.rooms_[room.room_id].userData.sprites.icon;
|
||||
const value_sprite = self.meshes_[room.room_id].userData.sprites.value;
|
||||
const icon_sprite = self.meshes_[room.room_id].userData.sprites.icon;
|
||||
|
||||
// Room outline
|
||||
if (self.rooms_[room.room_id] === self.active_mesh_) {
|
||||
self.rooms_[room.room_id].userData.outline.visible = true;
|
||||
if (self.meshes_[room.room_id] === self.active_mesh_) {
|
||||
self.meshes_[room.room_id].userData.outline.visible = true;
|
||||
} else {
|
||||
self.rooms_[room.room_id].userData.outline.visible = false;
|
||||
self.meshes_[room.room_id].userData.outline.visible = false;
|
||||
}
|
||||
|
||||
let color;
|
||||
@ -458,7 +454,7 @@ beestat.component.scene.prototype.update_ = function() {
|
||||
// Labels
|
||||
if (
|
||||
self.labels_ === true ||
|
||||
self.rooms_[room.room_id] === self.active_mesh_
|
||||
self.meshes_[room.room_id] === self.active_mesh_
|
||||
) {
|
||||
switch (self.data_type_) {
|
||||
case 'temperature':
|
||||
@ -494,7 +490,7 @@ beestat.component.scene.prototype.update_ = function() {
|
||||
icon_sprite.material = self.get_blank_label_material_();
|
||||
}
|
||||
|
||||
self.rooms_[room.room_id].material.color.setHex(color.replace('#', '0x'));
|
||||
self.meshes_[room.room_id].material.color.setHex(color.replace('#', '0x'));
|
||||
});
|
||||
});
|
||||
|
||||
@ -568,13 +564,14 @@ beestat.component.scene.prototype.add_room_ = function(layer, group, room) {
|
||||
mesh.translateY(room.y);
|
||||
|
||||
// Store a reference to the mesh representing each room.
|
||||
if (this.rooms_ === undefined) {
|
||||
this.rooms_ = {};
|
||||
if (this.meshes_ === undefined) {
|
||||
this.meshes_ = {};
|
||||
}
|
||||
|
||||
// TODO Do I need both these?
|
||||
this.rooms_[room.room_id] = mesh;
|
||||
// Allow me to go from room -> mesh and mesh -> room
|
||||
this.meshes_[room.room_id] = mesh;
|
||||
// mesh.userData.room_id = room.room_id;
|
||||
mesh.userData.room = room;
|
||||
|
||||
layer.add(mesh);
|
||||
|
||||
@ -982,3 +979,16 @@ beestat.component.scene.prototype.dispose = function() {
|
||||
window.cancelAnimationFrame(this.animation_frame_);
|
||||
beestat.component.prototype.dispose.apply(this, arguments);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the currently active room.
|
||||
*
|
||||
* @return {object}
|
||||
*/
|
||||
beestat.component.scene.prototype.get_active_room_ = function() {
|
||||
if (this.active_mesh_ !== undefined) {
|
||||
return this.active_mesh_.userData.room;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user