{ "custom": { "trendConfig": {} }, "params": { "selectedPens": [], "tagPath": "[Ignition_Common_IO_Gtwy]MPR1140/SATB1_CHW_TES02_TT02" }, "propConfig": { "custom.trendConfig": { "persistent": true }, "custom.trendConfig.allPens": { "binding": { "config": { "struct": { "pens": "{view.custom.trendConfig.selectedPens}", "tagPath": "{view.params.tagPath}" }, "waitOnAll": true }, "transforms": [ { "code": " # Initialize a dictionary to store instances grouped by \u0027engUnit\u0027\n lists \u003d {}\n output \u003d []\n \n # Fetch tag configurations, including nested tags\n nodes \u003d system.tag.getConfiguration(value[\u0027tagPath\u0027], True)\n total \u003d 0\n for item in nodes:\n # Check if the item contains the \u0027tags\u0027 key\n if \u0027tags\u0027 in item:\n \ttotal \u003d len(item[\u0027tags\u0027])\n \tsortedTags \u003d sorted(item[\u0027tags\u0027], key\u003dlambda x: x[\u0027name\u0027])\n \tsortedTags \u003d sorted(sortedTags, key\u003dlambda x: x.get(\u0027engUnit\u0027, \u0027misc\u0027))\n \t\n \tfor i, tagConfig in enumerate(sortedTags):\n \t\tif str(tagConfig[\u0027tagType\u0027]) \u003d\u003d \u0027AtomicTag\u0027:\n\t\t\t\t\tisEnabled \u003d False\n\t\t\t\t\t# Get the engineering unit or default to \u0027Misc\u0027 if not available\n\t\t\t\t\tengUnit \u003d tagConfig.get(\"engUnit\", \"misc\")\n\t\t\t\t\tif engUnit \u003d\u003d \"\":\n\t\t\t\t\t engUnit \u003d \"misc\"\n\t\t\t\t\t\n\t\t\t\t\t# Initialize a list for the \u0027engUnit\u0027 if it hasn\u0027t been added\n\t\t\t\t\tif engUnit not in lists:\n\t\t\t\t\t lists[engUnit] \u003d []\n\t\t\t\t\t\n\t\t\t\t\t# Create tag instance details\n\t\t\t\t\tname \u003d tagConfig.get(\"name\", \"\")\n\t\t\t\t\ttagPath \u003d value[\u0027tagPath\u0027] + \u0027/\u0027 + name\n\t\t\t\t\tif name in value[\u0027pens\u0027]:\n\t\t\t\t\t\tisEnabled \u003d True\n\t\t\t\t\tinstance \u003d {\n\t\t\t\t\t \"instanceStyle\": {\n\t\t\t\t\t \"classes\": \"\"\n\t\t\t\t\t },\n\t\t\t\t\t \"instancePosition\": {},\n\t\t\t\t\t \"name\": name,\n\t\t\t\t\t \"tagPath\": tagPath,\n\t\t\t\t\t \"engUnit\": engUnit,\n\t\t\t\t\t \"color\": \u0027\u0027,\n\t\t\t\t\t \"enabled\": isEnabled\n\t\t\t\t\t}\n\t\t\t\t\tlists[engUnit].append(instance)\n\t\t\t\t\t\n # Return the sorted and grouped output\n for li in sorted(lists):\n \toutput.append({\n \t\t\u0027group\u0027: lists[li][0][\u0027engUnit\u0027],\n \t\t\u0027penList\u0027: lists[li]\n \t})\n return output", "type": "script" } ], "type": "expr-struct" } }, "custom.trendConfig.selectedPens": { "binding": { "config": { "path": "view.params.selectedPens" }, "type": "property" } }, "params.selectedPens": { "paramDirection": "input", "persistent": true }, "params.tagPath": { "paramDirection": "input", "persistent": true } }, "props": { "defaultSize": { "width": 1200 } }, "root": { "children": [ { "children": [ { "children": [ { "meta": { "name": "ToggleSwitch" }, "position": { "basis": "34px", "shrink": 0 }, "props": { "label": { "text": "Table View" } }, "type": "ia.input.toggle-switch" }, { "meta": { "name": "FlexRepeater" }, "propConfig": { "props.instances": { "binding": { "config": { "struct": { "allPens": "{view.custom.trendConfig.allPens}", "selectedPens": "{view.custom.trendConfig.selectedPens}" }, "waitOnAll": true }, "transforms": [ { "code": "\toutput \u003d []\n\tallPens \u003d value[\u0027allPens\u0027]\n\tfor i in range(len(allPens)):\n\t\tpenGroup \u003d allPens[i].get(\u0027group\u0027, \u0027Misc\u0027)\n\t\tpenList \u003d allPens[i].get(\u0027penList\u0027, [])\n\t\tlistLength \u003d len(penList)\n\t\tnewPenList \u003d []\n\t\tfor i, pen in enumerate(penList):\n\t\t\tpen \u003d dict(pen)\n\t\t\tname \u003d pen[\u0027name\u0027]\n\t\t\tpen[\u0027color\u0027] \u003d utils.misc.getHexColorFromInt(i + 1, listLength)\n\t\t\tif name in value[\u0027selectedPens\u0027]:\n\t\t\t\tpen[\u0027enabled\u0027] \u003d True\n\t\t\tnewPenList.append(pen)\n\t\toutput.append({\n\t\t\t\u0027group\u0027: penGroup, \n\t\t\t\u0027penList\u0027: newPenList\n\t\t})\n\treturn output", "type": "script" } ], "type": "expr-struct" } } }, "props": { "direction": "column", "elementPosition": { "basis": "auto", "grow": 0, "shrink": 0 }, "loading": { "order": "with-parent" }, "path": "Library/Templates/Framework/Pen List", "useDefaultViewHeight": false, "useDefaultViewWidth": false }, "type": "ia.display.flex-repeater" } ], "meta": { "name": "Pens Lists" }, "position": { "basis": "250px" }, "props": { "direction": "column", "style": { "border": "1px solid var(--border)", "border-right": "none" } }, "type": "ia.container.flex" }, { "children": [ { "meta": { "domId": "CustomPowerChart", "name": "Power Chart" }, "position": { "basis": "800px", "grow": 1 }, "propConfig": { "custom.pens": { "binding": { "config": { "struct": { "axes": "{this.props.axes}", "pens": "{view.custom.trendConfig.selectedPens}", "tagPath": "{view.params.tagPath}" }, "waitOnAll": true }, "transforms": [ { "code": "\t\n\tinfo \u003d value\n\ttagProvider \u003d \u0027ignition-satb1-io6\u0027\n\tdef find_characters(text, char_list):\n\t\tfound_characters \u003d {}\n\t\tfor char_to_find in char_list:\n\t\t\tif char_to_find in text:\n\t\t\t\tfound_characters[char_to_find] \u003d True\n\t\t\t\treturn found_characters\n\t\n\tsearch_text \u003d value[\u0027tagPath\u0027].split(\u0027_\u0027)[2]\n\tcharacters_to_find \u003d [\u00271\u0027, \u00272\u0027, \u00273\u0027, \u00274\u0027, \u00275\u0027]\n\tfound \u003d find_characters(search_text, characters_to_find)\n\t\t\n\tif found:\n\t\tfor character in found:\n\t\t\tif character \u003d\u003d \"1\":\n\t\t\t\ttagProvider \u003d \u0027ignition-satb1-io1\u0027\n\t\t\telif character \u003d\u003d \"2\":\n\t\t\t\ttagProvider \u003d \u0027ignition-satb1-io2\u0027\n\t\t\telif character \u003d\u003d \"3\":\n \t\t\t \ttagProvider \u003d \u0027ignition-satb1-io3\u0027\n \t\t\telif character \u003d\u003d \"4\":\n \t\t\t \ttagProvider \u003d \u0027ignition-satb1-io4\u0027\n \t\t\telif character \u003d\u003d \"5\":\n \t\t\t \ttagProvider \u003d \u0027ignition-satb1-io5\u0027\n\t\t\telse:\n\t\t\t \ttagProvider \u003d \u0027ignition-satb1-io6\u0027\n\treturn tagProvider", "type": "script" }, { "code": "\toutput \u003d []\n\t\n\ttry:\n\t\tpensList \u003d self.parent.parent.getChild(\"Pens Lists\").getChild(\"FlexRepeater\").props.instances\n\t\tfor tagGroup in pensList:\n\t\t\tgroupName \u003d tagGroup[\u0027group\u0027]\n\t\t\tpenList \u003d tagGroup[\u0027penList\u0027]\n\t\t\tfor tag in penList:\n\t\t\t\taxis \u003d tag[\u0027engUnit\u0027]\n\t\t\t\tcolor \u003d tag[\u0027color\u0027]\n\t\t\t\tinstance \u003d {\n\t\t\t\t\"axis\": axis,\n\t\t\t\t\"data\": {\n\t\t\t\t\"aggregateMode\": \"default\",\n\t\t\t\t\"source\": \u0027histprov:Ignition_Hist:/drv:\u0027+ value +\u0027:default:/tag:\u0027 + tag[\u0027tagPath\u0027].split(\u0027]\u0027)[1].lower()\n\t\t\t\t},\n\t\t\t\t\"display\": {\n\t\t\t\t\"breakLine\": True,\n\t\t\t\t\"interpolation\": \"curveLinear\",\n\t\t\t\t\"radius\": 3,\n\t\t\t\t\"styles\": {\n\t\t\t\t \"highlighted\": {\n\t\t\t\t \"fill\": {\n\t\t\t\t \"color\": color,\n\t\t\t\t \"opacity\": 1\n\t\t\t\t },\n\t\t\t\t \"stroke\": {\n\t\t\t\t \"color\": color,\n\t\t\t\t \"dashArray\": 0,\n\t\t\t\t \"opacity\": 1,\n\t\t\t\t \"width\": 1\n\t\t\t\t }\n\t\t\t\t },\n\t\t\t\t \"muted\": {\n\t\t\t\t \"fill\": {\n\t\t\t\t \"color\": color,\n\t\t\t\t \"opacity\": 0.4\n\t\t\t\t },\n\t\t\t\t \"stroke\": {\n\t\t\t\t \"color\": color,\n\t\t\t\t \"dashArray\": 0,\n\t\t\t\t \"opacity\": 0.4,\n\t\t\t\t \"width\": 1\n\t\t\t\t }\n\t\t\t\t },\n\t\t\t\t \"normal\": {\n\t\t\t\t \"fill\": {\n\t\t\t\t \"color\": color,\n\t\t\t\t \"opacity\": 0.8\n\t\t\t\t },\n\t\t\t\t \"stroke\": {\n\t\t\t\t \"color\": color,\n\t\t\t\t \"dashArray\": 0,\n\t\t\t\t \"opacity\": 0.8,\n\t\t\t\t \"width\": 1\n\t\t\t\t }\n\t\t\t\t },\n\t\t\t\t \"selected\": {\n\t\t\t\t \"fill\": {\n\t\t\t\t \"color\": color,\n\t\t\t\t \"opacity\": 1\n\t\t\t\t },\n\t\t\t\t \"stroke\": {\n\t\t\t\t \"color\": color,\n\t\t\t\t \"dashArray\": 0,\n\t\t\t\t \"opacity\": 1,\n\t\t\t\t \"width\": 1\n\t\t\t\t }\n\t\t\t\t }\n\t\t\t\t},\n\t\t\t\t\"type\": \"line\"\n\t\t\t\t},\n\t\t\t\t\"enabled\": True,\n\t\t\t\t\"name\": tag[\u0027name\u0027],\n\t\t\t\t\"plot\": 1,\n\t\t\t\t\"selectable\": False,\n\t\t\t\t\"visible\": True\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\toutput.append(instance)\n\texcept:\n\t\tpass\n\treturn output", "type": "script" } ], "type": "expr-struct" } }, "position.display": { "binding": { "config": { "expression": "!{.../Pens Lists/ToggleSwitch.props.selected}" }, "type": "expr" } }, "props.axes": { "binding": { "config": { "struct": { "tags": "{.../Pens Lists/FlexRepeater.props.instances}" }, "waitOnAll": true }, "transforms": [ { "code": "\toutput \u003d []\n\taxes \u003d []\n\tfor i, engUnit in enumerate(value[\u0027tags\u0027]):\n#\t\tengUnit \u003d tagConfig[\u0027engUnit\u0027]\n\t\tif engUnit not in axes:\n\t\t\taxes.append(engUnit)\n\t\t\toutput.append({\n\t\t\t\t\"name\": engUnit,\n\t\t\t\t\"position\": \"left\",\n\t\t\t\t\"width\": 60,\n\t\t\t\t\"color\": \"#757A7F\",\n\t\t\t\t\"dataFormat\": \"0,0.##\",\n\t\t\t\t\"range\": {\n\t\t\t\t\"auto\": True,\n\t\t\t\t\"min\": \"\",\n\t\t\t\t\"max\": \"\"\n\t\t\t\t},\n\t\t\t\t\"label\": {\n\t\t\t\t\"text\": engUnit,\n\t\t\t\t\"offset\": 0,\n\t\t\t\t\"font\": {\n\t\t\t\t \"color\": \"#757A7F\",\n\t\t\t\t \"size\": 10\n\t\t\t\t},\n\t\t\t\t\"style\": {\n\t\t\t\t \"classes\": \"\"\n\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"tick\": {\n\t\t\t\t\"color\": \"#757A7F\",\n\t\t\t\t\"count\": \"auto\",\n\t\t\t\t\"label\": {\n\t\t\t\t \"format\": \"HH:mm\",\n\t\t\t\t \"font\": {\n\t\t\t\t \"color\": \"#757A7F\",\n\t\t\t\t \"size\": 10\n\t\t\t\t },\n\t\t\t\t \"style\": {\n\t\t\t\t \"classes\": \"\"\n\t\t\t\t }\n\t\t\t\t},\n\t\t\t\t\"style\": {\n\t\t\t\t \"classes\": \"\"\n\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"style\": {\n\t\t\t\t\"classes\": \"\"\n\t\t\t\t}\n\t\t\t})\n\treturn output", "type": "script" } ], "type": "expr-struct" } }, "props.config": { "onChange": { "enabled": null, "script": "\tconfig \u003d currentValue.value\n\t\n\tif config[\u0027mode\u0027].value \u003d\u003d \u0027historical\u0027:\n\t\tif previousValue !\u003d None:\n\t\t\tif previousValue.value !\u003d None:\n\n\t\t\t\ttry:\n\t\t\t\t\tstartDate \u003d config[\u0027startDate\u0027].value \n\t\t\t\t\tendDate \u003d config[\u0027endDate\u0027].value\n\t\t\t\texcept:\n\t\t\t\t\tstartDate \u003d system.date.now()\n\t\t\t\t\tendDate \u003d system.date.addDays(startDate, -1)\t\t\t\t\n\t\t\t\t\n\t\t\t\tdaysBetween \u003d system.date.daysBetween(startDate,endDate)\n\t\t\t\t\n\t\t\t\tif daysBetween \u003e 14:\n\t\t\t\t\toldStartDate \u003d previousValue.value[\u0027startDate\u0027].value\n\t\t\t\t\toldEndDate \u003d previousValue.value[\u0027endDate\u0027].value\n\t\t\t\t\t\n\t\t\t\t\tif oldStartDate \u003d\u003d startDate:\n\t\t\t\t\t\tself.props.config.startDate \u003d system.date.addDays(endDate,-14)\n\t\t\t\t\telse:\n\t\t\t\t\t\tself.props.config.endDate \u003d system.date.addDays(startDate,14)\n\telif config[\u0027mode\u0027].value \u003d\u003d \u0027realtime\u0027:\n\t\tunits \u003d config[\u0027measureOfTime\u0027].value\n\t\ttime \u003d config[\u0027unitOfTime\u0027].value\n\t\t\n\t\tif units \u003d\u003d \u0027seconds\u0027:\n\t\t\tif time \u003e 1209600:\n\t\t\t\tself.props.config.unitOfTime \u003d 1209600\n\t\telif units \u003d\u003d \u0027minutes\u0027:\n\t\t\tif time \u003e 20160:\n\t\t\t\tself.props.config.unitOfTime \u003d 20160\n\t\telif units \u003d\u003d \u0027hours\u0027:\n\t\t\tif time \u003e 336:\n\t\t\t\tself.props.config.unitOfTime \u003d 336\n\t\telif units \u003d\u003d \u0027days\u0027:\n\t\t\tif time \u003e 14:\n\t\t\t\tself.props.config.unitOfTime \u003d 14\n\t\telif units \u003d\u003d \u0027weeks\u0027:\n\t\t\tif time \u003e 2:\n\t\t\t\tself.props.config.unitOfTime \u003d 2\n\t\telse:\n\t\t\tself.props.config.unitOfTime \u003d 2\n\t\t\tself.props.config.measureOfTime \u003d \u0027weeks\u0027\n\thistSetting \u003d utils.helper.sanitize_tree(self.parent.parent.parent.getChild(\"FlexContainer\").custom.historianSettings)\n#\tsystem.perspective.print(\"%s\"%histSetting)\n\thistSetting.update(utils.helper.sanitize_tree(self.props.config))\n\tself.parent.parent.parent.getChild(\"FlexContainer\").custom.historianSettings \u003d histSetting" } }, "props.pens": { "binding": { "config": { "struct": { "enabledPens": "{view.custom.trendConfig.selectedPens}", "pens": "{this.custom.pens}" }, "waitOnAll": true }, "transforms": [ { "code": "\t# Utilize the trendConfig.allPens to know which pens from the \u0027pens\u0027\n\t# custom property to append to the pensToReturn list.\n\t\n\tcurrentPens \u003d self.props.pens\n\t\n\tpensToReturn \u003d []\n\t\n\tpens \u003d value[\u0027pens\u0027]\n\tenabledPens \u003d value[\u0027enabledPens\u0027]\n\t\n\tfor pen in pens:\n\t\tif pen.name in enabledPens:\n\t\t\thistoryPen \u003d ({\u0027axis\u0027:pen.axis,\u0027data\u0027:pen.data,\u0027display\u0027:pen.display,\n\t\t\t\u0027enabled\u0027:pen.enabled,\u0027name\u0027:pen.name,\u0027plot\u0027:pen.plot,\n\t\t\t\u0027selectable\u0027:pen.selectable,\u0027visible\u0027:pen.visible})\n\t\t\t\n\t\t\t# To retain visibility settings.\n\t\t\tfor currPen in currentPens:\n\t\t\t\tif pen.name \u003d\u003d currPen.name:\n\t\t\t\t\thistoryPen[\u0027visible\u0027] \u003d currPen.visible\n\t\t\t\t\t\n\t\t\tpensToReturn.append(historyPen)\n\t\t\t\n\treturn pensToReturn", "type": "script" } ], "type": "expr-struct" } } }, "props": { "config": { "endDate": { "$": [ "ts", 0, 1731972292627 ], "$ts": 1730879940000 }, "rangeSelectorPen": "histprov:Ignition_Hist_SATB1_IO1_default:/tag:Datahall 1/Development/GEN 1/Amps A", "responsiveDesignWidth": 100, "startDate": { "$": [ "ts", 0, 1731972292627 ], "$ts": 1730733759000 }, "unitOfTime": 2, "visibility": { "buttons": { "showAnnotationButton": false, "showSettingsButton": false, "showTagBrowserButton": false } } }, "interaction": { "chartZoomLevel": 1, "rangeZoomLevel": 1 }, "plots": [ { "color": "transparent", "markers": [], "relativeWeight": 3, "style": { "classes": "" } }, { "color": "transparent", "markers": [], "relativeWeight": 3, "style": { "classes": "" } }, { "color": "transparent", "markers": [], "relativeWeight": 3, "style": { "classes": "" } }, { "color": "transparent", "markers": [], "relativeWeight": 2, "style": { "classes": "" } }, { "color": "transparent", "markers": [], "relativeWeight": 1, "style": { "classes": "" } }, { "color": "transparent", "markers": [], "relativeWeight": 1, "style": { "classes": "" } } ] }, "type": "ia.chart.powerchart" }, { "children": [ { "meta": { "name": "Label", "visible": false }, "position": { "basis": "200px" }, "propConfig": { "position.display": { "binding": { "config": { "path": ".../Power Chart.props.pens" }, "transforms": [ { "code": "\t# If no pens are enabled, then show this label (informing the user to select a pen).\n\t\n\tfor pen in value:\n\t\tif pen.enabled \u003d\u003d True:\n\t\t\treturn False\n\treturn True", "type": "script" } ], "type": "property" } } }, "props": { "style": { "color": "--neutral-80", "fontSize": "14px", "marginTop": "-143px", "minHeight": "-143px" }, "text": "Please select a tag." }, "type": "ia.display.label" } ], "meta": { "name": "Pens Cont" }, "position": { "basis": "0px" }, "props": { "alignItems": "center", "direction": "column", "style": { "overflow": "visible", "zIndex": 0 } }, "type": "ia.container.flex" }, { "meta": { "name": "TrendTable" }, "position": { "basis": "320px", "grow": 1 }, "propConfig": { "position.display": { "binding": { "config": { "path": ".../Pens Lists/ToggleSwitch.props.selected" }, "type": "property" } }, "props.params.historianSettings": { "binding": { "config": { "path": "..../FlexContainer.custom.historianSettings" }, "type": "property" } }, "props.params.selectedPens": { "binding": { "config": { "path": "../Power Chart.props.pens" }, "type": "property" } } }, "props": { "path": "Library/Templates/Framework/TrendTable" }, "type": "ia.display.view" } ], "meta": { "name": "Chart Cont" }, "position": { "basis": "200px", "grow": 1 }, "props": { "direction": "column" }, "type": "ia.container.flex" } ], "custom": { "historianSettings": { "dateFormat": "YYYY/MM/DD", "endDate": { "$": [ "ts", 192, 1747947368983 ], "$ts": 1730879940000 }, "export": { "dateFormat": "None", "timeFormat": "x" }, "measureOfTime": "hours", "mode": "realtime", "penNamePathDepth": 1, "pointCount": 300, "rangeEndDate": null, "rangeSelectorPen": "histprov:Ignition_Hist_SATB1_IO1_default:/tag:Datahall 1/Development/GEN 1/Amps A", "rangeStartDate": null, "refreshRate": 1000, "responsiveDesignWidth": 100, "startDate": { "$": [ "ts", 192, 1747947368983 ], "$ts": 1730733759000 }, "tagBrowserStartPath": "", "timeFormat": "h:mm A", "unitOfTime": 2, "visibility": { "buttons": { "showAnnotationButton": false, "showFullscreenButton": true, "showMoreButton": true, "showPanZoomButton": true, "showRangeBrushButton": true, "showSettingsButton": false, "showTagBrowserButton": false, "showXTraceButton": true }, "showDateRangeSelector": true, "showPenControlDisplay": true, "showTagBrowser": false } } }, "meta": { "name": "FlexContainer" }, "position": { "basis": "100%" }, "type": "ia.container.flex" } ], "meta": { "name": "root" }, "props": { "direction": "column", "style": { "classes": "containers/padded-container" } }, "type": "ia.container.flex" } }