Skip to content

Instantly share code, notes, and snippets.

@ali1234
Last active October 22, 2016 19:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ali1234/0b1f793ac693081cc8a29f7e874404fa to your computer and use it in GitHub Desktop.
Save ali1234/0b1f793ac693081cc8a29f7e874404fa to your computer and use it in GitHub Desktop.
Python Restful Control Panel
#!/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