Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
P
Printrun
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
machinery
Printrun
Commits
218ce7f0
Commit
218ce7f0
authored
Mar 27, 2014
by
Guillaume Seguin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove prontserve.py
How many prontserve leftover did I miss ? ^^
parent
dab09cb9
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
0 additions
and
345 deletions
+0
-345
prontserve.py
printrun/prontserve.py
+0
-345
No files found.
printrun/prontserve.py
deleted
100644 → 0
View file @
dab09cb9
#!/usr/bin/env python
# This file is part of the Printrun suite.
#
# Printrun is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Printrun is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Printrun. If not, see <http://www.gnu.org/licenses/>.
import
os
,
time
,
sys
,
codecs
,
random
,
textwrap
,
re
,
traceback
import
logging
,
tornado
.
ioloop
from
.
import
pronsole
# Allow construct protocol developers to use a specific lib for dev purposes
c_path
=
os
.
getenv
(
'PY_CONSTRUCT_PATH'
)
if
c_path
!=
None
:
print
"$PY_CONSTRUCT_PATH detected, loading server lib from:
\n
%
s"
%
c_path
sys
.
path
.
insert
(
1
,
c_path
)
from
construct_server.construct_server
import
ConstructServer
from
construct_server.event_emitter
import
EventEmitter
sys
.
stdout
=
codecs
.
getwriter
(
'utf8'
)(
sys
.
stdout
)
log
=
logging
.
getLogger
(
"root"
)
# Routes
# -------------------------------------------------
class
RootHandler
(
tornado
.
web
.
RequestHandler
):
def
get
(
self
):
self
.
render
(
"index.html"
)
class
InspectHandler
(
tornado
.
web
.
RequestHandler
):
def
prepare
(
self
):
construct_auth
(
self
,
None
)
def
get
(
self
):
self
.
render
(
"inspect.html"
)
# Faster GCoder implementation without any parsing
# -------------------------------------------------
class
Line
(
object
):
__slots__
=
(
'raw'
,
'command'
,
'is_move'
)
def
__init__
(
self
,
l
):
self
.
raw
=
l
def
__getattr__
(
self
,
name
):
return
None
class
FastGCode
(
object
):
def
__init__
(
self
,
data
):
self
.
lines
=
[
Line
(
l2
)
for
l2
in
(
l
.
strip
()
for
l
in
data
)
if
l2
]
self
.
all_layers
=
[
self
.
lines
]
def
__len__
(
self
):
return
len
(
self
.
lines
)
def
__iter__
(
self
):
return
self
.
lines
.
__iter__
()
def
idxs
(
self
,
index
):
return
(
0
,
index
)
# Prontserve: Server-specific functionality
# -------------------------------------------------
class
Prontserve
(
pronsole
.
pronsole
,
EventEmitter
):
def
__init__
(
self
,
**
kwargs
):
self
.
initializing
=
True
self
.
max_w_val
=
0
pronsole
.
pronsole
.
__init__
(
self
)
EventEmitter
.
__init__
(
self
)
self
.
settings
.
sensor_names
=
{
'T'
:
'extruder'
,
'B'
:
'bed'
}
self
.
settings
.
sensor_poll_rate
=
1
# seconds
self
.
p
.
loud
=
kwargs
[
'loud'
]
self
.
dry_run
=
kwargs
[
'dry_run'
]
self
.
heaptrace
=
kwargs
[
'heaptrace'
]
self
.
stdout
=
sys
.
stdout
self
.
load_default_rc
()
self
.
p
.
sendcb
=
self
.
sendcb
self
.
initializing
=
False
dir
=
os
.
path
.
dirname
(
__file__
)
self
.
server
=
ConstructServer
(
printer
=
self
,
settings
=
dict
(
pause_between_prints
=
self
.
settings
.
pause_between_prints
,
sensor_poll_rate
=
self
.
settings
.
sensor_poll_rate
*
1000
),
components
=
dict
(
temps
=
[
"e0"
,
"b"
],
fans
=
[
"f0"
],
conveyors
=
[
"c0"
],
axes
=
[]
# In the far off future we may have axes like these for position data:
# axes= ["x", "y", "z"]
),
server_settings
=
dict
(
template_path
=
os
.
path
.
join
(
dir
,
"server"
,
"templates"
),
static_path
=
os
.
path
.
join
(
dir
,
"server"
,
"static"
),
debug
=
True
),
routes
=
[
(
r"/"
,
RootHandler
),
(
r"/inspect"
,
InspectHandler
)
]
)
def
display_startup_padding
(
self
):
if
self
.
dry_run
:
for
i
in
range
(
0
,
7
):
sys
.
stdout
.
write
(
"
\x1B
[0;33m Dry Run
\x1B
[0m"
)
print
""
def
display_startup_message
(
self
):
welcome
=
textwrap
.
dedent
(
u"""
+---+
\x1B
[0;32mProntserve: Your printer just got a whole lot better.
\x1B
[0m|
\u2713
| Ready to print.
+---+ More details at http://localhost:8888/"""
)
print
"
\n
"
+
"-"
*
80
self
.
display_startup_padding
()
sys
.
stdout
.
write
(
welcome
)
print
"
\n
"
self
.
display_startup_padding
()
print
"-"
*
80
+
"
\n
"
def
start
(
self
):
try
:
if
self
.
dry_run
==
False
:
# Attempt to connect to the printer
self
.
do_connect
(
""
)
if
self
.
p
.
printer
==
None
:
sys
.
exit
(
1
)
print
"Connecting to printer..."
# Wait for the attempt to succeed or timeout
for
x
in
range
(
0
,
50
-
1
):
if
self
.
p
.
online
==
True
:
break
sys
.
stdout
.
write
(
"."
)
sys
.
stdout
.
flush
()
time
.
sleep
(
0.1
)
print
""
if
self
.
p
.
online
==
False
:
print
"Unable to connect to printer: Connection timed-out."
sys
.
exit
(
1
)
# Wait for the printer to finish connecting and then reset it
time
.
sleep
(
2
)
self
.
reset
()
# Start the server, display the startup message and start the ioloop
self
.
server
.
start
()
self
.
display_startup_message
()
self
.
server
.
ioloop
.
start
()
except
Exception
as
ex
:
print
traceback
.
format_exc
()
if
self
.
heaptrace
:
from
guppy
import
hpy
print
hpy
()
.
heap
()
self
.
p
.
disconnect
()
exit
()
def
is_online
(
self
):
return
self
.
p
.
online
==
True
def
is_printing
(
self
):
return
self
.
p
.
printing
==
False
and
self
.
p
.
online
def
post_process_print_job
(
self
,
filename
,
filebody
):
return
FastGCode
(
filebody
.
split
(
"
\n
"
))
def
get_print_job_memory_footprint
(
self
,
filename
,
filebody
):
return
0
# TODO
def
current_print_line
(
self
):
if
(
self
.
p
.
printing
):
return
(
self
.
p
.
queueindex
)
return
0
def
total_print_lines
(
self
,
job_body
):
return
len
(
job_body
)
def
start_print_job
(
self
,
job
):
self
.
p
.
startprint
(
job
[
'body'
])
self
.
p
.
paused
=
False
def
do_home
(
self
,
*
args
,
**
kwargs
):
pronsole
.
pronsole
.
do_home
(
self
,
" "
.
join
(
args
))
def
do_move
(
self
,
**
kwargs
):
# Convert mm/s to mm/minute
if
"at"
in
kwargs
:
speed_multiplier
=
float
(
kwargs
[
'at'
]
.
replace
(
"
%
"
,
""
))
*
0.01
else
:
speed_multiplier
=
1
for
k
,
v
in
kwargs
.
iteritems
():
if
k
==
"at"
:
continue
# Getting the feedrate
if
k
in
[
"z"
,
"e"
]:
prefix
=
k
else
:
prefix
=
"xy"
speed
=
getattr
(
self
.
settings
,
"
%
s_feedrate"
%
prefix
)
*
speed_multiplier
# Creating the pronsole axial move command
args
=
{
"axis"
:
k
,
"dist"
:
v
,
"speed"
:
speed
}
cmd
=
"
%(axis)
s
%(dist)
s
%(speed)
s"
%
args
print
"move
%
s"
%
cmd
pronsole
.
pronsole
.
do_move
(
self
,
cmd
)
def
do_stop_move
(
self
):
raise
Exception
(
"Continuous movement not supported"
)
def
do_estop
(
self
):
self
.
reset
()
print
"Emergency Stop!"
# Not thread safe; must be run from the ioloop thread.
def
reset
(
self
):
self
.
async
(
self
.
server
.
set_blocking_temps
,
[])
# pause the print job if any is printing
if
self
.
p
.
printing
:
pronsole
.
pronsole
.
do_pause
(
self
,
""
)
# Prevent the sensor from polling for 2 seconds while the firmware
# restarts
self
.
server
.
set_reset_timeout
(
time
.
time
()
+
2
)
self
.
server
.
set_sensor_update_received
(
True
)
# restart the firmware
pronsole
.
pronsole
.
do_reset
(
self
,
""
)
self
.
p
.
printing
=
False
def
on_temp_target_change
(
self
,
parent_path
,
component
,
value
):
target
=
parent_path
[
0
]
gcode
=
"M104"
if
target
==
"b"
:
gcode
=
"M140"
if
not
target
in
[
"b"
,
"e0"
]:
gcode
+=
" p
%
i"
%
(
int
(
target
[
1
:]))
gcode
+=
" S
%
f"
%
float
(
value
)
self
.
p
.
send_now
(
gcode
)
def
on_fan_enabled_change
(
self
,
parent_path
,
component
,
value
):
update_fan
(
component
)
def
on_fan_speed_change
(
self
,
parent_path
,
component
,
value
):
update_fan
(
component
)
def
update_fan
(
self
,
component
):
speed
=
int
(
component
[
'speed'
])
if
component
[
'enabled'
]
==
False
:
speed
=
0
print
"M106 S
%
i"
%
speed
self
.
p
.
send_now
(
"M106 S
%
i"
%
speed
)
def
on_motors_enabled_change
(
self
,
parent_path
,
component
,
value
):
self
.
p
.
send_now
({
True
:
"M17"
,
False
:
"M18"
}[
value
])
def
request_sensor_update
(
self
):
if
self
.
dry_run
:
return
self
.
_receive_sensor_update
(
"ok T:
%
i B:
%
i"
%
(
random
.
randint
(
30
,
60
),
random
.
randint
(
30
,
60
))
)
if
self
.
p
.
online
:
self
.
p
.
send_now
(
"M105"
)
def
recvcb
(
self
,
l
):
""" Parses a line of output from the printer via printcore """
l
=
l
.
rstrip
()
#print l
if
self
.
server
.
waiting_to_reach_temp
and
(
"ok"
in
l
):
self
.
async
(
self
.
server
.
set_blocking_temps
,
[])
if
(
"T:"
in
l
):
self
.
async
(
self
.
_receive_sensor_update
,
l
)
if
l
!=
"ok"
and
not
l
.
startswith
(
"ok T"
)
and
not
l
.
startswith
(
"T:"
):
self
.
async
(
self
.
_receive_printer_error
,
l
)
def
sendcb
(
self
,
l
,
gl
):
# Monitor the sent commands for new extruder target temperatures
if
(
"M109"
in
l
)
or
(
"M104"
in
l
)
or
(
"M140"
in
l
)
or
(
"M190"
in
l
):
temp
=
float
(
re
.
search
(
'S([0-9]+)'
,
l
)
.
group
(
1
))
if
(
"M109"
in
l
)
or
(
"M104"
in
l
):
target
=
"e0"
if
" P"
in
l
:
target
=
"e
%
i"
%
(
int
(
re
.
search
(
' P([0-9]+)'
,
l
)
.
group
(
1
)))
else
:
target
=
"b"
self
.
async
(
self
.
server
.
c_set
,
[
target
,
"target_temp"
],
temp
,
internal
=
True
)
if
(
"M109"
in
l
)
or
(
"M190"
in
l
)
or
(
"M116"
in
l
):
if
(
"M116"
in
l
):
target
=
"e0"
self
.
async
(
self
.
server
.
set_blocking_temps
,
[
target
])
# Adds a callback to the ioloop to run a method later on in the server thread
def
async
(
self
,
*
args
,
**
kwargs
):
self
.
server
.
ioloop
.
add_callback
(
*
args
,
**
kwargs
)
def
_receive_sensor_update
(
self
,
l
):
try
:
self
.
async
(
self
.
server
.
set_sensor_update_received
,
True
)
words
=
filter
(
lambda
s
:
s
.
find
(
":"
)
>
0
,
l
.
lower
()
.
split
(
" "
))
d
=
dict
([
s
.
split
(
":"
)
for
s
in
words
])
for
key
,
value
in
d
.
iteritems
():
if
key
==
"t"
:
key
=
"e0"
if
not
key
in
self
.
server
.
components
:
continue
self
.
server
.
c_set
([
key
,
"current_temp"
],
float
(
value
),
internal
=
True
)
# Fire a event if the extruder is giving us a countdown till it's online
# see: TEMP_RESIDENCY_TIME (via the googles)
# see: https://github.com/ErikZalm/Marlin/blob/Marlin_v1/Marlin/Marlin_main.cpp#L1191
if
(
"w"
in
d
)
and
(
not
d
[
"w"
]
==
"?"
):
w
=
float
(
d
[
"w"
])
*
1000
for
target
in
(
self
.
server
.
blockers
):
self
.
server
.
c_set
([
target
,
"target_temp_countdown"
],
w
,
internal
=
True
)
except
Exception
as
ex
:
print
traceback
.
format_exc
()
def
log
(
self
,
*
msg
):
msg
=
''
.
join
(
str
(
i
)
for
i
in
msg
)
msg
.
replace
(
"
\r
"
,
""
)
print
msg
# self.server.broadcast([
# dict(type= "log", data= dict(msg= msg, level= "debug"))
# ])
def
logError
(
self
,
*
msg
):
print
u""
.
join
(
unicode
(
i
)
for
i
in
msg
)
if
self
.
initializing
==
False
:
raise
Exception
(
u""
.
join
(
unicode
(
i
)
for
i
in
msg
))
def
write_prompt
(
self
):
None
def
confirm
(
self
):
True
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment