Skip to content

Commit

Permalink
Add halfmetre dashboard.
Browse files Browse the repository at this point in the history
  • Loading branch information
pchote committed Aug 23, 2023
1 parent 9e4dfa2 commit 09f3597
Show file tree
Hide file tree
Showing 7 changed files with 293 additions and 588 deletions.
91 changes: 34 additions & 57 deletions dashboard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,31 @@
GENERATED_DATA_DIR = os.path.join(os.path.dirname(__file__), '..', 'generated')

W1M_GENERATED_DATA = {
'blue': 'dashboard-BLUE.json',
'blue/thumb': 'dashboard-BLUE-thumb.jpg',
'blue/clip': 'dashboard-BLUE-clip.jpg',
'red': 'dashboard-RED.json',
'red/thumb': 'dashboard-RED-thumb.jpg',
'red/clip': 'dashboard-RED-clip.jpg',
}

CLASP_GENERATED_DATA = {
'cam1': 'dashboard-CAM1.json',
'cam1/thumb': 'dashboard-CAM1-thumb.jpg',
'cam1/clip': 'dashboard-CAM1-clip.jpg',
'cam2': 'dashboard-CAM2.json',
'cam2/thumb': 'dashboard-CAM2-thumb.jpg',
'cam2/clip': 'dashboard-CAM2-clip.jpg',
}

HALFMETRE_GENERATED_DATA = {
'thumb': 'dashboard-HALFMETRE-thumb.jpg',
'clip': 'ddashboard-HALFMETRE-clip.jpg',
}

SUPERWASP_GENERATED_DATA = {
'cam1': 'dashboard-1.json',
'cam1/thumb': 'dashboard-1-thumb.jpg',
'cam1/clip': 'dashboard-1-clip.jpg',
'cam2': 'dashboard-2.json',
'cam2/thumb': 'dashboard-2-thumb.jpg',
'cam2/clip': 'dashboard-2-clip.jpg',
'cam3': 'dashboard-3.json',
'cam3/thumb': 'dashboard-3-thumb.jpg',
'cam3/clip': 'dashboard-3-clip.jpg',
'cam4': 'dashboard-4.json',
'cam4/thumb': 'dashboard-4-thumb.jpg',
'cam4/clip': 'dashboard-4-clip.jpg',
}
Expand Down Expand Up @@ -151,7 +148,7 @@ def get_user_account():

# https://github.com/orgs/warwick-one-metre/teams/observers
if is_github_team_member(user, 2128810):
permissions.update(['w1m', 'infrastructure_log', 'satellites'])
permissions.update(['w1m', 'halfmetre', 'infrastructure_log', 'satellites'])

# https://github.com/orgs/GOTO-OBS/teams/ops-team/
if is_github_team_member(user, 2308649):
Expand Down Expand Up @@ -263,6 +260,23 @@ def superwasp_generated_data(path):
abort(404)


@app.route('/halfmetre/')
def halfmetre_dashboard():
account = get_user_account()
if 'halfmetre' not in account['permissions']:
return redirect(url_for('site_overview'))

return render_template('halfmetre.html', user_account=get_user_account())


@app.route('/data/halfmetre/<path:path>')
def halfmetre_generated_data(path):
account = get_user_account()
if 'halfmetre' in account['permissions'] and path in HALFMETRE_GENERATED_DATA:
print(HALFMETRE_GENERATED_DATA[path])
return send_from_directory(GENERATED_DATA_DIR, HALFMETRE_GENERATED_DATA[path])
abort(404)

@app.route('/goto1/')
def goto1_dashboard():
account = get_user_account()
Expand Down Expand Up @@ -314,6 +328,7 @@ def site_overview():
authorised_goto = user_account is not None and 'goto' in user_account['permissions']
authorised_satellites = user_account is not None and 'satellites' in user_account['permissions']
authorised_onemetre = user_account is not None and 'w1m' in user_account['permissions']
authorised_halfmetre = user_account is not None and 'halfmetre' in user_account['permissions']
authorised_extcams = authorised_goto or authorised_satellites

