Skip to content

Commit

Permalink
plugin settings finally works. saving it nnow
Browse files Browse the repository at this point in the history
  • Loading branch information
kennethjiang committed Jan 5, 2019
1 parent f1f3297 commit d3c82cc
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 77 deletions.
3 changes: 2 additions & 1 deletion .editorconfig
Expand Up @@ -10,7 +10,8 @@ insert_final_newline = true
trim_trailing_whitespace = true

[**.py]
indent_style = tab
indent_style = space
indent_size = 4

[**.js]
indent_style = space
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -7,7 +7,7 @@
Install via the bundled [Plugin Manager](https://github.com/foosel/OctoPrint/wiki/Plugin:-Plugin-Manager)
or manually using this URL:

https://github.com/TheSpaghettiDetective/OctoPrint-TheSpaghettiDetective/archive/master.zip
https://github.com/TheSpaghettiDetective/TheSpaghettiDetective/archive/master.zip

**TODO:** Describe how to install your plugin, if more needs to be done than just installing it via pip or through
the plugin manager.
Expand Down
2 changes: 1 addition & 1 deletion extras/README.txt
@@ -1,6 +1,6 @@
Currently Cookiecutter generates the following helpful extras to this folder:

TheSpaghettiDetective.md
thespaghettidetective.md
Data file for plugins.octoprint.org. Fill in the missing TODOs once your
plugin is ready for release and file a PR as described at
http://plugins.octoprint.org/help/registering/ to get it published.
Expand Down
14 changes: 7 additions & 7 deletions extras/TheSpaghettiDetective.md
@@ -1,18 +1,18 @@
---
layout: plugin

id: TheSpaghettiDetective
id: thespaghettidetective
title: TheSpaghettiDetective
description: OctoPrint plugin for The Spaghetti Detective
author: Kenneth Jiang
description: TODO
author: The Spaghetti Detective
license: AGPLv3

# TODO
date: today's date in format YYYY-MM-DD, e.g. 2015-04-21

homepage: https://github.com/TheSpaghettiDetective/OctoPrint-TheSpaghettiDetective
source: https://github.com/TheSpaghettiDetective/OctoPrint-TheSpaghettiDetective
archive: https://github.com/TheSpaghettiDetective/OctoPrint-TheSpaghettiDetective/archive/master.zip
homepage: https://github.com/TheSpaghettiDetective/TheSpaghettiDetective
source: https://github.com/TheSpaghettiDetective/TheSpaghettiDetective
archive: https://github.com/TheSpaghettiDetective/TheSpaghettiDetective/archive/master.zip

# TODO
# Set this to true if your plugin uses the dependency_links setup parameter to include
Expand Down Expand Up @@ -86,4 +86,4 @@ compatibility:
---

**TODO**: Longer description of your plugin, configuration examples etc. This part will be visible on the page at
http://plugins.octoprint.org/plugin/TheSpaghettiDetective/
http://plugins.octoprint.org/plugin/thespaghettidetective/
170 changes: 114 additions & 56 deletions octoprint_thespaghettidetective/__init__.py
Expand Up @@ -4,6 +4,9 @@
import threading
import os, sys, time
import requests
import backoff

from .webcam_capture import capture_jpeg

### (Don't forget to remove me)
# This is a basic skeleton for your plugin's __init__.py. You probably want to adjust the class name of your plugin
Expand All @@ -17,70 +20,125 @@

_logger = logging.getLogger(__name__)

POLL_INTERVAL_SECONDS = 30

class TheSpaghettiDetectivePlugin(octoprint.plugin.SettingsPlugin,
octoprint.plugin.StartupPlugin,
octoprint.plugin.EventHandlerPlugin,
octoprint.plugin.AssetPlugin,
octoprint.plugin.TemplatePlugin):

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

##~~ SettingsPlugin mixin

def get_settings_defaults(self):
return dict(
endpoint_prefix="https://app.gofab.xyz/"
)

##~~ AssetPlugin mixin

def get_assets(self):
# Define your plugin's asset files to automatically include in the
# core UI here.
return dict(
js=["js/TheSpaghettiDetective.js"],
css=["css/TheSpaghettiDetective.css"],
less=["less/TheSpaghettiDetective.less"]
)

##~~ Softwareupdate hook

def get_update_information(self):
# Define the configuration for your plugin to use with the Software Update
# Plugin here. See https://github.com/foosel/OctoPrint/wiki/Plugin:-Software-Update
# for details.
return dict(
TheSpaghettiDetective=dict(
displayName="TheSpaghettiDetective Plugin",
displayVersion=self._plugin_version,

# version check: github repository
type="github_release",
user="kennethjiang",
repo="OctoPrint-TheSpaghettiDetective",
current=self._plugin_version,

# update method: pip
pip="https://github.com/TheSpaghettiDetective/OctoPrint-TheSpaghettiDetective/archive/{target_version}.zip"
)
)
octoprint.plugin.StartupPlugin,
octoprint.plugin.EventHandlerPlugin,
octoprint.plugin.AssetPlugin,
octoprint.plugin.TemplatePlugin):

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

