--
-- Copyright © 2016-2017 The Thingsboard Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

/** SYSTEM **/

/** System admin **/
INSERT INTO thingsboard.user ( id, tenant_id, customer_id, email, search_text, authority )
VALUES ( minTimeuuid ( '2016-11-01 01:01:01+0000' ), minTimeuuid ( 0 ), minTimeuuid ( 0 ), 'sysadmin@thingsboard.org',
'sysadmin@thingsboard.org', 'SYS_ADMIN' );

INSERT INTO thingsboard.user_credentials ( id, user_id, enabled, password )
VALUES ( now ( ), minTimeuuid ( '2016-11-01 01:01:01+0000' ), true,
'$2a$10$5JTB8/hxWc9WAy62nCGSxeefl3KWmipA9nFpVdDa0/xfIseeBB4Bu' );

/** System settings **/
INSERT INTO thingsboard.admin_settings ( id, key, json_value )
VALUES ( now ( ), 'general', '{
	"baseUrl": "http://localhost:8080"
}' );

INSERT INTO thingsboard.admin_settings ( id, key, json_value )
VALUES ( now ( ), 'mail', '{
	"mailFrom": "Thingsboard <sysadmin@localhost.localdomain>",
	"smtpProtocol": "smtp",
	"smtpHost": "localhost",
	"smtpPort": "25",
	"timeout": "10000",
	"enableTls": "false",
	"username": "",
	"password": ""
}' );

/** System widgets library **/
INSERT INTO "thingsboard"."widgets_bundle" ( "id", "tenant_id", "alias", "search_text", "title" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'gpio_widgets', 'gpio widgets', 'GPIO widgets' );

INSERT INTO "thingsboard"."widgets_bundle" ( "id", "tenant_id", "alias", "search_text", "title" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'maps', 'maps', 'Maps' );

