Some minor changes before merging the PR
* moved virtual printer into plugin * made default serial factory use supplied parameters instead of directly utilizing self._port and similar * documented new hook
This commit is contained in:
parent
5588deb925
commit
8ac375fc9b
4 changed files with 126 additions and 13 deletions
|
|
@ -3,6 +3,9 @@
|
|||
Available plugin hooks
|
||||
======================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
.. _sec-plugins-hook-comm-protocol-action:
|
||||
|
||||
octoprint.comm.protocol.action
|
||||
|
|
@ -111,4 +114,81 @@ octoprint.comm.protocol.scripts
|
|||
:param str script_type: The type of the script for which the hook was called, currently only "gcode" is supported here.
|
||||
:param str script_name: The name of the script for which the hook was called.
|
||||
:return: A 2-tuple in the form ``(prefix, postfix)`` or None
|
||||
:rtype: tuple or None
|
||||
:rtype: tuple or None
|
||||
|
||||
.. _sec-plugins-hook-comm-transport-serial-factory:
|
||||
|
||||
octoprint.comm.transport.serial.factory
|
||||
---------------------------------------
|
||||
|
||||
.. py:function:: hook(comm_instance, port, baudrate, read_timeout, *args, **kwargs)
|
||||
|
||||
Return a serial object to use as serial connection to the printer. If a handler cannot create a serial object
|
||||
for the specified ``port`` (and ``baudrate``), it should just return ``None``.
|
||||
|
||||
If the hook handler needs to perform state switches (e.g. for autodetection) or other operations on the
|
||||
:class:`~octoprint.util.comm.MachineCom` instance, it can use the supplied ``comm_instance`` to do so. Plugin
|
||||
authors should keep in mind however that due to a pending change in the communication layer of
|
||||
OctoPrint, that interface will change in the future. Authors are advised to follow OctoPrint's development
|
||||
closely if directly utilizing :class:`~octoprint.util.comm.MachineCom` functionality.
|
||||
|
||||
A valid serial instance is expected to provide the following methods, analogue to PySerial's
|
||||
`serial.Serial <https://pythonhosted.org//pyserial/pyserial_api.html#serial.Serial>`_:
|
||||
|
||||
readline(size=None, eol='\n')
|
||||
Reads a line from the serial connection, compare `serial.Filelike.readline <https://pythonhosted.org//pyserial/pyserial_api.html#serial.FileLike.readline>`_.
|
||||
write(data)
|
||||
Writes data to the serial connection, compare `serial.Filelike.write <https://pythonhosted.org//pyserial/pyserial_api.html#serial.FileLike.write>`_.
|
||||
close()
|
||||
Closes the serial connection, compare `serial.Serial.close <https://pythonhosted.org//pyserial/pyserial_api.html#serial.Serial.close>`_.
|
||||
|
||||
Additionally setting the following attributes need to be supported if baudrate detection is supposed to work:
|
||||
|
||||
baudrate
|
||||
An integer describing the baudrate to use for the serial connection, compare `serial.Serial.baudrate <https://pythonhosted.org//pyserial/pyserial_api.html#serial.Serial.baudrate>`_.
|
||||
timeout
|
||||
An integer describing the read timeout on the serial connection, compare `serial.Serial.timeout <https://pythonhosted.org//pyserial/pyserial_api.html#serial.Serial.timeout>`_.
|
||||
|
||||
**Example:**
|
||||
|
||||
Serial factory similar to the default one which performs auto detection of the serial port if ``port`` is ``None``
|
||||
or ``AUTO``.
|
||||
|
||||
.. code-block:: python
|
||||
:linenos:
|
||||
|
||||
def default(comm_instance, port, baudrate, connection_timeout):
|
||||
if port is None or port == 'AUTO':
|
||||
# no known port, try auto detection
|
||||
comm_instance._changeState(comm_instance.STATE_DETECT_SERIAL)
|
||||
serial_obj = comm_instance._detectPort(False)
|
||||
if serial_obj is None:
|
||||
comm_instance._log("Failed to autodetect serial port")
|
||||
comm_instance._errorValue = 'Failed to autodetect serial port.'
|
||||
comm_instance._changeState(comm_instance.STATE_ERROR)
|
||||
eventManager().fire(Events.ERROR, {"error": comm_instance.getErrorString()})
|
||||
return None
|
||||
|
||||
else:
|
||||
# connect to regular serial port
|
||||
comm_instance._log("Connecting to: %s" % port)
|
||||
if baudrate == 0:
|
||||
serial_obj = serial.Serial(str(port), 115200, timeout=connection_timeout, writeTimeout=10000, parity=serial.PARITY_ODD)
|
||||
else:
|
||||
serial_obj = serial.Serial(str(port), baudrate, timeout=connection_timeout, writeTimeout=10000, parity=serial.PARITY_ODD)
|
||||
serial_obj.close()
|
||||
serial_obj.parity = serial.PARITY_NONE
|
||||
serial_obj.open()
|
||||
|
||||
return serial_obj
|
||||
|
||||
:param MachineCom comm_instance: The :class:`~octoprint.util.comm.MachineCom` instance which triggered the hook.
|
||||
:param port str: The port for which to construct a serial instance. May be ``None`` or ``AUTO`` in which case port
|
||||
auto detection is to be performed.
|
||||
:param baudrate int: The baudrate for which to construct a serial instance. May be 0 in which case baudrate auto
|
||||
detection is to be performed.
|
||||
:param read_timeout int: The read timeout to set on the serial port.
|
||||
:return: The constructed serial object ready for use, or ``None`` if the handler could not construct the object.
|
||||
:rtype: A serial instance implementing implementing the methods ``readline(...)``, ``write(...)``, ``close()`` and
|
||||
optionally ``baudrate`` and ``timeout`` attributes as described above.
|
||||
|
||||
|
|
|
|||
38
src/octoprint/plugins/virtual_printer/__init__.py
Normal file
38
src/octoprint/plugins/virtual_printer/__init__.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# coding=utf-8
|
||||
from __future__ import absolute_import
|
||||
|
||||
__author__ = "Gina Häußge <osd@foosel.net>"
|
||||
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
|
||||
__copyright__ = "Copyright (C) 2015 The OctoPrint Project - Released under terms of the AGPLv3 License"
|
||||
|
||||
import octoprint.plugin
|
||||
|
||||
class VirtualPrinterPlugin(octoprint.plugin.SettingsPlugin):
|
||||
|
||||
def virtual_printer_factory(self, comm_instance, port, baudrate, read_timeout):
|
||||
if not port == "VIRTUAL":
|
||||
return None
|
||||
|
||||
if not self._settings.global_get_boolean(["devel", "virtualPrinter", "enabled"]):
|
||||
return None
|
||||
|
||||
from . import virtual
|
||||
serial_obj = virtual.VirtualPrinter(read_timeout=float(read_timeout))
|
||||
return serial_obj
|
||||
|
||||
__plugin_name__ = "Virtual Printer"
|
||||
__plugin_author__ = "Gina Häußge, based on work by Daid Braam"
|
||||
__plugin_homepage__ = "https://github.com/foosel/OctoPrint/wiki/Plugin:-Virtual-Printer"
|
||||
__plugin_license__ = "AGPLv3"
|
||||
__plugin_description__ = "Provides a virtual printer via a virtual serial port for development and testing purposes"
|
||||
|
||||
def __plugin_load__():
|
||||
plugin = VirtualPrinterPlugin()
|
||||
|
||||
global __plugin_implementation__
|
||||
__plugin_implementation__ = plugin
|
||||
|
||||
global __plugin_hooks__
|
||||
__plugin_hooks__ = {
|
||||
"octoprint.comm.transport.serial.factory": plugin.virtual_printer_factory
|
||||
}
|
||||
|
|
@ -25,7 +25,6 @@ from octoprint.events import eventManager, Events
|
|||
from octoprint.filemanager import valid_file_type
|
||||
from octoprint.filemanager.destinations import FileDestinations
|
||||
from octoprint.util import get_exception_string, sanitize_ascii, filter_non_ascii, CountedEvent, RepeatedTimer
|
||||
from octoprint.util.virtual import VirtualPrinter
|
||||
|
||||
try:
|
||||
import _winreg
|
||||
|
|
@ -174,7 +173,7 @@ class MachineCom(object):
|
|||
self._gcode_hooks = self._pluginManager.get_hooks("octoprint.comm.protocol.gcode")
|
||||
self._printer_action_hooks = self._pluginManager.get_hooks("octoprint.comm.protocol.action")
|
||||
self._gcodescript_hooks = self._pluginManager.get_hooks("octoprint.comm.protocol.scripts")
|
||||
self._serial_hooks = self._pluginManager.get_hooks("octoprint.comm.protocol.serial")
|
||||
self._serial_factory_hooks = self._pluginManager.get_hooks("octoprint.comm.transport.serial.factory")
|
||||
|
||||
# SD status data
|
||||
self._sdAvailable = False
|
||||
|
|
@ -1205,8 +1204,8 @@ class MachineCom(object):
|
|||
return None
|
||||
|
||||
def _openSerial(self):
|
||||
def default(_, port, baudrate, connection_timeout):
|
||||
if self._port is None or self._port == 'AUTO':
|
||||
def default(_, port, baudrate, read_timeout):
|
||||
if port is None or port == 'AUTO':
|
||||
# no known port, try auto detection
|
||||
self._changeState(self.STATE_DETECT_SERIAL)
|
||||
serial_obj = self._detectPort(False)
|
||||
|
|
@ -1217,24 +1216,20 @@ class MachineCom(object):
|
|||
eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
|
||||
return None
|
||||
|
||||
elif port == "VIRTUAL":
|
||||
# virtual printer, use that
|
||||
serial_obj = VirtualPrinter()
|
||||
|
||||
else:
|
||||
# connect to regular serial port
|
||||
self._log("Connecting to: %s" % self._port)
|
||||
self._log("Connecting to: %s" % port)
|
||||
if baudrate == 0:
|
||||
serial_obj = serial.Serial(str(port), 115200, timeout=connection_timeout, writeTimeout=10000, parity=serial.PARITY_ODD)
|
||||
serial_obj = serial.Serial(str(port), 115200, timeout=read_timeout, writeTimeout=10000, parity=serial.PARITY_ODD)
|
||||
else:
|
||||
serial_obj = serial.Serial(str(port), baudrate, timeout=connection_timeout, writeTimeout=10000, parity=serial.PARITY_ODD)
|
||||
serial_obj = serial.Serial(str(port), baudrate, timeout=read_timeout, writeTimeout=10000, parity=serial.PARITY_ODD)
|
||||
serial_obj.close()
|
||||
serial_obj.parity = serial.PARITY_NONE
|
||||
serial_obj.open()
|
||||
|
||||
return serial_obj
|
||||
|
||||
serial_factories = self._serial_hooks.items() + [("default", default)]
|
||||
serial_factories = self._serial_factory_hooks.items() + [("default", default)]
|
||||
for name, factory in serial_factories:
|
||||
try:
|
||||
serial_obj = factory(self, self._port, self._baudrate, settings().getFloat(["serial", "timeout", "connection"]))
|
||||
|
|
|
|||
Loading…
Reference in a new issue