##~~ SettingsPlugin mixin

def get_settings_defaults(self):
return dict(
endpoint_prefix=''
)

##~~ AssetPlugin mixin

def get_assets(self):
# Define your plugin's asset files to automatically include in the
# core UI here.
return dict(
js=["js/TheSpaghettiDetective.js"],
css=["css/TheSpaghettiDetective.css"],
less=["less/TheSpaghettiDetective.less"]
)

##~~ Softwareupdate hook

def get_update_information(self):
# Define the configuration for your plugin to use with the Software Update
# Plugin here. See https://github.com/foosel/OctoPrint/wiki/Plugin:-Software-Update
# for details.
return dict(
TheSpaghettiDetective=dict(
displayName="TheSpaghettiDetective Plugin",
displayVersion=self._plugin_version,

# version check: github repository
type="github_release",
user="kennethjiang",
repo="OctoPrint-TheSpaghettiDetective",
current=self._plugin_version,

# update method: pip
pip="https://github.com/TheSpaghettiDetective/OctoPrint-TheSpaghettiDetective/archive/{target_version}.zip"
)
)

##~~Startup Plugin

def on_after_startup(self):
main_thread = threading.Thread(target=self.main_loop)
main_thread.daemon = True
main_thread.start()


## Private methods

def octoprint_data(self):
data = self._printer.get_current_data()
data['temperatures'] = self._printer.get_current_temperatures()
data['octoprint_port'] = self._octoprint_port
data['octoprint_ip'] = self._octoprint_ip
return data

def main_loop(self):
last_poll = 0
while True:
print(self._settings)
print(self._settings.get(["endpoint_prefix"]))
if not self._settings.get(["endpoint_prefix"]) or not self._settings.get(["auth_token"]):
next

if last_poll < time.time() - POLL_INTERVAL_SECONDS:
last_poll = time.time()
print("here!")
#self.post_jpg_to_endpoint()

time.sleep(1)

@backoff.on_exception(backoff.expo, Exception, max_value=240)
def post_jpg_to_endpoint(self):
endpoint_prefix = self._settings.get(["endpoint_prefix"]).strip()
if endpoint_prefix.endswith('/'):
endpoint_prefix = endpoint_prefix[:-1]

endpoint = endpoint_prefix + '/dev/predict'

files = {'image': capture_jpeg(self._settings.global_get(["webcam"]))}

resp = requests.post( endpoint, files=files)
resp.raise_for_status()
for command in resp.json():
if command["command"] == "print":
self.download_and_print(command["data"]["file_url"], command["data"]["file_name"])
if command["command"] == "cancel":
self._printer.cancel_print()
if command["command"] == "pause":
self._printer.pause_print()
if command["command"] == "resume":
self._printer.resume_print()


# If you want your plugin to be registered within OctoPrint under a different name than what you defined in setup.py
# ("OctoPrint-PluginSkeleton"), you may define that here. Same goes for the other metadata derived from setup.py that
# can be overwritten via __plugin_xyz__ control properties. See the documentation for that.
__plugin_name__ = "TheSpaghettiDetective Plugin"
__plugin_name__ = "The Spaghetti Detective"

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

global __plugin_hooks__
__plugin_hooks__ = {
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information
}
global __plugin_hooks__
__plugin_hooks__ = {
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information
}