INSERT INTO "thingsboard"."widgets_bundle" ( "id", "tenant_id", "alias", "search_text", "title" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges', 'digital gauges', 'Digital gauges' );

INSERT INTO "thingsboard"."widgets_bundle" ( "id", "tenant_id", "alias", "search_text", "title" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'charts', 'charts', 'Charts' );

INSERT INTO "thingsboard"."widgets_bundle" ( "id", "tenant_id", "alias", "search_text", "title" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'cards', 'cards', 'Cards' );

INSERT INTO "thingsboard"."widgets_bundle" ( "id", "tenant_id", "alias", "search_text", "title" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'analogue_gauges', 'analogue gauges', 'Analogue gauges' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'charts', 'timeseries',
'{"type":"timeseries","sizeX":8,"sizeY":5,"resources":[{"url":"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.4.0/Chart.min.js"}],"templateHtml":"<canvas id=\"lineChart\"></canvas>\n","templateCss":"","controllerScript":"self.onInit = function() {\n    \n    var lineData = {\n        labels: [],\n        datasets: []\n    };\n    \n    for (var i=0; i < self.ctx.data.length; i++) {\n        var dataKey = self.ctx.data[i].dataKey;\n        var keySettings = dataKey.settings;\n        var backgroundColor = tinycolor(dataKey.color);\n        backgroundColor.setAlpha(0.4);\n        var dataset = {\n            label: dataKey.label,\n            data: [],\n            borderColor: dataKey.color,\n            borderWidth: 2,\n            backgroundColor: backgroundColor.toRgbString(),\n            pointRadius: keySettings.showPoints ? 1 : 0,\n            fill: keySettings.fillLines || false,\n            showLine: keySettings.showLines || true,\n            spanGaps: false,\n            lineTension: angular.isDefined(keySettings.tension) ? keySettings.tension : 0.2\n        }\n        lineData.datasets.push(dataset);\n    }\n\n    var ctx = $(''#lineChart'', self.ctx.$container);\n    self.ctx.chart = new Chart(ctx, {\n        type: ''line'',\n        data: lineData,\n        options: {\n            responsive: false,\n            tooltips: {\n                mode: ''index'',\n                inersect: true\n            },\n            hover: {\n                mode: ''index'',\n                inersect: true\n            },\n            maintainAspectRatio: false,\n            /*animation: {\n              duration: 200,\n              easing: ''linear''\n            },*/\n            elements: {\n              line: {\n                  tension: 0.2\n              }  \n            },\n            scales: {\n                xAxes: [{\n                    type: ''time'',\n                    ticks: {\n                        maxRotation: 20,\n                        autoSkip: true\n                    },\n                    time: {\n                        displayFormats: {\n                            second: ''hh:mm:ss'',\n                            minute: ''hh:mm:ss''\n                        }\n                    }\n                }]\n            },\n            zoom: {\n                onSelect: function(startTimeMs, endTimeMs) {\n                    self.ctx.timewindowFunctions.onUpdateTimewindow(startTimeMs, endTimeMs);\n                },\n                onResetSelect: function() {\n                    self.ctx.timewindowFunctions.onResetTimewindow();\n                }\n            }\n        }\n    });\n    \n    self.onResize();\n    \n}\n\nself.onDataUpdated = function() {\n    \n    if (self.ctx.chart.zoom.isMouseInteraction) {\n        return;\n    }\n    if (!self.ctx.tickUpdate) {\n        for (var i = 0; i < self.ctx.data.length; i++) {\n            var dataSetData = [];\n            var dataKeyData = self.ctx.data[i].data;\n            for (var i2 = 0; i2 < dataKeyData.length; i2 ++) {\n                dataSetData.push({x: moment(dataKeyData[i2][0]), y: dataKeyData[i2][1]});\n                \n            }\n            self.ctx.chart.data.datasets[i].data = dataSetData; \n        }\n    }\n    \n    self.ctx.chart.options.scales.xAxes[0].time.min = moment(self.ctx.timeWindow.minTime);\n    self.ctx.chart.options.scales.xAxes[0].time.max = moment(self.ctx.timeWindow.maxTime);\n    \n    self.ctx.chart.update(0, true);\n\n}\n\nself.onResize = function() {\n    self.ctx.chart.resize();\n    self.ctx.chart.update(0, true);\n}\n\nself.onDestroy = function() {\n}\n\nfunction getYAxis(chartInstance) {\n    var scales = chartInstance.scales;\n    for (var scaleId in scales) {\n\t    var scale = scales[scaleId];\n\n\t    if (!scale.isHorizontal()) {\n\t\t    return scale;\n\t    }\n    }\n}\n\nfunction getXAxis(chartInstance) {\n    var scales = chartInstance.scales;\n    for (var scaleId in scales) {\n\t    var scale = scales[scaleId];\n\n\t    if (scale.isHorizontal()) {\n\t\t    return scale;\n\t    }\n    }\n}\n\nfunction eventPointer (e) {\n    if (angular.isDefined(e.touches) && e.touches.length > 0) {\n      return {\n        x : e.touches[0].pageX,\n        y : e.touches[0].pageY\n      };\n    } else if (angular.isDefined(e.changedTouches) && e.changedTouches.length > 0) {\n      return {\n        x : e.changedTouches[0].pageX,\n        y : e.changedTouches[0].pageY\n      };\n    } else if (e.pageX || e.pageY) {\n      return {\n        x : e.pageX,\n        y : e.pageY\n      };\n    } else if (e.clientX || e.clientY) {\n      var\n        d = document,\n        b = d.body,\n        de = d.documentElement;\n      return {\n        x: e.clientX + b.scrollLeft + de.scrollLeft,\n        y: e.clientY + b.scrollTop + de.scrollTop\n      };\n    }\n}\n\nvar zoomPlugin =     {\n        beforeInit: function(chartInstance) {\n            chartInstance.zoom = {};\n            var node = chartInstance.zoom.node = chartInstance.chart.ctx.canvas;\n            \n            chartInstance.zoom.mouseDownHandler = function(event) {\n                chartInstance.zoom.dragZoomStart = event;\n                chartInstance.zoom.dragZoomStartPointer = eventPointer(event);\n                chartInstance.zoom.isMouseInteraction = true;\n            };\n\n            node.addEventListener(''mousedown'', chartInstance.zoom.mouseDownHandler);\n            \n            chartInstance.zoom.mouseMoveHandler = function(event) {\n                if (chartInstance.zoom.dragZoomStart) {\n                    chartInstance.update(0);\n                    chartInstance.zoom.dragZoomEnd = event;\n                    chartInstance.zoom.dragZoomEndPointer = eventPointer(event);\n                }\n            };\n            \n            node.addEventListener(''mousemove'', chartInstance.zoom.mouseMoveHandler);\n            \n            chartInstance.zoom.mouseUpHandler = function(event) {\n                if (chartInstance.zoom.dragZoomStart) {\n                    \n                    var chartArea = chartInstance.chartArea;\n                    var yAxis = getYAxis(chartInstance);\n\t\t\t\t\tvar beginPoint = chartInstance.zoom.dragZoomStart;\n\t\t\t\t\tvar beginPointer = chartInstance.zoom.dragZoomStartPointer;\n\t\t\t\t\tvar upEventPointer = eventPointer(event);\n\t\t\t\t\tvar offsetX = beginPoint.target.getBoundingClientRect().left;\n\t\t\t\t\tvar startX = Math.min(beginPointer.x, upEventPointer.x) - offsetX;\n\t\t\t\t\tvar endX = Math.max(beginPointer.x, upEventPointer.x) - offsetX;\n\t\t\t\t\tvar dragDistance = endX - startX;\n\t\t\t\t\t\n\t\t\t\t\tif (dragDistance > 0) {\n    \t\t\t\t\tvar xAxis = getXAxis(chartInstance);\n    \t\t\t\t\tvar options = chartInstance.options;\n    \t\t\t\t\tif (options.scales.xAxes[0].time) {\n    \t\t\t\t\t    startX = Math.max(startX, xAxis.left);\n    \t\t\t\t\t    endX = Math.min(endX, xAxis.right);\n    \t\t\t\t\t    if (endX - startX > 0) {\n    \t\t\t\t\t        startX = startX - xAxis.left;\n    \t\t\t\t\t        endX = endX - xAxis.left;\n        \t\t\t\t\t    var time = options.scales.xAxes[0].time;\n        \t\t\t\t\t    var min = time.min.valueOf();\n        \t\t\t\t\t    var max = time.max.valueOf();\n    \t\t\t\t\t        var axisDistance = xAxis.right - xAxis.left;\n    \t\t\t\t\t        var timeDistance = max - min;\n    \t\t\t\t\t        \n    \t\t\t\t\t        var zoomStartTime = min + startX / axisDistance * timeDistance;\n    \t\t\t\t\t        var zoomEndTime = min + endX / axisDistance * timeDistance;\n\n    \t\t\t\t\t        if (options.zoom && options.zoom.onSelect) {\n    \t\t\t\t\t            options.zoom.onSelect(zoomStartTime, zoomEndTime);\n    \t\t\t\t\t        }\n    \t\t\t\t\t    }\n    \t\t\t\t\t}\n\t\t\t\t\t}\n        \t\t\tchartInstance.zoom.dragZoomStart = null;\n        \t\t\tchartInstance.zoom.dragZoomEnd = null;            \n                }\n                chartInstance.zoom.isMouseInteraction = false;\n            };\n            \n            node.addEventListener(''mouseup'', chartInstance.zoom.mouseUpHandler);\n            \n            chartInstance.zoom.mouseLeaveHandler = function(event) {\n                if (chartInstance.zoom.dragZoomStart) {\n        \t\t\tchartInstance.zoom.dragZoomStart = null;\n        \t\t\tchartInstance.zoom.dragZoomEnd = null;            \n                }\n                chartInstance.zoom.isMouseInteraction = false;\n            };\n            \n            node.addEventListener(''mouseleave'', chartInstance.zoom.mouseLeaveHandler);\n            \n            chartInstance.zoom.dblClickHandler = function(event) {\n                if (chartInstance.zoom.dragZoomStart) {\n        \t\t\tchartInstance.zoom.dragZoomStart = null;\n        \t\t\tchartInstance.zoom.dragZoomEnd = null;            \n                }\n                var options = chartInstance.options;\n                if (options.zoom && options.zoom.onResetSelect) {\n                    options.zoom.onResetSelect();\n                }\n            };\n            \n            node.addEventListener(''dblclick'', chartInstance.zoom.dblClickHandler);\n        },\n        beforeDatasetsDraw: function(chartInstance, easing) {\n    \t\tvar ctx = chartInstance.chart.ctx;\n    \t\tvar chartArea = chartInstance.chartArea;\n    \t\tctx.save();\n    \t\tctx.beginPath();\n    \t\tif (chartInstance.zoom && chartInstance.zoom.dragZoomEnd) {\n    \t\t\tvar yAxis = getYAxis(chartInstance);\n    \t\t\tvar beginPoint = chartInstance.zoom.dragZoomStart;\n    \t\t\tvar beginPointer = chartInstance.zoom.dragZoomStartPointer;\n    \t\t\tvar endPoint = chartInstance.zoom.dragZoomEnd;\n    \t\t\tvar endPointer = chartInstance.zoom.dragZoomEndPointer;\n    \t\t\t\n    \t\t\tvar offsetX = beginPoint.target.getBoundingClientRect().left;\n    \t\t\tvar startX = Math.min(beginPointer.x, endPointer.x) - offsetX;\n    \t\t\tvar endX = Math.max(beginPointer.x, endPointer.x) - offsetX;\n    \t\t\tvar rectWidth = endX - startX;\n    \t\t\tctx.fillStyle = ''rgba(157,203,255,0.1)'';\n    \t\t\tctx.lineWidth = 1;\n    \t\t\tctx.strokeRect(startX, yAxis.top, rectWidth, yAxis.bottom - yAxis.top);\n    \t\t\tctx.fillRect(startX, yAxis.top, rectWidth, yAxis.bottom - yAxis.top);\n    \t\t}\n    \t\tif (chartArea) {\n    \t\t    ctx.rect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);\n    \t\t}\n\t\t    ctx.clip();            \n        },\n        \n        afterDatasetsDraw: function(chartInstance) {\n\t        chartInstance.chart.ctx.restore();\n        },\n        \n        destroy: function(chartInstance) {\n            if (chartInstance.zoom) {\n                var node = chartInstance.zoom.node;\n\t\t\t\tnode.removeEventListener(''mousedown'', chartInstance.zoom.mouseDownHandler);\n\t\t\t\tnode.removeEventListener(''mousemove'', chartInstance.zoom.mouseMoveHandler);\n\t\t\t\tnode.removeEventListener(''mouseup'', chartInstance.zoom.mouseUpHandler);\n\t\t\t\tnode.removeEventListener(''mouseleave'', chartInstance.zoom.mouseLeaveHandler);\t \n\t\t\t\tnode.removeEventListener(''dblclick'', chartInstance.zoom.dblClickHandler);\n\t\t\t\tdelete chartInstance.zoom;\n            }\n        }\n    };\n\nChart.pluginService.register(zoomPlugin);\n","settingsSchema":"{}","dataKeySettingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"DataKeySettings\",\n        \"properties\": {\n            \"showLines\": {\n                \"title\": \"Show lines\",\n                \"type\": \"boolean\",\n                \"default\": true\n            },\n            \"fillLines\": {\n                \"title\": \"Fill lines\",\n                \"type\": \"boolean\",\n                \"default\": false\n            },\n            \"showPoints\": {\n                \"title\": \"Show points\",\n                \"type\": \"boolean\",\n                \"default\": false\n            },\n            \"tension\": {\n                \"title\": \"Line tension\",\n                \"type\": \"number\",\n                \"default\": 0.2\n            }\n        },\n        \"required\": [\"showLines\", \"fillLines\", \"showPoints\"]\n    },\n    \"form\": [\n        \"showLines\",\n        \"fillLines\",\n        \"showPoints\",\n        \"tension\"\n    ]\n}","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.5644745944820795,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.18379294198604845,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Timeseries - Chart.js (Deprecated)\"}"}',
'Timeseries - Chart.js (Deprecated)' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges',
'digital_vertical_bar',
'{"type":"latest","sizeX":2.5,"sizeY":4.5,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":60,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[\"#3d5afe\",\"#f44336\"],\"refreshAnimationType\":\"<>\",\"refreshAnimationTime\":700,\"startAnimationType\":\"<>\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"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,\"units\":\"°C\",\"minValue\":-60,\"dashThickness\":1.2},\"title\":\"Digital vertical bar\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Digital vertical bar' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'gpio_widgets', 'gpio_panel',
'{"type":"latest","sizeX":5,"sizeY":2,"resources":[],"templateHtml":"<div class=\"gpio-panel\" style=\"height: 100%;\">\n    <section layout=\"row\" ng-repeat=\"row in rows\">\n        <section flex layout=\"row\" ng-repeat=\"cell in row\">\n            <section layout=\"row\" flex ng-if=\"cell\" layout-align=\"{{$index===0 ? ''end center'' : ''start center''}}\">\n                <span class=\"gpio-left-label\" ng-show=\"$index===0\">{{ cell.label }}</span>\n                <section layout=\"row\" class=\"led-panel\" ng-class=\"$index===0 ? ''col-0'' : ''col-1''\"\n                      ng-style=\"{backgroundColor: ledPanelBackgroundColor }\">\n                    <span class=\"pin\" ng-show=\"$index===0\">{{cell.pin}}</span>\n                    <span class=\"led-container\">\n                        <tb-led-light size=\"prefferedRowHeight\"\n                                      color-on=\"cell.colorOn\"\n                                      color-off=\"cell.colorOff\"\n                                      off-opacity=\"''0.9''\"\n                                      tb-enabled=\"cell.enabled\">\n                        </tb-led-light>\n                    </span>\n                    <span class=\"pin\" ng-show=\"$index===1\">{{cell.pin}}</span>\n                </section>\n                <span class=\"gpio-right-label\" ng-show=\"$index===1\">{{ cell.label }}</span>\n            </section>\n            <section layout=\"row\" flex ng-if=\"!cell\">\n                <span flex ng-show=\"$index===0\"></span>\n                <span class=\"led-panel\"\n                      ng-style=\"{backgroundColor: ledPanelBackgroundColor }\"></span>\n                <span flex ng-show=\"$index===1\"></span>\n            </section>\n        </section>\n    </section>                            \n</div>","templateCss":".error {\n    font-size: 14px !important;\n    color: maroon;/*rgb(250,250,250);*/\n    background-color: transparent;\n    padding: 6px;\n}\n\n.error span {\n    margin: auto;\n}\n\n.gpio-panel {\n    padding-top: 10px;\n    white-space: nowrap;\n}\n\n.gpio-panel tb-led-light > div {\n    margin: auto;\n}\n\n.led-panel {\n    margin: 0;\n    width: 66px;\n    min-width: 66px;\n}\n\n.led-container {\n    width: 48px;\n    min-width: 48px;\n}\n\n.pin {\n    margin-top: auto;\n    margin-bottom: auto;\n    color: white;\n    font-size: 12px;\n    width: 16px;\n    min-width: 16px;\n}\n\n.led-panel.col-0 .pin {\n    margin-left: auto;\n    padding-left: 2px;\n    text-align: right;\n}\n\n.led-panel.col-1 .pin {\n    margin-right: auto;\n    \n    text-align: left;\n}\n\n.gpio-left-label {\n    margin-right: 8px;\n}\n\n.gpio-right-label {\n    margin-left: 8px;\n}","controllerScript":"self.onInit = function() {\n    var i, gpio;\n    \n    var scope = self.ctx.$scope;\n    var settings = self.ctx.settings;\n    \n    scope.gpioList = [];\n    scope.gpioByPin = {};\n    for (var g = 0; g < settings.gpioList.length; g++) {\n        gpio = settings.gpioList[g];\n        scope.gpioList.push(\n            {\n                row: gpio.row,\n                col: gpio.col,\n                pin: gpio.pin,\n                label: gpio.label,\n                enabled: false,\n                colorOn: tinycolor(gpio.color).lighten(20).toHexString(),\n                colorOff: tinycolor(gpio.color).darken().toHexString()\n            }\n        );\n        scope.gpioByPin[gpio.pin] = scope.gpioList[scope.gpioList.length-1];\n    }\n\n    scope.ledPanelBackgroundColor = settings.ledPanelBackgroundColor || tinycolor(''green'').lighten(2).toRgbString();\n\n    scope.gpioCells = {};\n    var rowCount = 0;\n    for (i = 0; i < scope.gpioList.length; i++) {\n        gpio = scope.gpioList[i];\n        scope.gpioCells[gpio.row+''_''+gpio.col] = gpio;\n        rowCount = Math.max(rowCount, gpio.row+1);\n    }\n    \n    scope.prefferedRowHeight = 32;\n    scope.rows = [];\n    for (i = 0; i < rowCount; i++) {\n        var row = [];\n        for (var c =0; c<2;c++) {\n            if (scope.gpioCells[i+''_''+c]) {\n                row[c] = scope.gpioCells[i+''_''+c];\n            } else {\n                row[c] = null;\n            }\n        }\n        scope.rows.push(row);\n    }    \n    \n    self.onResize();\n}\n\nself.onDataUpdated = function() {\n    var changed = false;\n    for (var d = 0; d < self.ctx.data.length; d++) {\n        var cellData = self.ctx.data[d];\n        var dataKey = cellData.dataKey;\n        var gpio = self.ctx.$scope.gpioByPin[dataKey.label];\n        if (gpio) {\n            var enabled = false;\n            if (cellData.data.length > 0) {\n                var tvPair = cellData.data[cellData.data.length - 1];\n                enabled = (tvPair[1] === true || tvPair[1] === ''true'');\n            }\n            if (gpio.enabled != enabled) {\n                changed = true;\n                gpio.enabled = enabled;\n            }\n        }\n    }\n    if (changed) {\n        self.ctx.$scope.$digest();\n    }    \n}\n\nself.onResize = function() {\n    var rowCount = self.ctx.$scope.rows.length;\n    var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n    prefferedRowHeight = Math.min(32, prefferedRowHeight);\n    prefferedRowHeight = Math.max(12, prefferedRowHeight);\n    self.ctx.$scope.prefferedRowHeight = prefferedRowHeight;\n    \n    var ratio = prefferedRowHeight/32;\n    \n    var leftLabels = $(''.gpio-left-label'', self.ctx.$container);\n    leftLabels.css(''font-size'', 16*ratio+''px'');\n    var rightLabels = $(''.gpio-right-label'', self.ctx.$container);\n    rightLabels.css(''font-size'', 16*ratio+''px'');\n    var pins = $(''.pin'', self.ctx.$container);\n    var pinsFontSize = Math.max(9, 12*ratio);\n    pins.css(''font-size'', pinsFontSize+''px'');    \n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"properties\": {\n            \"gpioList\": {\n                \"title\": \"Gpio leds\",\n                \"type\": \"array\",\n                \"minItems\" : 1,\n                \"items\": {\n                    \"title\": \"Gpio led\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"pin\": {\n                            \"title\": \"Pin\",\n                            \"type\": \"number\"\n                        },\n                        \"label\": {\n                            \"title\": \"Label\",\n                            \"type\": \"string\"\n                        },\n                        \"row\": {\n                            \"title\": \"Row\",\n                            \"type\": \"number\"\n                        },\n                        \"col\": {\n                            \"title\": \"Column\",\n                            \"type\": \"number\"\n                        },\n                        \"color\": {\n                            \"title\": \"Color\",\n                            \"type\": \"string\",\n                            \"default\": \"red\"\n                        }\n                    },\n                    \"required\": [\"pin\", \"label\", \"row\", \"col\", \"color\"]\n                }\n            },\n            \"ledPanelBackgroundColor\": {\n                \"title\": \"LED panel background color\",\n                \"type\": \"string\",\n                \"default\": \"#008a00\"\n            } \n        },\n        \"required\": [\"gpioList\", \n                     \"ledPanelBackgroundColor\"]\n    },\n    \"form\": [\n        {\n            \"key\": \"gpioList\",\n            \"items\": [\n                \"gpioList[].pin\",\n                \"gpioList[].label\",\n                \"gpioList[].row\",\n                \"gpioList[].col\",\n                {\n                    \"key\": \"gpioList[].color\",\n                    \"type\": \"color\"\n                }\n            ]\n        },\n        {\n            \"key\": \"ledPanelBackgroundColor\",\n            \"type\": \"color\"\n        }\n    ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"color\":\"#008000\",\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"color\":\"#ffff00\",\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"color\":\"#cf006f\",\"_uniqueKey\":2}],\"ledPanelBackgroundColor\":\"#b71c1c\"},\"title\":\"Basic GPIO Panel\",\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"1\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.22518255793320163,\"funcBody\":\"var period = time % 1500;\\nreturn period < 500;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"2\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.7008206860666621,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 500 && period < 1000;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"3\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.42600325102193426,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 1000;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}}}"}',
'Basic GPIO Panel' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'cards', 'timeseries_table',
'{"type":"timeseries","sizeX":8,"sizeY":6.5,"resources":[],"templateHtml":"<md-tabs md-selected=\"sourceIndex\" ng-class=\"{''tb-headless'': sources.length === 1}\"\n    id=\"tabs\" md-border-bottom flex class=\"tb-absolute-fill\">\n    <md-tab ng-repeat=\"source in sources\" label=\"{{ source.datasource.name }}\">\n        <md-table-container>\n            <table md-table>\n                <thead md-head md-order=\"source.query.order\" md-on-reorder=\"onReorder(source)\">\n                    <tr md-row>\n                        <th ng-show=\"showTimestamp\" md-column md-order-by=\"0\"><span>Timestamp</span></th>\n                        <th md-column md-order-by=\"{{ h.index }}\" ng-repeat=\"h in source.ts.header\"><span>{{ h.dataKey.label }}</span></th>\n                    </tr>\n                </thead>\n                <tbody md-body>\n                    <tr md-row ng-repeat=\"row in source.ts.data\">\n                        <td ng-show=\"$index > 0 || ($index === 0 && showTimestamp)\" md-cell ng-repeat=\"d in row track by $index\" ng-style=\"cellStyle(source, $index, d)\" ng-bind-html=\"cellContent(source, $index, row, d)\">\n                        </td>\n                    </tr>    \n                </tbody>    \n            </table>\n        </md-table-container>\n        <md-table-pagination md-limit=\"source.query.limit\" md-limit-options=\"[5, 10, 15]\"\n                             md-page=\"source.query.page\" md-total=\"{{source.ts.count}}\"\n                             md-on-paginate=\"onPaginate(source)\" md-page-select>\n        </md-table-pagination>\n    </md-tab>\n</md-tabs>","templateCss":"table.md-table thead.md-head>tr.md-row {\n    height: 40px;\n}\n\ntable.md-table tbody.md-body>tr.md-row, table.md-table tfoot.md-foot>tr.md-row {\n    height: 38px;\n}\n\n.md-table-pagination>* {\n    height: 46px;\n}\n","controllerScript":"self.onInit = function() {\n    \n    var scope = self.ctx.$scope;\n    \n    self.ctx.filter = scope.$injector.get(\"$filter\");\n\n    scope.sources = [];\n    scope.sourceIndex = 0;\n    scope.showTimestamp = self.ctx.settings.showTimestamp !== false;\n    var origColor = self.ctx.widgetConfig.color || ''rgba(0, 0, 0, 0.87)'';\n    var defaultColor = tinycolor(origColor);\n    var mdDark = defaultColor.setAlpha(0.87).toRgbString();\n    var mdDarkSecondary = defaultColor.setAlpha(0.54).toRgbString();\n    var mdDarkDisabled = defaultColor.setAlpha(0.26).toRgbString();\n    var mdDarkIcon = mdDarkSecondary;\n    var mdDarkDivider = defaultColor.setAlpha(0.12).toRgbString();\n    \n    var cssString = ''table.md-table th.md-column {\\n''+\n    ''color: '' + mdDarkSecondary + '';\\n''+\n    ''}\\n''+\n    ''table.md-table th.md-column md-icon.md-sort-icon {\\n''+\n    ''color: '' + mdDarkDisabled + '';\\n''+\n    ''}\\n''+\n    ''table.md-table th.md-column.md-active, table.md-table th.md-column.md-active md-icon {\\n''+\n    ''color: '' + mdDark + '';\\n''+\n    ''}\\n''+\n    ''table.md-table td.md-cell {\\n''+\n    ''color: '' + mdDark + '';\\n''+\n    ''border-top: 1px ''+mdDarkDivider+'' solid;\\n''+\n    ''}\\n''+\n    ''table.md-table td.md-cell.md-placeholder {\\n''+\n    ''color: '' + mdDarkDisabled + '';\\n''+\n    ''}\\n''+\n    ''table.md-table td.md-cell md-select > .md-select-value > span.md-select-icon {\\n''+\n    ''color: '' + mdDarkSecondary + '';\\n''+\n    ''}\\n''+\n    ''.md-table-pagination {\\n''+\n    ''color: '' + mdDarkSecondary + '';\\n''+\n    ''border-top: 1px ''+mdDarkDivider+'' solid;\\n''+\n    ''}\\n''+\n    ''.md-table-pagination .buttons md-icon {\\n''+\n    ''color: '' + mdDarkSecondary + '';\\n''+\n    ''}\\n''+\n    ''.md-table-pagination md-select:not([disabled]):focus .md-select-value {\\n''+\n    ''color: '' + mdDarkSecondary + '';\\n''+\n    ''}'';\n    \n    var cssParser = new cssjs();\n    cssParser.testMode = false;\n    var namespace = ''ts-table-'' + hashCode(cssString);\n    cssParser.cssPreviewNamespace = namespace;\n    cssParser.createStyleElement(namespace, cssString);\n    self.ctx.$container.addClass(namespace);\n    \n    function hashCode(str) {\n        var hash = 0;\n        var i, char;\n        if (str.length === 0) return hash;\n        for (i = 0; i < str.length; i++) {\n            char = str.charCodeAt(i);\n            hash = ((hash << 5) - hash) + char;\n            hash = hash & hash;\n        }\n        return hash;\n    }\n    \n    var keyOffset = 0;\n    for (var ds = 0; ds < self.ctx.datasources.length; ds++) {\n        var source = {};\n        var datasource = self.ctx.datasources[ds];\n        source.keyStartIndex = keyOffset;\n        keyOffset += datasource.dataKeys.length;\n        source.keyEndIndex = keyOffset;\n        source.datasource = datasource;\n        source.data = [];\n        source.rawData = [];\n        source.query = {\n            limit: 5,\n            page: 1,\n            order: ''-0''\n        }\n        source.ts = {\n            header: [],\n            count: 0,\n            data: [],\n            stylesInfo: [],\n            contentsInfo: [],\n            rowDataTemplate: {}\n        }\n        source.ts.rowDataTemplate[''Timestamp''] = null;\n        for (var a = 0; a < datasource.dataKeys.length; a++ ) {\n            var dataKey = datasource.dataKeys[a];\n            var keySettings = dataKey.settings;\n            source.ts.header.push({\n                index: a+1,\n                dataKey: dataKey\n            });\n            source.ts.rowDataTemplate[dataKey.label] = null;\n\n            var cellStyleFunction = null;\n            var useCellStyleFunction = false;\n            \n            if (keySettings.useCellStyleFunction === true) {\n                if (angular.isDefined(keySettings.cellStyleFunction) && keySettings.cellStyleFunction.length > 0) {\n                    try {\n                       cellStyleFunction = new Function(''value'', keySettings.cellStyleFunction);\n                       useCellStyleFunction = true;\n                    } catch (e) {\n                       cellStyleFunction = null;\n                       useCellStyleFunction = false;\n                    }\n                }\n            }\n\n            source.ts.stylesInfo.push({\n                useCellStyleFunction: useCellStyleFunction,\n                cellStyleFunction: cellStyleFunction\n            });\n            \n            var cellContentFunction = null;\n            var useCellContentFunction = false;\n            \n            if (keySettings.useCellContentFunction === true) {\n                if (angular.isDefined(keySettings.cellContentFunction) && keySettings.cellContentFunction.length > 0) {\n                    try {\n                       cellContentFunction = new Function(''value, rowData, filter'', keySettings.cellContentFunction);\n                       useCellContentFunction = true;\n                    } catch (e) {\n                       cellContentFunction = null;\n                       useCellContentFunction = false;\n                    }\n                }\n            }\n            \n            source.ts.contentsInfo.push({\n                useCellContentFunction: useCellContentFunction,\n                cellContentFunction: cellContentFunction\n            });\n            \n        }\n        scope.sources.push(source);\n    }\n\n    scope.onPaginate = function(source) {\n        updatePage(source);\n    }\n    \n    scope.onReorder = function(source) {\n        reorder(source);\n        updatePage(source);\n    }\n    \n    scope.cellStyle = function(source, index, value) {\n        var style = {};\n        if (index > 0) {\n            var styleInfo = source.ts.stylesInfo[index-1];\n            if (styleInfo.useCellStyleFunction && styleInfo.cellStyleFunction) {\n                try {\n                    style = styleInfo.cellStyleFunction(value);\n                } catch (e) {\n                    style = {};\n                }\n            }\n        }\n        return style;\n    }\n\n    scope.cellContent = function(source, index, row, value) {\n        if (index === 0) {\n            return self.ctx.filter(''date'')(value, ''yyyy-MM-dd HH:mm:ss'');\n        } else {\n            var strContent = '''';\n            if (angular.isDefined(value)) {\n                strContent = ''''+value;\n            }\n            var content = strContent;\n            var contentInfo = source.ts.contentsInfo[index-1];\n            if (contentInfo.useCellContentFunction && contentInfo.cellContentFunction) {\n                try {\n                    var rowData = source.ts.rowDataTemplate;\n                    rowData[''Timestamp''] = row[0];\n                    for (var h=0; h < source.ts.header.length; h++) {\n                        var headerInfo = source.ts.header[h];\n                        rowData[headerInfo.dataKey.name] = row[headerInfo.index];\n                    }\n                    content = contentInfo.cellContentFunction(value, rowData, self.ctx.filter);\n                } catch (e) {\n                    content = strContent;\n                }\n            }            \n            return content;\n        }\n    }\n    \n    scope.$watch(''sourceIndex'', function(newIndex, oldIndex) {\n       if (newIndex != oldIndex) {\n           updateSourceData(scope.sources[scope.sourceIndex]);\n       } \n    });\n}\n\nself.onDataUpdated = function() {\n    var scope = self.ctx.$scope;\n    for (var s=0; s < scope.sources.length; s++) {\n        var source = scope.sources[s];\n        source.rawData = self.ctx.data.slice(source.keyStartIndex, source.keyEndIndex);\n    }\n    updateSourceData(scope.sources[scope.sourceIndex]);\n    scope.$digest();\n}\n\nself.onDestroy = function() {\n}\n\nfunction updatePage(source) {\n    var startIndex = source.query.limit * (source.query.page - 1);\n    source.ts.data = source.data.slice(startIndex, startIndex + source.query.limit);\n}\n\nfunction reorder(source) {\n    source.data = self.ctx.filter(''orderBy'')(source.data, source.query.order);\n}\n\nfunction convertData(data) {\n    var rowsMap = {};\n    for (var d = 0; d < data.length; d++) {\n        var columnData = data[d].data;\n        for (var i = 0; i < columnData.length; i++) {\n            var cellData = columnData[i];\n            var timestamp = cellData[0];\n            var row = rowsMap[timestamp];\n            if (!row) {\n                row = [];\n                row[0] = timestamp;\n                for (var c = 0; c < data.length; c++) {\n                    row[c+1] = undefined;\n                }\n                rowsMap[timestamp] = row;\n            }\n            row[d+1] = cellData[1];\n        }\n    }\n    var rows = [];\n    for (var t in rowsMap) {\n        rows.push(rowsMap[t]);\n    }\n    return rows;\n}\n\nfunction updateSourceData(source) {\n    source.data = convertData(source.rawData);\n    source.ts.count = source.data.length;\n    reorder(source);\n    updatePage(source);\n}\n","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"TimeseriesTableSettings\",\n        \"properties\": {\n            \"showTimestamp\": {\n                \"title\": \"Display timestamp column\",\n                \"type\": \"boolean\",\n                \"default\": true\n            }\n        },\n        \"required\": []\n    },\n    \"form\": [\n        \"showTimestamp\"\n    ]\n}","dataKeySettingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"DataKeySettings\",\n        \"properties\": {\n            \"useCellStyleFunction\": {\n                \"title\": \"Use cell style function\",\n                \"type\": \"boolean\",\n                \"default\": false\n            },\n            \"cellStyleFunction\": {\n                \"title\": \"Cell style function: f(value)\",\n                \"type\": \"string\",\n                \"default\": \"\"\n            },\n            \"useCellContentFunction\": {\n                \"title\": \"Use cell content function\",\n                \"type\": \"boolean\",\n                \"default\": false\n            },\n            \"cellContentFunction\": {\n                \"title\": \"Cell content function: f(value, rowData, filter)\",\n                \"type\": \"string\",\n                \"default\": \"\"\n            }\n        },\n        \"required\": []\n    },\n    \"form\": [\n        \"useCellStyleFunction\",\n        {\n            \"key\": \"cellStyleFunction\",\n            \"type\": \"javascript\"\n        },\n        \"useCellContentFunction\",\n        {\n            \"key\": \"cellContentFunction\",\n            \"type\": \"javascript\"\n        }\n    ]\n}","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature  °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n    var percent = (value + 60)/120 * 100;\\n    var color = tinycolor.mix(''blue'', ''red'', amount = percent);\\n    color.setAlpha(.5);\\n    return {\\n      paddingLeft: ''20px'',\\n      color: ''#ffffff'',\\n      background: color.toRgbString(),\\n      fontSize: ''18px''\\n    };\\n} else {\\n    return {};\\n}\"},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n    var percent = value;\\n    var backgroundColor = tinycolor(''blue'');\\n    backgroundColor.setAlpha(value/100);\\n    var color = ''blue'';\\n    if (value > 50) {\\n        color = ''white'';\\n    }\\n    \\n    return {\\n      paddingLeft: ''20px'',\\n      color: color,\\n      background: backgroundColor.toRgbString(),\\n      fontSize: ''18px''\\n    };\\n} else {\\n    return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"interval\":1000,\"timewindowMs\":60000},\"aggregation\":{\"type\":\"NONE\",\"limit\":200}},\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"showTimestamp\":true},\"title\":\"Timeseries table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":false,\"showLegend\":false}"}',
'Timeseries table' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'charts', 'polar_area_chart_js',
'{"type":"latest","sizeX":7,"sizeY":5,"resources":[{"url":"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"}],"templateHtml":"<canvas id=\"pieChart\"></canvas>\n","templateCss":"","controllerScript":"self.onInit = function() {\n    var pieData = {\n        labels: [],\n        datasets: []\n    };\n\n    var dataset = {\n        data: [],\n        backgroundColor: [],\n        borderColor: [],\n        borderWidth: [],\n        hoverBackgroundColor: []\n    }\n    \n    pieData.datasets.push(dataset);\n    \n    for (var i = 0; i < self.ctx.data.length; i++) {\n        var dataKey = self.ctx.data[i].dataKey;\n        pieData.labels.push(dataKey.label);\n        dataset.data.push(0);\n        var hoverBackgroundColor = tinycolor(dataKey.color).lighten(15);\n        var borderColor = tinycolor(dataKey.color).darken();\n        dataset.backgroundColor.push(dataKey.color);\n        dataset.borderColor.push(''#fff'');\n        dataset.borderWidth.push(5);\n        dataset.hoverBackgroundColor.push(hoverBackgroundColor.toRgbString());\n    }\n\n    var ctx = $(''#pieChart'', self.ctx.$container);\n    self.ctx.chart = new Chart(ctx, {\n        type: ''polarArea'',\n        data: pieData,\n        options: {\n            responsive: false,\n            maintainAspectRatio: false\n        }\n    });\n    \n    self.onResize();\n}\n\nself.onDataUpdated = function() {\n    for (var i = 0; i < self.ctx.data.length; i++) {\n        var cellData = self.ctx.data[i];\n        if (cellData.data.length > 0) {\n             var tvPair = cellData.data[cellData.data.length - 1];\n             var value = tvPair[1];\n             self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n        }\n    }\n  \n    self.ctx.chart.update();\n}\n\nself.onResize = function() {\n    if (self.ctx.height >= 70) {\n        try {\n            self.ctx.chart.resize();\n        } catch (e) {}\n    }\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fifth\",\"color\":\"#607d8b\",\"settings\":{},\"_hash\":0.2074391823443591,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Polar Area - Chart.js\"}"}',
'Polar Area - Chart.js' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'cards', 'html_card',
'{"type":"static","sizeX":7.5,"sizeY":3,"resources":[],"templateHtml":"","templateCss":"","controllerScript":"self.onInit = function() {\n\n    var cssParser = new cssjs();\n    cssParser.testMode = false;\n    var namespace = ''html-card-'' + hashCode(self.ctx.settings.cardCss);\n    cssParser.cssPreviewNamespace = namespace;\n    cssParser.createStyleElement(namespace, self.ctx.settings.cardCss);\n    self.ctx.$container.addClass(namespace);\n    cardHtml = self.ctx.settings.cardHtml;\n    self.ctx.$container.html(cardHtml);\n    \n    function hashCode(str) {\n        var hash = 0;\n        var i, char;\n        if (str.length === 0) return hash;\n        for (i = 0; i < str.length; i++) {\n            char = str.charCodeAt(i);\n            hash = ((hash << 5) - hash) + char;\n            hash = hash & hash;\n        }\n        return hash;\n    }\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"required\": [\"cardHtml\"],\n        \"properties\": {\n            \"cardCss\": {\n                \"title\": \"CSS\",\n                \"type\": \"string\",\n                \"default\": \".card {\\n font-weight: bold; \\n}\"\n            },\n            \"cardHtml\": {\n                \"title\": \"HTML\",\n                \"type\": \"string\",\n                \"default\": \"<div class=''card''>HTML code here</div>\"\n            }\n        }\n    },\n    \"form\": [\n        {\n            \"key\": \"cardCss\",\n            \"type\": \"css\"\n        },           \n        {\n            \"key\": \"cardHtml\",\n            \"type\": \"html\"\n        }    \n    ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"static\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"cardHtml\":\"<div class=''card''>HTML code here</div>\",\"cardCss\":\".card {\\n    font-weight: bold;\\n    font-size: 32px;\\n    color: #999;\\n    width: 100%;\\n    height: 100%;\\n    display: flex;\\n    align-items: center;\\n    justify-content: center;\\n}\"},\"title\":\"HTML Card\",\"dropShadow\":true}"}',
'HTML Card' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges',
'simple_neon_gauge_justgage',
'{"type":"latest","sizeX":3,"sizeY":3,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#388e3c\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":1,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":40,\"dashThickness\":1.5,\"decimals\":0,\"gaugeType\":\"donut\"},\"title\":\"Simple neon gauge - justGage\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Simple neon gauge - justGage' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'analogue_gauges',
'radial_gauge_canvas_gauges',
'{"type":"latest","sizeX":6,"sizeY":5,"resources":[],"templateHtml":"<canvas id=\"radialGauge\"></canvas>\n","templateCss":"","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbAnalogueRadialGauge(self.ctx, ''radialGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.getSettingsSchema = function() {\n    return TbAnalogueRadialGauge.settingsSchema;\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 50 - 25;\\nif (value < -100) {\\n\\tvalue = -100;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":100,\"startAngle\":45,\"ticksAngle\":270,\"showBorder\":true,\"defaultColor\":\"#e65100\",\"needleCircleSize\":10,\"highlights\":[],\"showUnitTitle\":true,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":10,\"valueInt\":3,\"valueDec\":0,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":500,\"animationRule\":\"cycle\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"numbersFont\":{\"family\":\"Roboto\",\"size\":18,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#888\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":22,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"size\":36,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\"},\"minValue\":-100,\"colorNeedleShadowDown\":\"rgba(188,143,143,0.45)\",\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\"},\"title\":\"Radial gauge - Canvas Gauges\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Radial gauge - Canvas Gauges' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges',
'digital_speedometer',
'{"type":"latest","sizeX":5,"sizeY":3,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 45) {\\n\\tvalue = 45;\\n} else if (value > 130) {\\n\\tvalue = 130;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":180,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[\"#008000\",\"#fbc02d\",\"#f44336\"],\"refreshAnimationType\":\"linear\",\"refreshAnimationTime\":700,\"startAnimationType\":\"linear\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#ffffff\"},\"neonGlowBrightness\":40,\"dashThickness\":1.5,\"decimals\":0,\"unitTitle\":\"MPH\",\"showUnitTitle\":true,\"gaugeColor\":\"#171a1c\",\"gaugeType\":\"arc\"},\"title\":\"Digital speedometer\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Digital speedometer' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'charts', 'doughnut_chart_js',
'{"type":"latest","sizeX":7,"sizeY":5,"resources":[{"url":"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"}],"templateHtml":"<canvas id=\"pieChart\"></canvas>\n","templateCss":"","controllerScript":"self.onInit = function() {\n    var pieData = {\n        labels: [],\n        datasets: []\n    };\n\n    var dataset = {\n        data: [],\n        backgroundColor: [],\n        borderColor: [],\n        borderWidth: [],\n        hoverBackgroundColor: []\n    }\n    \n    var borderColor = self.ctx.settings.borderColor || ''#fff'';\n    var borderWidth = angular.isDefined(self.ctx.settings.borderWidth) ? self.ctx.settings.borderWidth : 5;\n    \n    pieData.datasets.push(dataset);\n    \n    for (var i=0; i < self.ctx.data.length; i++) {\n        var dataKey = self.ctx.data[i].dataKey;\n        pieData.labels.push(dataKey.label);\n        dataset.data.push(0);\n        var hoverBackgroundColor = tinycolor(dataKey.color).lighten(15);\n        dataset.backgroundColor.push(dataKey.color);\n        dataset.borderColor.push(borderColor);\n        dataset.borderWidth.push(borderWidth);\n        dataset.hoverBackgroundColor.push(hoverBackgroundColor.toRgbString());\n    }\n\n    var options = {\n        responsive: false,\n        maintainAspectRatio: false,\n        legend: {\n            display: true,\n            labels: {\n                fontColor: ''#666''\n            }\n        },\n        tooltips: {\n            callbacks: {\n                label: function(tooltipItem, data) {\n                    var label = data.labels[tooltipItem.index];\n                    var value = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];\n                    var content = label + '': '' + value;\n                    var units = self.ctx.settings.units ? self.ctx.settings.units : self.ctx.units;\n                    if (units) {\n                        content += '' '' + units;\n                    } \n                    return content;\n                }\n            }\n        }\n    };\n\n    if (self.ctx.settings.legend) {\n        options.legend.display = self.ctx.settings.legend.display !== false;\n        options.legend.labels.fontColor = self.ctx.settings.legend.labelsFontColor || ''#666'';\n    }\n\n    var ctx = $(''#pieChart'', self.ctx.$container);\n    self.ctx.chart = new Chart(ctx, {\n        type: ''doughnut'',\n        data: pieData,\n        options: options\n    });\n    \n    self.onResize();\n}\n\nself.onDataUpdated = function() {\n    for (var i = 0; i < self.ctx.data.length; i++) {\n        var cellData = self.ctx.data[i];\n        if (cellData.data.length > 0) {\n             var tvPair = cellData.data[cellData.data.length - 1];\n             var value = tvPair[1];\n             self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n        }\n    }\n    self.ctx.chart.update();\n}\n\nself.onResize = function() {\n    self.ctx.chart.resize();\n}\n\n","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"properties\": {\n            \"borderWidth\": {\n                \"title\": \"Border width\",\n                \"type\": \"number\",\n                \"default\": 5\n            },\n            \"borderColor\": {\n                \"title\": \"Border color\",\n                \"type\": \"string\",\n                \"default\": \"#fff\"\n            },\n            \"legend\": {\n                \"title\": \"Legend settings\",\n                \"type\": \"object\",\n                \"properties\": {\n                    \"display\": {\n                        \"title\": \"Display legend\",\n                        \"type\": \"boolean\",\n                        \"default\": true\n                    },\n                    \"labelsFontColor\": {\n                        \"title\": \"Labels font color\",\n                        \"type\": \"string\",\n                        \"default\": \"#666\"\n                    }\n                }\n            }\n        },\n        \"required\": []\n    },\n    \"form\": [\n        \"borderWidth\", \n        {\n            \"key\": \"borderColor\",\n            \"type\": \"color\"\n        }, \n        {\n            \"key\": \"legend\",\n            \"items\": [\n                \"legend.display\",\n                {\n                    \"key\": \"legend.labelsFontColor\",\n                    \"type\": \"color\"\n                }\n            ]\n        }\n    ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#26a69a\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#f57c00\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#afb42b\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#673ab7\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"borderWidth\":5,\"borderColor\":\"#fff\",\"legend\":{\"display\":true,\"labelsFontColor\":\"#666666\"}},\"title\":\"Doughnut - Chart.js\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Doughnut - Chart.js' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'charts', 'pie_chart_js',
'{"type":"latest","sizeX":8,"sizeY":5,"resources":[{"url":"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"}],"templateHtml":"<canvas id=\"pieChart\"></canvas>\n","templateCss":"","controllerScript":"self.onInit = function() {\n    \n    var pieData = {\n        labels: [],\n        datasets: []\n    };\n\n    var dataset = {\n        data: [],\n        backgroundColor: [],\n        borderColor: [],\n        borderWidth: [],\n        hoverBackgroundColor: []\n    }\n    \n    pieData.datasets.push(dataset);\n    \n    for (var i=0; i < self.ctx.data.length; i++) {\n        var dataKey = self.ctx.data[i].dataKey;\n        pieData.labels.push(dataKey.label);\n        dataset.data.push(0);\n        var hoverBackgroundColor = tinycolor(dataKey.color).lighten(15);\n        var borderColor = tinycolor(dataKey.color).darken();\n        dataset.backgroundColor.push(dataKey.color);\n        dataset.borderColor.push(''#fff'');\n        dataset.borderWidth.push(5);\n        dataset.hoverBackgroundColor.push(hoverBackgroundColor.toRgbString());\n    }\n\n    var ctx = $(''#pieChart'', self.ctx.$container);\n    self.ctx.chart = new Chart(ctx, {\n        type: ''pie'',\n        data: pieData,\n        options: {\n            responsive: false,\n            maintainAspectRatio: false\n        }\n    });    \n    \n    self.onResize();\n}\n\nself.onDataUpdated = function() {\n    for (var i = 0; i < self.ctx.data.length; i++) {\n        var cellData = self.ctx.data[i];\n        if (cellData.data.length > 0) {\n             var tvPair = cellData.data[cellData.data.length - 1];\n             var value = tvPair[1];\n             self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n        }\n    }\n    self.ctx.chart.update();\n}\n\nself.onResize = function() {\n    self.ctx.chart.resize();\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Pie - Chart.js\"}"}',
'Pie - Chart.js' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'charts', 'bars',
'{"type":"latest","sizeX":7,"sizeY":5,"resources":[{"url":"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"}],"templateHtml":"<canvas id=\"barChart\"></canvas>\n","templateCss":"","controllerScript":"self.onInit = function() {\n    var barData = {\n        labels: [],\n        datasets: []\n    };\n    \n    for (var i = 0; i < self.ctx.datasources.length; i++) {\n        var datasource = self.ctx.datasources[i];\n        for (var d = 0; d < datasource.dataKeys.length; d++) {\n            var dataset = {\n                label: datasource.dataKeys[d].label,\n                data: [0],\n                backgroundColor: [datasource.dataKeys[d].color],\n                borderColor: [datasource.dataKeys[d].color],\n                borderWidth: 1\n            }\n            barData.datasets.push(dataset);\n        }\n    }\n\n    var ctx = $(''#barChart'', self.ctx.$container);\n    self.ctx.chart = new Chart(ctx, {\n        type: ''bar'',\n        data: barData,\n        options: {\n            responsive: false,\n            maintainAspectRatio: false,\n            scales: {\n                yAxes: [{\n                    ticks: {\n                        beginAtZero:true\n                    }\n                }]\n            }\n        }\n    });\n    \n    self.onResize();\n}\n\nself.onDataUpdated = function() {\n    var c = 0;\n    for (var i = 0; i < self.ctx.chart.data.datasets.length; i++) {\n        var dataset = self.ctx.chart.data.datasets[i];\n        var cellData = self.ctx.data[i]; \n        if (cellData.data.length > 0) {\n             var tvPair = cellData.data[cellData.data.length - 1];\n             var value = tvPair[1];\n             dataset.data[0] = parseFloat(value);\n        }\n    }\n    self.ctx.chart.update();\n}\n\nself.onResize = function() {\n    self.ctx.chart.resize();\n}\n\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Bars - Chart.js\"}"}',
'Bars - Chart.js' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges', 'digital_bar',
'{"type":"latest","sizeX":6,"sizeY":2.5,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 80) {\\n\\tvalue = 80;\\n} else if (value > 160) {\\n\\tvalue = 160;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":180,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[\"#008000\",\"#fbc02d\",\"#f44336\"],\"refreshAnimationType\":\"linear\",\"refreshAnimationTime\":700,\"startAnimationType\":\"linear\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":18},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#ffffff\"},\"neonGlowBrightness\":40,\"dashThickness\":1.5,\"decimals\":0,\"unitTitle\":\"MPH\",\"showUnitTitle\":true,\"gaugeColor\":\"#171a1c\",\"gaugeType\":\"horizontalBar\",\"showTitle\":false},\"title\":\"Digital horizontal bar\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Digital horizontal bar' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges',
'mini_gauge_justgage',
'{"type":"latest","sizeX":2,"sizeY":2,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#7cb342\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":0,\"decimals\":0,\"roundedLineCap\":true,\"gaugeType\":\"donut\"},\"title\":\"Mini gauge - justGage\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Mini gauge - justGage' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'maps', 'route_map_openstreetmap',
'{"type":"timeseries","sizeX":8.5,"sizeY":6,"resources":[],"templateHtml":"","templateCss":".leaflet-zoom-box {\n\tz-index: 9;\n}\n\n.leaflet-pane         { z-index: 4; }\n\n.leaflet-tile-pane    { z-index: 2; }\n.leaflet-overlay-pane { z-index: 4; }\n.leaflet-shadow-pane  { z-index: 5; }\n.leaflet-marker-pane  { z-index: 6; }\n.leaflet-tooltip-pane   { z-index: 7; }\n.leaflet-popup-pane   { z-index: 8; }\n\n.leaflet-map-pane canvas { z-index: 1; }\n.leaflet-map-pane svg    { z-index: 2; }\n\n.leaflet-control {\n\tz-index: 9;\n}\n.leaflet-top,\n.leaflet-bottom {\n\tz-index: 11;\n}\n\n.tb-marker-label {\n    border: none;\n    background: none;\n    box-shadow: none;\n}\n\n.tb-marker-label:before {\n    border: none;\n    background: none;\n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.map = new TbMapWidget(''openstreet-map'', true, self.ctx);\n}\n\nself.onDataUpdated = function() {\n    self.ctx.map.update();\n}\n\nself.onResize = function() {\n    self.ctx.map.resize();\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{\n  \"schema\": {\n    \"title\": \"Route Map Configuration\",\n    \"type\": \"object\",\n    \"properties\": {\n      \"defaultZoomLevel\": {\n         \"title\": \"Default map zoom level (1 - 20)\",\n         \"type\": \"number\"\n      },\n      \"fitMapBounds\": {\n          \"title\": \"Fit map bounds to cover all markers\",\n          \"type\": \"boolean\",\n          \"default\": true\n      },\n      \"routesSettings\": {\n            \"title\": \"Routes\",\n            \"type\": \"array\",\n            \"items\": {\n              \"title\": \"Route settings\",\n              \"type\": \"object\",\n              \"properties\": {\n                  \"latKeyName\": {\n                    \"title\": \"Latitude key name\",\n                    \"type\": \"string\",\n                    \"default\": \"lat\"\n                  },\n                  \"lngKeyName\": {\n                    \"title\": \"Longitude key name\",\n                    \"type\": \"string\",\n                    \"default\": \"lng\"\n                  },\n                  \"showLabel\": {\n                    \"title\": \"Show label\",\n                    \"type\": \"boolean\",\n                    \"default\": true\n                  },                  \n                  \"label\": {\n                    \"title\": \"Label\",\n                    \"type\": \"string\"\n                  },\n                  \"tooltipPattern\": {\n                    \"title\": \"Pattern ( for ex. ''Text ${keyName} units.'' or ''${#<key index>} units''  )\",\n                    \"type\": \"string\",\n                    \"default\": \"<b>Latitude:</b> ${lat:7}<br/><b>Longitude:</b> ${lng:7}\"\n                  },\n                  \"color\": {\n                    \"title\": \"Color\",\n                    \"type\": \"string\"\n                  },\n                  \"useColorFunction\": {\n                    \"title\": \"Use color function\",\n                    \"type\": \"boolean\",\n                    \"default\": false\n                  },\n                  \"colorFunction\": {\n                    \"title\": \"Color function: f(data)\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImage\": {\n                    \"title\": \"Custom marker image\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImageSize\": {\n                     \"title\": \"Custom marker image size (px)\",\n                     \"type\": \"number\",\n                     \"default\": 34\n                  },\n                  \"useMarkerImageFunction\": {\n                    \"title\": \"Use marker image function\",\n                    \"type\": \"boolean\",\n                    \"default\": false\n                  },\n                  \"markerImageFunction\": {\n                    \"title\": \"Marker image function: f(data, images)\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImages\": {\n                        \"title\": \"Marker images\",\n                        \"type\": \"array\",\n                        \"items\": {\n                          \"title\": \"Marker image\",\n                          \"type\": \"string\"\n                        }\n                  },\n                  \"strokeWeight\": {\n                    \"title\": \"Stroke weight\",\n                    \"type\": \"number\",\n                    \"default\": 2\n                  },\n                  \"strokeOpacity\": {\n                    \"title\": \"Stroke opacity\",\n                    \"type\": \"number\",\n                    \"default\": 1.0\n                  }\n              }\n            }\n      }\n    },\n    \"required\": [\n    ]\n  },\n  \"form\": [\n    \"defaultZoomLevel\",\n    \"fitMapBounds\",\n    {\n        \"key\": \"routesSettings\",\n        \"items\": [\n            \"routesSettings[].latKeyName\",\n            \"routesSettings[].lngKeyName\",\n            \"routesSettings[].showLabel\",\n            \"routesSettings[].label\",\n            \"routesSettings[].tooltipPattern\",\n            {\n                \"key\": \"routesSettings[].color\",\n                \"type\": \"color\"\n            },\n            \"routesSettings[].useColorFunction\",\n            {\n                \"key\": \"routesSettings[].colorFunction\",\n                \"type\": \"javascript\"\n            },\n            {\n                \"key\": \"routesSettings[].markerImage\",\n                \"type\": \"image\"\n            },\n            \"routesSettings[].markerImageSize\",\n            \"routesSettings[].useMarkerImageFunction\",\n            {\n                \"key\": \"routesSettings[].markerImageFunction\",\n                \"type\": \"javascript\"\n            },\n            {\n                \"key\": \"routesSettings[].markerImages\",\n                \"items\": [\n                    {\n                        \"key\": \"routesSettings[].markerImages[]\",\n                        \"type\": \"image\"\n                    }\n                ]\n            },\n            \"routesSettings[].strokeWeight\",\n            \"routesSettings[].strokeOpacity\"\n        ]\n    }\n  ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.8950926999078694,\"funcBody\":\"var lats = [37.7696499,\\n37.7699074,\\n37.7699536,\\n37.7697242,\\n37.7695189,\\n37.7696889,\\n37.7697153,\\n37.7701244,\\n37.7700604,\\n37.7705491,\\n37.7715705,\\n37.771752,\\n37.7707533,\\n37.769866];\\n\\nvar i = Math.floor((time/3 % 14000) / 1000);\\n\\nreturn lats[i];\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.2757675428823283,\"funcBody\":\"var lons = [-122.4261215,\\n-122.4219157,\\n-122.4199623,\\n-122.4179074,\\n-122.4155876,\\n-122.4155521,\\n-122.4163203,\\n-122.4193876,\\n-122.4210496,\\n-122.422284,\\n-122.4232717,\\n-122.4235138,\\n-122.4247605,\\n-122.4258812];\\n\\nvar i = Math.floor((time/3 % 14000) / 1000);\\n\\nreturn lons[i];\"}],\"intervalSec\":60},{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.14481354591724638,\"funcBody\":\"var value = prevValue;\\nif (time % 500 < 100) {\\n    value = value + Math.random() * 40 - 20;\\n    if (value < 45) {\\n    \\tvalue = 45;\\n    } else if (value > 130) {\\n    \\tvalue = 130;\\n    }\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":30000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"fitMapBounds\":true,\"routesSettings\":[{\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"tooltipPattern\":\"<b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><b>Speed:</b> ${Speed} MPH<br/><small>See advanced settings for details</small>\",\"strokeWeight\":4,\"label\":\"First route\",\"color\":\"#3d5afe\",\"strokeOpacity\":1,\"useColorFunction\":true,\"useMarkerImageFunction\":true,\"markerImages\":[\"data:image/png;base64,[encoded data, 17264 characters]\",\"data:image/png;base64,[encoded data, 16628 characters]\",\"data:image/png;base64,[encoded data, 17120 characters]\"],\"colorFunction\":\"var speed = data[''Speed''];\\nif (typeof speed !== undefined) {\\n    var percent = (speed - 45)/85;\\n    if (percent < 0.5) {\\n        percent *=2*100; \\n        return tinycolor.mix(''green'', ''yellow'', amount = percent).toHexString();\\n    } else {\\n        percent = (percent - 0.5)*2*100;\\n        return tinycolor.mix(''yellow'', ''red'', amount = percent).toHexString();\\n    }\\n}\\nreturn ''green'';\",\"markerImageFunction\":\"var speed = data[''Speed''];\\nvar res = {\\n    url: images[0],\\n    size: 55\\n};\\nif (typeof speed !== undefined) {\\n    var percent = (speed - 45)/85;\\n    var index = Math.floor(3 * percent);\\n    res.url = images[index];\\n}\\nreturn res;\"}]},\"title\":\"Route Map - OpenStreetMap\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false}"}',
'Route Map - OpenStreetMap' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'cards', 'label_widget',
'{"type":"latest","sizeX":4.5,"sizeY":5,"resources":[],"templateHtml":"","templateCss":"#container {\n    overflow: auto;\n}\n\n.tbDatasource-container {\n    margin: 5px;\n    padding: 8px;\n}\n\n.tbDatasource-title {\n    font-size: 1.200rem;\n    font-weight: 500;\n    padding-bottom: 10px;\n}\n\n.tbDatasource-table {\n    width: 100%;\n    box-shadow: 0 0 10px #ccc;\n    border-collapse: collapse;\n    white-space: nowrap;\n    font-size: 1.000rem;\n    color: #757575;\n}\n\n.tbDatasource-table td {\n    position: relative;\n    border-top: 1px solid rgba(0, 0, 0, 0.12);\n    border-bottom: 1px solid rgba(0, 0, 0, 0.12);\n    padding: 0px 18px;\n    box-sizing: border-box;\n}","controllerScript":"self.onInit = function() {\n    self.ctx.varsRegex = /\\$\\{([^\\}]*)\\}/g;\n    \n    var imageUrl = self.ctx.settings.backgroundImageUrl ? self.ctx.settings.backgroundImageUrl :\n    ''data:image/svg+xml;base64,PHN2ZyBpZD0ic3ZnMiIgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTAwIiB3aWR0aD0iMTAwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmlld0JveD0iMCAwIDEwMCAxMDAiPgogPGcgaWQ9ImxheWVyMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAtOTUyLjM2KSI+CiAgPHJlY3QgaWQ9InJlY3Q0Njg0IiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBoZWlnaHQ9Ijk5LjAxIiB3aWR0aD0iOTkuMDEiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiB5PSI5NTIuODYiIHg9Ii40OTUwNSIgc3Ryb2tlLXdpZHRoPSIuOTkwMTAiIGZpbGw9IiNlZWUiLz4KICA8dGV4dCBpZD0idGV4dDQ2ODYiIHN0eWxlPSJ3b3JkLXNwYWNpbmc6MHB4O2xldHRlci1zcGFjaW5nOjBweDt0ZXh0LWFuY2hvcjptaWRkbGU7dGV4dC1hbGlnbjpjZW50ZXIiIGZvbnQtd2VpZ2h0PSJib2xkIiB4bWw6c3BhY2U9InByZXNlcnZlIiBmb250LXNpemU9IjEwcHgiIGxpbmUtaGVpZ2h0PSIxMjUlIiB5PSI5NzAuNzI4MDkiIHg9IjQ5LjM5NjQ3NyIgZm9udC1mYW1pbHk9IlJvYm90byIgZmlsbD0iIzY2NjY2NiI+PHRzcGFuIGlkPSJ0c3BhbjQ2OTAiIHg9IjUwLjY0NjQ3NyIgeT0iOTcwLjcyODA5Ij5JbWFnZSBiYWNrZ3JvdW5kIDwvdHNwYW4+PHRzcGFuIGlkPSJ0c3BhbjQ2OTIiIHg9IjQ5LjM5NjQ3NyIgeT0iOTgzLjIyODA5Ij5pcyBub3QgY29uZmlndXJlZDwvdHNwYW4+PC90ZXh0PgogIDxyZWN0IGlkPSJyZWN0NDY5NCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgaGVpZ2h0PSIxOS4zNiIgd2lkdGg9IjY5LjM2IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgeT0iOTkyLjY4IiB4PSIxNS4zMiIgc3Ryb2tlLXdpZHRoPSIuNjM5ODYiIGZpbGw9Im5vbmUiLz4KIDwvZz4KPC9zdmc+Cg=='';\n\n    self.ctx.$container.css(''background'', ''url(\"''+imageUrl+''\") no-repeat'');\n    self.ctx.$container.css(''backgroundSize'', ''contain'');\n    self.ctx.$container.css(''backgroundPosition'', ''50% 50%'');\n    \n    function processLabelPattern(pattern, data) {\n        var match = self.ctx.varsRegex.exec(pattern);\n        var replaceInfo = {};\n        replaceInfo.variables = [];\n        while (match !== null) {\n            var variableInfo = {};\n            variableInfo.dataKeyIndex = -1;\n            var variable = match[0];\n            var label = match[1];\n            var valDec = 2;\n            var splitVals = label.split('':'');\n            if (splitVals.length > 1) {\n                label = splitVals[0];\n                valDec = parseFloat(splitVals[1]);\n            }\n            variableInfo.variable = variable;\n            variableInfo.valDec = valDec;\n            \n            if (label.startsWith(''#'')) {\n                var keyIndexStr = label.substring(1);\n                var n = Math.floor(Number(keyIndexStr));\n                if (String(n) === keyIndexStr && n >= 0) {\n                    variableInfo.dataKeyIndex = n;\n                }\n            }\n            if (variableInfo.dataKeyIndex === -1) {\n                for (var i = 0; i < data.length; i++) {\n                     var datasourceData = data[i];\n                     var dataKey = datasourceData.dataKey;\n                     if (dataKey.label === label) {\n                         variableInfo.dataKeyIndex = i;\n                         break;\n                     }\n                }\n            }\n            replaceInfo.variables.push(variableInfo);\n            match = self.ctx.varsRegex.exec(pattern);\n        }\n        return replaceInfo;\n    }\n\n    var configuredLabels = self.ctx.settings.labels;\n    if (!configuredLabels) {\n        configuredLabels = [];\n    }\n    \n    self.ctx.labels = [];\n\n    for (var l = 0; l < configuredLabels.length; l++) {\n        var labelConfig = configuredLabels[l];\n        var localConfig = {};\n        localConfig.font = {};\n        \n        localConfig.pattern = labelConfig.pattern ? labelConfig.pattern : ''${#0}'';\n        localConfig.x = labelConfig.x ? labelConfig.x : 0;\n        localConfig.y = labelConfig.y ? labelConfig.y : 0;\n        localConfig.backgroundColor = labelConfig.backgroundColor ? labelConfig.backgroundColor : ''rgba(0,0,0,0)'';\n        \n        var settingsFont = labelConfig.font;\n        if (!settingsFont) {\n            settingsFont = {};\n        }\n        \n        localConfig.font.family = settingsFont.family || ''RobotoDraft'';\n        localConfig.font.size = settingsFont.size ? settingsFont.size : 6;\n        localConfig.font.style = settingsFont.style ? settingsFont.style : ''normal'';\n        localConfig.font.weight = settingsFont.weight ? settingsFont.weight : ''500'';\n        localConfig.font.color = settingsFont.color ? settingsFont.color : ''#fff'';\n        \n        localConfig.replaceInfo = processLabelPattern(localConfig.pattern, self.ctx.data);\n        \n        var label = {};\n        var labelElement = $(''<div/>'');\n        labelElement.css(''position'', ''absolute'');\n        labelElement.css(''display'', ''none'');\n        labelElement.css(''top'', ''0'');\n        labelElement.css(''left'', ''0'');\n        labelElement.css(''backgroundColor'', localConfig.backgroundColor);\n        labelElement.css(''color'', localConfig.font.color);\n        labelElement.css(''fontFamily'', localConfig.font.family);\n        labelElement.css(''fontStyle'', localConfig.font.style);\n        labelElement.css(''fontWeight'', localConfig.font.weight);\n        \n        labelElement.html(localConfig.pattern);\n        self.ctx.$container.append(labelElement);\n        label.element = labelElement;\n        label.config = localConfig;\n        label.htmlSet = false;\n        label.visible = false;\n        self.ctx.labels.push(label);\n    }\n\n    var bgImg = $(''<img />'');\n    bgImg.hide();\n    bgImg.bind(''load'', function()\n    {\n        self.ctx.bImageHeight = $(this).height();\n        self.ctx.bImageWidth = $(this).width();\n        self.onResize();\n    });\n    self.ctx.$container.append(bgImg);\n    bgImg.attr(''src'', imageUrl);\n    \n    self.onDataUpdated();\n}\n\nself.onDataUpdated = function() {\n    updateLabels();\n}\n\nself.onResize = function() {\n    if (self.ctx.bImageHeight && self.ctx.bImageWidth) {\n        var backgroundRect = {};\n        var imageRatio = self.ctx.bImageWidth / self.ctx.bImageHeight;\n        var componentRatio = self.ctx.width / self.ctx.height;\n        if (componentRatio >= imageRatio) {\n            backgroundRect.top = 0;\n            backgroundRect.bottom = 1.0;\n            backgroundRect.xRatio = imageRatio / componentRatio;\n            backgroundRect.yRatio = 1;\n            var offset = (1 - backgroundRect.xRatio) / 2;\n            backgroundRect.left = offset;\n            backgroundRect.right = 1 - offset;\n        } else {\n            backgroundRect.left = 0;\n            backgroundRect.right = 1.0;\n            backgroundRect.xRatio = 1;\n            backgroundRect.yRatio = componentRatio / imageRatio;\n            var offset = (1 - backgroundRect.yRatio) / 2;\n            backgroundRect.top = offset;\n            backgroundRect.bottom = 1 - offset;\n        }\n        for (var l = 0; l < self.ctx.labels.length; l++) {\n            var label = self.ctx.labels[l];\n            var labelLeft = backgroundRect.left*100 + (label.config.x*backgroundRect.xRatio);\n            var labelTop = backgroundRect.top*100 + (label.config.y*backgroundRect.yRatio);\n            var fontSize = self.ctx.height * backgroundRect.yRatio * label.config.font.size / 100;\n            label.element.css(''top'', labelTop + ''%'');\n            label.element.css(''left'', labelLeft + ''%'');\n            label.element.css(''fontSize'', fontSize + ''px'');\n            if (!label.visible) {\n                label.element.css(''display'', ''block'');\n                label.visible = true;\n            }\n        }\n    }    \n}\n\n\nfunction isNumber(n) {\n    return !isNaN(parseFloat(n)) && isFinite(n);\n}\n\nfunction padValue(val, dec, int) {\n    var i = 0;\n    var s, strVal, n;\n\n    val = parseFloat(val);\n    n = (val < 0);\n    val = Math.abs(val);\n\n    if (dec > 0) {\n        strVal = val.toFixed(dec).toString().split(''.'');\n        s = int - strVal[0].length;\n\n        for (; i < s; ++i) {\n            strVal[0] = ''0'' + strVal[0];\n        }\n\n        strVal = (n ? ''-'' : '''') + strVal[0] + ''.'' + strVal[1];\n    }\n\n    else {\n        strVal = Math.round(val).toString();\n        s = int - strVal.length;\n\n        for (; i < s; ++i) {\n            strVal = ''0'' + strVal;\n        }\n\n        strVal = (n ? ''-'' : '''') + strVal;\n    }\n\n    return strVal;\n}\n\nfunction updateLabels() {\n    for (var l = 0; l < self.ctx.labels.length; l++) {\n        var label = self.ctx.labels[l];\n        var text = label.config.pattern;\n        var replaceInfo = label.config.replaceInfo;\n        var updated = false;\n        for (var v = 0; v < replaceInfo.variables.length; v++) {\n            var variableInfo = replaceInfo.variables[v];\n            var txtVal = '''';\n            if (variableInfo.dataKeyIndex > -1) {\n                var varData = self.ctx.data[variableInfo.dataKeyIndex].data;\n                if (varData.length > 0) {\n                    var val = varData[varData.length-1][1];\n                    if (isNumber(val)) {\n                        txtVal = padValue(val, variableInfo.valDec, 0);\n                        updated = true;\n                    } else {\n                        txtVal = val;\n                        updated = true;\n                    }\n                }\n            }\n            text = text.split(variableInfo.variable).join(txtVal);\n        }\n        if (updated || !label.htmlSet) {\n            label.element.html(text);\n            if (!label.htmlSet) {\n                label.htmlSet = true;\n            }\n        }\n    }\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"required\": [\"backgroundImageUrl\"],\n        \"properties\": {\n            \"backgroundImageUrl\": {\n                \"title\": \"Background image\",\n                \"type\": \"string\",\n                \"default\": \"data:image/svg+xml;base64,PHN2ZyBpZD0ic3ZnMiIgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTAwIiB3aWR0aD0iMTAwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmlld0JveD0iMCAwIDEwMCAxMDAiPgogPGcgaWQ9ImxheWVyMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAtOTUyLjM2KSI+CiAgPHJlY3QgaWQ9InJlY3Q0Njg0IiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBoZWlnaHQ9Ijk5LjAxIiB3aWR0aD0iOTkuMDEiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiB5PSI5NTIuODYiIHg9Ii40OTUwNSIgc3Ryb2tlLXdpZHRoPSIuOTkwMTAiIGZpbGw9IiNlZWUiLz4KICA8dGV4dCBpZD0idGV4dDQ2ODYiIHN0eWxlPSJ3b3JkLXNwYWNpbmc6MHB4O2xldHRlci1zcGFjaW5nOjBweDt0ZXh0LWFuY2hvcjptaWRkbGU7dGV4dC1hbGlnbjpjZW50ZXIiIGZvbnQtd2VpZ2h0PSJib2xkIiB4bWw6c3BhY2U9InByZXNlcnZlIiBmb250LXNpemU9IjEwcHgiIGxpbmUtaGVpZ2h0PSIxMjUlIiB5PSI5NzAuNzI4MDkiIHg9IjQ5LjM5NjQ3NyIgZm9udC1mYW1pbHk9IlJvYm90byIgZmlsbD0iIzY2NjY2NiI+PHRzcGFuIGlkPSJ0c3BhbjQ2OTAiIHg9IjUwLjY0NjQ3NyIgeT0iOTcwLjcyODA5Ij5JbWFnZSBiYWNrZ3JvdW5kIDwvdHNwYW4+PHRzcGFuIGlkPSJ0c3BhbjQ2OTIiIHg9IjQ5LjM5NjQ3NyIgeT0iOTgzLjIyODA5Ij5pcyBub3QgY29uZmlndXJlZDwvdHNwYW4+PC90ZXh0PgogIDxyZWN0IGlkPSJyZWN0NDY5NCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgaGVpZ2h0PSIxOS4zNiIgd2lkdGg9IjY5LjM2IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgeT0iOTkyLjY4IiB4PSIxNS4zMiIgc3Ryb2tlLXdpZHRoPSIuNjM5ODYiIGZpbGw9Im5vbmUiLz4KIDwvZz4KPC9zdmc+Cg==\"\n            },\n            \"labels\": {\n                \"title\": \"Labels\",\n                \"type\": \"array\",\n                \"items\": {\n                   \"title\": \"Label\",\n                   \"type\": \"object\",\n                   \"required\": [\"pattern\"],\n                   \"properties\": {\n                       \"pattern\": {\n                           \"title\": \"Pattern ( for ex. ''Text ${keyName} units.'' or ''${#<key index>} units''  )\",\n                           \"type\": \"string\",\n                           \"default\": \"${#0}\"\n                       },\n                       \"x\": {\n                           \"title\": \"X (Percentage relative to background)\",\n                           \"type\": \"number\",\n                           \"default\": 50\n                       },\n                       \"y\": {\n                           \"title\": \"Y (Percentage relative to background)\",\n                           \"type\": \"number\",\n                           \"default\": 50\n                       },\n                       \"backgroundColor\": {\n                           \"title\": \"Backround color\",\n                           \"type\": \"string\",\n                           \"default\": \"rgba(0,0,0,0)\"\n                       },\n                       \"font\": {\n                           \"type\": \"object\",\n                           \"properties\": {\n                               \"family\": {\n                                    \"title\": \"Font family\",\n                                    \"type\": \"string\",\n                                    \"default\": \"RobotoDraft\"\n                                },\n                                \"size\": {\n                                    \"title\": \"Relative font size (percents)\",\n                                    \"type\": \"number\",\n                                    \"default\": 6\n                                },\n                                \"style\": {\n                                    \"title\": \"Style\",\n                                    \"type\": \"string\",\n                                    \"default\": \"normal\"\n                                },\n                                \"weight\": {\n                                    \"title\": \"Weight\",\n                                    \"type\": \"string\",\n                                    \"default\": \"500\"\n                                },\n                                \"color\": {\n                                    \"title\": \"color\",\n                                    \"type\": \"string\",\n                                    \"default\": \"#fff\"\n                                }\n                           }\n                       }\n                   }\n                }\n            }\n        }\n    },\n    \"form\": [\n        {\n            \"key\": \"backgroundImageUrl\",\n            \"type\": \"image\"\n        },\n        {\n            \"key\": \"labels\",\n            \"items\": [\n                \"labels[].pattern\",\n                \"labels[].x\",\n                \"labels[].y\",\n                {\n                    \"key\": \"labels[].backgroundColor\",\n                    \"type\": \"color\"\n                },\n                \"labels[].font.family\",\n                \"labels[].font.size\",\n                {\n                   \"key\": \"labels[].font.style\",\n                   \"type\": \"rc-select\",\n                   \"multiple\": false,\n                   \"items\": [\n                       {\n                           \"value\": \"normal\",\n                           \"label\": \"Normal\"\n                       },\n                       {\n                           \"value\": \"italic\",\n                           \"label\": \"Italic\"\n                       },\n                       {\n                           \"value\": \"oblique\",\n                           \"label\": \"Oblique\"\n                       }\n                    ]\n\n                },\n                {\n                   \"key\": \"labels[].font.weight\",\n                   \"type\": \"rc-select\",\n                   \"multiple\": false,\n                   \"items\": [\n                       {\n                           \"value\": \"normal\",\n                           \"label\": \"Normal\"\n                       },\n                       {\n                           \"value\": \"bold\",\n                           \"label\": \"Bold\"\n                       },\n                       {\n                           \"value\": \"bolder\",\n                           \"label\": \"Bolder\"\n                       },\n                       {\n                           \"value\": \"lighter\",\n                           \"label\": \"Lighter\"\n                       },\n                       {\n                           \"value\": \"100\",\n                           \"label\": \"100\"\n                       },\n                       {\n                           \"value\": \"200\",\n                           \"label\": \"200\"\n                       },\n                       {\n                           \"value\": \"300\",\n                           \"label\": \"300\"\n                       },\n                       {\n                           \"value\": \"400\",\n                           \"label\": \"400\"\n                       },\n                       {\n                           \"value\": \"500\",\n                           \"label\": \"500\"\n                       },\n                       {\n                           \"value\": \"600\",\n                           \"label\": \"600\"\n                       },\n                       {\n                           \"value\": \"700\",\n                           \"label\": \"800\"\n                       },\n                       {\n                           \"value\": \"800\",\n                           \"label\": \"800\"\n                       },\n                       {\n                           \"value\": \"900\",\n                           \"label\": \"900\"\n                       }\n                    ]\n                },\n                {\n                    \"key\": \"labels[].font.color\",\n                    \"type\": \"color\"\n                }\n            ]\n        }\n    ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"var\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"backgroundImageUrl\":\"data:image/svg+xml;base64,PHN2ZyBpZD0ic3ZnMiIgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMTAwIiB3aWR0aD0iMTAwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgdmlld0JveD0iMCAwIDEwMCAxMDAiPgogPGcgaWQ9ImxheWVyMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAtOTUyLjM2KSI+CiAgPHJlY3QgaWQ9InJlY3Q0Njg0IiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBoZWlnaHQ9Ijk5LjAxIiB3aWR0aD0iOTkuMDEiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiB5PSI5NTIuODYiIHg9Ii40OTUwNSIgc3Ryb2tlLXdpZHRoPSIuOTkwMTAiIGZpbGw9IiNlZWUiLz4KICA8dGV4dCBpZD0idGV4dDQ2ODYiIHN0eWxlPSJ3b3JkLXNwYWNpbmc6MHB4O2xldHRlci1zcGFjaW5nOjBweDt0ZXh0LWFuY2hvcjptaWRkbGU7dGV4dC1hbGlnbjpjZW50ZXIiIGZvbnQtd2VpZ2h0PSJib2xkIiB4bWw6c3BhY2U9InByZXNlcnZlIiBmb250LXNpemU9IjEwcHgiIGxpbmUtaGVpZ2h0PSIxMjUlIiB5PSI5NzAuNzI4MDkiIHg9IjQ5LjM5NjQ3NyIgZm9udC1mYW1pbHk9IlJvYm90byIgZmlsbD0iIzY2NjY2NiI+PHRzcGFuIGlkPSJ0c3BhbjQ2OTAiIHg9IjUwLjY0NjQ3NyIgeT0iOTcwLjcyODA5Ij5JbWFnZSBiYWNrZ3JvdW5kIDwvdHNwYW4+PHRzcGFuIGlkPSJ0c3BhbjQ2OTIiIHg9IjQ5LjM5NjQ3NyIgeT0iOTgzLjIyODA5Ij5pcyBub3QgY29uZmlndXJlZDwvdHNwYW4+PC90ZXh0PgogIDxyZWN0IGlkPSJyZWN0NDY5NCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgaGVpZ2h0PSIxOS4zNiIgd2lkdGg9IjY5LjM2IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgeT0iOTkyLjY4IiB4PSIxNS4zMiIgc3Ryb2tlLXdpZHRoPSIuNjM5ODYiIGZpbGw9Im5vbmUiLz4KIDwvZz4KPC9zdmc+Cg==\",\"labels\":[{\"pattern\":\"Value: ${#0:2} units.\",\"x\":20,\"y\":47,\"font\":{\"color\":\"#515151\",\"family\":\"Roboto\",\"size\":6,\"style\":\"normal\",\"weight\":\"500\"}}]},\"title\":\"Label widget\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Label widget' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'cards', 'simple_card',
'{"type":"latest","sizeX":5,"sizeY":3,"resources":[],"templateHtml":"","templateCss":"#container {\n    overflow: auto;\n}\n\n.tbDatasource-container {\n    width: 100%;\n    height: 100%;\n    overflow: hidden;\n}\n\n.tbDatasource-table {\n    width: 100%;\n    height: 100%;\n    border-collapse: collapse;\n    white-space: nowrap;\n    font-weight: 100;\n    text-align: right;\n}\n\n.tbDatasource-table td {\n    padding: 12px;\n    position: relative;\n    box-sizing: border-box;\n}\n\n.tbDatasource-data-key {\n    opacity: 0.7;\n    font-weight: 400;\n    font-size: 3.500rem;\n}\n\n.tbDatasource-value {\n    font-size: 5.000rem;\n}","controllerScript":"self.onInit = function() {\n    self.ctx.units = self.ctx.settings.units || self.ctx.units;\n    self.ctx.valueDec = (typeof self.ctx.settings.valueDec !== ''undefined'' && self.ctx.settings.valueDec !== null)\n                ? self.ctx.settings.valueDec : self.ctx.decimals;\n                \n    self.ctx.labelPosition = self.ctx.settings.labelPosition || ''left'';\n    \n    if (self.ctx.datasources.length > 0) {\n        var tbDatasource = self.ctx.datasources[0];\n        var datasourceId = ''tbDatasource'' + 0;\n        self.ctx.$container.append(\n            \"<div id=''\" + datasourceId +\n            \"'' class=''tbDatasource-container''></div>\"\n        );\n        \n        self.ctx.datasourceContainer = $(''#'' + datasourceId,\n            self.ctx.$container);\n        \n        var tableId = ''table'' + 0;\n        self.ctx.datasourceContainer.append(\n            \"<table id=''\" + tableId +\n            \"'' class=''tbDatasource-table''><col width=''30%''><col width=''70%''></table>\"\n        );\n        var table = $(''#'' + tableId, self.ctx.$container);\n        if (self.ctx.labelPosition === ''top'') {\n            table.css(''text-align'', ''left'');\n        }\n        \n        if (tbDatasource.dataKeys.length > 0) {\n            var dataKey = tbDatasource.dataKeys[0];\n            var labelCellId = ''labelCell'' + 0;\n            var cellId = ''cell'' + 0;\n            if (self.ctx.labelPosition === ''left'') {\n                table.append(\n                    \"<tr><td class=''tbDatasource-data-key'' id=''\" + labelCellId +\"''>\" +\n                    dataKey.label +\n                    \"</td><td class=''tbDatasource-value'' id=''\" +\n                    cellId +\n                    \"''></td></tr>\");\n            } else {\n                table.append(\n                    \"<tr style=''vertical-align: bottom;''><td class=''tbDatasource-data-key'' id=''\" + labelCellId +\"''>\" +\n                    dataKey.label +\n                    \"</td></tr><tr><td class=''tbDatasource-value'' id=''\" +\n                    cellId +\n                    \"''></td></tr>\");\n            }\n            self.ctx.labelCell = $(''#'' + labelCellId, table);\n            self.ctx.valueCell = $(''#'' + cellId, table);\n            self.ctx.valueCell.html(0 + '' '' + self.ctx.units);\n        }\n    }\n    \n    $.fn.textWidth = function(){\n        var html_org = $(this).html();\n        var html_calc = ''<span>'' + html_org + ''</span>'';\n        $(this).html(html_calc);\n        var width = $(this).find(''span:first'').width();\n        $(this).html(html_org);\n        return width;\n    };    \n    \n    self.onResize();\n}\n\nself.onDataUpdated = function() {\n    \n    function isNumber(n) {\n        return !isNaN(parseFloat(n)) && isFinite(n);\n    }\n    \n    function padValue(val, dec, int) {\n        var i = 0;\n        var s, strVal, n;\n    \n        val = parseFloat(val);\n        n = (val < 0);\n        val = Math.abs(val);\n    \n        if (dec > 0) {\n            strVal = val.toFixed(dec).toString().split(''.'');\n            s = int - strVal[0].length;\n    \n            for (; i < s; ++i) {\n                strVal[0] = ''0'' + strVal[0];\n            }\n    \n            strVal = (n ? ''-'' : '''') + strVal[0] + ''.'' + strVal[1];\n        }\n    \n        else {\n            strVal = Math.round(val).toString();\n            s = int - strVal.length;\n    \n            for (; i < s; ++i) {\n                strVal = ''0'' + strVal;\n            }\n    \n            strVal = (n ? ''-'' : '''') + strVal;\n        }\n    \n        return strVal;\n    }\n    \n    if (self.ctx.valueCell && self.ctx.data.length > 0) {\n        var cellData = self.ctx.data[0];\n        if (cellData.data.length > 0) {\n            var tvPair = cellData.data[cellData.data.length -\n                1];\n            var value = tvPair[1];\n            var txtValue;\n            if (isNumber(value)) {\n                txtValue = padValue(value, self.ctx.alueDec, 0) + '' '' + self.ctx.units;\n            } else {\n                txtValue = value;\n            }\n            self.ctx.valueCell.html(txtValue);\n            var targetWidth;\n            var minDelta;\n            if (self.ctx.labelPosition === ''left'') {\n                targetWidth = self.ctx.datasourceContainer.width() - self.ctx.labelCell.width();\n                minDelta = self.ctx.width/16 + self.ctx.padding;\n            } else {\n                targetWidth = self.ctx.datasourceContainer.width();\n                minDelta = self.ctx.padding;\n            }\n            var delta = targetWidth - self.ctx.valueCell.textWidth();\n            var fontSize = self.ctx.valueFontSize;\n            if (targetWidth > minDelta) {\n                while (delta < minDelta && fontSize > 6) {\n                    fontSize--;\n                    self.ctx.valueCell.css(''font-size'', fontSize+''px'');\n                    delta = targetWidth - self.ctx.valueCell.textWidth();\n                }\n            }\n        }\n    }    \n    \n}\n\nself.onResize = function() {\n    var labelFontSize;\n    if (self.ctx.labelPosition === ''top'') {\n        self.ctx.padding = self.ctx.height/20;\n        labelFontSize = self.ctx.height/4;\n        self.ctx.valueFontSize = self.ctx.height/2;\n    } else {\n        self.ctx.padding = self.ctx.width/50;\n        labelFontSize = self.ctx.height/2.5;\n        self.ctx.valueFontSize = height/2;\n        if (self.ctx.width/self.ctx.height <= 2.7) {\n            labelFontSize = self.ctx.width/7;\n            self.ctx.valueFontSize = self.ctx.width/6;\n        }\n    }\n    self.ctx.padding = Math.min(12, self.ctx.padding);\n    \n    if (self.ctx.labelCell) {\n        self.ctx.labelCell.css(''font-size'', labelFontSize+''px'');\n        self.ctx.labelCell.css(''padding'', self.ctx.padding+''px'');\n    }\n    if (self.ctx.valueCell) {\n        self.ctx.valueCell.css(''font-size'', self.ctx.valueFontSize+''px'');\n        self.ctx.valueCell.css(''padding'', self.ctx.padding+''px'');\n    }    \n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"properties\": {\n            \"labelPosition\": {\n                \"title\": \"Label position\",\n                \"type\": \"string\",\n                \"default\": \"left\"\n            }\n        },\n        \"required\": []\n    },\n    \"form\": [\n        {\n           \"key\": \"labelPosition\",\n           \"type\": \"rc-select\",\n           \"multiple\": false,\n           \"items\": [\n               {\n                   \"value\": \"left\",\n                   \"label\": \"Left\"\n               },\n               {\n                   \"value\": \"top\",\n                   \"label\": \"Top\"\n               }\n            ]\n        }\n    ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.2392660816082064,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ff5722\",\"color\":\"rgba(255, 255, 255, 0.87)\",\"padding\":\"16px\",\"settings\":{\"labelPosition\":\"top\"},\"title\":\"Simple card\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"units\":\"°C\",\"decimals\":0,\"useDashboardTimewindow\":true,\"showLegend\":false}"}',
'Simple card' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges', 'lcd_bar_gauge',
'{"type":"latest","sizeX":2,"sizeY":3.5,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#babab2\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\"linear\",\"refreshAnimationTime\":700,\"startAnimationType\":\"linear\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"400\",\"size\":16},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":1.5,\"decimals\":0,\"showUnitTitle\":true,\"defaultColor\":\"#444444\",\"gaugeType\":\"verticalBar\",\"units\":\"%\"},\"title\":\"LCD bar gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'LCD bar gauge' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges',
'vertical_bar_justgage',
'{"type":"latest","sizeX":2,"sizeY":3.5,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#f57c00\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#999999\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":12,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#666666\"},\"neonGlowBrightness\":0,\"decimals\":0,\"dashThickness\":1.5,\"gaugeColor\":\"#eeeeee\",\"showTitle\":false,\"gaugeType\":\"verticalBar\"},\"title\":\"Vertical bar - justGage\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Vertical bar - justGage' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'cards', 'html_value_card',
'{"type":"latest","sizeX":7.5,"sizeY":3,"resources":[],"templateHtml":"","templateCss":"","controllerScript":"self.onInit = function() {\n    self.ctx.varsRegex = /\\$\\{([^\\}]*)\\}/g;\n    self.ctx.htmlSet = false;\n    \n    var cssParser = new cssjs();\n    cssParser.testMode = false;\n    var namespace = ''html-value-card-'' + hashCode(self.ctx.settings.cardCss);\n    cssParser.cssPreviewNamespace = namespace;\n    cssParser.createStyleElement(namespace, self.ctx.settings.cardCss);\n    self.ctx.$container.addClass(namespace);\n    self.ctx.html = self.ctx.settings.cardHtml;\n    self.ctx.replaceInfo = processHtmlPattern(self.ctx.html, self.ctx.data);\n    \n    updateHtml();\n    \n    function hashCode(str) {\n        var hash = 0;\n        var i, char;\n        if (str.length === 0) return hash;\n        for (i = 0; i < str.length; i++) {\n            char = str.charCodeAt(i);\n            hash = ((hash << 5) - hash) + char;\n            hash = hash & hash;\n        }\n        return hash;\n    }\n    \n    function processHtmlPattern(pattern, data) {\n        var match = self.ctx.varsRegex.exec(pattern);\n        var replaceInfo = {};\n        replaceInfo.variables = [];\n        while (match !== null) {\n            var variableInfo = {};\n            variableInfo.dataKeyIndex = -1;\n            var variable = match[0];\n            var label = match[1];\n            var valDec = 2;\n            var splitVals = label.split('':'');\n            if (splitVals.length > 1) {\n                label = splitVals[0];\n                valDec = parseFloat(splitVals[1]);\n            }\n            variableInfo.variable = variable;\n            variableInfo.valDec = valDec;\n            \n            if (label.startsWith(''#'')) {\n                var keyIndexStr = label.substring(1);\n                var n = Math.floor(Number(keyIndexStr));\n                if (String(n) === keyIndexStr && n >= 0) {\n                    variableInfo.dataKeyIndex = n;\n                }\n            }\n            if (variableInfo.dataKeyIndex === -1) {\n                for (var i = 0; i < data.length; i++) {\n                     var datasourceData = data[i];\n                     var dataKey = datasourceData.dataKey;\n                     if (dataKey.label === label) {\n                         variableInfo.dataKeyIndex = i;\n                         break;\n                     }\n                }\n            }\n            replaceInfo.variables.push(variableInfo);\n            match = self.ctx.varsRegex.exec(pattern);\n        }\n        return replaceInfo;\n    }    \n}\n\nself.onDataUpdated = function() {\n    updateHtml();\n}\n\nself.onDestroy = function() {\n}\n\nfunction isNumber(n) {\n    return !isNaN(parseFloat(n)) && isFinite(n);\n}\n\nfunction padValue(val, dec, int) {\n    var i = 0;\n    var s, strVal, n;\n\n    val = parseFloat(val);\n    n = (val < 0);\n    val = Math.abs(val);\n\n    if (dec > 0) {\n        strVal = val.toFixed(dec).toString().split(''.'');\n        s = int - strVal[0].length;\n\n        for (; i < s; ++i) {\n            strVal[0] = ''0'' + strVal[0];\n        }\n\n        strVal = (n ? ''-'' : '''') + strVal[0] + ''.'' + strVal[1];\n    }\n\n    else {\n        strVal = Math.round(val).toString();\n        s = int - strVal.length;\n\n        for (; i < s; ++i) {\n            strVal = ''0'' + strVal;\n        }\n\n        strVal = (n ? ''-'' : '''') + strVal;\n    }\n\n    return strVal;\n}\n\nfunction updateHtml() {\n    var text = self.ctx.html;\n    var updated = false;\n    for (var v in self.ctx.replaceInfo.variables) {\n        var variableInfo = self.ctx.replaceInfo.variables[v];\n        var txtVal = '''';\n        if (variableInfo.dataKeyIndex > -1) {\n            var varData = self.ctx.data[variableInfo.dataKeyIndex].data;\n            if (varData.length > 0) {\n                var val = varData[varData.length-1][1];\n                if (isNumber(val)) {\n                    txtVal = padValue(val, variableInfo.valDec, 0);\n                } else {\n                    txtVal = val;\n                }\n            }\n        }\n        if (typeof variableInfo.lastVal === undefined ||\n            variableInfo.lastVal !== txtVal) {\n            updated = true;\n            variableInfo.lastVal = txtVal;\n        }\n        text = text.split(variableInfo.variable).join(txtVal);\n    }\n    if (updated || !self.ctx.htmlSet) {\n        self.ctx.$container.html(text);\n        if (!self.ctx.htmlSet) {\n            self.ctx.htmlSet = true;\n        }\n    }\n}\n\n","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"required\": [\"cardHtml\"],\n        \"properties\": {\n            \"cardCss\": {\n                \"title\": \"CSS\",\n                \"type\": \"string\",\n                \"default\": \".card {\\n font-weight: bold; \\n}\"\n            },\n            \"cardHtml\": {\n                \"title\": \"HTML\",\n                \"type\": \"string\",\n                \"default\": \"<div class=''card''>HTML code here</div>\"\n            }\n        }\n    },\n    \"form\": [\n        {\n            \"key\": \"cardCss\",\n            \"type\": \"css\"\n        },           \n        {\n            \"key\": \"cardHtml\",\n            \"type\": \"html\"\n        }    \n    ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"My value\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"return Math.random() * 5.45;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"cardCss\":\".card {\\n   width: 100%;\\n   height: 100%;\\n   border: 2px solid #ccc;\\n   box-sizing: border-box;\\n}\\n\\n.card .content {\\n   padding: 20px;\\n   display: flex;\\n   flex-direction: row;\\n   align-items: center;\\n   justify-content: space-around;\\n   height: 100%;\\n   box-sizing: border-box;\\n}\\n\\n.card .content .column {\\n   display: flex;\\n   flex-direction: column;    \\n   justify-content: space-around;\\n   height: 100%;\\n}\\n\\n.card h1 {\\n    text-transform: uppercase;\\n    color: #999;\\n    font-size: 20px;\\n    font-weight: bold;\\n    margin: 0;\\n    padding-bottom: 10px;\\n    line-height: 32px;\\n}\\n\\n.card .value {\\n    font-size: 38px;\\n    font-weight: 200;\\n}\\n\\n.card .description {\\n    font-size: 20px;\\n    color: #999;\\n}\\n\",\"cardHtml\":\"<div class=''card''>\\n    <div class=''content''>\\n        <div class=''column''>\\n            <h1>Value title</h1>\\n            <div class=''value''>\\n                ${My value:2} units.\\n            </div>    \\n            <div class=''description''>\\n                Value description text\\n            </div>\\n        </div>\\n        <img height=\\\"80px\\\" src=\\\"https://thingsboard.io/images/logo_small.png\\\" />\\n    </div>\\n</div>\"},\"title\":\"HTML Value Card\",\"dropShadow\":false}"}',
'HTML Value Card' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'gpio_widgets',
'raspberry_pi_gpio_panel',
'{"type":"latest","sizeX":7,"sizeY":10.5,"resources":[],"templateHtml":"<div class=\"gpio-panel\" style=\"height: 100%;\">\n    <section layout=\"row\" ng-repeat=\"row in rows\">\n        <section flex layout=\"row\" ng-repeat=\"cell in row\">\n            <section layout=\"row\" flex ng-if=\"cell\" layout-align=\"{{$index===0 ? ''end center'' : ''start center''}}\">\n                <span class=\"gpio-left-label\" ng-show=\"$index===0\">{{ cell.label }}</span>\n                <section layout=\"row\" class=\"led-panel\" ng-class=\"$index===0 ? ''col-0'' : ''col-1''\"\n                      ng-style=\"{backgroundColor: ledPanelBackgroundColor}\">\n                    <span class=\"pin\" ng-show=\"$index===0\">{{cell.pin}}</span>\n                    <span class=\"led-container\">\n                        <tb-led-light size=\"prefferedRowHeight\"\n                                      color-on=\"cell.colorOn\"\n                                      color-off=\"cell.colorOff\"\n                                      off-opacity=\"''0.9''\"\n                                      tb-enabled=\"cell.enabled\">\n                        </tb-led-light>\n                    </span>\n                    <span class=\"pin\" ng-show=\"$index===1\">{{cell.pin}}</span>\n                </section>\n                <span class=\"gpio-right-label\" ng-show=\"$index===1\">{{ cell.label }}</span>\n            </section>\n            <section layout=\"row\" flex ng-if=\"!cell\">\n                <span flex ng-show=\"$index===0\"></span>\n                <span class=\"led-panel\"\n                      ng-style=\"{backgroundColor: ledPanelBackgroundColor}\"></span>\n                <span flex ng-show=\"$index===1\"></span>\n            </section>\n        </section>\n    </section>                            \n</div>","templateCss":".error {\n    font-size: 14px !important;\n    color: maroon;/*rgb(250,250,250);*/\n    background-color: transparent;\n    padding: 6px;\n}\n\n.error span {\n    margin: auto;\n}\n\n.gpio-panel {\n    padding-top: 10px;\n    white-space: nowrap;\n}\n\n.gpio-panel tb-led-light > div {\n    margin: auto;\n}\n\n.led-panel {\n    margin: 0;\n    width: 66px;\n    min-width: 66px;\n}\n\n.led-container {\n    width: 48px;\n    min-width: 48px;\n}\n\n.pin {\n    margin-top: auto;\n    margin-bottom: auto;\n    color: white;\n    font-size: 12px;\n    width: 16px;\n    min-width: 16px;\n}\n\n.led-panel.col-0 .pin {\n    margin-left: auto;\n    padding-left: 2px;\n    text-align: right;\n}\n\n.led-panel.col-1 .pin {\n    margin-right: auto;\n    \n    text-align: left;\n}\n\n.gpio-left-label {\n    margin-right: 8px;\n}\n\n.gpio-right-label {\n    margin-left: 8px;\n}","controllerScript":"self.onInit = function() {\n    var i, gpio;\n    \n    var scope = self.ctx.$scope;\n    var settings = self.ctx.settings;\n    \n    scope.gpioList = [];\n    scope.gpioByPin = {};\n    for (var g = 0; g < settings.gpioList.length; g++) {\n        gpio = settings.gpioList[g];\n        scope.gpioList.push(\n            {\n                row: gpio.row,\n                col: gpio.col,\n                pin: gpio.pin,\n                label: gpio.label,\n                enabled: false,\n                colorOn: tinycolor(gpio.color).lighten(20).toHexString(),\n                colorOff: tinycolor(gpio.color).darken().toHexString()\n            }\n        );\n        scope.gpioByPin[gpio.pin] = scope.gpioList[scope.gpioList.length-1];\n    }\n\n    scope.ledPanelBackgroundColor = settings.ledPanelBackgroundColor || tinycolor(''green'').lighten(2).toRgbString();\n\n    scope.gpioCells = {};\n    var rowCount = 0;\n    for (i = 0; i < scope.gpioList.length; i++) {\n        gpio = scope.gpioList[i];\n        scope.gpioCells[gpio.row+''_''+gpio.col] = gpio;\n        rowCount = Math.max(rowCount, gpio.row+1);\n    }\n    \n    scope.prefferedRowHeight = 32;\n    scope.rows = [];\n    for (i = 0; i < rowCount; i++) {\n        var row = [];\n        for (var c =0; c<2;c++) {\n            if (scope.gpioCells[i+''_''+c]) {\n                row[c] = scope.gpioCells[i+''_''+c];\n            } else {\n                row[c] = null;\n            }\n        }\n        scope.rows.push(row);\n    }    \n    \n    self.onResize();\n}\n\nself.onDataUpdated = function() {\n    var changed = false;\n    for (var d = 0; d < self.ctx.data.length; d++) {\n        var cellData = self.ctx.data[d];\n        var dataKey = cellData.dataKey;\n        var gpio = self.ctx.$scope.gpioByPin[dataKey.label];\n        if (gpio) {\n            var enabled = false;\n            if (cellData.data.length > 0) {\n                var tvPair = cellData.data[cellData.data.length - 1];\n                enabled = (tvPair[1] === true || tvPair[1] === ''true'');\n            }\n            if (gpio.enabled != enabled) {\n                changed = true;\n                gpio.enabled = enabled;\n            }\n        }\n    }\n    if (changed) {\n        self.ctx.$scope.$digest();\n    }    \n}\n\nself.onResize = function() {\n    var rowCount = self.ctx.$scope.rows.length;\n    var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n    prefferedRowHeight = Math.min(32, prefferedRowHeight);\n    prefferedRowHeight = Math.max(12, prefferedRowHeight);\n    self.ctx.$scope.prefferedRowHeight = prefferedRowHeight;\n    \n    var ratio = prefferedRowHeight/32;\n    \n    var leftLabels = $(''.gpio-left-label'', self.ctx.$container);\n    leftLabels.css(''font-size'', 16*ratio+''px'');\n    var rightLabels = $(''.gpio-right-label'', self.ctx.$container);\n    rightLabels.css(''font-size'', 16*ratio+''px'');\n    var pins = $(''.pin'', self.ctx.$container);\n    var pinsFontSize = Math.max(9, 12*ratio);\n    pins.css(''font-size'', pinsFontSize+''px'');    \n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"properties\": {\n            \"gpioList\": {\n                \"title\": \"Gpio leds\",\n                \"type\": \"array\",\n                \"minItems\" : 1,\n                \"items\": {\n                    \"title\": \"Gpio led\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"pin\": {\n                            \"title\": \"Pin\",\n                            \"type\": \"number\"\n                        },\n                        \"label\": {\n                            \"title\": \"Label\",\n                            \"type\": \"string\"\n                        },\n                        \"row\": {\n                            \"title\": \"Row\",\n                            \"type\": \"number\"\n                        },\n                        \"col\": {\n                            \"title\": \"Column\",\n                            \"type\": \"number\"\n                        },\n                        \"color\": {\n                            \"title\": \"Color\",\n                            \"type\": \"string\",\n                            \"default\": \"red\"\n                        }\n                    },\n                    \"required\": [\"pin\", \"label\", \"row\", \"col\", \"color\"]\n                }\n            },\n            \"ledPanelBackgroundColor\": {\n                \"title\": \"LED panel background color\",\n                \"type\": \"string\",\n                \"default\": \"#008a00\"\n            } \n        },\n        \"required\": [\"gpioList\", \n                     \"ledPanelBackgroundColor\"]\n    },\n    \"form\": [\n        {\n            \"key\": \"gpioList\",\n            \"items\": [\n                \"gpioList[].pin\",\n                \"gpioList[].label\",\n                \"gpioList[].row\",\n                \"gpioList[].col\",\n                {\n                    \"key\": \"gpioList[].color\",\n                    \"type\": \"color\"\n                }\n            ]\n        },\n        {\n            \"key\": \"ledPanelBackgroundColor\",\n            \"type\": \"color\"\n        }\n    ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"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 Panel\",\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"7\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.22518255793320163,\"funcBody\":\"var period = time % 1500;\\nreturn period < 500;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"11\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.7008206860666621,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 500 && period < 1000;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"12\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.42600325102193426,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 1000;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"13\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.48362241571415243,\"funcBody\":\"var period = time % 1500;\\nreturn period < 500;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"29\",\"color\":\"#607d8b\",\"settings\":{},\"_hash\":0.7217670147518815,\"funcBody\":\"var period = time % 1500;\\nreturn period >= 500 && period < 1000;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}}}"}',
'Raspberry Pi GPIO Panel' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'charts', 'radar_chart_js',
'{"type":"latest","sizeX":7,"sizeY":5,"resources":[{"url":"https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"}],"templateHtml":"<canvas id=\"radarChart\"></canvas>\n","templateCss":"","controllerScript":"self.onInit = function() {\n    var barData = {\n        labels: [],\n        datasets: []\n    };\n\n    var backgroundColor = tinycolor(self.ctx.data[0].dataKey.color);\n    backgroundColor.setAlpha(0.2);\n    var borderColor = tinycolor(self.ctx.data[0].dataKey.color);\n    borderColor.setAlpha(1);\n    var dataset = {\n        label: self.ctx.datasources[0].name,\n        data: [],\n        backgroundColor: backgroundColor.toRgbString(),\n        borderColor: borderColor.toRgbString(),\n        pointBackgroundColor: borderColor.toRgbString(),\n        pointBorderColor: borderColor.darken().toRgbString(),\n        borderWidth: 1\n    }\n    \n    barData.datasets.push(dataset);\n    \n    for (var i = 0; i < self.ctx.data.length; i++) {\n        var dataKey = self.ctx.data[i].dataKey;\n        barData.labels.push(dataKey.label);\n        dataset.data.push(0);\n    }\n\n    var ctx = $(''#radarChart'', self.ctx.$container);\n    self.ctx.chart = new Chart(ctx, {\n        type: ''radar'',\n        data: barData,\n        options: {\n            responsive: false,\n            maintainAspectRatio: false\n        }\n    });\n    \n    self.onResize();\n}\n\nself.onDataUpdated = function() {\n    for (var i = 0; i < self.ctx.data.length; i++) {\n        var cellData = self.ctx.data[i];\n        if (cellData.data.length > 0) {\n             var tvPair = cellData.data[cellData.data.length - 1];\n             var value = tvPair[1];\n             self.ctx.chart.data.datasets[0].data[i] = parseFloat(value);\n        }\n    }    \n    self.ctx.chart.update();\n}\n\nself.onResize = function() {\n    if (self.ctx.height >= 70) {\n        self.ctx.chart.resize();\n    }\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.545701115289893,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.2592906835158064,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.12880275585455747,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Radar - Chart.js\"}"}',
'Radar - Chart.js' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges',
'neon_gauge_justgage',
'{"type":"latest","sizeX":5,"sizeY":3,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":70,\"dashThickness\":1,\"decimals\":1,\"gaugeType\":\"arc\"},\"title\":\"Neon gauge - justGage\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Neon gauge - justGage' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges',
'simple_gauge_justgage',
'{"type":"latest","sizeX":2,"sizeY":2,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>\n","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"\nself.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#ef6c00\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":0,\"decimals\":0,\"gaugeColor\":\"#eeeeee\",\"gaugeType\":\"donut\"},\"title\":\"Simple gauge - justGage\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Simple gauge - justGage' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'maps', 'route_map',
'{"type":"timeseries","sizeX":8.5,"sizeY":6,"resources":[],"templateHtml":"","templateCss":".error {\n    color: red;\n}\n.tb-labels {\n  color: #222;\n  font: 12px/1.5 \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n  text-align: center;\n  width: 100px;\n  white-space: nowrap;\n}","controllerScript":"self.onInit = function() {\n    self.ctx.map = new TbMapWidget(''google-map'', true, self.ctx);\n}\n\nself.onDataUpdated = function() {\n    self.ctx.map.update();\n}\n\nself.onResize = function() {\n    self.ctx.map.resize();\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{\n  \"schema\": {\n    \"title\": \"Route Map Configuration\",\n    \"type\": \"object\",\n    \"properties\": {\n      \"gmApiKey\": {\n        \"title\": \"Google Maps API Key\",\n        \"type\": \"string\"\n      },\n      \"gmDefaultMapType\": {\n          \"title\": \"Default map type\",\n          \"type\": \"string\",\n          \"default\": \"roadmap\"\n      },\n      \"defaultZoomLevel\": {\n         \"title\": \"Default map zoom level (1 - 20)\",\n         \"type\": \"number\"\n      },\n      \"fitMapBounds\": {\n          \"title\": \"Fit map bounds to cover all routes\",\n          \"type\": \"boolean\",\n          \"default\": true\n      },\n      \"routesSettings\": {\n            \"title\": \"Routes\",\n            \"type\": \"array\",\n            \"items\": {\n              \"title\": \"Route settings\",\n              \"type\": \"object\",\n              \"properties\": {\n                  \"latKeyName\": {\n                    \"title\": \"Latitude key name\",\n                    \"type\": \"string\",\n                    \"default\": \"lat\"\n                  },\n                  \"lngKeyName\": {\n                    \"title\": \"Longitude key name\",\n                    \"type\": \"string\",\n                    \"default\": \"lng\"\n                  },\n                  \"showLabel\": {\n                    \"title\": \"Show label\",\n                    \"type\": \"boolean\",\n                    \"default\": true\n                  },                  \n                  \"label\": {\n                    \"title\": \"Label\",\n                    \"type\": \"string\"\n                  },\n                  \"tooltipPattern\": {\n                    \"title\": \"Pattern ( for ex. ''Text ${keyName} units.'' or ''${#<key index>} units''  )\",\n                    \"type\": \"string\",\n                    \"default\": \"<b>Latitude:</b> ${lat:7}<br/><b>Longitude:</b> ${lng:7}\"\n                  },\n                  \"color\": {\n                    \"title\": \"Color\",\n                    \"type\": \"string\"\n                  },\n                  \"useColorFunction\": {\n                    \"title\": \"Use color function\",\n                    \"type\": \"boolean\",\n                    \"default\": false\n                  },\n                  \"colorFunction\": {\n                    \"title\": \"Color function: f(data)\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImage\": {\n                    \"title\": \"Custom marker image\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImageSize\": {\n                     \"title\": \"Custom marker image size (px)\",\n                     \"type\": \"number\",\n                     \"default\": 34\n                  },\n                  \"useMarkerImageFunction\": {\n                    \"title\": \"Use marker image function\",\n                    \"type\": \"boolean\",\n                    \"default\": false\n                  },\n                  \"markerImageFunction\": {\n                    \"title\": \"Marker image function: f(data, images)\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImages\": {\n                        \"title\": \"Marker images\",\n                        \"type\": \"array\",\n                        \"items\": {\n                          \"title\": \"Marker image\",\n                          \"type\": \"string\"\n                        }\n                  },\n                  \"strokeWeight\": {\n                    \"title\": \"Stroke weight\",\n                    \"type\": \"number\",\n                    \"default\": 2\n                  },\n                  \"strokeOpacity\": {\n                    \"title\": \"Stroke opacity\",\n                    \"type\": \"number\",\n                    \"default\": 1.0\n                  }\n              }\n            }\n      }\n    },\n    \"required\": [\n      \"gmApiKey\"\n    ]\n  },\n  \"form\": [\n    \"gmApiKey\",\n    {\n        \"key\": \"gmDefaultMapType\",\n        \"type\": \"rc-select\",\n        \"multiple\": false,\n        \"items\": [\n            {\n                \"value\": \"roadmap\",\n                \"label\": \"Roadmap\"\n            },\n            {\n                \"value\": \"satellite\",\n                \"label\": \"Satellite\"\n            },\n            {\n                \"value\": \"hybrid\",\n                \"label\": \"Hybrid\"\n            },\n            {\n                \"value\": \"terrain\",\n                \"label\": \"Terrain\"\n            }\n        ]\n    },    \n    \"defaultZoomLevel\",\n    \"fitMapBounds\",\n    {\n        \"key\": \"routesSettings\",\n        \"items\": [\n            \"routesSettings[].latKeyName\",\n            \"routesSettings[].lngKeyName\",\n            \"routesSettings[].showLabel\",\n            \"routesSettings[].label\",\n            \"routesSettings[].tooltipPattern\",\n            {\n                \"key\": \"routesSettings[].color\",\n                \"type\": \"color\"\n            },\n            \"routesSettings[].useColorFunction\",\n            {\n                \"key\": \"routesSettings[].colorFunction\",\n                \"type\": \"javascript\"\n            },\n            {\n                \"key\": \"routesSettings[].markerImage\",\n                \"type\": \"image\"\n            },\n            \"routesSettings[].markerImageSize\",\n            \"routesSettings[].useMarkerImageFunction\",\n            {\n                \"key\": \"routesSettings[].markerImageFunction\",\n                \"type\": \"javascript\"\n            },\n            {\n                \"key\": \"routesSettings[].markerImages\",\n                \"items\": [\n                    {\n                        \"key\": \"routesSettings[].markerImages[]\",\n                        \"type\": \"image\"\n                    }\n                ]\n            },\n            \"routesSettings[].strokeWeight\",\n            \"routesSettings[].strokeOpacity\"\n        ]\n    }\n  ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.3467277073670627,\"funcBody\":\"var lats = [37.7696499,\\n37.7699074,\\n37.7699536,\\n37.7697242,\\n37.7695189,\\n37.7696889,\\n37.7697153,\\n37.7701244,\\n37.7700604,\\n37.7705491,\\n37.7715705,\\n37.771752,\\n37.7707533,\\n37.769866];\\n\\nvar i = Math.floor((time/3 % 14000) / 1000);\\n\\nreturn lats[i];\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.058309787276281666,\"funcBody\":\"var lons = [-122.4261215,\\n-122.4219157,\\n-122.4199623,\\n-122.4179074,\\n-122.4155876,\\n-122.4155521,\\n-122.4163203,\\n-122.4193876,\\n-122.4210496,\\n-122.422284,\\n-122.4232717,\\n-122.4235138,\\n-122.4247605,\\n-122.4258812];\\n\\nvar i = Math.floor((time/3 % 14000) / 1000);\\n\\nreturn lons[i];\"}],\"intervalSec\":60},{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.14288960550237473,\"funcBody\":\"var value = prevValue;\\nif (time % 500 < 100) {\\n    value = value + Math.random() * 40 - 20;\\n    if (value < 45) {\\n    \\tvalue = 45;\\n    } else if (value > 130) {\\n    \\tvalue = 130;\\n    }\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":30000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"gmApiKey\":\"AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q\",\"fitMapBounds\":true,\"routesSettings\":[{\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"color\":\"#1976d2\",\"strokeWeight\":4,\"strokeOpacity\":0.65,\"label\":\"First route\",\"tooltipPattern\":\"<b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><b>Speed:</b> ${Speed} MPH<br/><small>See advanced settings for details</small>\",\"useColorFunction\":true,\"markerImageSize\":34,\"useMarkerImageFunction\":true,\"markerImageFunction\":\"var speed = data[''Speed''];\\nvar res = {\\n    url: images[0],\\n    size: 55\\n};\\nif (typeof speed !== undefined) {\\n    var percent = (speed - 45)/85;\\n    var index = Math.floor(3 * percent);\\n    res.url = images[index];\\n}\\nreturn res;\",\"markerImages\":[\"data:image/png;base64,[encoded data, 17264 characters]\",\"data:image/png;base64,[encoded data, 16628 characters]\",\"data:image/png;base64,[encoded data, 17120 characters]\"],\"colorFunction\":\"var speed = data[''Speed''];\\nif (typeof speed !== undefined) {\\n    var percent = (speed - 45)/85;\\n    if (percent < 0.5) {\\n        percent *=2*100; \\n        return tinycolor.mix(''green'', ''yellow'', amount = percent).toHexString();\\n    } else {\\n        percent = (percent - 0.5)*2*100;\\n        return tinycolor.mix(''yellow'', ''red'', amount = percent).toHexString();\\n    }\\n}\\nreturn ''green'';\"}]},\"title\":\"Route Map\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false}"}',
'Route Map' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'analogue_gauges',
'temperature_gauge_canvas_gauges',
'{"type":"latest","sizeX":7,"sizeY":3,"resources":[],"templateHtml":"<canvas id=\"linearGauge\"></canvas>\n","templateCss":"","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbAnalogueLinearGauge(self.ctx, ''linearGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.getSettingsSchema = function() {\n    return TbAnalogueLinearGauge.settingsSchema;\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 30 - 15;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":100,\"defaultColor\":\"#e64a19\",\"barStrokeWidth\":2.5,\"colorBar\":\"rgba(255, 255, 255, 0.4)\",\"colorBarEnd\":\"rgba(221, 221, 221, 0.38)\",\"showUnitTitle\":true,\"minorTicks\":2,\"valueBox\":true,\"valueInt\":3,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"colorNeedleShadowUp\":\"rgba(2,255,255,0.2)\",\"colorNeedleShadowDown\":\"rgba(188,143,143,0.45)\",\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\",\"highlightsWidth\":10,\"animation\":true,\"animationDuration\":1500,\"animationRule\":\"linear\",\"showBorder\":false,\"majorTicksCount\":8,\"numbersFont\":{\"family\":\"Arial\",\"size\":18,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#263238\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#78909c\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":26,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#37474f\"},\"valueFont\":{\"family\":\"Roboto\",\"size\":40,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#444\",\"shadowColor\":\"rgba(0,0,0,0.3)\"},\"minValue\":-60,\"highlights\":[{\"from\":-60,\"to\":-40,\"color\":\"#90caf9\"},{\"from\":-40,\"to\":-20,\"color\":\"rgba(144, 202, 249, 0.66)\"},{\"from\":-20,\"to\":0,\"color\":\"rgba(144, 202, 249, 0.33)\"},{\"from\":0,\"to\":20,\"color\":\"rgba(244, 67, 54, 0.2)\"},{\"from\":20,\"to\":40,\"color\":\"rgba(244, 67, 54, 0.4)\"},{\"from\":40,\"to\":60,\"color\":\"rgba(244, 67, 54, 0.6)\"},{\"from\":60,\"to\":80,\"color\":\"rgba(244, 67, 54, 0.8)\"},{\"from\":80,\"to\":100,\"color\":\"#f44336\"}],\"unitTitle\":\"Temperature\",\"units\":\"°C\",\"colorBarProgress\":\"#90caf9\",\"colorBarProgressEnd\":\"#f44336\",\"colorBarStroke\":\"#b0bec5\",\"valueDec\":1},\"title\":\"Temperature gauge - Canvas Gauges\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Temperature gauge - Canvas Gauges' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'maps', 'google_maps',
'{"type":"latest","sizeX":8.5,"sizeY":6,"resources":[],"templateHtml":"","templateCss":".error {\n    color: red;\n}\n.tb-labels {\n  color: #222;\n  font: 12px/1.5 \"Helvetica Neue\", Arial, Helvetica, sans-serif;\n  text-align: center;\n  width: 100px;\n  white-space: nowrap;\n}","controllerScript":"self.onInit = function() {\n    self.ctx.map = new TbMapWidget(''google-map'', false, self.ctx);\n}\n\nself.onDataUpdated = function() {\n    self.ctx.map.update();\n}\n\nself.onResize = function() {\n    self.ctx.map.resize();\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{\n  \"schema\": {\n    \"title\": \"Google Map Configuration\",\n    \"type\": \"object\",\n    \"properties\": {\n      \"gmApiKey\": {\n        \"title\": \"Google Maps API Key\",\n        \"type\": \"string\"\n      },\n      \"gmDefaultMapType\": {\n          \"title\": \"Default map type\",\n          \"type\": \"string\",\n          \"default\": \"roadmap\"\n      },\n      \"defaultZoomLevel\": {\n         \"title\": \"Default map zoom level (1 - 20)\",\n         \"type\": \"number\"\n      },\n      \"fitMapBounds\": {\n          \"title\": \"Fit map bounds to cover all markers\",\n          \"type\": \"boolean\",\n          \"default\": true\n      },\n      \"markersSettings\": {\n            \"title\": \"Markers\",\n            \"type\": \"array\",\n            \"items\": {\n              \"title\": \"Marker settings\",\n              \"type\": \"object\",\n              \"properties\": {\n                  \"latKeyName\": {\n                    \"title\": \"Latitude key name\",\n                    \"type\": \"string\",\n                    \"default\": \"lat\"\n                  },\n                  \"lngKeyName\": {\n                    \"title\": \"Longitude key name\",\n                    \"type\": \"string\",\n                    \"default\": \"lng\"\n                  },                  \n                  \"showLabel\": {\n                    \"title\": \"Show label\",\n                    \"type\": \"boolean\",\n                    \"default\": true\n                  },                  \n                  \"label\": {\n                    \"title\": \"Label\",\n                    \"type\": \"string\"\n                  },\n                  \"tooltipPattern\": {\n                    \"title\": \"Pattern ( for ex. ''Text ${keyName} units.'' or ''${#<key index>} units''  )\",\n                    \"type\": \"string\",\n                    \"default\": \"<b>Latitude:</b> ${lat:7}<br/><b>Longitude:</b> ${lng:7}\"\n                  },\n                  \"color\": {\n                    \"title\": \"Color\",\n                    \"type\": \"string\"\n                  },\n                  \"useColorFunction\": {\n                    \"title\": \"Use color function\",\n                    \"type\": \"boolean\",\n                    \"default\": false\n                  },\n                  \"colorFunction\": {\n                    \"title\": \"Color function: f(data)\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImage\": {\n                    \"title\": \"Custom marker image\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImageSize\": {\n                     \"title\": \"Custom marker image size (px)\",\n                     \"type\": \"number\",\n                     \"default\": 34\n                  },\n                  \"useMarkerImageFunction\": {\n                    \"title\": \"Use marker image function\",\n                    \"type\": \"boolean\",\n                    \"default\": false\n                  },\n                  \"markerImageFunction\": {\n                    \"title\": \"Marker image function: f(data, images)\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImages\": {\n                        \"title\": \"Marker images\",\n                        \"type\": \"array\",\n                        \"items\": {\n                          \"title\": \"Marker image\",\n                          \"type\": \"string\"\n                        }\n                  }\n              }\n            }\n      }\n    },\n    \"required\": [\n      \"gmApiKey\"\n    ]\n  },\n  \"form\": [\n    \"gmApiKey\",\n    {\n        \"key\": \"gmDefaultMapType\",\n        \"type\": \"rc-select\",\n        \"multiple\": false,\n        \"items\": [\n            {\n                \"value\": \"roadmap\",\n                \"label\": \"Roadmap\"\n            },\n            {\n                \"value\": \"satellite\",\n                \"label\": \"Satellite\"\n            },\n            {\n                \"value\": \"hybrid\",\n                \"label\": \"Hybrid\"\n            },\n            {\n                \"value\": \"terrain\",\n                \"label\": \"Terrain\"\n            }\n        ]\n    },\n    \"defaultZoomLevel\",\n    \"fitMapBounds\",\n    {\n        \"key\": \"markersSettings\",\n        \"items\": [\n            \"markersSettings[].latKeyName\",\n            \"markersSettings[].lngKeyName\",\n            \"markersSettings[].showLabel\",\n            \"markersSettings[].label\",\n            \"markersSettings[].tooltipPattern\",\n            {\n                \"key\": \"markersSettings[].color\",\n                \"type\": \"color\"\n            },\n            \"markersSettings[].useColorFunction\",\n            {\n                \"key\": \"markersSettings[].colorFunction\",\n                \"type\": \"javascript\"\n            },\n            {\n                \"key\": \"markersSettings[].markerImage\",\n                \"type\": \"image\"\n            },\n            \"markersSettings[].markerImageSize\",\n            \"markersSettings[].useMarkerImageFunction\",\n            {\n                \"key\": \"markersSettings[].markerImageFunction\",\n                \"type\": \"javascript\"\n            },\n            {\n                \"key\": \"markersSettings[].markerImages\",\n                \"items\": [\n                    {\n                        \"key\": \"markersSettings[].markerImages[]\",\n                        \"type\": \"image\"\n                    }\n                ]\n            }\n        ]\n    }\n  ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.05427416942713381,\"funcBody\":\"var value = prevValue || 15.833293;\\nif (time % 5000 < 500) {\\n    value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.680594833308841,\"funcBody\":\"var value = prevValue || -90.454350;\\nif (time % 5000 < 500) {\\n    value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]},{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"lat\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.05012157428742059,\"funcBody\":\"var value = prevValue || 14.450463;\\nif (time % 4000 < 500) {\\n    value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"lng\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.6742359401617628,\"funcBody\":\"var value = prevValue || -84.845334;\\nif (time % 4000 < 500) {\\n    value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]},{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"temperature\",\"color\":\"#607d8b\",\"settings\":{},\"_hash\":0.799863043034289,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"gmApiKey\":\"AIzaSyDoEx2kaGz3PxwbI9T7ccTSg5xjdw8Nw8Q\",\"markersSettings\":[{\"label\":\"First point\",\"color\":\"#1e88e5\",\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"tooltipPattern\":\"<b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><b>Temperature:</b> ${temperature} °C<br/><small>See advanced settings for details</small>\",\"useColorFunction\":true,\"colorFunction\":\"var temperature = data[''temperature''];\\nif (typeof temperature !== undefined) {\\n    var percent = (temperature + 60)/120 * 100;\\n    return tinycolor.mix(''blue'', ''red'', amount = percent).toHexString();\\n}\\nreturn ''blue'';\",\"markerImages\":[],\"useMarkerImageFunction\":false},{\"label\":\"Second point\",\"color\":\"#fdd835\",\"latKeyName\":\"lat\",\"lngKeyName\":\"lng\",\"showLabel\":true,\"tooltipPattern\":\"<b>Latitude:</b> ${lat:7}<br/><b>Longitude:</b> ${lng:7}<br/><b>Temperature:</b> ${temperature} °C<br/><small>See advanced settings for details</small>\",\"markerImageSize\":34,\"markerImages\":[\"data:image/png;base64,[encoded data, 4316 characters]\",\"data:image/png;base64,[encoded data, 4932 characters]\",\"data:image/png;base64,[encoded data, 4468 characters]\",\"data:image/png;base64,[encoded data, 4376 characters]\"],\"useMarkerImageFunction\":true,\"markerImageFunction\":\"var res = {\\n    url: images[0],\\n    size: 40\\n}\\nvar temperature = data[''temperature''];\\nif (typeof temperature !== undefined) {\\n    var percent = (temperature + 60)/120;\\n    var index = Math.floor(4 * percent);\\n    res.url = images[index];\\n}\\nreturn res;\",\"useColorFunction\":false}],\"fitMapBounds\":true,\"gmDefaultMapType\":\"roadmap\"},\"title\":\"Google Maps\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"useDashboardTimewindow\":true,\"showLegend\":false}"}',
'Google Maps' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'analogue_gauges',
'temperature_radial_gauge_canvas_gauges',
'{"type":"latest","sizeX":6,"sizeY":5,"resources":[],"templateHtml":"<canvas id=\"radialGauge\"></canvas>\n","templateCss":"","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbAnalogueRadialGauge(self.ctx, ''radialGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.getSettingsSchema = function() {\n    return TbAnalogueRadialGauge.settingsSchema;\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":60,\"startAngle\":67.5,\"ticksAngle\":225,\"showBorder\":true,\"defaultColor\":\"#e65100\",\"needleCircleSize\":7,\"highlights\":[{\"from\":-60,\"to\":-50,\"color\":\"#42a5f5\"},{\"from\":-50,\"to\":-40,\"color\":\"rgba(66, 165, 245, 0.83)\"},{\"from\":-40,\"to\":-30,\"color\":\"rgba(66, 165, 245, 0.66)\"},{\"from\":-30,\"to\":-20,\"color\":\"rgba(66, 165, 245, 0.5)\"},{\"from\":-20,\"to\":-10,\"color\":\"rgba(66, 165, 245, 0.33)\"},{\"from\":-10,\"to\":0,\"color\":\"rgba(66, 165, 245, 0.16)\"},{\"from\":0,\"to\":10,\"color\":\"rgba(229, 115, 115, 0.16)\"},{\"from\":10,\"to\":20,\"color\":\"rgba(229, 115, 115, 0.33)\"},{\"from\":20,\"to\":30,\"color\":\"rgba(229, 115, 115, 0.5)\"},{\"from\":30,\"to\":40,\"color\":\"rgba(229, 115, 115, 0.66)\"},{\"from\":40,\"to\":50,\"color\":\"rgba(229, 115, 115, 0.83)\"},{\"from\":50,\"to\":60,\"color\":\"#e57373\"}],\"showUnitTitle\":true,\"colorPlate\":\"#cfd8dc\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":2,\"valueInt\":3,\"valueDec\":1,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":1000,\"animationRule\":\"bounce\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"colorNeedleShadowDown\":\"rgba(188, 143, 143, 0.78)\",\"units\":\"°C\",\"majorTicksCount\":12,\"numbersFont\":{\"family\":\"Roboto\",\"size\":20,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#263238\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"normal\",\"color\":\"#263238\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":28,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"size\":30,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\"},\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\",\"unitTitle\":\"Temperature\",\"minValue\":-60},\"title\":\"Temperature radial gauge - Canvas Gauges\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Temperature radial gauge - Canvas Gauges' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'cards', 'attributes_card',
'{"type":"latest","sizeX":7.5,"sizeY":3,"resources":[],"templateHtml":"","templateCss":"#container {\n    overflow: auto;\n}\n\n.tbDatasource-container {\n    margin: 5px;\n    padding: 8px;\n}\n\n.tbDatasource-title {\n    font-size: 1.200rem;\n    font-weight: 500;\n    padding-bottom: 10px;\n}\n\n.tbDatasource-table {\n    width: 100%;\n    box-shadow: 0 0 10px #ccc;\n    border-collapse: collapse;\n    white-space: nowrap;\n    font-size: 1.000rem;\n    color: #757575;\n}\n\n.tbDatasource-table td {\n    position: relative;\n    border-top: 1px solid rgba(0, 0, 0, 0.12);\n    border-bottom: 1px solid rgba(0, 0, 0, 0.12);\n    padding: 0px 18px;\n    box-sizing: border-box;\n}","controllerScript":"self.onInit = function() {\n    \n    self.ctx.datasourceTitleCells = [];\n    self.ctx.valueCells = [];\n    self.ctx.labelCells = [];\n    \n    for (var i=0; i < self.ctx.datasources.length; i++) {\n        var tbDatasource = self.ctx.datasources[i];\n\n        var datasourceId = ''tbDatasource'' + i;\n        self.ctx.$container.append(\n            \"<div id=''\" + datasourceId +\n            \"'' class=''tbDatasource-container''></div>\"\n        );\n\n        var datasourceContainer = $(''#'' + datasourceId,\n            self.ctx.$container);\n\n        datasourceContainer.append(\n            \"<div class=''tbDatasource-title''>\" +\n            tbDatasource.name + \"</div>\"\n        );\n        \n        var datasourceTitleCell = $(''.tbDatasource-title'', datasourceContainer);\n        self.ctx.datasourceTitleCells.push(datasourceTitleCell);\n        \n        var tableId = ''table'' + i;\n        datasourceContainer.append(\n            \"<table id=''\" + tableId +\n            \"'' class=''tbDatasource-table''><col width=''30%''><col width=''70%''></table>\"\n        );\n        var table = $(''#'' + tableId, self.ctx.$container);\n\n        for (var a = 0; a < tbDatasource.dataKeys.length; a++) {\n            var dataKey = tbDatasource.dataKeys[a];\n            var labelCellId = ''labelCell'' + a;\n            var cellId = ''cell'' + a;\n            table.append(\"<tr><td id=''\" + labelCellId + \"''>\" + dataKey.label +\n                \"</td><td id=''\" + cellId +\n                \"''></td></tr>\");\n            var labelCell = $(''#'' + labelCellId, table);\n            self.ctx.labelCells.push(labelCell);\n            var valueCell = $(''#'' + cellId, table);\n            self.ctx.valueCells.push(valueCell);\n        }\n    }    \n    \n    self.onResize();\n}\n\nself.onDataUpdated = function() {\n    for (var i = 0; i < self.ctx.valueCells.length; i++) {\n        var cellData = self.ctx.data[i];\n        if (cellData && cellData.data && cellData.data.length > 0) {\n            var tvPair = cellData.data[cellData.data.length -\n                1];\n            var value = tvPair[1];\n            self.ctx.valueCells[i].html(value);\n        }\n    }    \n}\n\nself.onResize = function() {\n    var datasoirceTitleFontSize = self.ctx.height/8;\n    if (self.ctx.width/self.ctx.height <= 1.5) {\n        datasoirceTitleFontSize = self.ctx.width/12;\n    }\n    datasoirceTitleFontSize = Math.min(datasoirceTitleFontSize, 20);\n    for (var i = 0; i < self.ctx.datasourceTitleCells.length; i++) {\n        self.ctx.datasourceTitleCells[i].css(''font-size'', datasoirceTitleFontSize+''px'');\n    }\n    var valueFontSize = self.ctx.height/9;\n    var labelFontSize = self.ctx.height/9;\n    if (self.ctx.width/self.ctx.height <= 1.5) {\n        valueFontSize = self.ctx.width/15;\n        labelFontSize = self.ctx.width/15;\n    }\n    valueFontSize = Math.min(valueFontSize, 18);\n    labelFontSize = Math.min(labelFontSize, 18);\n\n    for (i = 0; i < self.ctx.valueCells; i++) {\n        self.ctx.valueCells[i].css(''font-size'', valueFontSize+''px'');\n        self.ctx.valueCells[i].css(''height'', valueFontSize*2.5+''px'');\n        self.ctx.valueCells[i].css(''padding'', ''0px '' + valueFontSize + ''px'');\n        self.ctx.labelCells[i].css(''font-size'', labelFontSize+''px'');\n        self.ctx.labelCells[i].css(''height'', labelFontSize*2.5+''px'');\n        self.ctx.labelCells[i].css(''padding'', ''0px '' + labelFontSize + ''px'');\n    }    \n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Random\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{},\"title\":\"Attributes card\"}"}',
'Attributes card' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges',
'digital_thermometer',
'{"type":"latest","sizeX":3,"sizeY":3,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < -60) {\\n\\tvalue = 60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#000000\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":60,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":1,\"levelColors\":[\"#304ffe\",\"#7e57c2\",\"#ff4081\",\"#d32f2f\"],\"refreshAnimationType\":\"<>\",\"refreshAnimationTime\":700,\"startAnimationType\":\"<>\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"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\":-60,\"units\":\"°C\",\"gaugeColor\":\"#333333\",\"neonGlowBrightness\":35,\"gaugeType\":\"donut\"},\"title\":\"Digital thermometer\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Digital thermometer' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'gpio_widgets',
'raspberry_pi_gpio_control',
'{"type":"rpc","sizeX":6,"sizeY":10.5,"resources":[],"templateHtml":"<fieldset class=\"gpio-panel\" ng-disabled=\"!rpcEnabled || executingRpcRequest\" style=\"height: 100%;\">\n    <section class=\"gpio-row\" layout=\"row\" ng-repeat=\"row in rows track by $index\" \n            ng-style=\"{''height'': prefferedRowHeight+''px''}\">\n        <section flex layout=\"row\" ng-repeat=\"cell in row track by $index\">\n            <section layout=\"row\" flex ng-if=\"cell\" layout-align=\"{{$index===0 ? ''end center'' : ''start center''}}\">\n                <span class=\"gpio-left-label\" ng-show=\"$index===0\">{{ cell.label }}</span>\n                <section layout=\"row\" class=\"switch-panel\" layout-align=\"start center\" ng-class=\"$index===0 ? ''col-0'' : ''col-1''\"\n                      ng-style=\"{''height'': prefferedRowHeight+''px'', ''backgroundColor'': ''{{ switchPanelBackgroundColor }}''}\">\n                    <span class=\"pin\" ng-show=\"$index===0\">{{cell.pin}}</span>\n                    <span flex ng-show=\"$index===1\"></span>\n                    <md-switch\n                        aria-label=\"{{ cell.label }}\"\n                        ng-disabled=\"!rpcEnabled || executingRpcRequest\"\n                        ng-model=\"cell.enabled\" \n                        ng-change=\"cell.enabled = !cell.enabled\" \n                        ng-click=\"gpioClick($event, cell)\">\n                    </md-switch>\n                    <span flex ng-show=\"$index===0\"></span>\n                    <span class=\"pin\" ng-show=\"$index===1\">{{cell.pin}}</span>\n                </section>\n                <span class=\"gpio-right-label\" ng-show=\"$index===1\">{{ cell.label }}</span>\n            </section>\n            <section layout=\"row\" flex ng-if=\"!cell\">\n                <span flex ng-show=\"$index===0\"></span>\n                <span class=\"switch-panel\"\n                      ng-style=\"{''height'': prefferedRowHeight+''px'', ''backgroundColor'': ''{{ switchPanelBackgroundColor }}''}\"></span>\n                <span flex ng-show=\"$index===1\"></span>\n            </section>\n        </section>\n    </section>                            \n    <span class=\"error\" style=\"position: absolute; bottom: 5px;\" ng-show=\"rpcErrorText\">{{rpcErrorText}}</span>\n    <md-progress-linear ng-show=\"executingRpcRequest\" style=\"position: absolute; bottom: 0;\" md-mode=\"indeterminate\"></md-progress-linear>    \n</fieldset>","templateCss":".error {\n    font-size: 14px !important;\n    color: maroon;/*rgb(250,250,250);*/\n    background-color: transparent;\n    padding: 6px;\n}\n\n.error span {\n    margin: auto;\n}\n\n.gpio-panel {\n    padding-top: 10px;\n    white-space: nowrap;\n}\n\n.switch-panel {\n    margin: 0;\n    height: 32px;\n    width: 66px;\n    min-width: 66px;\n}\n\n.switch-panel md-switch {\n    margin: 0;\n    width: 36px;\n    min-width: 36px;\n}\n\n.switch-panel md-switch > div.md-container {\n    margin: 0;\n}\n\n.switch-panel.col-0 md-switch {\n    margin-left: 8px;\n    margin-right: 4px;\n}\n\n.switch-panel.col-1 md-switch {\n    margin-left: 4px;\n    margin-right: 8px;\n}\n\n.gpio-row {\n    height: 32px;\n}\n\n.pin {\n    margin-top: auto;\n    margin-bottom: auto;\n    color: white;\n    font-size: 12px;\n    width: 16px;\n    min-width: 16px;\n}\n\n.switch-panel.col-0 .pin {\n    margin-left: auto;\n    padding-left: 2px;\n    text-align: right;\n}\n\n.switch-panel.col-1 .pin {\n    margin-right: auto;\n    \n    text-align: left;\n}\n\n.gpio-left-label {\n    margin-right: 8px;\n}\n\n.gpio-right-label {\n    margin-left: 8px;\n}","controllerScript":"self.onInit = function() {\n    \n    var i, gpio;\n    var scope = self.ctx.$scope;\n    var settings = self.ctx.settings;\n    scope.gpioList = [];\n    for (var g = 0; g < settings.gpioList.length; g++) {\n        gpio = settings.gpioList[g];\n        scope.gpioList.push(\n            {\n                row: gpio.row,\n                col: gpio.col,\n                pin: gpio.pin,\n                label: gpio.label,\n                enabled: false\n            }\n        );\n    }\n\n    scope.requestTimeout = settings.requestTimeout || 1000;\n\n    scope.switchPanelBackgroundColor = settings.switchPanelBackgroundColor || tinycolor(''green'').lighten(2).toRgbString();\n\n    scope.gpioStatusRequest = {\n        method: \"getGpioStatus\",\n        paramsBody: \"{}\"\n    };\n    \n    if (settings.gpioStatusRequest) {\n        scope.gpioStatusRequest.method = settings.gpioStatusRequest.method || scope.gpioStatusRequest.method;\n        scope.gpioStatusRequest.paramsBody = settings.gpioStatusRequest.paramsBody || scope.gpioStatusRequest.paramsBody;\n    }\n    \n    scope.gpioStatusChangeRequest = {\n        method: \"setGpioStatus\",\n        paramsBody: \"{\\n   \\\"pin\\\": \\\"{$pin}\\\",\\n   \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n    };\n    \n    if (settings.gpioStatusChangeRequest) {\n        scope.gpioStatusChangeRequest.method = settings.gpioStatusChangeRequest.method || scope.gpioStatusChangeRequest.method;\n        scope.gpioStatusChangeRequest.paramsBody = settings.gpioStatusChangeRequest.paramsBody || scope.gpioStatusChangeRequest.paramsBody;\n    }\n    \n    scope.parseGpioStatusFunction = \"return body[pin] === true;\";\n    \n    if (settings.parseGpioStatusFunction && settings.parseGpioStatusFunction.length > 0) {\n        scope.parseGpioStatusFunction = settings.parseGpioStatusFunction;\n    }\n    \n    scope.parseGpioStatusFunction = new Function(\"body, pin\", scope.parseGpioStatusFunction);\n    \n    function requestGpioStatus() {\n        self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusRequest.method, \n                            scope.gpioStatusRequest.paramsBody, \n                            scope.requestTimeout)\n            .then(\n                function success(responseBody) {\n                    for (var g = 0; g < scope.gpioList.length; g++) {\n                        var gpio = scope.gpioList[g];\n                        var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n                        gpio.enabled = enabled;                        \n                    }\n                }\n            );\n    }\n    \n    function changeGpioStatus(gpio) {\n        var pin = gpio.pin + '''';\n        var enabled = !gpio.enabled;\n        enabled = enabled === true ? ''true'' : ''false'';\n        var paramsBody = scope.gpioStatusChangeRequest.paramsBody;\n        var requestBody = JSON.parse(paramsBody.replace(\"\\\"{$pin}\\\"\", pin).replace(\"\\\"{$enabled}\\\"\", enabled));\n        self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusChangeRequest.method, \n                                    requestBody, scope.requestTimeout)\n                    .then(\n                        function success(responseBody) {\n                            var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n                            gpio.enabled = enabled;\n                        }\n                    );\n    }\n    \n    scope.gpioCells = {};\n    var rowCount = 0;\n    for (i = 0; i < scope.gpioList.length; i++) {\n        gpio = scope.gpioList[i];\n        scope.gpioCells[gpio.row+''_''+gpio.col] = gpio;\n        rowCount = Math.max(rowCount, gpio.row+1);\n    }\n    \n    scope.prefferedRowHeight = 32;\n    scope.rows = [];\n    for (i = 0; i < rowCount; i++) {\n        var row = [];\n        for (var c =0; c<2;c++) {\n            if (scope.gpioCells[i+''_''+c]) {\n                row[c] = scope.gpioCells[i+''_''+c];\n            } else {\n                row[c] = null;\n            }\n        }\n        scope.rows.push(row);\n    }\n\n    scope.gpioClick = function($event, gpio) {\n        changeGpioStatus(gpio);\n    };\n\n    requestGpioStatus();    \n    \n    self.onResize();\n}\n\nself.onResize = function() {\n    var scope = self.ctx.$scope;\n    var rowCount = scope.rows.length;\n    var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n    prefferedRowHeight = Math.min(32, prefferedRowHeight);\n    prefferedRowHeight = Math.max(12, prefferedRowHeight);\n    scope.prefferedRowHeight = prefferedRowHeight;\n    var ratio = prefferedRowHeight/32;\n    var switches = $(''md-switch'', self.ctx.$container);\n    switches.css(''height'', 30*ratio+''px'');\n    switches.css(''width'', 36*ratio+''px'');\n    switches.css(''min-width'', 36*ratio+''px'');\n    $(''.md-container'', switches).css(''height'', 24*ratio+''px'');\n    $(''.md-container'', switches).css(''width'', 36*ratio+''px'');\n    var bars = $(''.md-bar'', self.ctx.$container);\n    bars.css(''height'', 14*ratio+''px'');\n    bars.css(''width'', 34*ratio+''px'');\n    var thumbs = $(''.md-thumb'', self.ctx.$container);\n    thumbs.css(''height'', 20*ratio+''px'');\n    thumbs.css(''width'', 20*ratio+''px'');\n    \n    var leftLabels = $(''.gpio-left-label'', self.ctx.$container);\n    leftLabels.css(''font-size'', 16*ratio+''px'');\n    var rightLabels = $(''.gpio-right-label'', self.ctx.$container);\n    rightLabels.css(''font-size'', 16*ratio+''px'');\n    var pins = $(''.pin'', self.ctx.$container);\n    var pinsFontSize = Math.max(9, 12*ratio);\n    pins.css(''font-size'', pinsFontSize+''px'');    \n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"properties\": {\n            \"gpioList\": {\n                \"title\": \"Gpio switches\",\n                \"type\": \"array\",\n                \"minItems\" : 1,\n                \"items\": {\n                    \"title\": \"Gpio switch\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"pin\": {\n                            \"title\": \"Pin\",\n                            \"type\": \"number\"\n                        },\n                        \"label\": {\n                            \"title\": \"Label\",\n                            \"type\": \"string\"\n                        },\n                        \"row\": {\n                            \"title\": \"Row\",\n                            \"type\": \"number\"\n                        },\n                        \"col\": {\n                            \"title\": \"Column\",\n                            \"type\": \"number\"\n                        }\n                    },\n                    \"required\": [\"pin\", \"label\", \"row\", \"col\"]\n                }\n            },\n            \"requestTimeout\": {\n                \"title\": \"RPC request timeout\",\n                \"type\": \"number\",\n                \"default\": 500\n            },\n            \"switchPanelBackgroundColor\": {\n                \"title\": \"Switches panel background color\",\n                \"type\": \"string\",\n                \"default\": \"#008a00\"\n            },\n            \"gpioStatusRequest\": {\n                \"title\": \"GPIO status request\",\n                \"type\": \"object\",\n                 \"properties\": {\n                    \"method\": {\n                        \"title\": \"Method name\",\n                        \"type\": \"string\",\n                        \"default\": \"getGpioStatus\"\n                    },\n                    \"paramsBody\": {\n                      \"title\": \"Method body\",\n                      \"type\": \"string\",\n                      \"default\": \"{}\"\n                    }\n                },\n                \"required\": [\"method\", \"paramsBody\"]\n            },\n            \"gpioStatusChangeRequest\": {\n                \"title\": \"GPIO status change request\",\n                \"type\": \"object\",\n                 \"properties\": {\n                    \"method\": {\n                        \"title\": \"Method name\",\n                        \"type\": \"string\",\n                        \"default\": \"setGpioStatus\"\n                    },\n                    \"paramsBody\": {\n                      \"title\": \"Method body\",\n                      \"type\": \"string\",\n                      \"default\": \"{\\n   \\\"pin\\\": \\\"{$pin}\\\",\\n   \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n                    }\n                },\n                \"required\": [\"method\", \"paramsBody\"]\n            },\n            \"parseGpioStatusFunction\": {\n                \"title\": \"Parse gpio status function\",\n                \"type\": \"string\",\n                \"default\": \"return body[pin] === true;\"\n            } \n        },\n        \"required\": [\"gpioList\", \n                     \"requestTimeout\",\n                     \"switchPanelBackgroundColor\",\n                     \"gpioStatusRequest\",\n                     \"gpioStatusChangeRequest\",\n                     \"parseGpioStatusFunction\"]\n    },\n    \"form\": [\n        \"gpioList\",\n        \"requestTimeout\",\n        {\n            \"key\": \"switchPanelBackgroundColor\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"gpioStatusRequest\",\n            \"items\": [\n                \"gpioStatusRequest.method\",\n                {\n                    \"key\": \"gpioStatusRequest.paramsBody\",\n                    \"type\": \"json\"\n                }\n            ]\n        },\n        {\n            \"key\": \"gpioStatusChangeRequest\",\n            \"items\": [\n                \"gpioStatusChangeRequest.method\",\n                {\n                    \"key\": \"gpioStatusChangeRequest.paramsBody\",\n                    \"type\": \"json\"\n                }\n            ]\n        },\n        {\n            \"key\": \"parseGpioStatusFunction\",\n            \"type\": \"javascript\"\n        }\n    ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"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\"}"}',
'Raspberry Pi GPIO Control' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'gpio_widgets',
'basic_gpio_control',
'{"type":"rpc","sizeX":4,"sizeY":2,"resources":[],"templateHtml":"<fieldset class=\"gpio-panel\" ng-disabled=\"!rpcEnabled || executingRpcRequest\" style=\"height: 100%;\">\n    <section class=\"gpio-row\" layout=\"row\" ng-repeat=\"row in rows track by $index\" \n            ng-style=\"{''height'': prefferedRowHeight+''px''}\">\n        <section flex layout=\"row\" ng-repeat=\"cell in row track by $index\">\n            <section layout=\"row\" flex ng-if=\"cell\" layout-align=\"{{$index===0 ? ''end center'' : ''start center''}}\">\n                <span class=\"gpio-left-label\" ng-show=\"$index===0\">{{ cell.label }}</span>\n                <section layout=\"row\" class=\"switch-panel\" layout-align=\"start center\" ng-class=\"$index===0 ? ''col-0'' : ''col-1''\"\n                      ng-style=\"{''height'': prefferedRowHeight+''px'', ''backgroundColor'': ''{{ switchPanelBackgroundColor }}''}\">\n                    <span class=\"pin\" ng-show=\"$index===0\">{{cell.pin}}</span>\n                    <span flex ng-show=\"$index===1\"></span>\n                    <md-switch\n                        aria-label=\"{{ cell.label }}\"\n                        ng-disabled=\"!rpcEnabled || executingRpcRequest\"\n                        ng-model=\"cell.enabled\" \n                        ng-change=\"cell.enabled = !cell.enabled\" \n                        ng-click=\"gpioClick($event, cell)\">\n                    </md-switch>\n                    <span flex ng-show=\"$index===0\"></span>\n                    <span class=\"pin\" ng-show=\"$index===1\">{{cell.pin}}</span>\n                </section>\n                <span class=\"gpio-right-label\" ng-show=\"$index===1\">{{ cell.label }}</span>\n            </section>\n            <section layout=\"row\" flex ng-if=\"!cell\">\n                <span flex ng-show=\"$index===0\"></span>\n                <span class=\"switch-panel\"\n                      ng-style=\"{''height'': prefferedRowHeight+''px'', ''backgroundColor'': ''{{ switchPanelBackgroundColor }}''}\"></span>\n                <span flex ng-show=\"$index===1\"></span>\n            </section>\n        </section>\n    </section>                            \n    <span class=\"error\" style=\"position: absolute; bottom: 5px;\" ng-show=\"rpcErrorText\">{{rpcErrorText}}</span>\n    <md-progress-linear ng-show=\"executingRpcRequest\" style=\"position: absolute; bottom: 0;\" md-mode=\"indeterminate\"></md-progress-linear>    \n</fieldset>","templateCss":".error {\n    font-size: 14px !important;\n    color: maroon;/*rgb(250,250,250);*/\n    background-color: transparent;\n    padding: 6px;\n}\n\n.error span {\n    margin: auto;\n}\n\n.gpio-panel {\n    padding-top: 10px;\n    white-space: nowrap;\n}\n\n.switch-panel {\n    margin: 0;\n    height: 32px;\n    width: 66px;\n    min-width: 66px;\n}\n\n.switch-panel md-switch {\n    margin: 0;\n    width: 36px;\n    min-width: 36px;\n}\n\n.switch-panel md-switch > div.md-container {\n    margin: 0;\n}\n\n.switch-panel.col-0 md-switch {\n    padding-left: 8px;\n    padding-right: 4px;\n}\n\n.switch-panel.col-1 md-switch {\n    padding-left: 4px;\n    padding-right: 8px;\n}\n\n.gpio-row {\n    height: 32px;\n}\n\n.pin {\n    margin-top: auto;\n    margin-bottom: auto;\n    color: white;\n    font-size: 12px;\n    width: 16px;\n    min-width: 16px;\n}\n\n.switch-panel.col-0 .pin {\n    margin-left: auto;\n    padding-left: 2px;\n    text-align: right;\n}\n\n.switch-panel.col-1 .pin {\n    margin-right: auto;\n    \n    text-align: left;\n}\n\n.gpio-left-label {\n    margin-right: 8px;\n}\n\n.gpio-right-label {\n    margin-left: 8px;\n}","controllerScript":"self.onInit = function() {\n    \n    var i, gpio;\n    var scope = self.ctx.$scope;\n    var settings = self.ctx.settings;\n    scope.gpioList = [];\n    for (var g = 0; g < settings.gpioList.length; g++) {\n        gpio = settings.gpioList[g];\n        scope.gpioList.push(\n            {\n                row: gpio.row,\n                col: gpio.col,\n                pin: gpio.pin,\n                label: gpio.label,\n                enabled: false\n            }\n        );\n    }\n\n    scope.requestTimeout = settings.requestTimeout || 1000;\n\n    scope.switchPanelBackgroundColor = settings.switchPanelBackgroundColor || tinycolor(''green'').lighten(2).toRgbString();\n\n    scope.gpioStatusRequest = {\n        method: \"getGpioStatus\",\n        paramsBody: \"{}\"\n    };\n    \n    if (settings.gpioStatusRequest) {\n        scope.gpioStatusRequest.method = settings.gpioStatusRequest.method || scope.gpioStatusRequest.method;\n        scope.gpioStatusRequest.paramsBody = settings.gpioStatusRequest.paramsBody || scope.gpioStatusRequest.paramsBody;\n    }\n    \n    scope.gpioStatusChangeRequest = {\n        method: \"setGpioStatus\",\n        paramsBody: \"{\\n   \\\"pin\\\": \\\"{$pin}\\\",\\n   \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n    };\n    \n    if (settings.gpioStatusChangeRequest) {\n        scope.gpioStatusChangeRequest.method = settings.gpioStatusChangeRequest.method || scope.gpioStatusChangeRequest.method;\n        scope.gpioStatusChangeRequest.paramsBody = settings.gpioStatusChangeRequest.paramsBody || scope.gpioStatusChangeRequest.paramsBody;\n    }\n    \n    scope.parseGpioStatusFunction = \"return body[pin] === true;\";\n    \n    if (settings.parseGpioStatusFunction && settings.parseGpioStatusFunction.length > 0) {\n        scope.parseGpioStatusFunction = settings.parseGpioStatusFunction;\n    }\n    \n    scope.parseGpioStatusFunction = new Function(\"body, pin\", scope.parseGpioStatusFunction);\n    \n    function requestGpioStatus() {\n        self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusRequest.method, \n                            scope.gpioStatusRequest.paramsBody, \n                            scope.requestTimeout)\n            .then(\n                function success(responseBody) {\n                    for (var g = 0; g < scope.gpioList.length; g++) {\n                        var gpio = scope.gpioList[g];\n                        var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n                        gpio.enabled = enabled;                        \n                    }\n                }\n            );\n    }\n    \n    function changeGpioStatus(gpio) {\n        var pin = gpio.pin + '''';\n        var enabled = !gpio.enabled;\n        enabled = enabled === true ? ''true'' : ''false'';\n        var paramsBody = scope.gpioStatusChangeRequest.paramsBody;\n        var requestBody = JSON.parse(paramsBody.replace(\"\\\"{$pin}\\\"\", pin).replace(\"\\\"{$enabled}\\\"\", enabled));\n        self.ctx.controlApi.sendTwoWayCommand(scope.gpioStatusChangeRequest.method, \n                                    requestBody, scope.requestTimeout)\n                    .then(\n                        function success(responseBody) {\n                            var enabled = scope.parseGpioStatusFunction.apply(this, [responseBody, gpio.pin]);\n                            gpio.enabled = enabled;\n                        }\n                    );\n    }\n    \n    scope.gpioCells = {};\n    var rowCount = 0;\n    for (i = 0; i < scope.gpioList.length; i++) {\n        gpio = scope.gpioList[i];\n        scope.gpioCells[gpio.row+''_''+gpio.col] = gpio;\n        rowCount = Math.max(rowCount, gpio.row+1);\n    }\n    \n    scope.prefferedRowHeight = 32;\n    scope.rows = [];\n    for (i = 0; i < rowCount; i++) {\n        var row = [];\n        for (var c =0; c<2;c++) {\n            if (scope.gpioCells[i+''_''+c]) {\n                row[c] = scope.gpioCells[i+''_''+c];\n            } else {\n                row[c] = null;\n            }\n        }\n        scope.rows.push(row);\n    }\n\n    scope.gpioClick = function($event, gpio) {\n        changeGpioStatus(gpio);\n    };\n\n    requestGpioStatus();    \n    \n    self.onResize();\n}\n\nself.onResize = function() {\n    var scope = self.ctx.$scope;\n    var rowCount = scope.rows.length;\n    var prefferedRowHeight = (self.ctx.height - 35)/rowCount;\n    prefferedRowHeight = Math.min(32, prefferedRowHeight);\n    prefferedRowHeight = Math.max(12, prefferedRowHeight);\n    scope.prefferedRowHeight = prefferedRowHeight;\n    var ratio = prefferedRowHeight/32;\n    var switches = $(''md-switch'', self.ctx.$container);\n    switches.css(''height'', 30*ratio+''px'');\n    switches.css(''width'', 36*ratio+''px'');\n    switches.css(''min-width'', 36*ratio+''px'');\n    $(''.md-container'', switches).css(''height'', 24*ratio+''px'');\n    $(''.md-container'', switches).css(''width'', 36*ratio+''px'');\n    var bars = $(''.md-bar'', self.ctx.$container);\n    bars.css(''height'', 14*ratio+''px'');\n    bars.css(''width'', 34*ratio+''px'');\n    var thumbs = $(''.md-thumb'', self.ctx.$container);\n    thumbs.css(''height'', 20*ratio+''px'');\n    thumbs.css(''width'', 20*ratio+''px'');\n    \n    var leftLabels = $(''.gpio-left-label'', self.ctx.$container);\n    leftLabels.css(''font-size'', 16*ratio+''px'');\n    var rightLabels = $(''.gpio-right-label'', self.ctx.$container);\n    rightLabels.css(''font-size'', 16*ratio+''px'');\n    var pins = $(''.pin'', self.ctx.$container);\n    var pinsFontSize = Math.max(9, 12*ratio);\n    pins.css(''font-size'', pinsFontSize+''px'');    \n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{\n    \"schema\": {\n        \"type\": \"object\",\n        \"title\": \"Settings\",\n        \"properties\": {\n            \"gpioList\": {\n                \"title\": \"Gpio switches\",\n                \"type\": \"array\",\n                \"minItems\" : 1,\n                \"items\": {\n                    \"title\": \"Gpio switch\",\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"pin\": {\n                            \"title\": \"Pin\",\n                            \"type\": \"number\"\n                        },\n                        \"label\": {\n                            \"title\": \"Label\",\n                            \"type\": \"string\"\n                        },\n                        \"row\": {\n                            \"title\": \"Row\",\n                            \"type\": \"number\"\n                        },\n                        \"col\": {\n                            \"title\": \"Column\",\n                            \"type\": \"number\"\n                        }\n                    },\n                    \"required\": [\"pin\", \"label\", \"row\", \"col\"]\n                }\n            },\n            \"requestTimeout\": {\n                \"title\": \"RPC request timeout\",\n                \"type\": \"number\",\n                \"default\": 500\n            },\n            \"switchPanelBackgroundColor\": {\n                \"title\": \"Switches panel background color\",\n                \"type\": \"string\",\n                \"default\": \"#008a00\"\n            },\n            \"gpioStatusRequest\": {\n                \"title\": \"GPIO status request\",\n                \"type\": \"object\",\n                 \"properties\": {\n                    \"method\": {\n                        \"title\": \"Method name\",\n                        \"type\": \"string\",\n                        \"default\": \"getGpioStatus\"\n                    },\n                    \"paramsBody\": {\n                      \"title\": \"Method body\",\n                      \"type\": \"string\",\n                      \"default\": \"{}\"\n                    }\n                },\n                \"required\": [\"method\", \"paramsBody\"]\n            },\n            \"gpioStatusChangeRequest\": {\n                \"title\": \"GPIO status change request\",\n                \"type\": \"object\",\n                 \"properties\": {\n                    \"method\": {\n                        \"title\": \"Method name\",\n                        \"type\": \"string\",\n                        \"default\": \"setGpioStatus\"\n                    },\n                    \"paramsBody\": {\n                      \"title\": \"Method body\",\n                      \"type\": \"string\",\n                      \"default\": \"{\\n   \\\"pin\\\": \\\"{$pin}\\\",\\n   \\\"enabled\\\": \\\"{$enabled}\\\"\\n}\"\n                    }\n                },\n                \"required\": [\"method\", \"paramsBody\"]\n            },\n            \"parseGpioStatusFunction\": {\n                \"title\": \"Parse gpio status function\",\n                \"type\": \"string\",\n                \"default\": \"return body[pin] === true;\"\n            } \n        },\n        \"required\": [\"gpioList\", \n                     \"requestTimeout\",\n                     \"switchPanelBackgroundColor\",\n                     \"gpioStatusRequest\",\n                     \"gpioStatusChangeRequest\",\n                     \"parseGpioStatusFunction\"]\n    },\n    \"form\": [\n        \"gpioList\",\n        \"requestTimeout\",\n        {\n            \"key\": \"switchPanelBackgroundColor\",\n            \"type\": \"color\"\n        },\n        {\n            \"key\": \"gpioStatusRequest\",\n            \"items\": [\n                \"gpioStatusRequest.method\",\n                {\n                    \"key\": \"gpioStatusRequest.paramsBody\",\n                    \"type\": \"json\"\n                }\n            ]\n        },\n        {\n            \"key\": \"gpioStatusChangeRequest\",\n            \"items\": [\n                \"gpioStatusChangeRequest.method\",\n                {\n                    \"key\": \"gpioStatusChangeRequest.paramsBody\",\n                    \"type\": \"json\"\n                }\n            ]\n        },\n        {\n            \"key\": \"parseGpioStatusFunction\",\n            \"type\": \"javascript\"\n        }\n    ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"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\":\"#b71c1c\",\"gpioStatusRequest\":{\"method\":\"getGpioStatus\",\"paramsBody\":\"{}\"},\"gpioList\":[{\"pin\":1,\"label\":\"GPIO 1\",\"row\":0,\"col\":0,\"_uniqueKey\":0},{\"pin\":2,\"label\":\"GPIO 2\",\"row\":0,\"col\":1,\"_uniqueKey\":1},{\"pin\":3,\"label\":\"GPIO 3\",\"row\":1,\"col\":0,\"_uniqueKey\":2}]},\"title\":\"Basic GPIO Control\"}"}',
'Basic GPIO Control' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges',
'horizontal_bar_justgage',
'{"type":"latest","sizeX":7,"sizeY":3,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>\n","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#999999\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":18,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#666666\"},\"neonGlowBrightness\":0,\"decimals\":0,\"dashThickness\":0,\"gaugeColor\":\"#eeeeee\",\"showTitle\":true,\"gaugeType\":\"horizontalBar\"},\"title\":\"Horizontal bar - justGage\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Horizontal bar - justGage' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges',
'gauge_justgage',
'{"type":"latest","sizeX":4,"sizeY":3,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temp\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#ffffff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":100,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\">\",\"refreshAnimationTime\":700,\"startAnimationType\":\">\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#999999\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Roboto\",\"style\":\"normal\",\"weight\":\"500\",\"size\":36,\"color\":\"#666666\"},\"minMaxFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#666666\"},\"neonGlowBrightness\":0,\"decimals\":0,\"dashThickness\":0,\"gaugeColor\":\"#eeeeee\",\"showTitle\":true,\"gaugeType\":\"arc\"},\"title\":\"Gauge - justGage\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Gauge - justGage' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'digital_gauges', 'lcd_gauge',
'{"type":"latest","sizeX":5,"sizeY":3,"resources":[],"templateHtml":"<canvas id=\"digitalGauge\"></canvas>","templateCss":"#gauge {\n    text-align: center;\n   /* margin-left: -100px;\n    margin-right: -100px;*/\n    /*margin-top: -50px;*/\n    \n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbCanvasDigitalGauge(self.ctx, ''digitalGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.getSettingsSchema = function() {\n    return TbCanvasDigitalGauge.settingsSchema;\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 180) {\\n\\tvalue = 180;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"#babab2\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"0px\",\"settings\":{\"maxValue\":180,\"minValue\":0,\"donutStartAngle\":90,\"showValue\":true,\"showMinMax\":true,\"gaugeWidthScale\":0.75,\"levelColors\":[],\"refreshAnimationType\":\"linear\",\"refreshAnimationTime\":700,\"startAnimationType\":\"linear\",\"startAnimationTime\":700,\"titleFont\":{\"family\":\"Roboto\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"labelFont\":{\"family\":\"Roboto\",\"size\":8,\"style\":\"normal\",\"weight\":\"500\"},\"valueFont\":{\"family\":\"Segment7Standard\",\"style\":\"normal\",\"weight\":\"500\",\"size\":32},\"minMaxFont\":{\"family\":\"Segment7Standard\",\"size\":12,\"style\":\"normal\",\"weight\":\"500\"},\"neonGlowBrightness\":0,\"dashThickness\":1.5,\"decimals\":0,\"unitTitle\":\"MPH\",\"showUnitTitle\":true,\"defaultColor\":\"#444444\",\"gaugeType\":\"arc\"},\"title\":\"LCD gauge\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'LCD gauge' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'maps', 'openstreetmap',
'{"type":"latest","sizeX":8.5,"sizeY":6,"resources":[],"templateHtml":"","templateCss":".leaflet-zoom-box {\n\tz-index: 9;\n}\n\n.leaflet-pane         { z-index: 4; }\n\n.leaflet-tile-pane    { z-index: 2; }\n.leaflet-overlay-pane { z-index: 4; }\n.leaflet-shadow-pane  { z-index: 5; }\n.leaflet-marker-pane  { z-index: 6; }\n.leaflet-tooltip-pane   { z-index: 7; }\n.leaflet-popup-pane   { z-index: 8; }\n\n.leaflet-map-pane canvas { z-index: 1; }\n.leaflet-map-pane svg    { z-index: 2; }\n\n.leaflet-control {\n\tz-index: 9;\n}\n.leaflet-top,\n.leaflet-bottom {\n\tz-index: 11;\n}\n\n.tb-marker-label {\n    border: none;\n    background: none;\n    box-shadow: none;\n}\n\n.tb-marker-label:before {\n    border: none;\n    background: none;\n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.map = new TbMapWidget(''openstreet-map'', false, self.ctx);\n}\n\nself.onDataUpdated = function() {\n    self.ctx.map.update();\n}\n\nself.onResize = function() {\n    self.ctx.map.resize();\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{\n  \"schema\": {\n    \"title\": \"Google Map Configuration\",\n    \"type\": \"object\",\n    \"properties\": {\n      \"defaultZoomLevel\": {\n         \"title\": \"Default map zoom level (1 - 20)\",\n         \"type\": \"number\"\n      },\n      \"fitMapBounds\": {\n          \"title\": \"Fit map bounds to cover all markers\",\n          \"type\": \"boolean\",\n          \"default\": true\n      },\n      \"markersSettings\": {\n            \"title\": \"Markers\",\n            \"type\": \"array\",\n            \"items\": {\n              \"title\": \"Marker settings\",\n              \"type\": \"object\",\n              \"properties\": {\n                  \"latKeyName\": {\n                    \"title\": \"Latitude key name\",\n                    \"type\": \"string\",\n                    \"default\": \"lat\"\n                  },\n                  \"lngKeyName\": {\n                    \"title\": \"Longitude key name\",\n                    \"type\": \"string\",\n                    \"default\": \"lng\"\n                  },                  \n                  \"showLabel\": {\n                    \"title\": \"Show label\",\n                    \"type\": \"boolean\",\n                    \"default\": true\n                  },                  \n                  \"label\": {\n                    \"title\": \"Label\",\n                    \"type\": \"string\"\n                  },\n                  \"tooltipPattern\": {\n                    \"title\": \"Pattern ( for ex. ''Text ${keyName} units.'' or ''${#<key index>} units''  )\",\n                    \"type\": \"string\",\n                    \"default\": \"<b>Latitude:</b> ${lat:7}<br/><b>Longitude:</b> ${lng:7}\"\n                  },\n                  \"color\": {\n                    \"title\": \"Color\",\n                    \"type\": \"string\"\n                  },\n                  \"useColorFunction\": {\n                    \"title\": \"Use color function\",\n                    \"type\": \"boolean\",\n                    \"default\": false\n                  },\n                  \"colorFunction\": {\n                    \"title\": \"Color function: f(data)\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImage\": {\n                    \"title\": \"Custom marker image\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImageSize\": {\n                    \"title\": \"Custom marker image size (px)\",\n                    \"type\": \"number\",\n                    \"default\": 34\n                  },\n                  \"useMarkerImageFunction\": {\n                    \"title\": \"Use marker image function\",\n                    \"type\": \"boolean\",\n                    \"default\": false\n                  },\n                  \"markerImageFunction\": {\n                    \"title\": \"Marker image function: f(data, images)\",\n                    \"type\": \"string\"\n                  },\n                  \"markerImages\": {\n                        \"title\": \"Marker images\",\n                        \"type\": \"array\",\n                        \"items\": {\n                          \"title\": \"Marker image\",\n                          \"type\": \"string\"\n                        }\n                  }\n              }\n           }\n       }\n    },\n    \"required\": [\n    ]\n  },\n  \"form\": [\n    \"defaultZoomLevel\",\n    \"fitMapBounds\",\n    {\n        \"key\": \"markersSettings\",\n        \"items\": [\n            \"markersSettings[].latKeyName\",\n            \"markersSettings[].lngKeyName\",\n            \"markersSettings[].showLabel\",\n            \"markersSettings[].label\",\n            \"markersSettings[].tooltipPattern\",\n            {\n                \"key\": \"markersSettings[].color\",\n                \"type\": \"color\"\n            },\n            \"markersSettings[].useColorFunction\",\n            {\n                \"key\": \"markersSettings[].colorFunction\",\n                \"type\": \"javascript\"\n            },\n            {\n                \"key\": \"markersSettings[].markerImage\",\n                \"type\": \"image\"\n            },\n            \"markersSettings[].markerImageSize\",\n            \"markersSettings[].useMarkerImageFunction\",\n            {\n                \"key\": \"markersSettings[].markerImageFunction\",\n                \"type\": \"javascript\"\n            },\n            {\n                \"key\": \"markersSettings[].markerImages\",\n                \"items\": [\n                    {\n                        \"key\": \"markersSettings[].markerImages[]\",\n                        \"type\": \"image\"\n                    }\n                ]\n            }\n        ]\n    }\n  ]\n}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"latitude\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.05427416942713381,\"funcBody\":\"var value = prevValue || 15.833293;\\nif (time % 5000 < 500) {\\n    value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"longitude\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.680594833308841,\"funcBody\":\"var value = prevValue || -90.454350;\\nif (time % 5000 < 500) {\\n    value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]},{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"lat\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.05012157428742059,\"funcBody\":\"var value = prevValue || 14.450463;\\nif (time % 4000 < 500) {\\n    value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"lng\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.6742359401617628,\"funcBody\":\"var value = prevValue || -84.845334;\\nif (time % 4000 < 500) {\\n    value += Math.random() * 0.05 - 0.025;\\n}\\nreturn value;\"}]},{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"temperature\",\"color\":\"#607d8b\",\"settings\":{},\"_hash\":0.21553274887887564,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"markersSettings\":[{\"label\":\"First point\",\"color\":\"#1e88e5\",\"latKeyName\":\"latitude\",\"lngKeyName\":\"longitude\",\"showLabel\":true,\"tooltipPattern\":\"<b>Latitude:</b> ${latitude:7}<br/><b>Longitude:</b> ${longitude:7}<br/><b>Temperature:</b> ${temperature} °C<br/><small>See advanced settings for details</small>\",\"useColorFunction\":true,\"colorFunction\":\"var temperature = data[''temperature''];\\nif (typeof temperature !== undefined) {\\n    var percent = (temperature + 60)/120 * 100;\\n    return tinycolor.mix(''blue'', ''red'', amount = percent).toHexString();\\n}\\nreturn ''blue'';\"},{\"label\":\"Second point\",\"color\":\"#fdd835\",\"latKeyName\":\"lat\",\"lngKeyName\":\"lng\",\"showLabel\":true,\"tooltipPattern\":\"<b>Latitude:</b> ${lat:7}<br/><b>Longitude:</b> ${lng:7}<br/><b>Temperature:</b> ${temperature} °C<br/><small>See advanced settings for details</small>\",\"markerImageSize\":34,\"useMarkerImageFunction\":true,\"markerImages\":[\"data:image/svg+xml;base64,[encoded data, 122396 characters]\",\"data:image/svg+xml;base64,[encoded data, 106388 characters]\",\"data:image/svg+xml;base64,[encoded data, 115312 characters]\",\"data:image/svg+xml;base64,[encoded data, 122860 characters]\"],\"markerImageFunction\":\"var res = {\\n    url: images[0],\\n    size: 40\\n}\\nvar temperature = data[''temperature''];\\nif (typeof temperature !== undefined) {\\n    var percent = (temperature + 60)/120;\\n    var index = Math.floor(4 * percent);\\n    res.url = images[index];\\n}\\nreturn res;\"}],\"fitMapBounds\":true},\"title\":\"OpenStreetMap\"}"}',
'OpenStreetMap' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'analogue_gauges',
'speed_gauge_canvas_gauges',
'{"type":"latest","sizeX":7,"sizeY":5,"resources":[],"templateHtml":"<canvas id=\"radialGauge\"></canvas>\n","templateCss":"","controllerScript":"self.onInit = function() {\n    self.ctx.gauge = new TbAnalogueRadialGauge(self.ctx, ''radialGauge'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.gauge.update();\n}\n\nself.onResize = function() {\n    self.ctx.gauge.resize();\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.gauge.mobileModeChanged();\n}\n\nself.getSettingsSchema = function() {\n    return TbAnalogueRadialGauge.settingsSchema;\n}\n\nself.onDestroy = function() {\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Speed\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.7282710489093589,\"funcBody\":\"var value = prevValue + Math.random() * 50 - 25;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 220) {\\n\\tvalue = 220;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":false,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"maxValue\":180,\"startAngle\":45,\"ticksAngle\":270,\"showBorder\":false,\"defaultColor\":\"#e65100\",\"needleCircleSize\":7,\"highlights\":[{\"from\":80,\"to\":120,\"color\":\"#fdd835\"},{\"color\":\"#e57373\",\"from\":120,\"to\":180}],\"showUnitTitle\":false,\"colorPlate\":\"#fff\",\"colorMajorTicks\":\"#444\",\"colorMinorTicks\":\"#666\",\"minorTicks\":2,\"valueInt\":3,\"minValue\":0,\"valueDec\":0,\"highlightsWidth\":15,\"valueBox\":true,\"animation\":true,\"animationDuration\":1500,\"animationRule\":\"linear\",\"colorNeedleShadowUp\":\"rgba(2, 255, 255, 0)\",\"colorNeedleShadowDown\":\"rgba(188, 143, 143, 0.78)\",\"units\":\"MPH\",\"majorTicksCount\":9,\"numbersFont\":{\"family\":\"Roboto\",\"size\":22,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"titleFont\":{\"family\":\"Roboto\",\"size\":24,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#888\"},\"unitsFont\":{\"family\":\"Roboto\",\"size\":28,\"style\":\"normal\",\"weight\":\"500\",\"color\":\"#616161\"},\"valueFont\":{\"size\":32,\"style\":\"normal\",\"weight\":\"normal\",\"shadowColor\":\"rgba(0, 0, 0, 0.49)\",\"color\":\"#444\",\"family\":\"Segment7Standard\"},\"colorValueBoxRect\":\"#888\",\"colorValueBoxRectEnd\":\"#666\",\"colorValueBoxBackground\":\"#babab2\",\"colorValueBoxShadow\":\"rgba(0,0,0,1)\"},\"title\":\"Speed gauge - Canvas Gauges\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Speed gauge - Canvas Gauges' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'charts', 'pie',
'{"type":"latest","sizeX":8,"sizeY":5,"resources":[],"templateHtml":"","templateCss":".legend {\n    font-size: 13px;\n    line-height: 10px;\n}\n\n.legend table { \n    border-spacing: 0px;\n    border-collapse: separate;\n}\n\n.pie-label {\n    font-size: 12px;\n    font-family: ''Roboto'';\n    font-weight: bold;\n    text-align: center;\n    padding: 2px;\n    color: white;\n}\n","controllerScript":"self.onInit = function() {\n    self.ctx.flot = new TbFlot(self.ctx, ''pie'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.flot.update();\n}\n\nself.onResize = function() {\n    self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n    self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n    return TbFlot.pieSettingsSchema;\n}\n\nself.getDataKeySettingsSchema = function() {\n    return TbFlot.pieDatakeySettingsSchema;\n}\n\nself.onDestroy = function() {\n    self.ctx.flot.destroy();\n}\n","settingsSchema":"{}\n","dataKeySettingsSchema":"{}\n","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{},\"_hash\":0.15479322438769105,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#4caf50\",\"settings\":{},\"_hash\":0.6114638304362894,\"funcBody\":\"var value = (prevValue-20) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+20;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Third\",\"color\":\"#f44336\",\"settings\":{},\"_hash\":0.9955906536344441,\"funcBody\":\"var value = (prevValue-40) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+40;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Fourth\",\"color\":\"#ffc107\",\"settings\":{},\"_hash\":0.9430835931647599,\"funcBody\":\"var value = (prevValue-50) + Math.random() * 2 - 1;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value+50;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"radius\":1,\"fontColor\":\"#545454\",\"fontSize\":10,\"decimals\":1,\"legend\":{\"show\":true,\"position\":\"nw\",\"labelBoxBorderColor\":\"#CCCCCC\",\"backgroundColor\":\"#F0F0F0\",\"backgroundOpacity\":0.85},\"innerRadius\":0,\"showLabels\":true,\"stroke\":{\"width\":5},\"tilt\":1,\"animatedPie\":false},\"title\":\"Pie - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400}}"}',
'Pie - Flot' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'charts', 'timeseries_bars_flot',
'{"type":"timeseries","sizeX":8,"sizeY":5,"resources":[],"templateHtml":"","templateCss":".legend {\n    font-size: 13px;\n    line-height: 10px;\n}\n\n.legend table { \n    border-spacing: 0px;\n    border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n    cursor: crosshair; \n}\n\n","controllerScript":"self.onInit = function() {\n    self.ctx.flot = new TbFlot(self.ctx, ''bar'');    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.flot.update();\n}\n\nself.onResize = function() {\n    self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n    self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n    return TbFlot.settingsSchema;\n}\n\nself.getDataKeySettingsSchema = function() {\n    return TbFlot.datakeySettingsSchema(false);\n}\n\nself.onDestroy = function() {\n    self.ctx.flot.destroy();\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":false,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 0) {\\n\\tvalue = 0;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000},\"aggregation\":{\"limit\":200,\"type\":\"AVG\"}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"legend\":{\"show\":true,\"position\":\"nw\",\"backgroundColor\":\"#f0f0f0\",\"backgroundOpacity\":0.85,\"labelBoxBorderColor\":\"rgba(1, 1, 1, 0.45)\"},\"decimals\":1,\"stack\":true,\"tooltipIndividual\":false},\"title\":\"Timeseries Bars - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null}"}',
'Timeseries Bars - Flot' );