authorised = len(user_account['permissions']) > 0
Expand All @@ -334,7 +349,7 @@ def site_overview():
internal_cameras = [
SiteCamera('goto1', 'GOTO 1', authorised=authorised_goto, video=True, audio=True, light=True, infrared=True),
SiteCamera('goto2', 'GOTO 2', authorised=authorised_goto, video=True, audio=True, light=True, infrared=True),
SiteCamera('halfmetre', 'Half Metre', authorised=authorised_satellites, video=True, audio=True, light=True, infrared=True),
SiteCamera('halfmetre', 'Half Metre', authorised=authorised_halfmetre, video=True, audio=True, light=True, infrared=True),
SiteCamera('w1m', 'W1m', authorised=authorised_onemetre, video=True, audio=True, light=True, infrared=True),
SiteCamera('superwasp', 'SuperWASP', authorised=authorised_satellites, video=True, audio=True, light=True, infrared=True),
SiteCamera('clasp', 'CLASP', authorised=authorised_satellites, video=True, audio=True, light=True, infrared=True)
Expand Down Expand Up @@ -477,7 +492,7 @@ def clasp_log():
@app.route('/data/halfmetre/log')
def halfmetre_log():
account = get_user_account()
if 'satellites' not in account['permissions']:
if 'halfmetre' not in account['permissions']:
abort(404)

return fetch_log_messages({
Expand All @@ -488,6 +503,7 @@ def halfmetre_log():
'pipelined@halfmetre': 'pipeline',
'qhy_camd@halfmetre': 'cam',
'diskspaced@halfmetre': 'diskspace',
'focusd@halfmetre': 'focus'
})


Expand Down Expand Up @@ -741,55 +757,16 @@ def superwasp_dashboard_data():

@app.route('/data/halfmetre/')
def halfmetre_dashboard_data():
data = json.load(open(GENERATED_DATA_DIR + '/halfmetre-public.json'))
account = get_user_account()
if 'halfmetre' not in account['permissions']:
abort(404)

# Some private data is needed for the public info
data = json.load(open(GENERATED_DATA_DIR + '/halfmetre-public.json'))
private = json.load(open(GENERATED_DATA_DIR + '/halfmetre-private.json'))
data.update(private)

account = get_user_account()
if 'satellites' in account['permissions']:
data.update(private)

# Extract safe public info from private daemons
private_ops = private.get('superwasp_ops', {})
private_telescope = private.get('superwasp_telescope', {})
private_roof = private.get('superwasp_roof', {})

# Tel status:
# 0: error
# 1: offline
# 2: online
tel_status = 0
if 'state' in private_telescope:
tel_status = 1 if private_telescope['state'] == 0 else 2

# Roof status:
# 0: error
# 1: closed
# 2: open
roof_status = 0
if 'status' in private_roof and 'heartbeat_status' in private_roof:
if private_roof['heartbeat_status'] != 2:
roof_status = 1 if private_roof['status'] == 1 else 2

roof_mode = 0
if 'dome' in private_ops and 'mode' in private_ops['dome']:
roof_mode = private_ops['dome']['mode']

tel_mode = 0
if 'telescope' in private_ops and 'mode' in private_ops['telescope']:
tel_mode = private_ops['telescope']['mode']

env = {}
if 'environment' in private_ops:
env = private_ops['environment']

data['wasp_status'] = {
'tel': tel_status,
'roof': roof_status,
'tel_mode': tel_mode,
'roof_mode': roof_mode,
'environment': env
data['previews'] = {
'halfmetre': json.load(open(GENERATED_DATA_DIR + '/dashboard-HALFMETRE.json'))
}

response = jsonify(**data)
Expand Down
122 changes: 122 additions & 0 deletions dashboard/templates/halfmetre.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
{% extends "layout.html" %}
{% set title = '0.5m &raquo; Dashboard' -%}
{% set active_page = 'halfmetre-dashboard' -%}
{% block body %}
<div class="row dashboard-stats">
<div class="col-lg-3 col-md-6 col-xs-12 g-2">
<div class="list-group rounded-0">
<span class="list-group-item" data-index='["halfmetre_ops", "environment"]' data-generator="opsConditions" data-bs-toggle="tooltip" data-bs-placement="right">Environment</span>
<span class="list-group-item" data-index='["halfmetre_domealert", "tel_room_temp"]' data-generator="envLatestMinMax" data-units=" &deg;C">Tel. Rm. Temp.</span>
<span class="list-group-item" data-index='["halfmetre_domealert", "tel_room_humidity"]' data-generator="envLatestMinMax" data-units=" %RH">Tel. Rm. Humidity</span>
<span class="list-group-item" data-index='["halfmetre_aircon", "instrument_room"]' data-generator="powerInstrAircon">Tel. Rm. Aircon</span>
<span class="list-group-item" data-index='["halfmetre_domealert", "comp_room_temp"]' data-generator="envLatestMinMax" data-units=" &deg;C">Comp Room Temp.</span>
</div>
</div>
<div class="col-lg-3 col-md-6 col-xs-12 g-2">
<div class="list-group rounded-0">
<span class="list-group-item" data-index='["halfmetre_power"]' data-generator="powerUPS" data-prefix="ups1">UPS 1</span>
<span class="list-group-item" data-index='["halfmetre_power"]' data-generator="powerUPS" data-prefix="ups2">UPS 2</span>
<span class="list-group-item" data-index='["halfmetre_power", "ats_source"]' data-generator="powerATS">ATS</span>
<span class="list-group-item" data-index='["halfmetre_power", "clight"]' data-generator="powerOffOn">Comp. Rm. Light</span>
<span class="list-group-item" data-index='["halfmetre_power", "ilight"]' data-generator="powerOffOn">Tel. Rm. Light</span>
</div>
</div>
<div class="col-lg-3 col-md-6 col-xs-12 g-2">
<div class="list-group rounded-0">
<span class="list-group-item" data-mount-index='["halfmetre_telescope"]' data-power-index='["halfmetre_power", "mount"]' data-generator="mountState">Mount</span>
<span class="list-group-item" data-index='["halfmetre_telescope"]' data-generator="mountRADec">RA / Dec</span>
<span class="list-group-item" data-index='["halfmetre_telescope"]' data-generator="mountAltAz">Alt / Az</span>
<span class="list-group-item" data-index='["halfmetre_telescope"]' data-generator="mountSunMoon">Sun / Moon Sep.</span>
<span class="list-group-item" data-focuser-index='["halfmetre_focus"]' data-power-index='["halfmetre_power", "focuser"]' data-generator="halfmetreMirrorTemperature">Mirrors Temp.</span>
</div>
</div>
<div class="col-lg-3 col-md-6 col-xs-12 g-2">
<span class="m-0 text-center list-group-item" id="data-updated">Loading...</span>
<div class="list-group rounded-0">
<span class="list-group-item" data-index='["halfmetre_roof", "status"]' data-generator="roofState">Roof</span>
<span class="list-group-item" data-index='["halfmetre_roof"]' data-generator="roofHeartbeat">Heartbeat</span>
<span class="list-group-item" data-index='["halfmetre_power", "roofcharger"]' data-generator="powerOnOff">Roof Charger</span>
<span class="list-group-item" data-index='["halfmetre_roof", "battery_voltage_mean"]' data-generator="roofBattery" data-units=" V">Roof Battery</span>
</div>
</div>
</div>
<div class="row dashboard-stats">
<div class="col-lg-8 col-md-12">
<div class="row">
<div class="col-12 g-2">
<div class="list-group rounded-0">
<span class="list-group-item text-center fw-bold">Action Queue</span>
<div class="list-group-item overflow-y-scroll" style="height: 123px" data-index='["halfmetre_ops", "telescope"]' data-notify="opsActionsQueue">
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 col-xs-12 g-2">
<div class="list-group rounded-0">
<span class="list-group-item" data-index='["halfmetre_ops", "dome"]' data-type="open" data-generator="opsDomeTime">Dome Open</span>
</div>
</div>
<div class="col-md-6 col-xs-12 g-2">
<div class="list-group rounded-0">
<span class="list-group-item" data-index='["halfmetre_ops", "dome"]' data-type="close" data-generator="opsDomeTime">Dome Close</span>
</div>
</div>
</div>
</div>
<div class="col-lg-4 col-md-12 g-2">
<div class="list-group rounded-0">
<span class="list-group-item" data-cam-index='["halfmetre_cam","state"]' data-power-index='["halfmetre_power", "camera"]' data-generator="qhyState">Camera</span>
<span class="list-group-item" data-index='["halfmetre_cam"]' data-generator="qhyExposure">Exposure</span>
<span class="list-group-item" data-index='["halfmetre_cam"]' data-generator="qhyTemperature">Temperature</span>
<span class="list-group-item" data-index='["halfmetre_cam"]' data-generator="qhyFilter">Filter</span>
<span class="list-group-item" data-index='["halfmetre_diskspace", "data_fs_available_bytes"]' data-generator="diskSpaceGB" data-units=" GB">Disk Space</span>
<span class="list-group-item" data-focuser-index='["halfmetre_focus"]' data-power-index='["halfmetre_power", "focuser"]' data-focuser="1" data-generator="focusState">Focus</span>
</div>
</div>
</div>
<div id="preview-container" class="row dashboard-stats">
<div id="container" class="col-lg-8 col-md-12 g-2">
<div class="list-group list-group-item h-100 p-0 rounded-0" style="max-height: 502px">
<img id="preview-image" src="/data/halfmetre/thumb" data-url="/data/halfmetre/thumb" data-notify="previewImage" data-cam="halfmetre" width="100%" height="100%" class="bg-black object-fit-contain">
</div>
</div>
<div class="col-lg-4 col-md-12 g-2">
<div class="row">
<div class="col mb-2">
<div id="preview-info" class="list-group rounded-0">
<span class="list-group-item fw-bold text-center" data-notify="previewHeader" data-cam="halfmetre">Preview</span>
<span class="list-group-item" data-index='["previews"]' data-generator="previewTimestamp" data-cam="halfmetre">Exposure started</span>
<span class="list-group-item" data-index='["previews"]' data-generator="previewExposure" data-cam="halfmetre">Exposure length</span>
<span class="list-group-item" data-index='["previews"]' data-generator="previewType" data-cam="halfmetre">Type</span>
<span class="list-group-item" data-index='["previews"]' data-generator="previewOverheads" data-cam="halfmetre">Overheads</span>
<span class="list-group-item" data-index='["previews"]' data-generator="previewFilename" data-cam="halfmetre">Saved as</span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<div class="list-group rounded-0">
<div class="list-group-item overflow-y-scroll pt-0" style="height: 295px">
<table id="log-table" class="w-100"></table>
</div>
</div>
</div>
</div>
</div>
</div>

<script src="{{ url_for('static', filename='dashboard.js') }}"></script>
<script src="{{ url_for('static', filename='rockit-dashboard.js') }}"></script>
<script src="{{ url_for('static', filename='fetch-logs.js') }}"></script>
<script>
$(document).ready(function () {
const initial_camera = $(location).attr('hash').substr(1);
if ($("#thumb-" + initial_camera).length > 0)
selectPreview(initial_camera);

pollDashboard('{{ url_for('halfmetre_dashboard_data') }}');
pollLog('{{ url_for('halfmetre_log') }}');
});
</script>
{% endblock %}
Loading

0 comments on commit 09f3597

Please sign in to comment.