Commit cfc5ecb2 authored by vertighel's avatar vertighel
Browse files

Started implementing control page

parent 27bf7b83
Loading
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -125,14 +125,14 @@ module = ipcam
class = Webcam
node = IPCAM

######################################
[tel_temp]
module = astelco
class = Sensor
node = CABINET
outlet1 = 1
outlet2 = 2

# [tel_temp]
# module = astelco
# class = Sensor
# node = CABINET
# outlet1 = 1
# outlet2 = 2
######################################

# [met]
# module = meteo
+14 −2
Original line number Diff line number Diff line
@@ -70,12 +70,10 @@ async def start_background_tasks():
        if parts:
            subsystems.add(parts[0])

    print("---")
    for subsys in subsystems:
        if subsys not in ("blocks", "templates"):
            asyncio.create_task(streamer.subsystem_poll_loop(subsys))
            print(subsys)
    print("---")


@web_blueprint.websocket('/socket')
@@ -203,6 +201,20 @@ async def sequencer_page():
    
    return await render_template('sequencer.html')


@web_blueprint.route('/control')
async def control_page():
    """
    Render the control page.

    Returns
    -------
    str
        The rendered HTML content.
    """
    
    return await render_template('control.html')

@web_blueprint.route('/subsystem')
@web_blueprint.route('/subsystem/')
async def subsystems():
+9 −0
Original line number Diff line number Diff line
@@ -48,6 +48,15 @@
                        Init
                    </a>
                </li>

                <li class="nav-item">
                  <a class="nav-link {% if request.endpoint == 'web.control' %}active{% endif %}"
                     href="{{ url_for('web.control_page') }}">
                    Control
                  </a>
                </li>

                
                <li class="nav-item">
                    <a class="nav-link {% if request.endpoint == 'web.status_monitor' %}active{% endif %}"
                       href="{{ url_for('web.status_monitor') }}">
+83 −0
Original line number Diff line number Diff line
{% extends "base.html" %}
{% import "macros/widgets.html" as w %}
{% import "macros/control_elements.html" as ctrl %}

{% block content %}
<div class="row g-3">
    
    <!-- LEFT: Telescope & Dome Controls -->
    <section class="col-xl-4 col-lg-6">
        {{ ctrl.mount_pointing() }}
        
        <div class="bg-dark p-3 rounded border border-secondary shadow-sm mb-3">
            {{ w.widget_input({
                "label": "Focus",
                "info": "/telescope/focuser",
                "inputs": [{"value": 0}],
                "unit": "µm",
                "buttons": [{"label": "Set", "endpoint": "/telescope/focuser", "method": "PUT"}],
                "info_list": [{"label": "status", "status": "telescope-focuser-movement"}]
            }) }}
        </div>

        <div class="bg-dark p-3 rounded border border-secondary shadow-sm">
            <h6 class="text-info mb-3">Dome & Shutter</h6>
            {{ w.widget_shutter("/dome/shutter", "/dome/shutter/movement", extra_flags=False) }}
            <aside class="row g-0 mt-2 small font-monospace">
                <div class="col-4 text-success">Az: <var data-status="dome-position-azimuth">N/A</var>°</div>
                <div class="col-4 text-success">T: <var data-status="environment-external-Temperature_meteo_station">N/A</var>°</div>
                <div class="col-4 text-success text-end">Hum: <var data-status="environment-external-Humidity_meteo_station">N/A</var>%</div>
            </aside>
        </div>
    </section>

    <!-- CENTER: Camera & Sequencer Expose -->
    <section class="col-xl-4 col-lg-6">
        {{ ctrl.camera_exposure() }}
        
        <!-- Quick status of the camera -->
        <div class="card bg-black border-secondary p-2 small font-monospace text-success">
            <div>State: <var data-status="camera-snapshot-state">N/A</var></div>
            <div>Cooler: <var data-status="camera-cooler">N/A</var> (<var data-status="camera-temperature">N/A</var>°C)</div>
        </div>
    </section>

    <!-- RIGHT: Monitors (FITS, Webcam, Output) -->
    <section class="col-xl-4 col-12">
        <div class="card bg-dark border-secondary h-100 shadow-sm">
            <div class="card-header p-0 border-secondary">
                <ul class="nav nav-tabs border-0" role="tablist">
                    <li class="nav-item"><button class="nav-link active py-2" data-bs-toggle="tab" data-bs-target="#mon-fits">FITS</button></li>
                    <li class="nav-item"><button class="nav-link py-2" data-bs-toggle="tab" data-bs-target="#mon-webcam">Webcam</button></li>
                    <li class="nav-item"><button class="nav-link py-2" data-bs-toggle="tab" data-bs-target="#mon-output">Output</button></li>
                </ul>
            </div>
            <div class="card-body p-2 bg-black overflow-auto" style="min-height: 400px;">
                <div class="tab-content">
                    <div class="tab-pane fade show active" id="mon-fits">
                         <!-- Placeholder for FITS Viewer component -->
                         <div class="text-center text-muted mt-5">FITS Monitor active</div>
                    </div>
                    <div class="tab-pane fade" id="mon-webcam">
                         <img id="webcam-snapshot" class="img-fluid w-100" alt="Webcam">
                    </div>
                    <div class="tab-pane fade" id="mon-output">
                         <div id="sequencer-output-display" class="p-3 text-info font-monospace small">
                             Waiting for template output data...
                         </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

