Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable the support of complex IoT data #591

Merged
merged 60 commits into from
Dec 8, 2021
Merged
Changes from 1 commit
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
55e7008
add first data structures for the handling of data type models
schneiti Jan 7, 2021
0445e6e
enable the creation of data models and the connection of operator and…
schneiti Jan 9, 2021
38a8a3d
add mqtt message example generation feature for data models
schneiti Jan 11, 2021
0239f69
enable validation of complex iot data, storing/accessing it to/from t…
schneiti Jan 15, 2021
ab02b07
Little refactorings and add powerful sub tree algorithm for data mode…
schneiti Jan 19, 2021
593e91e
add first simple version of visualization backend handling (may be te…
schneiti Jan 21, 2021
94c558a
add first changes for updated sensor value visualization
schneiti Jan 24, 2021
dc5471b
add modular visualization chart cards for sensor values
schneiti Jan 28, 2021
b307afe
improve modular visualization, add leaflet map with osm tiles as visu…
schneiti Feb 1, 2021
1748d17
add some test adapters
schneiti Feb 3, 2021
7487e61
add the display of units and names of values in the sensor visualizat…
schneiti Feb 4, 2021
4c98847
make actuators work with the new concept
schneiti Feb 4, 2021
7065b22
make monitoring operators work again
schneiti Feb 5, 2021
9cfc612
add first basic version of a json path input directive
schneiti Feb 7, 2021
362418f
added first version of CEP for complex iot data
schneiti Feb 14, 2021
768f56a
add properly quotes around epl query field specification
schneiti Feb 15, 2021
ac44822
improve visualization of ValueLogs in the value statistics
schneiti Feb 15, 2021
65b61e2
add ui improvements for the query editor
schneiti Feb 17, 2021
3c82825
adapt the event filters for the CEPQueryBuilder to work again for com…
schneiti Feb 19, 2021
0cb0a9d
Enable multiple types for single visualization fields to improve user…
schneiti Feb 22, 2021
716c31f
fix CEP bug for value logs of the monitoring type
schneiti Feb 23, 2021
8fc1e6e
Add new value log display for environment models. Fix json path input…
schneiti Feb 25, 2021
8524a01
Bug fixes for type validation of date and binary, add utils for docum…
schneiti Feb 27, 2021
37493e4
fix bug concerning the environment model
schneiti Mar 2, 2021
cfb4dfd
add java doc and remove some todos
schneiti Mar 22, 2021
987d1f1
Merge branch 'master' into complex-iot-data
schneiti Mar 23, 2021
df52b3c
little ui improvements and data model input method
schneiti Apr 20, 2021
48fc388
code refactoring
schneiti May 7, 2021
cb32b1f
Merge branch 'master' into complex-iot-data
schneiti May 7, 2021
531439f
fix merge request exceptions (workarounds) and add extended visualiza…
schneiti May 8, 2021
b4bdef6
enable demonstration mode for complex data
schneiti May 11, 2021
7cd1d9f
fix geo map date label and remove unit field from operator creation m…
schneiti Jun 1, 2021
ab2a9b4
adapt array size key changes also to the html template for the data m…
schneiti Jun 8, 2021
a46c1bd
add example data models with operator scripts
schneiti Jun 8, 2021
9d99e16
Merge branch 'master' into complex-iot-data
schneiti Jun 8, 2021
cf7bd00
Merge branch 'master' into complex-iot-data
schneiti Jun 8, 2021
b5ff24b
Merge branch 'master' into complex-iot-data
schneiti Jul 2, 2021
a6c8d62
add single value log retrieve functionality for timestamp componentID…
schneiti Jul 8, 2021
524b1c9
Merge remote-tracking branch 'origin/master' into complex-iot-data
schneiti Jul 8, 2021
89922c1
Assign ValueLogs to each occuring CEP event for the Testing collection
schneiti Jul 9, 2021
3099f62
most important backend adaptions for complex data support in the test…
schneiti Jul 15, 2021
4734999
Merge branch 'master' into complex-iot-data
schneiti Jul 15, 2021
a4e1a05
adapt testing tool sensor value visualization
schneiti Jul 28, 2021
775b104
Merge branch 'master' into complex-iot-data
schneiti Jul 28, 2021
156f733
resolve merge conflict due to unknown and unused library import state…
schneiti Jul 28, 2021
e0e3d0e
Final testing tool frontend adaptions to support complex iot data
schneiti Aug 5, 2021
0ad7cbe
Merge branch 'master' into complex-iot-data
schneiti Aug 12, 2021
89c50ef
Add data model concept to the default components management. Adapt de…
schneiti Aug 12, 2021
080f7f3
Adapt testing tool sensor simulator jars to complex data format. Add …
schneiti Aug 23, 2021
aee5e45
little code style improvements
schneiti Aug 23, 2021
f78e209
New testing rerun functionality for the DemoDeployer replaces the old…
schneiti Sep 2, 2021
ea2b898
update extraction operators by adding a data model definition and cha…
schneiti Sep 9, 2021
f2f9b5b
fix wrong mqtt message example in resource file readme
schneiti Sep 15, 2021
46de5eb
remove unused dependency from pom.xml
schneiti Sep 23, 2021
355906f
Improve loading behavior of data model mqtt json message example (iss…
schneiti Sep 29, 2021
1e4260f
fix endless loading behavior of line charts (issue #619)
schneiti Sep 29, 2021
64f8e0b
Fix unwanted tab display behavior of chart tabs during sensor runs (i…
schneiti Sep 29, 2021
6805a87
Some adjustments
schneijan Dec 7, 2021
7420e6e
UI improvements, fixed JSPDF import
schneijan Dec 7, 2021
d246281
Further UI improvements for sensor page
schneijan Dec 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
adapt testing tool sensor value visualization
schneiti committed Jul 28, 2021

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit a4e1a0514c38cf04156374ed33f2c636626c0910
Original file line number Diff line number Diff line change
@@ -201,41 +201,6 @@ app.controller('TestingChartController',

}

/**
* [Public]
*
* Retrieves a certain number of value log data (in a specific order) for the current component
* as a promise.
*
* @param numberLogs The number of logs to retrieve
* @param descending The order in which the value logs should be retrieved. True results in descending
* order, false in ascending order. By default, the logs are retrieved in ascending
* order ([oldest log] --> ... --> [most recent log])
* @param unit The unit in which the values are supposed to be retrieved
* @param sensor The sensor of which the values are supposed to be retrieved
* @returns A promise that passes the logs as a parameter
*/
function retrieveComponentData(numberLogs, descending, unit, sensor) {
//Set default order
let order = 'asc';

//Check for user option
if (descending) {
order = 'desc';
}

//Initialize parameters for the server request
const pageDetails = {
sort: 'time,' + order,
size: numberLogs
};


//Perform the server request in order to retrieve the data
return ComponentService.getValueLogs(sensor.id, 'sensor', pageDetails, unit);
}


/**
* [Private]
* Initializes the live chart for displaying the most recent sensor values.
@@ -244,9 +209,9 @@ app.controller('TestingChartController',
/**
* Function that is called when the chart loads something
*/
function loadingStart() {
function loadingStart(visInstanceId) {
//Show the waiting screen
$(LIVE_CHART_CARD_SELECTOR).waitMe({
$(LIVE_CHART_CARD_SELECTOR.replace(".", "#") + "-" + visInstanceId).waitMe({
effect: 'bounce',
text: 'Loading chart...',
bg: 'rgba(255,255,255,0.85)'
@@ -256,9 +221,9 @@ app.controller('TestingChartController',
/**
* Function that is called when the chart finished loading
*/
function loadingFinish() {
function loadingFinish(visInstanceId) {
//Hide the waiting screen for the case it was displayed before
$(LIVE_CHART_CARD_SELECTOR).waitMe("hide");
$(LIVE_CHART_CARD_SELECTOR.replace(".", "#") + "-" + visInstanceId).waitMe("hide");
}

/**
@@ -274,7 +239,6 @@ app.controller('TestingChartController',
loadingStart: loadingStart,
loadingFinish: loadingFinish,
isUpdateable: isUpdateable,
getData: retrieveComponentData
};
}

@@ -287,9 +251,9 @@ app.controller('TestingChartController',
/**
* Function that is called when the chart loads something
*/
function loadingStart() {
function loadingStart(visInstanceId) {
//Show the waiting screen
$(HISTORICAL_CHART_CARD_SELECTOR).waitMe({
$(HISTORICAL_CHART_CARD_SELECTOR.replace(".", "#") + "-" + visInstanceId).waitMe({
effect: 'bounce',
text: 'Loading chart...',
bg: 'rgba(255,255,255,0.85)'
@@ -299,16 +263,15 @@ app.controller('TestingChartController',
/**
* Function that is called when the chart finished loading
*/
function loadingFinish() {
function loadingFinish(visInstanceId) {
//Hide the waiting screen for the case it was displayed before
$(HISTORICAL_CHART_CARD_SELECTOR).waitMe("hide");
$(HISTORICAL_CHART_CARD_SELECTOR.replace(".", "#") + "-" + visInstanceId).waitMe("hide");
}

//Expose
vm.historicalChart = {
loadingStart: loadingStart,
loadingFinish: loadingFinish,
getData: retrieveComponentData
};
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
/* global app */

'use strict';

/**
* Directive for a generic card to visualize complex sensor data, customizable in many ways.
*/
app.directive('customizableChartCard', ['ComponentService', function (ComponentService) {

/**
* Linking function, glue code
*
* @param scope Scope of the directive
* @param element Elements of the directive
* @param attrs Attributes of the directive
*/
var link = function (scope, element, attrs) {

console.log("INSTANCE ID");
console.log(scope.instanceId);
console.log(scope.componentData);
console.log(scope.liveLoadingStart);
console.log(scope.liveLoadingFinish);
console.log(scope.historicalLoadingStart);
console.log(scope.historicalLoadingFinish);
console.log(scope.getLiveData);
console.log(scope.getHistoricalData);
console.log(scope.isLiveChartUpdateable);
console.log(scope.historicalChartApi);
console.log(scope.deploymentState);

console.log("TEST:");
console.log(scope.componentData);


// All visualizations applicable for this component
scope.availableVisualizationsMappings = scope.componentData.operator.dataModel.possibleVisMappings;

// All visualization ids of all visualizations applicable for this component
scope.idOfAllApplicableVisualizations = scope.availableVisualizationsMappings.map(visObj => visObj.visName);

// Binding for the next chart to add (visualization id)
scope.nextChartToAdd = "select";

// The currently chosen chart visualization id
scope.currChart = "select";

scope.onCreateNewVisualizationClicked = function () {
//alert(scope.nextChartToAdd + " for sensor " + scope.componentData.name);
scope.currChart = scope.nextChartToAdd;
scope.visItem.visId = scope.currChart;
scope.visItem = new ActiveVisualization(scope.instanceId, scope.nextChartToAdd);
//alert(scope.nextChartToAdd);
}

/**
* [public]
*
* Actions when a deletion button of the visualization is pressed. Sets the visualization
* id to "select" which results in the display of the start menu.
* @param visId
*/
scope.deleteChartCard = function (visId) {
scope.currChart = "select";
scope.visItem.visId = "select";
scope.nextChartToAdd = "select";
};


// Represents one instance of a currently active visualization
class ActiveVisualization {
constructor(instanceId, visId) {
this.instanceId = instanceId;
this.visId = visId;
this.fieldCollectionId = "";
this.fieldCollectionIdInput = "";
this.visFieldToPathMapping = {};
this.visFieldToPathMappingInput = {};
this.jsonPath = "";
this.jsonPathInput = "";
this.availableOptions = getVisualizationMappingFieldByVisId(this.visId);

this.setFieldCollectionIdInput = function (newIdInput) {
alert("fieldcollection input set to " + newIdInput);
this.fieldCollectionIdInput = newIdInput;
}
}

hasVisualizationOptionFieldCollectionWithName = function hasVisualizationOptionFieldCollectionWithName(fieldCollectionName) {
if (this.availableOptions == null || fieldCollectionName == null) {
return false;
} else {
var hasFieldCollection = false;
this.availableOptions.forEach(function (item, index) {
if (item.fieldCollectionName === fieldCollectionName) {
hasFieldCollection = true;
}
});
return hasFieldCollection;
}
}

getJsonPathsByFieldCollectionName = function getJsonPathsByFieldCollectionName(fieldCollectionName) {
if (this.hasVisualizationOptionFieldCollectionWithName(fieldCollectionName)) {
var jsonPathList = null;
this.availableOptions.forEach(function (item, index) {
if (item.fieldCollectionName === fieldCollectionName) {
jsonPathList = item.jsonPathPerVisualizationField;
}
});
return jsonPathList;
} else {
return null;
}
}
}

function getVisualizationMappingFieldByVisId(visId) {
var match = null;
scope.availableVisualizationsMappings.forEach(function (item, index) {
if (item.visName === visId) {
match = item.mappingPerVisualizationField;
}
});
return match;
}
// --------------

scope.visItem = new ActiveVisualization(scope.instanceId, scope.nextChartToAdd);

/**
* Called, when the create button in the chart settings modal is triggered.
* Sets the jsonPath for the chart and let the modal fade out.
*/
scope.updateJsonPath = function (visToUpdate) {
// Convert string json object to objects
var convertMappings = function (mappingToConvert) {
Object.keys(mappingToConvert).forEach(function (key) {
if (typeof mappingToConvert[key] === "string") {
mappingToConvert[key] = JSON.parse(mappingToConvert[key]);
}
return mappingToConvert;
})
}
convertMappings(visToUpdate.visFieldToPathMappingInput);

visToUpdate.fieldCollectionId = visToUpdate.fieldCollectionIdInput;
visToUpdate.visFieldToPathMapping = JSON.parse(JSON.stringify(visToUpdate.visFieldToPathMappingInput));
$('div.modal.fade').modal('hide');
};

/**
* [Public]
* Retrieves a certain number of value log data (in a specific order) for the current component
* as a promise.
*
* @param numberLogs The number of logs to retrieve
* @param descending The order in which the value logs should be retrieved. True results in descending
* order, false in ascending order. By default, the logs are retrieved in ascending
* order ([oldest log] --> ... --> [most recent log])
* @param unit The unit in which the values are supposed to be retrieved
* @param startTime Start time for filtering
* @param endTime End time for filtering
* @returns A promise that passes the logs as a parameter
*/
scope.getData = function retrieveComponentData(numberLogs, descending, unit, startTime, endTime) {
//Set default order
let order = 'asc';

//Check for user option
if (descending) {
order = 'desc';
}

//Initialize parameters for the server request
let pageDetails = {
sort: 'time,' + order,
size: numberLogs,
startTime: startTime || "",
endTime: endTime || ""
};
//Perform the server request in order to retrieve the data
return ComponentService.getValueLogs(scope.componentData.id, scope.componentData.componentTypeName, pageDetails, unit);
}

/**
* [private]
* Activates a tab based on a given data-target
* @param tab the id prefix of the data-target
* @param instanceId [optional] to specify a certain tab instead of activating all with the tab prefix.
*/
function setTabActive(tab, instanceId) {
if (instanceId != null) {
$('.nav-tabs a[data-target="' + tab + "-" + instanceId + ']"').tab('show');
} else {
// Select the tab as active which id begins with tab
$('.nav-tabs a[data-target^="' + tab + '"]').tab('show');
}
}

// Watch the deployment status and change the chart tabs accordingly
scope.$watch(function () {
console.log("DEPLOYMENT STATE CHANGED!!!!")
return scope.deploymentState;
}, function (newValue, oldValue) {
if (newValue === 'RUNNING') {
// Make sure that the tab of the live chart is selected
setTabActive('#live-chart-card');
} else {
// Make sure that the tab of the historical chart is selected
setTabActive('#historical-chart-card');
}
});

}

//Configure and expose the directive
return {
restrict: 'E', //Elements only
templateUrl: 'templates/customizable-chart-card-template.html',
link: link,
scope: {
componentData: "=componentData",
instanceId: "@instanceId",
//Functions that are called when the chart loads/finishes loading data
liveLoadingStart: '&liveLoadingStart',
liveLoadingFinish: '&liveLoadingFinish',
historicalLoadingStart: '&historicalLoadingStart',
historicalLoadingFinish: '&historicalLoadingFinish',
//Function that checks whether the chart is allowed to update its data
isLiveChartUpdateable: '&isLiveChartUpdateable',
//Public api for the historical chart that provides functions for controlling the chart
historicalChartApi: "=historicalChartApi",
deploymentState: "=deploymentState"
}
};
}
]);
5 changes: 3 additions & 2 deletions src/main/webapp/WEB-INF/views/index.html
Original file line number Diff line number Diff line change
@@ -434,15 +434,16 @@
<script th:src="@{/js/directives/ngDropzone.js}"></script>
<script th:src="@{/js/directives/refreshTable.js}"></script>
<script th:src="@{/js/directives/units/UnitInput.js}"></script>
<script th:src="@{/js/directives/charts/LiveChart.js}"></script>
<script th:src="@{/js/directives/charts/HistoricalChart.js}"></script>
<script th:src="@{/js/directives/charts/line-chart/LiveChart.js}"></script>
<script th:src="@{/js/directives/charts/line-chart/HistoricalChart.js}"></script>
<script th:src="@{/js/directives/charts/geo-map/LiveGeoMapChart.js}"></script>
<script th:src="@{/js/directives/charts/geo-map/HistoricalGeoMapChart.js}"></script>
<script th:src="@{/js/directives/env-models/EnvModelTool.js}"></script>
<script th:src="@{/js/directives/stats/ValueLogStats.js}"></script>
<script th:src="@{/js/directives/triggers/CEPQueryEditor.js}"></script>
<script th:src="@{/js/directives/json-path-ui/jsonPathInput.js}"></script>
<script th:src="@{/js/directives/model-data/dmInput.js}"></script>
<script th:src="@{/js/directives/charts/customizable-chart-card/CustomizableChartCard.js}"></script>

<script th:src="@{/js/controllers/index/IndexController.js}"></script>
<script th:src="@{/js/controllers/ItemListController.js}"></script>
Loading