Commit 86bff050 authored by Sven Schneider's avatar Sven Schneider
Browse files

added aggregation method into appCharts.js

parent 02bd3700
Showing with 770 additions and 614 deletions
+770 -614
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="description" content="" /> <meta name="description" content="" />
<meta name="author" content="" /> <meta name="author" content="" />
<title>Dashboard - iCity Bosch</title> <title>Dashboard - iCity Bosch</title>
<link href="css/styles.css" rel="stylesheet" /> <link href="css/styles.css" rel="stylesheet" />
<link <link href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css" rel="stylesheet" crossorigin="anonymous" />
href="https://cdn.datatables.net/1.10.20/css/dataTables.bootstrap4.min.css"
rel="stylesheet"
crossorigin="anonymous"
/>
<!-- Font Awesome icons --> <!-- Font Awesome icons -->
<script <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/js/all.min.js" crossorigin="anonymous"></script>
src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/js/all.min.js"
crossorigin="anonymous"
></script>
<!-- Axios --> <!-- Axios -->
<!-- <script src="./node_modules/axios/dist/axios.min.js"></script> --> <!-- <script src="./node_modules/axios/dist/axios.min.js"></script> -->
...@@ -46,122 +37,100 @@ ...@@ -46,122 +37,100 @@
<!-- Cesium lib --> <!-- Cesium lib -->
<script src="https://cesium.com/downloads/cesiumjs/releases/1.48/Build/Cesium/Cesium.js"></script> <script src="https://cesium.com/downloads/cesiumjs/releases/1.48/Build/Cesium/Cesium.js"></script>
<link <link href="https://cesium.com/downloads/cesiumjs/releases/1.48/Build/Cesium/Widgets/widgets.css" rel="stylesheet" />
href="https://cesium.com/downloads/cesiumjs/releases/1.48/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"
/>
<!-- Bootstrap dashboard template --> <!-- Bootstrap dashboard template -->
<script <script defer src="https://code.jquery.com/jquery-3.5.1.slim.min.js" crossorigin="anonymous"></script>
defer <script defer src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
crossorigin="anonymous"
></script>
<script
defer
src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js"
crossorigin="anonymous"
></script>
<script defer src="js/thirdparty/scripts.js"></script> <script defer src="js/thirdparty/scripts.js"></script>
<!-- <!--
Custom JS --> Custom JS -->
<script defer type="module" src="js/appCesium.js"></script> <script defer type="module" src="js/appCesium.js"></script>
<script defer type="module" src="js/appChart.js"></script> <script defer type="module" src="js/appChart.js"></script>
</head> </head>
<body class="sb-nav-fixed">
<body class="sb-nav-fixed">
<nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark"> <nav class="sb-topnav navbar navbar-expand navbar-dark bg-dark">
<a class="navbar-brand" href="index.html">iCity Bosch Dashboard</a> <a class="navbar-brand" href="index.html">iCity Bosch Dashboard</a>
<button <button class="btn btn-link btn-sm order-1 order-lg-0" id="sidebarToggle" href="#">
class="btn btn-link btn-sm order-1 order-lg-0"
id="sidebarToggle"
href="#"
>
<i class="fas fa-bars"></i> <i class="fas fa-bars"></i>
</button> </button>
</nav> </nav>
<div id="layoutSidenav"> <div id="layoutSidenav">
<div id="layoutSidenav_nav"> <div id="layoutSidenav_nav">
<nav class="sb-sidenav accordion sb-sidenav-dark" id="sidenavAccordion"> <nav class="sb-sidenav accordion sb-sidenav-dark" id="sidenavAccordion">
<div class="sb-sidenav-menu"> <div class="sb-sidenav-menu">
<div class="nav"> <div class="nav">
<div class="sb-sidenav-menu-heading">Core</div> <div class="sb-sidenav-menu-heading">Core</div>
<a class="nav-link" href="index.html"> <a class="nav-link" href="index.html">
<div class="sb-nav-link-icon"> <div class="sb-nav-link-icon">
<i class="fas fa-tachometer-alt"></i> <i class="fas fa-tachometer-alt"></i>
</div>
Dashboard
</a>
</div>
</div> </div>
Dashboard </nav>
</a> </div>
</div> <div id="layoutSidenav_content">
</div> <main>
</nav> <div class="container-fluid">
</div> <h1 class="mt-4">Dashboard</h1>
<div id="layoutSidenav_content"> <ol class="breadcrumb mb-4">
<main> <li class="breadcrumb-item active">Dashboard</li>
<div class="container-fluid"> </ol>
<h1 class="mt-4">Dashboard</h1>
<ol class="breadcrumb mb-4">
<li class="breadcrumb-item active">Dashboard</li>
</ol>
<div class="row"> <div class="row">
<div class="col-xl-12"> <div class="col-xl-12">
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header"> <div class="card-header">
<i class="fas fa-globe mr-1"></i> <i class="fas fa-globe mr-1"></i> 3D Visualization
3D Visualization </div>
</div> <div class="card-body">
<div class="card-body"> <div id="cesiumGlobeContainer" width="100%" height="40">
<div </div>
id="cesiumGlobeContainer" </div>
width="100%" </div>
height="40" </div>
></div> </div>
</div> <div class="row">
<div class="col-xl-6">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-chart-line mr-1"></i> Line Chart Example
</div>
<div class="card-body">
<div id="chart-line" width="100%" height="40"></div>
</div>
</div>
</div>
<div class="col-xl-6">
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-chart-area mr-1"></i> Area Chart Example
</div>
<div class="card-body">
<div id="chart-heatmap" width="100%" height="40"></div>
</div>
</div>
</div>
</div>
</div> </div>
</div> </main>
</div> <footer class="py-4 bg-light mt-auto">
<div class="row"> <div class="container-fluid">
<div class="col-xl-6"> <div class="d-flex align-items-center justify-content-between small">
<div class="card mb-4"> <div class="text-muted">Copyright &copy; HfT Stuttgart 2021</div>
<div class="card-header"> <div>
<i class="fas fa-chart-line mr-1"></i> <a href="#">Privacy Policy</a> &middot;
Line Chart Example <a href="#">Terms &amp; Conditions</a>
</div> </div>
<div class="card-body"> </div>
<div id="chart-line" width="100%" height="40"></div>
</div>
</div> </div>
</div> </footer>
<div class="col-xl-6"> </div>
<div class="card mb-4">
<div class="card-header">
<i class="fas fa-chart-area mr-1"></i>
Area Chart Example
</div>
<div class="card-body">
<div id="chart-heatmap" width="100%" height="40"></div>
</div>
</div>
</div>
</div>
</div>
</main>
<footer class="py-4 bg-light mt-auto">
<div class="container-fluid">
<div
class="d-flex align-items-center justify-content-between small"
>
<div class="text-muted">Copyright &copy; HfT Stuttgart 2021</div>
<div>
<a href="#">Privacy Policy</a>
&middot;
<a href="#">Terms &amp; Conditions</a>
</div>
</div>
</div>
</footer>
</div>
</div> </div>
</body> </body>
</html>
</html>
\ No newline at end of file
...@@ -2,26 +2,27 @@ ...@@ -2,26 +2,27 @@
// Functions // Functions
import { import {
getDatastreamIdFromBuildingNumber, getDatastreamIdFromBuildingNumber,
getObservationsUrl, getObservationsUrl,
createTemporalFilterString, createTemporalFilterString,
formatSTAResponseForHeatMap, formatSTAResponseForHeatMap,
drawHeatMapHC, drawHeatMapHC,
formatSTAResponseForLineChart, formatSTAResponseForLineChart,
drawLineChartHC, drawLineChartHC,
followNextLink, followNextLink,
aggregateResponse,
} from "./appChart.js"; } from "./appChart.js";
// Constants // Constants
import { import {
BASE_URL, BASE_URL,
PARAM_RESULT_FORMAT, PARAM_RESULT_FORMAT,
PARAM_ORDER_BY, PARAM_ORDER_BY,
PARAM_SELECT, PARAM_SELECT,
} from "./appChart.js"; } from "./appChart.js";
Cesium.Ion.defaultAccessToken = Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyODgxYzJlNi1kNDZiLTQ3ZmQtYmUxYy0yMWI0OGM3NDA5MzAiLCJpZCI6NDczOSwic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTU0MTUyMzU0MX0.shj2hM3pvsvcmE_wMb2aBDuk_cKWmFmbolltInGImwU"; "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyODgxYzJlNi1kNDZiLTQ3ZmQtYmUxYy0yMWI0OGM3NDA5MzAiLCJpZCI6NDczOSwic2NvcGVzIjpbImFzciIsImdjIl0sImlhdCI6MTU0MTUyMzU0MX0.shj2hM3pvsvcmE_wMb2aBDuk_cKWmFmbolltInGImwU";
// Flag to determine models that will be loaded // Flag to determine models that will be loaded
// Set to `true` or `false` // Set to `true` or `false`
...@@ -29,10 +30,10 @@ const LOAD_DETAILED_BLDG225 = false; ...@@ -29,10 +30,10 @@ const LOAD_DETAILED_BLDG225 = false;
// Global variable // Global variable
const viewer = new Cesium.Viewer("cesiumGlobeContainer", { const viewer = new Cesium.Viewer("cesiumGlobeContainer", {
scene3DOnly: true, scene3DOnly: true,
imageryProvider: Cesium.createOpenStreetMapImageryProvider({ imageryProvider: Cesium.createOpenStreetMapImageryProvider({
url: "https://a.tile.openstreetmap.org/", url: "https://a.tile.openstreetmap.org/",
}), }),
}); });
/** /**
...@@ -40,26 +41,25 @@ const viewer = new Cesium.Viewer("cesiumGlobeContainer", { ...@@ -40,26 +41,25 @@ const viewer = new Cesium.Viewer("cesiumGlobeContainer", {
* @param {String} urlTiles URL to the 3DTiles to be loaded * @param {String} urlTiles URL to the 3DTiles to be loaded
* @returns {undefined} undefined * @returns {undefined} undefined
*/ */
const loadTiles = function (urlTiles) { const loadTiles = function(urlTiles) {
const tileset = new Cesium.Cesium3DTileset({ const tileset = new Cesium.Cesium3DTileset({
url: urlTiles, url: urlTiles,
}); });
viewer.scene.primitives.add(tileset); viewer.scene.primitives.add(tileset);
tileset.readyPromise.then(function () { tileset.readyPromise.then(function() {
viewer viewer
.zoomTo( .zoomTo(
tileset, tileset,
new Cesium.HeadingPitchRange( new Cesium.HeadingPitchRange(
0.0, 0.0, -0.5,
-0.5, tileset.boundingSphere.radius / 0.5
tileset.boundingSphere.radius / 0.5 )
) )
) .otherwise(function(err) {
.otherwise(function (err) { throw err;
throw err; });
}); });
});
}; };
/** /**
...@@ -67,12 +67,12 @@ const loadTiles = function (urlTiles) { ...@@ -67,12 +67,12 @@ const loadTiles = function (urlTiles) {
* @param{*} * @param{*}
* @returns {undefined} undefined * @returns {undefined} undefined
*/ */
const loadNonDetailed = function () { const loadNonDetailed = function() {
// Paths to data sources // Paths to data sources
const URL_3DTILES = "data_3d/3dtiles/1_full/tileset.json"; const URL_3DTILES = "data_3d/3dtiles/1_full/tileset.json";
// Tileset with all buildings // Tileset with all buildings
loadTiles(URL_3DTILES); loadTiles(URL_3DTILES);
}; };
/** /**
...@@ -81,19 +81,19 @@ const loadNonDetailed = function () { ...@@ -81,19 +81,19 @@ const loadNonDetailed = function () {
* @param {String} gltfId Name of the glTF model file without the extension i.e. exclude the `.gltf` suffix * @param {String} gltfId Name of the glTF model file without the extension i.e. exclude the `.gltf` suffix
* @returns {undefined} undefined * @returns {undefined} undefined
*/ */
const gltfLoad = function (gltfUrl, gltfId) { const gltfLoad = function(gltfUrl, gltfId) {
const modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame( const modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(9.083385, 48.881342, 0) Cesium.Cartesian3.fromDegrees(9.083385, 48.881342, 0)
); );
viewer.scene.primitives.add( viewer.scene.primitives.add(
Cesium.Model.fromGltf({ Cesium.Model.fromGltf({
url: `${gltfUrl}/${gltfId}.gltf`, url: `${gltfUrl}/${gltfId}.gltf`,
modelMatrix: modelMatrix, modelMatrix: modelMatrix,
scale: 0.0254, scale: 0.0254,
allowPicking: true, allowPicking: true,
}) })
); );
}; };
/** /**
...@@ -101,64 +101,64 @@ const gltfLoad = function (gltfUrl, gltfId) { ...@@ -101,64 +101,64 @@ const gltfLoad = function (gltfUrl, gltfId) {
* @param{*} * @param{*}
* @returns {undefined} undefined * @returns {undefined} undefined
*/ */
const loadDetailed = function () { const loadDetailed = function() {
// Paths to data sources // Paths to data sources
const URL_3DTILES = "data_3d/3dtiles/2_partial/tileset.json"; const URL_3DTILES = "data_3d/3dtiles/2_partial/tileset.json";
const URL_GLTF = "data_3d/gltf"; const URL_GLTF = "data_3d/gltf";
// Tileset without building 225 // Tileset without building 225
loadTiles(URL_3DTILES); loadTiles(URL_3DTILES);
// Load Building 225 // Load Building 225
gltfLoad(URL_GLTF, "bosch_si225_3"); gltfLoad(URL_GLTF, "bosch_si225_3");
// Load sensors in Building 225 // Load sensors in Building 225
const gltfArray = [ const gltfArray = [
"sensor_013", "sensor_013",
"sensor_023", "sensor_023",
"sensor_033", "sensor_033",
"sensor_053", "sensor_053",
"sensor_063", "sensor_063",
"sensor_073", "sensor_073",
"sensor_083", "sensor_083",
"sensor_093", "sensor_093",
"sensor_103", "sensor_103",
"sensor_113", "sensor_113",
"sensor_123", "sensor_123",
"sensor_133", "sensor_133",
"sensor_143", "sensor_143",
"sensor_153", "sensor_153",
"sensor_163", "sensor_163",
"sensor_173", "sensor_173",
"sensor_183", "sensor_183",
"sensor_213", "sensor_213",
"sensor_223", "sensor_223",
"sensor_233", "sensor_233",
"sensor_253", "sensor_253",
"sensor_263", "sensor_263",
"sensor_273", "sensor_273",
"sensor_283", "sensor_283",
"sensor_293", "sensor_293",
"sensor_303", "sensor_303",
"sensor_313", "sensor_313",
"sensor_323", "sensor_323",
"sensor_333", "sensor_333",
"sensor_343", "sensor_343",
"sensor_353", "sensor_353",
"sensor_363", "sensor_363",
"sensor_373", "sensor_373",
"sensor_383_v2", "sensor_383_v2",
]; ];
gltfArray.forEach((sensor) => gltfLoad(URL_GLTF, sensor)); gltfArray.forEach((sensor) => gltfLoad(URL_GLTF, sensor));
}; };
if (!LOAD_DETAILED_BLDG225) { if (!LOAD_DETAILED_BLDG225) {
// Default case: load only 3dTiles // Default case: load only 3dTiles
loadNonDetailed(); loadNonDetailed();
} else { } else {
// Alternative case: load 3dTiles + glTF // Alternative case: load 3dTiles + glTF
loadDetailed(); loadDetailed();
} }
/** /**
...@@ -166,109 +166,109 @@ if (!LOAD_DETAILED_BLDG225) { ...@@ -166,109 +166,109 @@ if (!LOAD_DETAILED_BLDG225) {
* @param {*} * @param {*}
* @returns {undefined} * @returns {undefined}
*/ */
const activate3DTileFeaturePicking = function () { const activate3DTileFeaturePicking = function() {
// HTML overlay for showing feature name on mouseover // HTML overlay for showing feature name on mouseover
const nameOverlay = document.createElement("div"); const nameOverlay = document.createElement("div");
viewer.container.appendChild(nameOverlay); viewer.container.appendChild(nameOverlay);
nameOverlay.className = "backdrop"; nameOverlay.className = "backdrop";
nameOverlay.style.display = "none"; nameOverlay.style.display = "none";
nameOverlay.style.position = "absolute"; nameOverlay.style.position = "absolute";
nameOverlay.style.bottom = "0"; nameOverlay.style.bottom = "0";
nameOverlay.style.left = "0"; nameOverlay.style.left = "0";
nameOverlay.style["pointer-events"] = "none"; nameOverlay.style["pointer-events"] = "none";
nameOverlay.style.padding = "4px"; nameOverlay.style.padding = "4px";
nameOverlay.style.backgroundColor = "black"; nameOverlay.style.backgroundColor = "black";
nameOverlay.style.color = "white"; nameOverlay.style.color = "white";
nameOverlay.style.fontFamily = "Fira Sans, sans-serif"; nameOverlay.style.fontFamily = "Fira Sans, sans-serif";
nameOverlay.style.fontSize = "0.75em"; nameOverlay.style.fontSize = "0.75em";
// Information about the currently selected feature // Information about the currently selected feature
const selected = { const selected = {
feature: undefined, feature: undefined,
originalColor: new Cesium.Color(), originalColor: new Cesium.Color(),
}; };
// An entity object which will hold info about the currently selected feature for infobox display // An entity object which will hold info about the currently selected feature for infobox display
const selectedEntity = new Cesium.Entity(); const selectedEntity = new Cesium.Entity();
// Get default left click handler for when a feature is not picked on left click // Get default left click handler for when a feature is not picked on left click
const clickHandler = viewer.screenSpaceEventHandler.getInputAction( const clickHandler = viewer.screenSpaceEventHandler.getInputAction(
Cesium.ScreenSpaceEventType.LEFT_CLICK Cesium.ScreenSpaceEventType.LEFT_CLICK
); );
// Change the feature color on mouse over // Change the feature color on mouse over
// Information about the currently highlighted feature // Information about the currently highlighted feature
const highlighted = { const highlighted = {
feature: undefined, feature: undefined,
originalColor: new Cesium.Color(), originalColor: new Cesium.Color(),
}; };
// Color a feature on hover. // Color a feature on hover.
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) { viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
// If a feature was previously highlighted, undo the highlight // If a feature was previously highlighted, undo the highlight
if (Cesium.defined(highlighted.feature)) { if (Cesium.defined(highlighted.feature)) {
highlighted.feature.color = highlighted.originalColor; highlighted.feature.color = highlighted.originalColor;
highlighted.feature = undefined; highlighted.feature = undefined;
} }
// Pick a new feature // Pick a new feature
const pickedFeature = viewer.scene.pick(movement.endPosition); const pickedFeature = viewer.scene.pick(movement.endPosition);
if (!Cesium.defined(pickedFeature)) { if (!Cesium.defined(pickedFeature)) {
nameOverlay.style.display = "none"; nameOverlay.style.display = "none";
return; return;
} }
// A feature was picked, so show it's overlay content // A feature was picked, so show it's overlay content
nameOverlay.style.display = "block"; nameOverlay.style.display = "block";
nameOverlay.style.bottom = nameOverlay.style.bottom =
viewer.canvas.clientHeight - movement.endPosition.y + "px"; viewer.canvas.clientHeight - movement.endPosition.y + "px";
nameOverlay.style.left = movement.endPosition.x + "px"; nameOverlay.style.left = movement.endPosition.x + "px";
let name = pickedFeature.getProperty("_gebaeude"); let name = pickedFeature.getProperty("_gebaeude");
if (!Cesium.defined(name)) { if (!Cesium.defined(name)) {
name = pickedFeature.getProperty("id"); name = pickedFeature.getProperty("id");
} }
nameOverlay.textContent = name; nameOverlay.textContent = name;
// Highlight the feature if it's not already selected. // Highlight the feature if it's not already selected.
if (pickedFeature !== selected.feature) { if (pickedFeature !== selected.feature) {
highlighted.feature = pickedFeature; highlighted.feature = pickedFeature;
Cesium.Color.clone(pickedFeature.color, highlighted.originalColor); Cesium.Color.clone(pickedFeature.color, highlighted.originalColor);
pickedFeature.color = Cesium.Color.GREY; pickedFeature.color = Cesium.Color.GREY;
} }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE); }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
// Color a feature on selection and show metadata in the InfoBox. // Color a feature on selection and show metadata in the InfoBox.
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) { viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
// If a feature was previously selected, undo the highlight // If a feature was previously selected, undo the highlight
if (Cesium.defined(selected.feature)) { if (Cesium.defined(selected.feature)) {
selected.feature.color = selected.originalColor; selected.feature.color = selected.originalColor;
selected.feature = undefined; selected.feature = undefined;
} }
// Pick a new feature // Pick a new feature
const pickedFeature = viewer.scene.pick(movement.position); const pickedFeature = viewer.scene.pick(movement.position);
if (!Cesium.defined(pickedFeature)) { if (!Cesium.defined(pickedFeature)) {
clickHandler(movement); clickHandler(movement);
return; return;
} }
// Select the feature if it's not already selected // Select the feature if it's not already selected
if (selected.feature === pickedFeature) { if (selected.feature === pickedFeature) {
return; return;
} }
selected.feature = pickedFeature; selected.feature = pickedFeature;
// Save the selected feature's original color // Save the selected feature's original color
if (pickedFeature === highlighted.feature) { if (pickedFeature === highlighted.feature) {
Cesium.Color.clone(highlighted.originalColor, selected.originalColor); Cesium.Color.clone(highlighted.originalColor, selected.originalColor);
highlighted.feature = undefined; highlighted.feature = undefined;
} else { } else {
Cesium.Color.clone(pickedFeature.color, selected.originalColor); Cesium.Color.clone(pickedFeature.color, selected.originalColor);
} }
// Highlight newly selected feature // Highlight newly selected feature
pickedFeature.color = Cesium.Color.LIME; pickedFeature.color = Cesium.Color.LIME;
// Set feature infobox description // Set feature infobox description
const featureName = pickedFeature.getProperty("name"); const featureName = pickedFeature.getProperty("name");
selectedEntity.name = featureName; selectedEntity.name = featureName;
selectedEntity.description = selectedEntity.description =
'Loading <div class="cesium-infoBox-loading"></div>'; 'Loading <div class="cesium-infoBox-loading"></div>';
viewer.selectedEntity = selectedEntity; viewer.selectedEntity = selectedEntity;
selectedEntity.description = ` selectedEntity.description = `
<table class="cesium-infoBox-defaultTable"> <table class="cesium-infoBox-defaultTable">
<tbody> <tbody>
<tr><th>Bau</th><td> <tr><th>Bau</th><td>
...@@ -290,57 +290,62 @@ const activate3DTileFeaturePicking = function () { ...@@ -290,57 +290,62 @@ const activate3DTileFeaturePicking = function () {
</table> </table>
`; `;
const clickedBuilding = pickedFeature.getProperty("_gebaeude"); const clickedBuilding = pickedFeature.getProperty("_gebaeude");
const clickedBuildingDatastreamId = getDatastreamIdFromBuildingNumber( const clickedBuildingDatastreamId = getDatastreamIdFromBuildingNumber(
clickedBuilding, clickedBuilding,
"vl", "vl",
"60min" "60min"
); );
const BASE_URL_OBSERVATIONS = getObservationsUrl(
BASE_URL,
clickedBuildingDatastreamId
);
const PARAM_FILTER = createTemporalFilterString("2020-01-01", "2021-01-01");
const axiosGetRequest = axios.get(BASE_URL_OBSERVATIONS, {
params: {
"$resultFormat": PARAM_RESULT_FORMAT,
"$orderBy": PARAM_ORDER_BY,
"$filter": PARAM_FILTER,
"$select": PARAM_SELECT,
},
});
const BASE_URL_OBSERVATIONS = getObservationsUrl(
BASE_URL,
clickedBuildingDatastreamId
);
const PARAM_FILTER = createTemporalFilterString("2020-01-01", "2021-01-01");
const axiosGetRequest = axios.get(BASE_URL_OBSERVATIONS, {
params: {
"$resultFormat": PARAM_RESULT_FORMAT,
"$orderBy": PARAM_ORDER_BY,
"$filter": PARAM_FILTER,
"$select": PARAM_SELECT,
},
});
// Get "ALL" the Observations that satisfy our query // Get "ALL" the Observations that satisfy our query
followNextLink(axiosGetRequest) followNextLink(axiosGetRequest)
.then((success) => { .then((success) => {
const successValue = success.data.value; const successValue = success.data.value;
// Array that will hold the combined observations // Array that will hold the combined observations
const combinedObservations = []; const combinedObservations = [];
successValue.forEach((dataObj) => { successValue.forEach((dataObj) => {
// Each page of results will have a dataArray that holds the observations // Each page of results will have a dataArray that holds the observations
const dataArrays = dataObj.dataArray; const dataArrays = dataObj.dataArray;
combinedObservations.push(...dataArrays);
});
// DEBUG: Check total number of observations
console.log(combinedObservations.length);
// DEBUG: Print the array of observations
console.log(combinedObservations);
return combinedObservations;
})
.catch((err) => {
console.log(err);
})
.then((observationArr) => {
var agg = aggregateResponse(observationArr, 0, 'mean');
console.log(agg);
drawHeatMapHC(formatSTAResponseForHeatMap(observationArr));
drawLineChartHC(formatSTAResponseForLineChart(observationArr));
});
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
combinedObservations.push(...dataArrays);
});
// DEBUG: Check total number of observations
console.log(combinedObservations.length);
// DEBUG: Print the array of observations
console.log(combinedObservations);
return combinedObservations;
})
.catch((err) => {
console.log(err);
})
.then((observationArr) => {
drawHeatMapHC(formatSTAResponseForHeatMap(observationArr));
drawLineChartHC(formatSTAResponseForLineChart(observationArr));
});
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}; };
activate3DTileFeaturePicking(); activate3DTileFeaturePicking();
\ No newline at end of file
...@@ -13,72 +13,72 @@ export const BASE_URL = "http://193.196.39.91:8080/frost-icity-tp31/v1.1"; ...@@ -13,72 +13,72 @@ export const BASE_URL = "http://193.196.39.91:8080/frost-icity-tp31/v1.1";
* @param {*} samplingRate String representing the sampling rate of the observations * @param {*} samplingRate String representing the sampling rate of the observations
* @returns {Number} Datastream corresponding to the input building * @returns {Number} Datastream corresponding to the input building
*/ */
export const getDatastreamIdFromBuildingNumber = function ( export const getDatastreamIdFromBuildingNumber = function(
buildingNumber, buildingNumber,
phenomenon, phenomenon,
samplingRate samplingRate
) { ) {
const buildingToDatastreamMapping = { const buildingToDatastreamMapping = {
101: { 101: {
vl: { "15min": "69", "60min": "75" }, vl: { "15min": "69", "60min": "75" },
rl: { "15min": "81", "60min": "87" }, rl: { "15min": "81", "60min": "87" },
flow: { "15min": "93", "60min": "99" }, flow: { "15min": "93", "60min": "99" },
power: { "15min": "105", "60min": "111" }, power: { "15min": "105", "60min": "111" },
energy: { "15min": "117", "60min": "123" }, energy: { "15min": "117", "60min": "123" },
energy_verb: { "15min": "129", "60min": "135" }, energy_verb: { "15min": "129", "60min": "135" },
}, },
102: { 102: {
vl: { "15min": "70", "60min": "76" }, vl: { "15min": "70", "60min": "76" },
rl: { "15min": "82", "60min": "88" }, rl: { "15min": "82", "60min": "88" },
flow: { "15min": "94", "60min": "100" }, flow: { "15min": "94", "60min": "100" },
power: { "15min": "106", "60min": "112" }, power: { "15min": "106", "60min": "112" },
energy: { "15min": "118", "60min": "124" }, energy: { "15min": "118", "60min": "124" },
energy_verb: { "15min": "130", "60min": "136" }, energy_verb: { "15min": "130", "60min": "136" },
}, },
107: { 107: {
vl: { "15min": "71", "60min": "77" }, vl: { "15min": "71", "60min": "77" },
rl: { "15min": "83", "60min": "89" }, rl: { "15min": "83", "60min": "89" },
flow: { "15min": "95", "60min": "101" }, flow: { "15min": "95", "60min": "101" },
power: { "15min": "107", "60min": "113" }, power: { "15min": "107", "60min": "113" },
energy: { "15min": "119", "60min": "125" }, energy: { "15min": "119", "60min": "125" },
energy_verb: { "15min": "131", "60min": "137" }, energy_verb: { "15min": "131", "60min": "137" },
}, },
"112, 118": { "112, 118": {
vl: { "15min": "72", "60min": "78" }, vl: { "15min": "72", "60min": "78" },
rl: { "15min": "84", "60min": "90" }, rl: { "15min": "84", "60min": "90" },
flow: { "15min": "96", "60min": "102" }, flow: { "15min": "96", "60min": "102" },
power: { "15min": "108", "60min": "114" }, power: { "15min": "108", "60min": "114" },
energy: { "15min": "120", "60min": "126" }, energy: { "15min": "120", "60min": "126" },
energy_verb: { "15min": "132", "60min": "138" }, energy_verb: { "15min": "132", "60min": "138" },
}, },
125: { 125: {
vl: { "15min": "73", "60min": "79" }, vl: { "15min": "73", "60min": "79" },
rl: { "15min": "85", "60min": "91" }, rl: { "15min": "85", "60min": "91" },
flow: { "15min": "97", "60min": "103" }, flow: { "15min": "97", "60min": "103" },
power: { "15min": "109", "60min": "115" }, power: { "15min": "109", "60min": "115" },
energy: { "15min": "121", "60min": "127" }, energy: { "15min": "121", "60min": "127" },
energy_verb: { "15min": "133", "60min": "139" }, energy_verb: { "15min": "133", "60min": "139" },
}, },
225: { 225: {
vl: { "15min": "74", "60min": "80" }, vl: { "15min": "74", "60min": "80" },
rl: { "15min": "86", "60min": "92" }, rl: { "15min": "86", "60min": "92" },
flow: { "15min": "98", "60min": "104" }, flow: { "15min": "98", "60min": "104" },
power: { "15min": "110", "60min": "116" }, power: { "15min": "110", "60min": "116" },
energy: { "15min": "122", "60min": "128" }, energy: { "15min": "122", "60min": "128" },
energy_verb: { "15min": "134", "60min": "140" }, energy_verb: { "15min": "134", "60min": "140" },
}, },
}; };
if (!buildingNumber) return; if (!buildingNumber) return;
// check if building is contained in mapping object // check if building is contained in mapping object
if (!(buildingNumber in buildingToDatastreamMapping)) return; if (!(buildingNumber in buildingToDatastreamMapping)) return;
const datastreamIdMatched = Number( const datastreamIdMatched = Number(
buildingToDatastreamMapping[buildingNumber][phenomenon][samplingRate] buildingToDatastreamMapping[buildingNumber][phenomenon][samplingRate]
); );
return datastreamIdMatched; return datastreamIdMatched;
}; };
/** /**
...@@ -86,10 +86,10 @@ export const getDatastreamIdFromBuildingNumber = function ( ...@@ -86,10 +86,10 @@ export const getDatastreamIdFromBuildingNumber = function (
* @param {Number} datastreamID - Integer representing the Datastream ID * @param {Number} datastreamID - Integer representing the Datastream ID
* @returns {String} URL string for fetching the Observations corresponding to a Datastream * @returns {String} URL string for fetching the Observations corresponding to a Datastream
*/ */
export const getObservationsUrl = function (baseUrl, datastreamID) { export const getObservationsUrl = function(baseUrl, datastreamID) {
if (!datastreamID) return; if (!datastreamID) return;
const fullDatastreamURL = `${baseUrl}/Datastreams(${datastreamID})/Observations`; const fullDatastreamURL = `${baseUrl}/Datastreams(${datastreamID})/Observations`;
return fullDatastreamURL; return fullDatastreamURL;
}; };
/** /**
...@@ -98,10 +98,10 @@ export const getObservationsUrl = function (baseUrl, datastreamID) { ...@@ -98,10 +98,10 @@ export const getObservationsUrl = function (baseUrl, datastreamID) {
* @param {String} dateStop Stop date in YYYY-MM-DD format * @param {String} dateStop Stop date in YYYY-MM-DD format
* @returns {String} Temporal filter string * @returns {String} Temporal filter string
*/ */
export const createTemporalFilterString = function (dateStart, dateStop) { export const createTemporalFilterString = function(dateStart, dateStop) {
if (!dateStart || !dateStop) return; if (!dateStart || !dateStop) return;
const filterString = `resultTime ge ${dateStart}T00:00:00.000Z and resultTime le ${dateStop}T00:00:00.000Z`; const filterString = `resultTime ge ${dateStart}T00:00:00.000Z and resultTime le ${dateStop}T00:00:00.000Z`;
return filterString; return filterString;
}; };
// const BASE_URL_OBSERVATIONS = getObservationsUrl(80); // const BASE_URL_OBSERVATIONS = getObservationsUrl(80);
...@@ -119,31 +119,218 @@ export const PARAM_SELECT = "result,phenomenonTime"; ...@@ -119,31 +119,218 @@ export const PARAM_SELECT = "result,phenomenonTime";
// }, // },
// }); // });
/**
*
* @param {JSON} obj JSON object on which to replace a specific key.
* @param {String} oldKey is the old key in the JSON to be renamed to newKey
* @param {String} newKey is the key that should replace the oldKey
* usage: myjson.forEach((obj) => renameKey(obj, "oldkey", "newkey"));
*/
function renameKey(obj, oldKey, newKey) {
obj[newKey] = obj[oldKey];
delete obj[oldKey];
}
/**
*
* @param {Array} arr is the Array to be converted into a JSON
* @returns {JSON} stringToJsonObject
*/
function convertArray2JSON(arr) {
var arrayToString = JSON.stringify(Object.assign({}, arr)); // convert array to string
var stringToJsonObject = JSON.parse(arrayToString); // convert string to json object
return stringToJsonObject;
}
function createDateFromDateTimeString(jsonData) {
let datx = [];
let daty = [];
const MONTH = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
for (var u = 0; u < jsonData.length; u++) {
daty.push(jsonData[u].temperature);
let date = new Date(jsonData[u].datetime);
let datum = date.getDate();
let month = MONTH[date.getMonth()];
let hour = date.getHours() + ":00";
let newDateStr = datum + "/" + month + "-" + hour;
datx.push(newDateStr);
}
return [datx, daty];
}
/**
* Format the response from SensorThings API to make it suitable for heatmap
* @param {Array} obsArray Response from SensorThings API as array
* @param {Int8} hours Number of hours to aggregate over. If hours=0,
* it will be aggregated by date (e.g. all values recorded on 1st of May etc...)
* if hours to any number (also hours=24) data will be aggregated over every 24hours,
* even if the date changes (e.g. data from 1st of May from 10pm up 9pm on 2nd of May etc.)
* @param {String} method Specify how to aggregate date. Use: 'mean' = default, 'sum', 'min' or 'max'
* @returns {Array} Aggregated Response
*/
export const aggregateResponse = function(obsArray, hours, method) {
if (!obsArray) return;
if (hours < 0) return;
// check if we have a defined method or the method specified is accepted, rest is handeled in switch/case below
if (method == undefined) method = 'mean';
// convert obsArray to json
let jsonFromArr = [];
for (var i = 0; i < obsArray.length; i++) {
jsonFromArr.push(convertArray2JSON(obsArray[i]));
}
// rename the keys in the jason
jsonFromArr.forEach((obj) => renameKey(obj, "0", "datetime"));
let jsonData = jsonFromArr;
jsonData.forEach((obj) => renameKey(obj, "1", "temperature"));
let newOutput = [];
var aggDates = [];
var aggregatedVals = [];
var vals = []; // store values temporarily to use for processing
if (hours == 0) { // i.e. aggregate over one Date / Day
var currentDate;
var oldDate;
for (var d = 0; d < jsonData.length; d++) {
let tmpDate = new Date(jsonData[d].datetime);
currentDate = tmpDate.getDate(); // gets the day of the month 1...31
if (d === 0) oldDate = currentDate;
if (currentDate == oldDate) {
vals.push(jsonData[d].temperature);
} else {
aggDates.push(new Date(tmpDate - 1));
if (vals.length == 0) {
aggregatedVals.push(-1);
oldDate = currentDate;
continue;
}
switch (method) {
case 'mean':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
break;
case 'sum':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b; }, 0));
break;
case 'min':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.min(a, b); }));
break;
case 'max':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.max(a, b); }));
break;
default:
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
}
vals = []; // clear the daily value vector
vals.push(jsonData[d].temperature); // now push first entry of new day into my temp value vector.
}
oldDate = currentDate;
} // end of for loop
// create output to be in the same List format as the original data from obsArray.
for (let i = 0; i < aggregatedVals.length; i++) {
newOutput.push([aggDates[i].toISOString(), aggregatedVals[i]]);
}
} else { // i.e. aggregate over X hours, irrespective of the day.
let cnt = 0;
let cumHours = 0;
for (var d = 0; d < jsonData.length; d++) {
if (cnt < hours) {
vals.push(jsonData[d].temperature);
cnt++;
} else {
cumHours += cnt;
cnt = 0;
aggDates.push(cumHours);
if (vals.length == 0) {
aggregatedVals.push(-1);
continue;
}
switch (method) {
case 'mean':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
break;
case 'sum':
aggregatedVals.push(vals.reduce(function(a, b) { return a + b; }, 0));
break;
case 'min':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.min(a, b); }));
break;
case 'max':
aggregatedVals.push(vals.reduce(function(a, b) { return Math.max(a, b); }));
break;
default:
aggregatedVals.push(vals.reduce(function(a, b) { return a + b / vals.length; }, 0));
}
vals = []; // clear the daily value vector
vals.push(jsonData[d].temperature); // now push first entry of new day into my temp value vector.
cnt++;
}
oldDate = currentDate;
} // end of for loop
// create output to be in the same List format as the original data from obsArray.
for (let i = 0; i < aggregatedVals.length; i++) {
newOutput.push([aggDates[i], aggregatedVals[i]]);
}
} // end else
return newOutput;
}
/** /**
* Format the response from SensorThings API to make it suitable for heatmap * Format the response from SensorThings API to make it suitable for heatmap
* @param {Array} obsArray Response from SensorThings API as array * @param {Array} obsArray Response from SensorThings API as array
* @returns {Array} Array of formatted observations suitable for use in a heatmap * @returns {Array} Array of formatted observations suitable for use in a heatmap
*/ */
export const formatSTAResponseForHeatMap = function (obsArray) { export const formatSTAResponseForHeatMap = function(obsArray) {
if (!obsArray) return; if (!obsArray) return;
const dataSTAFormatted = []; const dataSTAFormatted = [];
obsArray.forEach((obs) => { obsArray.forEach((obs) => {
// Get the date/time string; first element in input array; remove trailing "Z" // Get the date/time string; first element in input array; remove trailing "Z"
const obsDateTimeInput = obs[0].slice(0, -1); const obsDateTimeInput = obs[0].slice(0, -1);
// Get the "date" part of an observation // Get the "date" part of an observation
const obsDateInput = obs[0].slice(0, 10); const obsDateInput = obs[0].slice(0, 10);
// Create Date objects // Create Date objects
const obsDateTime = new Date(obsDateTimeInput); const obsDateTime = new Date(obsDateTimeInput);
const obsDate = new Date(obsDateInput); const obsDate = new Date(obsDateInput);
// x-axis -> timestamp; will be the same for observations from the same date // x-axis -> timestamp; will be the same for observations from the same date
const timestamp = Date.parse(obsDate); const timestamp = Date.parse(obsDate);
// y-axis -> hourOfDay // y-axis -> hourOfDay
const hourOfDay = obsDateTime.getHours(); const hourOfDay = obsDateTime.getHours();
// value -> the observation's value; second element in input array // value -> the observation's value; second element in input array
const value = obs[1]; const value = obs[1];
dataSTAFormatted.push([timestamp, hourOfDay, value]); dataSTAFormatted.push([timestamp, hourOfDay, value]);
}); });
return dataSTAFormatted; return dataSTAFormatted;
}; };
/** /**
...@@ -151,94 +338,91 @@ export const formatSTAResponseForHeatMap = function (obsArray) { ...@@ -151,94 +338,91 @@ export const formatSTAResponseForHeatMap = function (obsArray) {
* @param {Array} formattedObsArrayForHeatmap Response from SensorThings API formatted for use in a heatmap * @param {Array} formattedObsArrayForHeatmap Response from SensorThings API formatted for use in a heatmap
* @returns {Object} Highcharts library heatmap object * @returns {Object} Highcharts library heatmap object
*/ */
export const drawHeatMapHC = function (formattedObsArrayForHeatmap) { export const drawHeatMapHC = function(formattedObsArrayForHeatmap) {
Highcharts.chart("chart-heatmap", { Highcharts.chart("chart-heatmap", {
chart: { chart: {
type: "heatmap", type: "heatmap",
zoomType: "x", zoomType: "x",
}, },
boost: { boost: {
useGPUTranslations: true, useGPUTranslations: true,
}, },
title: { title: {
text: "Inlet flow (Vorlauf)", text: "Inlet flow (Vorlauf)",
align: "left", align: "left",
x: 40, x: 40,
}, },
subtitle: { subtitle: {
text: "Temperature variation by day and hour in 2020", text: "Temperature variation by day and hour in 2020",
align: "left", align: "left",
x: 40, x: 40,
}, },
xAxis: { xAxis: {
type: "datetime", type: "datetime",
// min: Date.UTC(2017, 0, 1), // min: Date.UTC(2017, 0, 1),
// max: Date.UTC(2017, 11, 31, 23, 59, 59), // max: Date.UTC(2017, 11, 31, 23, 59, 59),
labels: { labels: {
align: "left", align: "left",
x: 5, x: 5,
y: 14, y: 14,
format: "{value:%B}", // long month format: "{value:%B}", // long month
}, },
showLastLabel: false, showLastLabel: false,
tickLength: 16, tickLength: 16,
}, },
yAxis: { yAxis: {
title: { title: {
text: null, text: null,
}, },
labels: { labels: {
format: "{value}:00", format: "{value}:00",
}, },
minPadding: 0, minPadding: 0,
maxPadding: 0, maxPadding: 0,
startOnTick: false, startOnTick: false,
endOnTick: false, endOnTick: false,
// tickPositions: [0, 6, 12, 18, 24], // tickPositions: [0, 6, 12, 18, 24],
tickPositions: [0, 3, 6, 9, 12, 15, 18, 21, 24], tickPositions: [0, 3, 6, 9, 12, 15, 18, 21, 24],
tickWidth: 1, tickWidth: 1,
min: 0, min: 0,
max: 23, max: 23,
reversed: true, reversed: true,
},
colorAxis: {
stops: [
[0, "#3060cf"],
[0.5, "#fffbbc"],
[0.9, "#c4463a"],
[1, "#c4463a"],
],
min: 60,
max: 85,
startOnTick: false,
endOnTick: false,
labels: {
format: "{value}℃",
},
},
series: [
{
data: formattedObsArrayForHeatmap,
boostThreshold: 100,
borderWidth: 0,
nullColor: "#525252",
colsize: 24 * 36e5, // one day
tooltip: {
headerFormat: "Temperature<br/>",
pointFormat:
"{point.x:%e %b, %Y} {point.y}:00: <b>{point.value} ℃</b>",
}, },
turboThreshold: Number.MAX_VALUE, // #3404, remove after 4.0.5 release
}, colorAxis: {
], stops: [
}); [0, "#3060cf"],
[0.5, "#fffbbc"],
[0.9, "#c4463a"],
[1, "#c4463a"],
],
min: 60,
max: 85,
startOnTick: false,
endOnTick: false,
labels: {
format: "{value}℃",
},
},
series: [{
data: formattedObsArrayForHeatmap,
boostThreshold: 100,
borderWidth: 0,
nullColor: "#525252",
colsize: 24 * 36e5, // one day
tooltip: {
headerFormat: "Temperature<br/>",
pointFormat: "{point.x:%e %b, %Y} {point.y}:00: <b>{point.value} ℃</b>",
},
turboThreshold: Number.MAX_VALUE, // #3404, remove after 4.0.5 release
}, ],
});
}; };
/** /**
...@@ -246,15 +430,15 @@ export const drawHeatMapHC = function (formattedObsArrayForHeatmap) { ...@@ -246,15 +430,15 @@ export const drawHeatMapHC = function (formattedObsArrayForHeatmap) {
* @param {Array} obsArray Response from SensorThings API as array * @param {Array} obsArray Response from SensorThings API as array
* @returns {Array} Array of formatted observations suitable for use in a line chart * @returns {Array} Array of formatted observations suitable for use in a line chart
*/ */
export const formatSTAResponseForLineChart = function (obsArray) { export const formatSTAResponseForLineChart = function(obsArray) {
if (!obsArray) return; if (!obsArray) return;
const dataSTAFormatted = []; const dataSTAFormatted = [];
obsArray.forEach((result) => { obsArray.forEach((result) => {
const timestampObs = new Date(result[0].slice(0, -1)).getTime(); // slice() removes trailing "Z" character in timestamp const timestampObs = new Date(result[0].slice(0, -1)).getTime(); // slice() removes trailing "Z" character in timestamp
const valueObs = result[1]; const valueObs = result[1];
dataSTAFormatted.push([timestampObs, valueObs]); dataSTAFormatted.push([timestampObs, valueObs]);
}); });
return dataSTAFormatted; return dataSTAFormatted;
}; };
/** /**
...@@ -262,38 +446,36 @@ export const formatSTAResponseForLineChart = function (obsArray) { ...@@ -262,38 +446,36 @@ export const formatSTAResponseForLineChart = function (obsArray) {
* @param {Array} formattedObsArrayForLineChart - Response from SensorThings API formatted for use in a line chart * @param {Array} formattedObsArrayForLineChart - Response from SensorThings API formatted for use in a line chart
* @returns {Object} Highcharts library line chart object * @returns {Object} Highcharts library line chart object
*/ */
export const drawLineChartHC = function (formattedObsArrayForLineChart) { export const drawLineChartHC = function(formattedObsArrayForLineChart) {
// Create the chart // Create the chart
Highcharts.stockChart("chart-line", { Highcharts.stockChart("chart-line", {
chart: { chart: {
zoomType: "x", zoomType: "x",
}, },
rangeSelector: { rangeSelector: {
selected: 1, selected: 1,
},
title: {
text: "Inlet flow (Vorlauf)",
"align": "left",
},
subtitle: {
text: "Temperature variation by hour in 2020",
align: "left",
},
series: [
{
name: "AAPL",
data: formattedObsArrayForLineChart,
tooltip: {
valueDecimals: 2,
}, },
turboThreshold: Number.MAX_VALUE, // #3404, remove after 4.0.5 release
}, title: {
], text: "Inlet flow (Vorlauf)",
}); "align": "left",
},
subtitle: {
text: "Temperature variation by hour in 2020",
align: "left",
},
series: [{
name: "AAPL",
data: formattedObsArrayForLineChart,
tooltip: {
valueDecimals: 2,
},
turboThreshold: Number.MAX_VALUE, // #3404, remove after 4.0.5 release
}, ],
});
}; };
/** /**
...@@ -303,26 +485,26 @@ export const drawLineChartHC = function (formattedObsArrayForLineChart) { ...@@ -303,26 +485,26 @@ export const drawLineChartHC = function (formattedObsArrayForLineChart) {
* @param {Object} responsePromise Promise object * @param {Object} responsePromise Promise object
* @returns {Object} - Object containing results from all the "@iot.nextLink" links * @returns {Object} - Object containing results from all the "@iot.nextLink" links
*/ */
export const followNextLink = function (responsePromise) { export const followNextLink = function(responsePromise) {
if (!responsePromise) return; if (!responsePromise) return;
return responsePromise return responsePromise
.then(function (lastSuccess) { .then(function(lastSuccess) {
if (lastSuccess.data["@iot.nextLink"]) { if (lastSuccess.data["@iot.nextLink"]) {
return followNextLink( return followNextLink(
axios.get(lastSuccess.data["@iot.nextLink"]) axios.get(lastSuccess.data["@iot.nextLink"])
).then(function (nextLinkSuccess) { ).then(function(nextLinkSuccess) {
nextLinkSuccess.data.value = lastSuccess.data.value.concat( nextLinkSuccess.data.value = lastSuccess.data.value.concat(
nextLinkSuccess.data.value nextLinkSuccess.data.value
); );
return nextLinkSuccess; return nextLinkSuccess;
});
} else {
return lastSuccess;
}
})
.catch(function(err) {
console.log(err);
}); });
} else {
return lastSuccess;
}
})
.catch(function (err) {
console.log(err);
});
}; };
// Get "ALL" the Observations that satisfy our query // Get "ALL" the Observations that satisfy our query
...@@ -352,4 +534,4 @@ export const followNextLink = function (responsePromise) { ...@@ -352,4 +534,4 @@ export const followNextLink = function (responsePromise) {
// .then((observationArr) => { // .then((observationArr) => {
// drawHeatMapHC(observationArr); // drawHeatMapHC(observationArr);
// drawLineChartHC(observationArr); // drawLineChartHC(observationArr);
// }); // });
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment