Added GetActiveAlarms named query, removed extra scripts in the active alarm table
This commit is contained in:
parent
76e026896d
commit
e9843607db
@ -488,6 +488,7 @@
|
||||
],
|
||||
"custom": {
|
||||
"priorities": {
|
||||
"critical": false,
|
||||
"diagnostic": false,
|
||||
"high": false,
|
||||
"low": false,
|
||||
@ -599,7 +600,7 @@
|
||||
"component": {
|
||||
"onActionPerformed": {
|
||||
"config": {
|
||||
"script": "\ttry:\n\t # Get table data\n\t data \u003d self.parent.parent.parent.getChild(\"FlexContainer_0\").getChild(\"Table\").props.data\n\t\n\t # CSV header\n\t csv_content \u003d \"Number (ID),Event Timestamp,Duration,Priority,Description,Tag\\n\"\n\t\n\t if data and len(data) \u003e 0:\n\t for row in data:\n\t val \u003d row.get(\"value\", {})\n\t row_data \u003d [\n\t str(val.get(\"NumberID\", \"\")),\n\t str(val.get(\"EventTimestamp\", \"\")),\n\t str(val.get(\"Duration\", \"\")),\n\t str(val.get(\"Priority\", \"\")),\n\t str(val.get(\"Description\", \"\")),\n\t str(val.get(\"Tag\", \"\"))\n\t ]\n\t\n\t # Escape commas for CSV safety\n\t row_data \u003d [field.replace(\",\", \";\") for field in row_data]\n\t csv_content +\u003d \",\".join(row_data) + \"\\n\"\n\t else:\n\t csv_content +\u003d \"No alarms in current view\\n\"\n\t\n\texcept Exception as e:\n\t system.perspective.print(\"Error during CSV export: \" + str(e))\n\t csv_content \u003d \"Error exporting alarm data\\n\"\n\t\n\t# Convert to bytes and trigger download\n\tcsv_bytes \u003d csv_content.encode(\u0027utf-8\u0027)\n\tsystem.perspective.download(\"active_alarms.csv\", csv_bytes)\n "
|
||||
"script": "\tfrom datetime import datetime\n\ttry:\n\t # Get table data\n\t data \u003d self.parent.parent.parent.getChild(\"FlexContainer_0\").getChild(\"Table\").props.data\n\t \n\t column_order \u003d [\n\t \"ID\",\n\t \"StartTimestamp\", \n\t \"Duration\",\n\t \"Priority\",\n\t \"Location\",\n\t \"Description\",\n\t \"Tag\"\n\t ]\n\t\n\t # CSV header\n\t csv_content \u003d \",\".join(column_order) + \"\\n\"\n\t \n\t def unwrap(v):\n\t\t\tif hasattr(v, \u0027value\u0027):\n\t\t\t\treturn str(v.value)\n\t \t\n\t\t\treturn v\n\t \n\t if data and len(data) \u003e 0:\n\t for item in data:\n\t row_data \u003d []\n\t \n\t for col in column_order:\n\t # Look for the column in the current item\n\t if col in item:\n\t cell \u003d item[col]\n\t # Extract the value from the nested structure\n\t if isinstance(cell, dict) and \"value\" in cell:\n\t raw_value \u003d cell[\"value\"]\n\t else:\n\t raw_value \u003d cell\n\t else:\n\t raw_value \u003d \"\"\n\t \n\t # Process and clean the value\n\t processed_value \u003d unwrap(raw_value).replace(\",\", \";\")\n\t row_data.append(processed_value)\n\t \n\t csv_content +\u003d \",\".join(row_data) + \"\\n\"\n\t else:\n\t csv_content +\u003d \"No alarms in current view\\n\"\n\t\n\texcept Exception as e:\n\t system.perspective.print(\"Export Error: \" + str(e))\n\t csv_content \u003d \"Export failed\\n\"\n\t\n\tcsv_bytes \u003d csv_content.encode(\"utf-8\")\n\tsystem.perspective.download(\"active_alarms.csv\", csv_bytes) \n\t \n\t \n\t \n\t\n#\t if data and len(data) \u003e 0:\n#\t for row in data:\n#\t val \u003d row.get(\"value\", {})\n#\t row_data \u003d [\n#\t str(val.get(\"NumberID\", \"\")),\n#\t str(val.get(\"EventTimestamp\", \"\")),\n#\t str(val.get(\"Duration\", \"\")),\n#\t str(val.get(\"Priority\", \"\")),\n#\t str(val.get(\"Description\", \"\")),\n#\t str(val.get(\"Tag\", \"\"))\n#\t ]\n#\t\n#\t # Escape commas for CSV safety\n#\t row_data \u003d [field.replace(\",\", \";\") for field in row_data]\n#\t csv_content +\u003d \",\".join(row_data) + \"\\n\"\n#\t else:\n#\t csv_content +\u003d \"No alarms in current view\\n\"\n#\t\n#\texcept Exception as e:\n#\t system.perspective.print(\"Error during CSV export: \" + str(e))\n#\t csv_content \u003d \"Error exporting alarm data\\n\"\n#\t\n#\t# Convert to bytes and trigger download\n#\tcsv_bytes \u003d csv_content.encode(\u0027utf-8\u0027)\n#\tsystem.perspective.download(\"active_alarms.csv\", csv_bytes)\n "
|
||||
},
|
||||
"scope": "G",
|
||||
"type": "script"
|
||||
@ -691,24 +692,6 @@
|
||||
{
|
||||
"children": [
|
||||
{
|
||||
"custom": {
|
||||
"rawData": [
|
||||
{
|
||||
"style": {
|
||||
"classes": "Alarms-Styles/Low"
|
||||
},
|
||||
"value": {
|
||||
"Description": "MCM01 Hello world",
|
||||
"Duration": "00:05:48",
|
||||
"EventTimestamp": "2025-06-23 13:10:26",
|
||||
"Location": "MCM01",
|
||||
"NumberID": 60,
|
||||
"Priority": "Low",
|
||||
"Tag": "MCM01.HMI.Beacon_Light"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"meta": {
|
||||
"name": "Table"
|
||||
},
|
||||
@ -721,33 +704,34 @@
|
||||
"config": {
|
||||
"path": ".../FlexContainer/FlexContainer.custom.priorities"
|
||||
},
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.data": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"path": "this.custom.rawData"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\t\n\tpriorities \u003d self.custom.priorities if hasattr(self.custom, \"priorities\") else []\n\t\n\tactivePriorities \u003d [k.capitalize() for k, v in priorities.items() if v]\n\t\n\tif not activePriorities:\n\t return value\n\t\n\tfiltered_data \u003d []\n\t\n\tfor row in value:\n\t\tpriority \u003d row[\"value\"][\"Priority\"]\n\t\tif priority in activePriorities:\n\t \t filtered_data.append(row)\n\t\n\treturn filtered_data",
|
||||
"code": "\t\n\tpriority_to_number \u003d {\n\t \"critical\": 4,\n\t \"high\": 3,\n\t \"medium\": 2,\n\t \"low\": 1,\n\t \"diagnostic\": 0\n\t}\n\t\n\t\n\t# Collect enabled priorities\n\tenabled \u003d [str(priority_to_number[k]) for k, v in value.items() if v]\n\t\n\tresult \u003d \",\".join(enabled)\n\t\n\tif not result:\n\t\treturn \"\"\n\t\n\treturn result\n\t\n",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "property"
|
||||
}
|
||||
},
|
||||
"props.query": {
|
||||
"props.data": {
|
||||
"binding": {
|
||||
"config": {
|
||||
"expression": "now(2000)"
|
||||
"parameters": {
|
||||
"priorityList": "{this.custom.priorities}"
|
||||
},
|
||||
"type": "expr"
|
||||
"polling": {
|
||||
"enabled": true,
|
||||
"rate": "3"
|
||||
},
|
||||
"onChange": {
|
||||
"enabled": null,
|
||||
"script": "\tfrom system import date\n\t\n\ttag_provider \u003d \"[\" + self.session.custom.fc + \"_SCADA_TAG_PROVIDER]\"\n\n\t# Helper: format row for table\n\tdef testRow(eventTimeStamp, duration, location, priority, description, tag, className, numberId):\n\t\treturn {\n\t\t \"value\": {\n\t\t \"NumberID\": numberId,\n\t\t \"EventTimestamp\": eventTimeStamp,\n\t\t \"Duration\": duration,\n\t\t \"Priority\": priority,\n\t\t \"Location\": location,\n\t\t \"Description\": description,\n\t\t \"Tag\": tag,\n\t\t },\n\t\t \"style\": {\n\t\t \"classes\": className,\n\t\t }\n\t\t}\n\t\n\t# Query active alarms\n\tresults \u003d system.alarm.queryStatus(state\u003d[\"ActiveUnacked\", \"ActiveAcked\"])\n\t\n\t# Build rows\n\tdata \u003d []\n\tnumberID \u003d \"\"\n\tlcoation \u003d \"\"\n\tclassName \u003d \"\"\n\tif(results \u003d\u003d0):\n\t\treturn\n\t\n\tfor i, alarm in enumerate(results):\n\t\tactiveTime \u003d alarm.eventTime\n\t\tmyTag \u003d alarm.myTag\n\t\tOPCItemTag \u003d system.tag.read(tag_provider + myTag + \".OpcItemPath\").value\n\t\tif(OPCItemTag):\t\t\n\t\t\tparts \u003d OPCItemTag.split(\".\")\n\t\t\ttag \u003d str(alarm.displayPath) +\".\" + parts[1] + \".\" + parts[2]\n\t\telse:\n\t\t\ttag \u003d \"Unknown tag\"\n\t\t\n\t\ttag_parts \u003d myTag.split(\"/\")\n\t\tif(tag_parts):\n\t\t\tlocation \u003d tag_parts[1] \n\t\telse:\n\t\t\tlocation \u003d \"Unknown Location\"\n\t\t\n\t\t\n\t\ttry:\n\t\t query \u003d system.db.runQuery(\"SELECT id, eventtime FROM alarm_events WHERE eventid \u003d \" + \"\u0027\" + str(alarm.id) + \"\u0027\",\"MariaDB\")\n\t\t if(query):\n\t\t \tnumberID \u003d query[0][0]\n\t\t durationSeconds \u003d date.secondsBetween(activeTime, date.now())\n\t\t durationStr \u003d date.format(date.addSeconds(date.midnight(date.now()), durationSeconds), \"HH:mm:ss\")\n\t\t \n\t\t priority \u003d alarm.priority.toString()\n\t\t if priority \u003d\u003d \"High\":\n\t\t color \u003d \"Alarms-Styles/High\"\n\t\t elif priority \u003d\u003d \"Medium\":\n\t\t className \u003d \"Alarms-Styles/Medium\"\n\t\t elif priority \u003d\u003d \"Low\":\n\t\t className \u003d \"Alarms-Styles/Low\"\n\t\t elif priority \u003d\u003d \"Diagnostic\":\n\t\t className \u003d \"Alarms-Styles/Diagnostic\"\n\t\t else:\n\t\t className \u003d \"Alarms-Styles/NoAlarm\"\n\t\t \n\t\n\t\t data.append(testRow(\n\t\t eventTimeStamp \u003d date.format(activeTime, \"yyyy-MM-dd HH:mm:ss\"),\n\t\t duration \u003d durationStr,\n\t\t location \u003d location,\n\t\t numberId \u003d numberID,\n\t\t priority \u003d priority,\n\t\t description \u003d alarm.myLocation + \" \" + alarm.name,\n\t\t tag \u003d tag,\n\t\t className \u003d className,\n\t\t ))\n\t\texcept:\n\t\t\tpass\n\t\n\tself.custom.rawData \u003d data"
|
||||
"queryPath": "GetActiveAlarms"
|
||||
},
|
||||
"transforms": [
|
||||
{
|
||||
"code": "\n\tfrom system.dataset import toPyDataSet\n\n\tds \u003d toPyDataSet(value)\n\tdata \u003d []\n\n\tcolumn_names \u003d [col for col in ds.columnNames if col !\u003d \"EndTimestamp\"]\n\t\n\n\tfor row in ds:\n\t\tpriority \u003d row[\"Priority\"]\n\n\t\t# Use style class names from Perspective\n\t\tif priority \u003d\u003d \"High\":\n\t\t\tclassName \u003d \"Alarms-Styles/High\"\n\t\telif priority \u003d\u003d \"Medium\":\n\t\t\tclassName \u003d \"Alarms-Styles/Medium\"\n\t\telif priority \u003d\u003d \"Low\":\n\t\t\tclassName \u003d \"Alarms-Styles/Low\"\n\t\telif priority \u003d\u003d \"Diagnostic\":\n\t\t\tclassName \u003d \"Alarms-Styles/Diagnostic\"\n\t\telse:\n\t\t\tclassName \u003d \"Alarms-Styles/NoAlarm\"\n\n\t\t# Apply the style class to all cells in the row\n\t\trow_dict \u003d {\n\t\t\tcol: {\n\t\t\t\t\"value\": row[col],\n\t\t\t\t\"style\": { \"classes\": className }\n\t\t\t} for col in column_names\n\t\t}\n\t\tdata.append(row_dict)\n\n\treturn data",
|
||||
"type": "script"
|
||||
}
|
||||
],
|
||||
"type": "query"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -848,9 +832,9 @@
|
||||
{
|
||||
"align": "center",
|
||||
"boolean": "checkbox",
|
||||
"dateFormat": "MM/DD/YYYY",
|
||||
"dateFormat": "MM/DD/YYYY HH:mm:ss",
|
||||
"editable": false,
|
||||
"field": "EventTimestamp",
|
||||
"field": "StartTimestamp",
|
||||
"filter": {
|
||||
"boolean": {
|
||||
"condition": ""
|
||||
@ -1401,28 +1385,73 @@
|
||||
"emptyMessage": {
|
||||
"noData": {
|
||||
"text": "No Active Alarms"
|
||||
},
|
||||
"noFilterResults": {
|
||||
"text": "No Active Alarms"
|
||||
}
|
||||
},
|
||||
"filter": {
|
||||
"enabled": true,
|
||||
"results": {
|
||||
"data": [
|
||||
{
|
||||
"Description": "MCM01 Hello world",
|
||||
"Duration": "00:03:48",
|
||||
"EventTimestamp": "2025-06-23 13:10:26",
|
||||
"Location": "MCM01",
|
||||
"NumberID": 60,
|
||||
"Priority": "Low",
|
||||
"Tag": "MCM01.HMI.Beacon_Light"
|
||||
}
|
||||
],
|
||||
"enabled": true
|
||||
},
|
||||
"text": " "
|
||||
}
|
||||
},
|
||||
"selection": {
|
||||
"mode": "multiple interval"
|
||||
"data": [
|
||||
{
|
||||
"Description": {
|
||||
"style": {
|
||||
"classes": "Alarms-Styles/High"
|
||||
},
|
||||
"value": "MCM01 - Hello world"
|
||||
},
|
||||
"Duration": {
|
||||
"style": {
|
||||
"classes": "Alarms-Styles/High"
|
||||
},
|
||||
"value": "00:53:47"
|
||||
},
|
||||
"ID": {
|
||||
"style": {
|
||||
"classes": "Alarms-Styles/High"
|
||||
},
|
||||
"value": 103
|
||||
},
|
||||
"Location": {
|
||||
"style": {
|
||||
"classes": "Alarms-Styles/High"
|
||||
},
|
||||
"value": "MCM01"
|
||||
},
|
||||
"Priority": {
|
||||
"style": {
|
||||
"classes": "Alarms-Styles/High"
|
||||
},
|
||||
"value": "High"
|
||||
},
|
||||
"StartTimestamp": {
|
||||
"style": {
|
||||
"classes": "Alarms-Styles/High"
|
||||
},
|
||||
"value": {
|
||||
"$": [
|
||||
"ts",
|
||||
0,
|
||||
1750677703466
|
||||
],
|
||||
"$ts": 1750674476000
|
||||
}
|
||||
},
|
||||
"Tag": {
|
||||
"style": {
|
||||
"classes": "Alarms-Styles/High"
|
||||
},
|
||||
"value": "MCM01.HMI.Beacon_Light"
|
||||
}
|
||||
}
|
||||
],
|
||||
"mode": "multiple interval",
|
||||
"selectedRow": 0
|
||||
}
|
||||
},
|
||||
"type": "ia.display.table"
|
||||
@ -2923,7 +2952,7 @@
|
||||
"$": [
|
||||
"ts",
|
||||
192,
|
||||
1750667761263
|
||||
1750674251724
|
||||
],
|
||||
"$ts": 1750435156149
|
||||
},
|
||||
@ -2931,7 +2960,7 @@
|
||||
"$": [
|
||||
"ts",
|
||||
192,
|
||||
1750667761263
|
||||
1750674251724
|
||||
],
|
||||
"$ts": 1750436956149
|
||||
}
|
||||
@ -3871,7 +3900,7 @@
|
||||
"$": [
|
||||
"ts",
|
||||
192,
|
||||
1750667761263
|
||||
1750674251724
|
||||
],
|
||||
"$ts": 1750435156149
|
||||
},
|
||||
@ -3879,7 +3908,7 @@
|
||||
"$": [
|
||||
"ts",
|
||||
192,
|
||||
1750667761263
|
||||
1750674251724
|
||||
],
|
||||
"$ts": 1750436956149
|
||||
},
|
||||
@ -4138,7 +4167,6 @@
|
||||
"contentStyle": {
|
||||
"classes": "Background-Styles/Grey-Background"
|
||||
},
|
||||
"currentTabIndex": 2,
|
||||
"menuType": "modern",
|
||||
"style": {
|
||||
"classes": "Background-Styles/Grey-Background"
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
WITH Active AS (
|
||||
SELECT
|
||||
ae.id,
|
||||
ae.eventtime,
|
||||
ae.eventid,
|
||||
ae.source,
|
||||
ae.priority,
|
||||
ae.displaypath,
|
||||
TIMESTAMPDIFF(SECOND, ae.eventtime, NOW()) AS duration_seconds
|
||||
FROM alarm_events ae
|
||||
WHERE ae.eventtype = 0
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM alarm_events ae_clear
|
||||
WHERE ae_clear.eventid = ae.eventid
|
||||
AND ae_clear.eventtype = 1
|
||||
)
|
||||
AND ae.displaypath NOT LIKE '%System Startup%'
|
||||
AND ae.source NOT LIKE '%System Startup%'
|
||||
-- Priority filter using FIND_IN_SET for comma-separated values
|
||||
AND (
|
||||
:priorityList IS NULL
|
||||
OR :priorityList = ''
|
||||
OR FIND_IN_SET(ae.priority, :priorityList) > 0
|
||||
)
|
||||
GROUP BY ae.id
|
||||
),
|
||||
SingleMyTag AS (
|
||||
SELECT aed.id, aed.strValue
|
||||
FROM alarm_event_data aed
|
||||
WHERE aed.propname = 'myTag'
|
||||
GROUP BY aed.id
|
||||
)
|
||||
SELECT
|
||||
Active.id AS ID,
|
||||
Active.eventtime AS StartTimestamp,
|
||||
NULL AS EndTimestamp, -- no end time since it's still active
|
||||
CONCAT(
|
||||
LPAD(FLOOR(Active.duration_seconds / 3600), 2, '0'), ':',
|
||||
LPAD(FLOOR((Active.duration_seconds % 3600) / 60), 2, '0'), ':',
|
||||
LPAD(Active.duration_seconds % 60, 2, '0')
|
||||
) AS Duration,
|
||||
CONCAT(Active.displaypath, ' - ', SUBSTRING_INDEX(Active.source, ':/alm:', -1)) AS Description,
|
||||
CASE Active.priority
|
||||
WHEN 0 THEN 'Diagnostic'
|
||||
WHEN 1 THEN 'Low'
|
||||
WHEN 2 THEN 'Medium'
|
||||
WHEN 3 THEN 'High'
|
||||
WHEN 4 THEN 'Critical'
|
||||
ELSE 'Unknown'
|
||||
END AS Priority,
|
||||
CONCAT(
|
||||
Active.displaypath,
|
||||
'.HMI.',
|
||||
SUBSTRING_INDEX(aed.strValue, '/', -1)
|
||||
) AS Tag,
|
||||
SUBSTRING_INDEX(SUBSTRING_INDEX(aed.strValue, '/', 2), '/', -1) AS Location
|
||||
FROM Active
|
||||
LEFT JOIN SingleMyTag aed
|
||||
ON aed.id = Active.id
|
||||
ORDER BY Active.eventtime DESC;
|
||||
@ -0,0 +1,40 @@
|
||||
{
|
||||
"scope": "DG",
|
||||
"version": 2,
|
||||
"restricted": false,
|
||||
"overridable": true,
|
||||
"files": [
|
||||
"query.sql"
|
||||
],
|
||||
"attributes": {
|
||||
"useMaxReturnSize": false,
|
||||
"autoBatchEnabled": false,
|
||||
"fallbackValue": "",
|
||||
"maxReturnSize": 100,
|
||||
"cacheUnit": "SEC",
|
||||
"type": "Query",
|
||||
"enabled": true,
|
||||
"cacheAmount": 1,
|
||||
"cacheEnabled": false,
|
||||
"database": "MariaDB",
|
||||
"fallbackEnabled": false,
|
||||
"lastModificationSignature": "d4eef6a8194fc16fb2061c0ffe057909fb37ddedbe4fd6e4f2416cc6050f6209",
|
||||
"permissions": [
|
||||
{
|
||||
"zone": "default",
|
||||
"role": ""
|
||||
}
|
||||
],
|
||||
"lastModification": {
|
||||
"actor": "admin",
|
||||
"timestamp": "2025-06-23T10:38:45Z"
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"type": "Parameter",
|
||||
"identifier": "priorityList",
|
||||
"sqlType": 7
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,8 @@ WITH Active AS (
|
||||
LEFT JOIN alarm_events ae_clear
|
||||
ON ae.eventid = ae_clear.eventid AND ae_clear.eventtype = 1
|
||||
WHERE ae.eventtype = 0
|
||||
AND ae.displaypath NOT LIKE '%System Startup%'
|
||||
AND ae.source NOT LIKE '%System Startup%'
|
||||
GROUP BY ae.id -- Ensure one row per alarm
|
||||
),
|
||||
SingleMyTag AS (
|
||||
|
||||
@ -46,6 +46,8 @@ FROM (
|
||||
LEFT JOIN alarm_events ae_clear
|
||||
ON ae.eventid = ae_clear.eventid AND ae_clear.eventtype = 1
|
||||
WHERE ae.eventtype = 0
|
||||
AND ae.displaypath NOT LIKE '%System Startup%'
|
||||
AND ae.source NOT LIKE '%System Startup%'
|
||||
) AS Active
|
||||
|
||||
-- OPC tag path for building .hmi.Tag output
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user