6.4.1 widgetTimeTrend as Reading widget
First of all, an existing TimeTrend widget must be identified in the dashboard, of which the id <TARGET_WIDGET_NAME> must be noted.
The JS function to be inserted in the appropriate CK Editor box (in more options) of another widget of the same dashboard, in order to pilot the <TARGET_WIDGET_NAME> widgetTimeTrend is of the following type:
function execute() {
$('body').trigger({
type: "showTimeTrendFromExternalContentGis_<TARGET_WIDGET_NAME>",
eventGenerator: $(this),
targetWidget: <TARGET_WIDGET_NAME>,
range: "7/DAY",
color1: "#9b93ed",
color2: "#231d5c",
widgetTitle: "Occupied Parking Lots (Alberti Car Park) from Impulse Button",
field: "occupiedParkingLots",
serviceUri: "http://www.disit.org/km4city/resource/iot/orionUNIFI/DISIT/CarParkPal.Giustizia",
});
}
6.4.2 widgetTimeTrend as Writing widget: Click on widgetTimeTrend chart point or zoom on desired time interval
When clicking on chart point of the widgetTimeTrend, as well as selecting a desired time interval, a JSON object called param is passed to the execute() function set in the CK Editor, in which there are the SURI, the metric name and the starting and ending timestamp of the selected time interval (when clicking on a single chart point, the two timestamps are the same). In the following, a more advanced example is provided (the same illustrated in the Section 6.1), showing how to retrieve data in the selected time interval of a specific Device (by performing an ajax call to Snap4City SmartCity API), handling the results to calculate the mean value for each device’s metric, and finally send the results to be shown in a widgetBarSeries:
function execute() {
let minT, maxT = null;
if (param['t1'] != param['t2']) {
minT = param['t1'];
maxT = param['t2'];
} else {
minT = param['t1'] - 10000000;
maxT = param['t2'] + 10000000;
}
let dt1 = new Date(minT);
let dt1_iso = dt1.toISOString().split(".")[0];
let dt2 = new Date(maxT);
let dt2_iso = dt2.toISOString().split(".")[0];
function getMean(originalData) {
var singleOriginalData, singleData, convertedDate = null;
var convertedData = {
data: []
};
var originalDataWithNoTime = 0;
var originalDataNotNumeric = 0;
var meanDataObj = {};
if (originalData.hasOwnProperty("realtime")) {
if (originalData.realtime.hasOwnProperty("results")) {
if (originalData.realtime.results.hasOwnProperty("bindings")) {
if (originalData.realtime.results.bindings.length > 0) {
let propertyJson = "";
if (originalData.hasOwnProperty("BusStop")) {
propertyJson = originalData.BusStop;
} else {
if (originalData.hasOwnProperty("Sensor")) {
propertyJson = originalData.Sensor;
} else {
if (originalData.hasOwnProperty("Service")) {
propertyJson = originalData.Service;
} else {
propertyJson = originalData.Services;
}
}
}
for (var j = 0; j < originalData.realtime.head.vars.length; j++) {
var singleObj = {}
var field = originalData.realtime.head.vars[j];
var numericCount = 0;
var sum = 0;
var mean = 0;
if (field == "updating" || field == "measuredTime" || field == "instantTime" || field == "dateObserved") {
// convertedDate = singleOriginalData.updating.value;
continue;
}
for (var i = 0; i < originalData.realtime.results.bindings.length; i++) {
singleOriginalData = originalData.realtime.results.bindings[i];
if (singleOriginalData[field] !== undefined) {
if (!isNaN(parseFloat(singleOriginalData[field].value))) {
numericCount++;
sum = sum + parseFloat(singleOriginalData[field].value);
}
}
}
mean = sum / numericCount;
meanDataObj[field] = mean;
}
return meanDataObj;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
}
function buildDynamicData(data, name) {
var passedJson = [];
for (const item in data) {
var singleJson = {};
singleJson["metricId"] = "";
singleJson["metricHighLevelType"] = "Dynamic";
singleJson["metricName"] = name;
singleJson["metricType"] = item;
singleJson["metricValueUnit"] = "";
singleJson["value"] = data[item];
passedJson.push(singleJson)
}
return passedJson;
}
$.ajax({
url: "../controllers/superservicemapProxy.php/api/v1/?serviceUri=" + encodeServiceUri(param['sUri']) + "&fromTime=" + dt1_iso + "&toTime=" + dt2_iso,
// url: "../controllers/superservicemapProxy.php/api/v1/?serviceUri=" + encodeServiceUri(sUri) + "&fromTime=" + dt1_iso + "&toTime=" + dt2_iso + "&valueName=" + param['metricName'],
type: "GET",
data: {},
async: true,
dataType: 'json',
success: function(data) {
if (data.realtime.results) {
var meanData = getMean(data);
var passedJson = buildDynamicData(meanData, data.Service.features[0].properties.name);
$('body').trigger({
type: "showBarSeriesFromExternalContent_w_AggregationSeries_3664_widgetBarSeries35029",
eventGenerator: $(this),
targetWidget: "w_AggregationSeries_3664_widgetBarSeries35029",
color1: "#f22011",
color2: "#9c6b17",
widgetTitle: "Air Quality IT from Impulse Button",
passedData: passedJson
});
} else { $('#w_AggregationSeries_3664_widgetBarSeries35029_chartContainer').hide();
$('#w_AggregationSeries_3664_widgetBarSeries35029_noDataAlert').show();
}
},
error: function(data) {
console.log("Errore in scaricamento dati da Service Map");
console.log(JSON.stringify(data));
}
});
}
6.4.3 widgetTimeTrend reset zoom
In addition to commanding a zoom to one or more widgets, widgetTimeTrend can also reset the zoom of these widgets.
By clicking on the "Reset zoom" button, you can send a command to the other widgets to reset the magnification of the other widgets.
This operation is performed using the execute() function present in the CkEditor by sending it parameters present in the following code:
{
"event": 'reset zoom',
"t1": 1654434511034.4827,
"t2": 1658936003172.4138,
"sUri": "http://www.disit.org/km4city/resource/CarParkStazioneFirenzeS.M.N.",
"metricName": "occupiedParkingLots"
}
The user can then use these parameters to decide how to handle the zoom reset in the various widgets. By default this operation acts on widgets in which a zoom event has been defined in the ckeditor code.
function execute(){
let dt1 = new Date(param['t1']);
let dt1_iso = dt1.toISOString().split(".")[0];
let dt2 = new Date(param['t2']);
let dt2_iso = dt2.toISOString().split(".")[0];
$('body').trigger({
type: "showCurvedLinesFromExternalContent_w_AggregationSeries_3545_widgetCurvedLineSeries35689",
eventGenerator: $(this),
targetWidget: "w_AggregationSeries_3545_widgetCurvedLineSeries35689",
range: "7/DAY",
color1: "#9b93ed",
color2: "#231d5c",
widgetTitle: "Example",
t1: dt1_iso,
t2: dt2_iso,
event:"zoom"
});
}
For example, in this case in the ckeditor js code the target widget is "w_AggregationSeries_3545_widgetCurvedLineSeries35689", consequently zooming and resetting the zoom will only affect this widget.