diff --git a/PythonServer/screens/mcu.py b/PythonServer/screens/mcu.py index 839184e1a2226fc6011b99762f89a019639eae01..7289a83451bd1e875cdaceb0178698c9234b29e8 100755 --- a/PythonServer/screens/mcu.py +++ b/PythonServer/screens/mcu.py @@ -2,9 +2,34 @@ import epics import json import time import sys +import requests +import pandas +import datetime from threading import Thread +def get_from_archiver(pv, start_date, end_date): + try: + url = "http://archiver-utgard.cslab.esss.lu.se:17668/retrieval/data/getData.json?pv=ncount({})&from={}&to={}".format( + pv, start_date, end_date + ) + entries = int(requests.get(url).json()[0]["data"][0]["val"]) + url = "http://archiver-utgard.cslab.esss.lu.se:17668/retrieval/data/getData.json?pv=nth_{}({})&from={}&to={}".format( + int(entries // 100), pv, start_date, end_date + ) + r = requests.get(url).json()[0]["data"] + raw_data = pandas.DataFrame.from_dict(r) + return list( + zip( + (raw_data["secs"] * 1000).astype("int") + + (raw_data["nanos"] / 1e6).astype("int"), + round(raw_data["val"], 3), + ) + ) + except Exception: + return [] + + class mcuScreen(Thread): def __init__(self, stop_signal): Thread.__init__(self) @@ -20,71 +45,65 @@ class mcuScreen(Thread): "LabS-VIP:Chop-Drv-0101:Park_Stat", ] - array_points = 200 - time_interval = 24 * 3600 / array_points # 1 day + intervals = {"2w": 24 * 14, "1w": 24 * 7, "2d": 24 * 2, "1d": 24} epics_dict = {} for pv in pvs: epics_dict[pv] = epics.PV(pv, auto_monitor=True) - history = {} - for pv in pvs: - history[pv] = { - "counter": 0, - "timestamp": [0], - "value": [0], - "start": time.time(), - } - + json_dict = {} + counter = 0 while not self.stop_signal.isSet(): try: - json_dict = {} for pv in epics_dict: - json_dict[pv] = {} - if epics_dict[pv].connected: - json_dict[pv]["units"] = epics_dict[pv].units - json_dict[pv]["timestamp"] = epics_dict[pv].timestamp - value = epics_dict[pv].value - if type(value) == float: - json_dict[pv]["value"] = round(value, 3) - else: - json_dict[pv]["value"] = value - - if ( - pv == "LabS-VIP:Chop-Drv-0101:Spd_Stat" - or pv == "LabS-VIP:Chop-Drv-0101:Spd_SP" - or pv == "LabS-VIP:Chop-Drv-0101:MtrTmp_Stat" - ): - history[pv]["timestamp"][0] = int(time.time() * 1000) - history[pv]["value"][0] = round( - ( - history[pv]["value"][0] * history[pv]["counter"] - + json_dict[pv]["value"] - ) - / (history[pv]["counter"] + 1), - 3, - ) - history[pv]["counter"] += 1 - if ( - history[pv]["timestamp"][0] - > (history[pv]["start"] + time_interval) * 1000 - ): - history[pv]["timestamp"].insert( - 0, int(time.time() * 1000) + if ( + pv == "LabS-VIP:Chop-Drv-0101:Spd_Stat" + or pv == "LabS-VIP:Chop-Drv-0101:Spd_SP" + or pv == "LabS-VIP:Chop-Drv-0101:MtrTmp_Stat" + ): + if counter % 600 == 0: + if pv not in json_dict: + json_dict[pv] = {} + for interval in intervals: + start_date = ( + datetime.datetime.now() + - datetime.timedelta(hours=intervals[interval]) + ).isoformat() + "Z" + end_date = datetime.datetime.now().isoformat() + "Z" + json_dict[pv][interval] = get_from_archiver( + pv, start_date, end_date ) - history[pv]["value"].insert(0, json_dict[pv]["value"]) - history[pv]["counter"] = 1 - history[pv]["start"] = time.time() - if len(history[pv]["timestamp"]) > array_points: - history[pv]["timestamp"].pop(array_points) - history[pv]["value"].pop(array_points) - json_dict[pv]["array"] = list( - zip(history[pv]["timestamp"], history[pv]["value"]) - ) + counter = 0 + else: + if epics_dict[pv].connected: + if "live" not in json_dict[pv]: + json_dict[pv]["live"] = [] + value = epics_dict[pv].value + if type(value) == float: + json_dict[pv]["value"] = round(value, 3) + else: + json_dict[pv]["value"] = value + timestamp = int(time.time() * 1000) + if type(value) == float: + json_dict[pv]["live"].append( + (timestamp, round(value, 3)) + ) + if len(json_dict[pv]["live"]) > 100: + json_dict[pv]["live"].pop(100) else: - json_dict[pv]["units"] = "n.c." - json_dict[pv]["timestamp"] = "" - json_dict[pv]["value"] = "" + json_dict[pv] = {} + if epics_dict[pv].connected: + json_dict[pv]["units"] = epics_dict[pv].units + json_dict[pv]["timestamp"] = epics_dict[pv].timestamp + value = epics_dict[pv].value + if type(value) == float: + json_dict[pv]["value"] = round(value, 3) + else: + json_dict[pv]["value"] = value + else: + json_dict[pv]["units"] = "n.c." + json_dict[pv]["timestamp"] = "" + json_dict[pv]["value"] = "" tmp_json = json.dumps(json_dict) tmp_json = tmp_json.replace("NaN", "0") @@ -95,6 +114,7 @@ class mcuScreen(Thread): print(sys.exc_info()) time.sleep(1) time.sleep(0.5) + counter += 1 for pv in epics_dict: epics_dict[pv].clear_auto_monitor() diff --git a/WebSites/mcu/css/ess.css b/WebSites/mcu/css/ess.css index fc8cccfb7fc57fe5943eea8b887d2d0749535af2..8ad2ea955e8808a44f2fdb151188807462808766 100644 --- a/WebSites/mcu/css/ess.css +++ b/WebSites/mcu/css/ess.css @@ -94,9 +94,10 @@ overflow: hidden; border-radius: 50%; width: 22px; height: 22px; -border: 2px solid #49707e !important; +border: 2px solid #cef4ff !important; float: left; -background-color: #0b2d3c !important; +background-color:#FF1818 !important; +box-shadow: 0px 0px 15px #FF4040; margin-right: 8px !important; } diff --git a/WebSites/mcu/dashboard.json b/WebSites/mcu/dashboard.json index fd64b44c4f58e1848088460c708751a693489e26..7f4e4965090db5cd6a5031ddab02a75ee02b5db2 100644 --- a/WebSites/mcu/dashboard.json +++ b/WebSites/mcu/dashboard.json @@ -1,7 +1,7 @@ { "version": 1, "header_image": "", - "allow_edit": false, + "allow_edit": true, "plugins": [], "panes": [ { @@ -24,105 +24,102 @@ { "type": "html", "settings": { - "html": "datasources[\"Clock\"][\"numeric_value\"]; // trick to trigger the update\nvar cols = document.getElementsByClassName('gs_w')[0].getAttribute('data-sizex');\ndocument.getElementsByClassName('gs_w')[0].firstElementChild.firstElementChild.innerHTML = \"\";\nif (cols == 4){\n text = \"<div style=\\\"position: static; margin-top: -15px;\\\"><img src=\\\"../img/ess-logo.svg\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\"><div class=\\\"tw-value\\\" style=\\\"font-size: 50px; color:#ffffff !important; position: relative; bottom: 35px; left: 150px;\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\">Mini Chopper in Utgård Lab</div></img></div>\";\n}\nif (cols == 3){\n text = \"<div style=\\\"position: static; margin-top: -15px;\\\"><img src=\\\"../img/ess-logo.svg\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\"><div class=\\\"tw-value\\\" style=\\\"font-size: 40px; color:#ffffff !important; position: relative; bottom: 45px; left: 100px;\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\">Mini Chopper in Utgård Lab</div></img></div>\";\n}\n\nif (cols == 2){\n text = \"<div style=\\\"position: static; margin-top: -15px;\\\"><img src=\\\"../img/ess-logo.svg\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\"><div class=\\\"tw-value\\\" style=\\\"font-size: 24px; color:#ffffff !important; position: relative; bottom: 55px; left: 30px;\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\">Mini Chopper in Utgård Lab</div></img></div>\";\n\n}\nif (cols == 1){\n text = \"<div style=\\\"position: static; margin-top: -15px;\\\"><img src=\\\"../img/ess-logo.svg\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\"><div class=\\\"tw-value\\\" style=\\\"font-size: 30px; color:#ffffff !important; position: relative; bottom: 55px; left: 30px;\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\"></div></img></div>\";\n\tdocument.getElementsByClassName('gs_w')[0].firstElementChild.firstElementChild.innerHTML = \"Mini Chopper in Utgård Lab\";\n}\n\nreturn text", + "html": "datasources[\"Clock\"][\"numeric_value\"]; // trick to trigger the update\nvar cols = document.getElementsByClassName('gs_w')[0].getAttribute('data-sizex');\ndocument.getElementsByClassName('gs_w')[0].firstElementChild.firstElementChild.innerHTML = \"\";\nif (cols == 4){\n text = \"<div style=\\\"position: static; margin-top: -15px;\\\"><img src=\\\"../img/ess-logo.svg\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\"><div class=\\\"tw-value\\\" style=\\\"font-size: 50px; color:#ffffff !important; position: relative; bottom: 35px; left:100px;\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\">Mini Chopper in Utgård Lab</div></img></div>\";\n}\nif (cols == 3){\n text = \"<div style=\\\"position: static; margin-top: -15px;\\\"><img src=\\\"../img/ess-logo.svg\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\"><div class=\\\"tw-value\\\" style=\\\"font-size: 35px; color:#ffffff !important; position: relative; bottom: 45px; left: 60px;\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\">Mini Chopper in Utgård Lab</div></img></div>\";\n}\n\nif (cols == 2){\n text = \"<div style=\\\"position: static; margin-top: -15px;\\\"><img src=\\\"../img/ess-logo.svg\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\"><div class=\\\"tw-value\\\" style=\\\"font-size: 20px; color:#ffffff !important; position: relative; bottom: 65px; left: 20px;\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\">Mini Chopper in Utgård Lab</div></img></div>\";\n\n}\nif (cols == 1){\n text = \"<div style=\\\"position: static; margin-top: -15px;\\\"><img src=\\\"../img/ess-logo.svg\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\"><div class=\\\"tw-value\\\" style=\\\"font-size: 30px; color:#ffffff !important; position: relative; bottom: 55px; left: 30px;\\\" title=\\\"Designed by Emanuele Laface with PyEpics and Freeboard. Graphics by Dirk Nordt.\\\"></div></img></div>\";\n\tdocument.getElementsByClassName('gs_w')[0].firstElementChild.firstElementChild.innerHTML = \"Mini Chopper in Utgård Lab\";\n}\n\nreturn text", "height": 2 } } ] }, { - "title": "Warning and Alarms", + "title": "Motor Temperature", "width": 1, "row": { - "1": 25, - "2": 25, - "3": 25, - "4": 7, - "7": 7 + "1": 21, + "2": 21, + "3": 21, + "4": 21, + "5": 1, + "11": 21 }, "col": { "1": 1, "2": 1, "3": 1, - "4": 4, - "7": 4 + "4": 1, + "5": 5, + "11": 10 }, - "col_width": 1, + "col_width": 3, "widgets": [ { - "type": "ragIndicator", - "settings": { - "title": "Ref Alarm", - "value": "datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Ref_Alrm\"][\"value\"]", - "green_text": "Ok", - "amber_text": "Warning" - } - }, - { - "type": "ragIndicator", + "type": "flot_extended_plugin", "settings": { - "title": "Comm Alarm", - "value": "datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Comm_Alrm\"][\"value\"]", - "green_text": "Ok", - "amber_text": "Alarm" + "plot_type": "line", + "legend": true, + "height": 4, + "value": "var series = document.getElementById(\"time-series\").value;\ndata = [\n {label: 'Temperature', data: datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:MtrTmp_Stat\"][series]},\n];\nfreeboard.showLoadingIndicator(false);\nreturn data;", + "x_timestamp": true, + "zoom": "" } } ] }, { - "title": "Speed", + "title": "Time Selector", "width": 1, "row": { - "1": 31, - "2": 25, - "3": 25, - "4": 13, - "7": 13 + "1": 7, + "2": 7, + "3": 7, + "4": 7, + "5": 7, + "7": 7, + "8": 7, + "9": 7 }, "col": { "1": 1, - "2": 2, - "3": 2, - "4": 4, - "7": 4 + "2": 1, + "3": 1, + "4": 1, + "5": 1, + "7": 1, + "8": 1, + "9": 1 }, - "col_width": 1, + "col_width": 3, "widgets": [ { - "type": "text_widget", - "settings": { - "title": "Actual Speed", - "size": "regular", - "value": "datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Spd_Stat\"][\"value\"]", - "animate": true - } - }, - { - "type": "text_widget", + "type": "html", "settings": { - "title": "Set Point", - "size": "regular", - "value": "datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Spd_SP\"][\"value\"]", - "animate": true + "html": "<script>\n function setDatasource(event) {\n\t\tfreeboard.showLoadingIndicator(true);\n\t};\n</script>\n<div style=\"position:relative;height:100%;display:flex;flex-direction:column;justify-content:center;align-items:center;\">\n <select style=\"padding:0px 0px\" onchange=\"setDatasource()\" id=\"time-series\">\n <option value=\"2w\">Two Weeks</option>\n <option value=\"1w\">One Week</option>\n <option value=\"2d\">Two Days</option>\n <option value=\"1d\">One Day</option>\n <option value=\"live\">Live</option>\n </select>\n</div>", + "height": 1 } } ] }, { + "title": "Motor Speed", "width": 1, "row": { - "1": 7, - "2": 7, - "3": 7, - "4": 7, - "7": 1 + "1": 11, + "2": 11, + "3": 11, + "4": 11, + "5": 1, + "7": 1, + "9": 1, + "10": 1 }, "col": { "1": 1, "2": 1, "3": 1, "4": 1, - "7": 7 + "5": 5, + "7": 5, + "9": 5, + "10": 5 }, "col_width": 3, "widgets": [ @@ -132,49 +129,110 @@ "plot_type": "line", "legend": true, "height": 4, - "value": "data = [\n {label: \"Actual Speed\", data: datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Spd_Stat\"][\"array\"]},\n {label: \"Set Point\", data: datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Spd_SP\"][\"array\"]}\n]\nreturn data;", + "value": "var series = document.getElementById(\"time-series\").value;\ndata = [\n {label: 'Actual Speed', data: datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Spd_Stat\"][series]},\n {label: 'Set Point', data: datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Spd_SP\"][series]},\n];\nfreeboard.showLoadingIndicator(false);\nreturn data;", + "xticks": "6", "x_timestamp": true, "zoom": "" } + } + ] + }, + { + "title": "Warning and Alarms", + "width": 1, + "row": { + "1": 31, + "2": 31, + "3": 31, + "4": 7, + "5": 7, + "6": 7, + "7": 7, + "8": 7, + "9": 7, + "11": 7, + "12": 7 + }, + "col": { + "1": 1, + "2": 1, + "3": 1, + "4": 4, + "5": 2, + "6": 2, + "7": 2, + "8": 2, + "9": 2, + "11": 2, + "12": 2 + }, + "col_width": 1, + "widgets": [ + { + "type": "ragIndicator", + "settings": { + "title": "Ref Alarm", + "value": "datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Ref_Alrm\"][\"value\"]", + "green_text": "Ok", + "amber_text": "Warning" + } }, { - "type": "flot_extended_plugin", + "type": "indicator", "settings": { - "plot_type": "line", - "legend": true, - "height": 4, - "value": "data = [\n {label: \"Motor Status\", data: datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:MtrTmp_Stat\"][\"array\"]},\n]\nreturn data;", - "x_timestamp": true, - "zoom": "" + "title": "Comm Alarm", + "value": "!datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Comm_Alrm\"][\"value\"]", + "on_text": "Ok", + "off_text": "Alarm" } } ] }, { - "title": "Status", + "title": "Speed", "width": 1, "row": { "1": 37, "2": 31, - "3": 25, - "4": 19, - "9": 33 + "3": 31, + "4": 13, + "6": 7, + "7": 7, + "8": 7, + "11": 7, + "12": 7 }, "col": { "1": 1, - "2": 1, - "3": 3, + "2": 2, + "3": 2, "4": 4, - "9": 4 + "6": 3, + "7": 3, + "8": 3, + "11": 3, + "12": 3 }, "col_width": 1, "widgets": [ { "type": "text_widget", "settings": { + "title": "Actual Speed", "size": "regular", - "value": "value = datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Park_Stat\"][\"value\"]\nif (value == 0){\n return \"Not Parked\"\n}\n\nif (value == 1){\n return \"Parked\"\n}\n\nif (value == 2){\n return \"Parking\"\n}", - "animate": true + "value": "datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Spd_Stat\"][\"value\"]", + "animate": true, + "units": "" + } + }, + { + "type": "text_widget", + "settings": { + "title": "Set Point", + "size": "regular", + "value": "datasources[\"MCU\"][\"LabS-VIP:Chop-Drv-0101:Spd_SP\"][\"value\"]", + "animate": true, + "units": "" } } ] @@ -200,4 +258,4 @@ } ], "columns": 4 -} +} \ No newline at end of file