BNA8/.resources/03953ac962ec565471fec5838f7cb8f6a38ec5fe3f1554cf49071bed629c3a85

643 lines
22 KiB
Plaintext

{
"custom": {},
"params": {},
"props": {
"defaultSize": {
"height": 600,
"width": 750
}
},
"root": {
"children": [
{
"meta": {
"name": "TitleLabel"
},
"position": {
"height": 35,
"width": "100%"
},
"props": {
"style": {
"backgroundColor": "#1A4A5E",
"borderColor": "#000",
"borderStyle": "solid",
"borderWidth": "1px",
"color": "#FFF",
"fontSize": "20px",
"fontWeight": "bold",
"paddingLeft": 5
},
"text": "Heatmap Options"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "ShiftLabel"
},
"position": {
"height": 25,
"width": "33%",
"y": 40
},
"props": {
"style": {
"backgroundColor": "#F0F0F0",
"borderStyle": "solid",
"fontWeight": "bold",
"textAlign": "center"
},
"text": "Filter By Time \u0026 Shifts"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "TimeStartLabel"
},
"position": {
"height": 30,
"width": 75,
"y": 65
},
"props": {
"style": {
"backgroundColor": "#F0F0F0",
"borderLeftStyle": "solid",
"borderRightStyle": "solid",
"fontWeight": "bold",
"textAlign": "right"
},
"text": "Start:"
},
"type": "ia.display.label"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tstartDate \u003d self.props\n\tendDate \u003d self.getSibling(\"TimeEndInput\").props\n\thours \u003d system.date.hoursBetween(startDate.value, endDate.value)\n\tif hours \u003e 30*24:\n\t\t# Cap endDate to within 30 days of startDate:\n\t\tendDate.value \u003d system.date.addDays(startDate.value, 30)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "TimeStartInput"
},
"position": {
"height": 30,
"width": "calc(33% - 75px)",
"x": 75,
"y": 65
},
"props": {
"format": "YYYY-MM-DD HH:mm:ss",
"formattedValue": "2021-02-13 00:00:00",
"formattedValues": {
"date": "2021-02-13",
"datetime": "2021-02-13 00:00:00",
"time": "00:00:00"
},
"value": {
"$": [
"ts",
192,
1613256769474
],
"$ts": 1613192400000
}
},
"type": "ia.input.date-time-input"
},
{
"meta": {
"name": "TimeEndLabel"
},
"position": {
"height": 30,
"width": 75,
"y": 95
},
"props": {
"style": {
"backgroundColor": "#F0F0F0",
"borderLeftStyle": "solid",
"borderRightStyle": "solid",
"fontWeight": "bold",
"textAlign": "right"
},
"text": "End:"
},
"type": "ia.display.label"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\tstartDate \u003d self.getSibling(\"TimeStartInput\").props\n\tendDate \u003d self.props\n\thours \u003d system.date.hoursBetween(startDate.value, endDate.value)\n\tif hours \u003e 30*24:\n\t\t# Cap startDate to within 30 days of endDate:\n\t\tstartDate.value \u003d system.date.addDays(endDate.value, -30)"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "TimeEndInput"
},
"position": {
"height": 30,
"width": "calc(33% - 75px)",
"x": 75,
"y": 95
},
"props": {
"format": "YYYY-MM-DD HH:mm:ss",
"formattedValue": "2021-02-14 00:00:00",
"formattedValues": {
"date": "2021-02-14",
"datetime": "2021-02-14 00:00:00",
"time": "00:00:00"
},
"value": {
"$": [
"ts",
192,
1613256769474
],
"$ts": 1613278800000
}
},
"type": "ia.input.date-time-input"
},
{
"meta": {
"name": "AlarmTypeTable"
},
"position": {
"height": "calc(100% - 145px)",
"width": "33%",
"x": 251.25,
"y": 90
},
"propConfig": {
"props.cells.style.backgroundColor": {
"binding": {
"config": {
"path": "../AlarmTypeAll.props.selected"
},
"transforms": [
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "#888"
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
}
},
"props.data": {
"binding": {
"config": {
"queryPath": "Alarms/HeatmapUniqueAlarms"
},
"type": "query"
}
},
"props.selection.enableRowSelection": {
"binding": {
"config": {
"expression": "!{../AlarmTypeAll.props.selected}"
},
"type": "expr"
}
}
},
"props": {
"enableHeader": false,
"pager": {
"bottom": false,
"initialOption": 5
},
"selection": {
"mode": "multiple interval"
}
},
"type": "ia.display.table"
},
{
"meta": {
"name": "AlarmTypeLabel"
},
"position": {
"height": 25,
"width": "33%",
"x": 251.25,
"y": 40
},
"props": {
"style": {
"backgroundColor": "#F0F0F0",
"borderStyle": "solid",
"fontWeight": "bold",
"textAlign": "center"
},
"text": "Filter By Alarm Type"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "AlarmTypeAll"
},
"position": {
"height": 25,
"width": "33%",
"x": 251.25,
"y": 65
},
"props": {
"selected": true,
"style": {
"backgroundColor": "#F0F0F0",
"borderBottomStyle": "solid",
"borderLeftStyle": "solid",
"borderRightStyle": "solid"
},
"text": "Select All"
},
"type": "ia.input.checkbox"
},
{
"meta": {
"name": "ShiftAll"
},
"position": {
"height": 25,
"width": "33%",
"y": 125
},
"props": {
"selected": true,
"style": {
"backgroundColor": "#F0F0F0",
"borderStyle": "solid"
},
"text": "No Shift Filter (24/7)"
},
"type": "ia.input.checkbox"
},
{
"meta": {
"name": "ShiftTable"
},
"position": {
"height": "calc(100% - 205px)",
"width": "33%",
"y": 150
},
"propConfig": {
"props.cells.style.backgroundColor": {
"binding": {
"config": {
"path": "../ShiftAll.props.selected"
},
"transforms": [
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "#888"
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
}
},
"props.data": {
"binding": {
"config": {
"fallbackDelay": 2.5,
"mode": "direct",
"tagPath": "[default]Gateway/Shifts"
},
"transforms": [
{
"code": "\tdata \u003d [[value.getValueAt(r, \"Name\")] for r in range(value.getRowCount()) if value.getValueAt(r, \"Enabled\")]\n\tdata \u003d [r for r in data if r[0] !\u003d \"\"]\n\treturn system.dataset.toDataSet([\"description\"], data)",
"type": "script"
}
],
"type": "tag"
}
},
"props.selection.enableRowSelection": {
"binding": {
"config": {
"expression": "!{../ShiftAll.props.selected}"
},
"type": "expr"
}
}
},
"props": {
"enableHeader": false,
"pager": {
"bottom": false,
"initialOption": 5
},
"selection": {
"mode": "multiple interval"
}
},
"type": "ia.display.table"
},
{
"meta": {
"name": "DeviceTypeLabel"
},
"position": {
"height": 25,
"width": "33%",
"x": 502.5,
"y": 40
},
"props": {
"style": {
"backgroundColor": "#F0F0F0",
"borderStyle": "solid",
"fontWeight": "bold",
"textAlign": "center"
},
"text": "Filter By Device Type"
},
"type": "ia.display.label"
},
{
"meta": {
"name": "DeviceTypeAll"
},
"position": {
"height": 25,
"width": "33%",
"x": 502.5,
"y": 65
},
"props": {
"selected": true,
"style": {
"backgroundColor": "#F0F0F0",
"borderBottomStyle": "solid",
"borderLeftStyle": "solid",
"borderRightStyle": "solid"
},
"text": "Select All"
},
"type": "ia.input.checkbox"
},
{
"meta": {
"name": "DeviceTypeTable"
},
"position": {
"height": "calc(100% - 145px)",
"width": "33%",
"x": 502.5,
"y": 90
},
"propConfig": {
"props.cells.style.backgroundColor": {
"binding": {
"config": {
"path": "../DeviceTypeAll.props.selected"
},
"transforms": [
{
"fallback": null,
"inputType": "scalar",
"mappings": [
{
"input": true,
"output": "#888"
}
],
"outputType": "scalar",
"type": "map"
}
],
"type": "property"
}
},
"props.selection.enableRowSelection": {
"binding": {
"config": {
"expression": "!{../DeviceTypeAll.props.selected}"
},
"type": "expr"
}
}
},
"props": {
"columns": [
{
"align": "center",
"boolean": "checkbox",
"dateFormat": "MM/DD/YYYY",
"editable": false,
"field": "",
"footer": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"header": {
"align": "center",
"justify": "left",
"style": {
"classes": ""
},
"title": ""
},
"justify": "auto",
"number": "value",
"numberFormat": "0,0.##",
"progressBar": {
"bar": {
"color": "",
"style": {
"classes": ""
}
},
"max": 100,
"min": 0,
"track": {
"color": "",
"style": {
"classes": ""
}
},
"value": {
"enabled": true,
"format": "0,0.##",
"justify": "center",
"style": {
"classes": ""
}
}
},
"render": "auto",
"resizable": true,
"sort": "none",
"sortable": true,
"strictWidth": false,
"style": {
"classes": ""
},
"toggleSwitch": {
"color": {
"selected": "",
"unselected": ""
}
},
"viewParams": {},
"viewPath": "",
"visible": true,
"width": ""
}
],
"data": {
"$": [
"ds",
192,
1597260961733
],
"$columns": [
{
"data": [
"Beacons",
"EIPs",
"Encoders",
"Estops",
"Limit Switches",
"MCPs",
"Photo Eyes",
"Push Buttons",
"Scanners",
"VFDs",
"Solenoids",
"Conveyors"
],
"name": "description",
"type": "String"
},
{
"data": [
"beacon",
"eip",
"encoder",
"estop",
"limitswitch",
"mcp",
"photoeye",
"pushbutton",
"scanner",
"vfd",
"solenoid",
"conveyor"
],
"name": "type",
"type": "String"
}
]
},
"enableHeader": false,
"pager": {
"bottom": false,
"initialOption": 5
},
"selection": {
"mode": "multiple interval"
}
},
"type": "ia.display.table"
},
{
"events": {
"component": {
"onActionPerformed": {
"config": {
"script": "\timport re\n\timport time\n\t\n\t# Gather Shifts:\n\tshifts \u003d []\n\tshiftsQuery \u003d []\n\tshiftsText \u003d \"None\"\n\tif not self.getSibling(\"ShiftAll\").props.selected:\n\t\t# Retrieve shift table:\n\t\tshiftTable \u003d utils.datasetToJSON(system.tag.readBlocking([\"[default]Gateway/Shifts\"])[0].value)\n\t\tshiftTable \u003d {row[\"Name\"]: row for row in shiftTable}\n\t\t# Grab selection:\n\t\tselection \u003d self.getSibling(\"ShiftTable\").props.selection.data\n\t\tshifts \u003d [dat[\"description\"] for dat in selection]\n\t\tshiftsText \u003d \", \".join(shifts)\n\t\t# Generate shift query:\n\t\tfor shift in selection:\n\t\t\tif shift[\"description\"] in shiftTable:\n\t\t\t\tshift \u003d shiftTable[shift[\"description\"]]\n\t\t\t\tline \u003d []\n\t\t\t\t# Add day filter:\n\t\t\t\tdays \u003d [str(i+1) for i, day in enumerate([\"isSunday\", \"isMonday\", \"isTuesday\", \"isWednesday\", \"isThursday\", \"isFriday\", \"isSaturday\"]) if shift[day]]\n\t\t\t\t# If no days, ignore this shift:\n\t\t\t\tif len(days) \u003c\u003d 0:\n\t\t\t\t\tshiftsQuery.append(\"false\")\n\t\t\t\t\tcontinue\n\t\t\t\t# If not all days are present, then add day filter:\n\t\t\t\tif len(days) \u003c 7:\n\t\t\t\t\tline.append(\"DAYOFWEEK(eventtime) IN (\"+\",\".join(days)+\")\")\n\t\t\t\t# If time range is incompatible (starttime \u003e\u003d endtime), then remove shift:\n\t\t\t\t# TODO: Handle time ranges that go across midnight\n\t\t\t\tif shift[\"StartHour\"]*60+shift[\"StartMinute\"] \u003e\u003d shift[\"EndHour\"]*60+shift[\"EndMinute\"]:\n\t\t\t\t\tshiftsQuery.append(\"false\")\n\t\t\t\t\tcontinue\n\t\t\t\t# Add time range:\n\t\t\t\tline.append(\"TIME(eventtime) BETWEEN \\\"{:02d}:{:02d}:00\\\" AND \\\"{:02d}:{:02d}:00\\\"\".format(shift[\"StartHour\"], shift[\"StartMinute\"], shift[\"EndHour\"], shift[\"EndMinute\"]))\n\t\t\t\t# If nothing was added to line, then treat shift as 24/7, which then we can ignore all shifts:\n\t\t\t\tif len(line) \u003c\u003d 0:\n\t\t\t\t\tshiftsQuery \u003d []\n\t\t\t\t\tbreak\n\t\t\t\t# Add shift to shifts:\n\t\t\t\tshiftsQuery.append(\" AND \".join(line))\n\t# Gather Alarms:\n\talarms \u003d []\n\talarmsText \u003d \"All\"\n\tif not self.getSibling(\"AlarmTypeAll\").props.selected:\n\t\talarms \u003d self.getSibling(\"AlarmTypeTable\").props.selection.data\n\t\talarms \u003d [dat[\"description\"] for dat in alarms]\n\t\talarmsText \u003d \", \".join(alarms)\n\tif len(alarms) \u003d\u003d 0:\n\t\talarms \u003d self.getSibling(\"AlarmTypeTable\").props.data\n\t\talarms \u003d [alarms.getValueAt(r, \"description\") for r in range(alarms.getRowCount())]\n\t# Gather Devices:\n\tdevices \u003d []\n\tdeviceTypes \u003d []\n\tdevicesText \u003d \"All\"\n\tif self.getSibling(\"DeviceTypeAll\").props.selected:\n\t\tdataset \u003d self.getSibling(\"DeviceTypeTable\").props.data\n\t\tdevices \u003d [dataset.getValueAt(row, \"description\") for row in range(dataset.getRowCount())]\n\t\tdeviceTypes \u003d [dataset.getValueAt(row, \"type\") for row in range(dataset.getRowCount())]\n\telse:\n\t\tdataset \u003d self.getSibling(\"DeviceTypeTable\").props.data\n\t\tdevices \u003d [dat[\"description\"] for dat in self.getSibling(\"DeviceTypeTable\").props.selection.data]\n\t\tdeviceTypes \u003d [dataset.getValueAt(row, \"type\") for row in range(dataset.getRowCount()) if dataset.getValueAt(row, \"description\") in devices]\n\t\tdevicesText \u003d \", \".join(devices)\n\tdevices \u003d [dat.replace(\" \", \"\") for dat in devices]\n\tif len(devices) \u003d\u003d 0:\n\t\tdevicesText \u003d \"None\"\n\t\n\t# Run report:\n\t# Sanitize:\n\talarmQuery \u003d (\u0027\"\u0027+alarm.replace(\"\\\\\", \"\\\\\\\\\").replace(\u0027\"\u0027, \u0027\\\\\"\u0027)+\u0027\"\u0027 for alarm in alarms)\n\tshiftsQuery \u003d [\"(\"+shift+\")\" for shift in shiftsQuery]\n\tparams \u003d {\n\t\t\"startDate\": self.getSibling(\"TimeStartInput\").props.formattedValue,\n\t\t\"endDate\": self.getSibling(\"TimeEndInput\").props.formattedValue,\n\t\t\"alarms\": \",\".join(alarmQuery),\n\t\t\"shifts\": \" \" if len(shiftsQuery) \u003d\u003d 0 else \"AND (\"+\" OR \".join(shiftsQuery)+\")\",\n\t\t\"devices\": \u0027\"\"\u0027 if len(deviceTypes) \u003d\u003d 0 else \",\".join([\u0027\"\u0027+device+\u0027\"\u0027 for device in deviceTypes])\n\t}\n\t#system.perspective.print(params)\n\tdata \u003d system.db.runNamedQuery(\"Alarms/Heatmap\", params)\n\t\n\t# Apply and activate heatmap:\n\tself.session.custom.heatmapSettings \u003d {\n\t\t\"enabled\": True,\n\t\t\"time\": {\n\t\t\t\"start\": params[\"startDate\"],\n\t\t\t\"end\": params[\"endDate\"]\n\t\t},\n\t\t\"shifts\": shifts,\n\t\t\"alarms\": alarms,\n\t\t\"devices\": devices,\n\t\t\"shiftsText\": shiftsText,\n\t\t\"alarmsText\": alarmsText,\n\t\t\"devicesText\": devicesText,\n\t\t\"data\": data\n\t}\n\t\n\t# Close popup:\n\tif self.session.custom.isMobile:\n\t\tsystem.perspective.navigate(page\u003d\"/\")\n\telse:\n\t\tsystem.perspective.closePopup(\"\")\n\t\t# Force client to graphics screens only:\n\t\tif self.page.props.primaryView !\u003d \"Windows/GraphicsWrapper\":\n\t\t\tsystem.perspective.navigate(page\u003d\"/\")"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "RunButton"
},
"position": {
"height": 50,
"width": "100%",
"y": "calc(100% - 50px)"
},
"propConfig": {
"props.enabled": {
"binding": {
"config": {
"expression": " {../TimeStartInput.props.value} !\u003d null\r\n\u0026\u0026{../TimeEndInput.props.value} !\u003d null\r\n\u0026\u0026({../ShiftAll.props.selected}||{../ShiftTable.props.selection.selectedRow}!\u003dnull)\r\n\u0026\u0026({../AlarmTypeAll.props.selected}||{../AlarmTypeTable.props.selection.selectedRow}!\u003dnull)"
},
"type": "expr"
}
}
},
"props": {
"style": {
"classes": "Buttons/Grey"
},
"text": "Run heatmap"
},
"type": "ia.input.button"
}
],
"events": {
"system": {
"onStartup": {
"config": {
"script": "\tnow \u003d system.date.now()\n\tstart \u003d system.date.midnight(now)\n\tend \u003d system.date.addDays(start, 1)\n\tself.getChild(\"TimeStartInput\").props.value \u003d start\n\tself.getChild(\"TimeEndInput\").props.value \u003d end"
},
"scope": "G",
"type": "script"
}
}
},
"meta": {
"name": "root"
},
"props": {
"style": {
"classes": "window",
"minWidth": "750px"
}
},
"type": "ia.container.coord"
}
}