gpio_widgets.json
52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
{
"widgetsBundle": {
"alias": "gpio_widgets",
"title": "GPIO widgets",
"image": null
},
"widgetTypes": [
{
"alias": "basic_gpio_control",
"name": "Basic GPIO Control",
"descriptor": {
"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\"}"
}
},
{
"alias": "gpio_panel",
"name": "Basic GPIO Panel",
"descriptor": {
"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}}}"
}
},
{
"alias": "raspberry_pi_gpio_control",
"name": "Raspberry Pi GPIO Control",
"descriptor": {
"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\"}"
}
},
{
"alias": "raspberry_pi_gpio_panel",
"name": "Raspberry Pi GPIO Panel",
"descriptor": {
"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}}}"
}
}
]
}