Created API V1
This commit is contained in:
parent
d04943c944
commit
973ccf67ab
8 changed files with 132 additions and 18 deletions
1
openflexure_microscope/api/__init__.py
Normal file
1
openflexure_microscope/api/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from . import utilities
|
||||
9
openflexure_microscope/api/templates/index_v1.html
Normal file
9
openflexure_microscope/api/templates/index_v1.html
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Video Streaming Demonstration</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Video Streaming Demonstration</h1>
|
||||
<img src="{{ url_for('stream') }}">
|
||||
</body>
|
||||
</html>
|
||||
15
openflexure_microscope/api/utilities.py
Normal file
15
openflexure_microscope/api/utilities.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
def parse_payload(request):
|
||||
"""Convert request to JSON. Will eventually handle error-checking."""
|
||||
# TODO: Handle invalid JSON payloads
|
||||
state = request.get_json()
|
||||
return state
|
||||
|
||||
|
||||
def gen(camera):
|
||||
"""Video streaming generator function."""
|
||||
while True:
|
||||
# the obtained frame is a jpeg
|
||||
frame = camera.get_frame()
|
||||
|
||||
yield (b'--frame\r\n'
|
||||
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
|
||||
|
|
@ -11,34 +11,19 @@ from flask import (
|
|||
|
||||
import numpy as np
|
||||
|
||||
from openflexure_microscope.api.utilities import parse_payload, gen
|
||||
from openflexure_microscope.camera.pi import StreamingCamera
|
||||
|
||||
app = Flask(__name__)
|
||||
cam = StreamingCamera()
|
||||
|
||||
|
||||
def parse_payload(request):
|
||||
"""Convert request to JSON. Will eventually handle error-checking."""
|
||||
# TODO: Handle invalid JSON payloads
|
||||
state = request.get_json()
|
||||
return state
|
||||
|
||||
|
||||
def gen(camera):
|
||||
"""Video streaming generator function."""
|
||||
while True:
|
||||
# the obtained frame is a jpeg
|
||||
frame = camera.get_frame()
|
||||
|
||||
yield (b'--frame\r\n'
|
||||
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')
|
||||
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
"""Video streaming home page."""
|
||||
cam.start_worker() # Start the stream
|
||||
return render_template('index.html')
|
||||
return render_template('index_v0.html')
|
||||
|
||||
|
||||
@app.route('/stream')
|
||||
85
openflexure_microscope/api/v1.py
Normal file
85
openflexure_microscope/api/v1.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
TODO: Implement stage control methods
|
||||
TODO: Reimplement capture methods
|
||||
TODO: Implement API route to cleanly shut down server
|
||||
TODO: Implement microscope function API routes (autofocus etc)
|
||||
"""
|
||||
|
||||
from pprint import pprint
|
||||
from importlib import import_module
|
||||
import time
|
||||
import datetime
|
||||
|
||||
from flask import (
|
||||
Flask, render_template, Response,
|
||||
redirect, request, jsonify, send_file)
|
||||
|
||||
import numpy as np
|
||||
|
||||
from openflexure_microscope.api.utilities import parse_payload, gen
|
||||
|
||||
from openflexure_microscope import Microscope
|
||||
from openflexure_microscope.camera.pi import StreamingCamera
|
||||
from openflexure_stage import OpenFlexureStage
|
||||
|
||||
import logging, sys
|
||||
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
|
||||
|
||||
|
||||
# Create the microscope object globally (common to all spawned server threads)
|
||||
microscope = Microscope(
|
||||
StreamingCamera(),
|
||||
OpenFlexureStage("/dev/ttyUSB0")
|
||||
)
|
||||
|
||||
# Create flask app
|
||||
app = Flask(__name__)
|
||||
|
||||
# Some useful functions
|
||||
def uri(suffix, base='/api/v1'):
|
||||
return base + suffix
|
||||
|
||||
# Define front-end routes
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
"""Video streaming home page."""
|
||||
return render_template(
|
||||
'index_v1.html'
|
||||
)
|
||||
|
||||
# Define API routes
|
||||
|
||||
# Basic routes
|
||||
|
||||
@app.route(uri('/stream'))
|
||||
def stream():
|
||||
"""Video streaming route. Put this in the src attribute of an img tag."""
|
||||
global microscope
|
||||
|
||||
return Response(
|
||||
gen(microscope.camera),
|
||||
mimetype='multipart/x-mixed-replace; boundary=frame')
|
||||
|
||||
@app.route(uri('/state'))
|
||||
def state():
|
||||
"""Return JSONified microscope state"""
|
||||
global microscope
|
||||
|
||||
return jsonify(microscope.state)
|
||||
|
||||
# Positioning routes
|
||||
|
||||
@app.route(uri('/position'), methods=['GET', 'POST', 'PUT'])
|
||||
def position():
|
||||
"""Return JSONified microscope state"""
|
||||
global microscope
|
||||
|
||||
if request.method == 'POST' or request.method == 'PUT':
|
||||
logging.debug("TODO: Move stage.")
|
||||
|
||||
return jsonify(microscope.state['position'])
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', threaded=True, debug=True, use_reloader=False)
|
||||
|
|
@ -24,3 +24,22 @@ class Microscope(object):
|
|||
"""Shut down the microscope hardware."""
|
||||
self.camera.close()
|
||||
self.stage.close()
|
||||
|
||||
# Create unified state
|
||||
@property
|
||||
def state(self):
|
||||
state = {}
|
||||
|
||||
# Add stage position
|
||||
position = self.stage.position
|
||||
state['position'] = {
|
||||
'absolute': True,
|
||||
'x': position[0],
|
||||
'y': position[1],
|
||||
'z': position[2],
|
||||
}
|
||||
|
||||
# Add camera state
|
||||
state.update(self.camera.state)
|
||||
|
||||
return state
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue