Improperly reporting Klipper tool temperature

This is a single file plugin example which just need to be copied to the plugin dir and use the temperatur hook :slight_smile: LedStripePlugin.zip (1,4 KB)

Thanks for the example. Even though I'm a retired software engineer, I'm a noob with Python and OctoPrint plugins. But if you give me a good example, I can usually turn that into something else that works!

Don't forget to take a look to this one:
https://docs.octoprint.org/en/master/plugins/gettingstarted.html and Python is pure fun bringing fuctionality into code, e.g connectiing to octoprints REST from commandline outside the octoprints emvironment. Have Fun :slight_smile:

Curious if your printer profile is configured properly @shdwshinobi. Do you have it like this?

image

Assuming the printer profile is configured correctly, I believe OctoPrint is expecting a temperature report with two temperatures in it (both the same because they are, in reality, the same single nozzle).

The following assumes that you have figured out how to SSH into your RPi using PuTTY (on Windows), ssh (on Linux), or something else on macOS. I have tested this on my LulzBot TAZ 6 with both a single extruder and a dual extruder and with the single extruder, it modifies the parsed_temperatures to report two temperatures.

Connect to octopi via SSH (or login as the effective octoprint user on your machine) copy this snippet and paste it straight into the terminal:

cat > /home/pi/.octoprint/plugins/Fix_Klipper_Temp.py << EOF
# coding=utf-8
from __future__ import absolute_import

import octoprint.plugin

class fix_klipper_temp(octoprint.plugin.OctoPrintPlugin):
	def FixKlipperTemp(self, comm_instance, parsed_temperatures, *args, **kwargs):
		self._logger.debug("Before: %s" % parsed_temperatures)
		if 'T0' not in parsed_temperatures.keys(): return parsed_temperatures
		if 'T1' in parsed_temperatures.keys(): return parsed_temperatures
		parsed_temperatures[u'T1'] = (parsed_temperatures['T0'][0],parsed_temperatures['T0'][1])
		self._logger.debug("After: %s" % parsed_temperatures)
		return parsed_temperatures

__plugin_name__ = "Fix Klipper Temp"
__plugin_version__ = "1.0.5"
__plugin_description__ = "Fix Klipper Temperature Report"
__plugin_pythoncompat__ = ">=2.7,<4"

def __plugin_load__():
	global __plugin_implementation__
	__plugin_implementation__ = fix_klipper_temp()

	global __plugin_hooks__
	__plugin_hooks__ = {
		"octoprint.comm.protocol.temperatures.received": __plugin_implementation__.FixKlipperTemp
	}
EOF

sudo service octoprint restart

If you want to see the _logger output (in ~/.octoprint/logs/octoprint.log), you will need to add an entry to OctoPrint's Settings, Logging to look like:

Nice @b-morgan, looks like it worked. You might want to wrap it and make it distributable via the plugin repo. If you'd like, I'd be happy to do that for you or help you through it.

b-morgan,

That definitely worked! I'm planning on putting in a couple more extruder motors, same nozzle. So I believe I'll have to alter your code, but this is a great starting point! I'd have to read more into the octoprint codebase since I'm not sure what's available, but it'd be nice to be able to see if shared_heater was checked and see how many extruders are in the active printer profile.

Yep, that's exactly what it looks like for the printer profile.

Yeah pulling the quantity of extruders from the default printer profile settings is trivial. Then you could use that as an iterator, or simply do a slight different comparison using in possibly like foosel mentioned in discord I think.

Alright, I grabbed the info from printer profiles and it should expand out if sharedNozzle is selected.

from __future__ import absolute_import

import octoprint.plugin

class fix_klipper_temp(octoprint.plugin.OctoPrintPlugin):
  def FixKlipperTemp(self, comm_instance, parsed_temperatures, *args, **kwargs):
    extruders = self._printer_profile_manager.get_current_or_default()["extruder"]["count"]
    sharedNozzle = self._printer_profile_manager.get_current_or_default()["extruder"]["sharedNozzle"]
    self._logger.debug("Before: %s" % parsed_temperatures)
    if 'T0' not in parsed_temperatures.keys(): return parsed_temperatures
    if sharedNozzle is True and extruders > 1 and 'T1' not in parsed_temperatures.keys():
      for i in range(1, extruders):
        parsed_temperatures[u'T' + str(i)] = (parsed_temperatures['T0'][0],parsed_temperatures['T0'][1])
    self._logger.debug("After: %s" % parsed_temperatures)
    return parsed_temperatures

__plugin_name__ = "Fix Klipper Temp"
__plugin_version__ = "1.0.5"
__plugin_description__ = "Fix Klipper Temperature Report"
__plugin_pythoncompat__ = ">=2.7,<4"

