Combine plugins

Hi,

Is it possible to combine multiple plugins? For example catch an event of a filament runout plugin and then use the pushover plugin too send a notification.

I have a feature request on my GitHub page (https://github.com/thijsbekke/OctoPrint-Pushover/issues/37) but I don't want too develop another filament sensor plugin.

And how do I do that?

Hi @thijsbekke,

out of the box there is no "communication-path" between plugins.

My DisplayLayerProgress-Plugin (DLP) e.g. provides data and a lot of other Plugins consume this data in different ways. E.g. "Dashboard-Plugin" listen on the internal OP Eventbus or "OctoPod" is using a web-socket interface.
So, this plugin provides several data-provider interfaces (eventbus, websocket, rest-api).

On the other hand my PrintJobHistory-Plugin is a data consumer. It collects data from DLP, PreHeat,...and a lot of other plugin.
Here you need to contact the "Provider-Plugin" Author to define an interface (e.g. eventbus naming/structure) or (more risky) just grab the plugin implementation and read the fields.


	pluginInfo = self._getPluginInformation("preheat")
	self._preHeatPluginImplementationState = pluginInfo[0]
	self._preHeatPluginImplementation = pluginInfo[1]
...
       neededValue = self._preHeatPluginImplementation.neededValue
...

	# get the plugin with status information
	# [0] == status-string
	# [1] == implementaiton of the plugin
	def _getPluginInformation(self, pluginKey):

		status = None
		implementation = None

		if pluginKey in self._plugin_manager.plugins:
			plugin = self._plugin_manager.plugins[pluginKey]
			if plugin != None:
				if (plugin.enabled == True):
					status = "enabled"
					# for OP 1.4.x we need to check agains "incompatible"-attribute
					if (hasattr(plugin, 'incompatible') ):
						if (plugin.incompatible == False):
							implementation = plugin.implementation
						else:
							status = "incompatible"
					else:
						# OP 1.3.x
						implementation = plugin.implementation
					pass
				else:
					status = "disabled"
		else:
			status = "missing"

		return [status, implementation]

Hi @OllisGit,

Thanks for the reply, I tried it and yes I can get values from other plugins. But then I still need to write the logica in my own plugin, and I don't want that.

The Filament-Reloaded plugin has an API endpoint which I can poll that. Is that an acceptable solution? I don't know.

It would be perfect if the Filament-Reloaded could throw an event which my plugins listens for, I think self._plugin_manager.send_plugin_message( will do just that. I am going too try that.

API endpoints are completely acceptable options. They are in my power plugins and other systems are hooking into them. But in your case, yes an eventbus driven integration would probably be preferred because the send_plugin_message I believe will only work when a web browser is open to the OctoPrint web interface.

I just looked at your linked issue and I'm curious why the pause event doesn't work as mentioned by the reply?

@jneilliii good point about the web interface, I did not know that. lets look into the eventbus driven integration option.

I don't know why that don't work either, should it? Because then the issue can be closed and I don't have to do anything. :slight_smile:

It looks like that the https://github.com/kontakt/Octoprint-Filament-Reloaded is not maintained any more.
So, my suggestion is to create a fork and take over that plugin.

Make a patch for using the eventbus!
Something like this:
Patch

def sensor_callback(self, _):
...
if self.no_filament():
   eventManager().fire("Filament-Reloaded-Sensor-Status", "no filament")
else:
   eventManager().fire("Filament-Reloaded-Sensor-Status", "filament detected")

And in your plugin you can use the on_event Methode or you subscribe to a above event:

eventmanager.subscribe("Filament-Reloaded-Sensor-Status", self._myEventListener)
or
def on_event(self, event, payload):
    if event == ""Filament-Reloaded-Sensor-Status"":
        ## do something usefull

As @jneilliii already mentioned send_plugin_message method could only be used, if you want to exchange data from one plugin to an other via the browser-session.

BR
Olli

Another filament sensor plugin maybe I will do that.
There are already enough filament plugins, https://plugins.octoprint.org/search/?q=Filament

Thanks for the snippets, I will definitely try it.

You should try to integrate the most popular/recently updated plugin to submit your changes to. As you mentioned some of those plugin authors have gone ghost.

Don't just blindly create arbitrary event names though. They should follow a pattern and also need to be registered with the system.

https://docs.octoprint.org/en/master/plugins/hooks.html#octoprint-events-register-custom-events

Example use:

https://github.com/OctoPrint/OctoPrint/blob/a819b5d2ca2443f3f58532e8525b349877a87d06/src/octoprint/plugins/pi_support/init.py#L326

https://github.com/OctoPrint/OctoPrint/blob/a819b5d2ca2443f3f58532e8525b349877a87d06/src/octoprint/plugins/pi_support/init.py#L323

https://github.com/OctoPrint/OctoPrint/blob/a819b5d2ca2443f3f58532e8525b349877a87d06/src/octoprint/plugins/tracking/init.py#L140

Note the hasattr check in the consumer (last link). If the plugin providing the event isn't there, an error would be produced without that.

1 Like