diff --git a/application/pom.xml b/application/pom.xml index f62b1c9f5e..8a12fe05bb 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT thingsboard application diff --git a/application/src/main/data/json/demo/dashboards/gateways.json b/application/src/main/data/json/demo/dashboards/gateways.json index 34474ea890..0a18b10a52 100644 --- a/application/src/main/data/json/demo/dashboards/gateways.json +++ b/application/src/main/data/json/demo/dashboards/gateways.json @@ -955,7 +955,7 @@ }, "methodName": "gateway_restart", "methodParams": "{}", - "buttonText": "gateway restart" + "buttonText": "GATEWAY RESTART" }, "title": "New RPC Button", "dropShadow": true, diff --git a/application/src/main/data/json/demo/dashboards/raspberry_pi_gpio_demo_dashboard.json b/application/src/main/data/json/demo/dashboards/raspberry_pi_gpio_demo_dashboard.json deleted file mode 100644 index 1dfba7c8d4..0000000000 --- a/application/src/main/data/json/demo/dashboards/raspberry_pi_gpio_demo_dashboard.json +++ /dev/null @@ -1,700 +0,0 @@ -{ - "title": "Raspberry PI GPIO Demo Dashboard", - "configuration": { - "description": "Demo dashboard for Raspberry PI GPIO Demo", - "widgets": { - "602177f6-267b-cb87-4e8f-e23d7fb2f61c": { - "isSystemType": true, - "bundleAlias": "gpio_widgets", - "typeAlias": "raspberry_pi_gpio_control", - "type": "rpc", - "title": "New widget", - "sizeX": 6, - "sizeY": 10, - "config": { - "targetDeviceAliases": [], - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "0px", - "settings": { - "parseGpioStatusFunction": "return body[pin] === true;", - "gpioStatusChangeRequest": { - "method": "setGpioStatus", - "paramsBody": "{\n \"pin\": \"{$pin}\",\n \"enabled\": \"{$enabled}\"\n}" - }, - "requestTimeout": 500, - "switchPanelBackgroundColor": "#008a00", - "gpioStatusRequest": { - "method": "getGpioStatus", - "paramsBody": "{}" - }, - "gpioList": [ - { - "pin": 7, - "label": "GPIO 4 (GPCLK0)", - "row": 3, - "col": 0, - "_uniqueKey": 0 - }, - { - "pin": 11, - "label": "GPIO 17", - "row": 5, - "col": 0, - "_uniqueKey": 1 - }, - { - "pin": 12, - "label": "GPIO 18", - "row": 5, - "col": 1, - "_uniqueKey": 2 - }, - { - "_uniqueKey": 3, - "pin": 13, - "label": "GPIO 27", - "row": 6, - "col": 0 - }, - { - "_uniqueKey": 4, - "pin": 15, - "label": "GPIO 22", - "row": 7, - "col": 0 - }, - { - "_uniqueKey": 5, - "pin": 16, - "label": "GPIO 23", - "row": 7, - "col": 1 - }, - { - "_uniqueKey": 6, - "pin": 18, - "label": "GPIO 24", - "row": 8, - "col": 1 - }, - { - "_uniqueKey": 7, - "pin": 22, - "label": "GPIO 25", - "row": 10, - "col": 1 - }, - { - "_uniqueKey": 8, - "pin": 29, - "label": "GPIO 5", - "row": 14, - "col": 0 - }, - { - "_uniqueKey": 9, - "pin": 31, - "label": "GPIO 6", - "row": 15, - "col": 0 - }, - { - "_uniqueKey": 10, - "pin": 32, - "label": "GPIO 12", - "row": 15, - "col": 1 - }, - { - "_uniqueKey": 11, - "pin": 33, - "label": "GPIO 13", - "row": 16, - "col": 0 - }, - { - "_uniqueKey": 12, - "pin": 35, - "label": "GPIO 19", - "row": 17, - "col": 0 - }, - { - "_uniqueKey": 13, - "pin": 36, - "label": "GPIO 16", - "row": 17, - "col": 1 - }, - { - "_uniqueKey": 14, - "pin": 37, - "label": "GPIO 26", - "row": 18, - "col": 0 - }, - { - "_uniqueKey": 15, - "pin": 38, - "label": "GPIO 20", - "row": 18, - "col": 1 - }, - { - "_uniqueKey": 16, - "pin": 40, - "label": "GPIO 21", - "row": 19, - "col": 1 - } - ] - }, - "title": "Raspberry Pi GPIO Control Panel", - "datasources": [], - "targetDeviceAliasIds": [ - "f26b12b6-6938-e1a0-85ec-d88a1f23e382" - ] - }, - "row": 0, - "col": 0, - "id": "602177f6-267b-cb87-4e8f-e23d7fb2f61c" - }, - "3cca52a5-e874-eb43-b444-8efa01e663c8": { - "isSystemType": true, - "bundleAlias": "gpio_widgets", - "typeAlias": "raspberry_pi_gpio_panel", - "type": "latest", - "title": "New widget", - "sizeX": 7, - "sizeY": 10, - "config": { - "showTitle": true, - "backgroundColor": "#fff", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "0px", - "settings": { - "gpioList": [ - { - "pin": 1, - "label": "3.3V", - "row": 0, - "col": 0, - "color": "#fc9700", - "_uniqueKey": 0 - }, - { - "pin": 2, - "label": "5V", - "row": 0, - "col": 1, - "color": "#fb0000", - "_uniqueKey": 1 - }, - { - "pin": 3, - "label": "GPIO 2 (I2C1_SDA)", - "row": 1, - "col": 0, - "color": "#02fefb", - "_uniqueKey": 2 - }, - { - "color": "#fb0000", - "pin": 4, - "label": "5V", - "row": 1, - "col": 1 - }, - { - "color": "#02fefb", - "pin": 5, - "label": "GPIO 3 (I2C1_SCL)", - "row": 2, - "col": 0 - }, - { - "color": "#000000", - "pin": 6, - "label": "GND", - "row": 2, - "col": 1 - }, - { - "color": "#00fd00", - "pin": 7, - "label": "GPIO 4 (GPCLK0)", - "row": 3, - "col": 0 - }, - { - "color": "#fdfb00", - "pin": 8, - "label": "GPIO 14 (UART_TXD)", - "row": 3, - "col": 1 - }, - { - "color": "#000000", - "pin": 9, - "label": "GND", - "row": 4, - "col": 0 - }, - { - "color": "#fdfb00", - "pin": 10, - "label": "GPIO 15 (UART_RXD)", - "row": 4, - "col": 1 - }, - { - "color": "#00fd00", - "pin": 11, - "label": "GPIO 17", - "row": 5, - "col": 0 - }, - { - "color": "#00fd00", - "pin": 12, - "label": "GPIO 18", - "row": 5, - "col": 1 - }, - { - "color": "#00fd00", - "pin": 13, - "label": "GPIO 27", - "row": 6, - "col": 0 - }, - { - "color": "#000000", - "pin": 14, - "label": "GND", - "row": 6, - "col": 1 - }, - { - "color": "#00fd00", - "pin": 15, - "label": "GPIO 22", - "row": 7, - "col": 0 - }, - { - "color": "#00fd00", - "pin": 16, - "label": "GPIO 23", - "row": 7, - "col": 1 - }, - { - "color": "#fc9700", - "pin": 17, - "label": "3.3V", - "row": 8, - "col": 0 - }, - { - "color": "#00fd00", - "pin": 18, - "label": "GPIO 24", - "row": 8, - "col": 1 - }, - { - "color": "#fd01fd", - "pin": 19, - "label": "GPIO 10 (SPI_MOSI)", - "row": 9, - "col": 0 - }, - { - "color": "#000000", - "pin": 20, - "label": "GND", - "row": 9, - "col": 1 - }, - { - "color": "#fd01fd", - "pin": 21, - "label": "GPIO 9 (SPI_MISO)", - "row": 10, - "col": 0 - }, - { - "color": "#00fd00", - "pin": 22, - "label": "GPIO 25", - "row": 10, - "col": 1 - }, - { - "color": "#fd01fd", - "pin": 23, - "label": "GPIO 11 (SPI_SCLK)", - "row": 11, - "col": 0 - }, - { - "color": "#fd01fd", - "pin": 24, - "label": "GPIO 8 (SPI_CE0)", - "row": 11, - "col": 1 - }, - { - "color": "#000000", - "pin": 25, - "label": "GND", - "row": 12, - "col": 0 - }, - { - "color": "#fd01fd", - "pin": 26, - "label": "GPIO 7 (SPI_CE1)", - "row": 12, - "col": 1 - }, - { - "color": "#ffffff", - "pin": 27, - "label": "ID_SD", - "row": 13, - "col": 0 - }, - { - "color": "#ffffff", - "pin": 28, - "label": "ID_SC", - "row": 13, - "col": 1 - }, - { - "color": "#00fd00", - "pin": 29, - "label": "GPIO 5", - "row": 14, - "col": 0 - }, - { - "color": "#000000", - "pin": 30, - "label": "GND", - "row": 14, - "col": 1 - }, - { - "color": "#00fd00", - "pin": 31, - "label": "GPIO 6", - "row": 15, - "col": 0 - }, - { - "color": "#00fd00", - "pin": 32, - "label": "GPIO 12", - "row": 15, - "col": 1 - }, - { - "color": "#00fd00", - "pin": 33, - "label": "GPIO 13", - "row": 16, - "col": 0 - }, - { - "color": "#000000", - "pin": 34, - "label": "GND", - "row": 16, - "col": 1 - }, - { - "color": "#00fd00", - "pin": 35, - "label": "GPIO 19", - "row": 17, - "col": 0 - }, - { - "color": "#00fd00", - "pin": 36, - "label": "GPIO 16", - "row": 17, - "col": 1 - }, - { - "color": "#00fd00", - "pin": 37, - "label": "GPIO 26", - "row": 18, - "col": 0 - }, - { - "color": "#00fd00", - "pin": 38, - "label": "GPIO 20", - "row": 18, - "col": 1 - }, - { - "color": "#000000", - "pin": 39, - "label": "GND", - "row": 19, - "col": 0 - }, - { - "color": "#00fd00", - "pin": 40, - "label": "GPIO 21", - "row": 19, - "col": 1 - } - ], - "ledPanelBackgroundColor": "#008a00" - }, - "title": "Raspberry Pi GPIO Status Panel", - "datasources": [ - { - "type": "entity", - "dataKeys": [ - { - "name": "7", - "type": "attribute", - "label": "7", - "color": "#2196f3", - "settings": {}, - "_hash": 0.20925966435886978 - }, - { - "name": "11", - "type": "attribute", - "label": "11", - "color": "#4caf50", - "settings": {}, - "_hash": 0.330267349594344 - }, - { - "name": "12", - "type": "attribute", - "label": "12", - "color": "#f44336", - "settings": {}, - "_hash": 0.5040578704481748 - }, - { - "name": "13", - "type": "attribute", - "label": "13", - "color": "#ffc107", - "settings": {}, - "_hash": 0.588956328191639 - }, - { - "name": "15", - "type": "attribute", - "label": "15", - "color": "#607d8b", - "settings": {}, - "_hash": 0.9229040530336119 - }, - { - "name": "16", - "type": "attribute", - "label": "16", - "color": "#9c27b0", - "settings": {}, - "_hash": 0.8692315253041654 - }, - { - "name": "18", - "type": "attribute", - "label": "18", - "color": "#8bc34a", - "settings": {}, - "_hash": 0.41465562857521543 - }, - { - "name": "22", - "type": "attribute", - "label": "22", - "color": "#3f51b5", - "settings": {}, - "_hash": 0.36135260043112827 - }, - { - "name": "29", - "type": "attribute", - "label": "29", - "color": "#e91e63", - "settings": {}, - "_hash": 0.9904592276182183 - }, - { - "name": "31", - "type": "attribute", - "label": "31", - "color": "#ffeb3b", - "settings": {}, - "_hash": 0.038330985429919195 - }, - { - "name": "32", - "type": "attribute", - "label": "32", - "color": "#03a9f4", - "settings": {}, - "_hash": 0.4334683890135089 - }, - { - "name": "33", - "type": "attribute", - "label": "33", - "color": "#ff9800", - "settings": {}, - "_hash": 0.6487255992492305 - }, - { - "name": "35", - "type": "attribute", - "label": "35", - "color": "#673ab7", - "settings": {}, - "_hash": 0.971555321150732 - }, - { - "name": "36", - "type": "attribute", - "label": "36", - "color": "#cddc39", - "settings": {}, - "_hash": 0.7826129728424382 - }, - { - "name": "37", - "type": "attribute", - "label": "37", - "color": "#009688", - "settings": {}, - "_hash": 0.44925676517537627 - }, - { - "name": "38", - "type": "attribute", - "label": "38", - "color": "#795548", - "settings": {}, - "_hash": 0.051518155759787465 - }, - { - "name": "40", - "type": "attribute", - "label": "40", - "color": "#00bcd4", - "settings": {}, - "_hash": 0.8733296686871144 - } - ], - "name": "RPi", - "entityAliasId": "f26b12b6-6938-e1a0-85ec-d88a1f23e382" - } - ], - "timewindow": { - "realtime": { - "timewindowMs": 60000 - } - } - }, - "row": 0, - "col": 6, - "id": "3cca52a5-e874-eb43-b444-8efa01e663c8" - } - }, - "states": { - "default": { - "name": "Default", - "root": true, - "layouts": { - "main": { - "widgets": { - "602177f6-267b-cb87-4e8f-e23d7fb2f61c": { - "sizeX": 6, - "sizeY": 10, - "row": 0, - "col": 0 - }, - "3cca52a5-e874-eb43-b444-8efa01e663c8": { - "sizeX": 7, - "sizeY": 10, - "row": 0, - "col": 6 - } - }, - "gridSettings": { - "backgroundColor": "#eeeeee", - "color": "rgba(0,0,0,0.870588)", - "columns": 24, - "margins": [ - 10, - 10 - ], - "backgroundSizeMode": "100%" - } - } - } - } - }, - "entityAliases": { - "f26b12b6-6938-e1a0-85ec-d88a1f23e382": { - "id": "f26b12b6-6938-e1a0-85ec-d88a1f23e382", - "alias": "RPi", - "filter": { - "type": "entityName", - "resolveMultiple": false, - "entityType": "DEVICE", - "entityNameFilter": "Raspberry Pi Demo Device" - } - } - }, - "timewindow": { - "displayValue": "", - "selectedTab": 0, - "realtime": { - "interval": 1000, - "timewindowMs": 60000 - }, - "history": { - "historyType": 0, - "interval": 1000, - "timewindowMs": 60000, - "fixedTimewindow": { - "startTimeMs": 1498653734150, - "endTimeMs": 1498740134150 - } - }, - "aggregation": { - "type": "AVG", - "limit": 200 - } - }, - "settings": { - "stateControllerId": "default", - "showTitle": true, - "showDashboardsSelect": true, - "showEntitiesSelect": true, - "showDashboardTimewindow": true, - "showDashboardExport": true, - "toolbarAlwaysOpen": false - } - }, - "name": "Raspberry PI GPIO Demo Dashboard" -} \ No newline at end of file diff --git a/application/src/main/data/json/demo/dashboards/temperature___humidity_demo_dashboard.json b/application/src/main/data/json/demo/dashboards/temperature___humidity_demo_dashboard.json deleted file mode 100644 index 4d4f901558..0000000000 --- a/application/src/main/data/json/demo/dashboards/temperature___humidity_demo_dashboard.json +++ /dev/null @@ -1,264 +0,0 @@ -{ - "title": "Temperature & Humidity Demo Dashboard", - "configuration": { - "description": "Demo dashboard for sample applications that upload temperature and humidity received from DHT11 or DHT22 sensors", - "widgets": { - "03e06986-1c50-e9e4-267c-2bae930ad9a2": { - "isSystemType": true, - "bundleAlias": "digital_gauges", - "typeAlias": "digital_thermometer", - "type": "latest", - "title": "New widget", - "sizeX": 5, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "dataKeys": [ - { - "name": "temperature", - "type": "timeseries", - "label": "temperature", - "color": "#2196f3", - "settings": {}, - "_hash": 0.3720839051412099 - } - ], - "name": "DHT11", - "entityAliasId": "63a93238-c13f-4403-4bcc-9ccc86bd6a62" - } - ], - "timewindow": { - "realtime": { - "timewindowMs": 60000 - } - }, - "showTitle": false, - "backgroundColor": "#000000", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "0px", - "settings": { - "maxValue": 50, - "donutStartAngle": 90, - "showValue": true, - "showMinMax": true, - "gaugeWidthScale": 1, - "levelColors": [ - "#304ffe", - "#7e57c2", - "#ff4081", - "#d32f2f" - ], - "refreshAnimationType": "<>", - "refreshAnimationTime": 700, - "startAnimationType": "<>", - "startAnimationTime": 700, - "titleFont": { - "family": "RobotoDraft", - "size": 12, - "style": "normal", - "weight": "500" - }, - "labelFont": { - "family": "RobotoDraft", - "size": 8, - "style": "normal", - "weight": "500" - }, - "valueFont": { - "family": "Segment7Standard", - "style": "normal", - "weight": "500", - "size": 18 - }, - "minMaxFont": { - "family": "Segment7Standard", - "size": 12, - "style": "normal", - "weight": "500" - }, - "dashThickness": 1.5, - "decimals": 0, - "minValue": 0, - "units": "°C", - "gaugeColor": "#333333", - "neonGlowBrightness": 35, - "gaugeType": "donut", - "showTitle": false - }, - "title": "Temperature" - }, - "row": 0, - "col": 0, - "id": "03e06986-1c50-e9e4-267c-2bae930ad9a2" - }, - "88808eb1-d381-9970-c852-e3499df68bd8": { - "isSystemType": true, - "bundleAlias": "digital_gauges", - "typeAlias": "digital_vertical_bar", - "type": "latest", - "title": "New widget", - "sizeX": 3, - "sizeY": 5, - "config": { - "datasources": [ - { - "type": "entity", - "dataKeys": [ - { - "name": "humidity", - "type": "timeseries", - "label": "humidity", - "color": "#2196f3", - "settings": {}, - "_hash": 0.9492802776509441 - } - ], - "name": "DHT11", - "entityAliasId": "63a93238-c13f-4403-4bcc-9ccc86bd6a62" - } - ], - "timewindow": { - "realtime": { - "timewindowMs": 60000 - } - }, - "showTitle": false, - "backgroundColor": "#000000", - "color": "rgba(0, 0, 0, 0.87)", - "padding": "0px", - "settings": { - "maxValue": 100, - "donutStartAngle": 90, - "showValue": true, - "showMinMax": true, - "gaugeWidthScale": 0.75, - "levelColors": [ - "#3d5afe", - "#f44336" - ], - "refreshAnimationType": "<>", - "refreshAnimationTime": 700, - "startAnimationType": "<>", - "startAnimationTime": 700, - "titleFont": { - "family": "RobotoDraft", - "size": 12, - "style": "normal", - "weight": "500" - }, - "labelFont": { - "family": "RobotoDraft", - "size": 8, - "style": "normal", - "weight": "500" - }, - "valueFont": { - "family": "Segment7Standard", - "style": "normal", - "weight": "500", - "size": 14 - }, - "minMaxFont": { - "family": "Segment7Standard", - "size": 8, - "style": "normal", - "weight": "normal", - "color": "#cccccc" - }, - "neonGlowBrightness": 20, - "decimals": 0, - "showUnitTitle": true, - "gaugeColor": "#171a1c", - "gaugeType": "verticalBar", - "showTitle": false, - "minValue": 0, - "dashThickness": 1.2 - }, - "title": "Humidity" - }, - "row": 0, - "col": 5, - "id": "88808eb1-d381-9970-c852-e3499df68bd8" - } - }, - "states": { - "default": { - "name": "Default", - "root": true, - "layouts": { - "main": { - "widgets": { - "03e06986-1c50-e9e4-267c-2bae930ad9a2": { - "sizeX": 5, - "sizeY": 5, - "row": 0, - "col": 0 - }, - "88808eb1-d381-9970-c852-e3499df68bd8": { - "sizeX": 3, - "sizeY": 5, - "row": 0, - "col": 5 - } - }, - "gridSettings": { - "backgroundColor": "#eeeeee", - "color": "rgba(0,0,0,0.870588)", - "columns": 24, - "margins": [ - 10, - 10 - ], - "backgroundSizeMode": "100%" - } - } - } - } - }, - "entityAliases": { - "63a93238-c13f-4403-4bcc-9ccc86bd6a62": { - "id": "63a93238-c13f-4403-4bcc-9ccc86bd6a62", - "alias": "DHT11", - "filter": { - "type": "entityName", - "resolveMultiple": false, - "entityType": "DEVICE", - "entityNameFilter": "DHT11 Demo Device" - } - } - }, - "timewindow": { - "displayValue": "", - "selectedTab": 0, - "realtime": { - "interval": 1000, - "timewindowMs": 60000 - }, - "history": { - "historyType": 0, - "interval": 1000, - "timewindowMs": 60000, - "fixedTimewindow": { - "startTimeMs": 1498653790019, - "endTimeMs": 1498740190019 - } - }, - "aggregation": { - "type": "AVG", - "limit": 200 - } - }, - "settings": { - "stateControllerId": "default", - "showTitle": true, - "showDashboardsSelect": true, - "showEntitiesSelect": true, - "showDashboardTimewindow": true, - "showDashboardExport": true, - "toolbarAlwaysOpen": false - } - }, - "name": "Temperature & Humidity Demo Dashboard" -} \ No newline at end of file diff --git a/application/src/main/data/json/demo/dashboards/thermostats.json b/application/src/main/data/json/demo/dashboards/thermostats.json index 07b542c3aa..4f486effdf 100644 --- a/application/src/main/data/json/demo/dashboards/thermostats.json +++ b/application/src/main/data/json/demo/dashboards/thermostats.json @@ -147,9 +147,9 @@ "name": "Add", "icon": "add", "type": "customPretty", - "customHtml": "
\n \n