def __plugin_load__():
  global __plugin_implementation__
  __plugin_implementation__ = fix_klipper_temp()

  global __plugin_hooks__
  __plugin_hooks__ = {
    "octoprint.comm.protocol.temperatures.received": __plugin_implementation__.FixKlipperTemp
  }


1 Like

If you think it should be a full-fledged plugin then I nominate @shdwshinobi for that honor. It sounds like he is in a position to both test and expand on my start. I'm hesitant to "own" something I can't actually test. I'm sure he would welcome your help.

IMO, the ability to create these single-file solutions is a hidden OctoPrint "gem" and I'm just happy to let them "shine" on their own.

So I've never tried installing one of these gems, you just drop it in the plugins folder or can you install via wen interface upload? That's my biggest point. If it's beneficial to the masses, it's easier to get it out there if it's registered in the repo. I question if the vast majority of the users even connect to ssh on their pi to reset their password.

The way it was posted does require knowing how to SSH into OctoPi, but it doesn't require skills beyond cut and paste (right-mouse click in the SSH window). The plugin folder is already coded into the post as is the OctoPrint server restart.

All (3 of) the "Get Help" topics I've answered like this are for specific printers (that I don't own) and therefore are "experiments" that need to be verified by the original poster.

I agree that if it is beneficial to the masses, then it probably should be in the plugin repository. I believe it still has to pass through this stage in order to validate that it solves the issue.

@jneilliii, Now all we need to do is define what constitutes the "masses" and the "vast majority". Take a look at https://community.octoprint.org/t/octopi-not-reading-sd-card-or-print-progress-from-ender-3-solved/9821

I personally think that, while it'd be nice to have this in the repository, it's probably a very niche case and a very worthwhile use of the single file plugin. I can throw it onto github in the near future with a readme on how to install it with SSH.

I also don't believe anyone using klipper wouldn't know how to SSH to their octoprint instance as that's part of installing klipper.

That's a good point in regard to having to know how to do it already. I wonder if it might be helpful though to have a generic plugin that is registered in the repo that allows for single plugin updates maybe? If no-one else is up to the task, I could probably squeeze something like that in, but would have to figure out a good way to handle the upload process, as the only one I've done that does that is the custombackground plugin and it utilizes the internal gcode upload process. Which might not be terrible solution. Drag/Drop your single line python file to upload local, grab it as it uploads and store it in the plugins folder and then delete the file on file added event so it's not in the file list. Hmmm...this actually probably wouldn't take me long to write...damn you guys! I'll probably program this tonight. Just would need a way to also delete the files, so a settings interface that lists the currently loaded files.

Many of these single file plugins are written to deal with "broken" firmware on specific 3D printer models (or manufacturers). Whatever solution we come up with should have a way of searching for or identifying a printer model and/or firmware version which then lists plugins that have been written.

For the record, I've extracted the printer safety check into its own standalone project (which OctoPrint depends on) for 1.4.1 to be able to maintain (and update) it separately from OctoPrint, in order to be able to add new detection for broken firmware quickly and recommend plugins for these.

E.g. when it detects the infamous CBD make it, it will now tell you to download the corresponding fix plugin. Same could be done for other such situations. And since printer safety no longer just detects a lack of thermal runaway protection but more, it's been renamed into firmware check.

See

So, the infrastructure for that is in place.

Regarding single file plugins, I'd actually love to enable the plugin manager to install and manage those (by copying them to the plugins folder). The upload capabilities are already there, it would just have to detect "plain python file" in addition to "zip archive or tarball" and act accordingly. I'll prioritize that and will try to get it into 1.4.1 still.

Might also be possible to enhance the software update plugin to allow updates of single file plugins (new copy file action or something), to allow updating single file plugins just like full features ones.

edit I'll probably give this a shot tonight on the livestream.

1 Like

plan

I just pushed the final commit for what I started on yesterday on the stream. It will not only be possible to install single file plugins through the Plugin Manager in OctoPrint 1.4.1, but thanks to some additions to the Software Update plugin, they will also be updateable.

Example for how that will look like for a plugin is here: https://gist.github.com/foosel/12e89d885c32b3adb81f5a999331f151

Instead of the jsondata update mechanism there, this would work as well and pick up any changes to the file (after a couple of minutes, Github caches heavily there):

def update_hook(*args, **kwargs):
	return dict(m108_support=dict(type="etag",
	                              url="https://gist.githubusercontent.com/foosel/12e89d885c32b3adb81f5a999331f151/raw/m108_support.py",
	                              method="single_file_plugin"))

Some new examples for software update configs have also been added to the docs, making use of the new stuff: https://docs.octoprint.org/en/maintenance/bundledplugins/softwareupdate.html