Commit 1510fe8448002e5c0f73a7ed957a0d52721df8dc

Authored by Andrii Shvaika
1 parent 6b212bb5

Default Dashboard and Rule Chain

  1 +{
  2 + "title": "Thermostats",
  3 + "configuration": {
  4 + "widgets": {
  5 + "f33c746c-0dfc-c212-395b-b448c8a17209": {
  6 + "isSystemType": true,
  7 + "bundleAlias": "cards",
  8 + "typeAlias": "entities_table",
  9 + "type": "latest",
  10 + "title": "New widget",
  11 + "sizeX": 11,
  12 + "sizeY": 11,
  13 + "config": {
  14 + "timewindow": {
  15 + "realtime": {
  16 + "interval": 1000,
  17 + "timewindowMs": 86400000
  18 + },
  19 + "aggregation": {
  20 + "type": "NONE",
  21 + "limit": 200
  22 + }
  23 + },
  24 + "showTitle": true,
  25 + "backgroundColor": "rgb(255, 255, 255)",
  26 + "color": "rgba(0, 0, 0, 0.87)",
  27 + "padding": "4px",
  28 + "settings": {
  29 + "enableSearch": true,
  30 + "displayPagination": true,
  31 + "defaultPageSize": 10,
  32 + "defaultSortOrder": "entityName",
  33 + "displayEntityName": true,
  34 + "displayEntityType": false,
  35 + "enableSelectColumnDisplay": false,
  36 + "entitiesTitle": "Thermostats",
  37 + "displayEntityLabel": false,
  38 + "entityNameColumnTitle": "Thermostat name"
  39 + },
  40 + "title": "Thermostats",
  41 + "dropShadow": true,
  42 + "enableFullscreen": false,
  43 + "titleStyle": {
  44 + "fontSize": "16px",
  45 + "fontWeight": 400,
  46 + "padding": "5px 10px 5px 10px"
  47 + },
  48 + "useDashboardTimewindow": false,
  49 + "showLegend": false,
  50 + "datasources": [
  51 + {
  52 + "type": "entity",
  53 + "dataKeys": [
  54 + {
  55 + "name": "active",
  56 + "type": "attribute",
  57 + "label": "Active",
  58 + "color": "#2196f3",
  59 + "settings": {
  60 + "columnWidth": "0px",
  61 + "useCellStyleFunction": true,
  62 + "useCellContentFunction": true,
  63 + "cellContentFunction": "value = '⬤';\nreturn value;",
  64 + "cellStyleFunction": "var color;\nif (value === \"true\") {\n color = 'rgb(39, 134, 34)';\n} else {\n color = 'rgb(255, 0, 0)';\n}\nreturn {\n color: color,\n fontSize: '18px'\n};"
  65 + },
  66 + "_hash": 0.9264526512320641
  67 + },
  68 + {
  69 + "name": "temperature",
  70 + "type": "timeseries",
  71 + "label": "Temperature",
  72 + "color": "#4caf50",
  73 + "settings": {
  74 + "columnWidth": "0px",
  75 + "useCellStyleFunction": false,
  76 + "useCellContentFunction": false
  77 + },
  78 + "_hash": 0.9801965063904188,
  79 + "units": "°C",
  80 + "decimals": 1
  81 + },
  82 + {
  83 + "name": "humidity",
  84 + "type": "timeseries",
  85 + "label": "Humidity",
  86 + "color": "#f44336",
  87 + "settings": {
  88 + "columnWidth": "0px",
  89 + "useCellStyleFunction": false,
  90 + "useCellContentFunction": false
  91 + },
  92 + "_hash": 0.5726727868178358,
  93 + "units": "%",
  94 + "decimals": 0
  95 + }
  96 + ],
  97 + "entityAliasId": "68a058e1-fdda-8482-715b-3ae4a488568e"
  98 + }
  99 + ],
  100 + "showTitleIcon": false,
  101 + "titleIcon": null,
  102 + "iconColor": "rgba(0, 0, 0, 0.87)",
  103 + "iconSize": "24px",
  104 + "titleTooltip": "",
  105 + "widgetStyle": {},
  106 + "displayTimewindow": true,
  107 + "actions": {
  108 + "headerButton": [
  109 + {
  110 + "id": "85b803db-90f2-5c63-1388-a378e0eb10d6",
  111 + "name": "Edit location",
  112 + "icon": "map",
  113 + "type": "openDashboardState",
  114 + "targetDashboardStateId": "map",
  115 + "setEntityId": false
  116 + },
  117 + {
  118 + "id": "8ab5a518-67d2-b6a2-956d-81fd512294b2",
  119 + "name": "Add",
  120 + "icon": "add",
  121 + "type": "customPretty",
  122 + "customHtml": "<md-dialog aria-label=\"Add entity\">\n <form name=\"addEntityForm\" class=\"add-entity-form\" ng-submit=\"vm.save()\">\n <md-toolbar>\n <div class=\"md-toolbar-tools\">\n <h2>Add thermostat</h2>\n <span flex></span>\n <md-button class=\"md-icon-button\" ng-click=\"vm.cancel()\">\n <ng-md-icon icon=\"close\" aria-label=\"Close\"></ng-md-icon>\n </md-button>\n </div>\n </md-toolbar>\n <md-dialog-content>\n <div class=\"md-dialog-content\">\n <md-input-container flex class=\"md-block\">\n <label>Thermostat name</label>\n <input ng-model=\"vm.entityName\" name=entityName required>\n <div ng-messages=\"addEntityForm.entityName.$error\">\n <div ng-message=\"required\">Thermostat name is required.</div>\n </div>\n </md-input-container>\n <md-switch ng-model=\"vm.attributes.alarmTemperature\">\n High temperature alarm\n </md-switch>\n <md-input-container flex class=\"md-block\">\n <label>High temperature threshold, °C</label>\n <input name=\"thresholdTemperature\" type=\"number\" step=\"any\" \n ng-model=\"vm.attributes.thresholdTemperature\"\n ng-disabled=\"!vm.attributes.alarmTemperature\"\n ng-required=\"vm.attributes.alarmTemperature\">\n <div ng-messages=\"addEntityForm.thresholdTemperature.$error\">\n <div ng-message=\"required\">High temperature threshold is required.</div>\n </div>\n </md-input-container>\n <md-switch ng-model=\"vm.attributes.alarmHumidity\">\n Low humidity alarm\n </md-switch>\n <md-input-container flex class=\"md-block\">\n <label>Low humidity threshold, %</label>\n <input name=\"thresholdHumidity\" type=\"number\" step=\"any\" \n ng-model=\"vm.attributes.thresholdHumidity\"\n ng-disabled=\"!vm.attributes.alarmHumidity\"\n ng-required=\"vm.attributes.alarmHumidity\">\n <div ng-messages=\"addEntityForm.thresholdHumidity.$error\">\n <div ng-message=\"required\">Low humidity threshold is required.</div>\n </div>\n </md-input-container>\n </div>\n </md-dialog-content>\n <md-dialog-actions>\n <md-button type=\"submit\" ng-disabled=\"addEntityForm.$invalid || !addEntityForm.$dirty\" class=\"md-raised md-primary\">Create</md-button>\n <md-button ng-click=\"vm.cancel()\" class=\"md-primary\">Cancel</md-button>\n </md-dialog-actions>\n </form>\n</md-dialog>",
  123 + "customCss": ".add-entity-form md-input-container {\n padding-right: 10px;\n}\n\n.add-entity-form .boolean-value-input {\n padding-left: 5px;\n}\n\n.add-entity-form .boolean-value-input .checkbox-label {\n margin-bottom: 8px;\n color: rgba(0,0,0,0.54);\n font-size: 12px;\n}\n\n",
  124 + "customFunction": "var $injector = widgetContext.$scope.$injector;\nvar $mdDialog = $injector.get('$mdDialog'),\n $document = $injector.get('$document'),\n $q = $injector.get('$q'),\n $rootScope = $injector.get('$rootScope'),\n deviceService = $injector.get('deviceService'),\n attributeService = $injector.get('attributeService');\n\nopenAddEntityDialog();\n\nfunction openAddEntityDialog() {\n $mdDialog.show({\n controller: ['$scope','$mdDialog', AddEntityDialogController],\n controllerAs: 'vm',\n template: htmlTemplate,\n locals: {\n entityId: entityId\n },\n parent: angular.element($document[0].body),\n targetEvent: $event,\n multiple: true,\n clickOutsideToClose: false\n });\n}\n\nfunction AddEntityDialogController($scope, $mdDialog) {\n var vm = this;\n vm.attributes = {};\n\n vm.save = function() {\n $scope.addEntityForm.$setPristine();\n saveEntityPromise().then(\n function (entity) {\n saveAttributes(entity.id);\n updateAliasData();\n $mdDialog.hide();\n }\n );\n };\n vm.cancel = function() {\n $mdDialog.hide();\n };\n \n \n function saveEntityPromise() {\n var entity = {\n name: vm.entityName,\n type: \"thermostat\"\n };\n return deviceService.saveDevice(entity);\n }\n \n function saveAttributes(entityId) {\n var attributesArray = [];\n for (var key in vm.attributes) {\n attributesArray.push({key: key, value: vm.attributes[key]});\n }\n if (attributesArray.length > 0) {\n attributeService.saveEntityAttributes(entityId.entityType, entityId.id, \"SERVER_SCOPE\", attributesArray);\n } \n }\n \n function updateAliasData() {\n var aliasIds = [];\n for (var id in widgetContext.aliasController.resolvedAliases) {\n aliasIds.push(id);\n }\n var tasks = [];\n aliasIds.forEach(function(aliasId) {\n widgetContext.aliasController.setAliasUnresolved(aliasId);\n tasks.push(widgetContext.aliasController.getAliasInfo(aliasId));\n });\n $q.all(tasks).then(function() {\n $rootScope.$broadcast('widgetForceReInit');\n });\n }\n}\n"
  125 + }
  126 + ],
  127 + "actionCellButton": [
  128 + {
  129 + "id": "ca241cd8-788d-5508-a9ce-74b03ef42a7f",
  130 + "name": "Chart",
  131 + "icon": "show_chart",
  132 + "type": "openDashboardState",
  133 + "targetDashboardStateId": "chart",
  134 + "setEntityId": true
  135 + },
  136 + {
  137 + "id": "7506576f-87ba-d3a0-88fb-e304d451776d",
  138 + "name": "Edit",
  139 + "icon": "edit",
  140 + "type": "customPretty",
  141 + "customHtml": "<md-dialog aria-label=\"Edit entity\">\n <form name=\"editEntityForm\" class=\"edit-entity-form\" ng-submit=\"vm.save()\">\n <md-toolbar>\n <div class=\"md-toolbar-tools\">\n <h2>Edit thermostat {{vm.entityName}}</h2>\n <span flex></span>\n <md-button class=\"md-icon-button\" ng-click=\"vm.cancel()\">\n <ng-md-icon icon=\"close\" aria-label=\"Close\"></ng-md-icon>\n </md-button>\n </div>\n </md-toolbar>\n <md-dialog-content>\n <div class=\"md-dialog-content\">\n <md-input-container flex class=\"md-block\">\n <label>Thermostat name</label>\n <input ng-model=\"vm.entityName\" readonly>\n </md-input-container>\n <md-switch ng-model=\"vm.attributes.alarmTemperature\">\n High temperature alarm\n </md-switch>\n <md-input-container flex class=\"md-block\">\n <label>High temperature threshold, °C</label>\n <input name=\"thresholdTemperature\" type=\"number\" step=\"any\" \n ng-model=\"vm.attributes.thresholdTemperature\"\n ng-disabled=\"!vm.attributes.alarmTemperature\"\n ng-required=\"vm.attributes.alarmTemperature\">\n <div ng-messages=\"editEntityForm.thresholdTemperature.$error\">\n <div ng-message=\"required\">High temperature threshold is required.</div>\n </div>\n </md-input-container>\n <md-switch ng-model=\"vm.attributes.alarmHumidity\">\n Low humidity alarm\n </md-switch>\n <md-input-container flex class=\"md-block\">\n <label>Low humidity threshold, %</label>\n <input name=\"thresholdHumidity\" type=\"number\" step=\"any\" \n ng-model=\"vm.attributes.thresholdHumidity\"\n ng-disabled=\"!vm.attributes.alarmHumidity\"\n ng-required=\"vm.attributes.alarmHumidity\">\n <div ng-messages=\"editEntityForm.thresholdHumidity.$error\">\n <div ng-message=\"required\">Low humidity threshold is required.</div>\n </div>\n </md-input-container>\n </div>\n </md-dialog-content>\n <md-dialog-actions>\n <md-button type=\"submit\" ng-disabled=\"editEntityForm.$invalid || !editEntityForm.$dirty\" class=\"md-raised md-primary\">Save</md-button>\n <md-button ng-click=\"vm.cancel()\" class=\"md-primary\">Cancel</md-button>\n </md-dialog-actions>\n </form>\n</md-dialog>",
  142 + "customCss": ".edit-entity-form md-input-container {\n padding-right: 10px;\n}\n\n.edit-entity-form .boolean-value-input {\n padding-left: 5px;\n}\n\n.edit-entity-form .boolean-value-input .checkbox-label {\n margin-bottom: 8px;\n color: rgba(0,0,0,0.54);\n font-size: 12px;\n}\n",
  143 + "customFunction": "var $injector = widgetContext.$scope.$injector;\nvar $mdDialog = $injector.get('$mdDialog'),\n $document = $injector.get('$document'),\n attributeService = $injector.get('attributeService');\n\nopenEditEntityDialog();\n\nfunction openEditEntityDialog() {\n $mdDialog.show({\n controller: ['$scope','$mdDialog', EditEntityDialogController],\n controllerAs: 'vm',\n template: htmlTemplate,\n locals: {\n entityId: entityId\n },\n parent: angular.element($document[0].body),\n targetEvent: $event,\n multiple: true,\n clickOutsideToClose: false\n });\n}\n\nfunction EditEntityDialogController($scope,$mdDialog) {\n var vm = this;\n vm.entityId = entityId;\n vm.entityName = entityName;\n vm.entityType = entityId.entityType;\n vm.attributes = {};\n vm.serverAttributes = {};\n getEntityInfo();\n \n vm.save = function() {\n saveAttributes();\n $mdDialog.hide();\n };\n vm.cancel = function() {\n $mdDialog.hide();\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 vm.serverAttributes = angular.copy(vm.attributes);\n }\n \n function getEntityInfo() {\n attributeService.getEntityAttributesValues(entityId.entityType, entityId.id, 'SERVER_SCOPE').then(\n function(data){\n if (data.length) {\n getEntityAttributes(data);\n }\n });\n }\n \n function saveAttributes() {\n var attributesArray = [];\n for (var key in vm.attributes) {\n if (vm.attributes[key] !== vm.serverAttributes[key]) {\n attributesArray.push({key: key, value: vm.attributes[key]});\n }\n }\n if (attributesArray.length > 0) {\n attributeService.saveEntityAttributes(entityId.entityType, entityId.id, \"SERVER_SCOPE\", attributesArray);\n } \n }\n}"
  144 + },
  145 + {
  146 + "id": "3488848b-e47d-6af6-659f-5d78369ece5e",
  147 + "name": "Delete",
  148 + "icon": "delete",
  149 + "type": "custom",
  150 + "customFunction": "var $injector = widgetContext.$scope.$injector;\nvar $mdDialog = $injector.get('$mdDialog'),\n $document = $injector.get('$document'),\n deviceService = $injector.get('deviceService')\n $rootScope = $injector.get('$rootScope'),\n $q = $injector.get('$q');\n\nopenDeleteEntityDialog();\n\nfunction openDeleteEntityDialog() {\n var title = 'Delete thermostat \"' + entityName + '\"';\n var content = 'Are you sure you want to delete the thermostat \"' +\n entityName + '\"?';\n var confirm = $mdDialog.confirm()\n .targetEvent($event)\n .title(title)\n .htmlContent(content)\n .ariaLabel(title)\n .cancel('Cancel')\n .ok('Delete');\n $mdDialog.show(confirm).then(function() {\n deleteEntity();\n })\n}\n\nfunction deleteEntity() {\n deviceService.deleteDevice(entityId.id).then(\n function success() {\n updateAliasData();\n },\n function fail() {\n showErrorDialog();\n }\n );\n}\n\nfunction updateAliasData() {\n var aliasIds = [];\n for (var id in widgetContext.aliasController.resolvedAliases) {\n aliasIds.push(id);\n }\n var tasks = [];\n aliasIds.forEach(function(aliasId) {\n widgetContext.aliasController.setAliasUnresolved(aliasId);\n tasks.push(widgetContext.aliasController.getAliasInfo(aliasId));\n });\n $q.all(tasks).then(function() {\n $rootScope.$broadcast('entityAliasesChanged', aliasIds);\n });\n}\n\nfunction showErrorDialog() {\n var title = 'Error';\n var content = 'An error occurred while deleting the thermostat. Please try again.';\n var alert = $mdDialog.alert()\n .title(title)\n .htmlContent(content)\n .ariaLabel(title)\n .parent(angular.element($document[0].body))\n .targetEvent($event)\n .multiple(true)\n .clickOutsideToClose(true)\n .ok('CLOSE');\n $mdDialog.show(alert);\n}"
  151 + }
  152 + ],
  153 + "rowClick": [
  154 + {
  155 + "id": "e3928f23-c135-0766-71d5-65ed61e0ce8d",
  156 + "name": "show alarm",
  157 + "icon": "more_horiz",
  158 + "type": "updateDashboardState",
  159 + "targetDashboardStateId": "default",
  160 + "setEntityId": true,
  161 + "stateEntityParamName": "alarm"
  162 + }
  163 + ]
  164 + }
  165 + },
  166 + "id": "f33c746c-0dfc-c212-395b-b448c8a17209"
  167 + },
  168 + "7943196b-eedb-d422-f9c3-b32d379ad172": {
  169 + "isSystemType": true,
  170 + "bundleAlias": "alarm_widgets",
  171 + "typeAlias": "alarms_table",
  172 + "type": "alarm",
  173 + "title": "New widget",
  174 + "sizeX": 13,
  175 + "sizeY": 5,
  176 + "config": {
  177 + "timewindow": {
  178 + "realtime": {
  179 + "interval": 1000,
  180 + "timewindowMs": 86400000
  181 + },
  182 + "aggregation": {
  183 + "type": "NONE",
  184 + "limit": 200
  185 + }
  186 + },
  187 + "showTitle": true,
  188 + "backgroundColor": "rgb(255, 255, 255)",
  189 + "color": "rgba(0, 0, 0, 0.87)",
  190 + "padding": "4px",
  191 + "settings": {
  192 + "enableSelection": true,
  193 + "enableSearch": true,
  194 + "displayDetails": true,
  195 + "allowAcknowledgment": true,
  196 + "allowClear": true,
  197 + "displayPagination": true,
  198 + "defaultPageSize": 10,
  199 + "defaultSortOrder": "-createdTime",
  200 + "enableSelectColumnDisplay": false,
  201 + "enableStatusFilter": true,
  202 + "alarmsTitle": "Alarms"
  203 + },
  204 + "title": "New Alarms table",
  205 + "dropShadow": true,
  206 + "enableFullscreen": false,
  207 + "titleStyle": {
  208 + "fontSize": "16px",
  209 + "fontWeight": 400,
  210 + "padding": "5px 10px 5px 10px"
  211 + },
  212 + "useDashboardTimewindow": false,
  213 + "showLegend": false,
  214 + "alarmSource": {
  215 + "type": "entity",
  216 + "dataKeys": [
  217 + {
  218 + "name": "createdTime",
  219 + "type": "alarm",
  220 + "label": "Created time",
  221 + "color": "#2196f3",
  222 + "settings": {},
  223 + "_hash": 0.7308410188824108
  224 + },
  225 + {
  226 + "name": "originator",
  227 + "type": "alarm",
  228 + "label": "Originator",
  229 + "color": "#4caf50",
  230 + "settings": {},
  231 + "_hash": 0.056085530105439485
  232 + },
  233 + {
  234 + "name": "type",
  235 + "type": "alarm",
  236 + "label": "Type",
  237 + "color": "#f44336",
  238 + "settings": {},
  239 + "_hash": 0.10212012352561795
  240 + },
  241 + {
  242 + "name": "severity",
  243 + "type": "alarm",
  244 + "label": "Severity",
  245 + "color": "#ffc107",
  246 + "settings": {},
  247 + "_hash": 0.1777349980531262
  248 + },
  249 + {
  250 + "name": "status",
  251 + "type": "alarm",
  252 + "label": "Status",
  253 + "color": "#607d8b",
  254 + "settings": {},
  255 + "_hash": 0.7977920750136249
  256 + }
  257 + ],
  258 + "entityAliasId": "ce27a9d0-93bf-b7a4-054d-d0369a8cf813",
  259 + "name": "alarms"
  260 + },
  261 + "alarmSearchStatus": "ANY",
  262 + "alarmsPollingInterval": 5,
  263 + "showTitleIcon": false,
  264 + "titleIcon": null,
  265 + "iconColor": "rgba(0, 0, 0, 0.87)",
  266 + "iconSize": "24px",
  267 + "titleTooltip": "",
  268 + "widgetStyle": {},
  269 + "displayTimewindow": true,
  270 + "actions": {},
  271 + "datasources": [],
  272 + "alarmsMaxCountLoad": 0,
  273 + "alarmsFetchSize": 100
  274 + },
  275 + "id": "7943196b-eedb-d422-f9c3-b32d379ad172"
  276 + },
  277 + "14a19183-f0b2-d6be-0f62-9863f0a51111": {
  278 + "isSystemType": true,
  279 + "bundleAlias": "charts",
  280 + "typeAlias": "basic_timeseries",
  281 + "type": "timeseries",
  282 + "title": "New widget",
  283 + "sizeX": 18,
  284 + "sizeY": 6,
  285 + "config": {
  286 + "datasources": [
  287 + {
  288 + "type": "entity",
  289 + "dataKeys": [
  290 + {
  291 + "name": "temperature",
  292 + "type": "timeseries",
  293 + "label": "Temperature",
  294 + "color": "#ef5350",
  295 + "settings": {
  296 + "excludeFromStacking": false,
  297 + "hideDataByDefault": false,
  298 + "disableDataHiding": false,
  299 + "removeFromLegend": false,
  300 + "showLines": true,
  301 + "fillLines": true,
  302 + "showPoints": false,
  303 + "showPointShape": "circle",
  304 + "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);",
  305 + "showPointsLineWidth": 5,
  306 + "showPointsRadius": 3,
  307 + "showSeparateAxis": false,
  308 + "axisPosition": "left",
  309 + "thresholds": [
  310 + {
  311 + "thresholdValueSource": "predefinedValue"
  312 + }
  313 + ],
  314 + "comparisonSettings": {
  315 + "showValuesForComparison": true
  316 + }
  317 + },
  318 + "_hash": 0.7852346160709658,
  319 + "units": "°C",
  320 + "decimals": 1
  321 + }
  322 + ],
  323 + "entityAliasId": "12ae98c7-1ea2-52cf-64d5-763e9d993547"
  324 + }
  325 + ],
  326 + "timewindow": {
  327 + "realtime": {
  328 + "interval": 30000,
  329 + "timewindowMs": 3600000
  330 + },
  331 + "aggregation": {
  332 + "type": "AVG",
  333 + "limit": 25000
  334 + }
  335 + },
  336 + "showTitle": true,
  337 + "backgroundColor": "#fff",
  338 + "color": "rgba(0, 0, 0, 0.87)",
  339 + "padding": "8px",
  340 + "settings": {
  341 + "shadowSize": 4,
  342 + "fontColor": "#545454",
  343 + "fontSize": 10,
  344 + "xaxis": {
  345 + "showLabels": true,
  346 + "color": "#545454"
  347 + },
  348 + "yaxis": {
  349 + "showLabels": true,
  350 + "color": "#545454"
  351 + },
  352 + "grid": {
  353 + "color": "#545454",
  354 + "tickColor": "#DDDDDD",
  355 + "verticalLines": true,
  356 + "horizontalLines": true,
  357 + "outlineWidth": 1
  358 + },
  359 + "stack": false,
  360 + "tooltipIndividual": false,
  361 + "timeForComparison": "months",
  362 + "xaxisSecond": {
  363 + "axisPosition": "top",
  364 + "showLabels": true
  365 + },
  366 + "smoothLines": true
  367 + },
  368 + "title": "Temperature",
  369 + "dropShadow": true,
  370 + "enableFullscreen": true,
  371 + "titleStyle": {
  372 + "fontSize": "16px",
  373 + "fontWeight": 400
  374 + },
  375 + "mobileHeight": null,
  376 + "showTitleIcon": false,
  377 + "titleIcon": null,
  378 + "iconColor": "rgba(0, 0, 0, 0.87)",
  379 + "iconSize": "24px",
  380 + "titleTooltip": "",
  381 + "widgetStyle": {},
  382 + "useDashboardTimewindow": false,
  383 + "displayTimewindow": true,
  384 + "showLegend": true,
  385 + "legendConfig": {
  386 + "direction": "column",
  387 + "position": "bottom",
  388 + "showMin": true,
  389 + "showMax": true,
  390 + "showAvg": true,
  391 + "showTotal": false
  392 + },
  393 + "actions": {}
  394 + },
  395 + "id": "14a19183-f0b2-d6be-0f62-9863f0a51111"
  396 + },
  397 + "07f49fd5-a73b-d74c-c220-362c20af81f4": {
  398 + "isSystemType": true,
  399 + "bundleAlias": "charts",
  400 + "typeAlias": "basic_timeseries",
  401 + "type": "timeseries",
  402 + "title": "New widget",
  403 + "sizeX": 18,
  404 + "sizeY": 6,
  405 + "config": {
  406 + "datasources": [
  407 + {
  408 + "type": "entity",
  409 + "dataKeys": [
  410 + {
  411 + "name": "humidity",
  412 + "type": "timeseries",
  413 + "label": "Humidity",
  414 + "color": "#2196f3",
  415 + "settings": {
  416 + "excludeFromStacking": false,
  417 + "hideDataByDefault": false,
  418 + "disableDataHiding": false,
  419 + "removeFromLegend": false,
  420 + "showLines": true,
  421 + "fillLines": true,
  422 + "showPoints": false,
  423 + "showPointShape": "circle",
  424 + "pointShapeFormatter": "var size = radius * Math.sqrt(Math.PI) / 2;\nctx.moveTo(x - size, y - size);\nctx.lineTo(x + size, y + size);\nctx.moveTo(x - size, y + size);\nctx.lineTo(x + size, y - size);",
  425 + "showPointsLineWidth": 5,
  426 + "showPointsRadius": 3,
  427 + "showSeparateAxis": false,
  428 + "axisPosition": "left",
  429 + "thresholds": [
  430 + {
  431 + "thresholdValueSource": "predefinedValue"
  432 + }
  433 + ],
  434 + "comparisonSettings": {
  435 + "showValuesForComparison": true
  436 + }
  437 + },
  438 + "_hash": 0.28640715926957183,
  439 + "units": "%",
  440 + "decimals": 0
  441 + }
  442 + ],
  443 + "entityAliasId": "12ae98c7-1ea2-52cf-64d5-763e9d993547"
  444 + }
  445 + ],
  446 + "timewindow": {
  447 + "realtime": {
  448 + "interval": 30000,
  449 + "timewindowMs": 3600000
  450 + },
  451 + "aggregation": {
  452 + "type": "AVG",
  453 + "limit": 25000
  454 + }
  455 + },
  456 + "showTitle": true,
  457 + "backgroundColor": "#fff",
  458 + "color": "rgba(0, 0, 0, 0.87)",
  459 + "padding": "8px",
  460 + "settings": {
  461 + "shadowSize": 4,
  462 + "fontColor": "#545454",
  463 + "fontSize": 10,
  464 + "xaxis": {
  465 + "showLabels": true,
  466 + "color": "#545454"
  467 + },
  468 + "yaxis": {
  469 + "showLabels": true,
  470 + "color": "#545454"
  471 + },
  472 + "grid": {
  473 + "color": "#545454",
  474 + "tickColor": "#DDDDDD",
  475 + "verticalLines": true,
  476 + "horizontalLines": true,
  477 + "outlineWidth": 1
  478 + },
  479 + "stack": false,
  480 + "tooltipIndividual": false,
  481 + "timeForComparison": "months",
  482 + "xaxisSecond": {
  483 + "axisPosition": "top",
  484 + "showLabels": true
  485 + },
  486 + "smoothLines": true
  487 + },
  488 + "title": "Humidity",
  489 + "dropShadow": true,
  490 + "enableFullscreen": true,
  491 + "titleStyle": {
  492 + "fontSize": "16px",
  493 + "fontWeight": 400
  494 + },
  495 + "mobileHeight": null,
  496 + "showTitleIcon": false,
  497 + "titleIcon": null,
  498 + "iconColor": "rgba(0, 0, 0, 0.87)",
  499 + "iconSize": "24px",
  500 + "titleTooltip": "",
  501 + "widgetStyle": {},
  502 + "useDashboardTimewindow": false,
  503 + "displayTimewindow": true,
  504 + "showLegend": true,
  505 + "legendConfig": {
  506 + "direction": "column",
  507 + "position": "bottom",
  508 + "showMin": true,
  509 + "showMax": true,
  510 + "showAvg": true,
  511 + "showTotal": false
  512 + },
  513 + "actions": {}
  514 + },
  515 + "id": "07f49fd5-a73b-d74c-c220-362c20af81f4"
  516 + },
  517 + "c4631f94-2db3-523b-4d09-2a1a0a75d93f": {
  518 + "isSystemType": true,
  519 + "bundleAlias": "input_widgets",
  520 + "typeAlias": "update_multiple_attributes",
  521 + "type": "latest",
  522 + "title": "New widget",
  523 + "sizeX": 6,
  524 + "sizeY": 6,
  525 + "config": {
  526 + "datasources": [
  527 + {
  528 + "type": "entity",
  529 + "dataKeys": [
  530 + {
  531 + "name": "alarmTemperature",
  532 + "type": "attribute",
  533 + "label": "High temperature alarm",
  534 + "color": "#4caf50",
  535 + "settings": {
  536 + "dataKeyType": "server",
  537 + "dataKeyValueType": "booleanCheckbox",
  538 + "required": false,
  539 + "isEditable": "editable",
  540 + "dataKeyHidden": false,
  541 + "step": 1
  542 + },
  543 + "_hash": 0.8725278440159361
  544 + },
  545 + {
  546 + "name": "thresholdTemperature",
  547 + "type": "attribute",
  548 + "label": "High temperature threshold, °C",
  549 + "color": "#f44336",
  550 + "settings": {
  551 + "dataKeyType": "server",
  552 + "dataKeyValueType": "double",
  553 + "required": false,
  554 + "isEditable": "editable",
  555 + "dataKeyHidden": false,
  556 + "step": 1,
  557 + "disabledOnDataKey": "alarmTemperature"
  558 + },
  559 + "_hash": 0.7316078472857874
  560 + },
  561 + {
  562 + "name": "alarmHumidity",
  563 + "type": "attribute",
  564 + "label": "Low humidity alarm",
  565 + "color": "#ffc107",
  566 + "settings": {
  567 + "dataKeyType": "server",
  568 + "dataKeyValueType": "booleanCheckbox",
  569 + "required": false,
  570 + "isEditable": "editable",
  571 + "dataKeyHidden": false,
  572 + "step": 1
  573 + },
  574 + "_hash": 0.5339673667431057
  575 + },
  576 + {
  577 + "name": "thresholdHumidity",
  578 + "type": "attribute",
  579 + "label": "Low humidity threshold, %",
  580 + "color": "#607d8b",
  581 + "settings": {
  582 + "dataKeyType": "server",
  583 + "dataKeyValueType": "double",
  584 + "required": false,
  585 + "isEditable": "editable",
  586 + "dataKeyHidden": false,
  587 + "step": 1,
  588 + "disabledOnDataKey": "alarmHumidity"
  589 + },
  590 + "_hash": 0.2687091190358901
  591 + }
  592 + ],
  593 + "entityAliasId": "12ae98c7-1ea2-52cf-64d5-763e9d993547"
  594 + }
  595 + ],
  596 + "timewindow": {
  597 + "realtime": {
  598 + "timewindowMs": 60000
  599 + }
  600 + },
  601 + "showTitle": true,
  602 + "backgroundColor": "#fff",
  603 + "color": "rgba(0, 0, 0, 0.87)",
  604 + "padding": "8px",
  605 + "settings": {
  606 + "showActionButtons": false,
  607 + "showResultMessage": true,
  608 + "fieldsAlignment": "column",
  609 + "fieldsInRow": 2,
  610 + "groupTitle": "${entityName}",
  611 + "widgetTitle": "Termostat settings"
  612 + },
  613 + "title": "New Update Multiple Attributes",
  614 + "dropShadow": true,
  615 + "enableFullscreen": false,
  616 + "enableDataExport": false,
  617 + "widgetStyle": {},
  618 + "titleStyle": {
  619 + "fontSize": "16px",
  620 + "fontWeight": 400
  621 + },
  622 + "useDashboardTimewindow": true,
  623 + "showLegend": false,
  624 + "actions": {},
  625 + "showTitleIcon": false,
  626 + "titleIcon": null,
  627 + "iconColor": "rgba(0, 0, 0, 0.87)",
  628 + "iconSize": "24px",
  629 + "titleTooltip": "",
  630 + "displayTimewindow": true
  631 + },
  632 + "id": "c4631f94-2db3-523b-4d09-2a1a0a75d93f"
  633 + },
  634 + "3da9a9a1-0b9a-2e1f-0dcb-0ff34a695abb": {
  635 + "isSystemType": true,
  636 + "bundleAlias": "maps_v2",
  637 + "typeAlias": "openstreetmap",
  638 + "type": "latest",
  639 + "title": "New widget",
  640 + "sizeX": 13,
  641 + "sizeY": 6,
  642 + "config": {
  643 + "datasources": [
  644 + {
  645 + "type": "entity",
  646 + "dataKeys": [
  647 + {
  648 + "name": "temperature",
  649 + "type": "timeseries",
  650 + "label": "temperature",
  651 + "color": "#2196f3",
  652 + "settings": {},
  653 + "_hash": 0.1371919646686739,
  654 + "decimals": 1,
  655 + "postFuncBody": "return value || \"\";"
  656 + },
  657 + {
  658 + "name": "humidity",
  659 + "type": "timeseries",
  660 + "label": "humidity",
  661 + "color": "#4caf50",
  662 + "settings": {},
  663 + "_hash": 0.043177186765847475,
  664 + "decimals": 0,
  665 + "postFuncBody": "return value || \"\";"
  666 + },
  667 + {
  668 + "name": "longitude",
  669 + "type": "attribute",
  670 + "label": "longitude",
  671 + "color": "#f44336",
  672 + "settings": {},
  673 + "_hash": 0.5548964320315584
  674 + },
  675 + {
  676 + "name": "latitude",
  677 + "type": "attribute",
  678 + "label": "latitude",
  679 + "color": "#ffc107",
  680 + "settings": {},
  681 + "_hash": 0.1803778014971602
  682 + },
  683 + {
  684 + "name": "active",
  685 + "type": "attribute",
  686 + "label": "active",
  687 + "color": "#607d8b",
  688 + "settings": {},
  689 + "_hash": 0.30926987994082844
  690 + }
  691 + ],
  692 + "entityAliasId": "68a058e1-fdda-8482-715b-3ae4a488568e"
  693 + }
  694 + ],
  695 + "timewindow": {
  696 + "realtime": {
  697 + "timewindowMs": 60000
  698 + }
  699 + },
  700 + "showTitle": false,
  701 + "backgroundColor": "#fff",
  702 + "color": "rgba(0, 0, 0, 0.87)",
  703 + "padding": "8px",
  704 + "settings": {
  705 + "fitMapBounds": true,
  706 + "latKeyName": "latitude",
  707 + "lngKeyName": "longitude",
  708 + "showLabel": true,
  709 + "label": "${entityName}",
  710 + "tooltipPattern": "<b>${entityName}</b><br/><br/><b>Temperature:</b> ${temperature:1} °C<br/><b>Humidity:</b> ${humidity:0} %<br/><br/><link-act name=\"navigate_to_details\">Thermostat details</link-act><br/>",
  711 + "markerImageSize": 48,
  712 + "useColorFunction": false,
  713 + "markerImages": [
  714 + "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiNmNDQzMzZ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+",
  715 + "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiMyNzg2MjJ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+Cg=="
  716 + ],
  717 + "useMarkerImageFunction": true,
  718 + "colorFunction": "\n",
  719 + "color": "#fe7569",
  720 + "mapProvider": "OpenStreetMap.HOT",
  721 + "showTooltip": true,
  722 + "autocloseTooltip": true,
  723 + "customProviderTileUrl": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
  724 + "defaultCenterPosition": [
  725 + 0,
  726 + 0
  727 + ],
  728 + "showTooltipAction": "click",
  729 + "polygonKeyName": "coordinates",
  730 + "polygonOpacity": 0.5,
  731 + "polygonStrokeOpacity": 1,
  732 + "polygonStrokeWeight": 1,
  733 + "zoomOnClick": true,
  734 + "showCoverageOnHover": true,
  735 + "animate": true,
  736 + "maxClusterRadius": 80,
  737 + "removeOutsideVisibleBounds": true,
  738 + "useLabelFunction": true,
  739 + "labelFunction": "var color;\nif(dsData[dsIndex].active !== \"true\"){\n color = 'rgb(255, 0, 0)';\n} else {\n color = 'rgb(39, 134, 34)';\n}\nreturn '<span style=\"border: solid ' + color + '; border-radius: 10px; color: ' + color + '; background-color: #fff; padding: 3px 5px; font-size: 14px\">' + \n '${entityLabel}' + \n '</span>'",
  740 + "defaultZoomLevel": 14,
  741 + "markerImageFunction": "var res;\nif(dsData[dsIndex].active !== \"true\"){\n\tvar res = {\n\t url: images[0],\n\t size: 48\n\t}\n} else {\n var res = {\n\t url: images[1],\n\t size: 48\n\t}\n}\nreturn res;"
  742 + },
  743 + "title": "Thermostat maps",
  744 + "dropShadow": true,
  745 + "enableFullscreen": false,
  746 + "titleStyle": {
  747 + "fontSize": "16px",
  748 + "fontWeight": 400
  749 + },
  750 + "useDashboardTimewindow": true,
  751 + "showLegend": false,
  752 + "widgetStyle": {},
  753 + "actions": {
  754 + "headerButton": [],
  755 + "tooltipAction": [
  756 + {
  757 + "id": "bef25673-b37a-8821-bc0f-5d6dd3680f24",
  758 + "name": "navigate_to_details",
  759 + "icon": "more_horiz",
  760 + "type": "openDashboardState",
  761 + "targetDashboardStateId": "chart",
  762 + "setEntityId": true
  763 + }
  764 + ]
  765 + },
  766 + "showTitleIcon": false,
  767 + "titleIcon": null,
  768 + "iconColor": "rgba(0, 0, 0, 0.87)",
  769 + "iconSize": "24px",
  770 + "titleTooltip": "",
  771 + "displayTimewindow": true
  772 + },
  773 + "id": "3da9a9a1-0b9a-2e1f-0dcb-0ff34a695abb"
  774 + },
  775 + "00fb2742-ba1f-7e43-673f-d6c08b72ed06": {
  776 + "isSystemType": true,
  777 + "bundleAlias": "input_widgets",
  778 + "typeAlias": "markers_placement_openstreetmap",
  779 + "type": "latest",
  780 + "title": "New widget",
  781 + "sizeX": 24,
  782 + "sizeY": 12,
  783 + "config": {
  784 + "datasources": [
  785 + {
  786 + "type": "entity",
  787 + "dataKeys": [
  788 + {
  789 + "name": "longitude",
  790 + "type": "attribute",
  791 + "label": "longitude",
  792 + "color": "#2196f3",
  793 + "settings": {},
  794 + "_hash": 0.3640193654284214
  795 + },
  796 + {
  797 + "name": "latitude",
  798 + "type": "attribute",
  799 + "label": "latitude",
  800 + "color": "#4caf50",
  801 + "settings": {},
  802 + "_hash": 0.49020393887695923
  803 + },
  804 + {
  805 + "name": "temperature",
  806 + "type": "timeseries",
  807 + "label": "temperature",
  808 + "color": "#f44336",
  809 + "settings": {},
  810 + "_hash": 0.5885892766009955,
  811 + "postFuncBody": "return value || \"\";"
  812 + },
  813 + {
  814 + "name": "humidity",
  815 + "type": "timeseries",
  816 + "label": "humidity",
  817 + "color": "#ffc107",
  818 + "settings": {},
  819 + "_hash": 0.21077893588180707,
  820 + "postFuncBody": "return value || \"\";"
  821 + },
  822 + {
  823 + "name": "active",
  824 + "type": "attribute",
  825 + "label": "active",
  826 + "color": "#607d8b",
  827 + "settings": {},
  828 + "_hash": 0.34722983638504346
  829 + }
  830 + ],
  831 + "entityAliasId": "68a058e1-fdda-8482-715b-3ae4a488568e"
  832 + }
  833 + ],
  834 + "timewindow": {
  835 + "realtime": {
  836 + "timewindowMs": 60000
  837 + }
  838 + },
  839 + "showTitle": false,
  840 + "backgroundColor": "#fff",
  841 + "color": "rgba(0, 0, 0, 0.87)",
  842 + "padding": "8px",
  843 + "settings": {
  844 + "fitMapBounds": true,
  845 + "latKeyName": "latitude",
  846 + "lngKeyName": "longitude",
  847 + "showLabel": true,
  848 + "label": "${entityName}",
  849 + "tooltipPattern": "<b>${entityName}</b><br/><br/><b>Temperature:</b> ${temperature:1} °C<br/><b>Humidity:</b> ${humidity:0} %<br/><br/><link-act name='delete'>Delete</link-act>",
  850 + "markerImageSize": 34,
  851 + "useColorFunction": false,
  852 + "markerImages": [
  853 + "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiNmNDQzMzZ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+",
  854 + "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiMyNzg2MjJ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+Cg=="
  855 + ],
  856 + "useMarkerImageFunction": true,
  857 + "color": "#fe7569",
  858 + "mapProvider": "OpenStreetMap.HOT",
  859 + "showTooltip": true,
  860 + "autocloseTooltip": true,
  861 + "defaultCenterPosition": [
  862 + 0,
  863 + 0
  864 + ],
  865 + "customProviderTileUrl": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
  866 + "showTooltipAction": "click",
  867 + "polygonKeyName": "coordinates",
  868 + "polygonOpacity": 0.5,
  869 + "polygonStrokeOpacity": 1,
  870 + "polygonStrokeWeight": 1,
  871 + "zoomOnClick": true,
  872 + "showCoverageOnHover": true,
  873 + "animate": true,
  874 + "maxClusterRadius": 80,
  875 + "removeOutsideVisibleBounds": true,
  876 + "defaultZoomLevel": 12,
  877 + "labelFunction": "var color;\nif(dsData[dsIndex].active !== \"true\"){\n color = 'rgb(255, 0, 0)';\n} else {\n color = 'rgb(39, 134, 34)';\n}\nreturn '<span style=\"border: solid ' + color + '; border-radius: 10px; color: ' + color + '; background-color: #fff; padding: 3px 5px; font-size: 14px\">' + \n '${entityLabel}' + \n '</span>'",
  878 + "markerImageFunction": "var res;\nif(dsData[dsIndex].active !== \"true\"){\n\tvar res = {\n\t url: images[0],\n\t size: 48\n\t}\n} else {\n var res = {\n\t url: images[1],\n\t size: 48\n\t}\n}\nreturn res;",
  879 + "useLabelFunction": true
  880 + },
  881 + "title": "New Markers Placement - OpenStreetMap",
  882 + "dropShadow": true,
  883 + "enableFullscreen": false,
  884 + "titleStyle": {
  885 + "fontSize": "16px",
  886 + "fontWeight": 400
  887 + },
  888 + "useDashboardTimewindow": true,
  889 + "showLegend": false,
  890 + "widgetStyle": {},
  891 + "actions": {
  892 + "tooltipAction": [
  893 + {
  894 + "id": "54c293c4-9ca6-e34f-dc6a-0271944c1c66",
  895 + "name": "delete",
  896 + "icon": "more_horiz",
  897 + "type": "custom",
  898 + "customFunction": "var $rootScope = widgetContext.$scope.$injector.get('$rootScope');\nvar entityDatasource = widgetContext.map.subscription.datasources.filter(\n function(entity) {\n return entity.entityId === entityId.id\n });\n\nwidgetContext.map.saveMarkerLocation(entityDatasource[0],\n widgetContext.map.locations[0], {\n \"lat\": null,\n \"lng\": null\n }).then(function succes() {\n $rootScope.$broadcast('widgetForceReInit');\n });"
  899 + }
  900 + ]
  901 + },
  902 + "showTitleIcon": false,
  903 + "titleIcon": null,
  904 + "iconColor": "rgba(0, 0, 0, 0.87)",
  905 + "iconSize": "24px",
  906 + "titleTooltip": "",
  907 + "displayTimewindow": true
  908 + },
  909 + "id": "00fb2742-ba1f-7e43-673f-d6c08b72ed06"
  910 + },
  911 + "0a430429-9078-9ae6-2b67-e4a15a2bf8bf": {
  912 + "isSystemType": true,
  913 + "bundleAlias": "input_widgets",
  914 + "typeAlias": "markers_placement_openstreetmap",
  915 + "type": "latest",
  916 + "title": "New widget",
  917 + "sizeX": 6,
  918 + "sizeY": 6,
  919 + "config": {
  920 + "datasources": [
  921 + {
  922 + "type": "entity",
  923 + "dataKeys": [
  924 + {
  925 + "name": "longitude",
  926 + "type": "attribute",
  927 + "label": "longitude",
  928 + "color": "#2196f3",
  929 + "settings": {},
  930 + "_hash": 0.3640193654284214
  931 + },
  932 + {
  933 + "name": "latitude",
  934 + "type": "attribute",
  935 + "label": "latitude",
  936 + "color": "#4caf50",
  937 + "settings": {},
  938 + "_hash": 0.49020393887695923
  939 + },
  940 + {
  941 + "name": "temperature",
  942 + "type": "timeseries",
  943 + "label": "temperature",
  944 + "color": "#f44336",
  945 + "settings": {},
  946 + "_hash": 0.5885892766009955,
  947 + "postFuncBody": "return value || \"\";"
  948 + },
  949 + {
  950 + "name": "humidity",
  951 + "type": "timeseries",
  952 + "label": "humidity",
  953 + "color": "#ffc107",
  954 + "settings": {},
  955 + "_hash": 0.21077893588180707,
  956 + "postFuncBody": "return value || \"\";"
  957 + },
  958 + {
  959 + "name": "active",
  960 + "type": "attribute",
  961 + "label": "active",
  962 + "color": "#607d8b",
  963 + "settings": {},
  964 + "_hash": 0.34722983638504346
  965 + }
  966 + ],
  967 + "entityAliasId": "12ae98c7-1ea2-52cf-64d5-763e9d993547"
  968 + }
  969 + ],
  970 + "timewindow": {
  971 + "realtime": {
  972 + "timewindowMs": 60000
  973 + }
  974 + },
  975 + "showTitle": false,
  976 + "backgroundColor": "#fff",
  977 + "color": "rgba(0, 0, 0, 0.87)",
  978 + "padding": "8px",
  979 + "settings": {
  980 + "fitMapBounds": true,
  981 + "latKeyName": "latitude",
  982 + "lngKeyName": "longitude",
  983 + "showLabel": true,
  984 + "label": "${entityName}",
  985 + "tooltipPattern": "<b>${entityName}</b><br/><br/><b>Temperature:</b> ${temperature:1} °C<br/><b>Humidity:</b> ${humidity:0} %<br/><br/><link-act name='delete'>Delete</link-act>",
  986 + "markerImageSize": 34,
  987 + "useColorFunction": false,
  988 + "markerImages": [
  989 + "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiNmNDQzMzZ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+",
  990 + "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJzdmc0NDA4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjAiIHk9IjAiIHZpZXdCb3g9IjAgMCAxNTAgMTUwIiB4bWw6c3BhY2U9InByZXNlcnZlIj48c3R5bGU+LnN0MntmaWxsOiMyNzg2MjJ9PC9zdHlsZT48ZyBpZD0ibGF5ZXIxIj48ZyBpZD0icGF0aDY4ODEtMy01LTUtMS04LTQtNC03LTgiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0xNDYuNDM4IC0yNzYuMDI4KSIgb3BhY2l0eT0iLjg5MiI+PHJhZGlhbEdyYWRpZW50IGlkPSJTVkdJRF8xXyIgY3g9IjMwODUuMjE1IiBjeT0iMzE3OC40NTgiIHI9IjQ5LjkwMSIgZ3JhZGllbnRUcmFuc2Zvcm09Im1hdHJpeCguNjc5MyAuMDA3NiAtLjUwOSAuNTYxMiAtMjMyLjYyOSAtMTQxMS43MjUpIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLW9wYWNpdHk9Ii4xODgiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGQ9Ik0yODUuNiAzODguNWMxMC4zLTEyLjQgNC40LTIyLjQtMTQuNC0yMi40LTE4LjkgMC00Mi40IDEwLTUzLjkgMjIuNC0xNi44IDE4IC40IDIzLjUtLjIgMzUtLjEgMS44IDMuOSAxLjggNyAwIDE5LjgtMTEuNSA0Ni41LTE3IDYxLjUtMzUiIGZpbGw9InVybCgjU1ZHSURfMV8pIi8+PC9nPjxwYXRoIGlkPSJwYXRoNjg4MS0zLTUtNS0xLTgtNC00IiBjbGFzcz0ic3QyIiBkPSJNMTI0LjcgNjkuMWMtLjktMjcuNS0yMi4zLTQ5LjgtNDkuOC00OS44cy00OSAyMi4zLTQ5LjggNDkuOGMtMS4zIDQwLjEgMzAuNyA1Mi4yIDQ0LjcgNzggMi4yIDQgOCA0IDEwLjEgMCAxNC4xLTI1LjggNDYuMS0zNy45IDQ0LjgtNzgiLz48L2c+PGcgaWQ9Imc0OTI4Ij48Y2lyY2xlIGlkPSJwYXRoNDk3OCIgY2xhc3M9InN0MiIgY3g9Ijc0LjkiIGN5PSI2OS4xIiByPSI0OS45Ii8+PGcgaWQ9Imc0OTE1Ij48cGF0aCBpZD0icGF0aDY4ODMtMi0zLTUtMi00LTktNC05IiBkPSJNNzQuOCAxMDYuNGMtMjAuNiAwLTM3LjQtMTYuNy0zNy40LTM3LjQgMC0yMC42IDE2LjctMzcuNCAzNy40LTM3LjQgMjAuNiAwIDM3LjQgMTYuNyAzNy40IDM3LjRzLTE2LjcgMzcuNC0zNy40IDM3LjQiIGZpbGw9IiNmZmYiLz48L2c+PC9nPjxwYXRoIGNsYXNzPSJzdDIiIGQ9Ik05NS45IDQ2LjZWNDloLTEwdi0yLjVsMTAgLjF6bS0yIDUuM2gtOHYyLjVoOHYtMi41em0tOCA3LjloNnYtMi41aC02djIuNXptNCAyLjloLTR2Mi41aDR2LTIuNXptLTQgNy44aDJWNjhoLTJ2Mi41em0xLjUgMTRjMCA2LjktNS41IDEyLjUtMTIuMyAxMi41cy0xMi4zLTUuNi0xMi4zLTEyLjVjMC00LjUgMi4zLTguNSA2LjEtMTAuN1Y0NS41YzAtMy41IDIuOC02LjMgNi4yLTYuM3M2LjIgMi44IDYuMiA2LjN2MjguM2MzLjggMi4yIDYuMSA2LjMgNi4xIDEwLjd6bS0yLjQgMGMwLTMuOC0yLjEtNy4yLTUuNC04LjlsLS43LS4zVjQ1LjVjMC0yLjEtMS43LTMuOC0zLjgtMy44LTIuMSAwLTMuOCAxLjctMy44IDMuOHYyOS44bC0uNy4zYy0zLjMgMS43LTUuNCA1LjEtNS40IDguOSAwIDUuNSA0LjQgMTAgOS45IDEwUzg1IDkwIDg1IDg0LjV6bS0yLjEgMGMwIDQuNC0zLjUgOC03LjggOHMtNy44LTMuNi03LjgtOGMwLTMuNiAyLjQtNi44IDUuOC03LjdsLjUtLjFWNjEuNWgzLjF2MTUuMmwuNS4xYzMuMyAxIDUuNyA0LjEgNS43IDcuN3ptLTcuNC01LjNjLS4yLS44LTEtMS40LTEuOS0xLjItMyAuNy01IDMuMy01IDYuNCAwIC45LjcgMS42IDEuNiAxLjZzMS42LS43IDEuNi0xLjZjMC0xLjYgMS4xLTMgMi42LTMuMy43LS4yIDEuMy0xIDEuMS0xLjl6Ii8+PC9zdmc+Cg=="
  991 + ],
  992 + "useMarkerImageFunction": true,
  993 + "color": "#fe7569",
  994 + "mapProvider": "OpenStreetMap.HOT",
  995 + "showTooltip": true,
  996 + "autocloseTooltip": true,
  997 + "defaultCenterPosition": [
  998 + 0,
  999 + 0
  1000 + ],
  1001 + "customProviderTileUrl": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
  1002 + "showTooltipAction": "click",
  1003 + "polygonKeyName": "coordinates",
  1004 + "polygonOpacity": 0.5,
  1005 + "polygonStrokeOpacity": 1,
  1006 + "polygonStrokeWeight": 1,
  1007 + "zoomOnClick": true,
  1008 + "showCoverageOnHover": true,
  1009 + "animate": true,
  1010 + "maxClusterRadius": 80,
  1011 + "removeOutsideVisibleBounds": true,
  1012 + "defaultZoomLevel": 12,
  1013 + "labelFunction": "var color;\nif(dsData[dsIndex].active !== \"true\"){\n color = 'rgb(255, 0, 0)';\n} else {\n color = 'rgb(39, 134, 34)';\n}\nreturn '<span style=\"border: solid ' + color + '; border-radius: 10px; color: ' + color + '; background-color: #fff; padding: 3px 5px; font-size: 14px\">' + \n '${entityLabel}' + \n '</span>'",
  1014 + "markerImageFunction": "var res;\nif(dsData[dsIndex].active !== \"true\"){\n\tvar res = {\n\t url: images[0],\n\t size: 48\n\t}\n} else {\n var res = {\n\t url: images[1],\n\t size: 48\n\t}\n}\nreturn res;",
  1015 + "useLabelFunction": true
  1016 + },
  1017 + "title": "New Markers Placement - OpenStreetMap",
  1018 + "dropShadow": true,
  1019 + "enableFullscreen": false,
  1020 + "titleStyle": {
  1021 + "fontSize": "16px",
  1022 + "fontWeight": 400
  1023 + },
  1024 + "useDashboardTimewindow": true,
  1025 + "showLegend": false,
  1026 + "widgetStyle": {},
  1027 + "actions": {
  1028 + "tooltipAction": [
  1029 + {
  1030 + "id": "54c293c4-9ca6-e34f-dc6a-0271944c1c66",
  1031 + "name": "delete",
  1032 + "icon": "more_horiz",
  1033 + "type": "custom",
  1034 + "customFunction": "var $rootScope = widgetContext.$scope.$injector.get('$rootScope');\nvar entityDatasource = widgetContext.map.subscription.datasources.filter(\n function(entity) {\n return entity.entityId === entityId.id\n });\n\nwidgetContext.map.saveMarkerLocation(entityDatasource[0],\n widgetContext.map.locations[0], {\n \"lat\": null,\n \"lng\": null\n }).then(function succes() {\n $rootScope.$broadcast('widgetForceReInit');\n });"
  1035 + }
  1036 + ]
  1037 + },
  1038 + "showTitleIcon": false,
  1039 + "titleIcon": null,
  1040 + "iconColor": "rgba(0, 0, 0, 0.87)",
  1041 + "iconSize": "24px",
  1042 + "titleTooltip": "",
  1043 + "displayTimewindow": true
  1044 + },
  1045 + "id": "0a430429-9078-9ae6-2b67-e4a15a2bf8bf"
  1046 + }
  1047 + },
  1048 + "states": {
  1049 + "default": {
  1050 + "name": "Thermostat",
  1051 + "root": true,
  1052 + "layouts": {
  1053 + "main": {
  1054 + "widgets": {
  1055 + "f33c746c-0dfc-c212-395b-b448c8a17209": {
  1056 + "sizeX": 11,
  1057 + "sizeY": 11,
  1058 + "row": 0,
  1059 + "col": 0
  1060 + },
  1061 + "7943196b-eedb-d422-f9c3-b32d379ad172": {
  1062 + "sizeX": 13,
  1063 + "sizeY": 5,
  1064 + "row": 0,
  1065 + "col": 11
  1066 + },
  1067 + "3da9a9a1-0b9a-2e1f-0dcb-0ff34a695abb": {
  1068 + "sizeX": 13,
  1069 + "sizeY": 6,
  1070 + "row": 5,
  1071 + "col": 11
  1072 + }
  1073 + },
  1074 + "gridSettings": {
  1075 + "backgroundColor": "#eeeeee",
  1076 + "color": "rgba(0,0,0,0.870588)",
  1077 + "columns": 24,
  1078 + "margins": [
  1079 + 10,
  1080 + 10
  1081 + ],
  1082 + "backgroundSizeMode": "100%",
  1083 + "autoFillHeight": true,
  1084 + "mobileAutoFillHeight": false,
  1085 + "mobileRowHeight": 70
  1086 + }
  1087 + }
  1088 + }
  1089 + },
  1090 + "map": {
  1091 + "name": "Edit location",
  1092 + "root": false,
  1093 + "layouts": {
  1094 + "main": {
  1095 + "widgets": {
  1096 + "00fb2742-ba1f-7e43-673f-d6c08b72ed06": {
  1097 + "sizeX": 24,
  1098 + "sizeY": 12,
  1099 + "row": 0,
  1100 + "col": 0
  1101 + }
  1102 + },
  1103 + "gridSettings": {
  1104 + "backgroundColor": "#eeeeee",
  1105 + "color": "rgba(0,0,0,0.870588)",
  1106 + "columns": 24,
  1107 + "margins": [
  1108 + 10,
  1109 + 10
  1110 + ],
  1111 + "backgroundSizeMode": "100%",
  1112 + "autoFillHeight": true,
  1113 + "mobileAutoFillHeight": false,
  1114 + "mobileRowHeight": 70
  1115 + }
  1116 + }
  1117 + }
  1118 + },
  1119 + "chart": {
  1120 + "name": "${entityName}",
  1121 + "root": false,
  1122 + "layouts": {
  1123 + "main": {
  1124 + "widgets": {
  1125 + "14a19183-f0b2-d6be-0f62-9863f0a51111": {
  1126 + "sizeX": 18,
  1127 + "sizeY": 6,
  1128 + "mobileHeight": null,
  1129 + "row": 0,
  1130 + "col": 6
  1131 + },
  1132 + "07f49fd5-a73b-d74c-c220-362c20af81f4": {
  1133 + "sizeX": 18,
  1134 + "sizeY": 6,
  1135 + "mobileHeight": null,
  1136 + "row": 6,
  1137 + "col": 6
  1138 + },
  1139 + "c4631f94-2db3-523b-4d09-2a1a0a75d93f": {
  1140 + "sizeX": 6,
  1141 + "sizeY": 6,
  1142 + "row": 0,
  1143 + "col": 0
  1144 + },
  1145 + "0a430429-9078-9ae6-2b67-e4a15a2bf8bf": {
  1146 + "sizeX": 6,
  1147 + "sizeY": 6,
  1148 + "row": 6,
  1149 + "col": 0
  1150 + }
  1151 + },
  1152 + "gridSettings": {
  1153 + "backgroundColor": "#eeeeee",
  1154 + "color": "rgba(0,0,0,0.870588)",
  1155 + "columns": 24,
  1156 + "margins": [
  1157 + 10,
  1158 + 10
  1159 + ],
  1160 + "backgroundSizeMode": "100%",
  1161 + "autoFillHeight": true,
  1162 + "mobileAutoFillHeight": false,
  1163 + "mobileRowHeight": 70
  1164 + }
  1165 + }
  1166 + }
  1167 + }
  1168 + },
  1169 + "entityAliases": {
  1170 + "68a058e1-fdda-8482-715b-3ae4a488568e": {
  1171 + "id": "68a058e1-fdda-8482-715b-3ae4a488568e",
  1172 + "alias": "Thermostats",
  1173 + "filter": {
  1174 + "type": "deviceType",
  1175 + "resolveMultiple": true,
  1176 + "deviceType": "thermostat",
  1177 + "deviceNameFilter": ""
  1178 + }
  1179 + },
  1180 + "12ae98c7-1ea2-52cf-64d5-763e9d993547": {
  1181 + "id": "12ae98c7-1ea2-52cf-64d5-763e9d993547",
  1182 + "alias": "Thermostat",
  1183 + "filter": {
  1184 + "type": "stateEntity",
  1185 + "resolveMultiple": false,
  1186 + "stateEntityParamName": null,
  1187 + "defaultStateEntity": null
  1188 + }
  1189 + },
  1190 + "ce27a9d0-93bf-b7a4-054d-d0369a8cf813": {
  1191 + "id": "ce27a9d0-93bf-b7a4-054d-d0369a8cf813",
  1192 + "alias": "Thermostat-alarm",
  1193 + "filter": {
  1194 + "type": "stateEntity",
  1195 + "resolveMultiple": false,
  1196 + "stateEntityParamName": "alarm",
  1197 + "defaultStateEntity": null
  1198 + }
  1199 + }
  1200 + },
  1201 + "timewindow": {
  1202 + "displayValue": "",
  1203 + "selectedTab": 0,
  1204 + "hideInterval": false,
  1205 + "hideAggregation": false,
  1206 + "hideAggInterval": false,
  1207 + "realtime": {
  1208 + "interval": 1000,
  1209 + "timewindowMs": 60000
  1210 + },
  1211 + "history": {
  1212 + "historyType": 0,
  1213 + "interval": 1000,
  1214 + "timewindowMs": 60000,
  1215 + "fixedTimewindow": {
  1216 + "startTimeMs": 1587473857304,
  1217 + "endTimeMs": 1587560257304
  1218 + }
  1219 + },
  1220 + "aggregation": {
  1221 + "type": "AVG",
  1222 + "limit": 25000
  1223 + }
  1224 + },
  1225 + "settings": {
  1226 + "stateControllerId": "entity",
  1227 + "showTitle": false,
  1228 + "showDashboardsSelect": true,
  1229 + "showEntitiesSelect": true,
  1230 + "showDashboardTimewindow": true,
  1231 + "showDashboardExport": true,
  1232 + "toolbarAlwaysOpen": true
  1233 + }
  1234 + },
  1235 + "name": "Thermostats"
  1236 +}