</div>
{% endblock %}

{% block scripts %}
    <script src="{{ url_for('web.static', filename='js/control.js') }}"></script>
    <script src="{{ url_for('web.static', filename='js/webcam.js') }}"></script>
    <script src="{{ url_for('web.static', filename='js/status-stream.js') }}"></script>
    <script src="{{ url_for('web.static', filename='js/actions.js') }}"></script>
{% endblock %}
    
+143 −0
Original line number Diff line number Diff line
{# 
    control_elements.html
    ---------------------
    Specialized components for the operational control page.
#}

{% macro mount_pointing() %}
<div class="card bg-dark border-secondary shadow-sm mb-3">
    <div class="card-body">
        <h6 class="card-title text-info mb-3">Mount Pointing</h6>
        
        <ul class="nav nav-tabs nav-fill mb-3" id="pointing-tabs" role="tablist">
            <li class="nav-item">
                <button class="nav-link py-1 active" data-bs-toggle="tab" data-bs-target="#tab-radec">Ra / Dec</button>
            </li>
            <li class="nav-item">
                <button class="nav-link py-1" data-bs-toggle="tab" data-bs-target="#tab-altaz">Alt / Az</button>
            </li>
        </ul>

        <div class="tab-content">
            <!-- RaDec Tab -->
            <div class="tab-pane fade show active" id="tab-radec">
                <div class="input-group input-group-sm mb-2">
                    <span class="input-group-text bg-dark border-secondary text-muted" style="width: 80px;"> α,δ / ID </span>
                    <input type="text" class="form-control bg-black text-info border-secondary" 
                           id="in-radec" placeholder="Object or HH MM SS ±DD MM SS"
                           data-parameter="mount-target">
                    <span class="input-group-text bg-dark border-secondary text-muted">  hms ±dms / id  </span>
                </div>
            </div>
            <!-- AltAz Tab -->
            <div class="tab-pane fade" id="tab-altaz">
                <div class="input-group input-group-sm mb-2">
                    <span class="input-group-text bg-dark border-secondary text-muted">Alt</span>
                    <input type="number" class="form-control bg-black text-info border-secondary" id="in-alt" placeholder="45.0">
                    <span class="input-group-text bg-dark border-secondary text-muted">Az</span>
                    <input type="number" class="form-control bg-black text-info border-secondary" id="in-az" placeholder="180.0">
                    <span class="input-group-text bg-dark border-secondary text-muted">  °  </span>
                </div>
            </div>
        </div>

        <div class="d-flex gap-2 mt-3">
            <button class="btn btn-primary btn-sm flex-fill btn-universal" 
                    id="btn-mount-slew" data-method="POST" data-url="/telescope/coordinates/movement/radec">SLEW</button>
            <button class="btn btn-outline-danger btn-sm flex-fill btn-universal" 
                    data-method="DELETE" data-url="/telescope/coordinates/movement">STOP</button>
        </div>

        <!-- Real-time feedback bar -->
        <div class="row g-0 mt-3 pt-2 border-top border-secondary small font-monospace">
            <div class="col-6 text-success">RA: <var data-status="telescope-coordinates-radec">N/A</var></div>
            <div class="col-6 text-success text-end">HA: <var data-status="telescope-coordinates-ha">N/A</var></div>
            <div class="col-6 text-success">Alt: <var data-status="telescope-coordinates-altaz">N/A</var></div>
            <div class="col-6 text-success text-end">LST: <var data-status="telescope-coordinates-lst">N/A</var></div>
        </div>
    </div>
</div>
{% endmacro %}


{% macro camera_exposure() %}
<div class="card bg-dark border-secondary shadow-sm mb-3">
    <div class="card-body">
        <h6 class="card-title text-info mb-3">Observation (Expose)</h6>
        
        <div class="row g-2 mb-2">
            <div class="col-4">
                <label class="small text-muted">Type</label>
                <select class="form-select form-select-sm bg-black text-light border-secondary" data-parameter="observation-frametype">
                    <option value="Light">Light</option>
                    <option value="Bias">Bias</option>
                    <option value="Flat">Flat</option>
                    <option value="Dark">Dark</option>
                </select>
            </div>
            <div class="col-4">
                <label class="small text-muted">Filter</label>
                <select class="form-select form-select-sm bg-black text-light border-secondary" data-parameter="observation-filter">
                  <option value="SDSS u">SDSS u</option>
                  <option value="SDSS g">SDSS g</option>
                  <option value="SDSS r">SDSS r</option>
                  <option value="SDSS i">SDSS i</option>
                  <option value="SDSS z">SDSS z</option>
                  <option value="SDSS y">SDSS y</option>
                  <option value="SDSS FREE">Free</option>
                </select>
            </div>
            <div class="col-4">
                <label class="small text-muted">Binning</label>
                <select class="form-select form-select-sm bg-black text-light border-secondary" data-parameter="observation-binning">
                    <option value="1">1x1</option><option value="2">2x2</option><option value="3">3x3</option>
                </select>
            </div>
        </div>

        <div class="row g-2 mb-3">
            <div class="col-6">
                <label class="small text-muted">Exptime (s)</label>
                <input type="number" class="form-control form-control-sm bg-black text-info border-secondary" 
                       value="10.0" data-parameter="observation-exptime">
            </div>
            <div class="col-6">
                <label class="small text-muted">Repeat (#)</label>
                <input type="number" class="form-control form-control-sm bg-black text-info border-secondary" 
                       value="1" data-parameter="observation-repeat">
            </div>
            <div class="col-12">
                <label class="small text-muted">Object Name</label>
                <input type="text" class="form-control form-control-sm bg-black text-info border-secondary" 
                       value="Test" data-parameter="observation-object">
            </div>
        </div>

        <div class="d-flex gap-2 mb-3 align-items-center bg-black bg-opacity-25 p-2 rounded">
             <div class="form-check form-switch mb-0">
                <input class="form-check-input" type="checkbox" id="check-recenter" data-parameter="observation-recenter">
                <label class="form-check-label small text-muted" for="check-recenter">Recenter</label>
            </div>
            <div class="input-group input-group-sm ms-auto" style="max-width: 120px;">
                <input type="number" class="form-control bg-black text-info border-secondary" value="300" data-parameter="observation-box">
                <span class="input-group-text bg-dark border-secondary small">px</span>
            </div>
        </div>

        <div class="d-flex gap-2">
            <!-- This button triggers a sequencer run with the 'observation' template -->
            <button class="btn btn-success flex-fill btn-universal" 
                    id="btn-camera-expose"
                    data-method="POST" 
                    data-url="/sequencer/run">
                EXPOSE
            </button>
            <button class="btn btn-outline-danger btn-universal" 
                    data-method="DELETE" 
                    data-url="/sequencer/run">
                STOP
            </button>
        </div>
    </div>
</div>
{% endmacro %}
Loading