Last active
October 22, 2016 19:39
-
-
Save ali1234/0b1f793ac693081cc8a29f7e874404fa to your computer and use it in GitHub Desktop.
Python Restful Control Panel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import http.server | |
import socketserver | |
from itertools import product | |
from subprocess import check_call, check_output | |
channels = 'ABCD' | |
ids = '1234' | |
devices = [x[0]+x[1] for x in product(channels.upper(), ids)] | |
commands = ['on', 'off'] | |
print(devices) | |
uihtml_header = """<html> | |
<head> | |
<title>Python Restful Control Panel</title> | |
<script type="text/javascript"> | |
function on(device) { x = new XMLHttpRequest(); x.open("GET", "/on/" + device, true); x.send(); }; | |
function off(device) { x = new XMLHttpRequest(); x.open("GET", "/off/" + device, true); x.send(); }; | |
</script> | |
<script src="https://code.jquery.com/jquery-3.1.1.js"></script> | |
<!-- Latest compiled and minified CSS --> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> | |
<!-- Optional theme --> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> | |
<!-- Latest compiled and minified JavaScript --> | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> | |
</head> | |
<body> | |
<nav class="navbar navbar-default"> | |
<div class="container-fluid"> | |
<div class="navbar-header"> | |
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> | |
<span class="sr-only">Toggle navigation</span> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
<span class="icon-bar"></span> | |
</button> | |
<a class="navbar-brand" href="https://github.com/ali1234">Python Restful Control Panel</a> | |
</div> | |
<!-- Collect the nav links, forms, and other content for toggling --> | |
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> | |
<ul class="nav navbar-nav navbar-right"> | |
<li class="dropdown"> | |
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">About <span class="caret"></span></a> | |
<ul class="dropdown-menu"> | |
<div class="container"> | |
<h4>A web control panel using Python 3, HTML, Javascript, Bootstrap, and jQuery.</h4> | |
<br /> | |
Buttons dynamically generated with Python and styled with Bootstrap. | |
<br /> | |
Javascript sends asnychronous RESTful requests to the server. | |
<br /> | |
Server handles requests and executes commands. | |
</div> | |
</ul> | |
</li> | |
</ul> | |
</div><!-- /.navbar-collapse --> | |
</div><!-- /.container-fluid --> | |
</nav> | |
<div class="container"> | |
<div class="row"> | |
""" | |
uihtml_footer = """ | |
</div> | |
</div> | |
</body> | |
</html>""" | |
uihtml_button = """ | |
<div class="col-sm-3 col-xs-6"> | |
<div class="panel panel-default"> | |
<div class="panel-heading"> | |
<h3 class="panel-title">%s</h3> | |
</div> | |
<div class="panel-body"> | |
<button class="btn btn-lg btn-default col-xs-6" style="padding:2em 0;" onClick="off('%s');">Off</button> | |
<button class="btn btn-lg btn-danger col-xs-6" style="padding:2em 0;" onClick="on('%s');">On</button> | |
</div> | |
</div> | |
</div> | |
""" | |
def button(device): | |
return uihtml_button % (device, device, device) | |
uihtml = uihtml_header + ''.join([button(d) for d in devices]) + uihtml_footer | |
PORT=8254 | |
class MyRequestHandler(http.server.BaseHTTPRequestHandler): | |
def send_content(self, code, content): | |
self.send_response(code) | |
self.send_header("Content-type", "text/html") | |
self.send_header("Content-length", len(content)) | |
self.end_headers() | |
self.wfile.write(content.encode('ascii')) | |
def do_GET(self): | |
if self.path == '/': | |
self.send_content(200, uihtml) | |
return | |
# IMPORTANT: always verify arguments are allowed, otherwise | |
# crafted requests may execute arbitrary commands! | |
t = self.path.split('/') | |
if len(t) == 3 and t[1] in commands and t[2] in devices: | |
print(' '.join(t)) | |
# run a local command: | |
#cmd = ['smjctl', t[2], t[1]] | |
#check_call(cmd) | |
self.send_content(200, "") | |
return | |
self.send_content(500, "Invalid request.") | |
return | |
Handler = MyRequestHandler | |
not_started = True | |
while not_started: | |
try: | |
httpd = socketserver.TCPServer(("", PORT), Handler) | |
not_started = False | |
except: | |
pass | |
print("running") | |
httpd.serve_forever() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment