how to send data from separate computer to flask app - python

My use case is I have a flaskapp running
The idea is it'll just display a static page (currently using PySimpleGUI) and upon receiving the information sent from the other computer (such as the name for e.g.) then it'll show the name as a QR code. (so perhaps a constant refresh on the GUI and changing upon receiving the data)
The code setup is this way currently
#app.route('/qrcode', methods=['GET'])
def displayQrCode():
args = request.args
name = args.get('name') #
try:
img = qrcode.make(name)
img.save('checkin-qrcode.png')
# Display QR Code
qrWindowThread = threading.Thread(target=qrCodeWindowShow)
qrWindowThread.start()
print(name)
return 'Success'
except RuntimeError:
return 'Error in GET'
However, being new to Flask i am not sure how to send a string from a separate computer running jupyter notebook to this Flask app. Online tutorials show like having a form field page but i wish to not have an user input.
So for instance if the jupyter notebook code sends a post request to the ipaddress:5000 it should ideally show (correct me here: ipaddress:5000/qrcode?name=JohnDoe)
so the flask app would retrieve this JohnDoe and display it as a QR code. I can hardcode or manually access this page but how would i have it 'listen' to this /qrcode and then Get the value when it's sent. Or am i misunderstanding it all and I need to do it via another way?

EDIT:
Alright third time lucky, I think I understand what you want now. So your use case is a first computer that is displaying a GUI and running a flask server with an route that can take in a string.
There's a second computer that can send a http request to that route with a name and when that happens you want the GUI on the first computer to refresh to display a QR code of the name.
I'd solve this by having the qrcode route write that name to persistent storage. Could be anything sqlite db, an environment variable, a string in a file.
The first computer running the PySimpleGUI interface poles this persistent storage for changes, and if it sees a change then it renders a new QR code for that name and displays it.

There are multiple ways available to do that:
REST API integration
Realtime data transmission using tornado or ??
Through a base origin for data transmission
Hope you get help with this.

Related

How to give status during a post request in flask?

I've created a page that allows a user to upload an excel file, which is then parsed into it's columns and then the rows are inserted into the database 500 rows at a time.
This is isn't a terribly long process - between 25 and 90 seconds, but long enough that I would like to give the user some feedback to let them know it's actually still working - in the form of status messages and/or progress bars.
My app is written in flask like this:
app.py
from flask import Flask, render_template, request
import tqdm
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def fun():
if request.method == 'GET':
return render_template('index.html')
else:
filename = request.form['filename']
print('opening file') #change from console print to webpage
df = pandas.read_excel(filename)
print('File read.. processing data\n') #change from console to webpage
processData()
print('connecting to db....\n') #change to webpage print
db.connect()
print('connected to db! inserting rows') #change to webpage print
bulk_inserts = rows/500
for i in tqdm(range(bulk_inserts)): #wrapping tqdm around range makes a progress bar
insert500rows()
db.commit()
db.disconnect()
return 'Complete. ' + str(rows) + ' inserted.' #this gets sent as a post to the page
app.run()
I know you can only send one response to a post request, but how can I give the user status of the process if I can only send one response? Maybe I'm going about this the wrong way, but I think this is a pretty common use case. How else should I set this up if this way won't work?
For some reason marked as a duplicate of this question. That question asks how to print a continuous stream of values to a screen. Here I am asking how to send a message at certain points of execution. I think the comments provided about Flask-socketio provide a different approach to a different problem.
The "one response to one request" is a matter of how HTTP protocol works: the client sends a query and some data (the POST request), and the server responds with some other data (your "one response"). While you could technically get the server to send back pieces of the response in chunks, that is not how it works in practice; for one, browsers don't handle that too well.
You need to do this a different way. For instance, create a "side channel" with SocketIO, as the commenters helpfully suggest. Then you can send updates to the client through this side channel - instead of your prints, you would use socketio.emit.
On the client side, you would first subscribe to a SocketIO channel when the page loads. Then you would submit the file through an AJAX call (or in an separate iframe), and keep the SocketIO connection open on the page, to display the updates.
This way the POST request is separated from your "page loading". The javascript on the page remains active and can read and display progress update, and the upload (with the associated wait time) happens in background.
I would also do it like #matejcik explained in their answer, but there is also another way. What websockets does is pushing the data back to browser when there is an update. There is also the pull method.
You can send queries to the server periodically and the server will give you the update. You still have to use AJAX to send requests, and javascript's setTimeout function to wait between the queries but what you do is basically simply refreshing the page without showing it to user. It is easier to understand for beginners as the used technology is still GET. Instead of printing your new logs you add it to a string, (or an array) and when the GET request is made, you return this array, clear your text output and write this new array, both with old and new info.
This method is far less efficient than websockets but for prototyping it can be faster.