\ No newline at end of file
... ...
  1 +{
  2 + "ruleChain": {
  3 + "additionalInfo": null,
  4 + "name": "Root Rule Chain",
  5 + "firstRuleNodeId": null,
  6 + "root": false,
  7 + "debugMode": false,
  8 + "configuration": null
  9 + },
  10 + "metadata": {
  11 + "firstNodeIndex": 2,
  12 + "nodes": [
  13 + {
  14 + "additionalInfo": {
  15 + "layoutX": 824,
  16 + "layoutY": 156
  17 + },
  18 + "type": "org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode",
  19 + "name": "Save Timeseries",
  20 + "debugMode": false,
  21 + "configuration": {
  22 + "defaultTTL": 0
  23 + }
  24 + },
  25 + {
  26 + "additionalInfo": {
  27 + "layoutX": 825,
  28 + "layoutY": 52
  29 + },
  30 + "type": "org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode",
  31 + "name": "Save Client Attributes",
  32 + "debugMode": false,
  33 + "configuration": {
  34 + "scope": "CLIENT_SCOPE"
  35 + }
  36 + },
  37 + {
  38 + "additionalInfo": {
  39 + "layoutX": 347,
  40 + "layoutY": 149
  41 + },
  42 + "type": "org.thingsboard.rule.engine.filter.TbMsgTypeSwitchNode",
  43 + "name": "Message Type Switch",
  44 + "debugMode": false,
  45 + "configuration": {
  46 + "version": 0
  47 + }
  48 + },
  49 + {
  50 + "additionalInfo": {
  51 + "layoutX": 825,
  52 + "layoutY": 266
  53 + },
  54 + "type": "org.thingsboard.rule.engine.action.TbLogNode",
  55 + "name": "Log RPC from Device",
  56 + "debugMode": false,
  57 + "configuration": {
  58 + "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
  59 + }
  60 + },
  61 + {
  62 + "additionalInfo": {
  63 + "layoutX": 825,
  64 + "layoutY": 379
  65 + },
  66 + "type": "org.thingsboard.rule.engine.action.TbLogNode",
  67 + "name": "Log Other",
  68 + "debugMode": false,
  69 + "configuration": {
  70 + "jsScript": "return '\\nIncoming message:\\n' + JSON.stringify(msg) + '\\nIncoming metadata:\\n' + JSON.stringify(metadata);"
  71 + }
  72 + },
  73 + {
  74 + "additionalInfo": {
  75 + "layoutX": 825,
  76 + "layoutY": 468
  77 + },
  78 + "type": "org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode",
  79 + "name": "RPC Call Request",
  80 + "debugMode": false,
  81 + "configuration": {
  82 + "timeoutInSeconds": 60
  83 + }
  84 + },
  85 + {
  86 + "additionalInfo": {
  87 + "layoutX": 1069,
  88 + "layoutY": 90
  89 + },
  90 + "type": "org.thingsboard.rule.engine.filter.TbJsFilterNode",
  91 + "name": "Is Thermostat?",
  92 + "debugMode": false,
  93 + "configuration": {
  94 + "jsScript": "return metadata[\"deviceType\"] === \"thermostat\";"
  95 + }
  96 + }
  97 + ],
  98 + "connections": [
  99 + {
  100 + "fromIndex": 0,
  101 + "toIndex": 6,
  102 + "type": "Success"
  103 + },
  104 + {
  105 + "fromIndex": 2,
  106 + "toIndex": 4,
  107 + "type": "Other"
  108 + },
  109 + {
  110 + "fromIndex": 2,
  111 + "toIndex": 1,
  112 + "type": "Post attributes"
  113 + },
  114 + {
  115 + "fromIndex": 2,
  116 + "toIndex": 0,
  117 + "type": "Post telemetry"
  118 + },
  119 + {
  120 + "fromIndex": 2,
  121 + "toIndex": 3,
  122 + "type": "RPC Request from Device"
  123 + },
  124 + {
  125 + "fromIndex": 2,
  126 + "toIndex": 5,
  127 + "type": "RPC Request to Device"
  128 + }
  129 + ],
  130 + "ruleChainConnections": [
  131 + {
  132 + "fromIndex": 6,
  133 + "targetRuleChainId": {
  134 + "entityType": "RULE_CHAIN",
  135 + "id": "83d42540-85fd-11ea-aee2-794850541ced"
  136 + },
  137 + "additionalInfo": {
  138 + "layoutX": 1088,
  139 + "layoutY": 203,
  140 + "ruleChainNodeId": "rule-chain-node-9"
  141 + },
  142 + "type": "True"
  143 + }
  144 + ]
  145 + }
  146 +}
