@eva-ics/hmi-block_ui
Version:
Block UI for EVA ICS
1,636 lines (1,592 loc) • 56.9 kB
JavaScript
`use strict`;
(() => {
const $ = require("jquery");
window.$ = $;
require("bootstrap");
require("bootstrap/dist/css/bootstrap.min.css");
require("swiped-events");
const VanillaToasts = require("vanillatoasts");
require("vanillatoasts/vanillatoasts.css");
require("@eva-ics/framework");
require("@eva-ics/toolbox");
const $eva = window.$eva;
var login_window;
var content_holder;
var first_time_login = true;
var btn_coord;
var camera_reloader = Array();
var chart_creators = Array();
var current_layout_compact = false;
var initialized = false;
var slider_update_funcs = Array();
var menu_active = false;
var popover_cbtns = Array();
var timers = Array();
var embedded = false;
function error(msg) {
throw new Error(msg);
}
function body_error_message(msg) {
content_holder.html('<div class="eva_hmi_body_error">' + msg + "</div>");
}
function display_info_bar(msg, cl, timeout) {
if (!cl) cl = "info";
if (!timeout) timeout = 2;
$("#eva_hmi_popup").removeClass();
$("#eva_hmi_popup").addClass("infobar");
$("#eva_hmi_popup").addClass(cl);
$("#eva_hmi_popup").html(msg);
$("#eva_hmi_popup").show();
setTimeout(function() {
$("#eva_hmi_popup").fadeOut(200);
}, timeout * 1000);
}
function server_error(err, wait, title) {
var t = wait !== undefined ? wait : 2000;
var msg = err.message;
if (!msg) msg = err;
if (!embedded) {
let toast = VanillaToasts.create({
title: title ? title : "Error",
type: "error",
text: msg,
timeout: t
});
} else {
display_info_bar(msg, "error");
}
}
function server_is_gone(err) {
stop_intervals();
var ct = 10;
var auto_reconnect = setTimeout(function() {
$eva.start();
}, (ct + 1) * 1000);
if (embedded) {
body_error_message("SERVER ERROR");
} else {
$eva.toolbox
.popup(
"eva_hmi_popup",
"error",
"Server error " + err,
"Connection to server failed",
{
ct: ct,
btn1: "Retry"
}
)
.then(function() {
clearTimeout(auto_reconnect);
$eva.start();
})
.catch((err) => {});
}
}
function create_control_block(block_id) {
if (
!window.eva_hmi_config_control_blocks ||
!(block_id in window.eva_hmi_config_control_blocks)
) {
$eva.hmi.error("Control block " + block_id + " is not defined");
}
var cblk = $("<div />");
cblk.addClass("eva_hmi_control_block");
$.each(window.eva_hmi_config_control_blocks[block_id]["elements"], function(
i,
v
) {
cblk.append(create_button(v));
});
return cblk;
}
function success(text, title) {
if (embedded || window.eva_hmi_config_info_level != "info") return;
let toast = VanillaToasts.create({
title: title ? title : "Completed",
type: "success",
text: text ? text : "Command successful",
timeout: 2000
});
}
function create_api_action(
api_method,
action_item,
params,
el,
config,
is_btn
) {
var on_error = function() {
el.removeClass("busy");
};
if (action_item.startsWith("unit:")) {
var before_start = function() {};
} else {
var before_start = function() {
el.addClass("busy");
};
}
var process_result = function() {};
var after_start = function() {};
if (!action_item.startsWith("unit:")) {
after_start = function() {
el.removeClass("busy");
success();
};
}
if (action_item.startsWith("lmacro:") || action_item.startsWith("unit:")) {
process_result = function(result) {
if (!result || !result.uuid) {
server_error("Action failed");
} else {
$eva.watch_action(result.uuid, function(a) {
if (a.finished) {
if (
a.exitcode ||
(a.status != "completed" && a.status != "ignored")
) {
server_error(
'<div align="left" width="100%">' +
a.uuid +
"<br />action: " +
a.item_oid +
"<br />code: " +
a.exitcode +
"; status: " +
a.status +
"<br />" +
a.err +
"</div>",
null,
"Action failed"
);
} else {
success("Action finished");
}
}
});
}
};
}
if (
(config.busy || (api_method == "run" && config.busy !== false)) &&
is_btn &&
!action_item.startsWith("lvar:")
) {
after_start = function(result) {
if (!result || !result.uuid) {
server_error(err);
on_error();
}
};
el.custom_busy = true;
if (!config.busy || config.busy == "uuid") {
after_start = function(result) {
if (!result || !result.uuid) {
el.removeClass("busy");
} else {
$eva.watch_action(result.uuid, function(a) {
if (a.finished) {
el.removeClass("busy");
}
});
}
};
} else if (config.busy.startsWith("lvar:")) {
after_start = function(result) {
let state = $eva.state(config.busy);
if (
!state.status ||
!state.value ||
($eva.api_version == 4 && state.status == 0) ||
($eva.api_version == 3 && state.value == "0")
) {
el.removeClass("busy");
}
if (!result || !result.uuid) {
server_error(err);
on_error();
}
};
set_el_busy_lvar(config.busy, el);
} else {
$eva.hmi.error("unknown busy class: " + config.busy);
}
}
return function() {
if (el.hasClass("busy")) return;
before_start();
$eva
.call(api_method, action_item, params)
.then(function(result) {
after_start(result);
process_result(result);
})
.catch(function(err) {
on_error(err);
server_error(err);
});
};
}
function set_el_busy_lvar(lvar, el) {
if (!lvar || !lvar.startsWith("lvar:")) return false;
$eva.watch(lvar, function(state) {
if (
state.status &&
state.value &&
(($eva.api_version == 4 && state.value != 0) ||
($eva.api_version == 3 && state.value != "0"))
) {
el.addClass("busy");
} else {
el.removeClass("busy");
}
});
el.custom_busy = true;
}
function append_action(el, config, is_btn, item) {
var action = config.action;
var a = null;
if (!action) {
if (is_btn) {
action = config.item;
if (!action) return;
} else {
return;
}
}
if (config.menu) {
if (is_btn) el.addClass("menu");
set_el_busy_lvar(config.busy, el);
if (config.menu === true || typeof config.menu == "number") {
var ms;
config.menu === true ? (ms = 2) : (ms = config.menu);
var mc = $("<span />");
for (var i = 0; i < ms; i++) {
var b = $("<button >");
b.addClass("eva_hmi_cbtn");
b.addClass("i_" + config.icon);
b.addClass("s_" + i);
b.append($("<span />", { class: "btn_border" }));
b.append($("<span />", { class: "btn_img" }));
var params = $.extend({}, config.action_params);
b.attr("eva-ui-status-to", i);
b.on("click", function() {
params["s"] = parseInt(this.getAttribute("eva-ui-status-to"));
let afunc = create_api_action(
"action",
action,
params,
el,
config,
is_btn
);
afunc();
});
b.appendTo(mc);
}
} else {
var mc = $("<span />");
$.each(config.menu, function(i, v) {
var b = create_button(v);
popover_cbtns.push(b);
b.appendTo(mc);
});
}
el.popover({
placement: "bottom",
html: true,
trigger: "click",
content: mc
});
el.attr("data-toggle", "popover");
a = function(e) {
e.preventDefault();
e.stopPropagation();
$('[data-toggle="popover"]').popover("hide");
if (!el.hasClass("busy") || config["allow-if-busy"]) el.popover("show");
};
} else if (config.slider && is_btn) {
el.addClass("menu");
set_el_busy_lvar(config.busy, el);
var min = config.slider.min;
var max = config.slider.max;
var step = config.slider.step;
var off_allowed = config.slider.can_off;
if (min === undefined || min === null) min = 0;
if (max === undefined || max === null) max = 100;
if (step == undefined || step === null) step = 1;
var mc = $("<span />");
var slc = $("<div />").addClass("eva_hmi_slider_container");
var slider = $("<input />", {
id: "eva_hmi_slider_" + item,
type: "range",
min: min - (off_allowed ? step : 0),
max: max
}).addClass("eva_hmi_slider");
var slider_label = $("<div />", {
id: "eva_hmi_slider_label_" + item
}).addClass("eva_hmi_slider_label");
slider.on("input change", function() {
var val = this.value;
if (val < min) {
val = "OFF";
slider.removeClass("slider_on");
slider.addClass("slider_off");
} else {
slider.removeClass("slider_off");
slider.addClass("slider_on");
}
slider_label.html(
val + (config.value && val >= min ? config.value : "")
);
});
slider.attr("step", step);
slider.on("mouseup touchend", function() {
$('[data-toggle="popover"]').popover("hide");
var params = $.extend({}, config.action_params);
var val = slider.val();
if (action.startsWith("unit:")) {
if (val < min) {
params["s"] = 0;
} else {
params["s"] = 1;
params["v"] = val;
}
let afunc = create_api_action(
"action",
action,
params,
el,
config,
is_btn
);
afunc();
} else if (action.startsWith("lvar:")) {
var v;
v = val < min ? null : val;
let method;
if ($eva.api_version == 4) {
method = "lvar.set";
} else {
method = "set";
}
let afunc = create_api_action(
method,
action,
{ v: v },
el,
config,
is_btn
);
afunc();
} else if (action.startsWith("lmacro:")) {
var params = $.extend({}, config.action_params);
if (val < min) {
params["a"] = "OFF";
} else {
params["a"] = val;
}
let afunc = create_api_action(
"run",
action,
params,
el,
config,
is_btn
);
afunc();
}
});
slider_update_funcs[item] = function(state) {
if (state.status || !off_allowed) {
slider.val(state.value);
slider_label.html(
state.value +
(config.value && state.value >= min ? config.value : "")
);
slider.removeClass("slider_off");
slider.addClass("slider_on");
} else {
slider.val(min - step);
slider_label.html("OFF");
slider.removeClass("slider_on");
slider.addClass("slider_off");
}
};
slc.append(slider);
slc.append(slider_label);
mc.append(slc);
el.popover({
placement: "bottom",
html: true,
trigger: "click",
content: mc
});
el.attr("data-toggle", "popover");
a = function(e) {
e.preventDefault();
e.stopPropagation();
$('[data-toggle="popover"]').popover("hide");
if (!el.hasClass("busy") || config["allow-if-busy"]) el.popover("show");
};
} else if (action.startsWith("unit:")) {
if (config.action_params && "s" in config.action_params) {
a = create_api_action(
"action",
action,
config.action_params,
el,
config,
is_btn
);
} else {
let method;
if ($eva.api_version == 4) {
method = "action.toggle";
} else {
method = "action_toggle";
}
a = create_api_action(
method,
action,
config.action_params,
el,
config,
is_btn
);
}
} else if (action.startsWith("lvar:")) {
if (config.action_params && "v" in config.action_params) {
let method;
if ($eva.api_version == 4) {
method = "lvar.set";
} else {
method = "set";
}
a = create_api_action(
method,
action,
config.action_params,
el,
config,
is_btn
);
} else {
let method;
if ($eva.api_version == 4) {
method = "lvar.toggle";
} else {
method = "toggle";
}
a = create_api_action(method, action, null, el, config, is_btn);
}
} else if (action.startsWith("lmacro:")) {
if (is_btn) el.addClass("gear");
var params = $.extend({}, config.action_params);
a = create_api_action("run", action, params, el, config, is_btn);
} else if (action.startsWith("url:")) {
a = function() {
document.location = action.substring(4);
};
} else if (action.startsWith("javascript:")) {
a = function() {
eval(action);
};
}
if (a) {
el.on("click", a);
if (!is_btn) {
el.css("cursor", "pointer");
}
}
}
function create_button(btn_name) {
if (
!window.eva_hmi_config_buttons ||
!(btn_name in window.eva_hmi_config_buttons)
) {
$eva.hmi.error("Button " + btn_name + " is not defined");
}
var btn_config = window.eva_hmi_config_buttons[btn_name];
var button = $("<button />", { id: "eva_hmi_cbtn_" + btn_name });
button.addClass("eva_hmi_cbtn");
$.each(btn_config.icon.split("."), function(i, v) {
button.addClass((i == 0 ? "i_" : "") + v);
});
$("<span />")
.addClass("btn_border")
.appendTo(button);
button.append($("<span />", { class: "btn_img" }));
if (btn_config.title) {
$("<span />")
.addClass("title")
.html(btn_config.title)
.appendTo(button);
}
var button_value = null;
if (btn_config.value !== false || btn_config.timer) {
button_value = $("<span />");
var bv = $("<span />").addClass("value");
bv.append(button_value);
var button_value_units = $("<span />");
bv.append(button_value_units);
button.append(bv);
var value_always = btn_config["value-always"];
var value_units = btn_config.value;
}
var item = btn_config.item;
var istatus = btn_config.status;
var timer = btn_config.timer;
if (timer) {
let timer_max = btn_config["timer-max"];
let timer_func = function() {
let exp = $eva.expires_in(timer);
if (exp > 0) {
button_value.html(seconds_to_pretty_string(exp, timer_max));
} else {
button_value.html("");
}
};
timers.push(setInterval(timer_func, 100));
}
if (!istatus) istatus = item;
button.custom_busy = false;
append_action(button, btn_config, true, istatus);
if (istatus) {
if (istatus.startsWith("unit:")) {
button.addClass("s_");
$eva.watch(istatus, function(state) {
if (istatus in slider_update_funcs) {
slider_update_funcs[istatus](state);
}
button.attr(
"class",
button
.attr("class")
.replace(
/\bs_\d*/g,
"s_" + (state.status >= 0 ? state.status : 0)
)
);
if (state.status == -1) {
button.append($("<span />", { class: "eva_hmi_cbtn_error" }));
} else {
button.find(".eva_hmi_cbtn_error").remove();
}
if (button_value) {
if (!timer) {
if (state.status > 0 || value_always) {
button_value.html(state.value);
button_value_units.html(value_units);
} else {
button_value.html("");
button_value_units.html("");
}
}
}
if (!button.custom_busy) {
if (
state.act ||
(state.nstatus !== undefined &&
(state.status != state.nstatus || state.value != state.nvalue))
) {
button.addClass("busy");
} else {
button.removeClass("busy");
}
}
});
} else if (istatus.startsWith("lvar:")) {
if (istatus in slider_update_funcs) {
slider_update_funcs[istatus](state);
}
button.addClass("s_");
$eva.watch(istatus, function(state) {
let st;
if ($eva.api_version == 4) {
st = state.status;
} else {
st = state.value;
}
button.attr(
"class",
button.attr("class").replace(/\bs_.*/g, "s_" + st)
);
});
}
}
return button;
}
function create_data_item(data_item_id, size, css_class) {
if (
!window.eva_hmi_config_data ||
!(data_item_id in window.eva_hmi_config_data)
) {
$eva.hmi.error("data item " + data_item_id + " is not defined");
}
var d = $("<div />").addClass("eva_hmi_data_item_holder");
if (size) {
d.addClass("size_" + size);
}
if (css_class) {
d.addClass(css_class);
}
var data_item_config = window.eva_hmi_config_data[data_item_id];
var data_item = $("<div />");
var data_item_value = $("<span />", {
id: "eva_hmi_data_value_" + data_item_id
});
if ("title" in data_item_config) {
let title = $("<div />")
.html(data_item_config["title"])
.addClass("eva_hmi_data_item_title");
if (size) {
title.addClass("size_" + size);
}
if (css_class) {
title.addClass(css_class);
}
title.appendTo(data_item);
}
data_item.append(data_item_value);
$("<span />")
.html(data_item_config["units"])
.appendTo(data_item);
data_item.attr("eva-display-decimals", data_item_config["decimals"]);
data_item.addClass("eva_hmi_data_item");
if (data_item_config.icon) {
data_item.addClass("i_" + data_item_config.icon);
data_item.css("background-repeat", "no-repeat");
} else {
data_item.addClass("i_none");
}
append_action(data_item, data_item_config, false);
var item = data_item_config["item"];
if (data_item_config["timer"]) {
let timer_max = data_item_config["timer-max"];
let timer_func = function() {
let exp = $eva.expires_in(item);
if (exp > 0) {
data_item_value.html(seconds_to_pretty_string(exp, timer_max, size));
} else if (exp == -1) {
data_item_value.html("DONE");
} else if (exp == -2) {
data_item_value.html("STOPPED");
}
};
timers.push(setInterval(timer_func, 100));
} else {
$eva.watch(item, function(state) {
var v = state.value;
var dc = data_item.attr("eva-display-decimals");
if (dc !== undefined && dc !== null && !isNaN(v)) {
try {
v = parseFloat(v).toFixed(dc);
} catch (e) {}
}
data_item_value.html(v);
});
}
if (size) {
data_item.addClass("size_" + size);
}
if (css_class) {
data_item.addClass(css_class);
}
return d.append(data_item);
}
function recreate_objects() {
$.each(chart_creators, function(i, v) {
v();
});
}
function run() {
redraw_layout();
stop_animation();
content_holder.show();
recreate_objects();
}
function init() {
initialized = true;
var u = new URLSearchParams(window.location.search);
embedded = u.get("embedded");
if (!embedded) {
if (!$eva.in_evaHI) {
document.addEventListener("swiped-right", function(e) {
if (!menu_active) {
open_menu();
}
});
document.addEventListener("swiped-left", function(e) {
if (menu_active) {
close_menu();
}
});
}
} else {
$eva.apikey = u.get("k");
}
if (!window.eva_hmi_config) {
error("HMI config not loaded");
}
if (!window.eva_hmi_config_url)
window.eva_hmi_config_url = document.location;
if (typeof window.evaHI === "object" && window.evaHI["index"]) {
window.eva_hmi_config_main_page = window.evaHI["index"];
} else {
window.eva_hmi_config_main_page = "/ui/";
}
if ("url" in window.eva_hmi_config) {
window.eva_hmi_config_url = window.eva_hmi_config["url"];
}
if ("class" in window.eva_hmi_config) {
window.eva_hmi_config_class = window.eva_hmi_config["class"];
}
if ("info-level" in window.eva_hmi_config) {
window.eva_hmi_config_info_level = window.eva_hmi_config["info-level"];
} else {
window.eva_hmi_config_info_level = "info";
}
if ("title" in window.eva_hmi_config) {
window.eva_hmi_config_title = window.eva_hmi_config["title"];
}
if ("motd" in window.eva_hmi_config) {
window.eva_hmi_config_motd = window.eva_hmi_config["motd"];
}
if ("default-login" in window.eva_hmi_config) {
$eva.login = window.eva_hmi_config["default-login"];
}
window.eva_hmi_config_layout = $.extend(
window.eva_hmi_config_layout,
window.eva_hmi_config["layout"]
);
window.eva_hmi_config_layout_compact = $.extend(
window.eva_hmi_config_layout_compact,
window.eva_hmi_config["layout-compact"]
);
$("body").empty();
var close_popover = function(e) {
if (
$(e.target).data("toggle") !== "popover" &&
$(e.target).parents(".popover.in").length === 0
) {
$('[data-toggle="popover"]').popover("hide");
}
if (
$(e.target).data("toggle") !== "menu" &&
$(e.target).data("toggle") != "menuicon" &&
$(e.target)
.parents()
.data("toggle") != "menuicon"
) {
close_menu();
}
};
$("body").on("click", close_popover);
if (embedded == "friendly")
$("body", window.parent.document).on("click", close_popover);
$("<div />", { id: "eva_hmi_popup" }).appendTo("body");
$("<div />", { id: "eva_hmi_anim" }).appendTo("body");
if (!embedded) {
$("<div />")
.addClass("eva_hmi_dialog_window_holder")
.addClass("evacc_setup")
.on("click", close_cc_setup)
.html(
'<div class="eva_hmi_dialog_window"> \
<div class="eva_hmi_setup_form"> \
<div class="eva_hmi_close_btn"></div> \
<a href="https://play.google.com/store/apps/details?id=com.altertech.evacc" \
class="eva_hmi_andr_app"></a> \
<span>Scan this code with </span> \
<a href="https://play.google.com/store/apps/details?id=com.altertech.evacc" \
class="eva_hmi_app_link">EVA Control Center app</a> \
<div class="eva_hmi_qr_install"><canvas id="evaccqr"></canvas></div> \
</div> \
</div>'
)
.appendTo("body");
}
if (
window.eva_hmi_config_class == "dashboard" ||
window.eva_hmi_config_class == "simple"
) {
window.eva_hmi_config_buttons = $.extend(
window.eva_hmi_config_buttons,
window.eva_hmi_config["buttons"]
);
window.eva_hmi_config_data = $.extend(
window.eva_hmi_config_data,
window.eva_hmi_config["data"]
);
window.eva_hmi_config_data_blocks = $.extend(
window.eva_hmi_config_data_blocks,
window.eva_hmi_config["data-blocks"]
);
window.eva_hmi_config_control_blocks = $.extend(
window.eva_hmi_config_control_blocks,
window.eva_hmi_config["control-blocks"]
);
window.eva_hmi_config_cameras = $.extend(
window.eva_hmi_config_cameras,
window.eva_hmi_config["cameras"]
);
var page_bg = $("<div />")
.addClass("eva_hmi_bg embedded")
.appendTo("body");
if (!embedded) {
page_bg.removeClass("embedded");
login_window = $("<div >/", {
id: "login_window"
}).addClass("eva_hmi_dialog_window_holder");
login_window.hide();
login_window.html(
'<div class="eva_hmi_dialog_window"> \
<form id="eva_hmi_login_form"> \
<div class="form-group eva_hmi_input_form"> \
<div class="eva_hmi_error_message" id="eva_hmi_login_error"></div> \
<input type="text" class="form-control" name="login" \
id="eva_hmi_login" value="" placeholder="User"/> \
<input type="password" class="form-control" \
name="password" id="eva_hmi_password" \
value="" placeholder="Password"/> \
</div> \
<div class="form-group eva_hmi_custom_checkbox"> \
<input type="checkbox" id="eva_hmi_remember_auth"/> \
<label for="eva_hmi_remember_auth">Remember me</label> \
</div> \
<div class="form-group"> \
<input type="submit" class="btn" \
id="eva_hmi_btn_login" value="Log in"/> \
</div> \
</form> \
</div>'
);
login_window.appendTo("body");
$("#eva_hmi_login_form").on("submit", submit_login);
if (window.eva_hmi_config_motd) {
var motd = $("<div />")
.addClass("eva_hmi_motd")
.html(window.eva_hmi_config_motd);
$("#eva_hmi_login_form").append(motd);
}
var cnt = $("<div />").addClass("eva_hmi_container");
var main = $("<div />", { id: "eva_hmi_main" });
var container = $("<div />").addClass("container");
var row = $("<div />").addClass("row");
cnt.appendTo("body");
main.appendTo(cnt);
container.appendTo(main);
row.appendTo(container);
content_holder = $("<div />").addClass("eva_hmi_content_holder");
content_holder.hide();
content_holder.appendTo(row);
$eva.on("login.success", function() {
login_window.hide();
update_sysblock();
run();
});
$eva.on("heartbeat.error", function() {
$eva
.stop(true)
.then(server_is_gone)
.catch(server_is_gone);
});
$eva.on("login.failed", function(err) {
stop_intervals();
if (err.code == 2 || err.code == -32002) {
stop_animation();
erase_login_cookies();
content_holder.hide();
login_window.show();
if (first_time_login) {
first_time_login = false;
} else {
$("#eva_hmi_login_error").html(err.message);
$("#eva_hmi_login_error").show();
}
$("#eva_hmi_login").val($eva.login);
$("#eva_hmi_password").val("");
focus_login_form();
} else {
server_is_gone(err);
}
});
}
} else if (window.eva_hmi_config_class == "sensors") {
if ("main-page" in window.eva_hmi_config) {
window.eva_hmi_config_main_page = window.eva_hmi_config["main-page"];
}
window.eva_hmi_config_charts = $.extend(
window.eva_hmi_config_charts,
window.eva_hmi_config["charts"]
);
if (!embedded) {
$eva.on("login.success", function() {
update_sysblock();
run();
});
$eva.on("login.failed", function(err) {
document.location = window.eva_hmi_config_main_page;
});
var cnt = $("<div />")
.addClass("eva_hmi_container")
.addClass("sensors");
content_holder = $("<div />").addClass(
"eva_hmi_content_holder_sensors"
);
content_holder.hide();
content_holder.appendTo(cnt);
if (window.eva_hmi_config_layout["sys-block"]) {
cnt.append(create_sysblock());
}
$("<div />")
.addClass("eva_hmi_bg")
.appendTo("body");
cnt.appendTo("body");
}
}
if (embedded) {
content_holder = $("<div />");
if (window.eva_hmi_config_class == "sensors") {
content_holder.addClass("eva_hmi_content_holder_sensors");
} else {
content_holder.addClass("eva_hmi_content_holder");
}
content_holder.addClass("embedded");
content_holder.appendTo("body");
$eva.on("login.success", function() {
update_sysblock();
run();
});
$eva.on("heartbeat.error", function() {
$eva
.stop(true)
.then(server_is_gone)
.catch(server_is_gone);
});
$eva.on("login.failed", function(err) {
stop_intervals();
if (err.code == 2 || err.code == -32002) {
stop_animation();
body_error_message("ACCESS DENIED");
} else {
server_is_gone(err);
}
});
}
var reload_ui = function() {
document.location = document.location;
};
$eva.on("server.reload", function() {
var ct = 5;
var ui_reloader = setTimeout(reload_ui, ct * 1000);
if (!embedded) {
$eva.toolbox
.popup(
"eva_hmi_popup",
"warning",
"UI reload",
"Server asked clients to reload UI",
{
ct: ct,
btn1: "Reload"
}
)
.then(function() {
clearTimeout(ui_reloader);
reload_ui();
})
.catch((err) => {});
} else {
display_info_bar("EVA ICS asked to reload UI", "info", 5);
}
});
$eva.on("server.restart", function() {
var ct = 15;
stop_intervals();
$eva.stop(true).catch((err) => {});
if (!embedded) {
$eva.toolbox
.popup(
"eva_hmi_popup",
"warning",
"Server restart",
"Server is being restarted, UI will be reconnected in" +
` ${ct} seconds. All functions are stopped`,
{
ct: ct
}
)
.catch((err) => {});
} else {
display_info_bar("Waiting for server restart", "warning", 15);
}
setTimeout(function() {
$eva.start();
}, ct * 1000);
});
}
function focus_login_form() {
if ($eva.login) {
$("#eva_hmi_login").val($eva.login);
$("#eva_hmi_password").focus();
} else {
$("#eva_hmi_login").focus();
}
}
function update_sysblock() {
if ($eva.server_info) {
$(".eva_version").html($eva.server_info.version);
if ($eva.api_version == 4) {
$(".eva_build").html($eva.server_info.build);
} else {
$(".eva_build").html($eva.server_info.product_build);
}
$(".eva_framework_version").html($eva.version);
let mode = $eva.get_mode();
if (mode == "wasm") {
mode = "W" + window.evajw.get_build();
}
$(".eva_framework_mode").html(mode);
$(".eva_key_id").html($eva.server_info.acl.key_id);
$(".eva_user").html($eva.authorized_user);
}
}
function stop_intervals() {
while (camera_reloader.length > 0) {
let reloader = camera_reloader.pop();
clearInterval(reloader);
}
while (timers.length > 0) {
let reloader = timers.pop();
clearInterval(reloader);
}
}
function draw_top_bar() {
var topbar = $("<div />", { id: "eva_hmi_top_bar" });
var hamb = $("<div />", { "data-toggle": "menuicon", id: "eva_hmi_hamb" });
for (var i = 0; i < 3; i++) {
$("<span />").appendTo(hamb);
}
hamb.on("click", toggle_menu);
topbar.append(hamb);
topbar.append(create_sysblock(true, "eva_hmi_top_bar_sysblock"));
content_holder.addClass("with_topbar");
content_holder.append(topbar);
$("#vanillatoasts-container").css("top", "35px");
var menu_container = $("<div />", { id: "eva_hmi_menu_container" });
$("<div />", { class: "bg_helper" }).appendTo(menu_container);
var menu_holder = $("<div />", {
id: "eva_hmi_menu",
"data-toggle": "menu"
});
var menu = $("<div />", { class: "eva_hmi_menu_holder" });
menu_holder.append(menu);
if (typeof window.evaHI === "object" && window.evaHI["home_icon"]) {
menu.append(
create_menu_item(
"Home",
"/" + window.evaHI["home_icon"],
window.eva_hmi_config_main_page
).addClass("eva_hmi_menu_page")
);
topbar.append(
create_menu_item(
"Home",
"/" + window.evaHI["home_icon"],
window.eva_hmi_config_main_page
)
);
} else {
menu.append(
create_menu_item(
"Home",
"home",
window.eva_hmi_config_main_page
).addClass("eva_hmi_menu_page")
);
topbar.append(
create_menu_item("Home", "home", window.eva_hmi_config_main_page)
);
}
if (typeof window.evaHI === "object" && window.evaHI["menu"]) {
$.each(window.evaHI["menu"], function(i, v) {
menu.append(
create_menu_item(v["name"], "/" + v["icon"], v["url"]).addClass(
"eva_hmi_menu_page"
)
);
topbar.append(
create_menu_item(v["name"], "/" + v["icon"], v["url"], true)
);
});
}
menu.append(create_menu_item("EvaCC setup", "evahi", open_cc_setup));
menu.append(create_menu_item("Logout", "logout", logout));
menu.append(
$("<div />")
.addClass("eva_hmi_logo_container")
.append(
$("<div />")
.addClass("eva_hmi_logo")
.html($eva.hmi.logo.text)
.on("click", function() {
document.location = $eva.hmi.logo.href;
})
)
);
content_holder.append(menu_container);
content_holder.append(menu_holder);
}
function create_menu_item(title, icon, action, for_topbar) {
var menu_item = $("<div />");
menu_item.addClass("eva_hmi_menu_item");
var menu_icon = $("<div />");
menu_icon.addClass("eva_hmi_menu_icon");
if (!icon.startsWith("/")) {
menu_icon.addClass("i_" + icon + (for_topbar ? "_tb" : ""));
} else {
menu_icon.css("background-image", "url(/.evahi/icons" + icon + ")");
menu_icon.addClass("i_evahi_icon");
}
menu_icon.attr("title", title);
menu_item.append(menu_icon);
menu_item.append(
$("<div />")
.addClass("eva_hmi_menu_title")
.html(title)
);
if (typeof action === "function") {
menu_item.on("click", action);
} else {
menu_item.on("click", function() {
document.location = action;
});
}
return menu_item;
}
function toggle_menu() {
if (menu_active) {
close_menu();
} else {
open_menu();
}
}
function open_menu() {
$("body").css("overflow", "hidden");
menu_active = true;
$("#eva_hmi_hamb").addClass("open");
$("#eva_hmi_menu").animate({ width: "toggle" }, 250);
$("#eva_hmi_menu_container").fadeIn(250);
$("#eva_hmi_menu_container .bg_helper").show(500);
}
function close_menu() {
if (menu_active) {
$("body").css("overflow", "auto");
menu_active = false;
$("#eva_hmi_hamb").removeClass("open");
$("#eva_hmi_menu").animate({ width: "toggle" }, 250);
$("#eva_hmi_menu_container").fadeOut(250);
$("#eva_hmi_menu_container .bg_helper").hide();
}
}
function correct_cbtn_padding() {
var padding = ($(window).width() - 24) / 8 - 10;
var max_padding = 40;
if (padding > max_padding) padding = max_padding;
if (padding < 0) padding = 0;
$(".eva_hmi_cbtn").css("padding", padding);
$.each(popover_cbtns, function(i, v) {
v.css("padding", padding);
});
}
function clear_layout() {
content_holder.empty();
popover_cbtns = Array();
$eva.unwatch();
}
function redraw_layout() {
clear_layout();
$eva.hmi.prepare_layout();
if (!embedded) $eva.hmi.top_bar();
stop_intervals();
chart_creators = Array();
if ($(window).width() < 768) {
draw_compact_layout();
current_layout_compact = true;
correct_cbtn_padding();
} else {
draw_layout();
current_layout_compact = false;
}
update_sysblock();
$eva.hmi.after_draw(current_layout_compact);
}
function create_data_block(block_id) {
var dh = $("<div />").addClass("eva_hmi_data_holder");
if (
!window.eva_hmi_config_data_blocks ||
!(block_id in window.eva_hmi_config_data_blocks) ||
!("elements" in window.eva_hmi_config_data_blocks[block_id])
) {
$eva.hmi.error(
"data block " + block_id + " is not defined or contains no elements"
);
}
var config = window.eva_hmi_config_data_blocks[block_id];
if ("size" in config) {
dh.addClass("size_" + config["size"]);
}
if ("css-class" in config) {
dh.addClass(config["css-class"]);
}
$.each(config["elements"], function(i, v) {
dh.append(create_data_item(v, config["size"], config["css-class"]));
});
append_action(dh, window.eva_hmi_config_data_blocks[block_id], false);
return dh;
}
function create_cam(cam_cfg, big) {
if (!cam_cfg || !("id" in cam_cfg)) {
$eva.hmi.error("Invalid camera block");
}
if (
!window.eva_hmi_config_cameras ||
!(cam_cfg["id"] in window.eva_hmi_config_cameras)
) {
$eva.hmi.error("Camera " + cam_cfg["id"] + " is not defined");
}
var cam_id = cam_cfg["id"];
var reload_int = cam_cfg["reload"];
if (!reload_int) reload_int = 1;
var cam = $("<div />").addClass("eva_hmi_camera_block");
var cam_img = $("<img />").attr("id", "eva_hmi_camera_" + cam_id);
if (!big) {
cam_img.addClass("eva_hmi_cam_preview");
} else {
cam_img.addClass("eva_hmi_cam_preview_big");
}
cam_img.addClass("eva_hmi_cam_img");
cam_img.appendTo(cam);
var reloader = setInterval(function() {
reload_camera(cam_id);
}, reload_int * 1000);
camera_reloader.push(reloader);
append_action(cam, cam_cfg, false);
return cam;
}
function format_chart_config(cfg_id, chart_cfg) {
return chart_cfg;
}
function create_chart_config(config) {
var c_type = config["type"] ? config["type"] : "line";
var item;
if (!("item" in config)) {
$eva.hmi.error("No item in chart config");
}
if (Array.isArray(config["item"])) {
item = config["item"];
} else {
item = config["item"].split(",");
}
var chart_cfg = {
type: c_type,
data: {
labels: [],
datasets: []
},
options: $.extend(
{},
typeof eva_hmi_config_chart_options === "function"
? eva_hmi_config_chart_options(config["cfg"])
: eva_hmi_config_chart_options
)
};
var count = item.length;
if (Array.isArray(config["params"]["timeframe"])) {
count *= config["params"]["timeframe"].length;
}
for (let i = 0; i < count; i++) {
if (Array.isArray(config["label"])) {
var c_label = config["label"][i];
} else {
var c_label = config["label"] ? config["label"] : "start";
}
if (Array.isArray(config["fill"])) {
var c_fill = config["fill"][i];
} else {
var c_fill = config["fill"] ? config["fill"] : "start";
}
if (Array.isArray(config["color"])) {
var c_color = config["color"][i];
} else {
var c_color = config["color"] ? config["color"] : "#aaaaaa";
}
if (Array.isArray(config["pointr"])) {
var c_pointr = config["point-radius"][i];
} else {
var c_pointr = config["point-radius"] ? config["point-radius"] : 0;
}
if (Array.isArray(config["background-color"])) {
var c_background = config["background-color"][i];
} else {
var c_background = config["background-color"]
? config["background-color"]
: "#eeeeee";
}
var dataset = {
label: c_label,
data: [],
fill: c_fill,
pointRadius: c_pointr,
borderColor: c_color,
backgroundColor: c_background
};
chart_cfg.data.datasets.push(dataset);
}
if (!chart_cfg.options.legend) {
if (config["legend"]) {
let legend = Array.isArray(config["legend"])
? config["legend"]
: [config["legend"]];
chart_cfg.options.legend = {
display: true,
labels: {
generateLabels: function(chart) {
let result = [];
legend.map((l, i) => {
let z = {
text: l,
strokeStyle: chart.config.data.datasets[i].borderColor
};
if (chart.config.data.datasets[i].backgroundColor) {
z.fillStyle = chart.config.data.datasets[i].backgroundColor;
}
result.push(z);
});
return result;
}
}
};
} else {
chart_cfg.options.legend = { display: false };
}
}
if (config["cfg"] && config["cfg"] != "default") {
$eva.hmi.format_chart_config(config["cfg"], chart_cfg);
}
return chart_cfg;
}
function create_chart(chart_id, reload) {
var reload_int = reload;
var chart_config = window.eva_hmi_config_charts[chart_id];
if (!chart_config) {
$eva.hmi.error("No config for chart " + chart_id);
}
if (!reload_int) reload_int = 60;
var chart = $("<div />").addClass("eva_hmi_chart_item");
var chart_title = chart_config["title"];
if (!chart_title) chart_title = " ";
$("<div />")
.addClass("eva_hmi_chart_title")
.html(chart_title)
.appendTo(chart);
var chart_info = $("<div />")
.addClass("i_" + chart_config["icon"])
.addClass("eva_hmi_data_item")
.addClass("chart_info");
chart_info.css("background-repeat", "no-repeat");
var chart_item_state = $("<span />", {
id: "eva_hmi_chart_" + chart_id + "_state"
}).appendTo(chart_info);
chart_item_state.attr("eva-display-decimals", chart_config["decimals"]);
$("<span />")
.html(chart_config["units"])
.appendTo(chart_info);
chart.append(
$('<div class="eva_hmi_data_item_holder chart_info" />').append(
chart_info
)
);
if (
"params" in chart_config &&
chart_config["params"]["prop"] == "status"
) {
$eva.watch(chart_config["item"], function(state) {
chart_item_state.html(state.status);
});
} else {
$eva.watch(chart_config["item"], function(state) {
var v = state.value;
var dc = chart_item_state.attr("eva-display-decimals");
if (dc !== undefined && dc !== null && !isNaN(v)) {
try {
v = parseFloat(v).toFixed(dc);
} catch (e) {}
}
chart_item_state.html(v);
});
}
$("<div />")
.addClass("eva_hmi_chart_units")
.html(chart_config["units"])
.appendTo(chart);
$("<div />", { id: "eva_hmi_chart_content_" + chart_id })
.addClass("eva_hmi_chart")
.appendTo(chart);
var params = $.extend({}, chart_config.params);
params["update"] = reload_int;
params["units"] = chart_config["units"];
var ccfg = create_chart_config(chart_config);
var creator = function() {
$eva.toolbox.chart(
"eva_hmi_chart_content_" + chart_id,
ccfg,
chart_config["item"],
params
);
};
chart_creators.push(creator);
return chart;
}
function draw_layout(for_compact) {
var cams = Array();
if (window.eva_hmi_config_class == "dashboard") {
var eva_bar_holder = $("<div />", { class: "eva_hmi_bar_holder" });
if (embedded) eva_bar_holder.addClass("embedded");
for (i = 1; i < 100; i++) {
if ("bar" + i in window.eva_hmi_config_layout) {
var bar = $("<div />").addClass("eva_hmi_bar");
if (embedded) bar.addClass("embedded");
var bar_cfg = window.eva_hmi_config_layout["bar" + i];
if ("camera" in bar_cfg) {
var cam = create_cam(bar_cfg["camera"]);
bar.append(cam);
cams.push(bar_cfg["camera"]["id"]);
}
var fcb = true;
if ("control-blocks" in bar_cfg) {
$.each(bar_cfg["control-blocks"], function(i, v) {
var cb = create_control_block(v);
if (!("camera" in bar_cfg)) {
cb.css("border-top", "0px");
}
bar.append(cb);
fcb = false;
});
}
var dblk = null;
if (bar_cfg["data-block"]) {
if (!dblk) dblk = $("<div />").addClass("eva_hmi_data_block");
dblk.append(create_data_block(bar_cfg["data-block"]));
}
if (bar_cfg["sys-block"]) {
if (!dblk) dblk = $("<div />").addClass("eva_hmi_data_block");
dblk.append(create_sysblock());
}
if (dblk) bar.append(dblk);
eva_bar_holder.append(bar);
content_holder.append(eva_bar_holder);
}
}
} else if (window.eva_hmi_config_class == "sensors") {
if (!$eva.in_evaHI && !embedded) {
$("<a />")
.attr("href", window.eva_hmi_config_main_page)
.addClass("eva_hmi_close_btn")
.addClass("secondary_page")
.appendTo(content_holder);
}
$.each(window.eva_hmi_config_layout["charts"], function(i, v) {
var chart = create_chart(v["id"], v["reload"]);
content_holder.append(chart);
});
} else if (window.eva_hmi_config_class == "simple") {
var holder = $("<div />", {
class: "eva_hmi_bar_holder single_bar_holder"
});
if ("camera" in window.eva_hmi_config_layout) {
var cam = create_cam(window.eva_hmi_config_layout["camera"], true);
holder.append(cam);
cams.push(window.eva_hmi_config_layout["camera"]["id"]);
}
if ("buttons" in window.eva_hmi_config_layout) {
$.each(window.eva_hmi_config_layout["buttons"], function(i, v) {
var btn = create_button(v);
holder.append(btn);
});
}
if (window.eva_hmi_config_layout.sysblock) {
holder.append(create_sysblock());
}
content_holder.append(holder);
}
if (!for_compact) {
content_holder.removeClass("compact");
} else {
content_holder.addClass("compact");
}
$.each(cams, function(i, v) {
reload_camera(v);
});
}
function create_sysblock(mini, cl_id) {
var sysblock = $("<div />")
.addClass(cl_id ? cl_id : "eva_hmi_sysblock")
.html(
'EVA ICS <span class="eva_version"></span>/' +
'<span class="eva_build"></span>/' +
'<span class="eva_framework_version"></span>/' +
'<span class="eva_framework_mode"></span>' +
' [<span class="eva_user"></span>]'
);
if (!mini) {
sysblock.append($("<br />"));
if (!$eva.in_evaHI) {
$("<span />")
.addClass("eva_hmi_links")
.css("margin-right", "10px")
.on("click", open_cc_setup)
.html("EvaCC setup")
.appendTo(sysblock);
}
$("<span />")
.addClass("eva_hmi_links")
.on("click", logout)
.html("Logout")
.appendTo(sysblock);
}
return sysblock;
}
function draw_compact_layout() {
if (
!window.eva_hmi_config_layout_compact ||
!("elements" in window.eva_hmi_config_layout_compact)
)
return draw_layout(true);
var cams = Array();
if (window.eva_hmi_config_class == "dashboard") {
var row = $("<div />", { class: "mob_layout" });
if (embedded) row.addClass("embedded");
var fcb = true;
$.each(window.eva_hmi_config_layout_compact["elements"], function(i, v) {
if (v["type"] == "control-block") {
var cb = create_control_block(v["id"]);
if (fcb) {
cb.css("border-top", "0px");
fcb = false;
}
row.append(cb);
} else {
fcb = true;
if (v["type"] == "data-block") {
var data_block = $("<div />", { class: "eva_hmi_data_block" });
data_block.append(create_data_block(v["id"]));
row.append(data_block);
} else if (v["type"] == "sys-block") {
row.append(create_sysblock());
} else if (v["type"] == "spacer") {
var h = v["hei