@@ -1,7 +1,7 @@
/*
* View model for TheSpaghettiDetective
*
* Author: Kenneth Jiang
* Author: The Spaghetti Detective
* License: AGPLv3
*/
$(function() {
Expand All @@ -23,7 +23,7 @@ $(function() {
construct: ThespaghettidetectiveViewModel,
// ViewModels your plugin depends on, e.g. loginStateViewModel, settingsViewModel, ...
dependencies: [ /* "loginStateViewModel", "settingsViewModel" */ ],
// Elements to bind to, e.g. #settings_plugin_TheSpaghettiDetective, #tab_plugin_TheSpaghettiDetective, ...
// Elements to bind to, e.g. #settings_plugin_thespaghettidetective, #tab_plugin_thespaghettidetective, ...
elements: [ /* ... */ ]
});
});
@@ -1,9 +1,14 @@
<form class="form-horizontal">
<div class="control-group">
<label class="control-label">{{ _('GoFab Token') }}</label>
<label class="control-label">{{ _('Server Address') }}</label>
<div class="controls">
<input type="text" class="input-block-level" data-bind="value: settings.plugins.TheSpaghettiDetective.auth_token">
<input type="text" class="input-block-level" data-bind="value: settings.plugins.thespaghettidetective.endpoint_prefix">
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('Auth Token') }}</label>
<div class="controls">
<input type="text" class="input-block-level" data-bind="value: settings.plugins.thespaghettidetective.auth_token">
</div>
</div>
</form>

62 changes: 62 additions & 0 deletions octoprint_thespaghettidetective/webcam_capture.py
@@ -0,0 +1,62 @@
# coding=utf-8
from __future__ import absolute_import
from datetime import datetime, timedelta
import time
import logging
import StringIO
import re
import urllib2
from urlparse import urlparse
from contextlib import closing
import requests
import backoff

_logger = logging.getLogger(__name__)

@backoff.on_exception(backoff.expo, Exception, max_value=1200)
@backoff.on_predicate(backoff.expo, max_value=1200)
def capture_jpeg(settings):
snapshot_url = settings.get("snapshot", '').strip()
if snapshot_url:
if not urlparse(snapshot_url).scheme:
snapshot_url = "http://localhost/" + re.sub(r"^\/", "", snapshot_url)

with closing(urllib2.urlopen(snapshot_url)) as res:
jpg = res.read()
return "--boundarydonotcross\r\nContent-Type: image/jpeg\r\nContent-Length: {0}\r\n\r\n{1}\r\n".format(len(jpg), jpg)

else:
stream_url = settings.get("stream", "/webcam/?action=stream").strip()
if not urlparse(stream_url).scheme:
stream_url = "http://localhost/" + re.sub(r"^\/", "", stream_url)

with closing(urllib2.urlopen(stream_url)) as res:
chunker = MjpegStreamChunker()

while True:
data = res.readline()
mjpg = chunker.findMjpegChunk(data)
if mjpg:
res.close()
return mjpg


class MjpegStreamChunker:

def __init__(self):
self.boundary = None
self.current_chunk = StringIO.StringIO()

# Return: mjpeg chunk if found
# None: in the middle of the chunk
def findMjpegChunk(self, line):
if not self.boundary: # The first time endOfChunk should be called with 'boundary' text as input
self.boundary = line
self.current_chunk.write(line)
return None

if len(line) == len(self.boundary) and line == self.boundary: # start of next chunk
return self.current_chunk.getvalue()

self.current_chunk.write(line)
return None
12 changes: 6 additions & 6 deletions setup.py
Expand Up @@ -4,7 +4,7 @@
### Do not forget to adjust the following variables to your own plugin.

# The plugin's identifier, has to be unique
plugin_identifier = "TheSpaghettiDetective"
plugin_identifier = "thespaghettidetective"

# The plugin's python package, should be "octoprint_<plugin identifier>", has to be unique
plugin_package = "octoprint_thespaghettidetective"
Expand All @@ -18,22 +18,22 @@

# The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin
# module
plugin_description = """OctoPrint plugin for The Spaghetti Detective"""
plugin_description = """TODO"""

# The plugin's author. Can be overwritten within OctoPrint's internal data via __plugin_author__ in the plugin module
plugin_author = "Kenneth Jiang"
plugin_author = "The Spaghetti Detective"

# The plugin's author's mail address.
plugin_author_email = "k@thespaghettidetective.com"
plugin_author_email = "admin@thespaghettidetective.com"

# The plugin's homepage URL. Can be overwritten within OctoPrint's internal data via __plugin_url__ in the plugin module
plugin_url = "https://github.com/TheSpaghettiDetective/OctoPrint-TheSpaghettiDetective"
plugin_url = "https://github.com/TheSpaghettiDetective/TheSpaghettiDetective"

# The plugin's license. Can be overwritten within OctoPrint's internal data via __plugin_license__ in the plugin module
plugin_license = "AGPLv3"

# Any additional requirements besides OctoPrint should be listed here
plugin_requires = []
plugin_requires = ["OctoPrint>=1.3.1", "backoff>=1.4.3"]

### --------------------------------------------------------------------------------------------------------------------
### More advanced options that you usually shouldn't have to touch follow after this point
Expand Down

0 comments on commit d3c82cc

Please sign in to comment.