Been working with this for a while and found a few helpful things, but I'm not good with AJAX yet...
I'm working to make a chromium-browser kiosk on the Raspberry Pi (which has been fine) but when in kiosk mode, there's not a "shutdown" button. I'm displaying a local HTML file in the chromium-browser and I want to create a button in the local HTML file that will shutdown the computer using AJAX/JQuery by calling a simple python code I made:
#! /usr/bin/python -u
import os
import shutil
import sys
os.system('sudo shutdown -h now')
I found this:
$.ajax({
type: "POST",
url: "~/shutdown.py",
data: { param: text}
}).done(function( o ) {
// do something
});
How do I connect this though? there's no output from my python, just want to call the python code and have the raspberry pi shutdown.
The python code when I run it in its own terminal shuts down the computer as expected.
Or if you have any other ideas for shutting down the Rpi while in Kiosk mode in the most "user friendly" way, let me know! The people using this won't know about using the terminal or SSH-ing in...
Thanks!
Probably the easiest way would be to run a local web server that listens for a request and then shuts down the computer. Instead of just displaying a local HTML file, actually serve it from flask. This gives you much more freedom, since you can run the commands server-side (even though the server and client are the same in this case) where you don't have restrictions like you do within a browser environment.
You could do this with flask.
Create a directory like this
/kiosk
/templates
index.html
app.py
The index.html is your current html page. Here is what app.py would look like.
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def index():
return render_template('index.html')
#app.route("/shutdown")
def shutdown():
os.system('sudo shutdown -h now')
if __name__ == "__main__":
app.run()
Your ajax call would look like this
$.ajax({
type: "POST",
url: "/shutdown"
});
Then just cd into the app directory and run python app.py, which starts the web application. Then open a browser and go to localhost:5000
Related
WHAT WORKS
I created a simple Web Application in Flask that takes care of operating a simple return render_template("index.html") when the root node is accessed by a Web Browser.
# app.py
from flask import Flask, render_template
app = Flask(__name__)
#app.route("/")
def show_index():
return render_template("index.html")
if __name__ == "__main__":
app.run(port=80)
The index.html is a simple page that uses tracking.js in order to get the user webcam and track his/her face in the live video stream.
Opening cmd and typing python app.py results in Running on http://127.0.0.1:80/
Accessing the above mentioned URL results in the correct display of the page, that asks me for permission to use the camera, opens it and correctly tracks my face in the live video feed. So it's all working fine till here.
WHAT DOES NOT WORKS
The problem I'm experiencing arises when I dockerize my application using Docker. docker-machine ip is 192.168.99.100
Opening cmd and typing: docker run -p 4000:80 my_face_track_app results in: Running on http://0.0.0.0:80/
Accessing 192.168.99.100:4000 results in the correct display of index.html but I am not asked anymore for permission on the camera and inspecting the JS console I read the following exception:
getUserMedia() no longer works on insecure origins
Here the full error log:
I know the error is telling me I'm not serving the page in HTTPS.
Has anyone else encountered this problem?
What would be the proper solution to the issue or a possible walkaround?
Any help will be highly appreciated, thank you a lot in advance
WHAT I HAVE TRIED TO DO IN ORDER TO SOLVE THE PROBLEM
Since an HTTPS serving of the page is needed in order for JS to execute the function getUserMedia() I tought about serving my Flask application with an SSL certificate by modifying app.py like this:
# app.py
from flask import Flask, render_template
import OpenSSL
app = Flask(__name__)
#app.route("/")
def show_index():
return render_template("index.html")
if __name__ == "__main__":
app.run(port=80, ssl_context="adhoc")
I then dockerized the app building a new image. Typing:
docker run -p 443:80 facetrackapphttps
Results in
Running on https://127.0.0.1:80
So yeah, here HTTPS is ON: the problem is that the port 80 of the HTTPS Flask App is mapped to the port 443 of the docker-machine ip 192.168.99.100.
Trying to access 192.168.99.100:443 does not work and nothing is shown.
Does anybody have an idea about how to do this?
If your application is bound to 127.0.0.1 inside the container, you're not going to be able to access it from your host. According to the flask docs, flask will bind to 127.0.0.1 by default.
You'll need to modify your service so that it binds to 0.0.0.0 inside the container:
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80, ssl_context="adhoc")
I log on my VPS with SSH method and set up a test web page with web.py
After I run the server with below command, the VPS come into the server state and I can't do other things to the VPS, e.g. open a browser to check if the server works...
Anyone know how can I do other thing with the server running? In the local computer, it seems no problem obviously.
My terminal operation screen shot
my main.py code is as follows:
# filename: main.py
import web
urls = (
'/wx', 'Handle',
)
class Handle(object):
def GET(self):
return "hello, this is a test"
if __name__ == '__main__':
app = web.application(urls, globals())
app.run()
Script is working properly. The app.run() call puts the program in an infinite loop waiting for clients to connect with it.
As #Andersson suggests, you could execute the script, putting it in the background. Or, open another SSH session and use one window for your script & another for whatever else you want to do on your server.
For production systems, you should run web.py under nginx or apache.
See http://webpy.org/cookbook/, scroll down to "Deployments", for guidance on running under Apache and Nginx.
I'm trying to set up python and flask on the arduino yun. I've managed to run python files via the /etc/config/uhttpd configuration file:
...
list interpreter ".py=/usr/bin/python"
...
The default path for the website's root is: /www in which I've placed a soft link (apps) to the sd card. So now I can run python programs: http://[ip arduino]/apps/helloworld.py
And when I make my first helloflask.py program and run that via python helloflask.py I can see the result at: http://[ip arduino]:5000
But now I want to configure the uhttpd mini webserver (which is capable to exchange information via CGI) to use the flask setup. The URI: http://flask.pocoo.org/docs/deploying/cgi/#server-setup shows some instructions... but I just don't get it. I've made a directory ../apps/uno in which I've placed a __init__.py file with the following content:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "He Flask!"
In the apps dir I've put a file: cgi.py with this content:
from wsgiref.handlers import CGIHandler
from uno import app
CGIHandler().run(app)
Now I when I browse: http://[ip arduino]/cgi.py get a server error occured, contact the administrator (I think this is the CGI interface from uhttpd).
I just don't grasp the CGI configuration for Flask/uhttpd
I looked into this too and got a little further, I was able to setup a simple hello world but once I tried to do something non-trivial I ran into a big issue that uhttpd doesn't support URL rewriting/aliasing. This means your flask app can only be served at the URL of its .py file instead of at a root like http:// (arduino IP) /flaskapp/. None of the routes inside the app will be visible and makes the whole thing unusable.
However, instead of trying to force flask into uhttpd I had great success running the built in server that flask provides. Take a look at this guide I wrote up that uses flask to serve data from a Yun: https://learn.adafruit.com/smart-measuring-cup/overview
The thing to do is add a call to app.run when the script is run, for example make your flask app look like:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello Flask!"
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True, threaded=True)
Then log in to the Yun and run the script using python. Flask's built in server should start serving the app on http:// (arduino IP) :5000/. Make sure to include the host='0.0.0.0' as it's required to listen on the Yun's external network interface. You probably also want debug=True so there are better error messages (and live reloading of the server when the code changes), and I found threaded=True helps because the default server only handles one connection at a time. The Yun is a relatively slow processor so don't expect to service a lot of concurrent requests, however it's quite capable for providing a simple REST API or web application for a few users.
If you want this server to always run on bootup, edit the /etc/rc.local file to include a call to python and your script.
Question: What would be a comparable solution to the example at this link, except implemented using gevent-socketio and Socket.io.js with bottle? I'm looking for the minimal solution that will simply pass some traffic in a loop from the client to the server and back to the client using gevent-socketio, Socket.io.js, and bottle.
Background: I have developed a simple web-app that provides a web-based terminal for a remote custom shell (cli) on the server. The browser (client) collects shell commands from a form input field, passes the command over a web-socket to a gevent.pywsgi.WSGIServer handling the requests via the geventwebsocket.WebSocketHandler handler, which supplies the command to the shell, while asynchronously returning output via the socket to a textarea field in a form in the client's browser. This is based on a great, little example provided by the bottle team:
http://bottlepy.org/docs/dev/async.html#finally-websockets
Provided here for redundancy:
example_server.py:
from bottle import request, Bottle, abort
app = Bottle()
#app.route('/websocket')
def handle_websocket():
wsock = request.environ.get('wsgi.websocket')
if not wsock:
abort(400, 'Expected WebSocket request.')
while True:
try:
message = wsock.receive()
wsock.send("Your message was: %r" % message)
except WebSocketError:
break
from gevent.pywsgi import WSGIServer
from geventwebsocket import WebSocketHandler, WebSocketError
server = WSGIServer(("0.0.0.0", 8080), app,
handler_class=WebSocketHandler)
server.serve_forever()
client.html:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var ws = new WebSocket("ws://example.com:8080/websocket");
ws.onopen = function() {
ws.send("Hello, world");
};
ws.onmessage = function (evt) {
alert(evt.data);
};
</script>
</head>
</html>
Motivation: My existing app works great in the latest version of Firefox and Chrome. IE support is non-existent, and Safari compatibility is middlin'. I'm ultimately looking for a cross-browswer solution to communicate shell commands and output between the client and server. If I had a simple example for bottle, I think I could move forward more quickly.
Incidentally, I looked at the gevent-socketio examples and even a bottle example, but all of these examples are too different from the above simple example for me to make the leap in application. (The gevent-socketio examples look nothing like the bottle apps, which which I'm familiar. And, the bottle example doesn't actually show how to communicate with the client.)
Thanks! :)
Circus! the process runner and watcher built on top of zmq, use bottle and socketio for the web interfaces:
https://github.com/mozilla-services/circus/blob/master/circus/web/circushttpd.py
https://github.com/mozilla-services/circus/blob/master/circus/web/server.py
The source code is simple enough for helping you to get started to build a bigger app with bottle and socketio.
Otherwise, I advice you to move to sockjs! which a more generic implementation with better support for different backends.
This other thread can help you :
SockJS or Socket.IO? Worth to recode ajax-based page?
I'm writing a simple python web-server on windows..
it works but now I want to run dynamic scripts (php or py) and not only html pages..
here is my code:
from BaseHTTPServer import HTTPServer
from CGIHTTPServer import CGIHTTPRequestHandler
class RequestsHandler(CGIHTTPRequestHandler):
cgi_directories = ["/www"] #to run all scripts in '/www' folder
def do_GET(self):
try:
f = open(curdir + sep + '/www' + self.path)
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(f.read())
f.close()
except IOError:
self.send_error(404, "Page '%s' not found" % self.path)
def main():
try:
server = HTTPServer(('', 80), RequestsHandler)
server.serve_forever()
except KeyboardInterrupt:
server.socket.close()
if __name__ == '__main__':
main()
if I put php code in www folder I get the page but the code isn't interpreted
what I have to do? thanks
Your First Python CGI Website
For someone making their first web server, I put this simple example together with all the needed steps to get it working. There are two files that need to be created. The first, server.py is the script that runs the web server. The second is a Python CGI script that the server will run and send its output to the browser as a "web page".
First create a project folder for the server, something like simple_server in your home directory, or wherever you like to put your projects.
In that folder create a subfolder called cgi-bin. Then copy the first script to a file, server.py and place that in simple_server. Then create the file, my_cgi_script.py and place that in the cgi-bin folder. These files are below in the body of this howto.
Directory structure should look like this:
|
-- [simple_server]
|
-- server.py
|
-- [cgi-bin]
|
-- my_cgi_script.py
You will need to set the permissions on my_cgi_script.py to make it executable - otherwise the web server can't run it to generate the web page output. If you're on Linux or MacOS, in the command shell enter:
$ chmod +x cgi-bin/my_cgi_script.py
On Windows, locate the file with the file explorer and right-click it, and make sure its permissions allow execution.
Open the command shell, and cd in to the simple_server folder and execute the server.py script:
$ cd simple_server
$ python server.py
It should run silently without any output so far. Then in a new tab in your favorite browser, browse to this URL:
http://localhost:8000/cgi-bin/my_cgi_script.py
"hello world!" should appear in the browser with a lot of whitespace as the web page (look for it in the upper left corner if you don't see it right away). There, you've done it! You've made your first website with Python CGI!
server.py
from http.server import HTTPServer, CGIHTTPRequestHandler
if __name__ == '__main__':
try:
CGIHTTPRequestHandler.cgi_directories = ['/cgi-bin']
httpd = HTTPServer(('', 8000), # localhost:8000
CGIHTTPRequestHandler) # CGI support.
print(f"Running server. Use [ctrl]-c to terminate.")
httpd.serve_forever()
except KeyboardInterrupt:
print(f"\nReceived keyboard interrupt. Shutting down server.")
httpd.socket.close()
cgi-bin/my_cgi_script.py
#!/usr/bin/env python
# The line above ^ is important. Don't leave it out. It should be at the
# top of the file.
import cgi, cgitb # Not used, but will be needed later.
print("Content-type: text/html\n\n")
print("hello world!")
If you got it running, you may be wondering
'what just happened?' server.py set up and is running a web server. It is configured to run scripts using the CGIHTTPRequestHandler. This request handler will run files within the cgi-bin folder as scripts. It uses the command shell to do this.
At the top of my_cgi_script.py, the #!/usr/bin/env python line tells the command shell to execute the code in the file using the Python interpreter.
The URL you entered in the browser is understood by the server as a path to a file - in this case the CGI script, my_cgi_script.py, under the cgi-bin folder: http://localhost:8000/cgi-bin/my_cgi_script.py
If you take a look at the command shell that the server is running in, you can see messages detailing the web traffic it's handled. Each time you access this server process, it will output more messages - go ahead and try refresh in the browser and watch it.
You can now modify my_cgi_script.py to output more text, or you could have it output HTML tags and generate a more interesting web page.
To create a web page that incorporates the CGI script, create a file named index.html and place it in the folder with server.py - the content for index.html is below.
index.html
<!DOCTYPE html>
<html>
<body>
<h1>My First Heading</h1>
<p>My first paragraph.</p>
<!-- Simple example to include text from the CGI script in this web page. -->
<object type="text/html" data="/cgi-bin/my_cgi_script.py"></object>
</body>
</html>
The directory structure should now look like this:
|
-- [simple_server]
|
-- server.py
|
-- index.html
|
-- [cgi-bin]
|
-- my_cgi_script.py
Once that's done, if you stopped the server process, start it up again and try browsing to http://localhost:8000 and verify you see "hello world!" below "My first paragraph." index.html is a special file name that web servers use as the default page for their URL's. Now you have all the basics in place to create a great website!
Moving forward, there are various opinions on what the best web development framework should be for learning, or serious development. From this example you should get a sense for very basic configuration, setup, and browser/server interaction.
So now, the question is where to go from here? You could continue to pursue the above model, and learn how to put more functionality into the basic site using Python CGI scripts, and bind them to form actions in the HTML page. That would be a perfectly valid path, and you'd likely learn a lot.
Someone recommended to me a good site that uses a production quality web server called Django. From what I gather, it has very good tutorials and other resources to help get started in web development.
That site is Django Girls Tutorial. Don't be put off by the name of the site, anyone can benefit from the tutorial and it provides a very good introduction to the tools and technology you'll need to progress in web development with Django.
Django Girls is an active developer community for women that hosts events around the world, and connects them with others that can help with their progress.
Django Girls Tutorial: https://tutorial.djangogirls.org/en/
More in-depth Python CGI examples: https://www.tutorialspoint.com/python/python_cgi_programming.htm
For learning HTML, this site has good tutorials: https://www.w3schools.com/html/default.asp
Reference on the CGI support module, cgi: https://docs.python.org/3/library/cgi.html
Documentation that includes the classes used in this example can be found within: https://docs.python.org/2/library/internet.html
I think you are over engineering.
#!/usr/bin/env python
import CGIHTTPServer
def main():
server_address = ('', 8000)
handler = CGIHTTPServer.CGIHTTPRequestHandler
handler.cgi_directories = ['/cgi']
server = CGIHTTPServer.BaseHTTPServer.HTTPServer(server_address, handler)
try:
server.serve_forever()
except KeyboardInterrupt:
server.socket.close()
if __name__ == '__main__':
main()
Did you make the php file executable??
chmod +x spam.php (for Linux, I have no Idea how to make files executable on windows)
You would need the PHP interpreter installed on your PC as well
source from a reply HERE
You should also consider using THIS as an indirect alternative.
The problem is with the CGIHTTPServer Class. It doesn't set CGI env variables.
This has been fixed here:
https://github.com/gabrielgrant/tonto/blob/master/tonto.py