\ No newline at end of file
... ...
  1 +{
  2 + "ruleChain": {
  3 + "additionalInfo": null,
  4 + "name": "Thermostat Alarms",
  5 + "firstRuleNodeId": null,
  6 + "root": false,
  7 + "debugMode": false,
  8 + "configuration": null
  9 + },
  10 + "metadata": {
  11 + "firstNodeIndex": 5,
  12 + "nodes": [
  13 + {
  14 + "additionalInfo": {
  15 + "layoutX": 929,
  16 + "layoutY": 67
  17 + },
  18 + "type": "org.thingsboard.rule.engine.action.TbCreateAlarmNode",
  19 + "name": "Create Temp Alarm",
  20 + "debugMode": false,
  21 + "configuration": {
  22 + "alarmType": "High Temperature",
  23 + "alarmDetailsBuildJs": "var details = {};\nif (metadata.prevAlarmDetails) {\n details = JSON.parse(metadata.prevAlarmDetails);\n}\ndetails.triggerValue = msg.temperature;\nreturn details;",
  24 + "severity": "MAJOR",
  25 + "propagate": true,
  26 + "useMessageAlarmData": false,
  27 + "relationTypes": []
  28 + }
  29 + },
  30 + {
  31 + "additionalInfo": {
  32 + "layoutX": 930,
  33 + "layoutY": 201
  34 + },
  35 + "type": "org.thingsboard.rule.engine.action.TbClearAlarmNode",
  36 + "name": "Clear Temp Alarm",
  37 + "debugMode": false,
  38 + "configuration": {
  39 + "alarmType": "High Temperature",
  40 + "alarmDetailsBuildJs": "var details = {};\nif (metadata.prevAlarmDetails) {\n details = JSON.parse(metadata.prevAlarmDetails);\n}\nreturn details;"
  41 + }
  42 + },
  43 + {
  44 + "additionalInfo": {
  45 + "layoutX": 930,
  46 + "layoutY": 131
  47 + },
  48 + "type": "org.thingsboard.rule.engine.action.TbCreateAlarmNode",
  49 + "name": "Create Humidity Alarm",
  50 + "debugMode": false,
  51 + "configuration": {
  52 + "alarmType": "Low Humidity",
  53 + "alarmDetailsBuildJs": "var details = {};\nif (metadata.prevAlarmDetails) {\n details = JSON.parse(metadata.prevAlarmDetails);\n}\ndetails.triggerValue = msg.humidity;\nreturn details;",
  54 + "severity": "MINOR",
  55 + "propagate": true,
  56 + "useMessageAlarmData": false,
  57 + "relationTypes": []
  58 + }
  59 + },
  60 + {
  61 + "additionalInfo": {
  62 + "layoutX": 929,
  63 + "layoutY": 275
  64 + },
  65 + "type": "org.thingsboard.rule.engine.action.TbClearAlarmNode",
  66 + "name": "Clear Humidity Alarm",
  67 + "debugMode": false,
  68 + "configuration": {
  69 + "alarmType": "Low Humidity",
  70 + "alarmDetailsBuildJs": "var details = {};\nif (metadata.prevAlarmDetails) {\n details = JSON.parse(metadata.prevAlarmDetails);\n}\nreturn details;"
  71 + }
  72 + },
  73 + {
  74 + "additionalInfo": {
  75 + "layoutX": 586,
  76 + "layoutY": 148
  77 + },
  78 + "type": "org.thingsboard.rule.engine.filter.TbJsSwitchNode",
  79 + "name": "Check Alarms",
  80 + "debugMode": true,
  81 + "configuration": {
  82 + "jsScript": "var relations = [];\nif(metadata[\"ss_alarmTemperature\"] === \"true\"){\n if(msg.temperature > metadata[\"ss_thresholdTemperature\"]){\n relations.push(\"NewTempAlarm\");\n } else {\n relations.push(\"ClearTempAlarm\");\n }\n}\nif(metadata[\"ss_alarmHumidity\"] === \"true\"){\n if(msg.humidity < metadata[\"ss_thresholdHumidity\"]){\n relations.push(\"NewHumidityAlarm\");\n } else {\n relations.push(\"ClearHumidityAlarm\");\n }\n}\n\nreturn relations;"
  83 + }
  84 + },
  85 + {
  86 + "additionalInfo": {
  87 + "layoutX": 321,
  88 + "layoutY": 149
  89 + },
  90 + "type": "org.thingsboard.rule.engine.metadata.TbGetAttributesNode",
  91 + "name": "Fetch Configuration",
  92 + "debugMode": true,
  93 + "configuration": {
  94 + "clientAttributeNames": [],
  95 + "sharedAttributeNames": [],
  96 + "serverAttributeNames": [
  97 + "alarmTemperature",
  98 + "thresholdTemperature",
  99 + "alarmHumidity",
  100 + "thresholdHumidity"
  101 + ],
  102 + "latestTsKeyNames": [],
  103 + "tellFailureIfAbsent": false,
  104 + "getLatestValueWithTs": false
  105 + }
  106 + }
  107 + ],
  108 + "connections": [
  109 + {
  110 + "fromIndex": 4,
  111 + "toIndex": 0,
  112 + "type": "NewTempAlarm"
  113 + },
  114 + {
  115 + "fromIndex": 4,
  116 + "toIndex": 1,
  117 + "type": "ClearTempAlarm"
  118 + },
  119 + {
  120 + "fromIndex": 4,
  121 + "toIndex": 2,
  122 + "type": "NewHumidityAlarm"
  123 + },
  124 + {
  125 + "fromIndex": 4,
  126 + "toIndex": 3,
  127 + "type": "ClearHumidityAlarm"
  128 + },
  129 + {
  130 + "fromIndex": 5,
  131 + "toIndex": 4,
  132 + "type": "Success"
  133 + }
  134 + ],
  135 + "ruleChainConnections": null
  136 + }
  137 +}
