UI: Implement state data aggregation. Introduce State chart.
This commit is contained in:
parent
70ddf20448
commit
ba6c2c1a1b
@ -152,6 +152,22 @@
|
|||||||
"dataKeySettingsSchema": "{}",
|
"dataKeySettingsSchema": "{}",
|
||||||
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000},\"aggregation\":{\"limit\":200,\"type\":\"AVG\"}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"legend\":{\"show\":true,\"position\":\"nw\",\"backgroundColor\":\"#f0f0f0\",\"backgroundOpacity\":0.85,\"labelBoxBorderColor\":\"rgba(1, 1, 1, 0.45)\"},\"decimals\":1,\"stack\":true,\"tooltipIndividual\":false},\"title\":\"Timeseries Bars - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null}"
|
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000},\"aggregation\":{\"limit\":200,\"type\":\"AVG\"}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"legend\":{\"show\":true,\"position\":\"nw\",\"backgroundColor\":\"#f0f0f0\",\"backgroundOpacity\":0.85,\"labelBoxBorderColor\":\"rgba(1, 1, 1, 0.45)\"},\"decimals\":1,\"stack\":true,\"tooltipIndividual\":false},\"title\":\"Timeseries Bars - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null}"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"alias": "state_chart",
|
||||||
|
"name": "State Chart",
|
||||||
|
"descriptor": {
|
||||||
|
"type": "timeseries",
|
||||||
|
"sizeX": 8,
|
||||||
|
"sizeY": 5,
|
||||||
|
"resources": [],
|
||||||
|
"templateHtml": "",
|
||||||
|
"templateCss": ".legend {\n font-size: 13px;\n line-height: 10px;\n}\n\n.legend table { \n border-spacing: 0px;\n border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n cursor: crosshair; \n}\n\n",
|
||||||
|
"controllerScript": "self.onInit = function() {\n self.ctx.flot = new TbFlot(self.ctx, 'state'); \n}\n\nself.onDataUpdated = function() {\n self.ctx.flot.update();\n}\n\nself.onResize = function() {\n self.ctx.flot.resize();\n}\n\nself.typeParameters = function() {\n return {\n stateData: true\n };\n}\n\nself.onEditModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n return TbFlot.settingsSchema;\n}\n\nself.getDataKeySettingsSchema = function() {\n return TbFlot.datakeySettingsSchema(true);\n}\n\nself.onDestroy = function() {\n self.ctx.flot.destroy();\n}\n",
|
||||||
|
"settingsSchema": "{}",
|
||||||
|
"dataKeySettingsSchema": "{}",
|
||||||
|
"defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 1\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false,\"axisPosition\":\"left\",\"showSeparateAxis\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"return Math.random() > 0.5 ? 1 : 0;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Switch 2\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false,\"axisPosition\":\"left\"},\"_hash\":0.12775350966079668,\"funcBody\":\"return Math.random() <= 0.5 ? 1 : 0;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\",\"ticksFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"stack\":false,\"tooltipIndividual\":false,\"tooltipValueFormatter\":\"if (value > 0 && value <= 1) {\\n return 'On';\\n} else if (value === 0) {\\n return 'Off';\\n} else {\\n return '';\\n}\",\"smoothLines\":false},\"title\":\"State Chart\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null,\"widgetStyle\":{},\"useDashboardTimewindow\":true,\"showLegend\":true,\"actions\":{},\"legendConfig\":{\"position\":\"bottom\",\"showMin\":false,\"showMax\":false,\"showAvg\":false,\"showTotal\":false}}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -96,9 +96,9 @@
|
|||||||
"templateHtml": "<tb-led-indicator ctx='ctx'></tb-led-indicator>",
|
"templateHtml": "<tb-led-indicator ctx='ctx'></tb-led-indicator>",
|
||||||
"templateCss": "",
|
"templateCss": "",
|
||||||
"controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}\n\nself.onResize = function() {\n if (self.ctx.resize) {\n self.ctx.resize();\n }\n}\n\nself.onDestroy = function() {\n}\n",
|
"controllerScript": "self.onInit = function() {\n var scope = self.ctx.$scope;\n scope.ctx = self.ctx;\n}\n\nself.onResize = function() {\n if (self.ctx.resize) {\n self.ctx.resize();\n }\n}\n\nself.onDestroy = function() {\n}\n",
|
||||||
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"title\": {\n \"title\": \"LED title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"ledColor\": {\n \"title\": \"LED Color\",\n \"type\": \"string\",\n \"default\": \"green\"\n },\n \"scheckStatusMethod\": {\n \"title\": \"RPC check device status method\",\n \"type\": \"string\",\n \"default\": \"checkStatus\"\n },\n \"retrieveValueMethod\": {\n \"title\": \"Retrieve led status value using method\",\n \"type\": \"string\",\n \"default\": \"attribute\"\n },\n \"valueAttribute\": {\n \"title\": \"Device attribute/timeseries containing led status value\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"parseValueFunction\": {\n \"title\": \"Parse led status value function, f(data), returns boolean\",\n \"type\": \"string\",\n \"default\": \"return data ? true : false;\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"scheckStatusMethod\", \"valueAttribute\", \"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n {\n \"key\": \"ledColor\",\n \"type\": \"color\"\n },\n \"scheckStatusMethod\",\n {\n \"key\": \"retrieveValueMethod\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"attribute\",\n \"label\": \"Subscribe for attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Subscribe for timeseries\"\n }\n ]\n },\n \"valueAttribute\",\n {\n \"key\": \"parseValueFunction\",\n \"type\": \"javascript\"\n },\n \"requestTimeout\"\n ]\n}",
|
"settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"Settings\",\n \"properties\": {\n \"initialValue\": {\n \"title\": \"Initial value\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"title\": {\n \"title\": \"LED title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"ledColor\": {\n \"title\": \"LED Color\",\n \"type\": \"string\",\n \"default\": \"green\"\n },\n \"performCheckStatus\": {\n \"title\": \"Perform RPC device status check\",\n \"type\": \"boolean\",\n \"default\": true\n },\n \"scheckStatusMethod\": {\n \"title\": \"RPC check device status method\",\n \"type\": \"string\",\n \"default\": \"checkStatus\"\n },\n \"retrieveValueMethod\": {\n \"title\": \"Retrieve led status value using method\",\n \"type\": \"string\",\n \"default\": \"attribute\"\n },\n \"valueAttribute\": {\n \"title\": \"Device attribute/timeseries containing led status value\",\n \"type\": \"string\",\n \"default\": \"value\"\n },\n \"parseValueFunction\": {\n \"title\": \"Parse led status value function, f(data), returns boolean\",\n \"type\": \"string\",\n \"default\": \"return data ? true : false;\"\n },\n \"requestTimeout\": {\n \"title\": \"RPC request timeout (ms)\",\n \"type\": \"number\",\n \"default\": 500\n }\n },\n \"required\": [\"scheckStatusMethod\", \"valueAttribute\", \"requestTimeout\"]\n },\n \"form\": [\n \"initialValue\",\n \"title\",\n {\n \"key\": \"ledColor\",\n \"type\": \"color\"\n },\n \"performCheckStatus\",\n \"scheckStatusMethod\",\n {\n \"key\": \"retrieveValueMethod\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"attribute\",\n \"label\": \"Subscribe for attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Subscribe for timeseries\"\n }\n ]\n },\n \"valueAttribute\",\n {\n \"key\": \"parseValueFunction\",\n \"type\": \"javascript\"\n },\n \"requestTimeout\"\n ]\n}",
|
||||||
"dataKeySettingsSchema": "{}\n",
|
"dataKeySettingsSchema": "{}\n",
|
||||||
"defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":true,\"title\":\"Led indicator\",\"ledColor\":\"#4caf50\",\"scheckStatusMethod\":\"checkStatus\",\"valueAttribute\":\"value\",\"retrieveValueMethod\":\"attribute\",\"parseValueFunction\":\"return data ? true : false;\"},\"title\":\"Led indicator\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}"
|
"defaultConfig": "{\"targetDeviceAliases\":[],\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"requestTimeout\":500,\"initialValue\":true,\"title\":\"Led indicator\",\"ledColor\":\"#4caf50\",\"scheckStatusMethod\":\"checkStatus\",\"valueAttribute\":\"value\",\"retrieveValueMethod\":\"attribute\",\"parseValueFunction\":\"return data ? true : false;\",\"performCheckStatus\":true},\"title\":\"Led indicator\",\"dropShadow\":true,\"enableFullscreen\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{},\"decimals\":2}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@ -186,7 +186,7 @@ function AttributeService($http, $q, $filter, types, telemetryWebsocketService)
|
|||||||
types.dataKeyType.timeseries : types.dataKeyType.attribute;
|
types.dataKeyType.timeseries : types.dataKeyType.attribute;
|
||||||
|
|
||||||
var subscriber = {
|
var subscriber = {
|
||||||
subscriptionCommand: subscriptionCommand,
|
subscriptionCommands: [subscriptionCommand],
|
||||||
type: type,
|
type: type,
|
||||||
onData: function (data) {
|
onData: function (data) {
|
||||||
if (data.data) {
|
if (data.data) {
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
export default class DataAggregator {
|
export default class DataAggregator {
|
||||||
|
|
||||||
constructor(onDataCb, tsKeyNames, startTs, limit, aggregationType, timeWindow, interval,
|
constructor(onDataCb, tsKeyNames, startTs, limit, aggregationType, timeWindow, interval,
|
||||||
steppedChart, types, $timeout, $filter) {
|
stateData, types, $timeout, $filter) {
|
||||||
this.onDataCb = onDataCb;
|
this.onDataCb = onDataCb;
|
||||||
this.tsKeyNames = tsKeyNames;
|
this.tsKeyNames = tsKeyNames;
|
||||||
this.dataBuffer = {};
|
this.dataBuffer = {};
|
||||||
@ -35,8 +35,10 @@ export default class DataAggregator {
|
|||||||
this.limit = limit;
|
this.limit = limit;
|
||||||
this.timeWindow = timeWindow;
|
this.timeWindow = timeWindow;
|
||||||
this.interval = interval;
|
this.interval = interval;
|
||||||
this.steppedChart = steppedChart;
|
this.stateData = stateData;
|
||||||
this.firstStepDataReceived = !this.steppedChart;
|
if (this.stateData) {
|
||||||
|
this.lastPrevKvPairData = {};
|
||||||
|
}
|
||||||
this.aggregationTimeout = Math.max(this.interval, 1000);
|
this.aggregationTimeout = Math.max(this.interval, 1000);
|
||||||
switch (aggregationType) {
|
switch (aggregationType) {
|
||||||
case types.aggregation.min.value:
|
case types.aggregation.min.value:
|
||||||
@ -81,10 +83,6 @@ export default class DataAggregator {
|
|||||||
}, this.aggregationTimeout, false);
|
}, this.aggregationTimeout, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
onFirstStepData(data) {
|
|
||||||
this.firstStepData = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
onData(data, update, history, apply) {
|
onData(data, update, history, apply) {
|
||||||
if (!this.dataReceived || this.resetPending) {
|
if (!this.dataReceived || this.resetPending) {
|
||||||
var updateIntervalScheduledTime = true;
|
var updateIntervalScheduledTime = true;
|
||||||
@ -158,6 +156,10 @@ export default class DataAggregator {
|
|||||||
var keyData = this.dataBuffer[key];
|
var keyData = this.dataBuffer[key];
|
||||||
for (var aggTimestamp in aggKeyData) {
|
for (var aggTimestamp in aggKeyData) {
|
||||||
if (aggTimestamp <= this.startTs) {
|
if (aggTimestamp <= this.startTs) {
|
||||||
|
if (this.stateData &&
|
||||||
|
(!this.lastPrevKvPairData[key] || this.lastPrevKvPairData[key][0] < aggTimestamp)) {
|
||||||
|
this.lastPrevKvPairData[key] = [Number(aggTimestamp), aggKeyData[aggTimestamp].aggValue];
|
||||||
|
}
|
||||||
delete aggKeyData[aggTimestamp];
|
delete aggKeyData[aggTimestamp];
|
||||||
} else if (aggTimestamp <= this.endTs) {
|
} else if (aggTimestamp <= this.endTs) {
|
||||||
var aggData = aggKeyData[aggTimestamp];
|
var aggData = aggKeyData[aggTimestamp];
|
||||||
@ -166,6 +168,9 @@ export default class DataAggregator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
keyData = this.$filter('orderBy')(keyData, '+this[0]');
|
keyData = this.$filter('orderBy')(keyData, '+this[0]');
|
||||||
|
if (this.stateData) {
|
||||||
|
this.updateStateBounds(keyData, angular.copy(this.lastPrevKvPairData[key]));
|
||||||
|
}
|
||||||
if (keyData.length > this.limit) {
|
if (keyData.length > this.limit) {
|
||||||
keyData = keyData.slice(keyData.length - this.limit);
|
keyData = keyData.slice(keyData.length - this.limit);
|
||||||
}
|
}
|
||||||
@ -174,6 +179,34 @@ export default class DataAggregator {
|
|||||||
return this.dataBuffer;
|
return this.dataBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateStateBounds(keyData, lastPrevKvPair) {
|
||||||
|
if (lastPrevKvPair) {
|
||||||
|
lastPrevKvPair[0] = this.startTs;
|
||||||
|
}
|
||||||
|
var firstKvPair;
|
||||||
|
if (!keyData.length) {
|
||||||
|
if (lastPrevKvPair) {
|
||||||
|
firstKvPair = lastPrevKvPair;
|
||||||
|
keyData.push(firstKvPair);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
firstKvPair = keyData[0];
|
||||||
|
}
|
||||||
|
if (firstKvPair && firstKvPair[0] > this.startTs) {
|
||||||
|
if (lastPrevKvPair) {
|
||||||
|
keyData.unshift(lastPrevKvPair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyData.length) {
|
||||||
|
var lastKvPair = keyData[keyData.length-1];
|
||||||
|
if (lastKvPair[0] < this.endTs) {
|
||||||
|
lastKvPair = angular.copy(lastKvPair);
|
||||||
|
lastKvPair[0] = this.endTs;
|
||||||
|
keyData.push(lastKvPair);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
if (this.intervalTimeoutHandle) {
|
if (this.intervalTimeoutHandle) {
|
||||||
this.$timeout.cancel(this.intervalTimeoutHandle);
|
this.$timeout.cancel(this.intervalTimeoutHandle);
|
||||||
|
|||||||
@ -105,7 +105,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
|
|||||||
var datasourceType = datasourceSubscription.datasourceType;
|
var datasourceType = datasourceSubscription.datasourceType;
|
||||||
var datasourceData = {};
|
var datasourceData = {};
|
||||||
var dataKeys = {};
|
var dataKeys = {};
|
||||||
var subscribers = {};
|
var subscribers = [];
|
||||||
var history = datasourceSubscription.subscriptionTimewindow &&
|
var history = datasourceSubscription.subscriptionTimewindow &&
|
||||||
datasourceSubscription.subscriptionTimewindow.fixedWindow;
|
datasourceSubscription.subscriptionTimewindow.fixedWindow;
|
||||||
var realtime = datasourceSubscription.subscriptionTimewindow &&
|
var realtime = datasourceSubscription.subscriptionTimewindow &&
|
||||||
@ -249,7 +249,6 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
|
|||||||
if (tsKeys.length > 0) {
|
if (tsKeys.length > 0) {
|
||||||
|
|
||||||
var subscriber;
|
var subscriber;
|
||||||
var subscriptionCommand;
|
|
||||||
|
|
||||||
if (history) {
|
if (history) {
|
||||||
|
|
||||||
@ -265,45 +264,103 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
|
|||||||
};
|
};
|
||||||
|
|
||||||
subscriber = {
|
subscriber = {
|
||||||
historyCommand: historyCommand,
|
historyCommands: [ historyCommand ],
|
||||||
type: types.dataKeyType.timeseries,
|
type: types.dataKeyType.timeseries,
|
||||||
onData: function (data) {
|
subsTw: subsTw
|
||||||
if (data.data) {
|
};
|
||||||
for (var key in data.data) {
|
|
||||||
|
if (subsTw.aggregation.stateData) {
|
||||||
|
subscriber.firstStateHistoryCommand = createFirstStateHistoryCommand(subsTw.fixedWindow.startTimeMs, tsKeys);
|
||||||
|
subscriber.historyCommands.push(subscriber.firstStateHistoryCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
subscriber.onData = function (data, subscriptionId) {
|
||||||
|
if (this.subsTw.aggregation.stateData &&
|
||||||
|
this.firstStateHistoryCommand && this.firstStateHistoryCommand.cmdId == subscriptionId) {
|
||||||
|
if (this.data) {
|
||||||
|
onStateHistoryData(data, this.data, this.subsTw.aggregation.limit,
|
||||||
|
subsTw.fixedWindow.startTimeMs, this.subsTw.fixedWindow.endTimeMs,
|
||||||
|
(data) => {
|
||||||
|
onData(data.data, types.dataKeyType.timeseries, true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.firstStateData = data;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.subsTw.aggregation.stateData) {
|
||||||
|
if (this.firstStateData) {
|
||||||
|
onStateHistoryData(this.firstStateData, data, this.subsTw.aggregation.limit,
|
||||||
|
this.subsTw.fixedWindow.startTimeMs, this.subsTw.fixedWindow.endTimeMs,
|
||||||
|
(data) => {
|
||||||
|
onData(data.data, types.dataKeyType.timeseries, true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (key in data.data) {
|
||||||
var keyData = data.data[key];
|
var keyData = data.data[key];
|
||||||
data.data[key] = $filter('orderBy')(keyData, '+this[0]');
|
data.data[key] = $filter('orderBy')(keyData, '+this[0]');
|
||||||
}
|
}
|
||||||
onData(data.data, types.dataKeyType.timeseries, true);
|
onData(data.data, types.dataKeyType.timeseries, true);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
onReconnected: function() {}
|
|
||||||
};
|
};
|
||||||
|
subscriber.onReconnected = function() {};
|
||||||
telemetryWebsocketService.subscribe(subscriber);
|
telemetryWebsocketService.subscribe(subscriber);
|
||||||
subscribers[subscriber.historyCommand.cmdId] = subscriber;
|
subscribers.push(subscriber);
|
||||||
|
|
||||||
if (subsTw.aggregation.steppedChart) {
|
|
||||||
createFirstStepSubscription(subsTw, tsKeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
subscriptionCommand = {
|
var subscriptionCommand = {
|
||||||
entityType: datasourceSubscription.entityType,
|
entityType: datasourceSubscription.entityType,
|
||||||
entityId: datasourceSubscription.entityId,
|
entityId: datasourceSubscription.entityId,
|
||||||
keys: tsKeys
|
keys: tsKeys
|
||||||
};
|
};
|
||||||
|
|
||||||
subscriber = {
|
subscriber = {
|
||||||
subscriptionCommand: subscriptionCommand,
|
subscriptionCommands: [subscriptionCommand],
|
||||||
type: types.dataKeyType.timeseries
|
type: types.dataKeyType.timeseries
|
||||||
};
|
};
|
||||||
|
|
||||||
if (datasourceSubscription.type === types.widgetType.timeseries.value) {
|
if (datasourceSubscription.type === types.widgetType.timeseries.value) {
|
||||||
|
subscriber.subsTw = subsTw;
|
||||||
updateRealtimeSubscriptionCommand(subscriptionCommand, subsTw);
|
updateRealtimeSubscriptionCommand(subscriptionCommand, subsTw);
|
||||||
|
|
||||||
|
if (subsTw.aggregation.stateData) {
|
||||||
|
subscriber.firstStateSubscriptionCommand = createFirstStateHistoryCommand(subsTw.startTs, tsKeys);
|
||||||
|
subscriber.historyCommands = [subscriber.firstStateSubscriptionCommand];
|
||||||
|
}
|
||||||
dataAggregator = createRealtimeDataAggregator(subsTw, tsKeyNames, types.dataKeyType.timeseries);
|
dataAggregator = createRealtimeDataAggregator(subsTw, tsKeyNames, types.dataKeyType.timeseries);
|
||||||
subscriber.onData = function(data) {
|
subscriber.onData = function(data, subscriptionId) {
|
||||||
dataAggregator.onData(data, false, false, true);
|
if (this.subsTw.aggregation.stateData &&
|
||||||
|
this.firstStateSubscriptionCommand && this.firstStateSubscriptionCommand.cmdId == subscriptionId) {
|
||||||
|
if (this.data) {
|
||||||
|
onStateHistoryData(data, this.data, this.subsTw.aggregation.limit,
|
||||||
|
this.subsTw.startTs, this.subsTw.startTs + this.subsTw.aggregation.timeWindow,
|
||||||
|
(data) => {
|
||||||
|
dataAggregator.onData(data, false, false, true);
|
||||||
|
});
|
||||||
|
this.stateDataReceived = true;
|
||||||
|
} else {
|
||||||
|
this.firstStateData = data;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this.subsTw.aggregation.stateData && !this.stateDataReceived) {
|
||||||
|
if (this.firstStateData) {
|
||||||
|
onStateHistoryData(this.firstStateData, data, this.subsTw.aggregation.limit,
|
||||||
|
this.subsTw.startTs, this.subsTw.startTs + this.subsTw.aggregation.timeWindow,
|
||||||
|
(data) => {
|
||||||
|
dataAggregator.onData(data, false, false, true);
|
||||||
|
});
|
||||||
|
this.stateDataReceived = true;
|
||||||
|
} else {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dataAggregator.onData(data, false, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
subscriber.onReconnected = function() {
|
subscriber.onReconnected = function() {
|
||||||
var newSubsTw = null;
|
var newSubsTw = null;
|
||||||
@ -315,14 +372,16 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
|
|||||||
listener.setRealtimeSubscription(newSubsTw);
|
listener.setRealtimeSubscription(newSubsTw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateRealtimeSubscriptionCommand(this.subscriptionCommand, newSubsTw);
|
this.subsTw = newSubsTw;
|
||||||
|
this.firstStateData = null;
|
||||||
|
this.data = null;
|
||||||
|
this.stateDataReceived = false;
|
||||||
|
updateRealtimeSubscriptionCommand(this.subscriptionCommands[0], this.subsTw);
|
||||||
|
if (this.subsTw.aggregation.stateData) {
|
||||||
|
updateFirstStateHistoryCommand(this.firstStateSubscriptionCommand, this.subsTw.startTs);
|
||||||
|
}
|
||||||
dataAggregator.reset(newSubsTw.startTs, newSubsTw.aggregation.timeWindow, newSubsTw.aggregation.interval);
|
dataAggregator.reset(newSubsTw.startTs, newSubsTw.aggregation.timeWindow, newSubsTw.aggregation.interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subsTw.aggregation.steppedChart) {
|
|
||||||
createFirstStepSubscription(subsTw, tsKeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
subscriber.onReconnected = function() {}
|
subscriber.onReconnected = function() {}
|
||||||
subscriber.onData = function(data) {
|
subscriber.onData = function(data) {
|
||||||
@ -333,21 +392,21 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
|
|||||||
}
|
}
|
||||||
|
|
||||||
telemetryWebsocketService.subscribe(subscriber);
|
telemetryWebsocketService.subscribe(subscriber);
|
||||||
subscribers[subscriber.subscriptionCommand.cmdId] = subscriber;
|
subscribers.push(subscriber);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrKeys.length > 0) {
|
if (attrKeys.length > 0) {
|
||||||
|
|
||||||
subscriptionCommand = {
|
var attrsSubscriptionCommand = {
|
||||||
entityType: datasourceSubscription.entityType,
|
entityType: datasourceSubscription.entityType,
|
||||||
entityId: datasourceSubscription.entityId,
|
entityId: datasourceSubscription.entityId,
|
||||||
keys: attrKeys
|
keys: attrKeys
|
||||||
};
|
};
|
||||||
|
|
||||||
subscriber = {
|
subscriber = {
|
||||||
subscriptionCommand: subscriptionCommand,
|
subscriptionCommands: [attrsSubscriptionCommand],
|
||||||
type: types.dataKeyType.attribute,
|
type: types.dataKeyType.attribute,
|
||||||
onData: function (data) {
|
onData: function (data) {
|
||||||
if (data.data) {
|
if (data.data) {
|
||||||
@ -358,7 +417,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
|
|||||||
};
|
};
|
||||||
|
|
||||||
telemetryWebsocketService.subscribe(subscriber);
|
telemetryWebsocketService.subscribe(subscriber);
|
||||||
subscribers[subscriber.cmdId] = subscriber;
|
subscribers.push(subscriber);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,35 +447,47 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createFirstStepSubscription(subsTw, tsKeys) {
|
function createFirstStateHistoryCommand(startTs, tsKeys) {
|
||||||
var startStepCommand = {
|
return {
|
||||||
entityType: datasourceSubscription.entityType,
|
entityType: datasourceSubscription.entityType,
|
||||||
entityId: datasourceSubscription.entityId,
|
entityId: datasourceSubscription.entityId,
|
||||||
keys: tsKeys,
|
keys: tsKeys,
|
||||||
startTs: subsTw.fixedWindow.startTimeMs - YEAR,
|
startTs: startTs - YEAR,
|
||||||
endTs: subsTw.fixedWindow.startTimeMs,
|
endTs: startTs,
|
||||||
interval: subsTw.aggregation.interval,
|
interval: 1000,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
agg: subsTw.aggregation.type
|
agg: types.aggregation.none.value
|
||||||
};
|
|
||||||
var subscriber = {
|
|
||||||
historyCommand: startStepCommand,
|
|
||||||
type: types.dataKeyType.timeseries,
|
|
||||||
onData: function (data) {
|
|
||||||
if (data.data) {
|
|
||||||
for (var key in data.data) {
|
|
||||||
var keyData = data.data[key];
|
|
||||||
data.data[key] = $filter('orderBy')(keyData, '+this[0]');
|
|
||||||
}
|
|
||||||
//onData(data.data, types.dataKeyType.timeseries, true);
|
|
||||||
//TODO: onStartStepData
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onReconnected: function() {}
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
telemetryWebsocketService.subscribe(subscriber);
|
function updateFirstStateHistoryCommand(stateHistoryCommand, startTs) {
|
||||||
subscribers[subscriber.historyCommand.cmdId] = subscriber;
|
stateHistoryCommand.startTs = startTs - YEAR;
|
||||||
|
stateHistoryCommand.endTs = startTs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onStateHistoryData(firstStateData, data, limit, startTs, endTs, onData) {
|
||||||
|
for (var key in data.data) {
|
||||||
|
var keyData = data.data[key];
|
||||||
|
data.data[key] = $filter('orderBy')(keyData, '+this[0]');
|
||||||
|
keyData = data.data[key];
|
||||||
|
if (keyData.length < limit) {
|
||||||
|
var firstStateKeyData = firstStateData.data[key];
|
||||||
|
if (firstStateKeyData.length) {
|
||||||
|
var firstStateDataTsKv = firstStateKeyData[0];
|
||||||
|
firstStateDataTsKv[0] = startTs;
|
||||||
|
firstStateKeyData = [
|
||||||
|
[ startTs, firstStateKeyData[0][1] ]
|
||||||
|
];
|
||||||
|
keyData.unshift(firstStateDataTsKv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keyData.length) {
|
||||||
|
var lastTsKv = angular.copy(keyData[keyData.length-1]);
|
||||||
|
lastTsKv[0] = endTs;
|
||||||
|
keyData.push(lastTsKv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createRealtimeDataAggregator(subsTw, tsKeyNames, dataKeyType) {
|
function createRealtimeDataAggregator(subsTw, tsKeyNames, dataKeyType) {
|
||||||
@ -430,7 +501,7 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
|
|||||||
subsTw.aggregation.type,
|
subsTw.aggregation.type,
|
||||||
subsTw.aggregation.timeWindow,
|
subsTw.aggregation.timeWindow,
|
||||||
subsTw.aggregation.interval,
|
subsTw.aggregation.interval,
|
||||||
subsTw.aggregation.steppedChart,
|
subsTw.aggregation.stateData,
|
||||||
types,
|
types,
|
||||||
$timeout,
|
$timeout,
|
||||||
$filter
|
$filter
|
||||||
@ -451,14 +522,14 @@ function DatasourceSubscription(datasourceSubscription, telemetryWebsocketServic
|
|||||||
timer = null;
|
timer = null;
|
||||||
}
|
}
|
||||||
if (datasourceType === types.datasourceType.entity) {
|
if (datasourceType === types.datasourceType.entity) {
|
||||||
for (var cmdId in subscribers) {
|
for (var i=0;i<subscribers.length;i++) {
|
||||||
var subscriber = subscribers[cmdId];
|
var subscriber = subscribers[i];
|
||||||
telemetryWebsocketService.unsubscribe(subscriber);
|
telemetryWebsocketService.unsubscribe(subscriber);
|
||||||
if (subscriber.onDestroy) {
|
if (subscriber.onDestroy) {
|
||||||
subscriber.onDestroy();
|
subscriber.onDestroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
subscribers = {};
|
subscribers.length = 0;
|
||||||
}
|
}
|
||||||
if (dataAggregator) {
|
if (dataAggregator) {
|
||||||
dataAggregator.destroy();
|
dataAggregator.destroy();
|
||||||
|
|||||||
@ -128,7 +128,7 @@ export default class Subscription {
|
|||||||
stDiff: this.ctx.stDiff
|
stDiff: this.ctx.stDiff
|
||||||
}
|
}
|
||||||
this.useDashboardTimewindow = options.useDashboardTimewindow;
|
this.useDashboardTimewindow = options.useDashboardTimewindow;
|
||||||
this.steppedChart = options.steppedChart;
|
this.stateData = options.stateData;
|
||||||
if (this.useDashboardTimewindow) {
|
if (this.useDashboardTimewindow) {
|
||||||
this.timeWindowConfig = angular.copy(options.dashboardTimewindow);
|
this.timeWindowConfig = angular.copy(options.dashboardTimewindow);
|
||||||
} else {
|
} else {
|
||||||
@ -612,7 +612,7 @@ export default class Subscription {
|
|||||||
this.subscriptionTimewindow =
|
this.subscriptionTimewindow =
|
||||||
this.ctx.timeService.createSubscriptionTimewindow(
|
this.ctx.timeService.createSubscriptionTimewindow(
|
||||||
this.timeWindowConfig,
|
this.timeWindowConfig,
|
||||||
this.timeWindow.stDiff, this.steppedChart);
|
this.timeWindow.stDiff, this.stateData);
|
||||||
}
|
}
|
||||||
this.updateTimewindow();
|
this.updateTimewindow();
|
||||||
return this.subscriptionTimewindow;
|
return this.subscriptionTimewindow;
|
||||||
|
|||||||
@ -34,6 +34,7 @@ function TelemetryWebsocketService($rootScope, $websocket, $timeout, $window, ty
|
|||||||
lastCmdId = 0,
|
lastCmdId = 0,
|
||||||
subscribers = {},
|
subscribers = {},
|
||||||
subscribersCount = 0,
|
subscribersCount = 0,
|
||||||
|
commands = {},
|
||||||
cmdsWrapper = {
|
cmdsWrapper = {
|
||||||
tsSubCmds: [],
|
tsSubCmds: [],
|
||||||
historyCmds: [],
|
historyCmds: [],
|
||||||
@ -120,7 +121,10 @@ function TelemetryWebsocketService($rootScope, $websocket, $timeout, $window, ty
|
|||||||
if (!isReconnect) {
|
if (!isReconnect) {
|
||||||
reconnectSubscribers = [];
|
reconnectSubscribers = [];
|
||||||
for (var id in subscribers) {
|
for (var id in subscribers) {
|
||||||
reconnectSubscribers.push(subscribers[id]);
|
var subscriber = subscribers[id];
|
||||||
|
if (reconnectSubscribers.indexOf(subscriber) === -1) {
|
||||||
|
reconnectSubscribers.push(subscriber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reset(false);
|
reset(false);
|
||||||
isReconnect = true;
|
isReconnect = true;
|
||||||
@ -138,7 +142,7 @@ function TelemetryWebsocketService($rootScope, $websocket, $timeout, $window, ty
|
|||||||
if (data.subscriptionId) {
|
if (data.subscriptionId) {
|
||||||
var subscriber = subscribers[data.subscriptionId];
|
var subscriber = subscribers[data.subscriptionId];
|
||||||
if (subscriber && data) {
|
if (subscriber && data) {
|
||||||
var keys = fetchKeys(subscriber);
|
var keys = fetchKeys(data.subscriptionId);
|
||||||
if (!data.data) {
|
if (!data.data) {
|
||||||
data.data = {};
|
data.data = {};
|
||||||
}
|
}
|
||||||
@ -148,20 +152,15 @@ function TelemetryWebsocketService($rootScope, $websocket, $timeout, $window, ty
|
|||||||
data.data[key] = [];
|
data.data[key] = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
subscriber.onData(data);
|
subscriber.onData(data, data.subscriptionId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkToClose();
|
checkToClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchKeys(subscriber) {
|
function fetchKeys(subscriptionId) {
|
||||||
var command;
|
var command = commands[subscriptionId];
|
||||||
if (angular.isDefined(subscriber.subscriptionCommand)) {
|
|
||||||
command = subscriber.subscriptionCommand;
|
|
||||||
} else {
|
|
||||||
command = subscriber.historyCommand;
|
|
||||||
}
|
|
||||||
if (command && command.keys && command.keys.length > 0) {
|
if (command && command.keys && command.keys.length > 0) {
|
||||||
return command.keys.split(",");
|
return command.keys.split(",");
|
||||||
} else {
|
} else {
|
||||||
@ -176,41 +175,73 @@ function TelemetryWebsocketService($rootScope, $websocket, $timeout, $window, ty
|
|||||||
|
|
||||||
function subscribe (subscriber) {
|
function subscribe (subscriber) {
|
||||||
isActive = true;
|
isActive = true;
|
||||||
var cmdId = nextCmdId();
|
var cmdId;
|
||||||
subscribers[cmdId] = subscriber;
|
if (angular.isDefined(subscriber.subscriptionCommands)) {
|
||||||
subscribersCount++;
|
for (var i=0;i<subscriber.subscriptionCommands.length;i++) {
|
||||||
if (angular.isDefined(subscriber.subscriptionCommand)) {
|
var subscriptionCommand = subscriber.subscriptionCommands[i];
|
||||||
subscriber.subscriptionCommand.cmdId = cmdId;
|
cmdId = nextCmdId();
|
||||||
if (subscriber.type === types.dataKeyType.timeseries) {
|
subscribers[cmdId] = subscriber;
|
||||||
cmdsWrapper.tsSubCmds.push(subscriber.subscriptionCommand);
|
subscriptionCommand.cmdId = cmdId;
|
||||||
} else if (subscriber.type === types.dataKeyType.attribute) {
|
commands[cmdId] = subscriptionCommand;
|
||||||
cmdsWrapper.attrSubCmds.push(subscriber.subscriptionCommand);
|
if (subscriber.type === types.dataKeyType.timeseries) {
|
||||||
|
cmdsWrapper.tsSubCmds.push(subscriptionCommand);
|
||||||
|
} else if (subscriber.type === types.dataKeyType.attribute) {
|
||||||
|
cmdsWrapper.attrSubCmds.push(subscriptionCommand);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (angular.isDefined(subscriber.historyCommand)) {
|
|
||||||
subscriber.historyCommand.cmdId = cmdId;
|
|
||||||
cmdsWrapper.historyCmds.push(subscriber.historyCommand);
|
|
||||||
}
|
}
|
||||||
|
if (angular.isDefined(subscriber.historyCommands)) {
|
||||||
|
for (i=0;i<subscriber.historyCommands.length;i++) {
|
||||||
|
var historyCommand = subscriber.historyCommands[i];
|
||||||
|
cmdId = nextCmdId();
|
||||||
|
subscribers[cmdId] = subscriber;
|
||||||
|
historyCommand.cmdId = cmdId;
|
||||||
|
commands[cmdId] = historyCommand;
|
||||||
|
cmdsWrapper.historyCmds.push(historyCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subscribersCount++;
|
||||||
publishCommands();
|
publishCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
function unsubscribe (subscriber) {
|
function unsubscribe (subscriber) {
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
var cmdId = null;
|
var cmdId = null;
|
||||||
if (subscriber.subscriptionCommand) {
|
if (subscriber.subscriptionCommands) {
|
||||||
subscriber.subscriptionCommand.unsubscribe = true;
|
for (var i=0;i<subscriber.subscriptionCommands.length;i++) {
|
||||||
if (subscriber.type === types.dataKeyType.timeseries) {
|
var subscriptionCommand = subscriber.subscriptionCommands[i];
|
||||||
cmdsWrapper.tsSubCmds.push(subscriber.subscriptionCommand);
|
subscriptionCommand.unsubscribe = true;
|
||||||
} else if (subscriber.type === types.dataKeyType.attribute) {
|
if (subscriber.type === types.dataKeyType.timeseries) {
|
||||||
cmdsWrapper.attrSubCmds.push(subscriber.subscriptionCommand);
|
cmdsWrapper.tsSubCmds.push(subscriptionCommand);
|
||||||
|
} else if (subscriber.type === types.dataKeyType.attribute) {
|
||||||
|
cmdsWrapper.attrSubCmds.push(subscriptionCommand);
|
||||||
|
}
|
||||||
|
cmdId = subscriptionCommand.cmdId;
|
||||||
|
if (cmdId) {
|
||||||
|
if (subscribers[cmdId]) {
|
||||||
|
delete subscribers[cmdId];
|
||||||
|
}
|
||||||
|
if (commands[cmdId]) {
|
||||||
|
delete commands[cmdId];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cmdId = subscriber.subscriptionCommand.cmdId;
|
|
||||||
} else if (subscriber.historyCommand) {
|
|
||||||
cmdId = subscriber.historyCommand.cmdId;
|
|
||||||
}
|
}
|
||||||
if (cmdId && subscribers[cmdId]) {
|
if (subscriber.historyCommands) {
|
||||||
delete subscribers[cmdId];
|
for (i=0;i<subscriber.historyCommands.length;i++) {
|
||||||
subscribersCount--;
|
var historyCommand = subscriber.historyCommands[i];
|
||||||
|
cmdId = historyCommand.cmdId;
|
||||||
|
if (cmdId) {
|
||||||
|
if (subscribers[cmdId]) {
|
||||||
|
delete subscribers[cmdId];
|
||||||
|
}
|
||||||
|
if (commands[cmdId]) {
|
||||||
|
delete commands[cmdId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
subscribersCount--;
|
||||||
publishCommands();
|
publishCommands();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,6 +299,7 @@ function TelemetryWebsocketService($rootScope, $websocket, $timeout, $window, ty
|
|||||||
lastCmdId = 0;
|
lastCmdId = 0;
|
||||||
subscribers = {};
|
subscribers = {};
|
||||||
subscribersCount = 0;
|
subscribersCount = 0;
|
||||||
|
commands = {};
|
||||||
cmdsWrapper.tsSubCmds = [];
|
cmdsWrapper.tsSubCmds = [];
|
||||||
cmdsWrapper.historyCmds = [];
|
cmdsWrapper.historyCmds = [];
|
||||||
cmdsWrapper.attrSubCmds = [];
|
cmdsWrapper.attrSubCmds = [];
|
||||||
|
|||||||
@ -261,7 +261,7 @@ function TimeService($translate, types) {
|
|||||||
return historyTimewindow;
|
return historyTimewindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createSubscriptionTimewindow(timewindow, stDiff, steppedChart) {
|
function createSubscriptionTimewindow(timewindow, stDiff, stateData) {
|
||||||
|
|
||||||
var subscriptionTimewindow = {
|
var subscriptionTimewindow = {
|
||||||
fixedWindow: null,
|
fixedWindow: null,
|
||||||
@ -273,12 +273,12 @@ function TimeService($translate, types) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
var aggTimewindow = 0;
|
var aggTimewindow = 0;
|
||||||
if (steppedChart) {
|
if (stateData) {
|
||||||
subscriptionTimewindow.aggregation = {
|
subscriptionTimewindow.aggregation = {
|
||||||
interval: SECOND,
|
interval: SECOND,
|
||||||
limit: MAX_LIMIT,
|
limit: MAX_LIMIT,
|
||||||
type: types.aggregation.none.value,
|
type: types.aggregation.none.value,
|
||||||
steppedChart: true
|
stateData: true
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
subscriptionTimewindow.aggregation = {
|
subscriptionTimewindow.aggregation = {
|
||||||
@ -288,7 +288,7 @@ function TimeService($translate, types) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (angular.isDefined(timewindow.aggregation) && !steppedChart) {
|
if (angular.isDefined(timewindow.aggregation) && !stateData) {
|
||||||
subscriptionTimewindow.aggregation = {
|
subscriptionTimewindow.aggregation = {
|
||||||
type: timewindow.aggregation.type || types.aggregation.avg.value,
|
type: timewindow.aggregation.type || types.aggregation.avg.value,
|
||||||
limit: timewindow.aggregation.limit || AVG_LIMIT
|
limit: timewindow.aggregation.limit || AVG_LIMIT
|
||||||
|
|||||||
@ -561,7 +561,7 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, $tr
|
|||||||
maxDatasources: -1, //unlimited
|
maxDatasources: -1, //unlimited
|
||||||
maxDataKeys: -1, //unlimited
|
maxDataKeys: -1, //unlimited
|
||||||
dataKeysOptional: false,
|
dataKeysOptional: false,
|
||||||
steppedChart: false
|
stateData: false
|
||||||
};
|
};
|
||||||
' }\n\n' +
|
' }\n\n' +
|
||||||
|
|
||||||
@ -632,8 +632,8 @@ function WidgetService($rootScope, $http, $q, $filter, $ocLazyLoad, $window, $tr
|
|||||||
if (angular.isUndefined(result.typeParameters.dataKeysOptional)) {
|
if (angular.isUndefined(result.typeParameters.dataKeysOptional)) {
|
||||||
result.typeParameters.dataKeysOptional = false;
|
result.typeParameters.dataKeysOptional = false;
|
||||||
}
|
}
|
||||||
if (angular.isUndefined(result.typeParameters.steppedChart)) {
|
if (angular.isUndefined(result.typeParameters.stateData)) {
|
||||||
result.typeParameters.steppedChart = false;
|
result.typeParameters.stateData = false;
|
||||||
}
|
}
|
||||||
if (angular.isFunction(widgetTypeInstance.actionSources)) {
|
if (angular.isFunction(widgetTypeInstance.actionSources)) {
|
||||||
result.actionSources = widgetTypeInstance.actionSources();
|
result.actionSources = widgetTypeInstance.actionSources();
|
||||||
|
|||||||
@ -340,7 +340,7 @@ export default function WidgetController($scope, $state, $timeout, $window, $ele
|
|||||||
if (widget.type !== types.widgetType.rpc.value && widget.type !== types.widgetType.static.value) {
|
if (widget.type !== types.widgetType.rpc.value && widget.type !== types.widgetType.static.value) {
|
||||||
options = {
|
options = {
|
||||||
type: widget.type,
|
type: widget.type,
|
||||||
steppedChart: vm.typeParameters.steppedChart
|
stateData: vm.typeParameters.stateData
|
||||||
}
|
}
|
||||||
if (widget.type == types.widgetType.alarm.value) {
|
if (widget.type == types.widgetType.alarm.value) {
|
||||||
options.alarmSource = angular.copy(widget.config.alarmSource);
|
options.alarmSource = angular.copy(widget.config.alarmSource);
|
||||||
|
|||||||
@ -55,7 +55,7 @@ export default class TbFlot {
|
|||||||
|
|
||||||
var tbFlot = this;
|
var tbFlot = this;
|
||||||
|
|
||||||
function seriesInfoDiv(label, color, value, units, trackDecimals, active, percent) {
|
function seriesInfoDiv(label, color, value, units, trackDecimals, active, percent, valueFormatFunction) {
|
||||||
var divElement = $('<div></div>');
|
var divElement = $('<div></div>');
|
||||||
divElement.css({
|
divElement.css({
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@ -83,7 +83,12 @@ export default class TbFlot {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
divElement.append(labelSpan);
|
divElement.append(labelSpan);
|
||||||
var valueContent = tbFlot.ctx.utils.formatValue(value, trackDecimals, units);
|
var valueContent;
|
||||||
|
if (valueFormatFunction) {
|
||||||
|
valueContent = valueFormatFunction(value);
|
||||||
|
} else {
|
||||||
|
valueContent = tbFlot.ctx.utils.formatValue(value, trackDecimals, units);
|
||||||
|
}
|
||||||
if (angular.isNumber(percent)) {
|
if (angular.isNumber(percent)) {
|
||||||
valueContent += ' (' + Math.round(percent) + ' %)';
|
valueContent += ' (' + Math.round(percent) + ' %)';
|
||||||
}
|
}
|
||||||
@ -107,7 +112,7 @@ export default class TbFlot {
|
|||||||
var units = item.series.dataKey.units && item.series.dataKey.units.length ? item.series.dataKey.units : tbFlot.ctx.trackUnits;
|
var units = item.series.dataKey.units && item.series.dataKey.units.length ? item.series.dataKey.units : tbFlot.ctx.trackUnits;
|
||||||
var decimals = angular.isDefined(item.series.dataKey.decimals) ? item.series.dataKey.decimals : tbFlot.ctx.trackDecimals;
|
var decimals = angular.isDefined(item.series.dataKey.decimals) ? item.series.dataKey.decimals : tbFlot.ctx.trackDecimals;
|
||||||
var divElement = seriesInfoDiv(item.series.dataKey.label, item.series.dataKey.color,
|
var divElement = seriesInfoDiv(item.series.dataKey.label, item.series.dataKey.color,
|
||||||
item.datapoint[1][0][1], units, decimals, true, item.series.percent);
|
item.datapoint[1][0][1], units, decimals, true, item.series.percent, item.series.dataKey.tooltipValueFormatFunction);
|
||||||
return divElement.prop('outerHTML');
|
return divElement.prop('outerHTML');
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@ -132,7 +137,7 @@ export default class TbFlot {
|
|||||||
var units = seriesHoverInfo.units && seriesHoverInfo.units.length ? seriesHoverInfo.units : tbFlot.ctx.trackUnits;
|
var units = seriesHoverInfo.units && seriesHoverInfo.units.length ? seriesHoverInfo.units : tbFlot.ctx.trackUnits;
|
||||||
var decimals = angular.isDefined(seriesHoverInfo.decimals) ? seriesHoverInfo.decimals : tbFlot.ctx.trackDecimals;
|
var decimals = angular.isDefined(seriesHoverInfo.decimals) ? seriesHoverInfo.decimals : tbFlot.ctx.trackDecimals;
|
||||||
var divElement = seriesInfoDiv(seriesHoverInfo.label, seriesHoverInfo.color,
|
var divElement = seriesInfoDiv(seriesHoverInfo.label, seriesHoverInfo.color,
|
||||||
seriesHoverInfo.value, units, decimals, seriesHoverInfo.index === seriesIndex);
|
seriesHoverInfo.value, units, decimals, seriesHoverInfo.index === seriesIndex, null, seriesHoverInfo.tooltipValueFormatFunction);
|
||||||
content += divElement.prop('outerHTML');
|
content += divElement.prop('outerHTML');
|
||||||
}
|
}
|
||||||
return content;
|
return content;
|
||||||
@ -168,7 +173,7 @@ export default class TbFlot {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.chartType === 'line' || this.chartType === 'bar' || this.chartType === 'stepped') {
|
if (this.chartType === 'line' || this.chartType === 'bar' || this.chartType === 'state') {
|
||||||
options.xaxis = {
|
options.xaxis = {
|
||||||
mode: 'time',
|
mode: 'time',
|
||||||
timezone: 'browser',
|
timezone: 'browser',
|
||||||
@ -196,6 +201,9 @@ export default class TbFlot {
|
|||||||
if (settings.yaxis && settings.yaxis.showLabels === false) {
|
if (settings.yaxis && settings.yaxis.showLabels === false) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
if (this.ticksFormatterFunction) {
|
||||||
|
return this.ticksFormatterFunction(value);
|
||||||
|
}
|
||||||
var factor = this.tickDecimals ? Math.pow(10, this.tickDecimals) : 1,
|
var factor = this.tickDecimals ? Math.pow(10, this.tickDecimals) : 1,
|
||||||
formatted = "" + Math.round(value * factor) / factor;
|
formatted = "" + Math.round(value * factor) / factor;
|
||||||
if (this.tickDecimals != null) {
|
if (this.tickDecimals != null) {
|
||||||
@ -218,6 +226,13 @@ export default class TbFlot {
|
|||||||
this.yaxis.labelFont.color = this.yaxis.font.color;
|
this.yaxis.labelFont.color = this.yaxis.font.color;
|
||||||
this.yaxis.labelFont.size = this.yaxis.font.size+2;
|
this.yaxis.labelFont.size = this.yaxis.font.size+2;
|
||||||
this.yaxis.labelFont.weight = "bold";
|
this.yaxis.labelFont.weight = "bold";
|
||||||
|
if (settings.yaxis.ticksFormatter && settings.yaxis.ticksFormatter.length) {
|
||||||
|
try {
|
||||||
|
this.yaxis.ticksFormatterFunction = new Function('value', settings.yaxis.ticksFormatter);
|
||||||
|
} catch (e) {
|
||||||
|
this.yaxis.ticksFormatterFunction = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
options.grid.borderWidth = 1;
|
options.grid.borderWidth = 1;
|
||||||
@ -271,7 +286,7 @@ export default class TbFlot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.chartType === 'stepped') {
|
if (this.chartType === 'state') {
|
||||||
options.series.lines = {
|
options.series.lines = {
|
||||||
steps: true,
|
steps: true,
|
||||||
show: true
|
show: true
|
||||||
@ -331,11 +346,28 @@ export default class TbFlot {
|
|||||||
var colors = [];
|
var colors = [];
|
||||||
this.yaxes = [];
|
this.yaxes = [];
|
||||||
var yaxesMap = {};
|
var yaxesMap = {};
|
||||||
|
|
||||||
|
var tooltipValueFormatFunction = null;
|
||||||
|
if (this.ctx.settings.tooltipValueFormatter && this.ctx.settings.tooltipValueFormatter.length) {
|
||||||
|
try {
|
||||||
|
tooltipValueFormatFunction = new Function('value', this.ctx.settings.tooltipValueFormatter);
|
||||||
|
} catch (e) {
|
||||||
|
tooltipValueFormatFunction = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var i = 0; i < this.subscription.data.length; i++) {
|
for (var i = 0; i < this.subscription.data.length; i++) {
|
||||||
var series = this.subscription.data[i];
|
var series = this.subscription.data[i];
|
||||||
colors.push(series.dataKey.color);
|
colors.push(series.dataKey.color);
|
||||||
var keySettings = series.dataKey.settings;
|
var keySettings = series.dataKey.settings;
|
||||||
|
series.dataKey.tooltipValueFormatFunction = tooltipValueFormatFunction;
|
||||||
|
if (keySettings.tooltipValueFormatter && keySettings.tooltipValueFormatter.length) {
|
||||||
|
try {
|
||||||
|
series.dataKey.tooltipValueFormatFunction = new Function('value', keySettings.tooltipValueFormatter);
|
||||||
|
} catch (e) {
|
||||||
|
series.dataKey.tooltipValueFormatFunction = tooltipValueFormatFunction;
|
||||||
|
}
|
||||||
|
}
|
||||||
series.lines = {
|
series.lines = {
|
||||||
fill: keySettings.fillLines === true,
|
fill: keySettings.fillLines === true,
|
||||||
show: this.chartType === 'line' ? keySettings.showLines !== false : keySettings.showLines === true
|
show: this.chartType === 'line' ? keySettings.showLines !== false : keySettings.showLines === true
|
||||||
@ -389,7 +421,7 @@ export default class TbFlot {
|
|||||||
|
|
||||||
this.options.colors = colors;
|
this.options.colors = colors;
|
||||||
this.options.yaxes = angular.copy(this.yaxes);
|
this.options.yaxes = angular.copy(this.yaxes);
|
||||||
if (this.chartType === 'line' || this.chartType === 'bar' || this.chartType === 'stepped') {
|
if (this.chartType === 'line' || this.chartType === 'bar' || this.chartType === 'state') {
|
||||||
if (this.chartType === 'bar') {
|
if (this.chartType === 'bar') {
|
||||||
this.options.series.bars.barWidth = this.subscription.timeWindow.interval * 0.6;
|
this.options.series.bars.barWidth = this.subscription.timeWindow.interval * 0.6;
|
||||||
}
|
}
|
||||||
@ -432,6 +464,14 @@ export default class TbFlot {
|
|||||||
yaxis.position = position;
|
yaxis.position = position;
|
||||||
|
|
||||||
yaxis.keysInfo = [];
|
yaxis.keysInfo = [];
|
||||||
|
|
||||||
|
if (keySettings.axisTicksFormatter && keySettings.axisTicksFormatter.length) {
|
||||||
|
try {
|
||||||
|
yaxis.ticksFormatterFunction = new Function('value', keySettings.axisTicksFormatter);
|
||||||
|
} catch (e) {
|
||||||
|
yaxis.ticksFormatterFunction = this.yaxis.ticksFormatterFunction;
|
||||||
|
}
|
||||||
|
}
|
||||||
return yaxis;
|
return yaxis;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,7 +482,7 @@ export default class TbFlot {
|
|||||||
}
|
}
|
||||||
if (this.subscription) {
|
if (this.subscription) {
|
||||||
if (!this.isMouseInteraction && this.ctx.plot) {
|
if (!this.isMouseInteraction && this.ctx.plot) {
|
||||||
if (this.chartType === 'line' || this.chartType === 'bar' || this.chartType === 'stepped') {
|
if (this.chartType === 'line' || this.chartType === 'bar' || this.chartType === 'state') {
|
||||||
|
|
||||||
var axisVisibilityChanged = false;
|
var axisVisibilityChanged = false;
|
||||||
if (this.yaxis) {
|
if (this.yaxis) {
|
||||||
@ -654,6 +694,11 @@ export default class TbFlot {
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
|
"tooltipValueFormatter": {
|
||||||
|
"title": "Tooltip value format function, f(value)",
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
"grid": {
|
"grid": {
|
||||||
"title": "Grid settings",
|
"title": "Grid settings",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
@ -739,6 +784,11 @@ export default class TbFlot {
|
|||||||
"title": "Ticks color",
|
"title": "Ticks color",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": null
|
"default": null
|
||||||
|
},
|
||||||
|
"ticksFormatter": {
|
||||||
|
"title": "Ticks formatter function, f(value)",
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -756,6 +806,10 @@ export default class TbFlot {
|
|||||||
"fontSize",
|
"fontSize",
|
||||||
"tooltipIndividual",
|
"tooltipIndividual",
|
||||||
"tooltipCumulative",
|
"tooltipCumulative",
|
||||||
|
{
|
||||||
|
"key": "tooltipValueFormatter",
|
||||||
|
"type": "javascript"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "grid",
|
"key": "grid",
|
||||||
"items": [
|
"items": [
|
||||||
@ -797,6 +851,10 @@ export default class TbFlot {
|
|||||||
{
|
{
|
||||||
"key": "yaxis.color",
|
"key": "yaxis.color",
|
||||||
"type": "color"
|
"type": "color"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "yaxis.ticksFormatter",
|
||||||
|
"type": "javascript"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -830,6 +888,11 @@ export default class TbFlot {
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
},
|
},
|
||||||
|
"tooltipValueFormatter": {
|
||||||
|
"title": "Tooltip value format function, f(value)",
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
"showSeparateAxis": {
|
"showSeparateAxis": {
|
||||||
"title": "Show separate axis",
|
"title": "Show separate axis",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
@ -849,6 +912,11 @@ export default class TbFlot {
|
|||||||
"title": "Axis position",
|
"title": "Axis position",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"default": "left"
|
"default": "left"
|
||||||
|
},
|
||||||
|
"axisTicksFormatter": {
|
||||||
|
"title": "Ticks formatter function, f(value)",
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["showLines", "fillLines", "showPoints"]
|
"required": ["showLines", "fillLines", "showPoints"]
|
||||||
@ -857,6 +925,10 @@ export default class TbFlot {
|
|||||||
"showLines",
|
"showLines",
|
||||||
"fillLines",
|
"fillLines",
|
||||||
"showPoints",
|
"showPoints",
|
||||||
|
{
|
||||||
|
"key": "tooltipValueFormatter",
|
||||||
|
"type": "javascript"
|
||||||
|
},
|
||||||
"showSeparateAxis",
|
"showSeparateAxis",
|
||||||
"axisTitle",
|
"axisTitle",
|
||||||
"axisTickDecimals",
|
"axisTickDecimals",
|
||||||
@ -874,8 +946,11 @@ export default class TbFlot {
|
|||||||
"label": "Right"
|
"label": "Right"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "axisTicksFormatter",
|
||||||
|
"type": "javascript"
|
||||||
}
|
}
|
||||||
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1129,6 +1204,7 @@ export default class TbFlot {
|
|||||||
label: series.dataKey.label,
|
label: series.dataKey.label,
|
||||||
units: series.dataKey.units,
|
units: series.dataKey.units,
|
||||||
decimals: series.dataKey.decimals,
|
decimals: series.dataKey.decimals,
|
||||||
|
tooltipValueFormatFunction: series.dataKey.tooltipValueFormatFunction,
|
||||||
time: pointTime,
|
time: pointTime,
|
||||||
distance: hoverDistance,
|
distance: hoverDistance,
|
||||||
index: i
|
index: i
|
||||||
|
|||||||
@ -130,15 +130,22 @@ function LedIndicatorController($element, $scope, $timeout, utils, types) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.checkStatusMethod = 'checkStatus';
|
vm.performCheckStatus = vm.ctx.settings.performCheckStatus != false;
|
||||||
if (vm.ctx.settings.checkStatusMethod && vm.ctx.settings.checkStatusMethod.length) {
|
if (vm.performCheckStatus) {
|
||||||
vm.checkStatusMethod = vm.ctx.settings.checkStatusMethod;
|
vm.checkStatusMethod = 'checkStatus';
|
||||||
|
if (vm.ctx.settings.checkStatusMethod && vm.ctx.settings.checkStatusMethod.length) {
|
||||||
|
vm.checkStatusMethod = vm.ctx.settings.checkStatusMethod;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!rpcEnabled) {
|
if (!rpcEnabled) {
|
||||||
onError('Target device is not set!');
|
onError('Target device is not set!');
|
||||||
} else {
|
} else {
|
||||||
if (!vm.isSimulated) {
|
if (!vm.isSimulated) {
|
||||||
rpcCheckStatus();
|
if (vm.performCheckStatus) {
|
||||||
|
rpcCheckStatus();
|
||||||
|
} else {
|
||||||
|
subscribeForValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user