telegram bot image from url - undesired cache

I am working on a telegram bot that displays images from several webcams upon request. I fetch the images from urls and then send to the user (using bot.sendPhoto() ) My problem is that for any given webcam the filename does not change and it seems that the photo is sent from telegram's cache. So it will display the image from the first time that image was requested.
I have thought about downloading the image from the url, saving with a variable name (like a name with a timestamp in it) then sending it to the chat, this seems like an inelegant solution and was hoping for something better. Like forcing the image not to be cached on the telegram server.
I am using the python-telegram-bot wrapper, but I am not sure that it's specific to that.
Any ideas? I have tried searching but so far am turning up little.
Thanks in advance.
I had the same problem too, but i've found the simplest solution.
When you call the image, you have to add a parameter with timestamp to the image link.
Example:
http://www.example.com/img/img.jpg?a=TIMESTAMP
Where TIMESTAMP is the timestamp function based on the language you are using.
Simple but tricky ;)
I think the best way is to do the same as we do in React where also, same URL calls are first checked in the cache.
If you are using Python the best way is:
timestamp = datetime.datetime.now().isoformat()
# Above statement returns like: '2013-11-18T08:18:31.809000'
pic_url = '{0}?a={1}'.format(img_url, timestamp)
Hope that helps!
I had the same problem. I wanted to create a bot which sends an image taken by a webcam of a ski slope (webcam.example.com/image.jpg). Unfortunately, the filename and so the url never updates and telegram always sends the cached image. So I decided to alter the url passed to the api. In order to achieve this, I wrote a simple php site (example.com/photo.php) which redirects to the original url of the photo. After that, I created a folder (example.com/getphoto/) on my webspace with a .htaccess file inside. The .htaccess redirects all request in this folder to the photo.php site which redirects to the image (webcam.example.com/image.jpg). So you could add everything to the url of the folder and still get the picture (e. g. example.com/getphoto/42 or example.com/getphoto/hrte8437g). The telegram api seems to cache photos by url, so if you add always another ending to the url passed to the api, telegram doesnt use the cached version and sends the current image instead. The easiest way to always change the url is by adding the current date to it.
example.com/photo.php
<?php
header("Location: http://webcam.example.com/image.jpg");
die();
?>
example.com/getphoto/.htaccess
RewriteEngine on
RewriteRule ^(.*)$ http://example.com/photo.php
in python:
bot.sendPhoto(chat_id, 'example.com/getphoto/' + strftime("%Y-%m-%d_%H-%M-%S", gmtime()))
This workaround should also work in other languages like java or php. You just need to change the way to get the current date.

Malformed token - facebook API using Python. Encoding issue?

I've playing around in Python and the Facebook API - I'm fairly new to it! I'm copying and pasting an access token into my Python app from the Graph API Explorer as oauth_access_token manually just before execution. The simple app is a loop which performs some actions based on the status of some inputs. The loop also refreshes the token so that once the app is started with a new token, it should keep going for a longer amount of time. Snippet posted below, with IDs anonymized:
oauth_access_token="ABCDEFGHIJL"
auth_str="/oauth/access_token?grant_type=fb_exchange_token&client_id=XYZ1ABC&client_secret=[ABC2XYZ&fb_exchange_token="+oauth_access_token
graph = facebook.GraphAPI(oauth_access_token)
oauth_access_token = str(graph.request(auth_str)['access_token'])
print oauth_access_token
profile = graph.request("/me/notifications")
profile2 = graph.request("/me/inbox?fields=unseen")
I realize this isn't particularly elegant way of doing it. Bizarrely, when I do this on Windows, it works fine and I have access to the my notifcations and messages. When I do this on my Mac or Ubunutu it doesn't work and I get this error...I think it has something to do with Encoding, but I'm not sure what nor how to fix it?
Malformed access token ABCDEFGHIJK?access_token=ABCDEFGHIJK

