Commit ab9e5516 authored by kliment's avatar kliment

Merge pull request #234 from beardface/experimental

Added web interface
parents 97964293 48f82b90
......@@ -4,6 +4,20 @@ Printrun consists of printcore, pronsole and pronterface, and a small collection
* pronsole.py is an interactive command-line host software with tabcompletion goodness
* pronterface.py is a graphical host software with the same functionality as pronsole
# Modifications by Beardface (Webinterface)
## Webinterface Dependencies
Cherrypy is required for the web interface. In my branch it is available in the libs folder, install by opening a
command prompt there and running python setup.py install. You can also download and install from cherrypy.
## Webinterface Configuration
* The Web interface port / ip is configurable in http.config
* The Default User / Password can be set in auth.config
## Webinterface Styling
* css/style.css can be modified to change the style of the Web Interface.
# INSTALLING DEPENDENCIES
## Windows
......
[user]
user = admin
pass = password
\ No newline at end of file
#title
{
text-align:center;
color:red;
}
#mainmenu
{
margin: 0;
padding: 0 0 20px 10px;
border-bottom: 1px solid #000;
}
#mainmenu ul, #mainmenu li
{
margin: 0;
padding: 0;
display: inline;
list-style-type: none;
}
#mainmenu a:link, #mainmenu a:visited
{
float: left;
line-height: 14px;
font-weight: bold;
margin: 0 10px 4px 10px;
text-decoration: none;
color: #999;
}
#mainmenu a:link#current, #mainmenu a:visited#current, #mainmenu a:hover
{
border-bottom: 4px solid #000;
padding-bottom: 2px;
background: transparent;
color: #000;
}
#mainmenu a:hover { color: #000; }
#content{
padding-top: 25px;
}
#controls{
float:left;
padding:0 0 1em 0;
overflow:hidden;
width:71%; /* right column content width */
left:102%; /* 100% plus left column left padding */
}
#control_xy{
display:inline;
}
#control_z{
display:inline;
position:absolute;
}
#gui{
float:left;
padding:0 0 1em 0;
overflow:hidden;
width:21%; /* left column content width (column width minus left and right padding) */
left:6%; /* (right column left and right padding) plus (left column left padding) */
}
#controls
{
width:21%; /* Width of left column content (column width minus padding on either side) */
left:31%; /* width of (right column) plus (center column left and right padding) plus (left column left padding) */
}
#controls ul
{
list-style: none;
margin: 0px;
padding: 0px;
border: none;
}
#controls ul li
{
margin: 0px;
padding: 0px;
}
#controls ul li a
{
font-size: 80%;
display: block;
border-bottom: 1px dashed #C39C4E;
padding: 5px 0px 2px 4px;
text-decoration: none;
color: #666666;
width:160px;
}
#controls ul li a:hover, #controls ul li a:focus
{
color: #000000;
background-color: #eeeeee;
}
#settings
{
margin: 0px;
padding-top: 50px;
border: none;
}
#settings table
{
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
border-width: 1px;
border-color: #999999;
border-collapse: collapse;
}
#settings table th {
background-color:#c3dde0;
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #a9c6c9;
}
#settings table tr {
background-color:#d4e3e5;
}
#settings table td {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #a9c6c9;
}
#status{
}
#console{
}
#file{
position:relative;
float:left;
width:100%;
height:20px; /* Height of the footer */
background:#eee;
}
#logframe{
}
#temp{
}
#tempmenu
{
padding: 0 0 10px 10px;
position: relative;
float: left;
width: 100%;
}
#tempmenu ul, #tempmenu li
{
margin: 0;
display: inline;
list-style-type: none;
}
#tempmenu b
{
padding-top: 4px;
float: left;
line-height: 14px;
font-weight: bold;
color: #888;
margin: 0 10px 4px 10px;
text-decoration: none;
color: #999;
}
#tempmenu a:link, #tempmenu a:visited
{
float: left;
border-bottom: 1px solid #000;
line-height: 14px;
font-weight: bold;
margin: 0 10px 4px 10px;
text-decoration: none;
color: #999;
}
#tempmenu a:link#tempmenu, #tempmenu a:visited#current, #tempmenu a:hover
{
border-bottom: 2px solid #000;
padding-bottom: 2px;
background: transparent;
color: #000;
}
#tempmenu a:hover { color: #000; }
\ No newline at end of file
[global]
server.socket_host: "localhost"
server.socket_port: 8080
<?php
$pronterfaceIP = "192.168.0.102:8080"; //Format: ip:port
$curl = curl_init();
curl_setopt($curl, CURLINFO_HEADER_OUT, true);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 1);
curl_setopt($curl,CURLOPT_TIMEOUT, 1);
curl_setopt($curl, CURLOPT_URL, "http://" . $pronterfaceIP . "/status/");
$data = curl_exec($curl);
if (curl_errno($curl) || empty($data))
{
die("Printer offline");
}
curl_close($curl);
try
{
$xml = new SimpleXMLElement($data);
echo "State: " . $xml->state . "<br />";
echo "Hotend: " . round($xml->hotend, 0) . "&deg;c<br />";
echo "Bed: " . round($xml->bed, 0) . "&deg;c<br />";
if ($xml->progress != "NA")
{
echo "Progress: " . $xml->progress . "%";
}
}
catch(Exception $e)
{
echo "ERROR:\n" . $e->getMessage(). " (severity " . $e->getCode() . ")";
}
?>
\ No newline at end of file
......@@ -49,11 +49,20 @@ if os.name=="nt":
pass
from xybuttons import XYButtons
from zbuttons import ZButtons
from graph import Graph
import pronsole
webavail = True
try :
import cherrypy, webinterface
from threading import Thread
except:
print _("CherryPy is not installed. Web Interface Disabled.")
webavail = False
def dosify(name):
return os.path.split(name)[1].split(".")[0][:8]+".g"
......@@ -156,6 +165,10 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
self.cur_button=None
self.hsetpoint=0.0
self.bsetpoint=0.0
if webavail:
self.webInterface=webinterface.WebInterface(self)
self.webThread = Thread(target=webinterface.StartWebInterfaceThread, args=(self.webInterface, ))
self.webThread.start()
def startcb(self):
self.starttime=time.time()
......@@ -284,6 +297,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
print _("You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0.")
except Exception,x:
print _("You must enter a temperature. (%s)" % (repr(x),))
if webavail:
self.webInterface.AddLog("You must enter a temperature. (%s)" % (repr(x),))
def do_bedtemp(self,l=""):
try:
......@@ -317,10 +332,16 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
wx.CallAfter(self.btemp.Refresh)
else:
print _("Printer is not online.")
if webavail:
self.webInterface.AddLog("Printer is not online.")
else:
print _("You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0.")
if webavail:
self.webInterface.AddLog("You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0.")
except:
print _("You must enter a temperature.")
if webavail:
self.webInterface.AddLog("You must enter a temperature.")
def end_macro(self):
pronsole.pronsole.end_macro(self)
......@@ -340,6 +361,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
self.delete_macro(macro_name)
return
print _("Cancelled.")
if webavail:
self.webInterface.AddLog("Cancelled.")
return
self.cur_macro_name = macro_name
self.cur_macro_def = definition
......@@ -358,6 +381,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
self.capture_skip_newline = True
return
wx.CallAfter(self.logbox.AppendText,l)
if webavail:
self.webInterface.AppendLog(l)
def scanserial(self):
"""scan for available ports. return a list of device names."""
......@@ -379,6 +404,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
projectlayer.setframe(self,self.p).Show()
else:
print _("Printer is not online.")
if webavail:
self.webInterface.AddLog("Printer is not online.")
def popmenu(self):
self.menustrip = wx.MenuBar()
......@@ -453,6 +480,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
return
elif len([c for c in macro if not c.isalnum() and c != "_"]):
print _("Macro name may contain only alphanumeric symbols and underscores")
if webavail:
self.webInterface.AddLog("Macro name may contain only alphanumeric symbols and underscores")
return
else:
old_def = ""
......@@ -906,6 +935,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
def help_button(self):
print _('Defines custom button. Usage: button <num> "title" [/c "colour"] command')
if webavail:
self.webInterface.AddLog('Defines custom button. Usage: button <num> "title" [/c "colour"] command')
def do_button(self,argstr):
def nextarg(rest):
......@@ -928,6 +959,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
command=argstr.strip()
if num<0 or num>=64:
print _("Custom button number should be between 0 and 63")
if webavail:
self.webInterface.AddLog("Custom button number should be between 0 and 63")
return
while num >= len(self.custombuttons):
self.custombuttons+=[None]
......@@ -1187,6 +1220,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
self.cur_button=None
except:
print _("event object missing")
if webavail:
self.webInterface.AddLog("event object missing")
self.cur_button=None
raise
......@@ -1203,6 +1238,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
except:
pass
self.Destroy()
if webavail:
webinterface.KillWebInterfaceThread()
def do_monitor(self,l=""):
if l.strip()=="":
......@@ -1215,11 +1252,17 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
wx.CallAfter(self.monitorbox.SetValue,self.monitor_interval>0)
except:
print _("Invalid period given.")
if webavail:
self.webInterface.AddLog("Invalid period given.")
self.setmonitor(None)
if self.monitor:
print _("Monitoring printer.")
if webavail:
self.webInterface.AddLog("Monitoring printer.")
else:
print _("Done monitoring.")
if webavail:
self.webInterface.AddLog("Done monitoring.")
def setmonitor(self,e):
......@@ -1236,6 +1279,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
if not len(command):
return
wx.CallAfter(self.logbox.AppendText,">>>"+command+"\n")
if webavail:
self.webInterface.AppendLog(">>>"+command+"\n")
self.onecmd(str(command))
self.commandbox.SetSelection(0,len(command))
......@@ -1399,6 +1444,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
import shlex
param = self.expandcommand(self.settings.slicecommand).encode()
print "Slicing: ",param
if webavail:
self.webInterface.AddLog("Slicing: "+param)
pararray=[i.replace("$s",self.filename).replace("$o",self.filename.replace(".stl","_export.gcode").replace(".STL","_export.gcode")).encode() for i in shlex.split(param.replace("\\","\\\\").encode())]
#print pararray
self.skeinp=subprocess.Popen(pararray,stderr=subprocess.STDOUT,stdout=subprocess.PIPE)
......@@ -1410,6 +1457,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
self.stopsf=1
except:
print _("Failed to execute slicing software: ")
if webavail:
self.webInterface.AddLog("Failed to execute slicing software: ")
self.stopsf=1
traceback.print_exc(file=sys.stdout)
......@@ -1496,6 +1545,8 @@ class PronterWindow(wx.Frame,pronsole.pronsole):
Xtot,Ytot,Ztot,Xmin,Xmax,Ymin,Ymax,Zmin,Zmax = pronsole.measurements(self.f)
print pronsole.totalelength(self.f), _("mm of filament used in this print\n")
print _("the print goes from %f mm to %f mm in X\nand is %f mm wide\n") % (Xmin, Xmax, Xtot)
if webavail:
self.webInterface.AddLog("the print goes from %f mm to %f mm in X\nand is %f mm wide\n") % (Xmin, Xmax, Xtot)
print _("the print goes from %f mm to %f mm in Y\nand is %f mm wide\n") % (Ymin, Ymax, Ytot)
print _("the print goes from %f mm to %f mm in Z\nand is %f mm high\n") % (Zmin, Zmax, Ztot)
print _("Estimated duration (pessimistic): "), pronsole.estimate_duration(self.f)
......@@ -1762,6 +1813,8 @@ class macroed(wx.Dialog):
self.callback(self.e.GetValue().split("\n"))
def close(self,ev):
self.Destroy()
if webavail:
webinterface.KillWebInterfaceThread()
def unindent(self,text):
self.indent_chars = text[:len(text)-len(text.lstrip())]
if len(self.indent_chars)==0:
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment