So, apparently I am trying to send data from my openCV webcam to a local sever spun using Flask. I am able to receive the data and print it on terminal, however, I am not really sure as to how to print it on a webpage.
This is my program :
from flask import jsonify, Flask, make_response,request, render_template
from flask_restful import Resource, Api
# creating the flask app
from flask import jsonify, Flask, make_response,request, render_template
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
#app.route("/getData", methods=['POST', 'GET'])
def get():
if request.method == 'POST':
textInput = request.form["data"]
print(textInput)
return render_template("text.html",text=textInput)
else:
return render_template("text.html")
#app.route("/", methods=['GET'])
def contact():
return render_template("index.html")
if __name__ == '__main__':
app.run(debug=True)
I am sending data from webcam.py using requests module via post request. The data is received and currently printed on terminal. However, I want it to be redirected to text.html.
data = {"data": res}
requests.post(url = API_ENDPOINT, data = data)
The above is the code snippet I use to send data from webcam.py to API_ENDPOINT (127.0.0.1:5000/getData).
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Sign to Speech</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html,
body {
background-color: #FFC107
}
</style>
</head>
<body>
<h4>{{text}}</h4>
</body>
</html>
The above is my text.html page under templates directory.
Any Help will be appreciated :D
The problem with your code is that you send data from OpenCV webcam to a local server and from local server you return a response to openCV webcam and that's why you see data in the terminal as you print it and you can't see data in the webpage of flask app as you don't have that data, because you have lost data at the moment you have returned a response to the openCV webcam.
In this case, you could use 1 of the 3 approaches.
Using a database, like sqlite3 and save received data from the openCV webcam, but then you will need to do more, like create models and etc.
Save data received from OpenCV webcam to a file - quicker option to verify that everything works (the one I will use in my code example)
Using flask.session and saving data to flask session and then reading from it as you would read data from python dictionary.
In these cases, when you open your flask web app in the browser, you need to read data from either DB, file or flask.session.
In this example, I will use a file named data.txt to which I will write (I will use a that means open file to append to the end of a file, then the old data will be left when you will send multiple requests from OpenCV webcam) information received from OpenCV webcam server.
from flask import Flask, request, render_template, jsonify
# creating the flask app
app = Flask(__name__)
#app.route("/getData", methods=['POST', 'GET'])
def getInfo():
if request.method == 'POST':
text_input = request.form["data"]
with open('data.txt', 'a') as data_file:
data_file.write(text_input)
return jsonify({'message': 'Data saved sucessfully!'}), 200
else:
text_input = None
with open('data.txt', 'r') as data_file:
text_input = data_file.read()
return render_template("text.html", text=text_input)
if __name__ == '__main__':
app.run(debug=True)
This way your OpenCV webcam will receive 200 response with a message. Then you can navigate to your web app /getData page, then the request method will be GET and then it will read the content of a file data.txt and will pass this to the webpage you have just opened.
Make sure that you can access data.txt, it should be placed in the same directory as your app exists (at least with this example, but you should make more appropriate structure later on or at all use the sqlite3 database for local development).
Try this below:
from flask import jsonify, Flask, make_response,request, render_template
from flask_restful import Resource, Api
# creating the flask app
app = Flask(__name__)
# creating an API object
api = Api(app)
#app.route("/getData", methods=['POST', 'GET'])
def getInfo():
textInput = request.form["data"]
print(textInput)
return render_template("text.html",text=textInput)
if __name__ == '__main__':
app.run(debug=True)
And in your HTML use Jinja like following below:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example</title>
</head>
<body>
{{ text }}
</body>
</html>
Related
I'm currently learning Flask and have recently found out about Flask-SocketIO. I've learned, that the module is based on events so that the client side can communicate with the server side, so I tried doing that. But for some reason, the events I send from the client side, don't make it to the server. I've tried fixing it for a few hours but I don't understand what is wrong with my code. Thanks for helping me!
main.py
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
#app.route("/", methods=["GET", "POST"])
def home():
return render_template("index.html")
#socketio.on('my event')
def handle_my_custom_event(json):
print('received json: ' + str(json))
if __name__ == "__main__":
socketio.run(app, debug=True)
/templates/index.html
<!DOCTYPE html>
<html lang="en">
<h1> Chat room</h1>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
var socket = io();
socket.on('connect', function() {
socket.emit('my event', {data: 'I\'m connected!'}); #Creating event when connected
});
</script>
</html>
Any time things don't go the way you think they should go, you have to look for clues left in the logs. In this case that means looking at the output of the Flask process, and the browser console.
The Flask process does not show any errors, but it does show that there was no Socket.IO connection attempted. So really this isn't a problem about events not being received, but connections don't being made.
The browser console shows this:
Uncaught SyntaxError: Private field '#Creating' must be declared in an enclosing class
You see the problem? You are using # to start a comment. That should have been a // in JavaScript.
I have need to separate my python Flask web app and running code communicating via socketio. I'm able to get messages up from the external python program to the web, but I'm unable to get events from the web detected by the python program. In effect, I'd like when a user presses a button on a web page, for the external python code to print to terminal a hello world message. In the console for this html, I'm definitely seeing "Button pressed".
<html>
<head>
<title>Listener</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.8/socket.io.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
var socket = io.connect();
$('#mybutton').on('click', function() {
socket.emit('my event', 'yodle');
console.log('Button pressed');
});
});
</script>
<button id="mybutton">Push Me!</button>
</body>
</html>
This is my basic Flask webserver code, which is working:
from flask import Flask, render_template
from flask_socketio import SocketIO
app = Flask(__name__)
app.config['SECRET_KEY'] = 'froggy'
app.debug = True
socketio = SocketIO(app, message_queue='redis://')
#app.route("/")
def index():
return render_template("index.html")
if __name__ == '__main__':
socketio.run(app, host='0.0.0.0')
This is my separate running program, which is not printing anything to terminal when the button is pressed:
from flask_socketio import SocketIO
socketio = SocketIO(message_queue='redis://', host='0.0.0.0')
def my_function_handler(data):
print("Hello World")
if __name__ == '__main__':
while True:
socketio.on_event('my event', my_function_handler)
Can anyone point me to where I'm going wrong? Many thanks in advance!
You are trying to do something that is not supported. External processes can only emit, they are not recipients. If you need to emit and receive in the external process, then I recommend that you move the Socket.IO server entirely to this process.
Apparently this behavior is not supported in socketIO according to Miguel's answer, so I'm posting my particular solution to the problem if anyone is interested. I spent a lot of time Googling, Stack Overflowing, and generally falling down rabbit holes. What I ended up doing was that as I was using redis already, I just used it to pass messages between processes. There are a ton of general downsides to this approach, but it fits my needs nicely, so here's what I did. For index.html:
<html>
<head>
<title>Listener</title>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.4.8/socket.io.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function() {
var socket = io.connect();
$('#mybutton').on('click', function() {
socket.emit('button event');
});
});
</script>
<button id="mybutton">Push Me!</button>
</body>
</html>
Server code:
from flask import Flask, render_template
from flask_socketio import SocketIO
import redis
app = Flask(__name__)
app.config['SECRET_KEY'] = 'froggy'
app.debug = True
socketio = SocketIO(app, message_queue='redis://')
r = redis.Redis("localhost")
r.set('button', 'not pressed')
#app.route("/")
def index():
return render_template("index.html")
#socketio.on('button event')
def handleMessage():
r.set('button', 'pressed')
if __name__ == '__main__':
socketio.run(app, host='0.0.0.0')
Separate running process:
import redis
r = redis.Redis("localhost")
if __name__ == '__main__':
while True:
if r.get('button') == 'pressed':
print("Button pressed!")
r.set('button', 'not pressed')
Basically I want to show a loading page while a time-consuming process takes place and then redirect to my complicated other page.
While not impossible to achieve, I recommend using javascript for this task.
Here is a small example. First lets write a very simple flask server, with one very slow endpoint.
from flask import Flask, render_template, jsonify
app = Flask(__name__)
#app.route("/")
def hello():
return render_template('redirect.html')
#app.route("/done")
def done():
return "Done!"
#app.route("/slow")
def slow():
import time
time.sleep(5)
return jsonify("oh so slow")
if __name__ == "__main__":
app.run()
Now, we can make a beautiful user experience by invoking the endpoint from javascript instead. Save it as templates/redirect.html as per usual.
<html>
<head>
<script>
function navigate() {
window.location.href = 'done'; // redirect when done!
}
fetch('slow').then(navigate); // load the slow url then navigate
</script>
</head>
<body>
Loading... <!-- Display a fancy loading screen -->
</body>
</html>
I am using below Python Flask code for reading remote user name in the web page.
and name = Request.remote_user.name is printing me REMOTE_USER as output can some one really tell me which particular configuration in web server i need to look at ? or how to get the real remote_user name into the web page.
from flask import Flask
from flask import Flask, render_template, Request, jsonify
app = Flask(__name__)
import flask
import os
import getpass
#app.route("/")
def hello():
return render_template('hello.html',name=name)
name =flask.Request.remote_user.name
if __name__ == "__main__":
app.run('localhost',8000)
and hello.html
<!doctype html>
<html>
<body>
<h1>Hello- {{ name }} </h1>
</body>
</html>
You can use
print(request.headers)
this will give you list of all session variables.
for getting a remote user
print(request.headers[X-Remote-User])
I guess we can use below code snippet initially to identify all headers and then the required one i.e. remote user
Identify all the Headers & values passed in the request
print("Headers: ", vars(request.headers))
for header in request.headers.items():
print(header)
then remote_user is available via key name X-Remote-User in the header.
remote_user = request.headers.get("X-Remote-User")
print("Remote User: ", remote_user)
I have been playing around with sending server sent events with Flask and Tornado. I took a look at this blog article:
https://s-n.me/blog/2012/10/16/realtime-websites-with-flask/
I decided to try writing my own Flask app to send server sent events as an exercise. Here is the code for my Flask app called sse_server.py:
#! /usr/bin/python
from flask import Flask, request, Response, render_template
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
app = Flask(__name__)
def event_stream():
count = 0
while True:
print 'data: {0}\n\n'.format(count)
yield 'data: {0}\n\n'.format(count)
count += 1
#app.route('/my_event_source')
def sse_request():
return Response(
event_stream(),
mimetype='text/event-stream')
#app.route('/')
def page():
return render_template('index.html')
if __name__ == '__main__':
print "Please open a web browser to http://127.0.0.1:5000."
# Spin up the app
http_server = HTTPServer(WSGIContainer(app))
http_server.listen(5000)
IOLoop.instance().start()
In my templates folder, I have a simple index.html page:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Test</title>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="//code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script type="text/javascript" src="../static/sse_client.js"></script>
</head>
<body>
<h3>Test</h3>
<ul id="output">
</ul>
</body>
</html>
In my static folder, I have a file called sse_client.js:
var queue = [];
var interval = setInterval(function(){addItem()}, 1000);
function addItem(){
if(queue.length > 0){
var item = queue[0];
queue.shift();
$('#output').append(item);
}
}
$(document).ready(
function() {
var sse = new EventSource('/my_event_source');
console.log('blah');
sse.onmessage = function(event) {
console.log('A message has arrived!');
var list_item = '<li>' + event.data + '</li>';
console.log(list_item);
queue.push(list_item);
};
})
Basically, my app's structure is
sse/
sse_server.py
static/
sse_client.js
templates/
index.html
The app displays the index page, but the data is not getting streamed to it. I have no idea what I am doing wrong. I think I need another set of eyes on this. I'm sure it's something really minor and stupid.
Tornado's WSGIContainer does not support streaming responses from wsgi apps. You can either use Flask with a multi-threaded or greenlet-based wsgi server, or use Tornado's native RequestHandler interface, but not when you're combining Flask and Tornado with WSGIContainer.
Combining Flask and Tornado is usually not a good idea; see https://github.com/mitsuhiko/flask/issues/986
To use the url "../static/sse_client.js" you need your webserver or your Flask app to serve the static JavaScript file. From the Flask docs:
To generate URLs for static files, use the special 'static' endpoint
name:
url_for('static', filename='style.css')
The file has to be stored on the filesystem as static/style.css.
Read more