INSERT INTO "thingsboard"."widget_type" ( "id", "tenant_id", "bundle_alias", "alias", "descriptor", "name" )
VALUES ( now ( ), minTimeuuid ( 0 ), 'charts', 'basic_timeseries',
'{"type":"timeseries","sizeX":8,"sizeY":5,"resources":[],"templateHtml":"","templateCss":".legend {\n    font-size: 13px;\n    line-height: 10px;\n}\n\n.legend table { \n    border-spacing: 0px;\n    border-collapse: separate;\n}\n\n.mouse-events .flot-overlay {\n    cursor: crosshair; \n}\n\n","controllerScript":"self.onInit = function() {\n    self.ctx.flot = new TbFlot(self.ctx);    \n}\n\nself.onDataUpdated = function() {\n    self.ctx.flot.update();\n}\n\nself.onResize = function() {\n    self.ctx.flot.resize();\n}\n\nself.onEditModeChanged = function() {\n    self.ctx.flot.checkMouseEvents();\n}\n\nself.onMobileModeChanged = function() {\n    self.ctx.flot.checkMouseEvents();\n}\n\nself.getSettingsSchema = function() {\n    return TbFlot.settingsSchema;\n}\n\nself.getDataKeySettingsSchema = function() {\n    return TbFlot.datakeySettingsSchema(true);\n}\n\nself.onDestroy = function() {\n    self.ctx.flot.destroy();\n}\n","settingsSchema":"{}","dataKeySettingsSchema":"{}","defaultConfig":"{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"First\",\"color\":\"#2196f3\",\"settings\":{\"showLines\":true,\"fillLines\":true,\"showPoints\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Second\",\"color\":\"#ffc107\",\"settings\":{\"showLines\":true,\"fillLines\":false,\"showPoints\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 100 - 50;\\nvar multiplier = Math.pow(10, 2 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -1000) {\\n\\tvalue = -1000;\\n} else if (value > 1000) {\\n\\tvalue = 1000;\\n}\\nreturn value;\"}]}],\"timewindow\":{\"realtime\":{\"timewindowMs\":60000}},\"showTitle\":true,\"backgroundColor\":\"#fff\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"shadowSize\":4,\"fontColor\":\"#545454\",\"fontSize\":10,\"xaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"yaxis\":{\"showLabels\":true,\"color\":\"#545454\"},\"grid\":{\"color\":\"#545454\",\"tickColor\":\"#DDDDDD\",\"verticalLines\":true,\"horizontalLines\":true,\"outlineWidth\":1},\"legend\":{\"show\":true,\"position\":\"nw\",\"backgroundColor\":\"#f0f0f0\",\"backgroundOpacity\":0.85,\"labelBoxBorderColor\":\"rgba(1, 1, 1, 0.45)\"},\"decimals\":1,\"stack\":false,\"tooltipIndividual\":false},\"title\":\"Timeseries - Flot\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400},\"mobileHeight\":null}"}',
'Timeseries - Flot' );


