well-api/well_web_files/deployment.html
2025-08-14 21:54:37 -07:00

4834 lines
155 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>Deployment View</title>
<!--
Written By: Robert Zmrzli robert@zmrinc.com
deployment.html
V3.01
-->
<style>
div.helper {
position: fixed;
bottom: 0;
left: 0px;
}
.temperature {color: red;} /* Green */
.humidity {color: blue;} /* Blue */
.pressure {color: balck;} /* Orange */
.co2 {color: yellow;} /* Red */
.voc {color: orange;} /* Gray */
.light {color: #e7e7e7;} /* Gray */
.radar {color: cyan;} /* Gray */
.small-button {
border: none;
color: white;
padding: 1px 1px;
text-align: center;
display: inline-block;
font-size: 12px;
margin: 1px 1px;
cursor: pointer;
background-color: #00A000;
height:24px;
width:100px;
border-radius: 5px;
box-shadow: 0 2px #999;
}
.small-button:hover {background-color: #808080; font-color: #0000ff}
.small-button:active {
background-color: #00ff00;
box-shadow: 0 4px #666;
transform: translateY(2px);
}
</style>
<style>
#wrapper {
border: 0px solid blue;
}
#checkmarks {
display: inline-block;
width:740px;
height:24px;
border: 0px solid red;
}
#div2 {
display: inline-block;
width:1400px;
height:24px;
border: 0px solid green;
}
.button {
border: none;
color: white;
padding: 5px 5px;
text-align: center;
display: inline-block;
font-size: 12px;
margin: 1px 1px;
: pointer;
background-color: #008CBA;
height:24px;
width:90px;
border-radius: 5px;
box-shadow: 0 2px #999;
}
.button-small {
border: none;
color: white;
padding: 5px 5px;
text-align: center;
display: inline-block;
font-size: 10px;
margin: 0px 0px;
: pointer;
background-color: #008CBA;
height:18x;
width:90px;
border-radius: 5px;
box-shadow: 0 1px #999;
}
.button-mini {
border: none;
color: white;
padding: 5px 5px;
text-align: center;
display: inline-block;
font-size: 10px;
margin: 0px 0px;
: pointer;
background-color: #008CBA;
height:18x;
width:30px;
border-radius: 5px;
box-shadow: 0 1px #999;
}
.button:hover {background-color: #808CBA}
.button:active {
background-color: #3e8e41;
box-shadow: 0 4px #666;
transform: translateY(4px);
@keyframes spin {
to { transform: rotate(360deg); }
}
</style>
<meta charset="UTF-8"/>
<!--[if lt IE 9]>
<script src="../../src/excanvas/excanvas_text.js"></script>
<script src="../../src/excanvas/canvas.text.js"></script>
<![endif]-->
<link rel="stylesheet" type="text/css" href="https://eluxnetworks.net/js/src/demo.css">
<script src="https://eluxnetworks.net/js/src/teechart.js" type="text/javascript"></script>
<script src="https://eluxnetworks.net/js/src/teechart-extras.js" type="text/javascript"></script>
<script src="https://eluxnetworks.net/js/src/date.format.js" type="text/javascript"></script>
<script src="https://eluxnetworks.net/js/src/jquery-2.1.3.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.36/moment-timezone-with-data.min.js"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js"
type="text/javascript"
></script>
<script src="https://cdn.jsdelivr.net/pako/1.0.3/pako.min.js"></script>
<!-- Bootstrap -->
<link href="https://eluxnetworks.net/js/3rd_party/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome -->
<link href="https://eluxnetworks.net/js/3rd_party/font-awesome-4.6.3/css/font-awesome.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- Custom Theme Style -->
<link href="https://eluxnetworks.net/js/3rd_party/build/css/custom.min.css" rel="stylesheet">
<script type="text/javascript">
var fresh = true;
var scroller, UniversalChart, axis;
var series0 = "";
var scroller = "";
var t_series = [];
var h_series = [];
var c_series = [];
var v_series = [];
var p_series = [];
var l_series = [];
var r_series = [];
var sensors_series_collection = [];
var valid_macs = [];
var displaying_sensor="";
sensors_series_collection.push(t_series, h_series, c_series, v_series, p_series, l_series, r_series);
var series_0 = [];
var series_1 = [];
var series_2 = [];
var series_3 = [];
var series_4 = [];
var series_5 = [];
var series_6 = [];
var vocs_scaled = {};
var last_t_time = 0;
var last_h_time = 0;
var last_c_time = 0;
var last_v_time = 0;
var last_p_time = 0;
var last_l_time = 0;
var last_r_time = 0;
var clicked_sensor_description_fixed = "";
var epoch_start = 0;
var user_name = localStorage.getItem('user_name') || '';
var user_id = localStorage.getItem('user_id') || '0';
var key = localStorage.getItem('key');
var token = localStorage.getItem('token');
var baseURL = window.location.origin;
var api_url = `${baseURL}/function/well-api`;
var client = "";
var options = {}
var hasColonInLast6 = false;
var sensor_tables = ["temperature", "humidity", "pressure", "co2", "voc", "light", "radar"];
var sensor_tablesn = ["temperature", "humidity", "pressure", "light", "radar", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9"];
var presence_graphs = ["raw", "presence", "z-graph"];
//var possible_graphs = ["temperature", "humidity", "pressure", "light", "radar", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9"];
var radar_tablesn = ["m0_max", "m1_max", "m2_max", "m3_max", "m4_max", "m5_max", "m6_max", "m7_max", "m8_max", "m08_max", "s2_max", "s3_max",
"s4_max", "s5_max", "s6_max", "s7_max", "s8_max", "s28_max", "s28_min"];
var colors = ["red", "blue", "black", "green", "orange", "magenta", "cyan"];
var colorsDev = ["red", "blue", "cyan", "green", "orange", "black", "black", "black", "black", "black", "black", "black", "black", "black", "black", "black"];
var Loc2Color = {"Bedroom":[[16,255,16],0],"Bedroom Master":[[0,255,0],0],"Bedroom Guest":[[32,255,32],0],"Bathroom":[[0,0,255],1],
"Bathroom Main":[[16,16,255],1],"Bathroom Guest":[[32,32,255],1],"Kitchen":[[255,0,0],2],"Dining Room":[[255,128,0],3],"Dining":[[255,128,0],3],
"Office":[[255,255,0],4],"Conference Room":[[0,0,128],5],"Conference":[[0,0,128],5],"Room":[[64,64,64],6],"Living Room":[[160,32,240],7],"Living":[[160,32,240],7],"Hallway":[[128,128,128],8],
"Garage":[[128,0,0],9],"Basement":[[64,64,64], 10],"Attic":[[255,165,0], 11],"Other":[[192,192,192],12],"?":[[0,0,0],13],"Outside":[[0,0,0],14]};
var device_id_2_location = {};
var Canvas1 = "";
var ctx1 = "";
var cw="";
var ch=""
var offsetX,offsetY;
var all_slices = {};
var positions = [];
var locations_map = {};
var MACs_map = {};
//var MACs_map = {};
var series_indexes = {};
var shift_key_state = 0;
var alt_key_state = 0;
var ctrl_key_state = 0;
var hours_delta = 0;
polar1 = [];
polar2 = [];
messages = [];
mousedown = false;
var enableCursor = false;
var interval = "";
var time_min = 0;
var time_max = 2645858117;
var msecsInADay = 86400000;
var start_epoch = 0;
var start_time = Date.now();
var signature = "deployment.htm" + start_time.toString();
var unique_identifier = Math.random().toString(16).substr(2, 8) + signature;
// 1day 1week
var time_ranges = {"86401":"L","604800":"1Min"};
setInterval(ProcessQueue, 10);
img1 = new Image();
//img2 = new Image();
function sendToBackend(topicl, send_what) {
// Once a connection has been made, make a subscription and send a message.
console.log("sendToBackend "+topicl+":" + send_what);
if (topicl.substr(topicl.length - 4) == "_cmp") {
//var djson = new TextDecoder("utf-8").encode(send_what);
var compressedJSON = pako.deflate(send_what);
//var message.payloadBytes= compressedJSON;
message = new Paho.MQTT.Message(compressedJSON);
message.destinationName = topicl;
}
else {
message = new Paho.MQTT.Message(send_what);
message.destinationName = topicl;
}
try {
client.send(message);
}
catch(error){
console.error(error);
try {
console.log(options);
client.connect(options);
} catch (err) {
console.log("Connection attempt failed:", err);
}
client.send(message);
}
}
var baseURL = window.location.origin;
var api_url = `${baseURL}/function/well-api`;
function ConnectMQTT() {
// Configure host and port correctly for WSS
const hostname = "mqtt.eluxnetworks.net";
const port = 443; // Use standard HTTPS port for Traefik
const topic = "/wellget"; // You need to define the topic, it was missing
console.log(`Connecting to: ${hostname} on port ${port} using WebSocket`);
// Create a client instance with the working path
client = new Paho.MQTT.Client(
hostname,
port,
"/wss", // Updated to use the working WebSocket path
signature // Your client ID
);
// Set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
// Connection options - removing any invalid properties
const options = {
useSSL: true, // Always use SSL since we're connecting through Traefik on HTTPS
userName: user_name,
password: key,
onSuccess: onConnect,
onFailure: function(err) {
console.log("Connection failed: " + err.errorMessage);
// Explicit reconnect with exponential backoff
setTimeout(function() {
console.log("Attempting to reconnect...");
client.connect(options);
}, 2000); // Wait 2 seconds before reconnecting
},
keepAliveInterval: 30
};
// Called when the client connects
function onConnect() {
console.log("Successfully connected to MQTT broker");
// Subscribe to your topic
//client.subscribe("/well_cmp" + signature, {
//client.subscribe("#", {
// qos: 0
//});
// Send initial message
const message = new Paho.MQTT.Message("Hello");
message.destinationName = "/wellget";
client.send(message);
DeploymentChange();
}
// Called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:" + responseObject.errorMessage);
client.connect({
onSuccess: onConnect,
userName: user_name,
password: key,
useSSL: true // Always use SSL since we're connecting through Traefik
});
}
}
function onMessageArrived(message) {
try {
if (message.destinationName.charAt(0) !== "/") {
return;
}
if (message.destinationName.length == 13) {
if (!valid_macs.includes(message.destinationName)) {
return;
}
}
if (message.destinationName == "/test") {
return;
}
if (message.destinationName.length > 13) {
if (!message.destinationName.includes(unique_identifier)) {
return;
}
}
//here if message matches signature or mac
// Try to parse as JSON first
let payload;
if (typeof message.payloadBytes !== 'undefined') {
// Convert bytes to string properly
const decoder = new TextDecoder('utf-8');
payload = decoder.decode(new Uint8Array(message.payloadBytes));
} else {
payload = message.payloadString;
}
if (typeof payload === 'string' && payload.includes("'")) {
payload = payload.replace(/'/g, '"');
}
// Try to parse as JSON if it looks like JSON
if (payload.startsWith('{')) {
payload = JSON.parse(payload);
}
console.log("Message arrived:", payload);
if (payload !== "Hello") {
messages.push({
topic: message.destinationName,
payload: payload
});
}
} catch (error) {
console.warn("Error processing message:", error);
// Don't disconnect on message processing error
// Just log it and continue
}
}
// Attempt connection - only call connect ONCE
console.log("Attempting to connect to MQTT broker...");
try {
console.log(options);
client.connect(options);
} catch (err) {
console.log("Connection attempt failed:", err);
}
}
function handleMouseDown(e){
/* // tell the browser we're handling this event
if (shift_key_state == 1) {
e.preventDefault();
e.stopPropagation();
// get mouse position
var mx=parseInt(e.clientX-offsetX);
var my=parseInt(e.clientY-offsetY);
// test for possible start of dragging
//isDown=(mx>range.x && mx<range.x+range.width && my>range.y-range.height/2 && my<range.y+range.height/2);
document.querySelector('#copyc').checked = false;
//var canvas = document.getElementById("Canvas1");
stage_area_x = Canvas1.width;
stage_area_y = Canvas1.height;
kx = stage_area_x/stage_x_travel;
ky = stage_area_y/stage_y_travel;
new_x = mx/kx;
new_y = (stage_area_y - my)/ky;
new_x = parseInt(100*new_x)/100;
new_y = parseInt(100*new_y)/100;
new_z = parseFloat(document.getElementById('z_position').value);
document.getElementById('movex').value = new_x;
document.getElementById('movey').value = new_y;
MoveStage(new_x, new_y, new_z);
}
else if (ctrl_key_state == 1) {
mousedown = true;
clickedArea = findCurrentArea(e.offsetX, e.offsetY);
x1 = e.offsetX;
y1 = e.offsetY;
x2 = e.offsetX;
y2 = e.offsetY;
}*/
}
/*function handleMouseUpOut(e){
// tell the browser we're handling this event
if (ctrl_key_state == 0) {
e.preventDefault();
e.stopPropagation();
// stop dragging
}
else{
}
mousedown=false;
}
*/
window.addEventListener('mouseover', function() {
window.focus();
//console.log("In!")
});
// Prevent the window from losing focus when the mouse leaves
window.addEventListener('mouseout', function(e) {
e.preventDefault();
//console.log("Out!")
});
window.addEventListener('keyup', function(event) {
//event.stopPropagation();
let keyState = '';
let keyName = '';
switch (event.key) {
case 'Shift':
shift_key_state = 0;
event.preventDefault();
keyState = 'shift_key_state = 0';
keyName = 'Shift';
break;
case 'Alt':
alt_key_state = 0;
event.preventDefault();
keyState = 'alt_key_state = 0';
keyName = 'Alt';
break;
case 'Control':
ctrl_key_state = 0;
event.preventDefault();
keyState = 'ctrl_key_state = 0';
keyName = 'Ctrl';
break;
default:
return; // Exit the function for other keys
}
//console.log(keyState);
AddToTutorial(keyState);
//console.log(`${keyName} key released`);
});
window.addEventListener('keydown', function(event) {
//event.stopPropagation();
let keyState = '';
let keyName = '';
switch (event.key) {
case 'Shift':
shift_key_state = 1;
event.preventDefault();
keyState = 'shift_key_state = 1';
keyName = 'Shift';
break;
case 'Alt':
alt_key_state = 1;
event.preventDefault();
keyState = 'alt_key_state = 1';
keyName = 'Alt';
break;
case 'Control':
ctrl_key_state = 1;
event.preventDefault();
keyState = 'ctrl_key_state = 1';
keyName = 'Ctrl';
break;
default:
return; // Exit the function for other keys
}
//console.log(keyState);
AddToTutorial(keyState);
//console.log(`${keyName} key pressed`);
});
/*
document.onkeydown = function (event) {
modifier = "";
if (event.repeat != undefined) {
allowed = !event.repeat;
}
if (!allowed) return;
allowed = false;
switch (event.keyCode) {
case 16: //Shift
shift_key_state = 1;
console.log("shift_key_state = 1");
showTutorial("shift_key_state = 1");
break;
case 18: //Alt
alt_key_state = 1;
console.log("alt_key_state = 1");
showTutorial("alt_key_state = 1");
break;
case 17: //Ctrl
ctrl_key_state = 1;
console.log("ctrl_key_state = 1");
showTutorial("ctrl_key_state = 1")
break;
}
switch (event.keyCode) {
case 37: //Left
break;
case 38: //Up
break;
case 39: //Right
break;
case 40: //Down
break;
}
};
document.onkeyup = function (event) {
switch (event.keyCode) {
case 16: //Shift
shift_key_state = 0;
console.log("shift_key_state = 0");
AddToTutorial("shift_key_state = 0");
break;
case 18: //Alt
alt_key_state = 0;
console.log("alt_key_state = 0");
AddToTutorial("alt_key_state = 0");
break;
case 17: //Ctrl
ctrl_key_state = 0;
console.log("ctrl_key_state = 0");
AddToTutorial("ctrl_key_state = 0");
break;
}
};
*/
function handleMouseUp(e){
mousedown=false;
// get mouse position
if (shift_key_state == 0 && ctrl_key_state == 0 && alt_key_state == 0) return;
ddate = document.getElementById("ddate").value;
to_date = document.getElementById("to_date").value;
reOffset();
var mx=parseInt(e.clientX) - offsetX;
var my=parseInt(e.clientY) - offsetY;
//lets round mx to multiple of 5 (minutes)
mx = Math.round(mx / 5) * 5;
if(document.getElementById("zmap_type").value != "none"){
document.getElementById("zmap_type").value = "none";
if (positions[0][0] < 200){
devices_count = parseInt(Canvas1.height/70);
}
else{
devices_count = parseInt(Canvas1.height/150);
}
PrepareChart(devices_count);
}
map_type = document.getElementById("map_type").value;
if(map_type == 1){ //All sensors
if (positions[0][0] < 200){
devices_count = parseInt(Canvas1.height/70);
if (document.getElementById("GroupBy").value == "sensortype") {
sensor_index = parseInt(my/(devices_count*10));
sensor_type = sensor_tables[sensor_index];
position = 1+parseInt(my/10) % devices_count;
}
else {
position = 1+parseInt(my/(7*10));
sensor_index = parseInt(my/(10) % 7);
sensor_type = sensor_tables[sensor_index];
}
}
else{
devices_count = parseInt(Canvas1.height/150);
if (document.getElementById("GroupBy").value == "sensortype") {
sensor_index = parseInt(my/(devices_count*10));
sensor_type = sensor_tablesn[sensor_index];
position = 1+parseInt(my/10) % devices_count;
}
else {
position = 1+parseInt(my/(15*10));
sensor_index = parseInt(my/(10) % 15);
sensor_type = sensor_tablesn[sensor_index];
}
}
device_id = positions[position-1][0];
location_desc = locations_map[device_id];
time = mx/60;
hours = String(parseInt(time)).padStart(2, '0');
minutes = String(parseInt((time*60) % 60)).padStart(2, '0');
seconds = "00";
//console.log(hours+":"+minutes+":"+seconds + " "+sensor_type+ " @ "+location_desc);
//document.getElementById('describe').innerHTML = hours+":"+minutes+":"+seconds + " "+sensor_type+ " @ "+location_desc;
//clicked_sensor_description = hours+":"+minutes+":"+seconds + " "+sensor_type+ " @ "+location_desc;
clicked_sensor_description_fixed = device_id + " "+MAC + " "+sensor_type+ " @ "+location_desc;
UniversalChart.title.text = clicked_sensor_description_fixed + " "+ hours+":"+minutes+":"+seconds;
//UniversalChart.draw();
if (shift_key_state == 1) {
showTutorial("Getting group graphs data...")
console.log(mx, sensor_type, position);
epoch_clicked = new Date(ddate).getTime();
epoch_clicked = epoch_clicked+60000*mx;
var d = new Date(epoch_clicked);
const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
var date = moment(); // Current date and time
var offset = moment.tz(date, userTimeZone).utcOffset();
var epoch_clicked = d.getTime() - ((offset) * 60000);
//var nd = new Date(utc + (3600000*offset));
//return nd.toLocaleString();
epoch_from = epoch_clicked/1000 - 1800
epoch_to = epoch_clicked/1000 + 1800
RequestMapSlice(positions, epoch_from, epoch_to);
}
if (alt_key_state == 1) {
showTutorial("Getting group graphs data...")
console.log(mx, sensor_type, position);
epoch_clicked = new Date(ddate).getTime();
epoch_clicked = epoch_clicked+60000*mx;
var d = new Date(epoch_clicked);
const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
var date = moment(); // Current date and time
var offset = moment.tz(date, userTimeZone).utcOffset();
var epoch_clicked = d.getTime() - ((offset) * 60000);
//var nd = new Date(utc + (3600000*offset));
//return nd.toLocaleString();
time_range = document.getElementById("time_range").value;
switch(time_range) {
case 'D10M':
semi_range_seconds = 600;
break;
case 'D30M':
semi_range_seconds = 1800;
break;
case 'D1H':
semi_range_seconds = 3600;
break;
case 'D2H':
semi_range_seconds = 7200;
break;
case 'D4H':
sesemi_range_seconds = 14400;
break;
}
epoch_from = epoch_clicked/1000 - semi_range_seconds
epoch_to = epoch_clicked/1000 + semi_range_seconds
one_sensor_list = [];
epoch_clicked = new Date(ddate).getTime();
//Lets un-select all checkmarks on top
for (var d = 0; d <devices_count; d++) { //device index
device_check = "device_check"+(d).toString();
document.getElementById(device_check).checked = false;
}
if (device_id < 200){
}
else{
for (var si = 0; si < 15; si++) { //sensor index
switch(si) {
case 0:
sensor_check = "t-check";
break;
case 1:
sensor_check = "h-check";
break;
case 2:
sensor_check = "p-check";
break;
case 3:
sensor_check = "l-check";
break;
case 4:
sensor_check = "r-check";
break;
case 5:
sensor_check = "v0-check";
break;
case 6:
sensor_check = "v1-check";
break;
case 7:
sensor_check = "v2-check";
break;
case 8:
sensor_check = "v3-check";
break;
case 9:
sensor_check = "v4-check";
break;
case 10:
sensor_check = "v5-check";
break;
case 11:
sensor_check = "v6-check";
break;
case 12:
sensor_check = "v7-check";
break;
case 13:
sensor_check = "v8-check";
break;
case 14:
sensor_check = "v9-check";
break;
}
document.getElementById(sensor_check).checked = false;
}
}
if (device_id < 200){
}
else{
sensor_check = "t-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "h-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "l-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "r-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "v0-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "v1-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "v2-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "v3-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "v4-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "v5-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "v6-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "v7-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "v8-check";
document.getElementById(sensor_check).checked = true;
sensor_check = "v9-check";
document.getElementById(sensor_check).checked = true;
sensors_list = ["temperature","humidity","light","radar","s0","s1","s2","s3","s4","s5","s6","s7","s8","s9"];
}
device_check = "device_check"+(position-1).toString();
document.getElementById(device_check).checked = true;
UpdateSelections();
//RequestData(MAC,sensor_type, false); //not all sensors
single_position = positions[position-1]
RequestAPIDeviceSlice(single_position, sensors_list, epoch_from, epoch_to);
}
else if (ctrl_key_state == 1) {
one_sensor_list = [];
showTutorial("Getting single graph data...")
console.log(mx, sensor_type, position);
epoch_clicked = new Date(ddate).getTime();
//var d = new Date(epoch_clicked);
//var start_of_day = d.getTime() + ((d.getTimezoneOffset()) * 60000);
//var start_of_day = d.getTime(); //in UTC
//MAC = MACs_map[device_id];
//Lets un-select all checkmarks on top
for (var d = 0; d <devices_count; d++) { //device index
device_check = "device_check"+(d).toString();
document.getElementById(device_check).checked = false;
}
if (device_id < 200){
for (var si = 0; si < 7; si++) { //sensor index
switch(si) {
case 0:
sensor_check = "t-check";
break;
case 1:
sensor_check = "h-check";
break;
case 2:
sensor_check = "p-check";
break;
case 3:
sensor_check = "c-check";
break;
case 4:
sensor_check = "v-check";
break;
case 5:
sensor_check = "l-check";
break;
case 6:
sensor_check = "r-check";
break;
}
document.getElementById(sensor_check).checked = false;
}
}
else{
for (var si = 0; si < 15; si++) { //sensor index
switch(si) {
case 0:
sensor_check = "t-check";
break;
case 1:
sensor_check = "h-check";
break;
case 2:
sensor_check = "p-check";
break;
case 3:
sensor_check = "l-check";
break;
case 4:
sensor_check = "r-check";
break;
case 5:
sensor_check = "v0-check";
break;
case 6:
sensor_check = "v1-check";
break;
case 7:
sensor_check = "v2-check";
break;
case 8:
sensor_check = "v3-check";
break;
case 9:
sensor_check = "v4-check";
break;
case 10:
sensor_check = "v5-check";
break;
case 11:
sensor_check = "v6-check";
break;
case 12:
sensor_check = "v7-check";
break;
case 13:
sensor_check = "v8-check";
break;
case 14:
sensor_check = "v9-check";
break;
}
document.getElementById(sensor_check).checked = false;
}
}
if (device_id < 200){
switch(sensor_index) {
case 0:
sensor_check = "t-check";
one_sensor_list = ["temperature"];
break;
case 1:
sensor_check = "h-check";
one_sensor_list = ["humidity"];
break;
case 2:
sensor_check = "p-check";
one_sensor_list = ["pressure"];
break;
case 3:
sensor_check = "c-check";
one_sensor_list = ["co2"];
break;
case 4:
sensor_check = "v-check";
one_sensor_list = ["voc"];
break;
case 5:
sensor_check = "l-check";
one_sensor_list = ["light"];
break;
case 6:
sensor_check = "r-check";
one_sensor_list = ["radar"];
break;
}
}
else{
switch(sensor_index) {
case 0:
sensor_check = "t-check";
one_sensor_list = ["temperature"];
break;
case 1:
sensor_check = "h-check";
one_sensor_list = ["humidity"];
break;
case 2:
sensor_check = "p-check";
one_sensor_list = ["pressure"];
break;
case 3:
sensor_check = "l-check";
one_sensor_list = ["light"];
break;
case 4:
sensor_check = "r-check";
one_sensor_list = ["radar"];
break;
case 5:
sensor_check = "v0-check";
one_sensor_list = ["s0"];
break;
case 6:
sensor_check = "v1-check";
one_sensor_list = ["s1"];
break;
case 7:
sensor_check = "v2-check";
one_sensor_list = ["s2"];
break;
case 8:
sensor_check = "v3-check";
one_sensor_list = ["s3"];
break;
case 9:
sensor_check = "v4-check";
one_sensor_list = ["s4"];
break;
case 10:
sensor_check = "v5-check";
one_sensor_list = ["s5"];
break;
case 11:
sensor_check = "v6-check";
one_sensor_list = ["s6"];
break;
case 12:
sensor_check = "v7-check";
one_sensor_list = ["s7"];
break;
case 13:
sensor_check = "v8-check";
one_sensor_list = ["s8"];
break;
case 14:
sensor_check = "v9-check";
one_sensor_list = ["s9"];
break;
}
}
document.getElementById(sensor_check).checked = true;
device_check = "device_check"+(position-1).toString();
document.getElementById(device_check).checked = true;
UpdateSelections();
//RequestData(MAC,sensor_type, false); //not all sensors
single_position = [positions[position-1]]
RequestSingleSlice(single_position, one_sensor_list, ddate, to_date, ctrl_key_state, alt_key_state);
}
}
else if (map_type == 2) { //Radar only
if (positions[0][0] < 200){
devices_count = parseInt(Canvas1.height/5*19);
position = 1+parseInt(my/(5*19));
sensor_index = parseInt(my/(5) % 19);
sensor_type = sensor_tables[sensor_index];
}
else{
devices_count = parseInt(Canvas1.height/(5*19));
position = 1+parseInt(my/(5*19));
sensor_index = parseInt(my/(5) % 19);
sensor_type = radar_tablesn[sensor_index];
}
device_id = positions[position-1][0];
location_desc = locations_map[device_id];
time = mx/60;
hours = String(parseInt(time)).padStart(2, '0');
minutes = String(parseInt((time*60) % 60)).padStart(2, '0');
seconds = "00";
//console.log(hours+":"+minutes+":"+seconds + " "+sensor_type+ " @ "+location_desc);
//document.getElementById('describe').innerHTML = hours+":"+minutes+":"+seconds + " "+sensor_type+ " @ "+location_desc;
//clicked_sensor_description = hours+":"+minutes+":"+seconds + " "+sensor_type+ " @ "+location_desc;
clicked_sensor_description_fixed = device_id + " "+MAC + " "+sensor_type+ " @ "+location_desc;
UniversalChart.title.text = clicked_sensor_description_fixed + " "+ hours+":"+minutes+":"+seconds;
//UniversalChart.draw();
if (shift_key_state == 1) {
showTutorial("Getting group graphs data...")
console.log(mx, sensor_type, position);
epoch_clicked = new Date(ddate).getTime();
epoch_clicked = epoch_clicked+60000*mx;
var d = new Date(epoch_clicked);
const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
var date = moment(); // Current date and time
var offset = moment.tz(date, userTimeZone).utcOffset();
var epoch_clicked = d.getTime() - ((offset) * 60000);
//var nd = new Date(utc + (3600000*offset));
//return nd.toLocaleString();
epoch_from = epoch_clicked/1000 - 1800
epoch_to = epoch_clicked/1000 + 1800
RequestMapSlice(positions, epoch_from, epoch_to);
}
else if (ctrl_key_state == 1) {
sensor_index_list = [sensor_index];
showTutorial("Getting single graph data...")
console.log(mx, sensor_type, position);
epoch_clicked = new Date(ddate).getTime();
//var d = new Date(epoch_clicked);
//var start_of_day = d.getTime() + ((d.getTimezoneOffset()) * 60000);
//var start_of_day = d.getTime(); //in UTC
//RequestData(MAC,sensor_type, false); //not all sensors
single_position = [positions[position-1]]
RequestSingleRadarSlice(single_position, sensor_index_list, ddate, ctrl_key_state, alt_key_state, sensor_type);
}
}
}
function reOffset(){
var BB = Canvas1.getBoundingClientRect();
offsetX = BB.left;
offsetY = BB.top;
}
img1.onload = function() {
ctx1.drawImage(img1, 0, 0);
}
//img2.onload = function() {
// ctx2.drawImage(img2, 0, 0);
//}
function DisplayAllSlices(MAC, well_id) {
EmptyAllSeries();
let series_index = 0;
// Get the first (and only) key from all_slices
const sensorId = Object.keys(all_slices)[0]; // This will get "273" or whatever the ID is
const sensorData = all_slices[sensorId];
// Now iterate through all metrics (temperature, humidity, etc.)
Object.entries(sensorData).forEach(([metricType, timeseriesData]) => {
console.log(`Processing metric ${metricType}`);
// Get the appropriate series index
series_index = series_indexes[MAC + metricType];
if (series_index === undefined) {
console.warn(`No series index found for ${sensorId}${metricType}`);
return; // Skip this iteration
}
let series = UniversalChart.series.items[series_index];
if (!series) {
console.warn(`No series found at index ${series_index}`);
return; // Skip this iteration
}
// Initialize arrays
series.data.x = [];
series.data.values = [];
let cnt = 0;
// Process each timestamp-value pair
timeseriesData.forEach(([timestamp, value]) => {
if (value != null) {
const epoch_ms = timestamp * 1000; // Convert to milliseconds
const time_obj = new Date(epoch_ms);
series.data.x[cnt] = time_obj;
series.data.values[cnt] = value;
cnt++;
}
});
//series.visible = false;
//UniversalChart.legend.visible = false;
//series.showInLegend = false;
UniversalChart.draw();
});
// Update chart settings
UniversalChart.axes.bottom.labels.roundFirst = true;
UniversalChart.axes.bottom.labels.dateFormat = "shortDateTime";
// Update UI
//UpdateSelections();
// series_count = UniversalChart.series.items.length;
// for (var d = 0; d <series_count; d++) { //series index
// var s = UniversalChart.series.items[d];
// if (s.title.includes(well_id)){
// s.visible = true;
// s.showInLegend = true;
// }
// }
UniversalChart.draw();
//UpdateSelections();
showTutorial("Data shown!");
}
function DisplayAllSensors() {
HideAndEmptyAllSeries();
let series_index = 0;
// First, read and parse the data
fetch('paste.txt')
.then(response => response.text())
.then(content => {
const data = JSON.parse(content);
// Now iterate through all sensor IDs (like "273")
Object.entries(data).forEach(([sensorId, sensorData]) => {
// For each sensor, iterate through all metrics (temperature, humidity, etc.)
Object.entries(sensorData).forEach(([metricType, timeseriesData]) => {
console.log(`Processing sensor ${sensorId}, metric ${metricType}`);
// Get the appropriate series index
series_index = series_indexes[sensorId + metricType];
if (series_index === undefined) {
console.warn(`No series index found for ${sensorId}${metricType}`);
return; // Skip this iteration
}
let series = UniversalChart.series.items[series_index];
if (!series) {
console.warn(`No series found at index ${series_index}`);
return; // Skip this iteration
}
// Initialize arrays
series.data.x = [];
series.data.values = [];
let cnt = 0;
// Process each timestamp-value pair
timeseriesData.forEach(([timestamp, value]) => {
if (value != null) {
const epoch_ms = timestamp * 1000; // Convert to milliseconds
const time_obj = new Date(epoch_ms);
series.data.x[cnt] = time_obj;
series.data.values[cnt] = value;
cnt++;
}
});
});
});
// Update chart settings
UniversalChart.axes.bottom.labels.roundFirst = true;
UniversalChart.axes.bottom.labels.dateFormat = "shortDateTime";
// Update UI
UpdateSelections();
showTutorial("Data shown!");
})
.catch(error => {
console.error('Error loading or processing data:', error);
showTutorial("Error loading data!");
});
}
function getTimeZoneOffset(timeZone) {
// Get current date
const date = new Date();
// Get the time in the specified timezone
const timeString = date.toLocaleString('en-US', { timeZone: timeZone });
const tzDate = new Date(timeString);
// Calculate offset in hours
const offset = Math.round((tzDate - date) / (1000 * 60 * 60));
return offset;
}
function getTimezoneDiffHours(targetTimezone) {
const localDate = new Date();
const targetDate = new Date(localDate.toLocaleString(undefined, { timeZone: targetTimezone }));
return Math.round((targetDate - localDate) / (1000 * 60 * 60));
}
function DisplaySingleSlice(time_zone_st) {
try {
// First verify chart is ready
if (!UniversalChart || !UniversalChart.series || !UniversalChart.series.items) {
console.error("Chart not properly initialized");
return;
}
HideAndEmptyAllSeries();
series_index = 0;
// Track if we actually added any data
let dataAdded = false;
hours_delta = getTimezoneDiffHours(time_zone_st);
Object.entries(all_slices).forEach(([key1, value1]) => {
Object.entries(value1).forEach(([key2, value2]) => {
if (key1.startsWith("d_")) {
series_index = series_indexes["derivative"];
} else {
series_index = series_indexes[key1+key2];
}
// Verify series exists
if (series_index === undefined || !UniversalChart.series.items[series_index]) {
console.error("Invalid series index:", series_index);
return;
}
map_type = document.getElementById("map_type").value;
series = UniversalChart.series.items[series_index];
// Clear existing data
series.data.values = [];
series.data.x = [];
series.visible = key1.startsWith("d_") ?
document.getElementById("der-check").checked : true;
l = value2.length;
if (l === 0) return; // Skip empty data sets
// Process data points
for (var t = 0; t < l; t++) {
timee = value2[t][0];
if (timee == null) continue;
// Get value based on series type
if (key1.startsWith("d_")) {
if(key2 == "radar") {
vall = value2[t][2] - value2[t][3];
} else {
vall = value2[t][4] > value2[t][1] ?
value2[t][2]-value2[t][3] :
value2[t][3]-value2[t][2];
}
}
else {
vall = value2[t][1];
if (map_type == 1) {
if(key2 == "radar") {
vall = vall % 128;
}
else if (key2.startsWith("s")){ //All sensors) {
vall = 102400000 - vall;
}
}
}
if (vall != null) {
//here we need to apply time difference between where user is and what is time zone of deployment
epoch_ms = (timee+hours_delta * 3600) * 1000;
series.data.x.push(new Date(epoch_ms));
series.data.values.push(vall);
dataAdded = true;
}
}
console.log(timee);
console.log(epoch_ms);
if (!key1.startsWith("d_")) {
series_index = series_index + 1;
}
});
});
// Only proceed if we actually have data
if (!dataAdded) {
console.warn("No data was added to the chart");
return;
}
// Configure axes
try {
UniversalChart.axes.bottom.labels.roundFirst = true;
UniversalChart.axes.bottom.labels.dateFormat = "shortDateTime";
//UniversalChart.axes.bottom.labels.format = {
// hour12: false
//};
// Remove last point. It was added to illustrate whole day, but should not be displayed!
if (series.data.x.length > 0) {
series.data.x.pop();
series.data.values.pop();
}
createCustomLegend();
UniversalChart.draw();
showTutorial("Data shown!");
} catch (e) {
console.error("Error during chart configuration/drawing:", e);
}
} catch (e) {
console.error("Error in DisplaySingleSlice:", e);
}
}
function ProcessQueue_Old() {
var message=""
if(messages.length){
message = messages.shift();
switch(message["payload"]["mtype"]) {
case "radar":
if (displaying_sensor == "radar"){
MAC = message["topic"].substring(1);
series_index = series_indexes[MAC+displaying_sensor];
series = UniversalChart.series.items[series_index];
radar_part = document.getElementById("RadarPart").value;
timee = message["payload"]["time"];
switch(radar_part) {
case "absent":
vall = message["payload"]["radar"][0][1]/message["payload"]["radar"][0][0];
break;
case "moving":
vall = message["payload"]["radar"][0][2]/message["payload"]["radar"][0][0];
break;
case "stationary":
vall = message["payload"]["radar"][0][3]/message["payload"]["radar"][0][0];
break;
case "both":
vall = message["payload"]["radar"][0][4]/message["payload"]["radar"][0][0];
break;
case "m0":
vall = message["payload"]["radar"][0][5]/message["payload"]["radar"][0][0];
break;
case "m1":
vall = message["payload"]["radar"][0][6]/message["payload"]["radar"][0][0];
break;
case "m2":
vall = message["payload"]["radar"][0][7]/message["payload"]["radar"][0][0];
break;
case "m3":
vall = message["payload"]["radar"][0][8]/message["payload"]["radar"][0][0];
break;
case "m4":
vall = message["payload"]["radar"][0][9]/message["payload"]["radar"][0][0];
break;
case "m5":
vall = message["payload"]["radar"][0][10]/message["payload"]["radar"][0][0];
break;
case "m6":
vall = message["payload"]["radar"][0][11]/message["payload"]["radar"][0][0];
break;
case "m7":
vall = message["payload"]["radar"][0][12]/message["payload"]["radar"][0][0];
break;
case "m8":
vall = message["payload"]["radar"][0][13]/message["payload"]["radar"][0][0];
break;
case "s2":
vall = message["payload"]["radar"][1][3]/message["payload"]["radar"][1][0];
break;
case "s3":
vall = message["payload"]["radar"][1][4]/message["payload"]["radar"][1][0];
break;
case "s4":
vall = message["payload"]["radar"][1][5]/message["payload"]["radar"][1][0];
break;
case "s5":
vall = message["payload"]["radar"][1][6]/message["payload"]["radar"][1][0];
break;
case "s6":
vall = message["payload"]["radar"][1][7]/message["payload"]["radar"][1][0];
break;
case "s7":
vall = message["payload"]["radar"][1][8]/message["payload"]["radar"][1][0];
break;
case "s8":
vall = message["payload"]["radar"][1][9]/message["payload"]["radar"][1][0];
break;
case "s28":
vall = 0;
for (i=3; i<=9; i++){
vall += message["payload"]["radar"][1][i]
}
vall = vall/(7.0*message["payload"]["radar"][1][0]);
break;
}
epoch_ms = (timee+hours_delta * 3600) * 1000;
series.data.x.push(new Date(epoch_ms));
series.data.values.push(vall);
series.data.values.push(vall);
time_obj = new Date(epoch_ms);
series.data.x.push(time_obj);
UniversalChart.axes.bottom.labels.roundFirst = true;
UniversalChart.axes.bottom.labels.dateFormat = "shortDateTime";
UniversalChart.draw();
}
break;
case "sensors":
//message["payload"]["topic"]
map_type = document.getElementById("map_type").value;
if(map_type == 1){ //All sensors
if (displaying_sensor[0] === "s"){
smell_index = displaying_sensor[1];
displaying_sensor_t = "smell";
}
else {
displaying_sensor_t = displaying_sensor;
}
if (displaying_sensor_t in message["payload"]) {
MAC = message["topic"].substring(1);
if (displaying_sensor[0] === "s"){
series_index = series_indexes[MAC+"s"+smell_index];
}
else {
series_index = series_indexes[MAC+displaying_sensor];
}
series = UniversalChart.series.items[series_index];
//cnt = series.data.values.length;
//last_x = series.data.x[cnt-1]
//series.data.x.pop(); // Remove last x coordinate
//series.data.values.pop();
//series.data.x.pop(); // Remove last x coordinate
//series.data.values.pop();
timee = message["payload"]["time"];
vall = message["payload"][displaying_sensor_t];
if (displaying_sensor.startsWith("s")) {
vall = 102400000 - vall[smell_index];
}
epoch_ms = (timee+hours_delta * 3600) * 1000;
if (displaying_sensor == "temperature"){
vall = vall-16;
}
if (displaying_sensor.startsWith("s")) {
if (vall > 0 && vall < 102400000 ){
series.data.values.push(vall);
time_obj = new Date(epoch_ms);
series.data.x.push(time_obj);
}
}
else {
series.data.values.push(vall);
time_obj = new Date(epoch_ms);
series.data.x.push(time_obj);
}
//series.data.values.push(vall);
//series.data.x.push(last_x);
//cnt = cnt + 1;
UniversalChart.axes.bottom.labels.roundFirst = true;
UniversalChart.axes.bottom.labels.dateFormat = "shortDateTime";
UniversalChart.draw();
}
}
break;
case "pressure":
break;
case "temperature":
break;
case "humidity":
break;
case "light":
break;
}
}
}
function ProcessQueue() {
var message=""
if(messages.length){
message = messages.shift();
if (CountVisible().length > 10) {
return;
}
MAC = message["topic"].substring(1);
vall = -1000000;
switch(message["payload"]["mtype"]) {
case "radar":
case 16:
//lets charts dictate which sensors are to be displayed
MAC = message["topic"].substring(1);
if(document.getElementById("map_type").value == 1){
i = 4; //4=radar
if (MAC+sensor_tablesn[i] in series_indexes){
series_index = series_indexes[MAC+sensor_tablesn[i]];
series = UniversalChart.series.items[series_index];
if (series.visible == true) {
radar_part = document.getElementById("RadarPart").value;
timee = message["payload"]["time"];
switch(radar_part) {
case "absent":
vall = message["payload"]["radar"][0][1]/message["payload"]["radar"][0][0];
break;
case "moving":
vall = message["payload"]["radar"][0][2]/message["payload"]["radar"][0][0];
break;
case "stationary":
vall = message["payload"]["radar"][0][3]/message["payload"]["radar"][0][0];
break;
case "both":
vall = message["payload"]["radar"][0][4]/message["payload"]["radar"][0][0];
break;
case "m0":
vall = message["payload"]["radar"][0][5]/message["payload"]["radar"][0][0];
break;
case "m1":
vall = message["payload"]["radar"][0][6]/message["payload"]["radar"][0][0];
break;
case "m2":
vall = message["payload"]["radar"][0][7]/message["payload"]["radar"][0][0];
break;
case "m3":
vall = message["payload"]["radar"][0][8]/message["payload"]["radar"][0][0];
break;
case "m4":
vall = message["payload"]["radar"][0][9]/message["payload"]["radar"][0][0];
break;
case "m5":
vall = message["payload"]["radar"][0][10]/message["payload"]["radar"][0][0];
break;
case "m6":
vall = message["payload"]["radar"][0][11]/message["payload"]["radar"][0][0];
break;
case "m7":
vall = message["payload"]["radar"][0][12]/message["payload"]["radar"][0][0];
break;
case "m8":
vall = message["payload"]["radar"][0][13]/message["payload"]["radar"][0][0];
break;
case "s2":
vall = message["payload"]["radar"][1][3]/message["payload"]["radar"][1][0];
break;
case "s3":
vall = message["payload"]["radar"][1][4]/message["payload"]["radar"][1][0];
break;
case "s4":
vall = message["payload"]["radar"][1][5]/message["payload"]["radar"][1][0];
break;
case "s5":
vall = message["payload"]["radar"][1][6]/message["payload"]["radar"][1][0];
break;
case "s6":
vall = message["payload"]["radar"][1][7]/message["payload"]["radar"][1][0];
break;
case "s7":
vall = message["payload"]["radar"][1][8]/message["payload"]["radar"][1][0];
break;
case "s8":
vall = message["payload"]["radar"][1][9]/message["payload"]["radar"][1][0];
break;
case "s28":
vall = 0;
for (i_=3; i_<=9; i_++){
vall += message["payload"]["radar"][1][i_]
}
vall = vall/(7.0*message["payload"]["radar"][1][0]);
break;
}
}
if (vall != -1000000) {
epoch_ms = (timee+hours_delta * 3600) * 1000;
series.data.x.push(new Date(epoch_ms));
series.data.values.push(vall);
//series.data.values.push(vall);
//time_obj = new Date(epoch_ms);
//series.data.x.push(time_obj);
UniversalChart.axes.bottom.labels.roundFirst = true;
UniversalChart.axes.bottom.labels.dateFormat = "shortDateTime";
UniversalChart.draw();
}
}
}
else{
for(i = 0; i<=18; i++){
if (MAC+radar_tablesn[i] in series_indexes){
series_index = series_indexes[MAC+radar_tablesn[i]];
series = UniversalChart.series.items[series_index];
if (series.visible == true) {
radar_part = document.getElementById("RadarPart").value;
timee = message["payload"]["time"];
switch(radar_part) {
case "absent":
vall = message["payload"]["radar"][0][1]/message["payload"]["radar"][0][0];
break;
case "moving":
vall = message["payload"]["radar"][0][2]/message["payload"]["radar"][0][0];
break;
case "stationary":
vall = message["payload"]["radar"][0][3]/message["payload"]["radar"][0][0];
break;
case "both":
vall = message["payload"]["radar"][0][4]/message["payload"]["radar"][0][0];
break;
case "m0":
vall = message["payload"]["radar"][0][5]/message["payload"]["radar"][0][0];
break;
case "m1":
vall = message["payload"]["radar"][0][6]/message["payload"]["radar"][0][0];
break;
case "m2":
vall = message["payload"]["radar"][0][7]/message["payload"]["radar"][0][0];
break;
case "m3":
vall = message["payload"]["radar"][0][8]/message["payload"]["radar"][0][0];
break;
case "m4":
vall = message["payload"]["radar"][0][9]/message["payload"]["radar"][0][0];
break;
case "m5":
vall = message["payload"]["radar"][0][10]/message["payload"]["radar"][0][0];
break;
case "m6":
vall = message["payload"]["radar"][0][11]/message["payload"]["radar"][0][0];
break;
case "m7":
vall = message["payload"]["radar"][0][12]/message["payload"]["radar"][0][0];
break;
case "m8":
vall = message["payload"]["radar"][0][13]/message["payload"]["radar"][0][0];
break;
case "s2":
vall = message["payload"]["radar"][1][3]/message["payload"]["radar"][1][0];
break;
case "s3":
vall = message["payload"]["radar"][1][4]/message["payload"]["radar"][1][0];
break;
case "s4":
vall = message["payload"]["radar"][1][5]/message["payload"]["radar"][1][0];
break;
case "s5":
vall = message["payload"]["radar"][1][6]/message["payload"]["radar"][1][0];
break;
case "s6":
vall = message["payload"]["radar"][1][7]/message["payload"]["radar"][1][0];
break;
case "s7":
vall = message["payload"]["radar"][1][8]/message["payload"]["radar"][1][0];
break;
case "s8":
vall = message["payload"]["radar"][1][9]/message["payload"]["radar"][1][0];
break;
case "s28":
vall = 0;
for (i_=3; i_<=9; i_++){
vall += message["payload"]["radar"][1][i_]
}
vall = vall/(7.0*message["payload"]["radar"][1][0]);
break;
}
}
if (vall != -1000000) {
epoch_ms = (timee+hours_delta * 3600) * 1000;
series.data.x.push(new Date(epoch_ms));
series.data.values.push(vall);
//series.data.values.push(vall);
//time_obj = new Date(epoch_ms);
//series.data.x.push(time_obj);
UniversalChart.axes.bottom.labels.roundFirst = true;
UniversalChart.axes.bottom.labels.dateFormat = "shortDateTime";
UniversalChart.draw();
}
}
}
}
break;
case "sensors":
case 17:
//case "light":
//message["payload"]["topic"]
map_type = document.getElementById("map_type").value;
if(map_type == 1){ //All sensors
MAC = message["topic"].substring(1);
for (let i = 0; i < sensor_tablesn.length; i++) {
if (MAC+sensor_tablesn[i] in series_indexes){
displaying_sensor_t = sensor_tablesn[i];
series_index = series_indexes[MAC+displaying_sensor_t];
series = UniversalChart.series.items[series_index];
if (series.visible == true) {
timee = message["payload"]["time"];
if (displaying_sensor[0] === "s"){
smell_index = displaying_sensor[1];
displaying_sensor_t = "smell";
vall = message["payload"][displaying_sensor_t];
vall = 102400000 - vall[smell_index];
}
else {
displaying_sensor_t = displaying_sensor;
vall = message["payload"][displaying_sensor_t];
}
epoch_ms = (timee+hours_delta * 3600) * 1000;
if (displaying_sensor == "temperature"){
vall = vall;
}
if (displaying_sensor.startsWith("s")) {
if (vall > 0 && vall < 102400000 ){
series.data.values.push(vall);
time_obj = new Date(epoch_ms);
series.data.x.push(time_obj);
}
}
else {
series.data.values.push(vall);
time_obj = new Date(epoch_ms);
series.data.x.push(time_obj);
}
//series.data.values.push(vall);
//series.data.x.push(last_x);
//cnt = cnt + 1;
UniversalChart.axes.bottom.labels.roundFirst = true;
UniversalChart.axes.bottom.labels.dateFormat = "shortDateTime";
UniversalChart.draw();
}
}
}
}
break;
case "pressure":
break;
case "temperature":
break;
case "humidity":
break;
case "light":
break;
}
}
}
function CountVisible() {
var visibles = [];
for (var l = 0; l < UniversalChart.series.count(); l++) {
var series = UniversalChart.series.items[l];
if (series.visible == true) {
visibles.push([l,series.title]);
}
}
return visibles;
}
function addZeroLineOld() {
// Create a new series just for the zero line
var zeroLine = new Tee.Line();
UniversalChart.addSeries(zeroLine);
// Set series properties
zeroLine.format.stroke.size = 1; // Line width
zeroLine.format.stroke.fill = "black"; // Line color
zeroLine.format.stroke.dash = [5, 5]; // Optional: Make it dashed
// Now add just two points - we only need start and end
// We'll use the min and max x values from the data
var minMaxX = getMinMaxTimeFromSeries();
// If we couldn't get min/max from data, use arbitrary large range
if (!minMaxX) {
var now = new Date();
minMaxX = {
min: new Date(now.getTime() - 86400000), // 24 hours ago
max: now
};
}
// Add the two points that make up our horizontal line
zeroLine.data.values = [0, 0]; // Both at y=0
zeroLine.data.x = [minMaxX.min, minMaxX.max]; // Span the full x range
// Make sure it's visible but in the background
zeroLine.visible = true;
zeroLine.zOrder = -1; // Put it behind other series
}
// Helper function to get min/max times from existing series
function getMinMaxTimeFromSeries() {
let min = null;
let max = null;
// Loop through all series to find global min/max x values
for (let i = 0; i < UniversalChart.series.count(); i++) {
let s = UniversalChart.series.items[i];
if (s.visible && s.data.x && s.data.x.length > 0) {
// Find min and max for this series
let seriesMin = s.data.x[0];
let seriesMax = s.data.x[s.data.x.length - 1];
// Update global min/max
if (min === null || seriesMin < min) min = seriesMin;
if (max === null || seriesMax > max) max = seriesMax;
}
}
return (min !== null && max !== null) ? { min: min, max: max } : null;
}
function PrepareChart(devices_count) {
//UniversalChart.series.items[0].horizAxis = "bottom";
//UniversalChart.title.text="";
//UniversalChart.title.visible = false;
UniversalChart.panel.transparent=true;
UniversalChart.legend.visible=false;
//UniversalChart.axes.bottom.setMinMax(x0[200].getTime(), x0[499].getTime());
UniversalChart.axes.bottom.labels.roundFirst=true;
UniversalChart.axes.bottom.labels.dateFormat = "shortDateTime";
UniversalChart.zoom.enabled=true;//false;
UniversalChart.zoom.mouseButton=0;//false;
UniversalChart.scroll.mouseButton=2;
UniversalChart.scroll.direction="both";
while (UniversalChart.series.count() > 0) {
var series = UniversalChart.series.items[0];
UniversalChart.removeSeries( series );
}
series_collection = [];
UniversalChart.draw();
zmap_type = document.getElementById("zmap_type").value; //None, all, raw, presence, z-graph
for (var t = 0; t < devices_count; t++) {
sensors_series_collection = [];
if (zmap_type == "none") {
if(map_type == 1){
if(positions[t][0] < 200)
sensors_series_collection.push(new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line());
else
sensors_series_collection.push(new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(),
new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line());
}
else if (map_type == 2){
if(positions[t][0] < 200)
sensors_series_collection.push(new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line());
else
sensors_series_collection.push(new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(),
new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line());
}
}
else{
if(zmap_type == "all"){ //3 for raw, presence, z-graph
sensors_series_collection.push(new Tee.Line(), new Tee.Line(), new Tee.Line());
}
else{
sensors_series_collection.push(new Tee.Line());
}
}
series_collection.push(sensors_series_collection);
}
series_indexes = {};
for (var t = 0; t < devices_count; t++) {
collection = series_collection[t];
for (var l = 0; l < collection.length; l++) {
UniversalChart.addSeries(collection[l]);
series_temp = collection[l];
series_temp.addRandom(100);
//if(l<2) {
// series_temp.vertAxis=UniversalChart.axes.right;
//}
//else {
series_temp.vertAxis=UniversalChart.axes.left;
//}
device_id = positions[t][1];
well_id = positions[t][0];
location_desc = locations_map[well_id];
rgb_comp = Loc2Color[device_id_2_location[well_id]][0];
console.log(rgb_comp);
series_temp.format.stroke.fill = "rgb(" + rgb_comp[0] + ", " + rgb_comp[1] + ", " + rgb_comp[2] + ")"
series_temp.format.fill = series_temp.format.stroke.fill;
if (zmap_type == "none") {
MAC = positions[t][4];
if(map_type == 1){
if(well_id<200){
series_indexes[MAC+sensor_tables[l]] = UniversalChart.series.items.length-1;
series_temp.title = sensor_tables[l] +":"+well_id;//+ ":"+ MAC;//location_desc;
}
else{
series_indexes[MAC+sensor_tablesn[l]] = UniversalChart.series.items.length-1;
series_temp.title = sensor_tablesn[l] +":"+well_id;//+ ":"+ MAC;//location_desc;
}
}
else if (map_type == 2){
if(well_id<200){
series_indexes[MAC+radar_tablesn[l]] = UniversalChart.series.items.length-1;
series_temp.title = radar_tablesn[l] +":"+well_id;//+ ":"+ MAC;//location_desc;
}
else{
series_indexes[MAC+radar_tablesn[l]] = UniversalChart.series.items.length-1;
series_temp.title = radar_tablesn[l] +":"+well_id;//+ ":"+ MAC;//location_desc;
}
}
}
else{
if (zmap_type == "all") {
series_indexes[well_id+"_"+presence_graphs[l]] = UniversalChart.series.items.length-1;
series_temp.title = presence_graphs[l] +":"+well_id;
}
else{
series_indexes[well_id+"_"+zmap_type] = UniversalChart.series.items.length-1;
series_temp.title = zmap_type +":"+well_id;
}
}
}
}
if(zmap_type == "all" || zmap_type == "multiple"){ //1 for multiple
sensors_series_collection = [];
series_collection = [];
sensors_series_collection.push(new Tee.Line());
//series_collection.push(sensors_series_collection);
UniversalChart.addSeries(sensors_series_collection[0]);
series_temp = sensors_series_collection[0];
series_temp.addRandom(100);
rgb_comp = [0,0,0];
series_temp.format.stroke.fill = "rgb(" + rgb_comp[0] + ", " + rgb_comp[1] + ", " + rgb_comp[2] + ")"
series_temp.format.fill = series_temp.format.stroke.fill;
series_indexes["multiple_"+zmap_type] = UniversalChart.series.items.length-1;
series_temp.title = zmap_type +":multiple";
//-----------------------------------------------------------
sensors_series_collection = [];
series_collection = [];
sensors_series_collection.push(new Tee.Line());
//series_collection.push(sensors_series_collection);
UniversalChart.addSeries(sensors_series_collection[0]);
series_temp = sensors_series_collection[0];
series_temp.addRandom(100);
rgb_comp = [64,64,64];
series_temp.format.stroke.fill = "rgb(" + rgb_comp[0] + ", " + rgb_comp[1] + ", " + rgb_comp[2] + ")"
series_temp.format.fill = series_temp.format.stroke.fill;
series_indexes["persons_"+zmap_type] = UniversalChart.series.items.length-1;
series_temp.title = zmap_type +":persons";
}
//UniversalChart.legend.format.transparency = 0;
//UniversalChart.legend.legendStyle = "series";
UniversalChart.title.visible = true;
//UniversalChart.title.text = "";
//changeTheme(Chart1, "minimal");
//Chart1.draw();
//changeTheme(UniversalChart, "minimal");
//UniversalChart.title.text = "";
UniversalChart.draw(); //get position
var t = new Tee.CursorTool(UniversalChart);
t.direction = "vertical";
//posXLabel=document.getElementById("xpos"); //parameter_h
//posXLabel = document.getElementById("parameter_h"); //parameter_h
t.onchange = function (p) {
if (true) {
xValue = UniversalChart.axes.bottom.fromPos(p.x);
ms_from_start = xValue - start_epoch;
data_index = parseInt(ms_from_start/10000.0);
var myDate = new Date(xValue);
var timeSinceMidnight = myDate.getTime() - new Date(myDate.getFullYear(), myDate.getMonth(), myDate.getDate()).getTime();
var minute_in_day = Math.floor(timeSinceMidnight / (1000 * 60));
decimal = ((xValue/10).toFixed(0) % 100);
decimal = String(decimal).padStart(2, '0');
//console.log(xValue);
//console.log(decimal);
yValue = UniversalChart.axes.left.fromPos(p.y);
yValue1 = UniversalChart.axes.right.fromPos(p.y);
time_string = myDate.toLocaleString();
mani_part = time_string.substr(0, time_string.length - 3);
ampm_part = time_string.substr(time_string.length - 3,time_string.length);
UniversalChart.title.text = data_index +" --- "+ clicked_sensor_description_fixed +" " +mani_part+"."+decimal+ampm_part +", " +yValue.toFixed(2);
UniversalChart.draw();
UpdateRoseChart(minute_in_day)
}
};
//var horizontalCursor = new Tee.CursorTool(UniversalChart);
//horizontalCursor.direction = "horizontal";
// Set the position to y=0 in data coordinates
//horizontalCursor.position = UniversalChart.axes.left.calc(0);
// Add the cursor to the chart tools
// // Custom draw function to keep cursor fixed at y=0
// UniversalChart.afterDraw = function() {
// // Recalculate position in case of zooming/scrolling
// horizontalCursor.position = UniversalChart.axes.left.calc(0);
// // Force horizontal cursor to redraw
// horizontalCursor.draw();
// }
// UniversalChart.afterDraw = function() {
// // Find the zero line series
// for (let i = 0; i < UniversalChart.series.count(); i++) {
// let s = UniversalChart.series.items[i];
// // Identify our zero line series (could add a special property to it)
// if (s.data.values.length === 2 && s.data.values[0] === 0 && s.data.values[1] === 0) {
// // Update x values to span visible area
// s.data.x = [
// new Date(UniversalChart.axes.bottom.minimum),
// new Date(UniversalChart.axes.bottom.maximum)
// ];
// break;
// }
// }
// }
if (!enableCursor) {
UniversalChart.tools.add(t);
//UniversalChart.tools.add(horizontalCursor);
enableCursor = true;
}
UniversalChart.legend.visible = false; // We're using custom legend
createCustomLegend();
const chartWidth = UniversalChart.canvas.width;
const legendWidth = 180;
const marginPercentage = (legendWidth / chartWidth) * 100;
console.log("Calculated margin percentage:", marginPercentage);
UniversalChart.panel.margins.left = marginPercentage;
UniversalChart.panel.margins.right = 0;
UniversalChart.draw();
}
function createCustomLegendOld() {
// Get container of the chart canvas
const chartContainer = UniversalChart.canvas.parentNode;
const canvasRect = UniversalChart.canvas.getBoundingClientRect();
// Calculate the chart's series area dimensions
// These values may need adjustment based on your specific chart layout
const legendWidth = 150; // Width for the legend
const chartTopMargin = 45; // Approximate top margin of chart (for title, etc.)
const chartBottomMargin = 40; // Approximate bottom margin (for axis labels, etc.)
// Create or update custom legend container
let legendDiv = document.getElementById('custom-chart-legend');
if (!legendDiv) {
legendDiv = document.createElement('div');
legendDiv.id = 'custom-chart-legend';
legendDiv.style.position = 'absolute';
legendDiv.style.top = chartTopMargin + 'px';
legendDiv.style.left = '20px';
legendDiv.style.width = legendWidth + 'px';
legendDiv.style.background = 'white';
legendDiv.style.border = '1px solid #ccc';
legendDiv.style.padding = '10px';
legendDiv.style.zIndex = '1000';
legendDiv.style.overflowY = 'auto';
chartContainer.appendChild(legendDiv);
}
// Clear existing legend
legendDiv.innerHTML = '';
// Calculate series area height to match legend height if needed
const seriesAreaHeight = canvasRect.height - chartTopMargin - chartBottomMargin;
legendDiv.style.height = seriesAreaHeight + 'px';
// Add legend items
for (let i = 0; i < UniversalChart.series.count(); i++) {
const series = UniversalChart.series.items[i];
// Create legend item container
const itemDiv = document.createElement('div');
itemDiv.style.marginBottom = '5px';
itemDiv.style.display = 'flex';
itemDiv.style.alignItems = 'center';
// Create checkbox
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.checked = series.visible;
checkbox.style.marginRight = '5px';
checkbox.setAttribute('data-series-index', i);
// Add event listener for checkbox
checkbox.addEventListener('change', function() {
const seriesIndex = parseInt(this.getAttribute('data-series-index'));
UniversalChart.series.items[seriesIndex].visible = this.checked;
UniversalChart.draw();
});
// Create color swatch
const colorSwatch = document.createElement('span');
colorSwatch.style.display = 'inline-block';
colorSwatch.style.width = '12px';
colorSwatch.style.height = '12px';
colorSwatch.style.backgroundColor = series.format.stroke.fill;
colorSwatch.style.marginRight = '5px';
// Create label
const label = document.createElement('span');
label.textContent = series.title;
// Add elements to item
itemDiv.appendChild(checkbox);
itemDiv.appendChild(colorSwatch);
itemDiv.appendChild(label);
// Add item to legend
legendDiv.appendChild(itemDiv);
}
// Hide the built-in legend
UniversalChart.legend.visible = false;
// Shift the chart panel to the right to make space for the legend
// This might require adjusting the chart margins or bounds
const chartWidth = UniversalChart.canvas.width;
const marginPercentage = ((30+legendWidth) / chartWidth) * 100;
UniversalChart.panel.margins.left = marginPercentage; // 20px extra spacing
UniversalChart.panel.margins.right = 0;
// Redraw the chart with new dimensions
UniversalChart.draw();
}
function createCustomLegend() {
// Get container of the chart canvas
const chartContainer = UniversalChart.canvas.parentNode;
const canvasRect = UniversalChart.canvas.getBoundingClientRect();
// Calculate the chart's series area dimensions
// These values may need adjustment based on your specific chart layout
const legendWidth = 150; // Width for the legend
const chartTopMargin = 35; // Approximate top margin of chart (for title, etc.)
const chartBottomMargin = 40; // Approximate bottom margin (for axis labels, etc.)
// Create or update custom legend container
let legendDiv = document.getElementById('custom-chart-legend');
if (!legendDiv) {
legendDiv = document.createElement('div');
legendDiv.id = 'custom-chart-legend';
legendDiv.style.position = 'absolute';
legendDiv.style.top = chartTopMargin + 'px';
legendDiv.style.left = '20px';
legendDiv.style.width = legendWidth + 'px';
legendDiv.style.background = 'white';
legendDiv.style.border = '1px solid #ccc';
legendDiv.style.padding = '10px';
legendDiv.style.zIndex = '1000';
legendDiv.style.overflowY = 'auto';
chartContainer.appendChild(legendDiv);
}
// Clear existing legend
legendDiv.innerHTML = '';
// Calculate series area height to match legend height if needed
const seriesAreaHeight = canvasRect.height - chartTopMargin - chartBottomMargin;
legendDiv.style.height = seriesAreaHeight + 'px';
// Create Select All/None controls
const controlsDiv = document.createElement('div');
controlsDiv.style.marginBottom = '1px';
controlsDiv.style.paddingBottom = '1px';
controlsDiv.style.borderBottom = '1px solid #ddd';
// Select All button
const selectAllBtn = document.createElement('button');
selectAllBtn.textContent = 'All';
selectAllBtn.style.fontSize = '11px';
selectAllBtn.style.padding = '2px 6px';
selectAllBtn.style.marginRight = '5px';
selectAllBtn.style.cursor = 'pointer';
selectAllBtn.style.border = '1px solid #ccc';
selectAllBtn.style.backgroundColor = '#f8f8f8';
// Select None button
const selectNoneBtn = document.createElement('button');
selectNoneBtn.textContent = 'None';
selectNoneBtn.style.fontSize = '11px';
selectNoneBtn.style.padding = '2px 6px';
selectNoneBtn.style.cursor = 'pointer';
selectNoneBtn.style.border = '1px solid #ccc';
selectNoneBtn.style.backgroundColor = '#f8f8f8';
// Add buttons to controls
controlsDiv.appendChild(selectAllBtn);
controlsDiv.appendChild(selectNoneBtn);
legendDiv.appendChild(controlsDiv);
// Function to update all checkboxes
function updateAllCheckboxes(checked) {
const checkboxes = legendDiv.querySelectorAll('input[type="checkbox"][data-series-index]');
checkboxes.forEach(checkbox => {
const seriesIndex = parseInt(checkbox.getAttribute('data-series-index'));
checkbox.checked = checked;
UniversalChart.series.items[seriesIndex].visible = checked;
if(checked){
console.log("Selected");
console.log(seriesIndex);
}
});
UniversalChart.draw();
}
// Add event listeners for Select All/None buttons
selectAllBtn.addEventListener('click', function() {
updateAllCheckboxes(true);
});
selectNoneBtn.addEventListener('click', function() {
updateAllCheckboxes(false);
});
// Add legend items
for (let i = 0; i < UniversalChart.series.count(); i++) {
const series = UniversalChart.series.items[i];
// Create legend item container
const itemDiv = document.createElement('div');
itemDiv.style.marginBottom = '5px';
itemDiv.style.display = 'flex';
itemDiv.style.alignItems = 'center';
// Create checkbox
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.checked = series.visible;
checkbox.style.marginRight = '5px';
checkbox.setAttribute('data-series-index', i);
// Add event listener for checkbox
checkbox.addEventListener('change', function() {
const seriesIndex = parseInt(this.getAttribute('data-series-index'));
UniversalChart.series.items[seriesIndex].visible = this.checked;
UniversalChart.draw();
});
// Create color swatch
const colorSwatch = document.createElement('span');
colorSwatch.style.display = 'inline-block';
colorSwatch.style.width = '12px';
colorSwatch.style.height = '12px';
colorSwatch.style.backgroundColor = series.format.stroke.fill;
colorSwatch.style.marginRight = '5px';
// Create label
const label = document.createElement('span');
label.textContent = series.title;
label.style.fontSize = '12px';
// Add elements to item
itemDiv.appendChild(checkbox);
itemDiv.appendChild(colorSwatch);
itemDiv.appendChild(label);
// Add item to legend
legendDiv.appendChild(itemDiv);
}
// Hide the built-in legend
UniversalChart.legend.visible = false;
// Shift the chart panel to the right to make space for the legend
// This might require adjusting the chart margins or bounds
const chartWidth = UniversalChart.canvas.width;
const marginPercentage = ((30+legendWidth) / chartWidth) * 100;
UniversalChart.panel.margins.left = marginPercentage; // 20px extra spacing
UniversalChart.panel.margins.right = 0;
// Redraw the chart with new dimensions
UniversalChart.draw();
}
function HideAndEmptyAllSeries() {
series_count = UniversalChart.series.items.length;
for (var d = 0; d < series_count; d++) {
var s = UniversalChart.series.items[d];
s.data.x = [];
s.data.values = [];
s.visible = false;
}
UniversalChart.draw();
}
function EmptyAllSeries() {
series_count = UniversalChart.series.items.length;
for (var d = 0; d < series_count; d++) {
var s = UniversalChart.series.items[d];
s.data.x = [];
s.data.values = [];
}
UniversalChart.draw();
}
function DisplayPresence(data, zmap_type) {
try {
// First verify chart is ready
if (!UniversalChart || !UniversalChart.series || !UniversalChart.series.items) {
console.error("Chart not properly initialized");
return;
}
if (zmap_type == "all"){
presence = data.presence;
raw = data.raw;
z_graph = data.z_graph;
multiple = data.multiple;
persons = data.persons;
}
else if (zmap_type == "raw"){
raw = data.raw;
}
else if (zmap_type == "presence"){
presence = data.presence;
}
else if (zmap_type == "z-graph"){
z_graph = data.z_graph;
}
else if (zmap_type == "multiple"){
multiple = data.multiple;
persons = data.persons;
}
time_zone_st = data.time_zone;
hours_delta = getTimezoneDiffHours(time_zone_st);
start_epoch = 1000*data.time_start + hours_delta * 3600000;//[ms]
well_ids = data.well_ids;
devices_count = well_ids.length;
EmptyAllSeries();
UniversalChart.draw();
series_index = 0;
// Track if we actually added any data
let dataAdded = false;
if (zmap_type == "all"){
}
for (const well_id of well_ids) {
for (const chart_type of presence_graphs) {
series_index = series_indexes[well_id+"_"+chart_type];
// Verify series exists
if (series_index === undefined || !UniversalChart.series.items[series_index]) {
continue;
}
console.log("Processing data for well_id:", well_id, "chart_type:", chart_type);
console.log("Looking for series index:", well_id+"_"+chart_type, "Found:", series_index);
series = UniversalChart.series.items[series_index];
series.visible = true;
// Clear existing data
series.data.values = [];
series.data.x = [];
if (chart_type == "raw"){
value2 = raw[well_id];
}
else if (chart_type == "presence"){
value2 = presence[well_id];
//for (let i = 0; i < presence[well_id].length; i++) {
// value2.push(presence[well_id][i] * 100);
//}
}
else if (chart_type == "z-graph"){
value2 = z_graph[well_id];
}
console.log(`Data for well_id ${well_id}, chart_type ${chart_type}:`, value2 ? value2.slice(0, 5) : "undefined");
l = value2.length;
if (l > 0){
// Process data points
console.log("chart_type=[" + chart_type + "], length=" + chart_type.length);
console.log("z-graph=[z-graph], length=7");
if (chart_type != "z-graph"){
if(chart_type=="presence"){
for (var t = 0; t < l; t++) {
point = value2[t];
deca = point[0];
vall = 100*point[1];
epoch_ms = start_epoch + deca*10000; //deca in ms
//epoch_ms = epoch_ms + hours_delta * 3600000
if (vall != null) {
//here we need to apply time difference between where user is and what is time zone of deployment
series.data.x.push(new Date(epoch_ms));
series.data.values.push(vall);
dataAdded = true;
}
}
}
else{
for (var t = 0; t < l; t++) {
epoch_ms = start_epoch + t*10000; //deca in ms
//epoch_ms = epoch_ms + hours_delta * 3600000
vall = value2[t];
if (vall != null) {
//here we need to apply time difference between where user is and what is time zone of deployment
series.data.x.push(new Date(epoch_ms));
series.data.values.push(vall);
dataAdded = true;
}
}
}
UniversalChart.draw();
}
else{ //it is "z-graph"
for (var t = 0; t < l; t++) {
epoch_ms = start_epoch + value2[t][0]*10000; //deca in ms
vall = value2[t][1]/6;
if (vall != null) {
series.data.x.push(new Date(epoch_ms));
series.data.values.push(vall);
dataAdded = true;
}
}
}
}
console.log(`Series ${series_index} data count:`, series.data.values.length);
if (series.data.values.length > 0) {
console.log(`Series ${series_index} first few values:`, series.data.values.slice(0, 5));
}
}
}
if (zmap_type == "all" || zmap_type == "multiple"){
value2 = multiple;
l = value2.length;
series = UniversalChart.series.items[UniversalChart.series.items.length - 2]; //next to last series
series.visible = true;
// Clear existing data
series.data.values = [];
series.data.x = [];
for (var t = 0; t < l; t++) {
epoch_ms = start_epoch + value2[t][0]*10000; //deca in ms
vall = value2[t][1]/6;
if (vall != null) {
series.data.x.push(new Date(epoch_ms));
series.data.values.push(vall);
dataAdded = true;
}
}
value2 = persons;
l = value2.length;
series = UniversalChart.series.items[UniversalChart.series.items.length - 1]; //last series
series.visible = true;
// Clear existing data
series.data.values = [];
series.data.x = [];
for (var t = 0; t < l; t++) {
point = value2[t];
deca = point[0];
vall = point[1];
epoch_ms = start_epoch + deca*10000; //deca in ms
//epoch_ms = epoch_ms + hours_delta * 3600000
if (vall != null) {
//here we need to apply time difference between where user is and what is time zone of deployment
series.data.x.push(new Date(epoch_ms));
series.data.values.push(vall);
dataAdded = true;
}
}
}
// Only proceed if we actually have data
if (!dataAdded) {
console.warn("No data was added to the chart");
return;
}
console.log("Data added:", dataAdded);
console.log("Sample data point:", series.data.x[0], series.data.values[0]);
console.log("Total points added for series:", series.data.x.length);
// Configure axes
try {
const chartWidth = UniversalChart.canvas.width;
console.log("Chart width:", chartWidth);
UniversalChart.axes.left.automatic = true;
UniversalChart.axes.bottom.automatic = true;
UniversalChart.title.visible = true;
UniversalChart.legend.visible = false; // We're using custom legend
createCustomLegend();
const legendWidth = 180;
const marginPercentage = (legendWidth / chartWidth) * 100;
console.log("Calculated margin percentage:", marginPercentage);
UniversalChart.panel.margins.left = marginPercentage;
UniversalChart.panel.margins.right = 0;
UniversalChart.draw();
showTutorial("Data shown!");
} catch (e) {
console.error("Error during chart configuration/drawing:", e);
}
} catch (e) {
console.error("Error in DisplaySingleSlice:", e);
}
}
function PrepareDeviceChart(device_properties) {
UniversalChart.panel.transparent=true;
UniversalChart.legend.visible=true;
UniversalChart.axes.bottom.labels.roundFirst=true;
UniversalChart.axes.bottom.labels.dateFormat = "shortDateTime";
UniversalChart.zoom.enabled=true;//false;
UniversalChart.zoom.mouseButton=0;//false;
UniversalChart.scroll.mouseButton=2;
UniversalChart.scroll.direction="both";
while (UniversalChart.series.count() > 0) {
var series = UniversalChart.series.items[0];
UniversalChart.removeSeries( series );
}
series_collection = [];
UniversalChart.draw();
var t = 0;
sensors_series_collection = [];
if(map_type == 1){
if(device_properties[0] < 200)
sensors_series_collection.push(new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line());
else
sensors_series_collection.push(new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(),
new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line());
}
else if (map_type == 2){
if(device_properties[0] < 200)
sensors_series_collection.push(new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line());
else
sensors_series_collection.push(new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(),
new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line(), new Tee.Line());
}
series_collection.push(sensors_series_collection);
series_indexes = {};
t = 0;
collection = series_collection[t];
for (var l = 0; l < collection.length; l++) {
UniversalChart.addSeries(collection[l]);
series_temp = collection[l];
series_temp.addRandom(1000);
series_temp.vertAxis=UniversalChart.axes.left;
series_temp.format.stroke.fill = colorsDev[l];
device_id = device_properties[1];
well_id = device_properties[0];
//location_desc = locations_map[device_id];
MAC = device_properties[4];
if(map_type == 1){
if(well_id<200){
series_indexes[MAC+sensor_tables[l]] = UniversalChart.series.items.length-1;
series_temp.title = sensor_tables[l] +":"+well_id;//+ ":"+ MAC;//location_desc;
}
else{
series_indexes[MAC+sensor_tablesn[l]] = UniversalChart.series.items.length-1;
series_temp.title = sensor_tablesn[l] +":"+well_id;//+ ":"+ MAC;//location_desc;
}
}
else if (map_type == 2){
if(well_id<200){
series_indexes[MAC+radar_tablesn[l]] = UniversalChart.series.items.length-1;
series_temp.title = radar_tablesn[l] +":"+well_id;//+ ":"+ MAC;//location_desc;
}
else{
series_indexes[MAC+radar_tablesn[l]] = UniversalChart.series.items.length-1;
series_temp.title = radar_tablesn[l] +":"+well_id;//+ ":"+ MAC;//location_desc;
}
}
series_temp.format.fill = colors[l];
series_temp.format.stroke.fill = colorsDev[l];
}
//UniversalChart.legend.format.transparency = 0;
UniversalChart.legend.legendStyle = "series";
UniversalChart.title.visible = true;
//UniversalChart.title.text = "";
//changeTheme(Chart1, "minimal");
//Chart1.draw();
//changeTheme(UniversalChart, "minimal");
//UniversalChart.title.text = "";
UniversalChart.draw(); //get position
var t = new Tee.CursorTool(UniversalChart);
t.direction = "vertical";
//posXLabel=document.getElementById("xpos"); //parameter_h
//posXLabel = document.getElementById("parameter_h"); //parameter_h
t.onchange = function (p) {
if (true) {
xValue = UniversalChart.axes.bottom.fromPos(p.x);
var myDate = new Date(xValue);
var timeSinceMidnight = myDate.getTime() - new Date(myDate.getFullYear(), myDate.getMonth(), myDate.getDate()).getTime();
var minute_in_day = Math.floor(timeSinceMidnight / (1000 * 60));
decimal = ((xValue/10).toFixed(0) % 100);
decimal = String(decimal).padStart(2, '0');
//console.log(xValue);
//console.log(decimal);
yValue = UniversalChart.axes.left.fromPos(p.y);
yValue1 = UniversalChart.axes.right.fromPos(p.y);
time_string = myDate.toLocaleString();
mani_part = time_string.substr(0, time_string.length - 3);
ampm_part = time_string.substr(time_string.length - 3,time_string.length);
UniversalChart.title.text = clicked_sensor_description_fixed +" " +mani_part+"."+decimal+ampm_part +", " +yValue.toFixed(2);// +", " +yValue1.toFixed(2);// +", " +xValue.toFixed(3);
//posXLabel.textContent =
// "" + myDate.toLocaleString() + ", " + yValue.toFixed(2);
//UniversalChart.tools.visible = true;
UniversalChart.draw();
UpdateRoseChart(minute_in_day)
}
};
if (!enableCursor) {
UniversalChart.tools.add(t);
enableCursor = true;
}
UniversalChart.draw();
}
function UpdateRoseChart(minute_in_day){
try {
if (Object.keys(vocs_scaled).length > 0){
index_key = device_id.toString()+'_0';
voc0_component = vocs_scaled[index_key][minute_in_day];
voc0_component_max = vocs_scaled[index_key][1440];
voc0_component_min = vocs_scaled[index_key][1441];
voc0_component_total_max = vocs_scaled[index_key][1442];
voc0_component_total_min = vocs_scaled[index_key][1443];
index_key = device_id.toString()+'_1';
voc1_component = vocs_scaled[index_key][minute_in_day];
voc1_component_max = vocs_scaled[index_key][1440];
voc1_component_min = vocs_scaled[index_key][1441];
voc1_component_total_max = vocs_scaled[index_key][1442];
voc1_component_total_min = vocs_scaled[index_key][1443];
index_key = device_id.toString()+'_2';
voc2_component = vocs_scaled[index_key][minute_in_day];
voc2_component_max = vocs_scaled[index_key][1440];
voc2_component_min = vocs_scaled[index_key][1441];
voc2_component_total_max = vocs_scaled[index_key][1442];
voc2_component_total_min = vocs_scaled[index_key][1443];
index_key = device_id.toString()+'_3';
voc3_component = vocs_scaled[index_key][minute_in_day];
voc3_component_max = vocs_scaled[index_key][1440];
voc3_component_min = vocs_scaled[index_key][1441];
voc3_component_total_max = vocs_scaled[index_key][1442];
voc3_component_total_min = vocs_scaled[index_key][1443];
index_key = device_id.toString()+'_4';
voc4_component = vocs_scaled[index_key][minute_in_day];
voc4_component_max = vocs_scaled[index_key][1440];
voc4_component_min = vocs_scaled[index_key][1441];
voc4_component_total_max = vocs_scaled[index_key][1442];
voc4_component_total_min = vocs_scaled[index_key][1443];
index_key = device_id.toString()+'_5';
voc5_component = vocs_scaled[index_key][minute_in_day];
voc5_component_max = vocs_scaled[index_key][1440];
voc5_component_min = vocs_scaled[index_key][1441];
voc5_component_total_max = vocs_scaled[index_key][1442];
voc5_component_total_min = vocs_scaled[index_key][1443];
index_key = device_id.toString()+'_6';
voc6_component = vocs_scaled[index_key][minute_in_day];
voc6_component_max = vocs_scaled[index_key][1440];
voc6_component_min = vocs_scaled[index_key][1441];
voc6_component_total_max = vocs_scaled[index_key][1442];
voc6_component_total_min = vocs_scaled[index_key][1443];
index_key = device_id.toString()+'_7';
voc7_component = vocs_scaled[index_key][minute_in_day];
voc7_component_max = vocs_scaled[index_key][1440];
voc7_component_min = vocs_scaled[index_key][1441];
voc7_component_total_max = vocs_scaled[index_key][1442];
voc7_component_total_min = vocs_scaled[index_key][1443];
index_key = device_id.toString()+'_8';
voc8_component = vocs_scaled[index_key][minute_in_day];
voc8_component_max = vocs_scaled[index_key][1440];
voc8_component_min = vocs_scaled[index_key][1441];
voc8_component_total_max = vocs_scaled[index_key][1442];
voc8_component_total_min = vocs_scaled[index_key][1443];
index_key = device_id.toString()+'_9';
voc9_component = vocs_scaled[index_key][minute_in_day];
voc9_component_max = vocs_scaled[index_key][1440];
voc9_component_min = vocs_scaled[index_key][1441];
voc9_component_total_max = vocs_scaled[index_key][1442];
voc9_component_total_min = vocs_scaled[index_key][1443];
if (voc0_component == 102400000)
voc0_scaled = 0;
else{
if (document.getElementById("rcr-check").checked)
voc0_scaled = 100-(voc0_component-voc0_component_total_min)*100/(voc0_component_total_max-voc0_component_total_min);
else
voc0_scaled = 100-(voc0_component-voc0_component_min)*100/(voc0_component_max-voc0_component_min);
}
if (voc1_component == 102400000)
voc1_scaled = 0;
else{
if (document.getElementById("rcr-check").checked)
voc1_scaled = 100-(voc1_component-voc1_component_total_min)*100/(voc1_component_total_max-voc1_component_total_min);
else
voc1_scaled = 100-(voc1_component-voc1_component_min)*100/(voc1_component_max-voc1_component_min);
}
if (voc2_component == 102400000)
voc2_scaled = 0;
else{
if (document.getElementById("rcr-check").checked)
voc2_scaled = 100-(voc2_component-voc2_component_total_min)*100/(voc2_component_total_max-voc2_component_total_min);
else
voc2_scaled = 100-(voc2_component-voc2_component_min)*100/(voc2_component_max-voc2_component_min);
}
if (voc3_component == 102400000)
voc3_scaled = 0;
else{
if (document.getElementById("rcr-check").checked)
voc3_scaled = 100-(voc3_component-voc3_component_total_min)*100/(voc3_component_total_max-voc3_component_total_min);
else
voc3_scaled = 100-(voc3_component-voc3_component_min)*100/(voc3_component_max-voc3_component_min);
}
if (voc4_component == 102400000)
voc4_scaled = 0;
else{
if (document.getElementById("rcr-check").checked)
voc4_scaled = 100-(voc4_component-voc4_component_total_min)*100/(voc4_component_total_max-voc4_component_total_min);
else
voc4_scaled = 100-(voc4_component-voc4_component_min)*100/(voc4_component_max-voc4_component_min);
}
if (voc5_component == 102400000)
voc5_scaled = 0;
else{
if (document.getElementById("rcr-check").checked)
voc5_scaled = 100-(voc5_component-voc5_component_total_min)*100/(voc5_component_total_max-voc5_component_total_min);
else
voc5_scaled = 100-(voc5_component-voc5_component_min)*100/(voc5_component_max-voc5_component_min);
}
if (voc6_component == 102400000)
voc6_scaled = 0;
else{
if (document.getElementById("rcr-check").checked)
voc6_scaled = 100-(voc6_component-voc6_component_total_min)*100/(voc6_component_total_max-voc6_component_total_min);
else
voc6_scaled = 100-(voc6_component-voc6_component_min)*100/(voc6_component_max-voc6_component_min);
}
if (voc7_component == 102400000)
voc7_scaled = 0;
else{
if (document.getElementById("rcr-check").checked)
voc7_scaled = 100-(voc7_component-voc7_component_total_min)*100/(voc7_component_total_max-voc7_component_total_min);
else
voc7_scaled = 100-(voc7_component-voc7_component_min)*100/(voc7_component_max-voc7_component_min);
}
if (voc8_component == 102400000)
voc8_scaled = 0;
else{
if (document.getElementById("rcr-check").checked)
voc8_scaled = 100-(voc8_component-voc8_component_total_min)*100/(voc8_component_total_max-voc8_component_total_min);
else
voc8_scaled = 100-(voc8_component-voc8_component_min)*100/(voc8_component_max-voc8_component_min);
}
if (voc9_component == 102400000)
voc9_scaled = 0;
else{
if (document.getElementById("rcr-check").checked)
voc9_scaled = 100-(voc9_component-voc9_component_total_min)*100/(voc9_component_total_max-voc9_component_total_min);
else
voc9_scaled = 100-(voc9_component-voc9_component_min)*100/(voc9_component_max-voc9_component_min);
}
polar1.data.values = [voc0_scaled, voc1_scaled, voc2_scaled, voc3_scaled, voc4_scaled, voc5_scaled, voc6_scaled, voc7_scaled, voc8_scaled, voc9_scaled];
//polar2.addRandom(10);
Chart10.draw();
console.log(voc0_scaled, voc1_scaled, voc2_scaled, voc3_scaled, voc4_scaled, voc5_scaled, voc6_scaled, voc7_scaled, voc8_scaled, voc9_scaled)
}
}
catch(error){
console.error(error);
}
}
function handleMouseMove(e){
reOffset();
var mx=parseInt(e.clientX) - offsetX;
var my=parseInt(e.clientY) - offsetY;
device_id = "0";
sensor_type = "";
location_desc = "";
hours = "00";
minutes = "00";
seconds = "00";
map_type = document.getElementById("map_type").value;
if(map_type == 1){
if(positions.length > 0){
if (positions[0][0] < 200){
devices_count = parseInt(Canvas1.height/70);
if (document.getElementById("GroupBy").value == "sensortype") {
sensor_index = parseInt(my/(devices_count*10));
sensor_type = sensor_tables[sensor_index];
position = 1+parseInt(my/10) % devices_count;
}
else {
position = 1+parseInt(my/(7*10));
sensor_index = parseInt(my/(10) % 7);
sensor_type = sensor_tables[sensor_index];
}
}
else{
devices_count = parseInt(Canvas1.height/150);
if (document.getElementById("GroupBy").value == "sensortype") {
sensor_index = parseInt(my/(devices_count*10));
sensor_type = sensor_tablesn[sensor_index];
position = 1+parseInt(my/10) % devices_count;
}
else {
position = 1+parseInt(my/(150));
sensor_index = parseInt(my/10 % 15);
sensor_type = sensor_tablesn[sensor_index];
}
}
device_id = positions[position-1][0];
location_desc = locations_map[device_id];
MAC = positions[position-1][4];
time = mx/60;
minute_in_day = parseInt(mx);
UpdateRoseChart(minute_in_day);
hours = String(parseInt(time)).padStart(2, '0');
minutes = String(parseInt((time*60) % 60)).padStart(2, '0');
seconds = "00";
clicked_sensor_description = device_id + " "+MAC + " "+sensor_type+ " @ "+location_desc+ " "+ hours+":"+minutes+":"+seconds;
UniversalChart.title.text = clicked_sensor_description_fixed + " "+ hours+":"+minutes+":"+seconds;
Canvas1 = document.getElementById("Canvas1");
Canvas1.title = clicked_sensor_description;
UniversalChart.draw();
}
}
else if(map_type == 4){ //Locations collapsed
time = mx/60;
minute_in_day = parseInt(mx);
UpdateRoseChart(minute_in_day);
hours = String(parseInt(time)).padStart(2, '0');
minutes = String(parseInt((time*60) % 60)).padStart(2, '0');
seconds = "00";
clicked_sensor_description = "@ "+location_desc+ " "+ hours+":"+minutes+":"+seconds;
UniversalChart.title.text = clicked_sensor_description_fixed + " "+ hours+":"+minutes+":"+seconds;
Canvas1 = document.getElementById("Canvas1");
Canvas1.title = clicked_sensor_description;
UniversalChart.draw();
}
else if(map_type == 2){ //Radar Only
if(positions.length > 0){
if (positions[0][0] < 200){
devices_count = parseInt(Canvas1.height/70);
if (document.getElementById("GroupBy").value == "sensortype") {
sensor_index = parseInt(my/(devices_count*10));
sensor_type = radar_tablesn[sensor_index];
position = 1+parseInt(my/10) % devices_count;
}
else {
position = 1+parseInt(my/(5*19));
sensor_index = parseInt(my/(5) % 19);
sensor_type = radar_tablesn[sensor_index];
}
}
else{
position = 1+parseInt(my/(5*19));
sensor_index = parseInt(my/(5) % 19);
sensor_type = radar_tablesn[sensor_index];
}
device_id = positions[position-1][0];
location_desc = locations_map[device_id];
MAC = positions[position-1][4];
time = mx/60;
minute_in_day = parseInt(mx);
UpdateRoseChart(minute_in_day);
hours = String(parseInt(time)).padStart(2, '0');
minutes = String(parseInt((time*60) % 60)).padStart(2, '0');
seconds = "00";
clicked_sensor_description = device_id + " "+MAC + " "+sensor_type+ " @ "+location_desc+ " "+ hours+":"+minutes+":"+seconds;
UniversalChart.title.text = clicked_sensor_description_fixed + " "+ hours+":"+minutes+":"+seconds;
Canvas1 = document.getElementById("Canvas1");
Canvas1.title = clicked_sensor_description;
UniversalChart.draw();
}
}
const h3Element = document.querySelector('.page-title .title_left h3');
h3Element.textContent = device_id+" "+sensor_type+" "+location_desc+" "+hours+":"+minutes+":"+seconds;
}
function draw() {
//Chart1=new Tee.Chart("canvas");
UniversalChart = new Tee.Chart("canvasU");
//Canvas1.onmousedown=(function(e){handleMouseDown(e);});
Canvas1 = document.getElementById("Canvas1");
//Canvas1.onmousemove=(function(e){handleMouseMove(e);});
$("#Canvas1").mousemove(handleMouseMove);
ctx1 = Canvas1.getContext('2d');
//Canvas2 = document.getElementById("Canvas2");
//ctx2 = Canvas2.getContext('2d');
cw=Canvas1.width;
ch=Canvas1.height;
//offsetX,offsetY;
reOffset();
Canvas1.onmouseup=(function(e){handleMouseUp(e);});
//Canvas1.onmouseout=(function(e){handleMouseUpOut(e);});
Chart10=new Tee.Chart("polar_canvas");
polar1 = Chart10.addSeries(new Tee.Polar()),
polar2 = Chart10.addSeries(new Tee.Polar());
// Set specific angle values for data points
polar1.data.x = [0, 36, 72, 108, 144, 180, 216, 252, 288, 324];
var labels = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var angles = [0, 36, 72, 108, 144, 180, 216, 252, 288, 324];
polar1.addRandom(10);
polar2.data.x = [-1,0,1, 35,36, 37, 71,72,73, 107,108,109, 143,144,145, 179,180,181, 215,216,217, 251,252,253, 287,288,289, 323,324,325];
polar2.data.values = [0,100,0,0,100,0, 0,100,0,0,100,0,0,100,0,0,100,0,0,100,0,0,100,0,0,100,0,0,100,0]
// optional degree (0 to 360) point positions:
//polar2.data.x=[10,30,90,110,270,300];
polar1.pointer.style="ellipse";
polar2.pointer.style="none";
// PENDING FEATURES:
//polar1.stacked="yes";
//polar2.stacked="yes";
//polar1.smooth=0.5;
polar1.format.transparency=0;
polar2.format.transparency=0.2;
// Cosmetics:
Chart10.title.text="Smell Signature";
Chart10.title.visible = true;
Chart10.walls.back.format.gradient.visible=true;
Chart10.panel.format.gradient.colors=["rgba(255,255,255,1)","rgba(255,255,255,1)"];
Chart10.panel.format.gradient.visible=true;
Chart10.panel.format.shadow.visible=false;
Chart10.panel.format.stroke.fill="";
Chart10.panel.format.round.x=0;
Chart10.panel.format.round.y=0;
Chart10.legend.visible=false;
// Set labels for bottom axis
//Chart10.axes.bottom.labels.labels = labels;
//Chart10.axes.bottom.labels.angle = angles;
//Chart10.axes.bottom.labels.format.font.style = "14px Verdana"; // Set font size and style as needed
//Chart10.axes.bottom.labels.format.font.fill = "black"; // Set font color as needed
Chart10.series.items[0].notmandatory.grid.visible=false;
//Chart10.series.items[0].mandatoryAxis.visible = false;
// Clear default labels
//Chart10.axes.bottom.labels.visible = false;
//Chart10.tools.add(new Tee.ToolTip(Chart10));
Chart10.draw();
ConnectMQTT();
}
function DoRefresh() {
n= t_series.data.values.length;
m= c_t_series.data.values.length;
if ((n !=1000) || (m !=1000)) {
MAC = document.getElementById("MAC").value;
RequestData(MAC, "temperature", false);
RequestData(MAC, "humidity", false);
RequestData(MAC, "pressure", false);
RequestData(MAC, "co2", false);
RequestData(MAC, "voc", false);
RequestData(MAC, "light", false);
RequestData(MAC, "radar", false);
}
}
function DoRefreshGraph(){
}
async function downloadReadings(deployment_id, date_from, date_to, group_by, consolidated_by, re_create, radar_part) {
const url = api_url + `/api?name=download&deployment_id=${deployment_id}&date_from=${date_from}&date_to=${date_to}&group_by=${group_by}&consolidated_by=${consolidated_by}&user_name=${user_name}&token=${token}&re_create=${re_create}&radar_part=${radar_part}`;
try {
// Show loading indicator
const loadingDiv = document.createElement('div');
loadingDiv.textContent = 'Downloading... 0%';
document.body.appendChild(loadingDiv);
const response = await fetch(url, {
method: 'GET',
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// Get total size from headers if available
const totalSize = response.headers.get('content-length') || 0;
let downloadedSize = 0;
// Create stream reader
const reader = response.body.getReader();
const chunks = [];
while(true) {
const {done, value} = await reader.read();
if (done) break;
chunks.push(value);
downloadedSize += value.length;
// Update progress
if (totalSize) {
const progress = ((downloadedSize / totalSize) * 100).toFixed(1);
loadingDiv.textContent = `Downloading... ${progress}%`;
}
}
// Combine chunks into single Blob
const blob = new Blob(chunks, {type: 'application/zip'});
// Generate filename
const filename = `readings_${deployment_id}_${date_from}_to_${date_to}_${consolidated_by}.zip`;
// Create download link
const downloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = filename;
// Trigger download
link.click();
// Cleanup
window.URL.revokeObjectURL(downloadUrl);
document.body.removeChild(loadingDiv);
} catch (error) {
console.error('Error downloading data:', error);
alert('Failed to download data. Please try again.');
}
}
function DoDownload(){
deployment_id = document.getElementById("Deployments").value;
date_from = document.getElementById('ddate').value;
to_date = document.getElementById('to_date').value;
consolidated_by = document.getElementById('consolidated_by').value;
re_create = document.getElementById("rcr-check").checked;
radar_part = document.getElementById("RadarPart").value;
downloadReadings(deployment_id, date_from, to_date, group_by, consolidated_by, re_create, radar_part);
}
function AddRefresh() {
n= t_series.data.values.length;
m= c_t_series.data.values.length;
if ((n !=1000) || (m !=1000)) {
MAC = document.getElementById("MAC").value;
RequestNewData(MAC, "temperature", false);
RequestNewData(MAC, "humidity", false);
RequestNewData(MAC, "pressure", false);
RequestNewData(MAC, "co2", false);
RequestNewData(MAC, "voc", false);
RequestNewData(MAC, "light", false);
RequestNewData(MAC, "radar", false);
sensor_changed();
}
}
function FindAbsoluteTop(object_id){
temp_object = document.getElementById(object_id);
var totalOffsetTop = temp_object.offsetTop;
var parent = temp_object.offsetParent;
// Traverse through the parent elements to calculate total offset top
while (parent) {
totalOffsetTop += parent.offsetTop;
parent = parent.offsetParent;
}
return(totalOffsetTop);
}
function resize(chart) {
//var canvas_cl = Chart1.canvas;
if(chart!=null){
var canvas = chart.canvas;
startWidth = 1000;
startHeight = 400;
var w = startWidth;
var h = startHeight;
if( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ) {
w = window.innerWidth;
h = window.innerHeight;
if(w<=991){
canvas.style.width="" + 0.8*w + "px";
canvas.style.height="" + w*0.8*startHeight/startWidth + "px";
}
else{
canvas.style.width = "" + startWidth + "px";
canvas.style.height = "" + startHeight + "px";
chart.bounds.width = startWidth;
chart.bounds.height = startHeight;
}
chart.draw();
}
else{
absolute_top = FindAbsoluteTop("Canvas1");
chart_wrapper = document.getElementById("ChartU");
map_bottom = absolute_top + Canvas1.height;
chart_wrapper.style.top = map_bottom+"px";
//polar_top = FindAbsoluteTop("PolarChart");
var form = document.forms['myform'];
// Get the input field within the form
var inputField = form.elements['stage'];
// Get the bounding rectangle of the input field
var rect = inputField.getBoundingClientRect();
// The top position of the input field relative to the viewport
polar_top = rect.top;
//polar_top = myform.to;
w = window.innerWidth - canvas.offsetLeft - 30;
//h = window.innerHeight -canvas.offsetTop - 230;
h = polar_top - map_bottom;
//w = 0; //window.innerWidth - canvas.offsetLeft-30;
//h = 0; //window.innerHeight -canvas.offsetTop - 320;
//canvas_cl.setAttribute('width', "" + 0 + "px");
//canvas_cl.setAttribute('height', "" + 0 + "px");
//canvas_cl.style.width = "" + 0 + "px";
//canvas_cl.style.height = "" + 0 + "px";
//Chart1.bounds.width = 0;
//Chart1.bounds.height = 0;
//Chart1.draw();
//h = 100
canvas.setAttribute('width', "" + w + "px");
canvas.setAttribute('height', "" + h + "px");
//canvas.style.top = "" + 10 + "px";
canvas.style.width = "" + w + "px";
canvas.style.height = "" + h + "px";
chart.bounds.width = w;
if (h > 50)
chart.bounds.height = h;
chart.draw();
}
}
}
function resizeToolBar(){
var toolbar1 = document.getElementById("toolbar1");
var w = window.innerWidth;
//toolbar1.style.width = "" + w + "px";
}
function AskForLatest(){
timee = Date.now();
time_period = time_max - time_min;
time_range = GetTimeRange(time_period);
var obj = {
function: "request_new",
signature:signature,
MAC: MAC,
last_t_time: last_t_time,
last_h_time: last_h_time,
last_c_time: last_c_time,
last_v_time: last_v_time,
last_p_time: last_p_time,
last_l_time: last_l_time,
last_r_time: last_r_time,
time_max: 2645858117,
user_name:user_name,
ps:key
};
var json = JSON.stringify(obj);
sendToBackend("/wellget", json);
}
function Frequency_changed(){
if (document.getElementById("auto").checked == true) {
refresh_frequency = 1000*document.getElementById("frequency").value;
if(interval != "")
clearInterval(interval);
interval = setInterval(AskForLatest, refresh_frequency);
}
else {
if(interval != "")
clearInterval(interval);
}
}
async function ShowHistoryMap() {
deployment_id = document.getElementById("Deployments").value;
ddate = document.getElementById("ddate").value;
map_type = document.getElementById("map_type").value;
if(deployment_id == "0") return;
if (map_type == 5) { //history
date1 = new Date(document.getElementById("ddate").value);
date2 = new Date(document.getElementById('to_date').value);
days_count = 1 + Math.ceil(Math.abs(date1 - date2) / (1000 * 60 * 60 * 24));
stretch_by = Math.ceil(1000 / days_count);
if (stretch_by > 50){
stretch_by = 50;
}
if (Canvas1.height != days_count * stretch_by){
Canvas1.height = days_count * stretch_by;
resize(UniversalChart);
}
}
else {
const formData = new URLSearchParams();
formData.append('function', "request_deployment_map_new");
formData.append('token', token);
formData.append('user_name', user_name);
formData.append('date', ddate);
formData.append('deployment_id', deployment_id);
formData.append('map_type', map_type);
data = await SubmitForm(formData);
if (data.status !== "200 OK") {
alert('Bad response from API!');
return;
}
//return;
maps_dates = data["maps_dates"];
map_type = data["map_type"];
proximity = data["proximity"];
device_count = data["device_count"];
if (maps_dates.length > 0) {
locations_map = data["locations_desc_map"];
var checkmarks_string = data["checkmarks"];
var devices_count = data["device_count"];
document.getElementById("checkmarks").innerHTML = checkmarks_string;
document.getElementById("devices_count").value = devices_count;
//Canvas1.height = devices_count * 70;
if(devices_count > 0) {
positions = proximity; //.split(",");
}
if(proximity[0][0] < 200){
if (Canvas1.height != devices_count * 70){
Canvas1.height = devices_count * 70;
resize(UniversalChart);
}
}
else{
if(map_type < 2){
if (Canvas1.height != devices_count * 150){
Canvas1.height = devices_count * 150;
resize(UniversalChart);
}
}
else if (map_type == 2){
if (Canvas1.height != devices_count * 5 * 19){
Canvas1.height = devices_count * 5 * 19;
resize(UniversalChart);
}
}
else{
if (Canvas1.height != devices_count * 70){
Canvas1.height = devices_count * 70;
resize(UniversalChart);
}
}
}
PrepareChart(devices_count);
}
}
group_by = document.getElementById("GroupBy").value;
re_create = document.getElementById("rcr-check").checked;
radar_part = document.getElementById("RadarPart").value;
map_type = document.getElementById("map_type").value;
bw = document.getElementById("bw-check").checked;
//if (Canvas1.height != devices_count * 70)
// Canvas1.height = devices_count * 70;
//image_address1 = '?function=get_image_file&deployment='+deployment+"&date="+ddate+"&re_create="+re_create+"&group_by="+group_by+"&user="+user+"&key="+key+"&" + new Date().getTime();
//image_address1 = map_server + '?function=get_image_file&deployment='+deployment+"&beneficiary="+beneficiary+"&date="+ddate+"&re_create="+re_create+"&group_by="+group_by+"&user="+user+"&key="+key+"&token="+token+"&signature="+signature+"&" + new Date().getTime();
zmap_type = document.getElementById("zmap_type").value;
if (zmap_type == "none") {
if (map_type < 2) {
image_address1 = api_url + '/api?name=get_image_file&deployment_id='+deployment_id+
"&radar_part="+radar_part+
"&date="+ddate+
"&re_create="+re_create+
"&group_by="+group_by+
"&user_name="+user_name+
"&token="+token+
"&map_type="+map_type+
"&bw="+bw+
"&unique_identifier="+unique_identifier+
"&" + new Date().getTime();
}
else if (map_type == 6) { //AI locations
devices_count = document.getElementById("devices_count").value;
motion = document.getElementById("motion-check").checked;
scale_global = document.getElementById("global-check").checked;
fast = document.getElementById("fast-check").checked;
filter = $("#filter").val();
if (Canvas1.height != devices_count * 22 * 5) //radar has following elements: present_max, stationary_max, moving_max, both_max, m0-8_max, m08_max, s2-8_max, s28_max = 22
Canvas1.height = devices_count * 22 * 5;
image_address1 = api_url + '/api?name=get_presence_map&deployment_id='+deployment_id+"&date="+ddate+
"&re_create="+re_create+"&bw="+bw+"&motion="+motion+"&scale_global="+scale_global+
"&map_type="+map_type+"&user_name="+user_name+"&fast="+fast+"&filter="+filter+"&" +"&token="+token+"&" + new Date().getTime();
}
else {
devices_count = document.getElementById("devices_count").value;
motion = document.getElementById("motion-check").checked;
scale_global = document.getElementById("global-check").checked;
fast = document.getElementById("fast-check").checked;
filter = $("#filter").val();
if (map_type == 4) { //Collapsed
if (Canvas1.height != 50)
Canvas1.height = 50;
}
else if(map_type == 5){ //History
//done above
}
else{ //Analog or Digital radar
//traces m0_max-m8_max, m08_max, s2_max-s8_max, s28_max, s28_min
traces_count = 19;
if (Canvas1.height != devices_count * traces_count * 5) //radar has following elements: present_max, stationary_max, moving_max, both_max, m0-8_max, m08_max, s2-8_max, s28_max = 22
Canvas1.height = devices_count * traces_count * 5;
}
if(map_type == 5){ //History
to_date = document.getElementById('to_date').value;
now_date = document.getElementById('to_date').options[0].value;
image_address1 = api_url + '/api?name=get_full_location_map&deployment_id='+deployment_id+"&date="+ddate+
"&re_create="+re_create+"&bw="+bw+"&motion="+motion+"&scale_global="+scale_global+
"&map_type="+map_type+"&user_name="+user_name+"&fast="+fast+"&filter="+filter+"&" +"&token="+token+"&to_date="+to_date +"&now_date="+now_date +"&"+ new Date().getTime();
}
else {
image_address1 = api_url + '/api?name=get_full_location_map&deployment_id='+deployment_id+"&date="+ddate+
"&re_create="+re_create+"&bw="+bw+"&motion="+motion+"&scale_global="+scale_global+
"&map_type="+map_type+"&user_name="+user_name+"&fast="+fast+"&filter="+filter+"&" +"&token="+token+"&" + new Date().getTime();
}
}
img1.src = image_address1;
}
else {
GetZGraph();
}
}
function Date_changed(){
ShowHistoryMap();
}
async function Calibrate() {
deployment_id = document.getElementById("Deployments").value;
ddate = document.getElementById("ddate").value;
stdev_range = document.getElementById("filter").value;
if(deployment_id == "0") return;
const formData = new URLSearchParams();
formData.append('function', "calibrate_thresholds");
formData.append('token', token);
formData.append('user_name', user_name);
formData.append('date', ddate);
formData.append('stdev_range', stdev_range);
formData.append('deployment_id', deployment_id);
// data = await SubmitForm(formData);
// if (data.status !== "200 OK") {
// alert('Bad response from API!');
// return;
// }
}
function HideAndEmptyAllSeries(){
if (!UniversalChart || !UniversalChart.series || !UniversalChart.series.items) {
console.error("Chart not properly initialized for hiding series");
return;
}
series_count = UniversalChart.series.items.length;
for (var d = 0; d <series_count; d++) { //series index
var s = UniversalChart.series.items[d];
s.data.x = [];
s.data.values = [];
s.visible = false;
//UniversalChart.draw();
}
UniversalChart.draw();
}
async function GetZGraph() {
console.log("presence_graphs:", presence_graphs);
deployment_id = document.getElementById("Deployments").value;
ddate = document.getElementById("ddate").value;
to_date = document.getElementById("to_date").value;
filter = document.getElementById("filter").value;
data_type = document.getElementById("zmap_type").value;
if(deployment_id == "0") return;
timee = Date.now();
const formData = new URLSearchParams();
formData.append('function', "get_presence_data");
formData.append('user_name', user_name);
formData.append('token', token);
formData.append('deployment_id', deployment_id);
formData.append('date', ddate);
formData.append('to_date', to_date);
formData.append('filter', filter);
formData.append('time', timee);
formData.append('data_type', data_type);
if (document.getElementById("rcr-check").checked){
formData.append('refresh', 1);
}
else{
formData.append('refresh', 0);
}
data = await SubmitForm(formData);
if (data.status !== "200 OK") {
alert('Bad response from API!');
return;
}
presence = data.presence;
raw = data.raw;
z_graph = data.z_graph;
start_epoch = data.time_start;
time_zone_st = data.time_zone_st;
well_ids = data.well_ids;
devices_count = well_ids.length
//Since all_slices is
devices_list = data.devices_list;
zmap_type = document.getElementById("zmap_type").value; //None, all, raw, presence, z-graph
if (zmap_type == "none") return;
PrepareChart(devices_count);
//PreparePresenceChart(data, zmap_type);
DisplayPresence(data, zmap_type);
console.log("API returned data:", data);
console.log("Series indexes:", series_indexes);
// Define the function to draw the zero line
function drawZeroLine() {
var ctx = UniversalChart.canvas.getContext("2d");
// Calculate y position for value 0
var y = UniversalChart.axes.left.calc(0);
// Get x coordinates (full width of chart plotting area)
var x1 = UniversalChart.axes.bottom.startPos;
var x2 = UniversalChart.axes.bottom.endPos;
// Save current context state
ctx.save();
// Set line style
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
// Draw the line
ctx.beginPath();
ctx.moveTo(x1, y);
ctx.lineTo(x2, y);
ctx.stroke();
// Restore context state
ctx.restore();
}
// Store the original draw function
var originalDraw = UniversalChart.draw;
// Override the draw function
UniversalChart.draw = function() {
// Call the original draw function first
originalDraw.apply(this, arguments);
// Then draw our zero line on top
drawZeroLine();
};
// Force an initial redraw to show the line
UniversalChart.draw();
}
function HideAllSeries(){
series_count = UniversalChart.series.items.length;
for (var d = 0; d <series_count; d++) { //series index
var s = UniversalChart.series.items[d];
s.visible = false;
//UniversalChart.draw();
}
UniversalChart.draw();
}
function EmptyAllSeries(){
series_count = UniversalChart.series.items.length;
for (var d = 0; d <series_count; d++) { //series index
var s = UniversalChart.series.items[d];
s.data.x = [];
s.data.values = [];
}
}
// function UpdateSelections(){
// devices_count = document.getElementById("devices_count").value;
// HideAllSeries();
// var s = UniversalChart.series.items[7*devices_count];
// s.visible = document.querySelector("#der-check").checked;
// UniversalChart.draw();
// }
function UpdateSelections(){
device_id = positions[position-1][0];
if(device_id < 200){
devices_count = (UniversalChart.series.items.length-1) / 7; //derivtive was added...
for (var d = 0; d <devices_count; d++) { //device index
for (var si = 0; si < 7; si++) { //sensor index
var s = UniversalChart.series.items[7*d+si];
switch(si) {
case 0:
sensor_check = "t-check";
break;
case 1:
sensor_check = "h-check";
break;
case 2:
sensor_check = "p-check";
break;
case 3:
sensor_check = "c-check";
break;
case 4:
sensor_check = "v-check";
break;
case 5:
sensor_check = "l-check";
break;
case 6:
sensor_check = "r-check";
break;
}
device_check = "device_check"+(d).toString();
//console.log(document.getElementById("checkmarks").innerHTML);
//console.log(device_check);
//console.log(document.querySelector(sensor_check).checked);
//console.log(document.querySelector("#"+device_check).checked);
if (document.getElementById(sensor_check).checked == true && document.getElementById(device_check).checked == true) {
s.visible = true;
//s.format.fill = s.format.oldFill;
}
else {
s.visible = false;
//s.format.oldFill = s.format.fill;
//s.format.fill == ""
}
}
}
//var s = UniversalChart.series.items[7*devices_count];
//s.visible = document.getElementById("der-check").checked;
}
else{
devices_count = (UniversalChart.series.items.length) / 15; //derivtive was added...
for (var d = 0; d <devices_count; d++) { //device index
for (var si = 0; si < 15; si++) { //sensor index
var s = UniversalChart.series.items[15*d+si];
switch(si) {
case 0:
sensor_check = "t-check";
break;
case 1:
sensor_check = "h-check";
break;
case 2:
sensor_check = "p-check";
break;
case 3:
sensor_check = "l-check";
break;
case 4:
sensor_check = "r-check";
break;
case 5:
sensor_check = "v0-check";
break;
case 6:
sensor_check = "v1-check";
break;
case 7:
sensor_check = "v2-check";
break;
case 8:
sensor_check = "v3-check";
break;
case 9:
sensor_check = "v4-check";
break;
case 10:
sensor_check = "v5-check";
break;
case 11:
sensor_check = "v6-check";
break;
case 12:
sensor_check = "v7-check";
break;
case 13:
sensor_check = "v8-check";
break;
case 14:
sensor_check = "v9-check";
break;
}
device_check = "device_check"+(d).toString();
//console.log(document.getElementById("checkmarks").innerHTML);
//console.log(device_check);
//console.log(document.querySelector(sensor_check).checked);
//console.log(document.querySelector("#"+device_check).checked);
if (document.getElementById(sensor_check).checked == true && document.getElementById(device_check).checked == true) {
s.visible = true;
//s.format.fill = s.format.oldFill;
}
else {
s.visible = false;
//s.format.oldFill = s.format.fill;
//s.format.fill == ""
}
}
}
//var s = UniversalChart.series.items[7*devices_count];
//s.visible = document.querySelector("#der-check").checked;
}
UniversalChart.draw();
}
function GetTimeRange(time_period) {
for (const [key, value] of Object.entries(time_ranges)) {
console.log(key, value);
if(time_period < parseInt(key)) return(value);
}
return("1H");
}
function RequestDeployments() {
timee = Date.now();
var obj = {
function: "request_deployments_new",
signature:signature,
user_name:user_name,
token:token,
ps:key
};
var json = JSON.stringify(obj);
sendToBackend("/wellget", json);
}
function RequestData(MAC, sensor, only_sensor) {
timee = Date.now();
//Lets delete previous series content
switch(sensor) {
case "temperature":
series_index = 0;
var series = UniversalChart.series.items[series_index];
series.data.values = [];
series.data.x = [];
if (only_sensor) {
series_0.data.values = [];
series_0.data.x = [];
t_series.data.values = [];
t_series.data.x = [];
}
break;
case "humidity":
series_index = 1;
var series = UniversalChart.series.items[series_index];
series.data.values = [];
series.data.x = [];
if (only_sensor) {
series_1.data.values = [];
series_1.data.x = [];
h_series.data.values = [];
h_series.data.x = [];
}
break;
case "pressure":
series_index = 2;
var series = UniversalChart.series.items[series_index];
series.data.values = [];
series.data.x = [];
if (only_sensor) {
series_2.data.values = [];
series_2.data.x = [];
p_series.data.values = [];
p_series.data.x = [];
}
break;
case "co2":
series_index = 3;
var series = UniversalChart.series.items[series_index];
series.data.values = [];
series.data.x = [];
if (only_sensor) {
series_3.data.values = [];
series_3.data.x = [];
c_series.data.values = [];
c_series.data.x = [];
}
break;
case "voc":
series_index = 4;
var series = UniversalChart.series.items[series_index];
series.data.values = [];
series.data.x = [];
if (only_sensor) {
series_4.data.values = [];
series_4.data.x = [];
v_series.data.values = [];
v_series.data.x = [];
}
break;
case "light":
series_index = 5;
var series = UniversalChart.series.items[series_index];
series.data.values = [];
series.data.x = [];
if (only_sensor) {
series_5.data.values = [];
series_5.data.x = [];
l_series.data.values = [];
l_series.data.x = [];
}
break;
case "radar":
series_index = 6;
var series = UniversalChart.series.items[series_index];
series.data.values = [];
series.data.x = [];
if (only_sensor) {
series_6.data.values = [];
series_6.data.x = [];
r_series.data.values = [];
r_series.data.x = [];
}
break;
}
if (time_max == 2645858117) {
time_range = "L";
}
else {
time_period = time_max - time_min;
time_range = GetTimeRange(time_period);
}
var obj = {
function: "request_data",
signature:signature,
MAC: MAC,
sensor: sensor,
time_min: time_min,
time_max: time_max,
only_sensor:only_sensor,
time_range:time_range,
time:timee,
user_name:user_name,
ps:key
};
var json = JSON.stringify(obj);
sendToBackend("/wellget", json);
}
function RequestMapSlice(devices_list, epoch_from, epoch_to) {
timee = Date.now();
radar_part = document.getElementById("RadarPart").value;
time_range = "L";
var obj = {
function: "request_slice",
signature:signature,
devices_list: devices_list,
radar_part: radar_part,
epoch_from: epoch_from,
epoch_to: epoch_to,
time:timee,
user_name:user_name,
ps:key
};
var json = JSON.stringify(obj);
sendToBackend("/wellget", json);
}
async function RequestAPIDeviceSlice(devices_details, sensors_list, epoch_from, epoch_to) {
timee = Date.now();
MAC_t = devices_details[4]
device_id = devices_details[1]
well_id = devices_details[0]
deployment_id = document.getElementById("Deployments").value;
if(deployment_id == "0") return;
const formData = new URLSearchParams();
formData.append('user_name', user_name);
formData.append('token', token);
formData.append('function', "request_device_slice");
formData.append('deployment_id', deployment_id);
formData.append('epoch_from', epoch_from);
formData.append('epoch_to', epoch_to);
formData.append('device_id', device_id);
formData.append('well_id', well_id);
formData.append('MAC', MAC_t);
formData.append('sensors_list', sensors_list);
formData.append('radar_part', radar_part);
data = await SubmitForm(formData);
if (data.status !== "200 OK") {
alert('Bad response from API!');
return;
}
all_slices = data.all_slices;
device_properties = data.proximity.filter(entry => entry[1] === device_id)[0];
PrepareDeviceChart(device_properties);
MAC = data.MAC;
time_zone_st = data.time_zone_st;
//Since all_slices is
//device_id = data.well_id;
devices_count = parseInt(Canvas1.height/150);
console.log("Chart initialization state:", {
chart: !!UniversalChart,
axes: UniversalChart ? !!UniversalChart.axes : false,
series: UniversalChart ? !!UniversalChart.series : false,
panels: UniversalChart ? !!UniversalChart.panels : false
});
DisplayAllSlices(MAC, well_id);
//DisplaySingleSlice(time_zone_st);
// const ddateSelect = document.getElementById("ddate");
// const isTopMost = ddateSelect.selectedIndex === 0;
// //MAC = devices_list[0][4]
// if (isTopMost){
valid_macs = ["/"+MAC_t];
// }
// else {
// valid_macs = [];
// }
displaying_sensor = sensor_list;
}
async function ReadSensorWholeRange() {
}
async function RequestSingleSlice(devices_list, sensor_list, ddate, date_to, ctrl_key_state, alt_key_state) {
timee = Date.now();
time_range = "L";
radar_part = document.getElementById("RadarPart").value;
if (alt_key_state == 1) {
data_type = "RL"; //Raw line
}
else {
data_type = "ML"; //Minutes line
}
MAC_t = devices_list[0][4]
device_id = devices_list[0][1]
deployment_id = document.getElementById("Deployments").value;
if(deployment_id == "0") return;
const formData = new URLSearchParams();
formData.append('function', "request_single_slice");
formData.append('token', token);
formData.append('user_name', user_name);
formData.append('date', ddate);
formData.append('to_date', to_date);
formData.append('devices_list', devices_list);
formData.append('deployment_id', deployment_id);
formData.append('sensor_list', sensor_list);
formData.append('ctrl_key_state', ctrl_key_state);
formData.append('alt_key_state', alt_key_state);
formData.append('radar_part', radar_part);
formData.append('time', timee);
formData.append('data_type', data_type);
data = await SubmitForm(formData);
if (data.status !== "200 OK") {
alert('Bad response from API!');
return;
}
all_slices = data.all_slices;
time_zone_st = data.time_zone_st;
//Since all_slices is
device_id = data.well_id;
devices_list = data.devices_list;
if(device_id<200)
devices_count = parseInt(Canvas1.height/70);
else
devices_count = parseInt(Canvas1.height/150);
PrepareChart(devices_count);
console.log("Chart initialization state:", {
chart: !!UniversalChart,
axes: UniversalChart ? !!UniversalChart.axes : false,
series: UniversalChart ? !!UniversalChart.series : false,
panels: UniversalChart ? !!UniversalChart.panels : false
});
DisplaySingleSlice(time_zone_st);
const ddateSelect = document.getElementById("ddate");
const isTopMost = ddateSelect.selectedIndex === 0;
//MAC = devices_list[0][4]
if (isTopMost){
valid_macs = ["/"+MAC_t];
}
else {
valid_macs = [];
}
displaying_sensor = sensor_list[0];
}
async function RequestSingleRadarSlice(devices_list, sensor_index_list, ddate, ctrl_key_state, alt_key_state, sensor_type) {
timee = Date.now();
time_range = "L";
radar_part = document.getElementById("RadarPart").value;
if (alt_key_state == 1) {
data_type = "RL"; //Raw line
}
else {
data_type = "ML"; //Minutes line
}
MAC_t = devices_list[0][4]
device_id = devices_list[0][1]
deployment_id = document.getElementById("Deployments").value;
if(deployment_id == "0") return;
const formData = new URLSearchParams();
formData.append('function', "request_single_radar_slice");
formData.append('token', token);
formData.append('user_name', user_name);
formData.append('date', ddate);
formData.append('devices_list', devices_list);
formData.append('deployment_id', deployment_id);
formData.append('sensor_index_list', sensor_index_list);
formData.append('ctrl_key_state', ctrl_key_state);
formData.append('alt_key_state', alt_key_state);
formData.append('time', timee);
formData.append('data_type', data_type);
data = await SubmitForm(formData);
if (data.status !== "200 OK") {
alert('Bad response from API!');
return;
}
all_slices = data.all_slices;
time_zone_st = data.time_zone_st;
//Since all_slices is
device_id = data.well_id;
devices_list = data.devices_list;
map_type = document.getElementById("map_type").value;
if (map_type == 1){
if(device_id<200)
devices_count = parseInt(Canvas1.height/70);
else
devices_count = parseInt(Canvas1.height/150);
}
else {
if(device_id<200)
devices_count = parseInt(Canvas1.height/70);
else
devices_count = parseInt(Canvas1.height/(5*19));
}
PrepareChart(devices_count);
console.log("Chart initialization state:", {
chart: !!UniversalChart,
axes: UniversalChart ? !!UniversalChart.axes : false,
series: UniversalChart ? !!UniversalChart.series : false,
panels: UniversalChart ? !!UniversalChart.panels : false
});
DisplaySingleSlice(time_zone_st);
const ddateSelect = document.getElementById("ddate");
const isTopMost = ddateSelect.selectedIndex === 0;
//MAC = devices_list[0][4]
if (isTopMost){
valid_macs = ["/"+MAC_t];
}
else {
valid_macs = [];
}
displaying_sensor = sensor_type;
}
function RequestNewData(MAC, sensor, only_sensor) {
timee = Date.now();
time_period = time_max - time_min;
time_range = GetTimeRange(time_period);
var obj = {
function: "request_data",
signature:signature,
MAC: MAC,
sensor: sensor,
time_min: time_min,
time_max: time_max,
only_sensor:only_sensor,
time_range:time_range,
time:timee,
user_name:user_name,
token:token,
ps:key
};
var json = JSON.stringify(obj);
sendToBackend("/wellget", json);
}
async function SubmitForm(formData) {
console.log(formData.toString());
const response = await fetch(api_url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
mode: 'cors',
body: formData.toString()
});
if (response.ok) {
const text = await response.text();
//console.log(text);
if(text.includes("Log-Out")) {
alert('You need to log-in again!');
}
else {
try {
data = JSON.parse(text);
return data;
}
catch {
data = {
ok: 0
}
return data;
}
}
} else {
//console.log(await response.json());
data = {
ok: 0
}
return data;
}
}
async function RequestFilteredDevices(group_id, deployment_id, location, is_fresh) {
const formData = new URLSearchParams();
formData.append('function', "request_devices");
formData.append('token', token);
formData.append('user_name', user_name);
formData.append('group_id', group_id);
formData.append('deployment_id', deployment_id);
formData.append('location', location);
formData.append('fresh', is_fresh);
data = await SubmitForm(formData);
if (data.status !== "200 OK") {
alert('Bad response from API!');
return;
}
matching_devices = data["devices"];
let topics = [];
for (i = 0; i < matching_devices.length; i++) {
mac = matching_devices[i][2];
device_id_2_location[matching_devices[i][1]] = matching_devices[i][4]
topics.push("/"+mac)
}
qos = 1;
if (client !=""){
// Subscribe to each topic individually
for (let i = 0; i < topics.length; i++) {
try {
client.subscribe(topics[i], {qos: qos});
console.log(`Subscribed to ${topics[i]} with QoS: ${qos}`);
} catch (error) {
console.error(`Error subscribing to ${topics[i]}:`, error);
}
}
}
//doc.getElementById("here_table").appendChild(table);
}
async function DeploymentChange() {
// Sample data to post
deployment_id = document.getElementById("Deployments").value;
ddate = document.getElementById("ddate").value;
if(deployment_id == "0") return;
const formData = new URLSearchParams();
formData.append('function', "request_deployment_map_new");
formData.append('token', token);
formData.append('user_name', user_name);
formData.append('date', ddate);
formData.append('deployment_id', deployment_id);
localStorage.setItem('deployment_id', deployment_id);
data = await SubmitForm(formData);
if (data.status !== "200 OK") {
alert('Bad response from API!');
return;
}
//return;
maps_dates = data["maps_dates"];
proximity = data["proximity"];
device_count = data["device_count"];
if ('vocs_scaled' in data)
vocs_scaled = data["vocs_scaled"];
if (maps_dates.length > 0) {
locations_map = data["locations_desc_map"];
var checkmarks_string = data["checkmarks"];
var devices_count = data["device_count"];
document.getElementById("checkmarks").innerHTML = checkmarks_string;
document.getElementById("devices_count").value = devices_count;
//Canvas1.height = devices_count * 70;
if(devices_count > 0) {
positions = proximity; //.split(",");
}
$("#ddate").empty();
$("#to_date").empty();
var oldSel = $("#ddate").get(0);
var oldSel1 = $("#to_date").get(0);
for (i = 0; i < maps_dates.length; i++)
{
var opt = document.createElement('option');
opt.text = maps_dates[i];
opt.value = maps_dates[i];
oldSel.add(opt, null);
var opt1 = document.createElement('option');
opt1.text = maps_dates[i];
opt1.value = maps_dates[i];
oldSel1.add(opt1, null);
}
if(proximity[0][0] < 200){
if (Canvas1.height != devices_count * 70){
Canvas1.height = devices_count * 70;
resize(UniversalChart);
}
}
else{
if (Canvas1.height != devices_count * 150){
Canvas1.height = devices_count * 150;
resize(UniversalChart);
}
}
groups = "0"; // Document.getElementById("group_id").value;
deployments = "0"; // Document.getElementById("Deployments").value;
locations = "0"; // Document.getElementById("Locations").value;
RequestFilteredDevices(groups, deployments, locations, fresh);
ShowHistoryMap();
//PrepareChart(devices_count); //that is called inside ShowHistoryMap
}
// var select = document.getElementById("Deployments");
// var selectedIndex = select.selectedIndex;
// var deployment = select.value;
// var beneficiary = select.options[selectedIndex].text;
// timee = Date.now();
// user = document.getElementById("user").value;
// key = document.getElementById("ps").value;
// token = document.getElementById("token").value;
// ddate = document.getElementById("ddate").value;
// document.getElementById("beneficiary").value = beneficiary;
// var obj = {
// function: "request_deployment_map_new",
// signature:signature,
// beneficiary:beneficiary,
// token:token,
// date:ddate,
// user:user,
// ps:key
// };
// var json = JSON.stringify(obj);
// sendToBackend("/wellget", json);
}
function sensor_changed(){
overview_sensor = document.getElementById("SensorSel").value;
//if (btn.innerText == "Set Devices") { //single
MAC = document.getElementById("MAC").value;
RequestData(MAC,overview_sensor,true);
}
/* function range_changed(){
range_sensor = document.getElementById("RangeSel").value;
epoch_ms = Date.now();
time_min = (epoch_ms-1000*range_sensor)/1000.0;
time_max = (epoch_ms)/1000;
Chart1.axes.bottom.setMinMax(1000*time_min,1000*time_max);
scroller.draw();
}*/
function showTutorial(name) {
document.myform.stage.value = name;
}
function AddToTutorial(name) {
if (document.myform.stage.value.length < 128) {
document.myform.stage.value = document.myform.stage.value + ": "+name;
}
else {
document.myform.stage.value = name;
}
}
function openFloorPlan() {
// You can change this URL to any website you want to open
window.open('https://eluxnetworks.net/shared/LayoutEditor.html', '_blank');
}
function openAnimation() {
// You can change this URL to any website you want to open
window.open('https://eluxnetworks.net/shared/LayoutAnimate1.html', '_blank');
}
</script>
</head>
<body onload="draw(); resize(UniversalChart); resizeToolBar();" onresize="resize(UniversalChart); resizeToolBar();">
<div class="helper">
<form name="myform">
<input type="text" name="stage" size="160" />
</form>
</div>
<div class="right_col" role="main">
<div class="page-title">
<div class="title_left">
<h3>Deployment History Overview<span class="smallLetters"></span></h3>
</div>
</div>
<div class="x_panel">
<div id="wrapper" >
<div id="checkmarks" display: inline-block onmouseup="UpdateSelections();">
T><input checked type="checkbox" id="t-check" value="0" onchange="UpdateSelections();"/>
H><input type="checkbox" id="h-check" value="0" onchange="UpdateSelections();"/>
P><input type="checkbox" id="p-check" value="0" onchange="UpdateSelections();" />
C><input type="checkbox" id="c-check" value="0" onchange="UpdateSelections();" />
V><input type="checkbox" id="v-check" value="0" onchange="UpdateSelections();" />
L><input type="checkbox" id="l-check" value="0" onchange="UpdateSelections();" />
R><input type="checkbox" id="r-check" value="0" onchange="UpdateSelections();" />
------ 23><input checked type="checkbox" id="device_check0" value="0" onchange="UpdateSelections();" />
26><input type="checkbox" id="device_check1" value="0" title="New Deployment (address)" onchange="UpdateSelections();" />
29><input type="checkbox" id="device_check2" value="0" onchange="UpdateSelections();" />
34><input type="checkbox" id="device_check3" value="0" onchange="UpdateSelections();" />
38> <input type="checkbox" id="device_check4" value="0" onchange="UpdateSelections();" />
38> <input type="checkbox" id="device_check5" value="0" onchange="UpdateSelections();" />
38> <input type="checkbox" id="device_check6" value="0" onchange="UpdateSelections();" />
38> <input type="checkbox" id="device_check7" value="0" onchange="UpdateSelections();" />
38> <input type="checkbox" id="device_check8" value="0" onchange="UpdateSelections();" />
38> <input type="checkbox" id="device_check9" value="0" onchange="UpdateSelections();" />
</div>
<div id="div2">
Date:
<select id="ddate" size="1" onchange="Date_changed()">
<option value="2022-4-2">4/2/2022</option>
<option value="2022-4-3">4/3/2022</option>
</select>
-------- Deployment:
<select name="Deployments" id="Deployments" onchange="DeploymentChange();" size="1">
###INSTALLS###
</select>
<button class="small-button" onclick="Date_changed()">Update</button>
<button class="small-button" onclick="DoDownload()">Download</button>
--- Export To Date:
<select id="to_date" size="1">
<option value="2022-4-2">4/2/2022</option>
<option value="2022-4-3">4/3/2022</option>
</select>
--- Consolidate By:
<select id="consolidated_by" size="1">
<option value="by_minute_rc" selected>By minute radar s28</option>
<option value="by_minute_rd">By minute radar detailed</option>
<option value="by_deca_rd">By 10 seconds radar detailed</option>
</select>
<br>
Time Range for slice:
<select id="time_range" size="1">
<option value="1D" selected>Day</option>
<option value="ALL">All Days selected</option>
<option value="D10M">-/+ 10m</option>
<option value="D30M">-/+ 30m</option>
<option value="D1H">-/+ 1 h</option>
<option value="D2H">-/+ 2 h</option>
<option value="D4H">-/+ 4 h</option>
</select>
-------- Group by:
<select name="GroupBy" id="GroupBy" onchange="Date_changed();" size="1">
<option value="sensortype" selected>Sensor Type</option>
<option value="devicenumber">Device #</option>
</select>
-------- Radar part:
<select name="RadarPart" id="RadarPart" size="1">
<option value="absent">Absent</option>
<option value="moving">Moving</option>
<option value="stationary">Stationary</option>
<option value="both">Both</option>
<option value="m0">M0</option>
<option value="m1">M1</option>
<option value="m2">M2</option>
<option value="m3">M3</option>
<option value="m4">M4</option>
<option value="m5">M5</option>
<option value="m6">M6</option>
<option value="m7">M7</option>
<option value="m8">M8</option>
<option value="s2">S2</option>
<option value="s3">S3</option>
<option value="s4">S4</option>
<option value="s5">S5</option>
<option value="s6">S6</option>
<option value="s7">S7</option>
<option value="s8">S8</option>
<option value="s28" selected>S2-8</option>
</select>
-------- Map Type:
<select name="map_type" id="map_type" size="1">
<option value="1">All sensors</option>
<option value="2">Radar Only</option>
<option value="4">Locations</option>
<option value="5">History</option>
<option value="6">AI locations</option>
</select>
-----Global Max <input type="checkbox" id="global-check" value="0" onchange="Date_changed();"/>
-----B/W-<input type="checkbox" id="bw-check" value="0" onchange="Date_changed();"/>
-----Motion-<input type="checkbox" id="motion-check" value="0" onchange="Date_changed();"/>
-----Fast-<input type="checkbox" id="fast-check" value="0" checked />
-----Filter-<input type="text" id="filter" name="filter" value="6" style="width: 40px; text-align: center;">
</div>
<br>
Equilize to 100%<input type="checkbox" id="equilize-check" value="0" onchange="UpdateSelections();" />
. Derivative<input type="checkbox" id="der-check" value="0" onchange="UpdateSelections();" />
. Re-Create<input type="checkbox" id="rcr-check" />
<button class="small-button" onclick="Calibrate()">Calibrate</button>
<button class="small-button" onclick="openFloorPlan()">Floor Plan</button>
<button class="small-button" onclick="openAnimation()">Animate</button>
-------- Presence Type:
<select name="zmap_type" id="zmap_type" size="1">
<option value="none">None</option>
<option value="all">All</option>
<option value="raw">RAW</option>
<option value="presence">Presence</option>
<option value="z-graph">Z-Graph</option>
<option value="multiple">Multiple</option>
</select>
<div class="clearfix"></div>
</div>
<div class="x_content">
<canvas id="Canvas1" width="1440px" height="350px" style="border:1px solid #000000; z-index:1" title="this will be displayed as a tooltip">
Your browser does not support the HTML5 canvas tag.
</canvas>
<br>
<!---
<canvas id="Canvas2" width="1440px" height="10px" style="border:1px solid #000000; z-index:1">
Your browser does not support the HTML5 canvas tag.
</canvas>
--->
<div hidden style="position:fixed; top:360px; left:1500px">
<div style="background-color:black;color:white;padding:0px; height: 16px; width: 120px;">
UNKNOWN
</div>
<div style="background-color:rgb(0,255,0);color:black;padding:0px; height: 16px; width: 120px;">
BEDROOM
</div>
<div style="background-color:rgb(0,0,255);color:white;padding:0px; height: 16px; width: 120px;">
BATHROOM 1
</div>
<div style="background-color:rgb(0,255,255);color:black;padding:0px; height: 16px; width: 120px;">
BATHROOM 2
</div>
<div style="background-color:rgb(255,255,0);color:black;padding:0px; height: 16px; width: 120px;">
OFFICE 1
</div>
<div style="background-color:rgb(255,174,0);color:black;padding:0px; height: 16px; width: 120px;">
OFFICE 2
</div>
<div style="background-color:rgb(255,0,0);color:black;padding:0px; height: 16px; width: 120px;">
KITCHEN
</div>
<div style="background-color:rgb(255,146,182);color:black;padding:0px; height: 16px; width: 120px;">
DINING ROOM
</div>
<div style="background-color:rgb(255,0,255);color:black;padding:0px; height: 16px; width: 120px;">
LIVING ROOM
</div>
<div style="background-color:rgb(128,128,128);color:black;padding:0px; height: 16px; width: 120px;">
HALLWAY
</div>
<div style="background-color:rgb(172,124,22);color:black;padding:0px; height: 16px; width: 120px;">
GARAGE
</div>
</div>
<!---
<div id="PolarChart" style="position:fixed; bottom:0px; left:300px">
<canvas id="polar_canvas" height="450px" width="450px">>
This browser does not seem to support HTML5 Canvas.
</canvas>
</div>
--->
<div id= "ChartU" style="position:fixed; top:550px; left:0px; height:350px;">
<br><canvas id="canvasU" width="100%" height="100%">
This browser does not seem to support HTML5 Canvas.
</canvas>
<br/>
</div>
<br/>
<span id="data"/>
</div>
</div>
<div class="clearfix"></div>
</div>
<input type="hidden" id="MAC" value="###MAC###" size="4">
<input type="hidden" id="beneficiary" value="###BENEFICIARY###" size="32">
<input type="hidden" id="privilidges" value="###PRIVILIDGES###" size="4">
<input type="hidden" id="devices_count" value="5" size="4">
<script src="https://eluxnetworks.net/js/3rd_party/jquery/js/jquery-1.7.1.min.js"></script>
<!-- Custom Theme Scripts -->
</body>
</html>