\ No newline at end of file
... ...
... ... @@ -5,7 +5,7 @@
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7 7 *
8   - * http://www.apache.org/licenses/LICENSE-2.0
  8 + * http://www.apache.org/licenses/LICENSE-2.0
9 9 *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
... ... @@ -25,24 +25,32 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
25 25 import org.springframework.stereotype.Service;
26 26 import org.thingsboard.server.common.data.AdminSettings;
27 27 import org.thingsboard.server.common.data.Customer;
  28 +import org.thingsboard.server.common.data.DataConstants;
28 29 import org.thingsboard.server.common.data.Device;
29 30 import org.thingsboard.server.common.data.Tenant;
30 31 import org.thingsboard.server.common.data.User;
31 32 import org.thingsboard.server.common.data.id.CustomerId;
  33 +import org.thingsboard.server.common.data.id.DeviceId;
32 34 import org.thingsboard.server.common.data.id.TenantId;
  35 +import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry;
  36 +import org.thingsboard.server.common.data.kv.BooleanDataEntry;
  37 +import org.thingsboard.server.common.data.kv.DoubleDataEntry;
  38 +import org.thingsboard.server.common.data.kv.LongDataEntry;
33 39 import org.thingsboard.server.common.data.security.Authority;
34 40 import org.thingsboard.server.common.data.security.DeviceCredentials;
35 41 import org.thingsboard.server.common.data.security.UserCredentials;
36 42 import org.thingsboard.server.common.data.widget.WidgetsBundle;
  43 +import org.thingsboard.server.dao.attributes.AttributesService;