Add thermostat

\n \n \n
\n \n \n
\n
\n \n Thermostat name\n \n \n Thermostat name is required.\n \n \n
\n \n High temperature alarm\n \n \n High temperature threshold, °C\n \n \n High temperature threshold is required.\n \n \n \n \n Low humidity alarm\n \n \n \n Low humidity threshold, %\n \n \n Low humidity threshold is required.\n \n \n
\n
\n
\n \n \n
\n
", + "customHtml": "
\n \n

Add thermostat

\n \n \n
\n \n \n
\n
\n \n Thermostat name\n \n \n Thermostat name is required.\n \n \n
\n \n High temperature alarm\n \n \n High temperature threshold, °C\n \n \n High temperature threshold is required.\n \n \n \n \n Low humidity alarm\n \n \n \n Low humidity threshold, %\n \n \n Low humidity threshold is required.\n \n \n
\n
\n
\n \n \n
\n
", "customCss": ".add-entity-form{\n width: 300px;\n}\n", - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\nlet attributeService = $injector.get(widgetContext.servicesMap.get('attributeService'));\n\nopenAddEntityDialog();\n\nfunction openAddEntityDialog() {\n customDialog.customDialog(htmlTemplate, AddEntityDialogController).subscribe();\n}\n\nfunction AddEntityDialogController(instance) {\n let vm = instance;\n \n vm.addEntityFormGroup = vm.fb.group({\n entityName: ['', [vm.validators.required]],\n attributes: vm.fb.group({\n alarmTemperature: [false],\n thresholdTemperature: [{value: null, disabled: true}],\n alarmHumidity: [false],\n thresholdHumidity: [{value: null, disabled: true}]\n })\n });\n \n vm.addEntityFormGroup.get('attributes').get('alarmTemperature').valueChanges\n .subscribe(activate => {\n if (activate) {\n vm.addEntityFormGroup.get('attributes').get('thresholdTemperature').enable();\n } else {\n vm.addEntityFormGroup.get('attributes').get('thresholdTemperature').disable();\n }\n });\n \n vm.addEntityFormGroup.get('attributes').get('alarmHumidity').valueChanges\n .subscribe(activate => {\n if (activate) {\n vm.addEntityFormGroup.get('attributes').get('thresholdHumidity').enable();\n } else {\n vm.addEntityFormGroup.get('attributes').get('thresholdHumidity').disable();\n }\n });\n\n vm.save = function() {\n vm.addEntityFormGroup.markAsPristine();\n saveEntityObservable().subscribe(\n function (entity) {\n saveAttributes(entity.id).subscribe(\n function () {\n widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n }\n );\n };\n \n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n \n function saveEntityObservable() {\n const formValues = vm.addEntityFormGroup.value;\n let entity = {\n name: formValues.entityName,\n type: \"thermostat\"\n };\n return deviceService.saveDevice(entity);\n }\n \n function saveAttributes(entityId) {\n let attributes = vm.addEntityFormGroup.get('attributes').value;\n let attributesArray = [];\n for (let key in attributes) {\n if(attributes[key] !== null) {\n attributesArray.push({key: key, value: attributes[key]});\n }\n }\n if (attributesArray.length > 0) {\n return attributeService.saveEntityAttributes(entityId, \"SERVER_SCOPE\", attributesArray);\n } else {\n return widgetContext.rxjs.of([]);\n }\n }\n}", + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet deviceService = $injector.get(widgetContext.servicesMap.get('deviceService'));\nlet attributeService = $injector.get(widgetContext.servicesMap.get('attributeService'));\n\nopenAddEntityDialog();\n\nfunction openAddEntityDialog() {\n customDialog.customDialog(htmlTemplate, AddEntityDialogController).subscribe();\n}\n\nfunction AddEntityDialogController(instance) {\n let vm = instance;\n \n vm.addEntityFormGroup = vm.fb.group({\n entityName: ['', [vm.validators.required]],\n attributes: vm.fb.group({\n temperatureAlarmFlag: [false],\n temperatureAlarmThreshold: [{value: null, disabled: true}],\n humidityAlarmFlag: [false],\n humidityAlarmThreshold: [{value: null, disabled: true}]\n })\n });\n \n vm.addEntityFormGroup.get('attributes').get('temperatureAlarmFlag').valueChanges\n .subscribe(activate => {\n if (activate) {\n vm.addEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').enable();\n } else {\n vm.addEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').disable();\n }\n });\n \n vm.addEntityFormGroup.get('attributes').get('humidityAlarmFlag').valueChanges\n .subscribe(activate => {\n if (activate) {\n vm.addEntityFormGroup.get('attributes').get('humidityAlarmThreshold').enable();\n } else {\n vm.addEntityFormGroup.get('attributes').get('humidityAlarmThreshold').disable();\n }\n });\n\n vm.save = function() {\n vm.addEntityFormGroup.markAsPristine();\n saveEntityObservable().subscribe(\n function (entity) {\n saveAttributes(entity.id).subscribe(\n function () {\n widgetContext.updateAliases();\n vm.dialogRef.close(null);\n }\n );\n }\n );\n };\n \n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n \n function saveEntityObservable() {\n const formValues = vm.addEntityFormGroup.value;\n let entity = {\n name: formValues.entityName,\n type: \"thermostat\"\n };\n return deviceService.saveDevice(entity);\n }\n \n function saveAttributes(entityId) {\n let attributes = vm.addEntityFormGroup.get('attributes').value;\n let attributesArray = [];\n for (let key in attributes) {\n if(attributes[key] !== null) {\n attributesArray.push({key: key, value: attributes[key]});\n }\n }\n if (attributesArray.length > 0) {\n return attributeService.saveEntityAttributes(entityId, \"SERVER_SCOPE\", attributesArray);\n } else {\n return widgetContext.rxjs.of([]);\n }\n }\n}", "customResources": [], "id": "8ab5a518-67d2-b6a2-956d-81fd512294b2" } @@ -167,9 +167,9 @@ "name": "Edit", "icon": "edit", "type": "customPretty", - "customHtml": "
\n \n

Edit thermostat {{entityName}}

\n \n \n
\n \n \n
\n
\n \n Thermostat name\n \n \n
\n \n High temperature alarm\n \n \n High temperature threshold, °C\n \n \n High temperature threshold is required.\n \n \n\n \n Low humidity alarm\n \n\n \n Low humidity threshold, %\n \n \n Low humidity threshold is required.\n \n \n
\n
\n
\n \n \n
\n
", + "customHtml": "
\n \n

Edit thermostat {{entityName}}

\n \n \n
\n \n \n
\n
\n \n Thermostat name\n \n \n
\n \n High temperature alarm\n \n \n High temperature threshold, °C\n \n \n High temperature threshold is required.\n \n \n\n \n Low humidity alarm\n \n\n \n Low humidity threshold, %\n \n \n Low humidity threshold is required.\n \n \n
\n
\n
\n \n \n
\n
", "customCss": ".edit-entity-form{\n width: 300px;\n}", - "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet attributeService = $injector.get(widgetContext.servicesMap.get('attributeService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n \n vm.entityId = entityId;\n vm.entityName = entityName;\n vm.attributes = {};\n \n vm.editEntityFormGroup = vm.fb.group({\n entityName: [''],\n attributes: vm.fb.group({\n alarmTemperature: [false],\n thresholdTemperature: [{value: null, disabled: true}],\n alarmHumidity: [false],\n thresholdHumidity: [{value: null, disabled: true}]\n })\n });\n \n vm.editEntityFormGroup.get('attributes').get('alarmTemperature').valueChanges\n .subscribe(activate => {\n if (activate) {\n vm.editEntityFormGroup.get('attributes').get('thresholdTemperature').enable();\n } else {\n vm.editEntityFormGroup.get('attributes').get('thresholdTemperature').disable();\n }\n });\n \n vm.editEntityFormGroup.get('attributes').get('alarmHumidity').valueChanges\n .subscribe(activate => {\n if (activate) {\n vm.editEntityFormGroup.get('attributes').get('thresholdHumidity').enable();\n } else {\n vm.editEntityFormGroup.get('attributes').get('thresholdHumidity').disable();\n }\n });\n \n \n getEntityInfo();\n \n \n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveAttributes(entityId).subscribe(\n function () {\n vm.dialogRef.close(null);\n }\n );\n };\n \n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n \n function getEntityAttributes(attributes) {\n for (var i = 0; i < attributes.length; i++) {\n vm.attributes[attributes[i].key] = attributes[i].value;\n }\n }\n \n function getEntityInfo() {\n attributeService.getEntityAttributes(entityId, 'SERVER_SCOPE').subscribe(\n function (attributes) {\n getEntityAttributes(attributes);\n vm.editEntityFormGroup.patchValue({\n entityName: vm.entityName,\n attributes: vm.attributes\n });\n // if(vm.attributes.alarmTemperature) {\n // vm.editEntityFormGroup.get('attributes').get('thresholdTemperature').enable();\n // }\n // if(vm.attributes.alarmHumidity) {\n // vm.editEntityFormGroup.get('attributes').get('thresholdHumidity').enable();\n // }\n }\n );\n }\n \n function saveAttributes(entityId) {\n let attributes = vm.editEntityFormGroup.get('attributes').value;\n let attributesArray = [];\n for (let key in attributes) {\n if (attributes[key] !== vm.attributes[key]) {\n attributesArray.push({key: key, value: attributes[key]});\n }\n }\n if (attributesArray.length > 0) {\n return attributeService.saveEntityAttributes(entityId, \"SERVER_SCOPE\", attributesArray);\n } else {\n return widgetContext.rxjs.of([]);\n }\n }\n}", + "customFunction": "let $injector = widgetContext.$scope.$injector;\nlet customDialog = $injector.get(widgetContext.servicesMap.get('customDialog'));\nlet attributeService = $injector.get(widgetContext.servicesMap.get('attributeService'));\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n customDialog.customDialog(htmlTemplate, EditEntityDialogController).subscribe();\n}\n\nfunction EditEntityDialogController(instance) {\n let vm = instance;\n \n vm.entityId = entityId;\n vm.entityName = entityName;\n vm.attributes = {};\n \n vm.editEntityFormGroup = vm.fb.group({\n entityName: [''],\n attributes: vm.fb.group({\n temperatureAlarmFlag: [false],\n temperatureAlarmThreshold: [{value: null, disabled: true}],\n humidityAlarmFlag: [false],\n humidityAlarmThreshold: [{value: null, disabled: true}]\n })\n });\n \n vm.editEntityFormGroup.get('attributes').get('temperatureAlarmFlag').valueChanges\n .subscribe(activate => {\n if (activate) {\n vm.editEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').enable();\n } else {\n vm.editEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').disable();\n }\n });\n \n vm.editEntityFormGroup.get('attributes').get('humidityAlarmFlag').valueChanges\n .subscribe(activate => {\n if (activate) {\n vm.editEntityFormGroup.get('attributes').get('humidityAlarmThreshold').enable();\n } else {\n vm.editEntityFormGroup.get('attributes').get('humidityAlarmThreshold').disable();\n }\n });\n \n \n getEntityInfo();\n \n \n vm.save = function() {\n vm.editEntityFormGroup.markAsPristine();\n saveAttributes(entityId).subscribe(\n function () {\n vm.dialogRef.close(null);\n }\n );\n };\n \n vm.cancel = function() {\n vm.dialogRef.close(null);\n };\n \n function getEntityAttributes(attributes) {\n for (var i = 0; i < attributes.length; i++) {\n vm.attributes[attributes[i].key] = attributes[i].value;\n }\n }\n \n function getEntityInfo() {\n attributeService.getEntityAttributes(entityId, 'SERVER_SCOPE').subscribe(\n function (attributes) {\n getEntityAttributes(attributes);\n vm.editEntityFormGroup.patchValue({\n entityName: vm.entityName,\n attributes: vm.attributes\n });\n // if(vm.attributes.temperatureAlarmFlag) {\n // vm.editEntityFormGroup.get('attributes').get('temperatureAlarmThreshold').enable();\n // }\n // if(vm.attributes.humidityAlarmFlag) {\n // vm.editEntityFormGroup.get('attributes').get('humidityAlarmThreshold').enable();\n // }\n }\n );\n }\n \n function saveAttributes(entityId) {\n let attributes = vm.editEntityFormGroup.get('attributes').value;\n let attributesArray = [];\n for (let key in attributes) {\n if (attributes[key] !== vm.attributes[key]) {\n attributesArray.push({key: key, value: attributes[key]});\n }\n }\n if (attributesArray.length > 0) {\n return attributeService.saveEntityAttributes(entityId, \"SERVER_SCOPE\", attributesArray);\n } else {\n return widgetContext.rxjs.of([]);\n }\n }\n}", "customResources": [], "id": "7506576f-87ba-d3a0-88fb-e304d451776d" }, @@ -550,7 +550,7 @@ "type": "entity", "dataKeys": [ { - "name": "alarmTemperature", + "name": "temperatureAlarmFlag", "type": "attribute", "label": "High temperature alarm", "color": "#4caf50", @@ -565,7 +565,7 @@ "_hash": 0.8725278440159361 }, { - "name": "thresholdTemperature", + "name": "temperatureAlarmThreshold", "type": "attribute", "label": "High temperature threshold, °C", "color": "#f44336", @@ -576,12 +576,12 @@ "isEditable": "editable", "dataKeyHidden": false, "step": 1, - "disabledOnDataKey": "alarmTemperature" + "disabledOnDataKey": "temperatureAlarmFlag" }, "_hash": 0.7316078472857874 }, { - "name": "alarmHumidity", + "name": "humidityAlarmFlag", "type": "attribute", "label": "Low humidity alarm", "color": "#ffc107", @@ -596,7 +596,7 @@ "_hash": 0.5339673667431057 }, { - "name": "thresholdHumidity", + "name": "humidityAlarmThreshold", "type": "attribute", "label": "Low humidity threshold, %", "color": "#607d8b", @@ -607,7 +607,7 @@ "isEditable": "editable", "dataKeyHidden": false, "step": 1, - "disabledOnDataKey": "alarmHumidity" + "disabledOnDataKey": "humidityAlarmFlag" }, "_hash": 0.2687091190358901 } diff --git a/application/src/main/data/json/demo/rule_chains/root_rule_chain.json b/application/src/main/data/json/demo/rule_chains/root_rule_chain.json deleted file mode 100644 index 97ad46c756..0000000000 --- a/application/src/main/data/json/demo/rule_chains/root_rule_chain.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "ruleChain": { - "additionalInfo": null, - "name": "Root Rule Chain", - "firstRuleNodeId": null, - "root": true, - "debugMode": false, - "configuration": null - }, - "metadata": { - "firstNodeIndex": 3, - "nodes": [ - { - "additionalInfo": { - "layoutX": 1069, - "layoutY": 267 - }, - "type": "org.thingsboard.rule.engine.filter.TbJsFilterNode", - "name": "Is Thermostat?", - "debugMode": false, - "configuration": { - "jsScript": "return msg.id.entityType === \"DEVICE\" && msg.type === \"thermostat\";" - } - }, - { - "additionalInfo": { - "layoutX": 824, - "layoutY": 156 - }, - "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", - "name": "Save Timeseries", - "debugMode": false, - "configuration": { - "defaultTTL": 0 - } - }, - { - "additionalInfo": { - "layoutX": 825, - "layoutY": 52 - }, - "type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode", - "name": "Save Client Attributes", - "debugMode": false, - "configuration": { - "scope": "CLIENT_SCOPE", - "notifyDevice": "false" - } - }, - { - "additionalInfo": { - "layoutX": 347, - "layoutY": 149 - }, - "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode", - "name": "Message Type Switch", - "debugMode": false, - "configuration": { - "version": 0 - } - }, - { - "additionalInfo": { - "layoutX": 839, - "layoutY": 345 - }, - "type": "org.thingsboard.rule.engine.action.TbLogNode", - "name": "Log RPC from Device", - "debugMode": false, - "configuration": { - "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" - } - }, - { - "additionalInfo": { - "layoutX": 832, - "layoutY": 407 - }, - "type": "org.thingsboard.rule.engine.action.TbLogNode", - "name": "Log Other", - "debugMode": false, - "configuration": { - "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" - } - }, - { - "additionalInfo": { - "layoutX": 825, - "layoutY": 468 - }, - "type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode", - "name": "RPC Call Request", - "debugMode": false, - "configuration": { - "timeoutInSeconds": 60 - } - }, - { - "additionalInfo": { - "layoutX": 1069, - "layoutY": 90 - }, - "type": "org.thingsboard.rule.engine.filter.TbJsFilterNode", - "name": "Is Thermostat?", - "debugMode": false, - "configuration": { - "jsScript": "return metadata[\"deviceType\"] === \"thermostat\";" - } - }, - { - "additionalInfo": { - "layoutX": 1090, - "layoutY": 360 - }, - "type": "org.thingsboard.rule.engine.action.TbCreateRelationNode", - "name": "Relate to Asset", - "debugMode": false, - "configuration": { - "direction": "FROM", - "relationType": "ToAlarmPropagationAsset", - "entityType": "ASSET", - "entityNamePattern": "Thermostat Alarms", - "entityTypePattern": "AlarmPropagationAsset", - "entityCacheExpiration": 300, - "createEntityIfNotExists": true, - "changeOriginatorToRelatedEntity": false, - "removeCurrentRelations": false - } - } - ], - "connections": [ - { - "fromIndex": 0, - "toIndex": 8, - "type": "True" - }, - { - "fromIndex": 1, - "toIndex": 7, - "type": "Success" - }, - { - "fromIndex": 3, - "toIndex": 5, - "type": "Other" - }, - { - "fromIndex": 3, - "toIndex": 2, - "type": "Post attributes" - }, - { - "fromIndex": 3, - "toIndex": 1, - "type": "Post telemetry" - }, - { - "fromIndex": 3, - "toIndex": 4, - "type": "RPC Request from Device" - }, - { - "fromIndex": 3, - "toIndex": 6, - "type": "RPC Request to Device" - }, - { - "fromIndex": 3, - "toIndex": 0, - "type": "Entity Created" - } - ], - "ruleChainConnections": [ - { - "fromIndex": 7, - "targetRuleChainId": { - "entityType": "RULE_CHAIN", - "id": "25e26570-89ed-11ea-a650-cd6e14e633bd" - }, - "additionalInfo": { - "layoutX": 1109, - "layoutY": 182, - "ruleChainNodeId": "rule-chain-node-10" - }, - "type": "True" - } - ] - } -} \ No newline at end of file diff --git a/application/src/main/data/json/demo/rule_chains/thermostat_alarms.json b/application/src/main/data/json/demo/rule_chains/thermostat_alarms.json deleted file mode 100644 index 30812d6003..0000000000 --- a/application/src/main/data/json/demo/rule_chains/thermostat_alarms.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "ruleChain": { - "additionalInfo": { - "description": "" - }, - "name": "Thermostat Alarms", - "firstRuleNodeId": null, - "root": false, - "debugMode": false, - "configuration": null - }, - "metadata": { - "firstNodeIndex": 6, - "nodes": [ - { - "additionalInfo": { - "layoutX": 822, - "layoutY": 294 - }, - "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode", - "name": "Save Timeseries", - "debugMode": false, - "configuration": { - "defaultTTL": 0 - } - }, - { - "additionalInfo": { - "description": null, - "layoutX": 824, - "layoutY": 221 - }, - "type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode", - "name": "Save Client Attributes", - "debugMode": false, - "configuration": { - "scope": "SERVER_SCOPE", - "notifyDevice": null - } - }, - { - "additionalInfo": { - "layoutX": 494, - "layoutY": 309 - }, - "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode", - "name": "Message Type Switch", - "debugMode": false, - "configuration": { - "version": 0 - } - }, - { - "additionalInfo": { - "layoutX": 824, - "layoutY": 383 - }, - "type": "org.thingsboard.rule.engine.action.TbLogNode", - "name": "Log RPC from Device", - "debugMode": false, - "configuration": { - "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" - } - }, - { - "additionalInfo": { - "layoutX": 823, - "layoutY": 444 - }, - "type": "org.thingsboard.rule.engine.action.TbLogNode", - "name": "Log Other", - "debugMode": false, - "configuration": { - "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);" - } - }, - { - "additionalInfo": { - "layoutX": 822, - "layoutY": 507 - }, - "type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode", - "name": "RPC Call Request", - "debugMode": false, - "configuration": { - "timeoutInSeconds": 60 - } - }, - { - "additionalInfo": { - "description": "", - "layoutX": 209, - "layoutY": 307 - }, - "type": "org.thingsboard.rule.engine.profile.TbDeviceProfileNode", - "name": "Device Profile Node", - "debugMode": false, - "configuration": { - "persistAlarmRulesState": false, - "fetchAlarmRulesStateOnStart": false - } - } - ], - "connections": [ - { - "fromIndex": 2, - "toIndex": 4, - "type": "Other" - }, - { - "fromIndex": 2, - "toIndex": 1, - "type": "Post attributes" - }, - { - "fromIndex": 2, - "toIndex": 0, - "type": "Post telemetry" - }, - { - "fromIndex": 2, - "toIndex": 3, - "type": "RPC Request from Device" - }, - { - "fromIndex": 2, - "toIndex": 5, - "type": "RPC Request to Device" - }, - { - "fromIndex": 6, - "toIndex": 2, - "type": "Success" - } - ], - "ruleChainConnections": null - } -} \ No newline at end of file diff --git a/application/src/main/data/json/system/widget_bundles/input_widgets.json b/application/src/main/data/json/system/widget_bundles/input_widgets.json index 097c31dac4..4ed3c2fab6 100644 --- a/application/src/main/data/json/system/widget_bundles/input_widgets.json +++ b/application/src/main/data/json/system/widget_bundles/input_widgets.json @@ -33,7 +33,7 @@ "templateCss": ".tb-toast {\n min-width: 0;\n font-size: 14px !important;\n}", "controllerScript": "self.onInit = function() {\r\n}\r\n\r\nself.onDataUpdated = function() {\r\n self.ctx.$scope.multipleInputWidget.onDataUpdated();\r\n}\r\n", "settingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"MultipleInput\",\n \"properties\": {\n \"widgetTitle\": {\n \"title\": \"Widget title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showActionButtons\":{\n \"title\":\"Show action buttons\",\n \"type\":\"boolean\",\n \"default\": true\n },\n \"updateAllValues\": {\n \"title\":\"Update all values, not only modified\",\n \"type\":\"boolean\",\n \"default\": false\n },\n \"saveButtonLabel\": {\n \"title\": \"'SAVE' button label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"resetButtonLabel\": {\n \"title\": \"'UNDO' button label\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"showResultMessage\":{\n \"title\":\"Show result message\",\n \"type\":\"boolean\",\n \"default\": true\n },\n \"showGroupTitle\": {\n \"title\":\"Show title for group of fields, related to different entities\",\n \"type\":\"boolean\",\n \"default\": false\n },\n \"groupTitle\": {\n \"title\": \"Group title\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"fieldsAlignment\": {\n \"title\": \"Fields alignment\",\n \"type\": \"string\",\n \"default\": \"row\"\n },\n \"fieldsInRow\": {\n \"title\": \"Number of fields in the row\",\n \"type\": \"number\",\n \"default\": \"2\"\n }\n },\n \"required\": []\n },\n \"form\": [\n \"widgetTitle\",\n \"showActionButtons\",\n {\n \"key\": \"updateAllValues\",\n \"condition\": \"model.showActionButtons === true\"\n },\n {\n \"key\": \"saveButtonLabel\",\n \"condition\": \"model.showActionButtons === true\"\n },\n {\n \"key\": \"resetButtonLabel\",\n \"condition\": \"model.showActionButtons === true\"\n },\n \"showResultMessage\",\n \"showGroupTitle\",\n \"groupTitle\",\n {\n \"key\": \"fieldsAlignment\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"row\",\n \"label\": \"Row (default)\"\n },\n {\n \"value\": \"column\",\n \"label\": \"Column\"\n }\n ]\n },\n {\n \"key\": \"fieldsInRow\",\n \"condition\": \"model.fieldsAlignment === 'row'\"\n }\n ]\n}", - "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"dataKeyType\": {\n \"title\": \"Datakey type\",\n \"type\": \"string\",\n \"default\": \"server\"\n },\n \"dataKeyValueType\": {\n \"title\": \"Datakey value type\",\n \"type\": \"string\",\n \"default\": \"string\"\n },\n \"step\": {\n \"title\": \"Step interval between values\",\n \"type\": \"number\",\n \"default\": \"1\"\n },\n \"minValue\": {\n \"title\": \"Minimum value\",\n \"type\": \"number\"\n },\n \"maxValue\": {\n \"title\": \"Maximum value\",\n \"type\": \"number\"\n },\n \"required\": {\n \"title\": \"Value is required\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"minValueErrorMessage\": {\n \"title\": \"'Min Value' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValueErrorMessage\": {\n \"title\": \"'Max Value' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"invalidDateErrorMessage\": {\n \"title\": \"'Invalid Date' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"selectOptionsType\": {\n \"title\": \"Select options type\",\n \"type\": \"string\",\n \"default\": \"valueWithLabel\"\n },\n \"selectOptionsList\": {\n \"title\": \"Select options list\",\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"value\": {\n \"title\": \"Value\",\n \"type\": \"string\"\n },\n \"label\": {\n \"title\": \"Label\",\n \"type\": \"string\"\n }\n },\n \"required\": [\"value\", \"label\"]\n }\n },\n \"isEditable\": {\n \"title\": \"Ability to edit attribute\",\n \"type\": \"string\",\n \"default\": \"editable\"\n },\n \"disabledOnDataKey\": {\n \"title\": \"Disable on false value of another datakey (specify datakey name)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"dataKeyHidden\": {\n \"title\": \"Hide input field\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"icon\": {\n \"title\": \"Icon to show before input cell\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"dataKeyType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"server\",\n \"label\": \"Server attribute (default)\"\n },\n {\n \"value\": \"shared\",\n \"label\": \"Shared attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Timeseries\"\n }\n ]\n },\n {\n \"key\": \"dataKeyValueType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"string\",\n \"label\": \"String\"\n },\n {\n \"value\": \"double\",\n \"label\": \"Double\"\n },\n {\n \"value\": \"integer\",\n \"label\": \"Integer\"\n },\n {\n \"value\": \"booleanCheckbox\",\n \"label\": \"Boolean (Checkbox)\"\n },\n {\n \"value\": \"booleanSwitch\",\n \"label\": \"Boolean (Switch)\"\n },\n {\n \"value\": \"dateTime\",\n \"label\": \"Date & Time\"\n },\n {\n \"value\": \"date\",\n \"label\": \"Date\"\n },\n {\n \"value\": \"time\",\n \"label\": \"Time\"\n },\n {\n \"value\": \"selectOption\",\n \"label\": \"Selectable option\"\n }\n ]\n },\n {\n \"key\": \"selectOptionsType\",\n \"condition\": \"model.dataKeyValueType === 'selectOption'\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"valueWithLabel\",\n \"label\": \"Values with labels\"\n },\n {\n \"value\": \"rawValue\",\n \"label\": \"Raw values\"\n }\n ]\n },\n {\n \"key\": \"selectOptionsList\",\n \"type\": \"array\",\n \"condition\": \"model.dataKeyValueType === 'selectOption'\",\n \"items\": [\n \"selectOptionsList[].value\",\n {\n \"key\": \"selectOptionsList[].label\",\n \"condition\": \"model.selectOptionsType === 'valueWithLabel'\"\n }\n ]\n },\n {\n \"key\": \"step\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"minValue\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"maxValue\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n \"required\",\n {\n \"key\": \"requiredErrorMessage\",\n \"condition\": \"model.required === true\"\n },\n {\n \"key\": \"invalidDateErrorMessage\",\n \"condition\": \"model.dataKeyValueType === 'dateTime' || model.dataKeyValueType === 'date' || model.dataKeyValueType === 'time'\"\n },\n {\n \"key\": \"minValueErrorMessage\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"maxValueErrorMessage\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"isEditable\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"editable\",\n \"label\": \"Editable (default)\"\n },\n {\n \"value\": \"disabled\",\n \"label\": \"Disabled\"\n },\n {\n \"value\": \"readonly\",\n \"label\": \"Read-only\"\n }\n ]\n },\n \"disabledOnDataKey\",\n \"dataKeyHidden\",\n\t\t{\n \t\t\"key\": \"icon\",\n\t\t\t\"type\": \"icon\"\n\t\t}\n ]\n}\n", + "dataKeySettingsSchema": "{\n \"schema\": {\n \"type\": \"object\",\n \"title\": \"DataKeySettings\",\n \"properties\": {\n \"dataKeyType\": {\n \"title\": \"Datakey type\",\n \"type\": \"string\",\n \"default\": \"server\"\n },\n \"dataKeyValueType\": {\n \"title\": \"Datakey value type\",\n \"type\": \"string\",\n \"default\": \"string\"\n },\n \"step\": {\n \"title\": \"Step interval between values\",\n \"type\": \"number\",\n \"default\": \"1\"\n },\n \"minValue\": {\n \"title\": \"Minimum value\",\n \"type\": \"number\"\n },\n \"maxValue\": {\n \"title\": \"Maximum value\",\n \"type\": \"number\"\n },\n \"required\": {\n \"title\": \"Value is required\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"requiredErrorMessage\": {\n \"title\": \"'Required' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"minValueErrorMessage\": {\n \"title\": \"'Min Value' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"maxValueErrorMessage\": {\n \"title\": \"'Max Value' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"invalidDateErrorMessage\": {\n \"title\": \"'Invalid Date' error message\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"isEditable\": {\n \"title\": \"Ability to edit attribute\",\n \"type\": \"string\",\n \"default\": \"editable\"\n },\n \"disabledOnDataKey\": {\n \"title\": \"Disable on false value of another datakey (specify datakey name)\",\n \"type\": \"string\",\n \"default\": \"\"\n },\n \"dataKeyHidden\": {\n \"title\": \"Hide input field\",\n \"type\": \"boolean\",\n \"default\": false\n },\n \"icon\": {\n \"title\": \"Icon to show before input cell\",\n \"type\": \"string\",\n \"default\": \"\"\n }\n },\n \"required\": []\n },\n \"form\": [\n {\n \"key\": \"dataKeyType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"server\",\n \"label\": \"Server attribute (default)\"\n },\n {\n \"value\": \"shared\",\n \"label\": \"Shared attribute\"\n },\n {\n \"value\": \"timeseries\",\n \"label\": \"Timeseries\"\n }\n ]\n },\n {\n \"key\": \"dataKeyValueType\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"string\",\n \"label\": \"String\"\n },\n {\n \"value\": \"double\",\n \"label\": \"Double\"\n },\n {\n \"value\": \"integer\",\n \"label\": \"Integer\"\n },\n {\n \"value\": \"booleanCheckbox\",\n \"label\": \"Boolean (Checkbox)\"\n },\n {\n \"value\": \"booleanSwitch\",\n \"label\": \"Boolean (Switch)\"\n },\n {\n \"value\": \"dateTime\",\n \"label\": \"Date & Time\"\n },\n {\n \"value\": \"date\",\n \"label\": \"Date\"\n },\n {\n \"value\": \"time\",\n \"label\": \"Time\"\n }\n ]\n },\n {\n \"key\": \"step\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"minValue\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"maxValue\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n \"required\",\n {\n \"key\": \"requiredErrorMessage\",\n \"condition\": \"model.required === true\"\n },\n {\n \"key\": \"invalidDateErrorMessage\",\n \"condition\": \"model.dataKeyValueType === 'dateTime' || model.dataKeyValueType === 'date' || model.dataKeyValueType === 'time'\"\n },\n {\n \"key\": \"minValueErrorMessage\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"maxValueErrorMessage\",\n \"condition\": \"model.dataKeyValueType === 'double' || model.dataKeyValueType === 'integer'\"\n },\n {\n \"key\": \"isEditable\",\n \"type\": \"rc-select\",\n \"multiple\": false,\n \"items\": [\n {\n \"value\": \"editable\",\n \"label\": \"Editable (default)\"\n },\n {\n \"value\": \"disabled\",\n \"label\": \"Disabled\"\n },\n {\n \"value\": \"readonly\",\n \"label\": \"Read-only\"\n }\n ]\n },\n \"disabledOnDataKey\",\n \"dataKeyHidden\",\n\t\t{\n \t\t\"key\": \"icon\",\n\t\t\t\"type\": \"icon\"\n\t\t}\n ]\n}\n", "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Sin\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.23592248334107624,\"funcBody\":\"return Math.round(1000*Math.sin(time/5000));\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Update Multiple Attributes\",\"dropShadow\":true,\"enableFullscreen\":false,\"enableDataExport\":false,\"widgetStyle\":{},\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false,\"actions\":{}}" } }, diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java index e645339e0b..afe929f6b1 100644 --- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java +++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/DefaultTbContext.java @@ -39,6 +39,7 @@ import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.DeviceId; @@ -510,14 +511,25 @@ class DefaultTbContext implements TbContext { mainCtx.getRuleNodeStateService().removeByRuleNodeIdAndEntityId(getTenantId(), getSelfId(), entityId); } + @Override + public void addTenantProfileListener(Consumer listener) { + mainCtx.getTenantProfileCache().addListener(getTenantId(), getSelfId(), listener); + } + @Override public void addDeviceProfileListeners(Consumer profileListener, BiConsumer deviceListener) { mainCtx.getDeviceProfileCache().addListener(getTenantId(), getSelfId(), profileListener, deviceListener); } @Override - public void removeProfileListener() { + public void removeListeners() { mainCtx.getDeviceProfileCache().removeListener(getTenantId(), getSelfId()); + mainCtx.getTenantProfileCache().removeListener(getTenantId(), getSelfId()); + } + + @Override + public TenantProfile getTenantProfile() { + return mainCtx.getTenantProfileCache().get(getTenantId()); } private TbMsgMetaData getActionMetaData(RuleNodeId ruleNodeId) { diff --git a/application/src/main/java/org/thingsboard/server/controller/AdminController.java b/application/src/main/java/org/thingsboard/server/controller/AdminController.java index c980bff796..52283029fe 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AdminController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AdminController.java @@ -26,7 +26,7 @@ import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.rule.engine.api.SmsService; -import org.thingsboard.rule.engine.api.sms.config.TestSmsRequest; +import org.thingsboard.server.common.data.sms.config.TestSmsRequest; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.UpdateMessage; import org.thingsboard.server.common.data.exception.ThingsboardException; diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index 2c28feebf2..dd0314e00e 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.asset.AssetInfo; import org.thingsboard.server.common.data.asset.AssetSearchQuery; import org.thingsboard.server.common.data.audit.ActionType; +import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.CustomerId; @@ -51,6 +52,8 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE; + @RestController @TbCoreComponent @RequestMapping("/api") @@ -89,6 +92,10 @@ public class AssetController extends BaseController { @ResponseBody public Asset saveAsset(@RequestBody Asset asset) throws ThingsboardException { try { + if (TB_SERVICE_QUEUE.equals(asset.getType())) { + throw new ThingsboardException("Unable to save asset with type " + TB_SERVICE_QUEUE, ThingsboardErrorCode.BAD_REQUEST_PARAMS); + } + asset.setTenantId(getCurrentUser().getTenantId()); checkEntity(asset.getId(), asset, Resource.ASSET); diff --git a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java index fb5fade521..2141027fa7 100644 --- a/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java +++ b/application/src/main/java/org/thingsboard/server/controller/TelemetryController.java @@ -45,6 +45,7 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.rule.engine.api.msg.DeviceAttributesEventNotificationMsg; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.DeviceId; @@ -69,6 +70,7 @@ import org.thingsboard.server.common.data.kv.LongDataEntry; import org.thingsboard.server.common.data.kv.ReadTsKvQuery; import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.transport.adaptor.JsonConverter; import org.thingsboard.server.dao.timeseries.TimeseriesService; import org.thingsboard.server.queue.util.TbCoreComponent; @@ -93,6 +95,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -205,7 +208,7 @@ public class TelemetryController extends BaseController { @RequestParam(name = "interval", defaultValue = "0") Long interval, @RequestParam(name = "limit", defaultValue = "100") Integer limit, @RequestParam(name = "agg", defaultValue = "NONE") String aggStr, - @RequestParam(name= "orderBy", defaultValue = "DESC") String orderBy, + @RequestParam(name = "orderBy", defaultValue = "DESC") String orderBy, @RequestParam(name = "useStrictDataTypes", required = false, defaultValue = "false") Boolean useStrictDataTypes) throws ThingsboardException { return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.READ_TELEMETRY, entityType, entityIdStr, (result, tenantId, entityId) -> { @@ -392,7 +395,7 @@ public class TelemetryController extends BaseController { if (attributes.isEmpty()) { return getImmediateDeferredResult("No attributes data found in request body!", HttpStatus.BAD_REQUEST); } - for (AttributeKvEntry attributeKvEntry: attributes) { + for (AttributeKvEntry attributeKvEntry : attributes) { if (attributeKvEntry.getKey().isEmpty() || attributeKvEntry.getKey().trim().length() == 0) { return getImmediateDeferredResult("Key cannot be empty or contains only spaces", HttpStatus.BAD_REQUEST); } @@ -440,9 +443,13 @@ public class TelemetryController extends BaseController { if (entries.isEmpty()) { return getImmediateDeferredResult("No timeseries data found in request body!", HttpStatus.BAD_REQUEST); } - SecurityUser user = getCurrentUser(); return accessValidator.validateEntityAndCallback(getCurrentUser(), Operation.WRITE_TELEMETRY, entityIdSrc, (result, tenantId, entityId) -> { - tsSubService.saveAndNotify(tenantId, entityId, entries, ttl, new FutureCallback() { + long tenantTtl = ttl; + if (!TenantId.SYS_TENANT_ID.equals(tenantId) && tenantTtl == 0) { + TenantProfile tenantProfile = tenantProfileCache.get(tenantId); + tenantTtl = TimeUnit.DAYS.toSeconds(((DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration()).getDefaultStorageTtlDays()); + } + tsSubService.saveAndNotify(tenantId, entityId, entries, tenantTtl, new FutureCallback() { @Override public void onSuccess(@Nullable Void tmp) { result.setResult(new ResponseEntity(HttpStatus.OK)); diff --git a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java index 330ecc23f5..50a273223d 100644 --- a/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/apiusage/DefaultTbApiUsageStateService.java @@ -147,6 +147,11 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { public void process(TbProtoQueueMsg msg, TbCallback callback) { ToUsageStatsServiceMsg statsMsg = msg.getValue(); TenantId tenantId = new TenantId(new UUID(statsMsg.getTenantIdMSB(), statsMsg.getTenantIdLSB())); + + if (tenantProfileCache.get(tenantId) == null) { + return; + } + TenantApiUsageState tenantState; List updatedEntries; Map result; @@ -166,7 +171,7 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { long newValue = tenantState.add(recordKey, kvProto.getValue()); updatedEntries.add(new BasicTsKvEntry(ts, new LongDataEntry(recordKey.getApiCountKey(), newValue))); long newHourlyValue = tenantState.addToHourly(recordKey, kvProto.getValue()); - updatedEntries.add(new BasicTsKvEntry(hourTs, new LongDataEntry(recordKey.getApiCountKey() + HOURLY, newHourlyValue))); + updatedEntries.add(new BasicTsKvEntry(newHourTs, new LongDataEntry(recordKey.getApiCountKey() + HOURLY, newHourlyValue))); apiFeatures.add(recordKey.getApiFeature()); } result = tenantState.checkStateUpdatedDueToThreshold(apiFeatures); @@ -343,7 +348,15 @@ public class DefaultTbApiUsageStateService implements TbApiUsageStateService { long now = System.currentTimeMillis(); myTenantStates.values().forEach(state -> { if ((state.getNextCycleTs() > now) && (state.getNextCycleTs() - now < TimeUnit.HOURS.toMillis(1))) { + TenantId tenantId = state.getTenantId(); state.setCycles(state.getNextCycleTs(), SchedulerUtils.getStartOfNextNextMonth()); + ToUsageStatsServiceMsg.Builder msg = ToUsageStatsServiceMsg.newBuilder(); + msg.setTenantIdMSB(tenantId.getId().getMostSignificantBits()); + msg.setTenantIdLSB(tenantId.getId().getLeastSignificantBits()); + for (ApiUsageRecordKey key : ApiUsageRecordKey.values()) { + msg.addValues(UsageStatsKVProto.newBuilder().setKey(key.name()).setValue(0).build()); + } + process(new TbProtoQueueMsg<>(UUID.randomUUID(), msg.build()), TbCallback.EMPTY); } }); } finally { diff --git a/application/src/main/java/org/thingsboard/server/service/device/DeviceProvisionServiceImpl.java b/application/src/main/java/org/thingsboard/server/service/device/DeviceProvisionServiceImpl.java index 583139f05c..2a2f1bd03a 100644 --- a/application/src/main/java/org/thingsboard/server/service/device/DeviceProvisionServiceImpl.java +++ b/application/src/main/java/org/thingsboard/server/service/device/DeviceProvisionServiceImpl.java @@ -18,9 +18,7 @@ package org.thingsboard.server.service.device; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.MoreExecutors; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.RandomStringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -114,6 +112,13 @@ public class DeviceProvisionServiceImpl implements DeviceProvisionService { public ProvisionResponse provisionDevice(ProvisionRequest provisionRequest) { String provisionRequestKey = provisionRequest.getCredentials().getProvisionDeviceKey(); String provisionRequestSecret = provisionRequest.getCredentials().getProvisionDeviceSecret(); + if (!StringUtils.isEmpty(provisionRequest.getDeviceName())) { + provisionRequest.setDeviceName(provisionRequest.getDeviceName().trim()); + if (StringUtils.isEmpty(provisionRequest.getDeviceName())) { + log.warn("Provision request contains empty device name!"); + throw new ProvisionFailedException(ProvisionResponseStatus.FAILURE.name()); + } + } if (StringUtils.isEmpty(provisionRequestKey) || StringUtils.isEmpty(provisionRequestSecret)) { throw new ProvisionFailedException(ProvisionResponseStatus.NOT_FOUND.name()); diff --git a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java index ef25eeefdb..c51420c8e0 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java @@ -82,7 +82,7 @@ import org.thingsboard.server.dao.widget.WidgetsBundleService; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedHashMap; +import java.util.TreeMap; @Service @Profile("install") @@ -272,7 +272,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { thermostatDeviceProfile.setProvisionType(DeviceProfileProvisionType.DISABLED); thermostatDeviceProfile.setDescription("Thermostat device profile"); thermostatDeviceProfile.setDefaultRuleChainId(ruleChainService.findTenantRuleChains( - demoTenant.getId(), new PageLink(1, 0, "Thermostat Alarms")).getData().get(0).getId()); + demoTenant.getId(), new PageLink(1, 0, "Thermostat")).getData().get(0).getId()); DeviceProfileData deviceProfileData = new DeviceProfileData(); DefaultDeviceProfileConfiguration configuration = new DefaultDeviceProfileConfiguration(); @@ -290,13 +290,13 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { AlarmCondition temperatureCondition = new AlarmCondition(); temperatureCondition.setSpec(new SimpleAlarmConditionSpec()); - KeyFilter alarmTemperatureAttributeFilter = new KeyFilter(); - alarmTemperatureAttributeFilter.setKey(new EntityKey(EntityKeyType.ATTRIBUTE, "alarmTemperature")); - alarmTemperatureAttributeFilter.setValueType(EntityKeyValueType.BOOLEAN); - BooleanFilterPredicate alarmTemperatureAttributePredicate = new BooleanFilterPredicate(); - alarmTemperatureAttributePredicate.setOperation(BooleanFilterPredicate.BooleanOperation.EQUAL); - alarmTemperatureAttributePredicate.setValue(new FilterPredicateValue<>(Boolean.TRUE)); - alarmTemperatureAttributeFilter.setPredicate(alarmTemperatureAttributePredicate); + KeyFilter temperatureAlarmFlagAttributeFilter = new KeyFilter(); + temperatureAlarmFlagAttributeFilter.setKey(new EntityKey(EntityKeyType.ATTRIBUTE, "temperatureAlarmFlag")); + temperatureAlarmFlagAttributeFilter.setValueType(EntityKeyValueType.BOOLEAN); + BooleanFilterPredicate temperatureAlarmFlagAttributePredicate = new BooleanFilterPredicate(); + temperatureAlarmFlagAttributePredicate.setOperation(BooleanFilterPredicate.BooleanOperation.EQUAL); + temperatureAlarmFlagAttributePredicate.setValue(new FilterPredicateValue<>(Boolean.TRUE)); + temperatureAlarmFlagAttributeFilter.setPredicate(temperatureAlarmFlagAttributePredicate); KeyFilter temperatureTimeseriesFilter = new KeyFilter(); temperatureTimeseriesFilter.setKey(new EntityKey(EntityKeyType.TIME_SERIES, "temperature")); @@ -305,13 +305,13 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { temperatureTimeseriesFilterPredicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER); FilterPredicateValue temperatureTimeseriesPredicateValue = new FilterPredicateValue<>(25.0, null, - new DynamicValue<>(DynamicValueSourceType.CURRENT_DEVICE, "thresholdTemperature")); + new DynamicValue<>(DynamicValueSourceType.CURRENT_DEVICE, "temperatureAlarmThreshold")); temperatureTimeseriesFilterPredicate.setValue(temperatureTimeseriesPredicateValue); temperatureTimeseriesFilter.setPredicate(temperatureTimeseriesFilterPredicate); - temperatureCondition.setCondition(Arrays.asList(alarmTemperatureAttributeFilter, temperatureTimeseriesFilter)); + temperatureCondition.setCondition(Arrays.asList(temperatureAlarmFlagAttributeFilter, temperatureTimeseriesFilter)); temperatureRule.setAlarmDetails("Current temperature = ${temperature}"); temperatureRule.setCondition(temperatureCondition); - highTemperature.setCreateRules(new LinkedHashMap<>(Collections.singletonMap(AlarmSeverity.MAJOR, temperatureRule))); + highTemperature.setCreateRules(new TreeMap<>(Collections.singletonMap(AlarmSeverity.MAJOR, temperatureRule))); AlarmRule clearTemperatureRule = new AlarmRule(); AlarmCondition clearTemperatureCondition = new AlarmCondition(); @@ -324,7 +324,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { clearTemperatureTimeseriesFilterPredicate.setOperation(NumericFilterPredicate.NumericOperation.LESS_OR_EQUAL); FilterPredicateValue clearTemperatureTimeseriesPredicateValue = new FilterPredicateValue<>(25.0, null, - new DynamicValue<>(DynamicValueSourceType.CURRENT_DEVICE, "thresholdTemperature")); + new DynamicValue<>(DynamicValueSourceType.CURRENT_DEVICE, "temperatureAlarmThreshold")); clearTemperatureTimeseriesFilterPredicate.setValue(clearTemperatureTimeseriesPredicateValue); clearTemperatureTimeseriesFilter.setPredicate(clearTemperatureTimeseriesFilterPredicate); @@ -340,13 +340,13 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { AlarmCondition humidityCondition = new AlarmCondition(); humidityCondition.setSpec(new SimpleAlarmConditionSpec()); - KeyFilter alarmHumidityAttributeFilter = new KeyFilter(); - alarmHumidityAttributeFilter.setKey(new EntityKey(EntityKeyType.ATTRIBUTE, "alarmHumidity")); - alarmHumidityAttributeFilter.setValueType(EntityKeyValueType.BOOLEAN); - BooleanFilterPredicate alarmHumidityAttributePredicate = new BooleanFilterPredicate(); - alarmHumidityAttributePredicate.setOperation(BooleanFilterPredicate.BooleanOperation.EQUAL); - alarmHumidityAttributePredicate.setValue(new FilterPredicateValue<>(Boolean.TRUE)); - alarmHumidityAttributeFilter.setPredicate(alarmHumidityAttributePredicate); + KeyFilter humidityAlarmFlagAttributeFilter = new KeyFilter(); + humidityAlarmFlagAttributeFilter.setKey(new EntityKey(EntityKeyType.ATTRIBUTE, "humidityAlarmFlag")); + humidityAlarmFlagAttributeFilter.setValueType(EntityKeyValueType.BOOLEAN); + BooleanFilterPredicate humidityAlarmFlagAttributePredicate = new BooleanFilterPredicate(); + humidityAlarmFlagAttributePredicate.setOperation(BooleanFilterPredicate.BooleanOperation.EQUAL); + humidityAlarmFlagAttributePredicate.setValue(new FilterPredicateValue<>(Boolean.TRUE)); + humidityAlarmFlagAttributeFilter.setPredicate(humidityAlarmFlagAttributePredicate); KeyFilter humidityTimeseriesFilter = new KeyFilter(); humidityTimeseriesFilter.setKey(new EntityKey(EntityKeyType.TIME_SERIES, "humidity")); @@ -355,14 +355,14 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { humidityTimeseriesFilterPredicate.setOperation(NumericFilterPredicate.NumericOperation.LESS); FilterPredicateValue humidityTimeseriesPredicateValue = new FilterPredicateValue<>(60.0, null, - new DynamicValue<>(DynamicValueSourceType.CURRENT_DEVICE, "thresholdHumidity")); + new DynamicValue<>(DynamicValueSourceType.CURRENT_DEVICE, "humidityAlarmThreshold")); humidityTimeseriesFilterPredicate.setValue(humidityTimeseriesPredicateValue); humidityTimeseriesFilter.setPredicate(humidityTimeseriesFilterPredicate); - humidityCondition.setCondition(Arrays.asList(alarmHumidityAttributeFilter, humidityTimeseriesFilter)); + humidityCondition.setCondition(Arrays.asList(humidityAlarmFlagAttributeFilter, humidityTimeseriesFilter)); humidityRule.setCondition(humidityCondition); humidityRule.setAlarmDetails("Current humidity = ${humidity}"); - lowHumidity.setCreateRules(new LinkedHashMap<>(Collections.singletonMap(AlarmSeverity.MINOR, humidityRule))); + lowHumidity.setCreateRules(new TreeMap<>(Collections.singletonMap(AlarmSeverity.MINOR, humidityRule))); AlarmRule clearHumidityRule = new AlarmRule(); AlarmCondition clearHumidityCondition = new AlarmCondition(); @@ -375,7 +375,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { clearHumidityTimeseriesFilterPredicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER_OR_EQUAL); FilterPredicateValue clearHumidityTimeseriesPredicateValue = new FilterPredicateValue<>(60.0, null, - new DynamicValue<>(DynamicValueSourceType.CURRENT_DEVICE, "thresholdHumidity")); + new DynamicValue<>(DynamicValueSourceType.CURRENT_DEVICE, "humidityAlarmThreshold")); clearHumidityTimeseriesFilterPredicate.setValue(clearHumidityTimeseriesPredicateValue); clearHumidityTimeseriesFilter.setPredicate(clearHumidityTimeseriesFilterPredicate); @@ -394,18 +394,18 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { attributesService.save(demoTenant.getId(), t1Id, DataConstants.SERVER_SCOPE, Arrays.asList(new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("latitude", 37.3948)), new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("longitude", -122.1503)), - new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmTemperature", true)), - new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmHumidity", true)), - new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdTemperature", (long) 20)), - new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdHumidity", (long) 50)))); + new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("temperatureAlarmFlag", true)), + new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("humidityAlarmFlag", true)), + new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("temperatureAlarmThreshold", (long) 20)), + new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("humidityAlarmThreshold", (long) 50)))); attributesService.save(demoTenant.getId(), t2Id, DataConstants.SERVER_SCOPE, Arrays.asList(new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("latitude", 37.493801)), new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("longitude", -121.948769)), - new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmTemperature", true)), - new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmHumidity", true)), - new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdTemperature", (long) 25)), - new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdHumidity", (long) 30)))); + new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("temperatureAlarmFlag", true)), + new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("humidityAlarmFlag", true)), + new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("temperatureAlarmThreshold", (long) 25)), + new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("humidityAlarmThreshold", (long) 30)))); installScripts.loadDashboards(demoTenant.getId(), null); } diff --git a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java index ac047060ae..5e6797eeb7 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java +++ b/application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java @@ -210,26 +210,9 @@ public class InstallScripts { public void loadDemoRuleChains(TenantId tenantId) throws Exception { - Path ruleChainsDir = Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, RULE_CHAINS_DIR); try { - JsonNode ruleChainJson = objectMapper.readTree(ruleChainsDir.resolve("thermostat_alarms.json").toFile()); - RuleChain ruleChain = objectMapper.treeToValue(ruleChainJson.get("ruleChain"), RuleChain.class); - RuleChainMetaData ruleChainMetaData = objectMapper.treeToValue(ruleChainJson.get("metadata"), RuleChainMetaData.class); - ruleChain.setTenantId(tenantId); - ruleChain = ruleChainService.saveRuleChain(ruleChain); - ruleChainMetaData.setRuleChainId(ruleChain.getId()); - ruleChainService.saveRuleChainMetaData(new TenantId(EntityId.NULL_UUID), ruleChainMetaData); - - JsonNode rootChainJson = objectMapper.readTree(ruleChainsDir.resolve("root_rule_chain.json").toFile()); - RuleChain rootChain = objectMapper.treeToValue(rootChainJson.get("ruleChain"), RuleChain.class); - RuleChainMetaData rootChainMetaData = objectMapper.treeToValue(rootChainJson.get("metadata"), RuleChainMetaData.class); - - RuleChainId thermostatsRuleChainId = ruleChain.getId(); - rootChainMetaData.getRuleChainConnections().forEach(connection -> connection.setTargetRuleChainId(thermostatsRuleChainId)); - rootChain.setTenantId(tenantId); - rootChain = ruleChainService.saveRuleChain(rootChain); - rootChainMetaData.setRuleChainId(rootChain.getId()); - ruleChainService.saveRuleChainMetaData(new TenantId(EntityId.NULL_UUID), rootChainMetaData); + createDefaultRuleChains(tenantId); + createDefaultRuleChain(tenantId, "Thermostat"); } catch (Exception e) { log.error("Unable to load dashboard from json", e); throw new RuntimeException("Unable to load dashboard from json", e); diff --git a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java index 7865321e67..e9cef05dd5 100644 --- a/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java +++ b/application/src/main/java/org/thingsboard/server/service/mail/DefaultMailService.java @@ -250,6 +250,8 @@ public class DefaultMailService implements MailService { helper.setText(body); mailSender.send(helper.getMimeMessage()); apiUsageClient.report(tenantId, ApiUsageRecordKey.EMAIL_EXEC_COUNT, 1); + } else { + throw new RuntimeException("Email sending is disabled due to API limits!"); } } diff --git a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java index 4406ff9ade..b9d9f57b92 100644 --- a/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java +++ b/application/src/main/java/org/thingsboard/server/service/queue/DefaultTbCoreConsumerService.java @@ -297,7 +297,7 @@ public class DefaultTbCoreConsumerService extends AbstractConsumerService(deviceId, key, value)); } else { - tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback(deviceId, key, value)); + tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback<>(deviceId, key, value)); } } private void save(DeviceId deviceId, String key, boolean value) { if (persistToTelemetry) { - tsSubService.saveAndNotify( + tsSubService.saveAndNotifyInternal( TenantId.SYS_TENANT_ID, deviceId, Collections.singletonList(new BasicTsKvEntry(System.currentTimeMillis(), new BooleanDataEntry(key, value))), - new AttributeSaveCallback(deviceId, key, value)); + new AttributeSaveCallback<>(deviceId, key, value)); } else { - tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback(deviceId, key, value)); + tsSubService.saveAttrAndNotify(TenantId.SYS_TENANT_ID, deviceId, DataConstants.SERVER_SCOPE, key, value, new AttributeSaveCallback<>(deviceId, key, value)); } } - private static class AttributeSaveCallback implements FutureCallback { + private static class AttributeSaveCallback implements FutureCallback { private final DeviceId deviceId; private final String key; private final Object value; @@ -553,7 +553,7 @@ public class DefaultDeviceStateService implements DeviceStateService { } @Override - public void onSuccess(@Nullable Void result) { + public void onSuccess(@Nullable T result) { log.trace("[{}] Successfully updated attribute [{}] with value [{}]", deviceId, key, value); } diff --git a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java index 7a35e6b317..5b3ad05ee9 100644 --- a/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java +++ b/application/src/main/java/org/thingsboard/server/service/telemetry/DefaultTelemetrySubscriptionService.java @@ -25,6 +25,7 @@ import org.thingsboard.common.util.ThingsBoardThreadFactory; import org.thingsboard.server.common.data.ApiUsageRecordKey; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; +import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.kv.AttributeKvEntry; @@ -34,13 +35,14 @@ import org.thingsboard.server.common.data.kv.DoubleDataEntry; import org.thingsboard.server.common.data.kv.LongDataEntry; import org.thingsboard.server.common.data.kv.StringDataEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import org.thingsboard.server.common.msg.queue.ServiceType; import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.entityview.EntityViewService; +import org.thingsboard.server.dao.tenant.TbTenantProfileCache; import org.thingsboard.server.dao.timeseries.TimeseriesService; -import org.thingsboard.server.dao.usagerecord.ApiUsageStateService; import org.thingsboard.server.gen.transport.TransportProtos; import org.thingsboard.server.queue.discovery.PartitionService; import org.thingsboard.server.queue.usagestats.TbApiUsageClient; @@ -119,11 +121,12 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer @Override public void saveAndNotify(TenantId tenantId, EntityId entityId, List ts, long ttl, FutureCallback callback) { checkInternalEntity(entityId); - if (apiUsageStateService.getApiUsageState(tenantId).isDbStorageEnabled()) { + boolean sysTenant = TenantId.SYS_TENANT_ID.equals(tenantId) || tenantId == null; + if (sysTenant || apiUsageStateService.getApiUsageState(tenantId).isDbStorageEnabled()) { saveAndNotifyInternal(tenantId, entityId, ts, ttl, new FutureCallback() { @Override public void onSuccess(Integer result) { - if (result != null && result > 0) { + if (!sysTenant && result != null && result > 0) { apiUsageClient.report(tenantId, ApiUsageRecordKey.STORAGE_DP_COUNT, result); } callback.onSuccess(null); @@ -134,7 +137,7 @@ public class DefaultTelemetrySubscriptionService extends AbstractSubscriptionSer callback.onFailure(t); } }); - } else{ + } else { callback.onFailure(new RuntimeException("DB storage writes are disabled due to API limits!")); } } diff --git a/application/src/main/resources/i18n/messages.properties b/application/src/main/resources/i18n/messages.properties index 9de9c4b789..bdbd64384b 100644 --- a/application/src/main/resources/i18n/messages.properties +++ b/application/src/main/resources/i18n/messages.properties @@ -4,4 +4,4 @@ account.activated.subject=Thingsboard - your account has been activated reset.password.subject=Thingsboard - Password reset has been requested password.was.reset.subject=Thingsboard - your account password has been reset account.lockout.subject=Thingsboard - User account has been lockout -api.usage.state=Thingsboard - Api Usage State for tenant has been updated \ No newline at end of file +api.usage.state=Thingsboard - Account limits \ No newline at end of file diff --git a/application/src/main/resources/templates/state.disabled.ftl b/application/src/main/resources/templates/state.disabled.ftl index f14bdd2235..2e341dbe20 100644 --- a/application/src/main/resources/templates/state.disabled.ftl +++ b/application/src/main/resources/templates/state.disabled.ftl @@ -103,40 +103,30 @@ style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em; background-color: #f6f6f6; margin: 0;" bgcolor="#f6f6f6"> - +
-
- +
+ - + - - + + + + - + - +
-

Your ThingsBoard account feature was disabled

-
We have disabled the ${apiFeature} for your account because ThingsBoard has already ${apiLimitValueLabel}. +
Your ThingsBoard account feature was disabled
+
+
We have disabled the ${apiFeature} for your account because ThingsBoard has already ${apiLimitValueLabel}.
+
Please contact your system administrator to resolve the issue. - Please contact your system administrator to resolve the issue.
— The ThingsBoard - — The ThingsBoard
@@ -144,16 +134,10 @@
- +
- +
This email was sent to ${targetEmail} by ThingsBoard. - This email was sent to ${targetEmail} by ThingsBoard.
diff --git a/application/src/main/resources/templates/state.enabled.ftl b/application/src/main/resources/templates/state.enabled.ftl index 0a7841f871..e03f38bba3 100644 --- a/application/src/main/resources/templates/state.enabled.ftl +++ b/application/src/main/resources/templates/state.enabled.ftl @@ -103,34 +103,27 @@ style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em; background-color: #f6f6f6; margin: 0;" bgcolor="#f6f6f6"> - +
-
- +
+ - + - - + + + + - +
-

Your ThingsBoard account feature was enabled

-
We have enabled the ${apiFeature} for your account and ThingsBoard is already able to ${apiLabel} messages. +
Your ThingsBoard account feature was enabled
+
+
We have enabled the ${apiFeature} for your account and ThingsBoard is already able to ${apiLabel} messages.
+
— The ThingsBoard - — The ThingsBoard
@@ -138,16 +131,10 @@
- +
- +
This email was sent to ${targetEmail} by ThingsBoard. - This email was sent to ${targetEmail} by ThingsBoard.
diff --git a/application/src/main/resources/templates/state.warning.ftl b/application/src/main/resources/templates/state.warning.ftl index 1ce29100a7..67fc557e87 100644 --- a/application/src/main/resources/templates/state.warning.ftl +++ b/application/src/main/resources/templates/state.warning.ftl @@ -103,41 +103,30 @@ style="font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif; box-sizing: border-box; font-size: 14px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; line-height: 1.6em; background-color: #f6f6f6; margin: 0;" bgcolor="#f6f6f6"> - +
-
- +
+ - + - - + + + + - + - +
-

Your ThingsBoard account feature may be disabled soon

-
- ThingsBoard has already ${apiValueLabel}.
${apiFeature} will be disabled for your account once the limit will be reached. +
Warning: your ThingsBoard account feature may be disabled soon
+
+
ThingsBoard has already ${apiValueLabel}.
${apiFeature} will be disabled for your account once the limit will be reached.
+
Please contact your system administrator to resolve the issue. - Please contact your system administrator to resolve the issue.
— The ThingsBoard - — The ThingsBoard
@@ -145,16 +134,10 @@
- +
- +
This email was sent to ${targetEmail} by ThingsBoard. - This email was sent to ${targetEmail} by ThingsBoard.
diff --git a/common/actor/pom.xml b/common/actor/pom.xml index 9258ee75a4..9dea3c57a3 100644 --- a/common/actor/pom.xml +++ b/common/actor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT common org.thingsboard.common diff --git a/common/dao-api/pom.xml b/common/dao-api/pom.xml index 650b05c04e..d50399525e 100644 --- a/common/dao-api/pom.xml +++ b/common/dao-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT common org.thingsboard.common diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProvisionService.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProvisionService.java index 5d038b2d31..660f1a5f35 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProvisionService.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProvisionService.java @@ -15,9 +15,6 @@ */ package org.thingsboard.server.dao.device; -import com.google.common.util.concurrent.ListenableFuture; -import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.dao.device.provision.ProvisionFailedException; import org.thingsboard.server.dao.device.provision.ProvisionRequest; import org.thingsboard.server.dao.device.provision.ProvisionResponse; diff --git a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TbTenantProfileCache.java b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TbTenantProfileCache.java index 735e23e73a..ea3d65eb49 100644 --- a/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TbTenantProfileCache.java +++ b/common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TbTenantProfileCache.java @@ -16,9 +16,12 @@ package org.thingsboard.server.dao.tenant; import org.thingsboard.server.common.data.TenantProfile; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; +import java.util.function.Consumer; + public interface TbTenantProfileCache { TenantProfile get(TenantId tenantId); @@ -31,4 +34,8 @@ public interface TbTenantProfileCache { void evict(TenantId id); + void addListener(TenantId tenantId, EntityId listenerId, Consumer profileListener); + + void removeListener(TenantId tenantId, EntityId listenerId); + } diff --git a/common/data/pom.xml b/common/data/pom.xml index fc1311ab02..b2dd156acb 100644 --- a/common/data/pom.xml +++ b/common/data/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT common org.thingsboard.common diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java index 17035f337b..3b6acce6f3 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/device/profile/DeviceProfileAlarm.java @@ -18,9 +18,8 @@ package org.thingsboard.server.common.data.device.profile; import lombok.Data; import org.thingsboard.server.common.data.alarm.AlarmSeverity; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; +import java.util.TreeMap; @Data public class DeviceProfileAlarm { @@ -28,7 +27,7 @@ public class DeviceProfileAlarm { private String id; private String alarmType; - private LinkedHashMap createRules; + private TreeMap createRules; private AlarmRule clearRule; // Hidden in advanced settings diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/AwsSnsSmsProviderConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java similarity index 94% rename from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/AwsSnsSmsProviderConfiguration.java rename to common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java index 74cd5486a1..2acad17a0f 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/AwsSnsSmsProviderConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/AwsSnsSmsProviderConfiguration.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.rule.engine.api.sms.config; +package org.thingsboard.server.common.data.sms.config; import lombok.Data; diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderConfiguration.java similarity index 95% rename from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderConfiguration.java rename to common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderConfiguration.java index 8feec6ff40..8b1984e9b4 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderConfiguration.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.rule.engine.api.sms.config; +package org.thingsboard.server.common.data.sms.config; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderType.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderType.java similarity index 92% rename from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderType.java rename to common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderType.java index e698dd4783..f60d917cf1 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/SmsProviderType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/SmsProviderType.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.rule.engine.api.sms.config; +package org.thingsboard.server.common.data.sms.config; public enum SmsProviderType { AWS_SNS, diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TestSmsRequest.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java similarity index 93% rename from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TestSmsRequest.java rename to common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java index 3d00f9e580..23c44be48c 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TestSmsRequest.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TestSmsRequest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.rule.engine.api.sms.config; +package org.thingsboard.server.common.data.sms.config; import lombok.Data; diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TwilioSmsProviderConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java similarity index 94% rename from rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TwilioSmsProviderConfiguration.java rename to common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java index 2e0585e466..6f9b226711 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/config/TwilioSmsProviderConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/sms/config/TwilioSmsProviderConfiguration.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.rule.engine.api.sms.config; +package org.thingsboard.server.common.data.sms.config; import lombok.Data; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java index 28ef5cae13..054f78766b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/tenant/profile/DefaultTenantProfileConfiguration.java @@ -45,6 +45,8 @@ public class DefaultTenantProfileConfiguration implements TenantProfileConfigura private long maxEmails; private long maxSms; + private int defaultStorageTtlDays; + private double warnThreshold; @Override diff --git a/common/message/pom.xml b/common/message/pom.xml index 17a0679630..bcff40ce4d 100644 --- a/common/message/pom.xml +++ b/common/message/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT common org.thingsboard.common diff --git a/common/pom.xml b/common/pom.xml index 52685d3891..5ceae3ea57 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT thingsboard common diff --git a/common/queue/pom.xml b/common/queue/pom.xml index aaf46710f7..54cd24f66d 100644 --- a/common/queue/pom.xml +++ b/common/queue/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT common org.thingsboard.common diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java index c683ed846d..5cceb43324 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/discovery/HashPartitionService.java @@ -195,9 +195,11 @@ public class HashPartitionService implements PartitionService { if (current.getServiceTypesList().contains(serviceType.name())) { result.add(current.getServiceId()); } - for (ServiceInfo serviceInfo : currentOtherServices) { - if (serviceInfo.getServiceTypesList().contains(serviceType.name())) { - result.add(serviceInfo.getServiceId()); + if (currentOtherServices != null) { + for (ServiceInfo serviceInfo : currentOtherServices) { + if (serviceInfo.getServiceTypesList().contains(serviceType.name())) { + result.add(serviceInfo.getServiceId()); + } } } return result; diff --git a/common/stats/pom.xml b/common/stats/pom.xml index 10c3ccb040..8cf70c7498 100644 --- a/common/stats/pom.xml +++ b/common/stats/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/coap/pom.xml b/common/transport/coap/pom.xml index 3b04a20abe..e775286bdd 100644 --- a/common/transport/coap/pom.xml +++ b/common/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java index afb83f513f..a6813e488d 100644 --- a/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java +++ b/common/transport/coap/src/main/java/org/thingsboard/server/transport/coap/CoapTransportService.java @@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.californium.core.CoapResource; import org.eclipse.californium.core.CoapServer; import org.eclipse.californium.core.network.CoapEndpoint; +import org.eclipse.californium.core.network.config.NetworkConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Service; @@ -46,7 +47,7 @@ public class CoapTransportService { public void init() throws UnknownHostException { log.info("Starting CoAP transport..."); log.info("Starting CoAP transport server"); - this.server = new CoapServer(); + this.server = new CoapServer(NetworkConfig.createStandardWithoutFile()); createResources(); InetAddress addr = InetAddress.getByName(coapTransportContext.getHost()); InetSocketAddress sockAddr = new InetSocketAddress(addr, coapTransportContext.getPort()); diff --git a/common/transport/http/pom.xml b/common/transport/http/pom.xml index 040f7c372e..ab60e6d4eb 100644 --- a/common/transport/http/pom.xml +++ b/common/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/pom.xml b/common/transport/mqtt/pom.xml index 8a02c940a7..8b043b8c2e 100644 --- a/common/transport/mqtt/pom.xml +++ b/common/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java index cabc61cab6..0df14d4655 100644 --- a/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java +++ b/common/transport/mqtt/src/main/java/org/thingsboard/server/transport/mqtt/MqttTransportHandler.java @@ -179,6 +179,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement } } } else { + ctx.close(); throw new RuntimeException("Unsupported topic for provisioning requests!"); } } catch (RuntimeException | AdaptorException e) { diff --git a/common/transport/pom.xml b/common/transport/pom.xml index fbdb10d081..22b17989c9 100644 --- a/common/transport/pom.xml +++ b/common/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT common org.thingsboard.common diff --git a/common/transport/transport-api/pom.xml b/common/transport/transport-api/pom.xml index 168c991eb6..d61963053e 100644 --- a/common/transport/transport-api/pom.xml +++ b/common/transport/transport-api/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.common - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT transport org.thingsboard.common.transport diff --git a/common/util/pom.xml b/common/util/pom.xml index 076eff152a..474db1270e 100644 --- a/common/util/pom.xml +++ b/common/util/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT common org.thingsboard.common diff --git a/dao/pom.xml b/dao/pom.xml index ec4960eb5f..907ddb7150 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT thingsboard dao diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java index 29eaad31fb..e8375d8065 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java @@ -78,6 +78,8 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ public static final String INCORRECT_PAGE_LINK = "Incorrect page link "; public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; public static final String INCORRECT_ASSET_ID = "Incorrect assetId "; + public static final String TB_SERVICE_QUEUE = "TbServiceQueue"; + @Autowired private AssetDao assetDao; @@ -329,8 +331,10 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ protected void validateCreate(TenantId tenantId, Asset asset) { DefaultTenantProfileConfiguration profileConfiguration = (DefaultTenantProfileConfiguration)tenantProfileCache.get(tenantId).getProfileData().getConfiguration(); - long maxAssets = profileConfiguration.getMaxAssets(); - validateNumberOfEntitiesPerTenant(tenantId, assetDao, maxAssets, EntityType.ASSET); + if (!TB_SERVICE_QUEUE.equals(asset.getType())) { + long maxAssets = profileConfiguration.getMaxAssets(); + validateNumberOfEntitiesPerTenant(tenantId, assetDao, maxAssets, EntityType.ASSET); + } } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java index a6e016c418..da2bc9e687 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java @@ -122,5 +122,5 @@ public interface AssetRepository extends PagingAndSortingRepository findTenantAssetTypes(@Param("tenantId") UUID tenantId); - Long countByTenantId(UUID tenantId); + Long countByTenantIdAndTypeIsNot(UUID tenantId, String type); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java index d2a5167b43..b56a3eb3a9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java @@ -39,6 +39,8 @@ import java.util.Objects; import java.util.Optional; import java.util.UUID; +import static org.thingsboard.server.dao.asset.BaseAssetService.TB_SERVICE_QUEUE; + /** * Created by Valerii Sosliuk on 5/19/2017. */ @@ -179,6 +181,6 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im @Override public Long countByTenantId(TenantId tenantId) { - return assetRepository.countByTenantId(tenantId.getId()); + return assetRepository.countByTenantIdAndTypeIsNot(tenantId.getId(), TB_SERVICE_QUEUE); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/tenant/DefaultTbTenantProfileCache.java b/dao/src/main/java/org/thingsboard/server/dao/tenant/DefaultTbTenantProfileCache.java index adf05e0f74..b468019872 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/tenant/DefaultTbTenantProfileCache.java +++ b/dao/src/main/java/org/thingsboard/server/dao/tenant/DefaultTbTenantProfileCache.java @@ -19,16 +19,15 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.TenantProfile; +import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantProfileId; -import org.thingsboard.server.dao.tenant.TbTenantProfileCache; -import org.thingsboard.server.dao.tenant.TenantProfileService; -import org.thingsboard.server.dao.tenant.TenantService; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; @Service @Slf4j @@ -40,6 +39,7 @@ public class DefaultTbTenantProfileCache implements TbTenantProfileCache { private final ConcurrentMap tenantProfilesMap = new ConcurrentHashMap<>(); private final ConcurrentMap tenantsMap = new ConcurrentHashMap<>(); + private final ConcurrentMap>> profileListeners = new ConcurrentHashMap<>(); public DefaultTbTenantProfileCache(TenantProfileService tenantProfileService, TenantService tenantService) { this.tenantProfileService = tenantProfileService; @@ -85,17 +85,56 @@ public class DefaultTbTenantProfileCache implements TbTenantProfileCache { public void put(TenantProfile profile) { if (profile.getId() != null) { tenantProfilesMap.put(profile.getId(), profile); + notifyTenantListeners(profile); } } @Override public void evict(TenantProfileId profileId) { tenantProfilesMap.remove(profileId); + notifyTenantListeners(get(profileId)); + } + + public void notifyTenantListeners(TenantProfile tenantProfile) { + if (tenantProfile != null) { + tenantsMap.forEach(((tenantId, tenantProfileId) -> { + if (tenantProfileId.equals(tenantProfile.getId())) { + ConcurrentMap> tenantListeners = profileListeners.get(tenantId); + if (tenantListeners != null) { + tenantListeners.forEach((id, listener) -> listener.accept(tenantProfile)); + } + } + })); + } } @Override public void evict(TenantId tenantId) { tenantsMap.remove(tenantId); + TenantProfile tenantProfile = get(tenantId); + if (tenantProfile != null) { + ConcurrentMap> tenantListeners = profileListeners.get(tenantId); + if (tenantListeners != null) { + tenantListeners.forEach((id, listener) -> listener.accept(tenantProfile)); + } + } + } + + @Override + public void addListener(TenantId tenantId, EntityId listenerId, Consumer profileListener) { + //Force cache of the tenant id. + get(tenantId); + if (profileListener != null) { + profileListeners.computeIfAbsent(tenantId, id -> new ConcurrentHashMap<>()).put(listenerId, profileListener); + } + } + + @Override + public void removeListener(TenantId tenantId, EntityId listenerId) { + ConcurrentMap> tenantListeners = profileListeners.get(tenantId); + if (tenantListeners != null) { + tenantListeners.remove(listenerId); + } } } diff --git a/msa/black-box-tests/pom.xml b/msa/black-box-tests/pom.xml index 74948b0e84..339b60741f 100644 --- a/msa/black-box-tests/pom.xml +++ b/msa/black-box-tests/pom.xml @@ -21,7 +21,7 @@ org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/js-executor/package.json b/msa/js-executor/package.json index 1f498922cd..af75855eaf 100644 --- a/msa/js-executor/package.json +++ b/msa/js-executor/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-js-executor", "private": true, - "version": "3.2.0", + "version": "3.2.1", "description": "ThingsBoard JavaScript Executor Microservice", "main": "server.js", "bin": "server.js", diff --git a/msa/js-executor/pom.xml b/msa/js-executor/pom.xml index ea286c58ba..692b371275 100644 --- a/msa/js-executor/pom.xml +++ b/msa/js-executor/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/pom.xml b/msa/pom.xml index 7419141995..cfdf6ed79f 100644 --- a/msa/pom.xml +++ b/msa/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT thingsboard msa diff --git a/msa/tb-node/pom.xml b/msa/tb-node/pom.xml index 2d42d8f6dd..ad700779a9 100644 --- a/msa/tb-node/pom.xml +++ b/msa/tb-node/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/tb/docker-cassandra/start-db.sh b/msa/tb/docker-cassandra/start-db.sh index fa80f6db57..8491a979d2 100644 --- a/msa/tb/docker-cassandra/start-db.sh +++ b/msa/tb/docker-cassandra/start-db.sh @@ -27,7 +27,11 @@ fi exec setsid nohup postgres >> ${PGLOG}/postgres.log 2>&1 & if [ ! -f ${firstlaunch} ]; then - psql -U ${pkg.user} -d postgres -c "CREATE DATABASE thingsboard" + sleep 2 + while ! psql -U ${pkg.user} -d postgres -c "CREATE DATABASE thingsboard" + do + sleep 1 + done fi cassandra_data_dir=${CASSANDRA_DATA} diff --git a/msa/tb/docker-postgres/start-db.sh b/msa/tb/docker-postgres/start-db.sh index 6119daf2f9..618dae77da 100644 --- a/msa/tb/docker-postgres/start-db.sh +++ b/msa/tb/docker-postgres/start-db.sh @@ -27,5 +27,9 @@ fi exec setsid nohup postgres >> ${PGLOG}/postgres.log 2>&1 & if [ ! -f ${firstlaunch} ]; then - psql -U ${pkg.user} -d postgres -c "CREATE DATABASE thingsboard" -fi + sleep 2 + while ! psql -U ${pkg.user} -d postgres -c "CREATE DATABASE thingsboard" + do + sleep 1 + done +fi \ No newline at end of file diff --git a/msa/tb/pom.xml b/msa/tb/pom.xml index f41a3afd1e..d1901a3e33 100644 --- a/msa/tb/pom.xml +++ b/msa/tb/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/transport/coap/pom.xml b/msa/transport/coap/pom.xml index 0b3ab420e8..ad09511f36 100644 --- a/msa/transport/coap/pom.xml +++ b/msa/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/http/pom.xml b/msa/transport/http/pom.xml index 5621fd6bdc..97196bb879 100644 --- a/msa/transport/http/pom.xml +++ b/msa/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/mqtt/pom.xml b/msa/transport/mqtt/pom.xml index 24f8350706..79a26aeef3 100644 --- a/msa/transport/mqtt/pom.xml +++ b/msa/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard.msa - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT transport org.thingsboard.msa.transport diff --git a/msa/transport/pom.xml b/msa/transport/pom.xml index e000241608..5a8b79d9d9 100644 --- a/msa/transport/pom.xml +++ b/msa/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT msa org.thingsboard.msa diff --git a/msa/web-ui/package.json b/msa/web-ui/package.json index d839f97a33..792926a86d 100644 --- a/msa/web-ui/package.json +++ b/msa/web-ui/package.json @@ -1,7 +1,7 @@ { "name": "thingsboard-web-ui", "private": true, - "version": "3.2.0", + "version": "3.2.1", "description": "ThingsBoard Web UI Microservice", "main": "server.js", "bin": "server.js", diff --git a/msa/web-ui/pom.xml b/msa/web-ui/pom.xml index f9ef249ce1..2902ea1c85 100644 --- a/msa/web-ui/pom.xml +++ b/msa/web-ui/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT msa org.thingsboard.msa diff --git a/netty-mqtt/pom.xml b/netty-mqtt/pom.xml index 58524a1a08..e917ce23f7 100644 --- a/netty-mqtt/pom.xml +++ b/netty-mqtt/pom.xml @@ -19,11 +19,11 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT thingsboard netty-mqtt - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT jar Netty MQTT Client diff --git a/pom.xml b/pom.xml index 1bfa507196..62c16da7e2 100755 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT pom Thingsboard diff --git a/rest-client/pom.xml b/rest-client/pom.xml index a7b97610d1..89f6b33a02 100644 --- a/rest-client/pom.xml +++ b/rest-client/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT thingsboard rest-client diff --git a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java index 0a92d4b1a8..e79bb2b713 100644 --- a/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java +++ b/rest-client/src/main/java/org/thingsboard/rest/client/RestClient.java @@ -109,6 +109,7 @@ import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentialsType; import org.thingsboard.server.common.data.security.model.SecuritySettings; import org.thingsboard.server.common.data.security.model.UserPasswordPolicy; +import org.thingsboard.server.common.data.sms.config.TestSmsRequest; import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.common.data.widget.WidgetsBundle; @@ -218,7 +219,11 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { } public void sendTestMail(AdminSettings adminSettings) { - restTemplate.postForEntity(baseURL + "/api/admin/settings/testMail", adminSettings, AdminSettings.class); + restTemplate.postForLocation(baseURL + "/api/admin/settings/testMail", adminSettings); + } + + public void sendTestSms(TestSmsRequest testSmsRequest) { + restTemplate.postForLocation(baseURL + "/api/admin/settings/testSms", testSmsRequest); } public Optional getSecuritySettings() { @@ -1714,6 +1719,10 @@ public class RestClient implements ClientHttpRequestInterceptor, Closeable { return restTemplate.postForEntity(baseURL + "/api/oauth2/config", oauth2Params, OAuth2ClientsParams.class).getBody(); } + public String getLoginProcessingUrl() { + return restTemplate.getForEntity(baseURL + "/api/oauth2/loginProcessingUrl", String.class).getBody(); + } + public void handleOneWayDeviceRPCRequest(DeviceId deviceId, JsonNode requestBody) { restTemplate.postForLocation(baseURL + "/api/plugins/rpc/oneway/{deviceId}", requestBody, deviceId.getId()); } diff --git a/rule-engine/pom.xml b/rule-engine/pom.xml index 197c4e500d..43bd3859af 100644 --- a/rule-engine/pom.xml +++ b/rule-engine/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT thingsboard rule-engine diff --git a/rule-engine/rule-engine-api/pom.xml b/rule-engine/rule-engine-api/pom.xml index 1a4c0b8506..448b5f8760 100644 --- a/rule-engine/rule-engine-api/pom.xml +++ b/rule-engine/rule-engine-api/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/SmsService.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/SmsService.java index fb34383a9d..01b82931a6 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/SmsService.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/SmsService.java @@ -15,7 +15,7 @@ */ package org.thingsboard.rule.engine.api; -import org.thingsboard.rule.engine.api.sms.config.TestSmsRequest; +import org.thingsboard.server.common.data.sms.config.TestSmsRequest; import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.id.TenantId; diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java index eb494af569..8dd9add1bd 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/TbContext.java @@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.ApiUsageRecordKey; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.DeviceProfile; +import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.id.DeviceId; @@ -237,7 +238,11 @@ public interface TbContext { void clearRuleNodeStates(); + void addTenantProfileListener(Consumer listener); + void addDeviceProfileListeners(Consumer listener, BiConsumer deviceListener); - void removeProfileListener(); + void removeListeners(); + + TenantProfile getTenantProfile(); } diff --git a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/SmsSenderFactory.java b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/SmsSenderFactory.java index 39daa48983..5930601c22 100644 --- a/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/SmsSenderFactory.java +++ b/rule-engine/rule-engine-api/src/main/java/org/thingsboard/rule/engine/api/sms/SmsSenderFactory.java @@ -15,7 +15,7 @@ */ package org.thingsboard.rule.engine.api.sms; -import org.thingsboard.rule.engine.api.sms.config.SmsProviderConfiguration; +import org.thingsboard.server.common.data.sms.config.SmsProviderConfiguration; public interface SmsSenderFactory { diff --git a/rule-engine/rule-engine-components/pom.xml b/rule-engine/rule-engine-components/pom.xml index 6253b39fc1..9fb02ec1f0 100644 --- a/rule-engine/rule-engine-components/pom.xml +++ b/rule-engine/rule-engine-components/pom.xml @@ -22,7 +22,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT rule-engine org.thingsboard.rule-engine diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java index fa7538bce6..27852316af 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNode.java @@ -54,7 +54,8 @@ import java.util.concurrent.TimeUnit; relationTypes = {"Alarm Created", "Alarm Updated", "Alarm Severity Updated", "Alarm Cleared", "Success", "Failure"}, configClazz = TbDeviceProfileNodeConfiguration.class, nodeDescription = "Process device messages based on device profile settings", - nodeDetails = "Create and clear alarms based on alarm rules defined in device profile. Generates ", + nodeDetails = "Create and clear alarms based on alarm rules defined in device profile. The output relation type is either " + + "'Alarm Created', 'Alarm Updated', 'Alarm Severity Updated' and 'Alarm Cleared' or simply 'Success' if no alarms were affected.", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbDeviceProfileConfig" ) @@ -119,7 +120,6 @@ public class TbDeviceProfileNode implements TbNode { } else { removeDeviceState(deviceId); } - } else { if (EntityType.DEVICE.equals(originatorType)) { DeviceId deviceId = new DeviceId(msg.getOriginator().getId()); @@ -149,7 +149,7 @@ public class TbDeviceProfileNode implements TbNode { @Override public void destroy() { - ctx.removeProfileListener(); + ctx.removeListeners(); deviceStates.clear(); } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNodeConfiguration.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNodeConfiguration.java index 14720aa342..7bbe1d9217 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNodeConfiguration.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/sms/TbSendSmsNodeConfiguration.java @@ -17,7 +17,7 @@ package org.thingsboard.rule.engine.sms; import lombok.Data; import org.thingsboard.rule.engine.api.NodeConfiguration; -import org.thingsboard.rule.engine.api.sms.config.SmsProviderConfiguration; +import org.thingsboard.server.common.data.sms.config.SmsProviderConfiguration; @Data public class TbSendSmsNodeConfiguration implements NodeConfiguration { diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java index a415e08695..e803392d5b 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/telemetry/TbMsgTimeseriesNode.java @@ -24,6 +24,7 @@ import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; +import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.kv.BasicTsKvEntry; import org.thingsboard.server.common.data.kv.KvEntry; import org.thingsboard.server.common.data.kv.TsKvEntry; @@ -31,10 +32,12 @@ import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.adaptor.JsonConverter; +import org.thingsboard.server.common.data.tenant.profile.DefaultTenantProfileConfiguration; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeUnit; @Slf4j @RuleNode( @@ -50,10 +53,20 @@ import java.util.Map; public class TbMsgTimeseriesNode implements TbNode { private TbMsgTimeseriesNodeConfiguration config; + private TbContext ctx; + private long tenantProfileDefaultStorageTtl; @Override public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException { this.config = TbNodeUtils.convert(configuration, TbMsgTimeseriesNodeConfiguration.class); + this.ctx = ctx; + ctx.addTenantProfileListener(this::onTenantProfileUpdate); + onTenantProfileUpdate(ctx.getTenantProfile()); + } + + void onTenantProfileUpdate(TenantProfile tenantProfile) { + DefaultTenantProfileConfiguration configuration = (DefaultTenantProfileConfiguration) tenantProfile.getProfileData().getConfiguration(); + tenantProfileDefaultStorageTtl = TimeUnit.DAYS.toSeconds(configuration.getDefaultStorageTtlDays()); } @Override @@ -77,6 +90,9 @@ public class TbMsgTimeseriesNode implements TbNode { } String ttlValue = msg.getMetaData().getValue("TTL"); long ttl = !StringUtils.isEmpty(ttlValue) ? Long.parseLong(ttlValue) : config.getDefaultTTL(); + if (ttl == 0L) { + ttl = tenantProfileDefaultStorageTtl; + } ctx.getTelemetryService().saveAndNotify(ctx.getTenantId(), msg.getOriginator(), tsKvEntryList, ttl, new TelemetryNodeCallback(ctx, msg)); } @@ -96,6 +112,7 @@ public class TbMsgTimeseriesNode implements TbNode { @Override public void destroy() { + ctx.removeListeners(); } } diff --git a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java index ae6bd7ebbd..39c16247fa 100644 --- a/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java +++ b/rule-engine/rule-engine-components/src/test/java/org/thingsboard/rule/engine/profile/TbDeviceProfileNodeTest.java @@ -23,17 +23,13 @@ import org.junit.runner.RunWith; import org.mockito.AdditionalAnswers; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; -import org.springframework.util.StringUtils; import org.thingsboard.rule.engine.api.RuleEngineAlarmService; import org.thingsboard.rule.engine.api.RuleEngineDeviceProfileCache; import org.thingsboard.rule.engine.api.TbContext; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.server.common.data.DeviceProfile; -import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.device.profile.AlarmCondition; import org.thingsboard.server.common.data.device.profile.AlarmRule; @@ -52,11 +48,10 @@ import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.session.SessionMsgType; -import org.thingsboard.server.dao.alarm.AlarmService; import org.thingsboard.server.dao.timeseries.TimeseriesService; import java.util.Collections; -import java.util.LinkedHashMap; +import java.util.TreeMap; import java.util.UUID; import static org.mockito.Mockito.verify; @@ -140,7 +135,7 @@ public class TbDeviceProfileNodeTest { DeviceProfileAlarm dpa = new DeviceProfileAlarm(); dpa.setId("highTemperatureAlarmID"); dpa.setAlarmType("highTemperatureAlarm"); - dpa.setCreateRules(new LinkedHashMap<>(Collections.singletonMap(AlarmSeverity.CRITICAL, alarmRule))); + dpa.setCreateRules(new TreeMap<>(Collections.singletonMap(AlarmSeverity.CRITICAL, alarmRule))); KeyFilter lowTempFilter = new KeyFilter(); lowTempFilter.setKey(new EntityKey(EntityKeyType.TIME_SERIES, "temperature")); diff --git a/tools/pom.xml b/tools/pom.xml index 14fd8b01b7..b3fce1373f 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT thingsboard tools diff --git a/transport/coap/pom.xml b/transport/coap/pom.xml index 1b7abf06db..94cb8e88a9 100644 --- a/transport/coap/pom.xml +++ b/transport/coap/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/http/pom.xml b/transport/http/pom.xml index f5ae869c75..59cfef95f0 100644 --- a/transport/http/pom.xml +++ b/transport/http/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/mqtt/pom.xml b/transport/mqtt/pom.xml index a1a45f54b8..b2ba041e0b 100644 --- a/transport/mqtt/pom.xml +++ b/transport/mqtt/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT transport org.thingsboard.transport diff --git a/transport/pom.xml b/transport/pom.xml index 429c953a46..d477fc7de2 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT thingsboard transport diff --git a/ui-ngx/package.json b/ui-ngx/package.json index 8e3ede2934..bf05109bb6 100644 --- a/ui-ngx/package.json +++ b/ui-ngx/package.json @@ -1,6 +1,6 @@ { "name": "thingsboard", - "version": "3.2.0", + "version": "3.2.1", "scripts": { "ng": "ng", "start": "node --max_old_space_size=8048 ./node_modules/@angular/cli/bin/ng serve --host 0.0.0.0 --open", diff --git a/ui-ngx/pom.xml b/ui-ngx/pom.xml index 14b9317e4a..0420401dbe 100644 --- a/ui-ngx/pom.xml +++ b/ui-ngx/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.thingsboard - 3.2.0-SNAPSHOT + 3.2.1-SNAPSHOT thingsboard org.thingsboard diff --git a/ui-ngx/src/app/core/auth/auth.service.ts b/ui-ngx/src/app/core/auth/auth.service.ts index 1f8788d821..3d4a203252 100644 --- a/ui-ngx/src/app/core/auth/auth.service.ts +++ b/ui-ngx/src/app/core/auth/auth.service.ts @@ -282,8 +282,7 @@ export class AuthService { if (publicId) { return this.publicLogin(publicId).pipe( mergeMap((response) => { - this.updateAndValidateToken(response.token, 'jwt_token', false); - this.updateAndValidateToken(response.refreshToken, 'refresh_token', false); + this.updateAndValidateTokens(response.token, response.refreshToken, false); return this.procceedJwtTokenValidate(); }), catchError((err) => { @@ -317,8 +316,7 @@ export class AuthService { }; return this.http.post('/api/auth/login', loginRequest, defaultHttpOptions()).pipe( mergeMap((loginResponse: LoginResponse) => { - this.updateAndValidateToken(loginResponse.token, 'jwt_token', false); - this.updateAndValidateToken(loginResponse.refreshToken, 'refresh_token', false); + this.updateAndValidateTokens(loginResponse.token, loginResponse.refreshToken, false); return this.procceedJwtTokenValidate(); } ) @@ -439,7 +437,7 @@ export class AuthService { })); } - public refreshJwtToken(): Observable { + public refreshJwtToken(loadUserElseStoreJwtToken = true): Observable { let response: Observable = this.refreshTokenSubject; if (this.refreshTokenSubject === null) { this.refreshTokenSubject = new ReplaySubject(1); @@ -456,7 +454,11 @@ export class AuthService { }; const refreshObservable = this.http.post('/api/auth/token', refreshTokenRequest, defaultHttpOptions()); refreshObservable.subscribe((loginResponse: LoginResponse) => { - this.setUserFromJwtToken(loginResponse.token, loginResponse.refreshToken, false); + if (loadUserElseStoreJwtToken) { + this.setUserFromJwtToken(loginResponse.token, loginResponse.refreshToken, false); + } else { + this.updateAndValidateTokens(loginResponse.token, loginResponse.refreshToken, true); + } this.refreshTokenSubject.next(loginResponse); this.refreshTokenSubject.complete(); this.refreshTokenSubject = null; @@ -474,7 +476,7 @@ export class AuthService { const subject = new ReplaySubject(); if (!AuthService.isTokenValid('jwt_token')) { if (doRefresh) { - this.refreshJwtToken().subscribe( + this.refreshJwtToken(!doRefresh).subscribe( () => { subject.next(); subject.complete(); @@ -505,8 +507,7 @@ export class AuthService { this.notifyUnauthenticated(); } } else { - this.updateAndValidateToken(jwtToken, 'jwt_token', true); - this.updateAndValidateToken(refreshToken, 'refresh_token', true); + this.updateAndValidateTokens(jwtToken, refreshToken, true); if (notify) { this.notifyUserLoaded(false); this.loadUser(false).subscribe( @@ -525,6 +526,11 @@ export class AuthService { } } + private updateAndValidateTokens(jwtToken, refreshToken, notify: boolean) { + this.updateAndValidateToken(jwtToken, 'jwt_token', notify); + this.updateAndValidateToken(refreshToken, 'refresh_token', notify); + } + public parsePublicId(): string { const token = AuthService.getJwtToken(); if (token) { diff --git a/ui-ngx/src/app/core/http/dashboard.service.ts b/ui-ngx/src/app/core/http/dashboard.service.ts index 42ba3834c9..61435747b3 100644 --- a/ui-ngx/src/app/core/http/dashboard.service.ts +++ b/ui-ngx/src/app/core/http/dashboard.service.ts @@ -130,7 +130,7 @@ export class DashboardService { const publicCustomerId = publicCustomers[0].customerId.id; let url = this.window.location.protocol + '//' + this.window.location.hostname; const port = this.window.location.port; - if (port !== '80' && port !== '443') { + if (port && port.length > 0 && port !== '80' && port !== '443') { url += ':' + port; } url += `/dashboard/${dashboard.id.id}?publicId=${publicCustomerId}`; diff --git a/ui-ngx/src/app/core/services/menu.models.ts b/ui-ngx/src/app/core/services/menu.models.ts index 028a0f5380..ad29c17258 100644 --- a/ui-ngx/src/app/core/services/menu.models.ts +++ b/ui-ngx/src/app/core/services/menu.models.ts @@ -23,6 +23,7 @@ export interface MenuSection extends HasUUID{ type: MenuSectionType; path: string; icon: string; + notExact?: boolean; isMdiIcon?: boolean; height?: string; pages?: Array; diff --git a/ui-ngx/src/app/core/services/menu.service.ts b/ui-ngx/src/app/core/services/menu.service.ts index e30d993d92..6184050142 100644 --- a/ui-ngx/src/app/core/services/menu.service.ts +++ b/ui-ngx/src/app/core/services/menu.service.ts @@ -288,6 +288,14 @@ export class MenuService { type: 'link', path: '/auditLogs', icon: 'track_changes' + }, + { + id: guid(), + name: 'api-usage.api-usage', + type: 'link', + path: '/usage', + icon: 'insert_chart', + notExact: true } ); return sections; @@ -374,6 +382,11 @@ export class MenuService { name: 'audit-log.audit-logs', icon: 'track_changes', path: '/auditLogs' + }, + { + name: 'api-usage.api-usage', + icon: 'insert_chart', + path: '/usage' } ] } diff --git a/ui-ngx/src/app/core/services/utils.service.ts b/ui-ngx/src/app/core/services/utils.service.ts index 3613c0f484..faaee28a80 100644 --- a/ui-ngx/src/app/core/services/utils.service.ts +++ b/ui-ngx/src/app/core/services/utils.service.ts @@ -21,17 +21,18 @@ import { Inject, Injectable, NgZone } from '@angular/core'; import { WINDOW } from '@core/services/window.service'; import { ExceptionData } from '@app/shared/models/error.models'; import { + baseUrl, createLabelFromDatasource, deepClone, deleteNullProperties, guid, isDefined, - isDefinedAndNotNull, + isDefinedAndNotNull, isString, isUndefined } from '@core/utils'; import { WindowMessage } from '@shared/models/window-message.model'; import { TranslateService } from '@ngx-translate/core'; -import { customTranslationsPrefix } from '@app/shared/models/constants'; +import { customTranslationsPrefix, i18nPrefix } from '@app/shared/models/constants'; import { DataKey, Datasource, DatasourceType, KeyInfo } from '@shared/models/widget.models'; import { EntityType } from '@shared/models/entity-type.models'; import { DataKeyType } from '@app/shared/models/telemetry/telemetry.models'; @@ -42,6 +43,8 @@ import jsonSchemaDefaults from 'json-schema-defaults'; import materialIconsCodepoints from '!raw-loader!material-design-icons/iconfont/codepoints'; import { Observable, of, ReplaySubject } from 'rxjs'; +const i18nRegExp = new RegExp(`{${i18nPrefix}:[^{}]+}`, 'g'); + const predefinedFunctions: { [func: string]: string } = { Sin: 'return Math.round(1000*Math.sin(time/5000));', Cos: 'return Math.round(1000*Math.cos(time/5000));', @@ -107,8 +110,8 @@ export class UtilsService { materialIcons: Array = []; constructor(@Inject(WINDOW) private window: Window, - private zone: NgZone, - private translate: TranslateService) { + private zone: NgZone, + private translate: TranslateService) { let frame: Element = null; try { frame = window.frameElement; @@ -221,8 +224,31 @@ export class UtilsService { } public customTranslation(translationValue: string, defaultValue: string): string { + if (translationValue && isString(translationValue)) { + if (translationValue.includes(`{${i18nPrefix}`)) { + const matches = translationValue.match(i18nRegExp); + let result = translationValue; + for (const match of matches) { + const translationId = match.substring(6, match.length - 1); + result = result.replace(match, this.doTranslate(translationId, match)); + } + return result; + } else { + return this.doTranslate(translationValue, defaultValue, customTranslationsPrefix); + } + } else { + return translationValue; + } + } + + private doTranslate(translationValue: string, defaultValue: string, prefix?: string): string { let result: string; - const translationId = customTranslationsPrefix + translationValue; + let translationId; + if (prefix) { + translationId = prefix + translationValue; + } else { + translationId = translationValue; + } const translation = this.translate.instant(translationId); if (translation !== translationId) { result = translation + ''; @@ -384,7 +410,7 @@ export class UtilsService { } public updateQueryParam(name: string, value: string | null) { - const baseUrl = [this.window.location.protocol, '//', this.window.location.host, this.window.location.pathname].join(''); + const baseUrlPart = [baseUrl(), this.window.location.pathname].join(''); const urlQueryString = this.window.location.search; let newParam = ''; let params = ''; @@ -404,7 +430,11 @@ export class UtilsService { } else if (newParam) { params = '?' + newParam; } - this.window.history.replaceState({}, '', baseUrl + params); + this.window.history.replaceState({}, '', baseUrlPart + params); + } + + public baseUrl(): string { + return baseUrl(); } public deepClone(target: T, ignoreFields?: string[]): T { diff --git a/ui-ngx/src/app/core/utils.ts b/ui-ngx/src/app/core/utils.ts index bf58d8c2c8..862e3a5bfd 100644 --- a/ui-ngx/src/app/core/utils.ts +++ b/ui-ngx/src/app/core/utils.ts @@ -385,6 +385,15 @@ export function padValue(val: any, dec: number): string { return strVal; } +export function baseUrl(): string { + let url = window.location.protocol + '//' + window.location.hostname; + const port = window.location.port; + if (port && port.length > 0 && port !== '80' && port !== '443') { + url += ':' + port; + } + return url; +} + export function sortObjectKeys(obj: T): T { return Object.keys(obj).sort().reduce((acc, key) => { acc[key] = obj[key]; diff --git a/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts b/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts index 99b4a82960..1297802fc3 100644 --- a/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts +++ b/ui-ngx/src/app/modules/home/components/device/copy-device-credentials.component.ts @@ -14,12 +14,12 @@ /// limitations under the License. /// -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; +import { ChangeDetectorRef, Component, Input, OnDestroy, OnInit } from '@angular/core'; import { EntityId } from '@shared/models/id/entity-id'; import { DeviceService } from '@core/http/device.service'; import { DeviceCredentials, DeviceCredentialsType } from '@shared/models/device.models'; import { isDefinedAndNotNull, isEqual } from '@core/utils'; -import { BehaviorSubject, Subject } from 'rxjs'; +import { BehaviorSubject, Subject, Subscription } from 'rxjs'; import { distinctUntilChanged, filter, mergeMap, tap } from 'rxjs/operators'; import { EntityType } from '@shared/models/entity-type.models'; import { ActionNotificationShow } from '@core/notification/notification.actions'; @@ -32,12 +32,10 @@ import { TranslateService } from '@ngx-translate/core'; templateUrl: './copy-device-credentials.component.html', styleUrls: [] }) -export class CopyDeviceCredentialsComponent implements OnDestroy { +export class CopyDeviceCredentialsComponent implements OnInit, OnDestroy { private deviceId$ = new BehaviorSubject(null); - private credentials$ = new Subject(); - private tooltipMessage: string; public hideButton = true; @@ -56,13 +54,14 @@ export class CopyDeviceCredentialsComponent implements OnDestroy { @Input() disabled: boolean; @Input() - set credentials(credential: DeviceCredentials) { - this.credentials$.next(credential); - } + credentials$: Subject; + + private credentialsSubscription: Subscription = null; constructor(private store: Store, private translate: TranslateService, - private deviceService: DeviceService + private deviceService: DeviceService, + private cd: ChangeDetectorRef ) { this.deviceId$.pipe( filter(device => isDefinedAndNotNull(device) && device.entityType === EntityType.DEVICE), @@ -73,19 +72,23 @@ export class CopyDeviceCredentialsComponent implements OnDestroy { this.processingValue(deviceCredentials); this.loading = false; }); + } - this.credentials$.pipe( + ngOnInit(): void { + this.credentialsSubscription = this.credentials$.pipe( filter(credential => isDefinedAndNotNull(credential)), distinctUntilChanged((prev, curr) => isEqual(prev, curr)) ).subscribe(deviceCredentials => { - console.warn(deviceCredentials); this.processingValue(deviceCredentials); + this.cd.detectChanges(); }); } ngOnDestroy(): void { this.deviceId$.unsubscribe(); - this.credentials$.unsubscribe(); + if (this.credentialsSubscription !== null) { + this.credentialsSubscription.unsubscribe(); + } } private processingValue(credential: DeviceCredentials): void { @@ -125,4 +128,5 @@ export class CopyDeviceCredentialsComponent implements OnDestroy { horizontalPosition: 'right' })); } + } diff --git a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html index 3468442b50..a803f4ad53 100644 --- a/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html @@ -44,8 +44,6 @@ {{ 'device-profile.alarm-type-unique' | translate }} - diff --git a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html index fa0029b46f..bc31b653b5 100644 --- a/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html +++ b/ui-ngx/src/app/modules/home/components/profile/tenant/default-tenant-profile-configuration.component.html @@ -148,6 +148,18 @@ {{ 'tenant-profile.max-d-p-storage-days-range' | translate}} + + tenant-profile.default-storage-ttl-days + + + {{ 'tenant-profile.default-storage-ttl-days-required' | translate}} + + + {{ 'tenant-profile.default-storage-ttl-days-range' | translate}} + + tenant-profile.max-rule-node-executions-per-message { this.updateModel(); diff --git a/ui-ngx/src/app/modules/home/components/widget/action/custom-action.models.ts b/ui-ngx/src/app/modules/home/components/widget/action/custom-action.models.ts index 6539780e02..e15fc7f0eb 100644 --- a/ui-ngx/src/app/modules/home/components/widget/action/custom-action.models.ts +++ b/ui-ngx/src/app/modules/home/components/widget/action/custom-action.models.ts @@ -71,7 +71,7 @@ const customPrettyActionCompletions: TbEditorCompletions = { } }, ...customActionCompletions -} +}; export const CustomActionEditorCompleter = new TbEditorCompleter(customActionCompletions); export const CustomPrettyActionEditorCompleter = new TbEditorCompleter(customPrettyActionCompletions); diff --git a/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.html b/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.html index d269fbbe92..54ddd6fc80 100644 --- a/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.html +++ b/ui-ngx/src/app/modules/home/components/widget/lib/alarms-table-widget.component.html @@ -61,7 +61,7 @@
- @@ -96,7 +96,7 @@ width: (actionCellDescriptors.length * 40) + 'px' }">
-
-
{{ column.title }} @@ -57,7 +57,7 @@ width: (actionCellDescriptors.length * 40) + 'px' }">
-
Timestamp @@ -67,7 +67,7 @@ width: (actionCellDescriptors.length * 40) + 'px' }">
- \n
\n", + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n" + }, + "title": "JavaScript functions", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": { + "cursor": "default" + }, + "titleStyle": { + "fontSize": "20px", + "fontWeight": 400 + }, + "useDashboardTimewindow": true, + "showLegend": false, + "actions": { + "elementClick": [ + { + "name": "javascript_functions_details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "javascript_functions", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "d4961bea-84de-e1af-e50f-666b98d34cd5" + } + ] + }, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "" + }, + "row": 0, + "col": 0, + "id": "fd6df872-2ddf-0921-3929-2e7f55062fad" + }, + "7e235874-461b-e7c2-2fdd-d8762a020773": { + "isSystemType": true, + "bundleAlias": "cards", + "typeAlias": "html_value_card", + "type": "latest", + "title": "New widget", + "sizeX": 7.5, + "sizeY": 3, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "dbApiState", + "type": "timeseries", + "label": "apiState", + "color": "#2196f3", + "settings": {}, + "_hash": 0.8830669138660703, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "storageDataPointsLimit", + "type": "timeseries", + "label": "limit", + "color": "#4caf50", + "settings": {}, + "_hash": 0.5463603803546802, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "storageDataPointsCount", + "type": "timeseries", + "label": "count", + "color": "#f44336", + "settings": {}, + "_hash": 0.5564241862015964, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "dbApiState", + "type": "timeseries", + "label": "apiStateClass", + "color": "#ffc107", + "settings": {}, + "_hash": 0.8737107059960671, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value ? value.toLowerCase() : '';" + }, + { + "name": "dbApiState", + "type": "timeseries", + "label": "cardId", + "color": "#607d8b", + "settings": {}, + "_hash": 0.051659774305067296, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return (Math.random()*100000).toFixed(0);" + }, + { + "name": "dbApiState", + "type": "timeseries", + "label": "title", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.6301889725474652, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"Telemetry\";" + }, + { + "name": "dbApiState", + "type": "timeseries", + "label": "unit", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.0027742924142306613, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"Data points storage days\";" + } + ] + } + ], + "timewindow": { + "realtime": { + "timewindowMs": 60000 + } + }, + "showTitle": false, + "backgroundColor": "#fff", + "color": "#666666", + "padding": "0", + "settings": { + "cardHtml": "
\n \n \n
\n
\n
\n
${title}
\n
${apiState}
\n
\n
\n
${unit}
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
", + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n" + }, + "title": "Telemetry persistence", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": { + "cursor": "default" + }, + "titleStyle": { + "fontSize": "20px", + "fontWeight": 400 + }, + "useDashboardTimewindow": true, + "showLegend": false, + "actions": { + "elementClick": [ + { + "name": "telemetry_persistence_details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "telemetry_persistence", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "6248831c-5b3f-8879-8548-afcf43f10610" + } + ] + }, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "" + }, + "row": 0, + "col": 0, + "id": "7e235874-461b-e7c2-2fdd-d8762a020773" + }, + "08545554-a0e8-05c7-66df-6000cfeff8a4": { + "isSystemType": true, + "bundleAlias": "cards", + "typeAlias": "html_value_card", + "type": "latest", + "title": "New widget", + "sizeX": 7.5, + "sizeY": 3, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "ruleEngineApiState", + "type": "timeseries", + "label": "apiState", + "color": "#2196f3", + "settings": {}, + "_hash": 0.8830669138660703, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "ruleEngineExecutionLimit", + "type": "timeseries", + "label": "limit", + "color": "#4caf50", + "settings": {}, + "_hash": 0.5463603803546802, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "ruleEngineExecutionCount", + "type": "timeseries", + "label": "count", + "color": "#f44336", + "settings": {}, + "_hash": 0.5564241862015964, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "ruleEngineApiState", + "type": "timeseries", + "label": "apiStateClass", + "color": "#ffc107", + "settings": {}, + "_hash": 0.8737107059960671, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value ? value.toLowerCase() : '';" + }, + { + "name": "ruleEngineApiState", + "type": "timeseries", + "label": "cardId", + "color": "#607d8b", + "settings": {}, + "_hash": 0.051659774305067296, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return (Math.random()*100000).toFixed(0);" + }, + { + "name": "ruleEngineApiState", + "type": "timeseries", + "label": "title", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.3551317421302518, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"Rule Engine\";" + }, + { + "name": "ruleEngineApiState", + "type": "timeseries", + "label": "unit", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.5100381746798048, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"Executions\";" + } + ] + } + ], + "timewindow": { + "realtime": { + "timewindowMs": 60000 + } + }, + "showTitle": false, + "backgroundColor": "#fff", + "color": "#666666", + "padding": "0", + "settings": { + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n", + "cardHtml": "
\n \n \n
\n
\n
\n
${title}
\n
${apiState}
\n
\n
\n
${unit}
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n \n \n
\n
" + }, + "title": "Rule Engine execution", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": { + "cursor": "default" + }, + "titleStyle": { + "fontSize": "20px", + "fontWeight": 400 + }, + "useDashboardTimewindow": true, + "showLegend": false, + "actions": { + "elementClick": [ + { + "name": "rule_engine_execution_details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "rule_engine_execution", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "3c30248f-0cd8-fb97-a917-bc1e09984a79" + }, + { + "name": "rule_engine_statistics_details", + "icon": "show_chart", + "type": "openDashboardState", + "targetDashboardStateId": "rule_engine_statistics", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "04e4565a-9e24-23df-f376-f2ec70a8165f" + } + ] + }, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "" + }, + "row": 0, + "col": 0, + "id": "08545554-a0e8-05c7-66df-6000cfeff8a4" + }, + "a245c67e-53ec-d299-fa89-69fe2062ccb2": { + "isSystemType": true, + "bundleAlias": "cards", + "typeAlias": "html_value_card", + "type": "latest", + "title": "New widget", + "sizeX": 7.5, + "sizeY": 3, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "transportApiState", + "type": "timeseries", + "label": "apiState", + "color": "#2196f3", + "settings": {}, + "_hash": 0.8830669138660703, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "transportMsgLimit", + "type": "timeseries", + "label": "limit", + "color": "#4caf50", + "settings": {}, + "_hash": 0.5463603803546802, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "transportMsgCount", + "type": "timeseries", + "label": "count", + "color": "#f44336", + "settings": {}, + "_hash": 0.5564241862015964, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "transportApiState", + "type": "timeseries", + "label": "apiStateClass", + "color": "#ffc107", + "settings": {}, + "_hash": 0.8737107059960671, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value ? value.toLowerCase() : '';" + }, + { + "name": "transportApiState", + "type": "timeseries", + "label": "cardId", + "color": "#607d8b", + "settings": {}, + "_hash": 0.051659774305067296, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return (Math.random()*100000).toFixed(0);" + }, + { + "name": "transportDataPointsLimit", + "type": "timeseries", + "label": "pointsLimit", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.22082255831864894, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "transportDataPointsCount", + "type": "timeseries", + "label": "pointsCount", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.6340356364819146, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "transportApiState", + "type": "timeseries", + "label": "title", + "color": "#3f51b5", + "settings": {}, + "_hash": 0.6894070537030252, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"Transport\";" + } + ] + } + ], + "timewindow": { + "realtime": { + "timewindowMs": 60000 + } + }, + "showTitle": false, + "backgroundColor": "#fff", + "color": "#666666", + "padding": "0", + "settings": { + "cardHtml": "
\n \n \n
\n
\n
\n
\n ${title}\n
\n
${apiState}
\n
\n
\n
\n
\n
Messages
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
Data points
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
", + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bars-row {\n flex: 1;\n display: flex;\n flex-direction: row;\n}\n\n.card .bar-column {\n flex: 1;\n display: flex;\n flex-direction: column;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 6px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n" + }, + "title": "Transport", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": { + "cursor": "default" + }, + "titleStyle": { + "fontSize": "20px", + "fontWeight": 400 + }, + "useDashboardTimewindow": true, + "showLegend": false, + "actions": { + "elementClick": [ + { + "name": "transport_details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "transport", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "46b7cefe-e1f2-67c1-4055-3a214520f869" + } + ] + }, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "" + }, + "row": 0, + "col": 0, + "id": "a245c67e-53ec-d299-fa89-69fe2062ccb2" + }, + "a151ae60-0326-6116-d818-9070dda8e9c7": { + "isSystemType": true, + "bundleAlias": "cards", + "typeAlias": "html_value_card", + "type": "latest", + "title": "New widget", + "sizeX": 7.5, + "sizeY": 3, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "emailApiState", + "type": "timeseries", + "label": "apiState", + "color": "#2196f3", + "settings": {}, + "_hash": 0.8830669138660703, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "emailLimit", + "type": "timeseries", + "label": "limit", + "color": "#4caf50", + "settings": {}, + "_hash": 0.5463603803546802, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "emailCount", + "type": "timeseries", + "label": "count", + "color": "#f44336", + "settings": {}, + "_hash": 0.5564241862015964, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "emailApiState", + "type": "timeseries", + "label": "apiStateClass", + "color": "#ffc107", + "settings": {}, + "_hash": 0.8737107059960671, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value ? value.toLowerCase() : '';" + }, + { + "name": "emailApiState", + "type": "timeseries", + "label": "cardId", + "color": "#607d8b", + "settings": {}, + "_hash": 0.051659774305067296, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return (Math.random()*100000).toFixed(0);" + }, + { + "name": "emailApiState", + "type": "timeseries", + "label": "title", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.43439375716502227, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"Email\";" + }, + { + "name": "emailApiState", + "type": "timeseries", + "label": "unit", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.9964061963495883, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"Messages\";" + } + ] + } + ], + "timewindow": { + "realtime": { + "timewindowMs": 60000 + } + }, + "showTitle": false, + "backgroundColor": "#fff", + "color": "#666666", + "padding": "0", + "settings": { + "cardHtml": "
\n \n \n
\n
\n
\n
${title}
\n
${apiState}
\n
\n
\n
${unit}
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
", + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n" + }, + "title": "Email messages", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": { + "cursor": "default" + }, + "titleStyle": { + "fontSize": "20px", + "fontWeight": 400 + }, + "useDashboardTimewindow": true, + "showLegend": false, + "actions": { + "elementClick": [ + { + "name": "email_messages_details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "email_messages", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "946ba769-84ac-1507-6baa-94701de8967b" + } + ] + }, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "" + }, + "row": 0, + "col": 0, + "id": "a151ae60-0326-6116-d818-9070dda8e9c7" + }, + "2503a391-5692-0614-85e6-f179c5ee0dc9": { + "isSystemType": true, + "bundleAlias": "cards", + "typeAlias": "html_value_card", + "type": "latest", + "title": "New widget", + "sizeX": 7.5, + "sizeY": 3, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "smsApiState", + "type": "timeseries", + "label": "apiState", + "color": "#2196f3", + "settings": {}, + "_hash": 0.8830669138660703, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "smsLimit", + "type": "timeseries", + "label": "limit", + "color": "#4caf50", + "settings": {}, + "_hash": 0.5463603803546802, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "smsCount", + "type": "timeseries", + "label": "count", + "color": "#f44336", + "settings": {}, + "_hash": 0.5564241862015964, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "smsApiState", + "type": "timeseries", + "label": "apiStateClass", + "color": "#ffc107", + "settings": {}, + "_hash": 0.8737107059960671, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return value ? value.toLowerCase() : '';" + }, + { + "name": "smsApiState", + "type": "timeseries", + "label": "cardId", + "color": "#607d8b", + "settings": {}, + "_hash": 0.051659774305067296, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return (Math.random()*100000).toFixed(0);" + }, + { + "name": "smsApiState", + "type": "timeseries", + "label": "title", + "color": "#9c27b0", + "settings": {}, + "_hash": 0.286155312985084, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"SMS\";" + }, + { + "name": "smsApiState", + "type": "timeseries", + "label": "unit", + "color": "#8bc34a", + "settings": {}, + "_hash": 0.39363366156190605, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": true, + "postFuncBody": "return \"Messages\";" + } + ] + } + ], + "timewindow": { + "realtime": { + "timewindowMs": 60000 + } + }, + "showTitle": false, + "backgroundColor": "#fff", + "color": "#666666", + "padding": "0", + "settings": { + "cardHtml": "
\n \n \n
\n
\n
\n
${title}
\n
${apiState}
\n
\n
\n
${unit}
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
", + "cardCss": ".card {\n width: 100%;\n height: 100%;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n}\n\n.card .content {\n flex: 1; \n padding: 13px 13px 0;\n display: flex;\n box-sizing: border-box;\n}\n\n.card .content .column {\n display: flex;\n flex-direction: column; \n justify-content: space-around;\n flex: 1;\n}\n\n.card .content .title-row {\n display: flex;\n flex-direction: row;\n padding-bottom: 10px;\n}\n\n.card .title {\n flex: 1;\n font-size: 20px;\n font-weight: 400;\n color: #666666;\n}\n\n.card .state {\n text-transform: uppercase;\n font-size: 20px;\n font-weight: bold;\n}\n\n.card.enabled .state {\n color: #00B260;\n}\n\n.card.warning .state {\n color: #FFAD6F;\n}\n\n.card.disabled .state {\n color: #F73243;\n}\n\n.card .bar-container {\n flex: 1;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.card .bar {\n flex: 1;\n max-height: 30px;\n margin-top: 3.5px;\n margin-bottom: 4px;\n background-color: #F0F0F0;\n border: 1px solid #DADCDB;\n border-radius: 2px;\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2);\n}\n\n.card.enabled .bar {\n border-color: #00B260;\n background-color: #F0FBF7;\n}\n\n.card.warning .bar {\n border-color: #FFAD6F;\n background-color: #FFFAF6;\n}\n\n.card.disabled .bar {\n border-color: #F73243;\n background-color: #FFF0F0;\n}\n\n.card .bar .bar-fill {\n background-color: #F0F0F0;\n border-radius: 2px;\n height: 100%;\n width: 0%;\n}\n\n.card.enabled .bar-fill {\n background-color: #00C46C;\n}\n\n.card.warning .bar-fill {\n background-color: #FFD099;\n}\n\n.card.disabled .bar-fill {\n background-color: #FF9494;\n}\n\n.card .bar-labels {\n height: 20px;\n font-size: 16px;\n color: #666;\n display: flex;\n flex-direction: row;\n}\n\n\n.card .mat-button {\n text-transform: uppercase;\n}\n\n.card .mat-button-wrapper {\n pointer-events: none;\n}\n\n.card .action-row {\n display: flex;\n flex-direction: row;\n justify-content: flex-end;\n padding: 8px 0;\n}\n\n@media screen and (min-width: 960px) and (max-width: 1279px) {\n .card .title {\n font-size: 12px;\n }\n .card .state {\n font-size: 12px;\n }\n .card .unit {\n font-size: 8px;\n }\n .card .bar-labels {\n font-size: 8px;\n }\n .card .mat-button {\n font-size: 8px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1280px) and (max-width: 1599px) {\n .card .title {\n font-size: 14px;\n }\n .card .state {\n font-size: 14px;\n }\n .card .unit {\n font-size: 10px;\n }\n .card .bar-labels {\n font-size: 10px;\n }\n .card .mat-button {\n font-size: 10px;\n }\n .card .action-row {\n padding: 0;\n }\n}\n\n@media screen and (min-width: 1600px) and (max-width: 1919px) {\n .card .title {\n font-size: 16px;\n }\n .card .state {\n font-size: 16px;\n }\n .card .unit {\n font-size: 12px;\n }\n .card .bar-labels {\n font-size: 12px;\n }\n .card .mat-button {\n font-size: 12px;\n }\n .card .action-row {\n padding: 0;\n }\n} \n\n\n" + }, + "title": "SMS messages", + "dropShadow": true, + "enableFullscreen": false, + "widgetStyle": { + "cursor": "default" + }, + "titleStyle": { + "fontSize": "20px", + "fontWeight": 400 + }, + "useDashboardTimewindow": true, + "showLegend": false, + "actions": { + "elementClick": [ + { + "name": "sms_messages_details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "sms_messages", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "73a35536-96a3-47dd-95bb-b1d9119d0ea2" + } + ] + }, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "" + }, + "row": 0, + "col": 0, + "id": "2503a391-5692-0614-85e6-f179c5ee0dc9" + }, + "68e16e98-0420-f72c-4848-41dedffd3904": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "ruleEngineExecutionCountHourly", + "type": "timeseries", + "label": "Rule Engine executions", + "color": "#ab00ff", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 86400000, + "interval": 3600000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "min": 0, + "tickDecimals": 0 + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 2400000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "Rule Engine hourly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": { + "headerButton": [ + { + "name": "View statistics", + "icon": "show_chart", + "type": "openDashboardState", + "targetDashboardStateId": "rule_engine_statistics", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "f9f08190-9ed9-d802-5b7a-c57ff84b5648" + }, + { + "name": "View details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "rule_engine_execution", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "1aec196b-44ba-ddf4-c4dc-c3f60c1eb6fc" + } + ] + }, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "68e16e98-0420-f72c-4848-41dedffd3904" + }, + "2aa6b499-6e27-b315-6833-89c4d58485ce": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "transportMsgCountHourly", + "type": "timeseries", + "label": "Transport messages", + "color": "#2196f3", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "transportDataPointsCountHourly", + "type": "timeseries", + "label": "Transport data points", + "color": "#4caf50", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.46849996721308895, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 86400000, + "interval": 3600000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "min": 0, + "tickDecimals": 0 + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": true, + "tooltipIndividual": false, + "defaultBarWidth": 2400000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + }, + "tooltipCumulative": false + }, + "title": "Transport hourly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": { + "headerButton": [ + { + "name": "View details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "transport", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "6ef12f6a-0266-25cf-6ca5-5dcb772252c6" + } + ] + }, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "2aa6b499-6e27-b315-6833-89c4d58485ce" + }, + "d890cea3-fba0-6474-9a21-fa780230dc62": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "jsExecutionCountHourly", + "type": "timeseries", + "label": "JavaScript executions", + "color": "#ff9900", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 86400000, + "interval": 3600000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "min": 0, + "tickDecimals": 0 + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 2400000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "JavaScript functions hourly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": { + "headerButton": [ + { + "name": "View details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "javascript_functions", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "4687d3f6-8800-a3b6-26e5-0d33f3b828a9" + } + ] + }, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "d890cea3-fba0-6474-9a21-fa780230dc62" + }, + "84b6cfa5-1449-e0f2-3560-f810d2dd7ead": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "storageDataPointsCountHourly", + "type": "timeseries", + "label": "Data points storage days", + "color": "#1039ee", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 86400000, + "interval": 3600000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "min": 0, + "tickDecimals": 0 + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 2400000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "Telemetry persistence hourly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": { + "headerButton": [ + { + "name": "View details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "telemetry_persistence", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "16707efb-e572-bd02-c219-55fc1b0f672a" + } + ] + }, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "84b6cfa5-1449-e0f2-3560-f810d2dd7ead" + }, + "d296b566-a000-7402-ae9d-c815381c5435": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "emailCountHourly", + "type": "timeseries", + "label": "Email messages", + "color": "#d35a00", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 86400000, + "interval": 3600000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "min": 0, + "tickDecimals": 0 + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 2400000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "Email messages hourly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": { + "headerButton": [ + { + "name": "View details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "email_messages", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "371882f9-ea23-3abc-fca8-9449c5dfdd6b" + } + ] + }, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "d296b566-a000-7402-ae9d-c815381c5435" + }, + "00a02464-9509-911b-3b5e-21fb37629822": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "smsCountHourly", + "type": "timeseries", + "label": "SMS messages", + "color": "#f36021", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 86400000, + "interval": 3600000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "min": 0, + "tickDecimals": 0 + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 2400000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "SMS messages hourly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": { + "headerButton": [ + { + "name": "View details", + "icon": "insert_chart", + "type": "openDashboardState", + "targetDashboardStateId": "sms_messages", + "setEntityId": false, + "stateEntityParamName": null, + "openRightLayout": false, + "id": "49aefac0-ec5e-d6f3-f39c-8744759f4b19" + } + ] + }, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "00a02464-9509-911b-3b5e-21fb37629822" + }, + "74199074-7873-6c6a-2a51-3fc614769f03": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "ruleEngineExecutionCountHourly", + "type": "timeseries", + "label": "Rule Engine executions", + "color": "#ab00ff", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000 + }, + "aggregation": { + "type": "SUM", + "limit": 1000 + } + }, + "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": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "min": 0, + "tickDecimals": 0 + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 1800000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "Rule Engine daily activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "74199074-7873-6c6a-2a51-3fc614769f03" + }, + "00006bc3-8a8d-b55e-ed39-e318f1bcd090": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "ruleEngineExecutionCount", + "type": "timeseries", + "label": "Rule Engine executions", + "color": "#ab00ff", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "min": 0, + "tickDecimals": 0 + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 900000000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "Rule Engine monthly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "00006bc3-8a8d-b55e-ed39-e318f1bcd090" + }, + "5f5ca59c-e507-5301-5910-7ad8cd34df40": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "jsExecutionCountHourly", + "type": "timeseries", + "label": "JavaScript executions", + "color": "#ff9900", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000 + }, + "aggregation": { + "type": "SUM", + "limit": 1000 + } + }, + "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", + "min": 0, + "tickDecimals": 0, + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 1800000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "JavaScript functions daily activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "5f5ca59c-e507-5301-5910-7ad8cd34df40" + }, + "ada32ee9-44ed-48d1-c368-fd0c94b7607f": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "jsExecutionCount", + "type": "timeseries", + "label": "JavaScript executions", + "color": "#ff9900", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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", + "min": 0, + "tickDecimals": 0, + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 900000000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "JavaScript functions monthly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "ada32ee9-44ed-48d1-c368-fd0c94b7607f" + }, + "98bae68b-0f35-72f2-a428-9b06889f1554": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "transportMsgCountHourly", + "type": "timeseries", + "label": "Transport messages", + "color": "#2196f3", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "transportDataPointsCountHourly", + "type": "timeseries", + "label": "Transport data points", + "color": "#4caf50", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.46849996721308895, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000 + }, + "aggregation": { + "type": "SUM", + "limit": 1000 + } + }, + "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": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "min": 0, + "tickDecimals": 0 + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": true, + "tooltipIndividual": false, + "defaultBarWidth": 1800000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + }, + "tooltipCumulative": false + }, + "title": "Transport daily activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "98bae68b-0f35-72f2-a428-9b06889f1554" + }, + "e61e5477-5a09-cc25-966b-f613d81da833": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "transportMsgCount", + "type": "timeseries", + "label": "Transport messages", + "color": "#2196f3", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + }, + { + "name": "transportDataPointsCount", + "type": "timeseries", + "label": "Transport data points", + "color": "#4caf50", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.46849996721308895, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 2592000000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;", + "min": 0, + "tickDecimals": 0 + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": true, + "tooltipIndividual": false, + "defaultBarWidth": 900000000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + }, + "tooltipCumulative": false + }, + "title": "Transport monthly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "e61e5477-5a09-cc25-966b-f613d81da833" + }, + "85fe0738-5326-f069-ab3f-30594bde5fed": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "storageDataPointsCountHourly", + "type": "timeseries", + "label": "Data points storage days", + "color": "#1039ee", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000 + }, + "aggregation": { + "type": "SUM", + "limit": 1000 + } + }, + "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", + "min": 0, + "tickDecimals": 0, + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 1800000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "Telemetry persistence daily activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "85fe0738-5326-f069-ab3f-30594bde5fed" + }, + "eaeb381a-437e-f6e9-60c9-6bc8826fdd44": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "storageDataPointsCount", + "type": "timeseries", + "label": "Data points storage days", + "color": "#1039ee", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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", + "min": 0, + "tickDecimals": 0, + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 900000000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "Telemetry persistence monthly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "eaeb381a-437e-f6e9-60c9-6bc8826fdd44" + }, + "4b798823-b97d-9d6a-59dc-fcafd897fc23": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "emailCountHourly", + "type": "timeseries", + "label": "Email messages", + "color": "#d35a00", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000 + }, + "aggregation": { + "type": "SUM", + "limit": 1000 + } + }, + "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", + "min": 0, + "tickDecimals": 0, + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 1800000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "Email messages daily activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "4b798823-b97d-9d6a-59dc-fcafd897fc23" + }, + "6a981580-7490-19dd-f937-b64cbf67a982": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "emailCount", + "type": "timeseries", + "label": "Email messages", + "color": "#d35a00", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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", + "min": 0, + "tickDecimals": 0, + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 900000000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "Email messages monthly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "6a981580-7490-19dd-f937-b64cbf67a982" + }, + "7302df65-1b0c-579e-bbdb-145126ae3392": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "smsCountHourly", + "type": "timeseries", + "label": "SMS messages", + "color": "#f36021", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 2592000000, + "interval": 86400000 + }, + "aggregation": { + "type": "SUM", + "limit": 1000 + } + }, + "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", + "min": 0, + "tickDecimals": 0, + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 1800000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "SMS messages daily activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "7302df65-1b0c-579e-bbdb-145126ae3392" + }, + "fdb385e7-14fe-fc9f-ebdc-b400f26fc66b": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "timeseries_bars_flot", + "type": "timeseries", + "title": "New widget", + "sizeX": 8, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "name": null, + "entityAliasId": "40193437-33ac-3172-eefd-0b08eb849062", + "filterId": null, + "dataKeys": [ + { + "name": "smsCount", + "type": "timeseries", + "label": "SMS messages", + "color": "#f36021", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": false, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.0661644137210089, + "units": null, + "decimals": null, + "funcBody": null, + "usePostProcessing": null, + "postFuncBody": null + } + ] + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 1, + "history": { + "historyType": 0, + "timewindowMs": 31536000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "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", + "min": 0, + "tickDecimals": 0, + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "defaultBarWidth": 900000000, + "barAlignment": "left", + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "SMS messages monthly activity", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "widgetStyle": {}, + "useDashboardTimewindow": false, + "showLegend": true, + "actions": {}, + "displayTimewindow": true, + "showTitleIcon": false, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "legendConfig": { + "direction": "column", + "position": "bottom", + "sortDataKeys": false, + "showMin": false, + "showMax": false, + "showAvg": false, + "showTotal": true + } + }, + "row": 0, + "col": 0, + "id": "fdb385e7-14fe-fc9f-ebdc-b400f26fc66b" + }, + "2408ad30-163e-8221-08e1-a82b638be564": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "basic_timeseries", + "type": "timeseries", + "title": "New widget", + "sizeX": 12, + "sizeY": 7, + "config": { + "datasources": [ + { + "type": "entity", + "dataKeys": [ + { + "name": "successfulMsgs", + "type": "timeseries", + "label": "${entityName} Successful", + "color": "#4caf50", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": true, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.15490750967648736 + }, + { + "name": "failedMsgs", + "type": "timeseries", + "label": "${entityName} Permanent Failures", + "color": "#ef5350", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": true, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.4186621166514697 + }, + { + "name": "tmpFailed", + "type": "timeseries", + "label": "${entityName} Processing Failures", + "color": "#ffc107", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": true, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.49891007198715376 + } + ], + "entityAliasId": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f" + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 3600000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 10000 + } + }, + "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", + "min": 0, + "tickDecimals": 0, + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "Queue Stats", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "mobileHeight": null, + "showTitleIcon": false, + "titleIcon": null, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "widgetStyle": {}, + "useDashboardTimewindow": false, + "displayTimewindow": true, + "showLegend": true, + "actions": {}, + "legendConfig": { + "direction": "column", + "position": "bottom", + "showMin": true, + "showMax": true, + "showAvg": false, + "showTotal": true + } + }, + "id": "2408ad30-163e-8221-08e1-a82b638be564" + }, + "e43dcfe1-b970-6a11-ce0e-5769f3eb5e88": { + "isSystemType": true, + "bundleAlias": "charts", + "typeAlias": "basic_timeseries", + "type": "timeseries", + "title": "New widget", + "sizeX": 12, + "sizeY": 7, + "config": { + "datasources": [ + { + "type": "entity", + "dataKeys": [ + { + "name": "timeoutMsgs", + "type": "timeseries", + "label": "${entityName} Permanent Timeouts", + "color": "#4caf50", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": true, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.565222981550328 + }, + { + "name": "tmpTimeout", + "type": "timeseries", + "label": "${entityName} Processing Timeouts", + "color": "#9c27b0", + "settings": { + "excludeFromStacking": false, + "hideDataByDefault": false, + "disableDataHiding": false, + "removeFromLegend": false, + "showLines": true, + "fillLines": false, + "showPoints": false, + "showPointShape": "circle", + "pointShapeFormatter": "", + "showPointsLineWidth": 5, + "showPointsRadius": 3, + "showSeparateAxis": false, + "axisPosition": "left", + "thresholds": [ + { + "thresholdValueSource": "predefinedValue" + } + ], + "comparisonSettings": { + "showValuesForComparison": true + } + }, + "_hash": 0.2679547062508352 + } + ], + "entityAliasId": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f" + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 3600000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 10000 + } + }, + "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", + "min": 0, + "tickDecimals": 0, + "ticksFormatter": "var rounder = Math.pow(10, 1);\nvar powers = [\n {key: 'Q', value: Math.pow(10, 15)},\n {key: 'T', value: Math.pow(10, 12)},\n {key: 'B', value: Math.pow(10, 9)},\n {key: 'M', value: Math.pow(10, 6)},\n {key: 'K', value: 1000}\n];\n\nvar key = '';\n\nfor (var i = 0; i < powers.length; i++) {\n var reduced = value / powers[i].value;\n reduced = Math.round(reduced * rounder) / rounder;\n if (reduced >= 1) {\n value = reduced;\n key = powers[i].key;\n break;\n }\n}\nreturn value + key;" + }, + "grid": { + "color": "#545454", + "tickColor": "#DDDDDD", + "verticalLines": true, + "horizontalLines": true, + "outlineWidth": 1 + }, + "stack": false, + "tooltipIndividual": false, + "timeForComparison": "months", + "xaxisSecond": { + "axisPosition": "top", + "showLabels": true + } + }, + "title": "Processing Failures and Timeouts", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "mobileHeight": null, + "showTitleIcon": false, + "titleIcon": null, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "widgetStyle": {}, + "useDashboardTimewindow": false, + "displayTimewindow": true, + "showLegend": true, + "actions": {}, + "legendConfig": { + "direction": "column", + "position": "bottom", + "showMin": true, + "showMax": true, + "showAvg": false, + "showTotal": true + } + }, + "id": "e43dcfe1-b970-6a11-ce0e-5769f3eb5e88" + }, + "a669cf86-e715-efa4-dd9a-b839abf499e9": { + "isSystemType": true, + "bundleAlias": "cards", + "typeAlias": "timeseries_table", + "type": "timeseries", + "title": "New widget", + "sizeX": 24, + "sizeY": 5, + "config": { + "datasources": [ + { + "type": "entity", + "dataKeys": [ + { + "name": "ruleEngineException", + "type": "timeseries", + "label": "Rule Chain", + "color": "#2196f3", + "settings": { + "useCellStyleFunction": false, + "useCellContentFunction": true, + "cellContentFunction": "return JSON.parse(value).ruleChainName;" + }, + "_hash": 0.9954481282345906 + }, + { + "name": "ruleEngineException", + "type": "timeseries", + "label": "Rule Node", + "color": "#4caf50", + "settings": { + "useCellStyleFunction": false, + "useCellContentFunction": true, + "cellContentFunction": "return JSON.parse(value).ruleNodeName;" + }, + "_hash": 0.18580357036589978 + }, + { + "name": "ruleEngineException", + "type": "timeseries", + "label": "Latest Error", + "color": "#f44336", + "settings": { + "useCellStyleFunction": false, + "useCellContentFunction": true, + "cellContentFunction": "return JSON.parse(value).message;" + }, + "_hash": 0.7255162989552142 + } + ], + "entityAliasId": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f" + } + ], + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 2592000000, + "interval": 1000 + }, + "aggregation": { + "type": "NONE", + "limit": 1000 + } + }, + "showTitle": true, + "backgroundColor": "rgb(255, 255, 255)", + "color": "rgba(0, 0, 0, 0.87)", + "padding": "8px", + "settings": { + "showTimestamp": true, + "displayPagination": true, + "defaultPageSize": 10 + }, + "title": "Exceptions", + "dropShadow": true, + "enableFullscreen": true, + "titleStyle": { + "fontSize": "16px", + "fontWeight": 400 + }, + "useDashboardTimewindow": false, + "showLegend": false, + "widgetStyle": {}, + "actions": {}, + "showTitleIcon": false, + "titleIcon": null, + "iconColor": "rgba(0, 0, 0, 0.87)", + "iconSize": "24px", + "titleTooltip": "", + "displayTimewindow": true + }, + "id": "a669cf86-e715-efa4-dd9a-b839abf499e9" + } + }, + "states": { + "default": { + "name": "Api Usage", + "root": true, + "layouts": { + "main": { + "widgets": { + "fd6df872-2ddf-0921-3929-2e7f55062fad": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 8, + "mobileHeight": 3 + }, + "7e235874-461b-e7c2-2fdd-d8762a020773": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 12, + "mobileHeight": 3 + }, + "08545554-a0e8-05c7-66df-6000cfeff8a4": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 4, + "mobileHeight": 3 + }, + "a245c67e-53ec-d299-fa89-69fe2062ccb2": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 0, + "mobileHeight": 3 + }, + "a151ae60-0326-6116-d818-9070dda8e9c7": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 16, + "mobileHeight": 3 + }, + "2503a391-5692-0614-85e6-f179c5ee0dc9": { + "sizeX": 4, + "sizeY": 2, + "row": 0, + "col": 20, + "mobileHeight": 3 + }, + "68e16e98-0420-f72c-4848-41dedffd3904": { + "sizeX": 8, + "sizeY": 4, + "row": 2, + "col": 8 + }, + "2aa6b499-6e27-b315-6833-89c4d58485ce": { + "sizeX": 8, + "sizeY": 4, + "row": 2, + "col": 0 + }, + "d890cea3-fba0-6474-9a21-fa780230dc62": { + "sizeX": 8, + "sizeY": 4, + "row": 2, + "col": 16 + }, + "84b6cfa5-1449-e0f2-3560-f810d2dd7ead": { + "sizeX": 8, + "sizeY": 4, + "row": 6, + "col": 0 + }, + "d296b566-a000-7402-ae9d-c815381c5435": { + "sizeX": 8, + "sizeY": 4, + "row": 6, + "col": 8 + }, + "00a02464-9509-911b-3b5e-21fb37629822": { + "sizeX": 8, + "sizeY": 4, + "row": 6, + "col": 16 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 5, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70 + } + } + } + }, + "transport": { + "name": "Transport", + "root": false, + "layouts": { + "main": { + "widgets": { + "98bae68b-0f35-72f2-a428-9b06889f1554": { + "sizeX": 24, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "e61e5477-5a09-cc25-966b-f613d81da833": { + "sizeX": 24, + "sizeY": 6, + "row": 6, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70 + } + } + } + }, + "rule_engine_execution": { + "name": "Rule Engine execution", + "root": false, + "layouts": { + "main": { + "widgets": { + "74199074-7873-6c6a-2a51-3fc614769f03": { + "sizeX": 24, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "00006bc3-8a8d-b55e-ed39-e318f1bcd090": { + "sizeX": 24, + "sizeY": 6, + "row": 6, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70 + } + } + } + }, + "javascript_functions": { + "name": "JavaScript functions", + "root": false, + "layouts": { + "main": { + "widgets": { + "5f5ca59c-e507-5301-5910-7ad8cd34df40": { + "sizeX": 24, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "ada32ee9-44ed-48d1-c368-fd0c94b7607f": { + "sizeX": 24, + "sizeY": 6, + "row": 6, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70 + } + } + } + }, + "telemetry_persistence": { + "name": "Telemetry persistence", + "root": false, + "layouts": { + "main": { + "widgets": { + "85fe0738-5326-f069-ab3f-30594bde5fed": { + "sizeX": 24, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "eaeb381a-437e-f6e9-60c9-6bc8826fdd44": { + "sizeX": 24, + "sizeY": 6, + "row": 6, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70 + } + } + } + }, + "email_messages": { + "name": "Email messages", + "root": false, + "layouts": { + "main": { + "widgets": { + "4b798823-b97d-9d6a-59dc-fcafd897fc23": { + "sizeX": 24, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "6a981580-7490-19dd-f937-b64cbf67a982": { + "sizeX": 24, + "sizeY": 6, + "row": 6, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70 + } + } + } + }, + "sms_messages": { + "name": "SMS messages", + "root": false, + "layouts": { + "main": { + "widgets": { + "7302df65-1b0c-579e-bbdb-145126ae3392": { + "sizeX": 24, + "sizeY": 6, + "row": 0, + "col": 0 + }, + "fdb385e7-14fe-fc9f-ebdc-b400f26fc66b": { + "sizeX": 24, + "sizeY": 6, + "row": 6, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70 + } + } + } + }, + "rule_engine_statistics": { + "name": "Rule Engine Statistics", + "root": false, + "layouts": { + "main": { + "widgets": { + "2408ad30-163e-8221-08e1-a82b638be564": { + "sizeX": 12, + "sizeY": 7, + "mobileHeight": null, + "row": 0, + "col": 0 + }, + "e43dcfe1-b970-6a11-ce0e-5769f3eb5e88": { + "sizeX": 12, + "sizeY": 7, + "mobileHeight": null, + "row": 0, + "col": 12 + }, + "a669cf86-e715-efa4-dd9a-b839abf499e9": { + "sizeX": 24, + "sizeY": 5, + "row": 7, + "col": 0 + } + }, + "gridSettings": { + "backgroundColor": "#eeeeee", + "color": "rgba(0,0,0,0.870588)", + "columns": 24, + "margin": 10, + "backgroundSizeMode": "100%", + "autoFillHeight": true, + "backgroundImageUrl": null, + "mobileAutoFillHeight": false, + "mobileRowHeight": 70 + } + } + } + } + }, + "entityAliases": { + "40193437-33ac-3172-eefd-0b08eb849062": { + "id": "40193437-33ac-3172-eefd-0b08eb849062", + "alias": "Api usage state", + "filter": { + "type": "apiUsageState", + "resolveMultiple": false + } + }, + "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f": { + "id": "2e4c97b0-257a-a1b9-690c-141d9bf2ec6f", + "alias": "TbServiceQueues", + "filter": { + "type": "assetType", + "resolveMultiple": true, + "assetType": "TbServiceQueue", + "assetNameFilter": "" + } + } + }, + "filters": {}, + "timewindow": { + "hideInterval": false, + "hideAggregation": false, + "hideAggInterval": false, + "selectedTab": 0, + "realtime": { + "timewindowMs": 86400000, + "interval": 3600000 + }, + "aggregation": { + "type": "NONE", + "limit": 50000 + } + }, + "settings": { + "stateControllerId": "entity", + "showTitle": false, + "showDashboardsSelect": false, + "showEntitiesSelect": false, + "showDashboardTimewindow": false, + "showDashboardExport": false, + "toolbarAlwaysOpen": true, + "titleColor": "rgba(0,0,0,0.870588)", + "showFilters": false + } + }, + "name": "Api Usage" +} \ No newline at end of file diff --git a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-page.component.html b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-page.component.html index 9f46f6b219..e6063b3556 100644 --- a/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-page.component.html +++ b/ui-ngx/src/app/modules/home/pages/dashboard/dashboard-page.component.html @@ -196,7 +196,7 @@ matTooltipPosition="above"> done -