Skip to content

Commit

Permalink
Initial checkin
Browse files Browse the repository at this point in the history
It's a start.
  • Loading branch information
markwal committed Mar 31, 2015
1 parent a75d47c commit 08b523c
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 0 deletions.
46 changes: 46 additions & 0 deletions octoprint_GPX/__init__.py
@@ -0,0 +1,46 @@
# coding=utf-8
from __future__ import absolute_import

import octoprint.plugin

class GPXPlugin(octoprint.plugin.TemplatePlugin, octoprint.plugin.SettingsPlugin):
def serial_handler(self, comm, port, baudrate, timeout):
if self._settings.get(["protocol"]) != "GPX":
return None

self._logger.info("Connecting through x3g.")
try:
if port is None or port == 'AUTO':
port = comm.detectPort(True)
if port is None:
return None
self._logger.info("calling constructor %s %ld" % (port, baudrate))
from .gpxprinter import GpxPrinter
return GpxPrinter(port, baudrate, timeout)
except Exception as e:
self._logger.info("Failed to connect to x3g e = %s." % e);
raise

def on_after_startup(self):
self._logger.info("GPXPlugin startup!")

def get_settings_defaults(self):
return dict(protocol="gcode")

def get_template_configs(self):
return [
dict(type="settings", custom_bindings=False)
]


__plugin_implementation__ = GPXPlugin()


def __plugin_init__():
plugin = GPXPlugin()

global __plugin_implementation__
__plugin_implementation__ = plugin

global __plugin_hooks__
__plugin_hooks__ = {"octoprint.comm.protocol.serial": plugin.serial_handler}
86 changes: 86 additions & 0 deletions octoprint_GPX/gpxprinter.py
@@ -0,0 +1,86 @@
# coding=utf-8
from __future__ import absolute_import
__author__ = "Mark Walker <markwal@hotmail.com> based on work by Gina Häußge"
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'

import logging
import time
import Queue

from octoprint.settings import settings

gpxAvailable = False
try:
import gpx
gpxAvailable = True
except:
pass

class GpxPrinter():
def __init__(self, port = None, baudrate = None, timeout = 0):
self._logger = logging.getLogger(__name__)
if not gpxAvailable:
self._logger.info("Unable to import gpx module")
raise ValueError("Unable to import gpx module")
if baudrate == 0:
raise IOError("AUTO baudrate not currently supported by GPX")
self.port = port
self.baudrate = self._baudrate = baudrate
self.timeout = timeout
self._logger.info("GPXPrinter created, port: %s, baudrate: %s" % (self.port, self.baudrate))
self.outgoing = Queue.Queue()
self.baudrateError = False;
try:
self._append(gpx.connect(port, baudrate, settings().getBaseFolder("plugins") + "/gpx.ini")) #, settings().getBaseFolder("logs") + "/gpx.log")
except Exception as e:
self._logger.info("gpx.connect raised exception = %s" % e)
raise

def _append(self, s):
if (s != ''):
for item in s.split('\n'):
self.outgoing.put(item)

def write(self, data):
data = data.strip()
self._logger.info("%s" % data)
# strip checksum
if "*" in data:
data = data[:data.rfind("*")]
if (self.baudrate != self._baudrate):
try:
self._baudrate = self.baudrate
self._logger.info("new baudrate = %d" % self.baudrate)
gpx.set_baudrate(self.baudrate)
self.baudrateError = False
except ValueError:
self.baudrateError = True
self.outgoing.put('')
pass
return
self._append(gpx.write("%s" % data))

def readline(self):
while (self.baudrateError):
if (self._baudrate != self.baudrate):
self.write("M105");
return ''
try:
s = self.outgoing.get_nowait()
self._logger.info("readline: %s" % s)
return s
except Queue.Empty:
pass
self._append(gpx.readnext())
try:
s = self.outgoing.get(timeout=self.timeout)
self._logger.info("readline: %s" % s)
return s
except Queue.Empty:
self._logger.info("timeout")
pass
return ''

def close(self):
gpx.disconnect()
return
7 changes: 7 additions & 0 deletions octoprint_GPX/templates/GPX_settings.jinja2
@@ -0,0 +1,7 @@
<div class="control-group">
<label class="control-label">{{ _('Protocol') }}</label>
<select data-bind="uniqueName: console.log($data), value: settings.plugins.GPX.protocol">
<option value="gcode">{{ _('G-Code') }}</option>
<option value="GPX">{{ _('x3g (via GPX)') }}</option>
</select>
</div>
2 changes: 2 additions & 0 deletions requirements.txt
@@ -0,0 +1,2 @@
OctoPrint

73 changes: 73 additions & 0 deletions setup.py
@@ -0,0 +1,73 @@
# coding=utf-8
import setuptools

########################################################################################################################

plugin_identifier = "GPX"
plugin_package = "octoprint_%s" % plugin_identifier
plugin_name = "OctoPrint GPX"
plugin_version = "0.1"
plugin_description = "Emulates the gcode printer protocol by translating to/from x3g."
plugin_author = "Mark Walker"
plugin_author_email = "markwal@hotmail.com"
plugin_url = "http://github.com/markwal/OctoPrint-GPX"
plugin_license = "MIT"

# Additional package data to install for this plugin. The subfolders "templates", "static" and "translations" will
# already be installed automatically if they exist.
plugin_additional_data = []

########################################################################################################################

def package_data_dirs(source, sub_folders):
import os
dirs = []

for d in sub_folders:
folder = os.path.join(source, d)
if not os.path.exists(folder):
continue

for dirname, _, files in os.walk(folder):
dirname = os.path.relpath(dirname, source)
for f in files:
dirs.append(os.path.join(dirname, f))

return dirs

def requirements(filename):
return filter(lambda line: line and not line.startswith("#"), map(lambda line: line.strip(), open(filename).read().split("\n")))

def params():
# Our metadata, as defined above
name = plugin_name
version = plugin_version
description = plugin_description
author = plugin_author
author_email = plugin_author_email
url = plugin_url
license = plugin_license

# we only have our plugin package to install
packages = [plugin_package]

# we might have additional data files in sub folders that need to be installed too
package_data = {plugin_package: package_data_dirs(plugin_package, ['static', 'templates', 'translations'] + plugin_additional_data)}
include_package_data = True

# If you have any package data that needs to be accessible on the file system, such as templates or static assets
# this plugin is not zip_safe.
zip_safe = False

# Read the requirements from our requirements.txt file
install_requires = requirements("requirements.txt")

# Hook the plugin into the "octoprint.plugin" entry point, mapping the plugin_identifier to the plugin_package.
# That way OctoPrint will be able to find the plugin and load it.
entry_points = {
"octoprint.plugin": ["%s = %s" % (plugin_identifier, plugin_package)]
}

return locals()

setuptools.setup(**params())

0 comments on commit 08b523c

Please sign in to comment.