37 44 import org.thingsboard.server.dao.customer.CustomerService;
38 45 import org.thingsboard.server.dao.device.DeviceCredentialsService;
39 46 import org.thingsboard.server.dao.device.DeviceService;
40   -import org.thingsboard.server.dao.model.ModelConstants;
41 47 import org.thingsboard.server.dao.settings.AdminSettingsService;
42 48 import org.thingsboard.server.dao.tenant.TenantService;
43 49 import org.thingsboard.server.dao.user.UserService;
44 50 import org.thingsboard.server.dao.widget.WidgetsBundleService;
45 51
  52 +import java.util.Arrays;
  53 +
46 54 @Service
47 55 @Profile("install")
48 56 @Slf4j
... ... @@ -77,6 +85,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
77 85 private DeviceService deviceService;
78 86
79 87 @Autowired
  88 + private AttributesService attributesService;
  89 +
  90 + @Autowired
80 91 private DeviceCredentialsService deviceCredentialsService;
81 92
82 93 @Bean
... ... @@ -120,7 +131,7 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
120 131 demoTenant.setRegion("Global");
121 132 demoTenant.setTitle("Tenant");
122 133 demoTenant = tenantService.saveTenant(demoTenant);
123   - installScripts.createDefaultRuleChains(demoTenant.getId());
  134 + installScripts.loadDemoRuleChains(demoTenant.getId());