How to accept a JSON POST?

First time here, it says to be specific... So here goes.
I'm doing a small project to connect Salesforce to my Raspberry Pi. The goal is to make a light (Think a beacon, siren-like light) flash when a high priority case comes in from a client in Salesforce. At the moment, clients usually send an email to a certain address, and this creates a case. It goes to the 'Unassigned Queue' and emails the team that this case is there waiting to be assigned.
Salesforce uses REST, so I need to be able to get the Pi to accept JSON so it can easily understand what Salesforce wants it to do.
Currently, I guess I have won half of the battle. I have a web server (Lighttpd) running on the Pi, which hosts an index page and a Python script. I am also using a Python wrapper, which allows me to easily run a command from a Telldus program I have installed. This program controls a USB RF Transmitter that I have connected, it is paired to a RF Socket, which is connected to the mains power supply with a light connected to it.
So the Python script is called power.py, and can be controlled with URL variables, so if I go to power.py?device=1&power=on&time=10&password=hunter2 that turns on device 1 for 10 seconds. I also created a POST form on the index page, which just POSTS to the python script, and runs it in the same way as using the URL variables. That all works great.
So all I need to do, is connect it to Salesforce. I would like to use REST and JSON, so that if I ever move away from Salesforce to another CRM program, it will easily be able to adapt and receive instructions from new places.
I have posted the Python script I am using here:
https://github.com/7ewis/RemotePiControl/blob/master/power.py
The Pi isn't currently allowed out of the local network, so I will need to somehow develop a way to send JSON commands, and the recieve and convert them to work using the correct variables etc. I'm not a programmer, I've just exposure to languages from hacking things and exploring. Hence why I need some guidance with this.
I have never used REST or JSON before, so what would I need to do to achieve this?
Seems like adding Flask http://flask.pocoo.org to your Raspberry Pi Webserver would be a good move. It allows server-side python to be run in response to JQuery ajax (and regular) requests. Check out a couple of examples here:
http://flask.pocoo.org/docs/patterns/jquery/
and this stack overflow question: how can I use data posted from ajax in flask?
Flask is pretty straightforward to get up and running, and is happy working with a number of servers, including Lighttpd. Writing RESTful flask is also a perfectly reasonable proposition, see: http://blog.miguelgrinberg.com/post/designing-a-restful-api-with-python-and-flask
Additionally, lots of people have used flask on the raspberry pi already-- so that could help get you up and running smoothly: http://mattrichardson.com/Raspberry-Pi-Flask/
Good luck!
Firstly don't use a Python script that prints out result directly to CGI. You will be forever debugging it.
Use a light weight framework like Flask. You can do something as simple as
from flask import Flask
application = Flask(__name__)
#application.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
# use Flask's build in json decoder
the_data = request.get_json()
# then do something with the data
return "This was a POST request, how interesting..."
else:
# request was GET rather than POST, so do something with else
return "Hello World!"
See how to configure Flask to run with Lighttpd here http://flask.pocoo.org/docs/deploying/fastcgi/
If you want to test this you can either write another Python script to send JSON data to your server (I recommend looking at the Python Requests library for this http://www.python-requests.org/en/latest/), or you can do this manually using a HTTP request builder, such as HTTPRequester for Firefox (https://addons.mozilla.org/en-US/firefox/addon/httprequester/)

Using memcached to host images

Im writing simple blogging platform in Flask microframework, and I'd like to allow users to change image on the front page but without actually writing it into filesystem. Is it possible to point src attribute in img tag to an object stored in memory?
Yes, you can do it.
Create a controller or serlvet called for example
www.yoursite.com/getImage/ID
When you execute this URL, your
program shoud connect to the memcached and return the image object
that you have previously stored in it.
Finally when in your html you add: src="www.yoursite.com/getImage/ID" the browser will execute
this url, but instead of reading a file from disk it will ask the memcached for the specific ID.
Be sure to add the correct content-type in your response from the server in order that the browser understand that you are sending an image content.
Fer

Categories

Resources