arksine / moonraker Goto Github PK
View Code? Open in Web Editor NEWWeb API Server for Klipper
Home Page: https://moonraker.readthedocs.io
License: GNU General Public License v3.0
Web API Server for Klipper
Home Page: https://moonraker.readthedocs.io
License: GNU General Public License v3.0
Would it be possible to allow us to turn off a power device when there is an MCU shutdown? It would be useful if there was a thermal runaway event for Moonraker to kill power to the printer.
Hello, i have python 3.8.3 installed and when using update_manager, it fails.
2021-01-25 02:23:30,369 [moonraker.py:load_plugin()] - Unable to load plugin (update_manager)
Traceback (most recent call last):
File "/home/pi/moonraker/moonraker/moonraker.py", line 148, in load_plugin
plugin = load_func(config)
File "/home/pi/moonraker/moonraker/plugins/update_manager.py", line 942, in load_plugin
return UpdateManager(config)
File "/home/pi/moonraker/moonraker/plugins/update_manager.py", line 51, in __init__
"moonraker": GitUpdater(self, mooncfg, MOONRAKER_PATH, env)
File "/home/pi/moonraker/moonraker/plugins/update_manager.py", line 453, in __init__
raise config.error("Invalid path for option '%s': %s"
confighelper.ConfigError: Invalid path for option '/home/pi/moonraker-env/lib/python3.7/site-packages': env_package_path
pi@orangepioneplus:~$ ls /home/pi/moonraker-env/lib/
python3.8
Thanks,
turtius
Currently UFP files are being parsed only on file upload. However, sometimes it might be more practical to just use good old samba network shares to copy files to the raspberry - such as currently curas octoprint upload plugin using a different api version than implemented in moonraker (or atleast that's the current situation, if I understood correctly).
Therefore I'd like to propose running any detected .ufp file in the gcodes folder through the same method as used on file upload - Unzipping the UFP, extracting thumbs/gcode from it and discarding the ufp.
moonraker/moonraker/plugins/file_manager.py
Line 421 in 943b781
I've had semi-success by just naively modifying the _list_directory method as follows, but obviously that's a rather dirty solution.
def _list_directory(self, path, is_extended=False):
if not os.path.isdir(path):
raise self.server.error(
f"Directory does not exist ({path})")
flist = {'dirs': [], 'files': []}
# Addition 1 START
dirty = False
# Addition 1 END
for fname in os.listdir(path):
full_path = os.path.join(path, fname)
if not os.path.exists(full_path):
continue
path_info = self._get_path_info(full_path)
if os.path.isdir(full_path):
path_info['dirname'] = fname
flist['dirs'].append(path_info)
elif os.path.isfile(full_path):
path_info['filename'] = fname
# Check to see if a filelist update is necessary
ext = os.path.splitext(fname)[-1].lower()
gc_path = self.file_paths.get('gcodes', None)
# Addition 2 START
if ext == '.ufp':
logging.info(full_path + " should be unzipped now!")
file = open(full_path, mode='rb')
self._unzip_ufp({'full_path':full_path, 'filename':fname, 'body':file.read()})
os.remove(full_path)
dirty = True
# Addition 2 END
if gc_path is not None and full_path.startswith(gc_path) and \
ext in VALID_GCODE_EXTS:
rel_path = os.path.relpath(full_path, start=gc_path)
self.gcode_metadata.parse_metadata(
rel_path, path_info['size'], path_info['modified'],
notify=True)
metadata = self.gcode_metadata.get(rel_path, None)
if metadata is not None and is_extended:
path_info.update(metadata)
flist['files'].append(path_info)
# Addition 3 START
if dirty:
return self._list_directory(path, is_extended)
# Addition 3 END
usage = shutil.disk_usage(path)
flist['disk_usage'] = usage._asdict()
return flist
Currently the config_path
must be in home or a subdirectory of home. This requirement should be relaxed to allow a arbitrary path.
Background: Most Distribution stick to the FHS. I plan to provide this as a gentoo ebuild and there asubdirectory of /etc/ should be possible.
Hello good fellas,
I'm struggling all day to get the power widget shown/activated.
After 3 fresh reinstalls i can't get it to work for some reason.
Maybe there's somebody can watch over this?
My printer uses UART communication with the drivers which means that klipper has to be restarted after a power cycle. Further the printer is not powered from USB so the port dissapears when the printer is off.
It would be great if this could be included in the startup code from my slicer, e.g. by using a macro. I tried the following macro:
[gcode_macro POWER_ON_PRINTER]
gcode:
{action_call_remote_method("set_device_power",
device="printer",
state="on")}
RESTART
However when I try issuing the command I get a response that moonraker cannot connect to klippy and therefrore neither fluid or moonsail allows me to issue the command.
i want to send file to my printer or print from cura.
Before i used duetRRF to send to DWC2 for clipper.
I changed for moonraker and mainsail.
I open issue in mainsail project, meteyou answer duetrrf can't work with mainsail and we have to use octoprint connector since moonraker emulate octoprint API.
I try to connect with serverIP or serverIP:7125 and API key but impossible to connect.
Do you think it's possible ?
Hello, (please excuse my bad English)
I installed Mainsail on an Orangepi Lite. I used the script from https://github.com/th33xitus/kiauh.
It works so far, only the HOSTREBOOT buttons don't work for me.
The Button HOSTSHUTDOWN work fine.
Where can I set what happens when these buttons are pressed?
Example: HOSTREBOOT should execute "sudo shutdown -h now".
Thank you Andre
Power on and off via url
I also use the raabi powermanagerscript to control my socket in my Smathome system. This is simply controlled via a url. with a separate on off command. it should be possible to realize that.
Powermanager Script Config:
printer_off="curl http://IP:PORT/set/loxone.0.15e032e3-02e4-5036-ffffeaed73a38093.active?value=false"
printer_on="curl http://IP:PORT/set/loxone.0.15e032e3-02e4-5036-ffffeaed73a38093.active?value=true"
I suspect this has to do with #73 but i don't know
my code is copied pasted from the example on how to set this up but still doesn't work. My version is v0.2.8-37
Here is the code
[power printer]
type: gpio
pin: gpio26
off_when_shutdown: True
initial_state: off
attached is my log file
moonraker.log
Linux distro
Armbian 20.08.1 Bionic with Linux 5.8.5-sunxi
Issue
Everything installs fine. Klipper installs and connects to printer no problem (see klippy.log). However, the moonraker API service does nothing. It installs and starts without problem. But no connection with klipper is made, port 7125 is not listening and the api is not generating a log. Trying to connect to http://:7125/printer/info gives connecton refused as expected with a port that is not listening.
Any ideas as to how this occurs and how to fix this?
Thanks in advance!
klippy.log:
klippy.log
printer.cfg (uploaded as txt due to github compatibility):
printer.txt
edit: more info added
As the title says. Logs include only these:
21:44:55,290 [moonraker.py:_read_klippy_stream()] - Unknown command received: {"id": 3048972656, "error": {"message": "webhooks: No registered callback for path 'GET'", "error": "WebRequestError"}}
klippylog has only these:
webhooks: No registered callback for path 'GET'
What am I doing wrong?
EDIT: Forgot to mention I tried installing it both manually and by several 'scripts', most noteworthy KIAUH (https://github.com/th33xitus/kiauh). No changes; the 404 remain.
EDIT2: Also tried Stephan's DWC2 which also seems to be unable to get info from the printer. (yes I know that's a totally different set up etc; but it might be worth mentioning)
When I ran ~/moonraker/scripts/install-moonraker.sh -r today on a non-raspbian device (an odroid running ubuntu), the compilation of pillow failed, complaining of "jpeg" not being available.
"The headers or library files could not be found for jpeg,
a required dependency when compiling Pillow from source."
once I installed libjpeg-dev, everything installed correctly
I suggest adding libjpeg-dev to the list of packages installed in the apt-get step.
Hi.
I added this script in moonraker.conf :
[power printer]
type: gpio
pin: gpio17
off_when_shutdown: False
initial_state: on
and reboot but it show error "No printer connection. Please check moonraker status and / or refresh."
I connect it via SSH and comment those added script, reboot again and it can connect to printer.
Something wrong ?
Not sure what the next step is to diagnose what's going wrong here.
I had this upgrading Mainsail to the latest version, so I've tried with a fresh copy of raspberyos and same problem.
I follow the installation instructions and no errors.
When I search the klippy.log file i do NOT see a "New connection" - clearly moonraker isn't functioning.
browser url - http://192.168.86.51:7125/printer/restart
moonraker.log
2020-08-18 11:58:51,084 [authorization.py:_check_trusted_connection()] - Trusted Connection Detected, IP: 192.168.86.47 2020-08-18 11:58:51,088 [web.py:log_request()] - 405 GET /printer/restart (192.168.86.47) 6.69ms
Browser error
Traceback (most recent call last): File "/home/pi/moonraker-env/lib/python3.7/site-packages/tornado/web.py", line 1703, in _execute result = await result File "/home/pi/moonraker/moonraker/app.py", line 282, in get raise tornado.web.HTTPError(405) tornado.web.HTTPError: HTTP 405: Method Not Allowed
While logging to stdout is available, moonraker still logs to a file. This is a bit annoying in NixOS as I couldn't find a good place to direct the logfile. When no -l
is set, moonraker should only log to stdout
Hi I am running out of ideas. I can not access the virtual SD Card. I already reinstalled everything twice.
Printer.cfg
[virtual_sdcard]
path: ~/sdcard
klippy.log
[virtual_sdcard]
path = ~/sdcard
moonraker.log
2020-09-09 07:26:50,594 [websockets.py:dispatch()] - Websocket Response::{"jsonrpc": "2.0", "result": {"status": {"temperature_sensor bed": {"measured_min_temp": -94.543263861882, "measured_max_temp": 0.0, "temperature": -94.543263861882}, "heaters": {"available_sensors": ["heater_bed", "temperature_sensor bed", "temperature_fan chamber", "extruder"], "available_heaters": ["heater_bed", "extruder"]}, "fan": {"speed": 0.0}, "bed_mesh": {"mesh_max": [0.0, 0.0], "mesh_matrix": [[]], "profile_name": "", "mesh_min": [0.0, 0.0], "probed_matrix": [[]]}, "pause_resume": {"is_paused": false}, "display_status": {"progress": 0.0, "message": null}, "gcode_move": {"homing_origin": [0.0, 0.0, 0.0, 0.0], "speed_factor": 1.0, "gcode_position": [0.0, 0.0, 0.0, 0.0], "absolute_extrude": true, "absolute_coordinates": true, "position": [0.0, 0.0, 0.0, 0.0], "speed": 1500.0, "extrude_factor": 1.0}, "print_stats": {"print_duration": 0.0, "total_duration": 0.0, "filament_used": 0.0, "filename": "", "state": "standby", "message": ""}, "heater_fan controller_fan": {"speed": 0.0}, "temperature_fan chamber": {"speed": 0.0, "temperature": -94.543263861882, "target": 50.0}, "idle_timeout": {"state": "Idle", "printing_time": 0.0}, "query_endstops": {"last_query": {}}, "toolhead": {"square_corner_velocity": 5.0, "max_accel": 3000.0, "homed_axes": "", "estimated_print_time": 612.4568908583333, "max_velocity": 300.0, "print_time": 0.001, "max_accel_to_decel": 1500.0, "position": [0.0, 0.0, 0.0, 0.0], "extruder": "extruder"}, "configfile": {"config": {"tmc2209 extruder": {"sense_resistor": "0.110", "interpolate": "false", "stealthchop_threshold": "0", "run_current": "0.5", "microsteps": "16", "uart_pin": "P1.4", "hold_current": "0.4"}, "display_data __voron_display printing_time": {"position": "2, 10", "text": "\n{% set ptime = printer.idle_timeout.printing_time %}\n{ "%02d:%02d" % (ptime // (60 * 60), (ptime // 60) % 60) }"}, "display_data __voron_display progress_text2": {"position": "1, 10", "text": "\n{% set progress = printer.display_status.progress %}\n{ draw_progress_bar(1, 10, 6, progress) }"}, "probe": {"samples_tolerance_retries": "3", "x_offset": "0", "pin": "^z:P0.10", "sample_retract_dist": "3.0", "samples_tolerance": "0.006", "samples_result": "median", "y_offset": "25.0", "samples": "3", "z_offset": "0", "speed": "10.0"}, "stepper_z2": {"step_pin": "z:P0.22", "step_distance": "0.00125", "dir_pin": "!z:P2.11", "enable_pin": "!z:P0.21"}, "neopixel neo_display": {"pin": "z:P1.21", "chain_count": "3", "color_order_grb": "False", "initial_red": "0.1", "initial_green": "0.5", "initial_blue": "0.0"}, "gcode_macro UNLOAD_FILAMENT": {"gcode": "\n{% if printer.toolhead.status == "Ready" %}\nM83 ; set extruder to relative\nG1 E10 F300 ; extrude a little to soften tip\nG1 E-780 F1800 ; retract filament completely\nM82 ; set extruder to absolute\n{% else %}\n{ printer.gcode.action_respond_info("Filament unloading disabled while printing!") }\n{% endif %}"}, "mcu rpi": {"serial": "/tmp/klipper_host_mcu"}, "display_data __voron_display chamber": {"position": "2, 0", "text": "\n{% set chamber = printer['temperature_fan chamber'] %}\nchamber\n{ "%3.0f" % (chamber.temperature,) }\ndegrees"}, "heater_bed": {"control": "pid", "pid_kp": "58.437", "sensor_pin": "z:P0.25", "pid_kd": "363.769", "heater_pin": "z:P2.3", "sensor_type": "NTC 100K MGB18-104F39050L32", "max_power": "0.6", "pid_ki": "2.347", "min_temp": "0", "max_temp": "120"}, "pause_resume": {}, "virtual_sdcard": {"path": "/sdcard"}, "stepper_z1": {"step_pin": "z:P0.19", "step_distance": "0.00125", "dir_pin": "z:P0.20", "enable_pin": "!z:P2.8"}, "gcode_macro LOAD_FILAMENT": {"gcode": "\n{% if printer.toolhead.status == "Ready" %}\nM83 ; set extruder to relative\nG1 E750 F1800 ; quickly load filament to down bowden\nG1 E30 F300 ; slower extrusion for hotend path\nG1 E15 F150 ; prime nozzle with filament\nM82 ; set extruder to absolute\n{% else %}\n{ printer.gcode.action_respond_info("Filament loading disabled while printing!") }\n{% endif %}"}, "verify_heater extruder": {"max_error": "120", "check_gain_time": "20", "heating_gain": "2", "hysteresis": "5"}, "display_data __voron_display bed": {"position": "1, 0", "text": "{ render("_vheater_temperature", param_heater_name="heater_bed") }"}, "stepper_z": {"homing_retract_dist": "3.0", "position_endstop": "-0.5", "position_max": "340", "endstop_pin": "z:P1.27", "second_homing_speed": "3.0", "step_pin": "z:P2.2", "position_min": "-5", "homing_speed": "15.0", "dir_pin": "!z:P2.6", "step_distance": "0.00125", "enable_pin": "!z:P2.1"}, "stepper_y": {"homing_positive_dir": "true", "homing_retract_dist": "5", "position_endstop": "350", "position_max": "350", "endstop_pin": "^!P1.28", "step_pin": "P0.19", "position_min": "0", "homing_speed": "25", "dir_pin": "!P0.20", "step_distance": "0.00625", "enable_pin": "!P2.8"}, "stepper_x": {"homing_positive_dir": "true", "homing_retract_dist": "5", "position_endstop": "350", "position_max": "350", "endstop_pin": "^!P1.29", "step_pin": "P2.2", "position_min": "0", "homing_speed": "25", "dir_pin": "!P2.6", "step_distance": "0.00625", "enable_pin": "!P2.1"}, "tmc2209 stepper_x": {"sense_resistor": "0.110", "interpolate": "True", "stealthchop_threshold": "0", "run_current": "0.8", "microsteps": "16", "uart_pin": "P1.10", "hold_current": "0.7"}, "display_data __voron_display print_status": {"position": "3, 0", "text": "\n{% if printer.display_status.message %}\n{ printer.display_status.message }\n{% elif printer.idle_timeout.printing_time %}\n{% set pos = printer.toolhead.position %}\n{ "X%-4.0fY%-4.0fZ%-5.2f" % (pos.x, pos.y, pos.z) }\n{% else %}\n{ "VX.xxx " }\nvoron~\n{% endif %}"}, "heater_fan controller_fan": {"heater": "heater_bed", "kick_start_time": "0.5", "pin": "z:P2.4", "heater_temp": "45.0"}, "display_data __voron_display progress_text": {"position": "1, 10", "text": "\n{% set progress = printer.display_status.progress %}\n{ "{:^6.0%}".format(progress) }"}, "display_glyph chamber": {"data": "\n0000000000000000\n1111111111111111\n1000010000100001\n1000010000100001\n1000011111100001\n1000000000000001\n1000000000000001\n1000001111000001\n1011101001011101\n1000001111000001\n1000000110000001\n1000000000000001\n1011111111111101\n1000100000010001\n1111111111111111\n0000000000000000"}, "display_glyph voroninv": {"data": "\n0000001110000000\n0000111111100000\n0001111111110000\n0111111111111100\n1111100111001110\n1111001110011110\n1110011100111110\n1100111001111110\n1111110011100110\n1111100111001110\n1111001110011110\n1110011100111110\n0111111111111100\n0001111111110000\n0000111111100000\n0000001110000000"}, "tmc2209 stepper_z1": {"sense_resistor": "0.110", "interpolate": "true", "stealthchop_threshold": "0", "run_current": "0.8", "microsteps": "16", "uart_pin": "z:P1.9", "hold_current": "0.8"}, "tmc2209 stepper_z3": {"sense_resistor": "0.110", "interpolate": "true", "stealthchop_threshold": "0", "run_current": "0.8", "microsteps": "16", "uart_pin": "z:P1.4", "hold_current": "0.8"}, "tmc2209 stepper_z2": {"sense_resistor": "0.110", "interpolate": "true", "stealthchop_threshold": "0", "run_current": "0.8", "microsteps": "16", "uart_pin": "z:P1.8", "hold_current": "0.8"}, "temperature_sensor bed": {"min_temp": "0", "sensor_type": "ATC Semitec 104GT-2", "gcode_id": "1B", "sensor_pin": "z:P0.23", "max_temp": "120"}, "gcode_macro PRINT_END": {"gcode": "\nM400 ; wait for buffer to clear\nG92 E0 ; zero the extruder\nG1 E-4.0 F3600 ; retract filament\nG91 ; relative positioning\nG0 Z1.00 X20.0 Y20.0 F20000 ; move nozzle to remove stringing\nTURN_OFF_HEATERS\nM107 ; turn off fan\nG1 Z5 F3000 ; move nozzle up 5mm\nG90 ; absolute positioning\nG0 X175 Y350 F3600 ; park nozzle at rear\nM117 Finished! ; display message\nBED_MESH_CLEAR"}, "printer": {"square_corner_velocity": "5.0", "max_accel": "3000", "max_z_accel": "350", "max_velocity": "300", "max_z_velocity": "15", "kinematics": "corexy"}, "display_data __voron_display fan": {"position": "0, 10", "text": "\n{% if 'fan' in printer %}\n{% set speed = printer.fan.speed %}\n{% if speed %}\n{% set frame = (printer.toolhead.estimated_print_time|int % 2) + 1 %}\nfan{frame}\n{% else %}\nfan1\n{% endif %}\n{ "{:>4.0%}".format(speed) }\n{% endif %}"}, "gcode_macro RESUME": {"rename_existing": "BASE_RESUME", "gcode": "\nG91\nG1 E1.7 F2100\nG91\nRESTORE_GCODE_STATE NAME=PAUSE_state MOVE=1\nBASE_RESUME"}, "display_data __voron_display extruder": {"position": "0, 0", "text": "{ render("_vheater_temperature", param_heater_name="extruder") }"}, "display_glyph voron": {"data": "\n1111111001111111\n1111100000011111\n1111000000001111\n1100000000000011\n1000001100110001\n1000011001100001\n1000110011000001\n1001100110000001\n1000000110011001\n1000001100110001\n1000011001100001\n1000110011000001\n1110000000000111\n1111000000001111\n1111100000011111\n1111111001111111"}, "gcode_macro PAUSE": {"default_parameter_y": "230", "rename_existing": "BASE_PAUSE", "default_parameter_z": "10", "gcode": "\nSAVE_GCODE_STATE NAME=PAUSE_state\nBASE_PAUSE\nG91\nG1 E-1.7 F2100\nG1 Z{Z}\nG90\nG1 X{X} Y{Y} F6000\nG91", "default_parameter_x": "230"}, "homing_override": {"gcode": "\nG90\nG0 Z5 F600\nG28 X Y\nG0 X0 Y0 F3600\nG28 Z\nG0 Z10 F1800\nG0 X175 Y175 Z30 F3600", "axes": "z", "set_position_z": "0"}, "idle_timeout": {"gcode": "\nTURN_OFF_HEATERS\nM84 ; disable steppers", "timeout": "1800"}, "fan": {"off_below": "0.10", "kick_start_time": "0.5", "pin": "P2.3"}, "tmc2209 stepper_z": {"sense_resistor": "0.110", "interpolate": "true", "stealthchop_threshold": "0", "run_current": "0.8", "microsteps": "16", "uart_pin": "z:P1.10", "hold_current": "0.8"}, "stepper_z3": {"step_pin": "z:P2.13", "step_distance": "0.00125", "dir_pin": "z:P0.11", "enable_pin": "!z:P2.12"}, "mcu": {"serial": "/dev/serial/by-id/usb-Klipper_lpc1769_1840010F871C4AAF863E7C5DC32000F5-if00"}, "tmc2209 stepper_y": {"sense_resistor": "0.110", "interpolate": "True", "stealthchop_threshold": "0", "run_current": "0.8", "microsteps": "16", "uart_pin": "P1.9", "hold_current": "0.7"}, "delayed_gcode setdisplayneopixel": {"gcode": "\nSET_LED LED=neo_display RED=1 GREEN=1 BLUE=1 INDEX=1\nSET_LED LED=neo_display RED=1 GREEN=0 BLUE=0 INDEX=2\nSET_LED LED=neo_display RED=1 GREEN=0 BLUE=0 INDEX=3 TRANSMIT=0", "initial_duration": "1"}, "gcode_macro G32": {"gcode": "\n{% if printer.toolhead.status == "Ready" %}\nBED_MESH_CLEAR\nG28\nQUAD_GANTRY_LEVEL\nG28 Z0\nG0 X175 Y175 Z20 F6000\n{% else %}\n{ printer.gcode.action_respond_info("G32 is disabled while printing!") }\n{% endif %}"}, "temperature_fan chamber": {"control": "pid", "pid_kp": "40", "max_speed": "1.0", "cycle_time": "0.05", "pin": "z:P2.7", "pid_kd": "0.1", "sensor_pin": "z:P0.24", "shutdown_speed": "0", "min_speed": "0", "sensor_type": "ATC Semitec 104GT-2", "target_temp": "50", "pid_deriv_time": "2.0", "max_power": "0.6", "kick_start_time": "0.500", "min_temp": "0", "pid_ki": "0.2", "hardware_pwm": "false", "gcode_id": "C", "max_temp": "70"}, "display_status": {}, "bed_mesh": {"mesh_pps": "4,4", "horizontal_move_z": "6", "mesh_min": "25,25", "algorithm": "bicubic", "mesh_max": "325,325", "split_delta_z": "0.0125", "probe_count": "7,7", "move_check_distance": "3", "speed": "300", "relative_reference_index": "24"}, "gcode_macro CANCEL_PRINT": {"default_parameter_y": "230", "rename_existing": "BASE_CANCEL_PRINT", "default_parameter_z": "10", "gcode": "\nM104 S0\nM140 S0\nM141 S0\nM106 S0\nCLEAR_PAUSE\nSDCARD_RESET_FILE\nBASE_CANCEL_PRINT", "default_parameter_x": "230"}, "gcode_macro PRINT_START": {"gcode": "\nM117 Homing... ; display message\nG28 ; home all axes\nG1 Z20 F3000 ; move nozzle away from bed\nM117 Preheat (Print) ; display message"}, "display_template _vheater_temperature": {"text": "\n{% if param_heater_name in printer %}\n{% set heater = printer[param_heater_name] %}\n{% if param_heater_name == "heater_bed" %}\n{% if heater.target %}\n{% set frame = (printer.toolhead.estimated_print_time|int % 2) + 1 %}\nbed_heat{frame}\n{% else %}\nbed\n{% endif %}\n{% else %}\nextruder\n{% endif %}\n{ "%3.0f" % (heater.temperature,) }\n{% if heater.target and (heater.temperature - heater.target)|abs > 2 %}\nright_arrow\n{ "%0.0f" % (heater.target,) }\n{% endif %}\ndegrees\n{% endif %}", "param_heater_name": ""extruder""}, "heater_fan hotend_fan": {"kick_start_time": "0.5", "heater_temp": "50.0", "max_power": "1.0", "pin": "P2.4", "heater": "extruder"}, "verify_heater heater_bed": {"max_error": "120", "check_gain_time": "60", "heating_gain": "2", "hysteresis": "5"}, "quad_gantry_level": {"retries": "5", "horizontal_move_z": "10", "retry_tolerance": "0.0075", "gantry_corners": "\n-60,-10\n410,420", "points": "\n50,25\n50,275\n300,275\n300,25", "speed": "100", "max_adjust": "10"}, "display": {"a0_pin": "z:P1.19", "cs_pin": "z:P1.18", "encoder_pins": "^z:P3.25,^z:P3.26", "lcd_type": "uc1701", "contrast": "63", "click_pin": "^!z:P0.28"}, "mcu z": {"serial": "/dev/serial/by-id/usb-Klipper_lpc1769_07300110871C4AAFBF427C5DC72000F5-if00"}, "extruder": {"control": "pid", "pid_kp": "26.213", "sensor_type": "SliceEngineering 450", "sensor_pin": "P0.24", "nozzle_diameter": "0.400", "pid_kd": "131.721", "pressure_advance_smooth_time": "0.040", "heater_pin": "P2.7", "min_extrude_temp": "170", "step_pin": "P2.13", "pressure_advance": "0.05", "max_power": "1.0", "min_temp": "10", "pid_ki": "1.304", "filament_diameter": "1.75", "dir_pin": "!P0.11", "max_temp": "270", "step_distance": "0.00120", "enable_pin": "!P2.12"}}}, "heater_fan hotend_fan": {"speed": 0.0}, "webhooks": {"state": "shutdown", "state_message": "MCU 'mcu' shutdown: ADC out of range\nThis generally occurs when a heater temperature exceeds\nits configured min_temp or max_temp.\nOnce the underlying issue is corrected, use the\n"FIRMWARE_RESTART" command to reset the firmware, reload the\nconfig, and restart the host software.\nPrinter is shutdown\n"}, "virtual_sdcard": {"progress": 0.0, "is_active": false, "file_position": 0}, "heater_bed": {"temperature": -88.51899597407109, "target": 0.0}, "extruder": {"pressure_advance": 0.05, "target": 0.0, "temperature": -90.85125769678834, "smooth_time": 0.04}}, "eventtime": 606.86352749}, "id": 1852}
but if I try to access the sdcard or write the gui.json I see:
2020-09-09 07:26:56,297 [websockets.py:dispatch()] - Websocket Request::{"jsonrpc":"2.0","method":"server.files.get_directory","params":{"path":"gcodes"},"id":6376}
2020-09-09 07:26:56,298 [websockets.py:dispatch()] - Websocket Response::{"jsonrpc": "2.0", "error": {"code": 400, "message": "Invalid base path (gcodes)"}, "id": 6376}
2020-09-09 07:27:07,379 [web.py:log_exception()] - 400 POST /server/files/upload (192.168.178.32): Gcodes root not available
2020-09-09 07:27:07,392 [web.py:log_request()] - 400 POST /server/files/upload (192.168.178.32) 14.94ms
The folder ~/sdcard is there and accesable with the user pi
I have no idea where to look next
When I warm up my printer, I like to wait long enough for the heated bed to soak up to temperature. It takes a while for a thick MIC6 plate to actually stabilize at print temperature, long after the thermistor reports it first gets there. To do this I usually tail the klippy.log with a python regex and watch the "pwm=" in the log and wait for that to stabilize, meaning the bed has reached equilibrium. To make this more sophisticated, I'd like to get this into some webui somewhere. Klipper already exports this information through its API, so moonraker is the next piece of software that needs to expose it.
Klipper exports it as "power" in its API, so it was trivial to add to your excellent framework as "power" to the endpoint /server/temperature_store
.
diff --git a/moonraker/plugins/data_store.py b/moonraker/plugins/data_store.py
index 77760a7..4a65a0a 100644
--- a/moonraker/plugins/data_store.py
+++ b/moonraker/plugins/data_store.py
@@ -66,9 +66,10 @@ class DataStore:
else:
new_store[sensor] = {
'temperatures': deque(maxlen=TEMPERATURE_STORE_SIZE),
- 'targets': deque(maxlen=TEMPERATURE_STORE_SIZE)}
+ 'targets': deque(maxlen=TEMPERATURE_STORE_SIZE),
+ 'powers': deque(maxlen=TEMPERATURE_STORE_SIZE)}
if sensor not in self.last_temps:
- self.last_temps[sensor] = (0., 0.)
+ self.last_temps[sensor] = (0., 0., 0.)
self.temperature_store = new_store
# Prune unconfigured sensors in self.last_temps
for sensor in list(self.last_temps.keys()):
@@ -86,17 +87,19 @@ class DataStore:
def _set_current_temps(self, data):
for sensor in self.temperature_store:
if sensor in data:
- last_temp, last_target = self.last_temps[sensor]
+ last_temp, last_target, last_power = self.last_temps[sensor]
self.last_temps[sensor] = (
round(data[sensor].get('temperature', last_temp), 2),
- data[sensor].get('target', last_target))
+ data[sensor].get('target', last_target),
+ data[sensor].get('power', last_power))
def _update_temperature_store(self):
# XXX - If klippy is not connected, set values to zero
# as they are unknown?
- for sensor, (temp, target) in self.last_temps.items():
+ for sensor, (temp, target, power) in self.last_temps.items():
self.temperature_store[sensor]['temperatures'].append(temp)
self.temperature_store[sensor]['targets'].append(target)
+ self.temperature_store[sensor]['powers'].append(power)
async def _handle_temp_store_request(self, web_request):
store = {}
I can make a pull request for this change if you'd like but I wanted to make sure you would be willing to accept it before I went through the effort of forking the repo and all that. It only changes the one file too, so I wouldn't mind if you just applied the patch and committed it yourself either. Just let me know if this sounds like something we can add.
EDIT: I followed Klipper's convention of outputting the PWM as 0.0 to 1.0, but if you'd prefer I can make the moonraker output 0-100 if you think that would make more sense to implementers further down the pipeline (KlipperScreen, Fluidd, Mainsail).
Hi,
might it be possible to add an document, which "shell commands" are used by moonraker?
Something like:
sudo
/bin/systemctl
etc.
So, that it would be easyer to inspect privilege elevations needed.
Thanks
Not sure if this is a bug or not but when issuing G-codes from a file there is, in some instances, a semi-colon at the end of the G-code to start a comment. I had START_PRINT; in my G-code file referring to my klipper printer.cfg macro START_PRINT.
Using Octoprint the semicolon did not cause any problems, however I got the message Malformed 'START_PRINT' using
with moon raker/mainsail. Removing the semicolon from the G-code file solved the issue.
It'd be fantastic if the commands returned in console help also returned their parameters. This way a user could have tab completion on command params.
Initially just a string list of the params for each command would be fine I think.
Tornado has the capability to 'export' the functionality also as Unix Domain Socket.
Normally moonraker is run behind a web server like NGINX or Apache HTTP.
This has serveral benifits, e.g:
Would it be possible to look into bringing some form of notifications to the api. At it's simplest, just a way of getting notifications when a print has completed. In it's most evolved form, notifications at some form of an interval that include a mjpg snapshot if a camera is available. I have several machines happily speeding along, but I have to monitor bookmarked mjpg streams to see when then are finished. One could maybe setup pushover/slack/email/growl..mqtt..whatever makes the most sense with the codebase. Thanks for an amazing contribution!
Hi, I accidentally closed the last issue sry, the command: / machine / services / restart? Service = klipper, returns ok but klipper does not restart. Could it be because of the typographical error of "sever"?
Currently, when you refresh a client - the sent command history is lost. This can be a bit confusing for some users as the console history looks a bit different after refresh.
It'd be be nice if we had an option to retain this.
moonraker log attached.
Looks like the issue is here:
2021-01-22 22:02:40,672 [power.py:init()] - Power plugin loading devices: ['power tasmota_plug']
2021-01-22 22:02:40,672 [moonraker.py:load_plugin()] - Unable to load plugin (power)
Traceback (most recent call last):
File "/home/pi/moonraker/moonraker/moonraker.py", line 148, in load_plugin
plugin = load_func(config)
File "/home/pi/moonraker/moonraker/plugins/power.py", line 439, in load_plugin_multi
return PrinterPower(config)
File "/home/pi/moonraker/moonraker/plugins/power.py", line 39, in init
self.devices[dev.get_name()] = dev
File "/home/pi/moonraker/moonraker/plugins/power.py", line 174, in get_name
return self.name
AttributeError: 'Tasmota' object has no attribute 'name'
moonraker (1).log
My tasmota plug is configured as follows:
[power tasmota_plug]
type = tasmota
address = 192.168.86.20
off_when_shutdown = True
Any idea what the issue could be? Was working before the latest moonraker update.
Currently moonraker logs to a file and the usual way of symlinking to /dev/stdout doesn't due to moonraker attempting to rotate the logs file. Therefore another process like tail or other must be used.
Trying to setup a second instance of Moonraker and Mainsail and found an issue with the https://github.com/Arksine/moonraker/blob/master/docs/installation.md#moonraker-configuration-moonrakerconf doco
It states:
klippy_address: /tmp/klippy_uds
The address of Unix Domain Socket used to communicate with Klippy. Default
is /tmp/klippy_uds
After going through the code and testing this should be.
klippy_uds_address: /tmp/klippy_uds
otherwise both moonraker services talk to the default klipper uds.
I think this question is somewhat in line with #3, but has there been any discussion around making moonraker and/or klipper have a schema first approach for delivering a web api?
I am toying with the idea of building a native android application (or maybe even do iOS and web concurrently all in kotlin). Obviously all on top of moonraker, but the effort required initially and ongoing would be far less if the api surface was communicated in a rigorous formal way.
Things like gRPC, GraphQL, or OpenApi come to mind.
There might be an argument that the growth rate of the klipper eco-system would benefit best from such a contract driven approach. I for one would LOVE to see a gRPC or GraphQL system as a way to interact with klipper.
Have posted on MainSail also.
Hardware is a Pi4 connected to 2 SKR1.3's
Installed twice, just incase I did not RTFM correctly the first time!
Following the instructions, it fails on the Moonraker install namely nginx
Please see log file for more info
REgards
Paul.
Hi! I'm curious if it is possible to allow CORS for WebSockets? I see there is a check in the websockets.py but I don't get where this setting can be set.
I start here, I know the FR needs modification at klipper and moonraker
I like the idea to have gpio relays controllable even if klipper is not running but it would be helpful if there would be a way that you also use them in gcode_macros. The best example here would be switch off the 24V power supply in you print_end macro.
what you would need in klipper is a definition e.g
[moonrakker_power]
devices: PSU
And then you could use the SET_PIN gcode to manipulate it. Instead sending it to a physical pin klipper would send it via API. and moonraker would use the pins defined in the power section. Restriction the device must be equal named. Moonraker should ignore calls for devices not specified in the [power] section.
I'd like to be able to specify the version of moonraker via an environment variable or a cmdline option, this would allow me to remove git as a runtime dependency.
Documentation for the api key says:
api_key_path
https://github.com/Arksine/moonraker/blob/master/docs/installation.md
But the code says:
api_key_file
moonraker/moonraker/authorization.py
Line 22 in 8440a10
Hi I got elementaryOS running with all the dependencies, on an old atom ITX mainboard.
I think I found a bug or maybe something is missing in my setup... all in all a soon as moonraker service starts it exits, with this error:
[sudo] password for pi:
โ moonraker.service - LSB: moonraker daemon
Loaded: loaded (/etc/init.d/moonraker; generated)
Active: active (exited) since Fri 2020-10-09 11:09:57 IDT; 39min ago
Docs: man:systemd-sysv-generator(8)
Process: 12966 ExecStop=/etc/init.d/moonraker stop (code=exited, status=0/SUCCESS)
Process: 12978 ExecStart=/etc/init.d/moonraker start (code=exited, status=0/SUCCESS)
Oct 09 11:09:57 tlm systemd[1]: Starting LSB: moonraker daemon...
Oct 09 11:09:57 tlm moonraker[12978]: * Starting moonraker moonraker
Oct 09 11:09:57 tlm moonraker[12978]: ...done.
Oct 09 11:09:57 tlm systemd[1]: Started LSB: moonraker daemon.```
Python version:
```pi@tlm:~$ python --version
Python 2.7.17
pi@tlm:~$ python3 --version
Python 3.6.9
Also when I run moonraker manually I got this error:
Traceback (most recent call last):
File "/home/pi/moonraker/moonraker/moonraker.py", line 15, in <module>
import utils
File "/home/pi/moonraker/moonraker/utils.py", line 11, in <module>
from queue import SimpleQueue as Queue
ImportError: cannot import name 'SimpleQueue'```
I have no clue what to do from here...
Any help will be appreciated.
Thanks for your awsome work!
Emanuel.
For packaging Moonraker + Klippy as a Docker container using Nix it is desirable to not have all the configs and stuff in $HOME. For some directories it's impossible, since the /share
directory of klippy resides in the Nix store /nix/store
. Please get rid of this arbitrary restriction or put it behind a flag so that I can disable it.
I created two instances of klipper + moonraker using Kiauh script :
https://github.com/th33xitus/KIAUH
In Fluidd webclient, both instances are connected to my two printers but raise a warning :
Fluidd warnings found.
Moonraker has failed plugins, please check your logs, update your configuration and restart moonraker.
update_manager
Plus, when I tried to heat my extruder, it seems that one 'printer session' entered in a loop getting temperatures alternatively from both printers, making strange charts.
here my two moonraker.cfg
`[server]
host: 0.0.0.0
port: 7125
enable_debug_logging: True
config_path: /home/jsh/klipper_config
klippy_uds_address: /tmp/klippy_uds
[authorization]
enabled: True
api_key_file: ~/.moonraker_api_key
trusted_clients:
127.0.0.1
192.168.0.0/16
192.168.1.0/24
::1/128
FE80::/10
cors_domains:
http://.local
http://my.mainsail.xyz
https://my.mainsail.xyz
http://app.fluidd.xyz
https://app.fluidd.xyz
http://192.168.1.48
http://192.168.1.48:
[update_manager]
[update_manager client fluidd]
type: web
repo: cadriel/fluidd
path: ~/fluidd
#[update_manager client KlipperScreen]
#type: git_repo
#path: /home//home/jsh/KlipperScreen
#origin: https://github.com/jordanruthe/KlipperScreen.git
#env: /home//home/jsh/.KlipperScreen-env/bin/python
#requirements: scripts/KlipperScreen-requirements.txt
#install_script: scripts/KlipperScreen-install.sh
`
Following one is complete, I removed all update_manager in order to try to remove the warning fro fluidd. With no success...
`[server]
host: 0.0.0.0
port: 7126
enable_debug_logging: True
config_path: /home/jsh/klipper-2_config
klippy_uds_address: /tmp/klippy-2_uds
[authorization]
enabled: True
api_key_file: ~/.moonraker_api_key
trusted_clients:
127.0.0.1
192.168.0.0/16
192.168.1.0/24
::1/128
FE80::/10
cors_domains:
http://.local
http://my.mainsail.xyz
https://my.mainsail.xyz
http://app.fluidd.xyz
https://app.fluidd.xyz
http://192.168.1.48
http://192.168.1.48:
[update_manager]
`
Hello,
I am trying to create a RESTful sensor in Home Assistant to get the progress of the print and then eventually get notified when print finishes. I am unable to find the method to do so from the documentation.
It will be great to have the following information available from REST
I believe this conditional is highly restrictive and should be refactored to allow for files to be placed anywhere where the daemon has proper permissions to access. For instance this restricts a user from using /etc/conf.d/
or any other directory that is outside of /home/
.
I don't necessarily understand why moonraker is being so restrictive in this situation and if it is for permission issues, I believe checking for read/write perms would be better than limiting to a single directory, which a user may not be able to write or read to anyways.
Thanks.
I had someone else bring this to my attention and i verified on my printer as well. If you baby step with the panel it lifts about 200mm instead of .2 i think their is a missing decimal point or typo somewhere i check line 526 and am trying go over it but im sure you will be able fix way quicker than i ever could lol
Hi,
Is it possible to power off printer certain minutes after print finished using gpio ?
thanks
jonathan
Hi,
Thanks for your time.
I have dug around trying to help myself and learn!
My PanelDue is running firmware 1.24
So the pins I need to use in the Pi are 4, 6, 8, 10
4 is +5v, 6 is Gnd.
8 is UART0 Tx, 10 is UART0 Rx.
Ran sudo raspi-config and disabled console messages and enabled serial.
ls -l /dev shows me
crw-rw---- 1 root dialout 166, 0 Sep 3 17:17 ttyACM0 crw-rw---- 1 root dialout 204, 64 Sep 3 17:08 ttyAMA0 and
lrwxrwxrwx 1 root root 5 Sep 3 17:22 serial0 -> ttyS0
lrwxrwxrwx 1 root root 7 Sep 3 17:22 serial1 -> ttyAMA0
I modified the moonraker.conf and set serial to
[paneldue] serial: /dev/ttyAMA0
I think this is correct.
Checked moonraker logs file
I have these entries
2020-09-03 17:22:27,481 [paneldue.py:_connect()] - Attempting to connect to: /dev/ttyAMA0 2020-09-03 17:22:27,483 [paneldue.py:_connect()] - PanelDue Connected 2020-09-03 17:22:27,485 [moonraker.py:connect()] - Klippy Connection Established
I have rebooted numerous times and the PanelDue just says 'Connecting' in the top right corner.
Have I missed something in my process?
Your input would be appreciated.
Regards,
Paul
Please add support esphome api for power plug.
If you show home assistant config and use tasmota power, may be you can add support [power printer] and [power device_name] with esphome restapi ?
https://esphome.io/web-api/index.html
I use sonoff pow2 on esphome. i see powermeter and can turnon off printer from home assistant, but not from Fluiid or other klippers web gui.
Is there some basic instructions on how to add macros to the PanelDue, please.
I could do with my Z_TILT_ADJUST on the touchpanel, and some others.
Thanks in advance.
Paul.
After testing the new [update_manager] feature ( Which was for me unclear if it has to set in Moonraker.conf or printer.cfg ),
I discovered that "DEBIAN_FRONTEND=noninteractive" isn't allowed to set.
There for, i will update the sudo_fix.sh, but it has a major issue. It HAVE to be a part of the installation
becaus you have to to update the /etc/environment file, to set DEBIAN_FRONTEND as a fixed System Variable.
Tested on latest FluiddPI Release.
After manual changes it works perfectly.
Who struggels with that Issue can do the following till update:
echo DEBIAN_FRONTEND=noninteractive >> /etc/environment
Update your 020-sudo-for-moonraker ( or create file according to your machine ) and append line:
Defaults!/usr/bin/apt-get env_keep +="DEBIAN_FRONTEND"
Please make sure you issue an Reboot!
Hi,
when I run POST / machine / services / restart? service = I get the following error:
Traceback (most recent call last):
File "/home/pi/moonraker-env/lib/python3.7/site-packages/tornado/web.py", line 1704, in _execute
result = await result
File "/home/pi/moonraker/moonraker/app.py", line 304, in post
await self._process_http_request('POST')
File "/home/pi/moonraker/moonraker/app.py", line 319, in _process_http_request
WebRequest(self.request.path, args, method, conn=conn))
File "/home/pi/moonraker/moonraker/plugins/machine.py", line 52, in _handle_service_restart
raise self.sever.error(
AttributeError: 'Machine' object has no attribute 'sever'
Any ideas? thanks
The only reson i can't get myself to switch to moonracker and a interface is the missing cancel objects. its allready implemented in the gcode from most slicers so it shuld not be an issue to implement that. Im just too dumb to try :D
There is a little issue with the method how g-code from PrusaSlicer is parsed.
return self._parse_max_float(r"G1\sZ\d+\.\d*\sF", self.footer_data)
https://github.com/Arksine/moonraker/blob/master/scripts/extract_metadata.py#L139
The regex there expects a speed value at the end, which is not always present for each z height.
I encountered that issue with a model sliced in vase mode which is 50mm high but in Mainsail only 49.90mm are displayed:
The last few g-code lines are as follows:
G1 Z49.800 F7800.000
; printing object heattower_medium.stl id:0 copy 0
G1 F3600.000
G1 Z49.800 X81.249 Y74.249 E0.00179
G1 Z49.825 X130.750 Y74.249 E0.88636
G1 Z49.850 X130.750 Y123.751 E0.88636
G1 Z49.875 X81.249 Y123.751 E0.88636
G1 Z49.900 X81.249 Y74.349 E0.88457
; stop printing object heattower_medium.stl id:0 copy 0
G1 Z49.900 F7800.000
; printing object heattower_medium.stl id:0 copy 0
G1 F3600.000
G1 Z49.900 X81.249 Y74.249 E0.00179
G1 Z49.925 X130.750 Y74.249 E0.88636
G1 Z49.950 X130.750 Y123.751 E0.88636
G1 Z49.975 X81.249 Y123.751 E0.88636
G1 Z50.000 X81.249 Y74.349 E0.88457
You can see that the speed is only set each 0.1mm increments, which is a full layerheight. But when reaching the total object height at Z50.000 there is no speed parameter given. Therefore it can't get parsed correctly.
This seems to be an edge case on vase mode prints?
I sliced the same object with vase mode disabled and i get the correct total object height displayed after that:
The g-code sequence looks there as follows:
G1 Z49.900 F7800.000
; printing object heattower_medium.stl id:0 copy 0
G1 X130.650 Y123.751
G1 F3600.000
G1 X81.249 Y123.751 E0.88457
G1 X81.249 Y74.249 E0.88636
G1 X130.750 Y74.249 E0.88636
G1 X130.750 Y123.751 E0.88636
G1 X130.726 Y123.751 E0.00045
; stop printing object heattower_medium.stl id:0 copy 0
G1 Z50.000 F7800.000
; printing object heattower_medium.stl id:0 copy 0
G1 X130.650 Y123.751
G1 F3600.000
G1 X81.249 Y123.751 E0.88457
G1 X81.249 Y74.249 E0.88636
G1 X130.750 Y74.249 E0.88636
G1 X130.750 Y123.751 E0.88636
G1 X130.726 Y123.751 E0.00045
; stop printing object heattower_medium.stl id:0 copy 0
You can see that now Z50.000 has an appended F parameter and can be parsed.
Since i am a total noob in regards to RegEx, i can only report this problem and can't provide a solution for it.
I attached the gcode files if you want to take a look at the g-code yourself.
gcode.zip
Sorry the title is possibly so vague. During installing, I get to the step to open url: "http://:7125/printer/info"
If I see this: "{"result": {"hostname": "voron250", "error_detected": false, "version": "v0.8.0-643-g528f9f25", "is_ready": true, "message": "Printer is ready", "cpu": "4 core ARMv7 Processor rev 4 (v7l)"}}"
My API is working....I do not get this, so I guess my API is not working.
I have this in my moonraker log file.
cat /tmp/moonraker.log
Moonraker Log Start...
Git Version: d04a419
================================================================================
2020-08-12 22:00:17,803 [moonraker.py:main()] - Moonraker Error
Traceback (most recent call last):
File "/home/pi/moonraker/moonraker/moonraker.py", line 393, in main
server = Server(cmd_line_args)
File "/home/pi/moonraker/moonraker/moonraker.py", line 34, in __init__
config = confighelper.get_configuration(self, args)
File "/home/pi/moonraker/moonraker/confighelper.py", line 71, in get_configuration
raise ConfigError(f"Configuration File Not Found: '{cfg_file_path}''")
confighelper.ConfigError: Configuration File Not Found: '/home/pi/moonraker.conf''
Any help would be appreciated.
I am running a fresh install of Rasperian Debian lite version updated to most recent packages, and have pulled what ever gets pulled when following these instructions: https://github.com/meteyou/mainsail/blob/master/docs/installation.md
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.