124 135 createUser(Authority.TENANT_ADMIN, demoTenant.getId(), null, "tenant@thingsboard.org", "tenant");
125 136
126 137 Customer customerA = new Customer();
... ... @@ -152,6 +163,25 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
152 163 createDevice(demoTenant.getId(), null, DEFAULT_DEVICE_TYPE, "Raspberry Pi Demo Device", "RASPBERRY_PI_DEMO_TOKEN", "Demo device that is used in " +
153 164 "Raspberry Pi GPIO control sample application");
154 165
  166 + DeviceId t1Id = createDevice(demoTenant.getId(), null, "thermostat", "Thermostat T1", "T1_TEST_TOKEN", "Demo device for Thermostats dashboard").getId();
  167 + DeviceId t2Id = createDevice(demoTenant.getId(), null, "thermostat", "Thermostat T2", "T2_TEST_TOKEN", "Demo device for Thermostats dashboard").getId();
  168 +
  169 + attributesService.save(demoTenant.getId(), t1Id, DataConstants.SERVER_SCOPE,
  170 + Arrays.asList(new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("latitude", 37.3948)),
  171 + new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("longitude", -122.1503)),
  172 + new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmTemperature", true)),
  173 + new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmHumidity", true)),
  174 + new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdTemperature", (long) 20)),
  175 + new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdHumidity", (long) 50))));
  176 +
  177 + attributesService.save(demoTenant.getId(), t2Id, DataConstants.SERVER_SCOPE,
  178 + Arrays.asList(new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("latitude", 37.493801)),
  179 + new BaseAttributeKvEntry(System.currentTimeMillis(), new DoubleDataEntry("longitude", -121.948769)),
  180 + new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmTemperature", true)),
  181 + new BaseAttributeKvEntry(System.currentTimeMillis(), new BooleanDataEntry("alarmHumidity", true)),
  182 + new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdTemperature", (long) 25)),
  183 + new BaseAttributeKvEntry(System.currentTimeMillis(), new LongDataEntry("thresholdHumidity", (long) 30))));
  184 +