/** System plugins and rules **/
INSERT INTO thingsboard.plugin ( id, tenant_id, name, state, search_text, api_token, plugin_class, public_access,
configuration )
VALUES ( minTimeuuid ( '2016-11-01 01:01:01+0000' ), minTimeuuid ( 0 ), 'System Telemetry Plugin', 'ACTIVE',
'system telemetry plugin', 'telemetry',
'org.thingsboard.server.extensions.core.plugin.telemetry.TelemetryStoragePlugin', true, '{}' );

INSERT INTO thingsboard.rule ( id, tenant_id, name, plugin_token, state, search_text, weight, filters, processor,
action )
VALUES ( minTimeuuid ( '2016-11-01 01:01:02+0000' ), minTimeuuid ( 0 ), 'System Telemetry Rule', 'telemetry', 'ACTIVE',
'system telemetry rule', 0,
'[{"clazz":"org.thingsboard.server.extensions.core.filter.MsgTypeFilter", "name":"TelemetryFilter", "configuration": {"messageTypes":["POST_TELEMETRY","POST_ATTRIBUTES","GET_ATTRIBUTES"]}}]',
null,
'{"clazz":"org.thingsboard.server.extensions.core.action.telemetry.TelemetryPluginAction", "name":"TelemetryMsgConverterAction", "configuration":{}}'
);

INSERT INTO thingsboard.plugin ( id, tenant_id, name, state, search_text, api_token, plugin_class, public_access,
configuration )
VALUES ( minTimeuuid ( '2016-11-01 01:01:03+0000' ), minTimeuuid ( 0 ), 'System RPC Plugin', 'ACTIVE',
'system rpc plugin', 'rpc', 'org.thingsboard.server.extensions.core.plugin.rpc.RpcPlugin', true, '{
       "defaultTimeout": 20000
     }' );

/** SYSTEM **/