155 185 installScripts.loadDashboards(demoTenant.getId(), null);
156 186 }
157 187
... ...
... ... @@ -5,7 +5,7 @@
5 5 * you may not use this file except in compliance with the License.
6 6 * You may obtain a copy of the License at
7 7 *
8   - * http://www.apache.org/licenses/LICENSE-2.0
  8 + * http://www.apache.org/licenses/LICENSE-2.0
9 9 *
10 10 * Unless required by applicable law or agreed to in writing, software
11 11 * distributed under the License is distributed on an "AS IS" BASIS,
... ... @@ -24,6 +24,7 @@ import org.springframework.util.StringUtils;
24 24 import org.thingsboard.server.common.data.Dashboard;
25 25 import org.thingsboard.server.common.data.id.CustomerId;
26 26 import org.thingsboard.server.common.data.id.EntityId;
  27 +import org.thingsboard.server.common.data.id.RuleChainId;
27 28 import org.thingsboard.server.common.data.id.TenantId;
28 29 import org.thingsboard.server.common.data.rule.RuleChain;
29 30 import org.thingsboard.server.common.data.rule.RuleChainMetaData;
... ... @@ -182,4 +183,54 @@ public class InstallScripts {
182 183 }
183 184
184 185
  186 + public void loadDemoRuleChains(TenantId tenantId) throws Exception {
  187 + Path ruleChainsDir = Paths.get(getDataDir(), JSON_DIR, DEMO_DIR, RULE_CHAINS_DIR);
  188 + try {
  189 + JsonNode ruleChainJson = objectMapper.readTree(ruleChainsDir.resolve("thermostat_alarms.json").toFile());
  190 + RuleChain ruleChain = objectMapper.treeToValue(ruleChainJson.get("ruleChain"), RuleChain.class);
  191 + RuleChainMetaData ruleChainMetaData = objectMapper.treeToValue(ruleChainJson.get("metadata"), RuleChainMetaData.class);
  192 + ruleChain.setTenantId(tenantId);
  193 + ruleChain = ruleChainService.saveRuleChain(ruleChain);
  194 + ruleChainMetaData.setRuleChainId(ruleChain.getId());
  195 + ruleChainService.saveRuleChainMetaData(new TenantId(EntityId.NULL_UUID), ruleChainMetaData);
  196 +
  197 + JsonNode rootChainJson = objectMapper.readTree(ruleChainsDir.resolve("root_rule_chain.json").toFile());
  198 + RuleChain rootChain = objectMapper.treeToValue(rootChainJson.get("ruleChain"), RuleChain.class);
  199 + RuleChainMetaData rootChainMetaData = objectMapper.treeToValue(rootChainJson.get("metadata"), RuleChainMetaData.class);
  200 +
  201 + RuleChainId thermostatsRuleChainId = ruleChain.getId();
  202 + rootChainMetaData.getRuleChainConnections().forEach(connection -> connection.setTargetRuleChainId(thermostatsRuleChainId));
  203 + rootChain.setTenantId(tenantId);
  204 + rootChain = ruleChainService.saveRuleChain(rootChain);
  205 + rootChainMetaData.setRuleChainId(rootChain.getId());
  206 + ruleChainService.saveRuleChainMetaData(new TenantId(EntityId.NULL_UUID), rootChainMetaData);
  207 + } catch (Exception e) {
  208 + log.error("Unable to load dashboard from json", e);
  209 + throw new RuntimeException("Unable to load dashboard from json", e);
  210 + }
  211 +
  212 + try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(ruleChainsDir, path -> path.toString().endsWith(JSON_EXT))) {
  213 + dirStream.forEach(
  214 + path -> {
  215 + try {
  216 + JsonNode ruleChainJson = objectMapper.readTree(path.toFile());
  217 + RuleChain ruleChain = objectMapper.treeToValue(ruleChainJson.get("ruleChain"), RuleChain.class);
  218 + RuleChainMetaData ruleChainMetaData = objectMapper.treeToValue(ruleChainJson.get("metadata"), RuleChainMetaData.class);
  219 +
  220 + ruleChain.setTenantId(tenantId);
  221 + if (ruleChain.getName().equals("Root Rule Chain")) {
  222 + ruleChain.setRoot(true);
  223 + }
  224 + ruleChain = ruleChainService.saveRuleChain(ruleChain);
  225 +
  226 + ruleChainMetaData.setRuleChainId(ruleChain.getId());
  227 + ruleChainService.saveRuleChainMetaData(new TenantId(EntityId.NULL_UUID), ruleChainMetaData);
  228 + } catch (Exception e) {
  229 + log.error("Unable to load dashboard from json: [{}]", path.toString());
  230 + throw new RuntimeException("Unable to load dashboard from json", e);
  231 + }
  232 + }
  233 + );
  234 + }
  235 + }
185 236 }
... ...