first commit

This commit is contained in:
David Zingg 2019-11-19 21:29:32 +01:00
commit 6daeefa71c
16 changed files with 1149 additions and 0 deletions

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TestRunnerService">
<option name="projectConfiguration" value="Nosetests" />
<option name="PROJECT_TEST_RUNNER" value="Nosetests" />
</component>
</module>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 2.7 (venv)" project-jdk-type="Python SDK" />
<component name="PyCharmProfessionalAdvertiser">
<option name="shown" value="true" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/MyStromSwitchPlugin.iml" filepath="$PROJECT_DIR$/.idea/MyStromSwitchPlugin.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

37
.idea/workspace.xml Normal file
View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="7e2e0eec-b22e-4d48-8f24-196d1ed9b51a" name="Default Changelist" comment="" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ProjectId" id="1TqgYXT1S9U5eM0eUvs1YarA1ll" />
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="7e2e0eec-b22e-4d48-8f24-196d1ed9b51a" name="Default Changelist" comment="" />
<created>1574193087583</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1574193087583</updated>
</task>
<servers />
</component>
</project>

1
MANIFEST.in Normal file
View File

@ -0,0 +1 @@
include README.md

5
README.md Normal file
View File

@ -0,0 +1,5 @@
# OctoPrint MyStrom Switch Plugin
This OctoPrint plugin enables the system to control the myStrom switch and read the current Powerconsumption of your system

6
babel.cfg Normal file
View File

@ -0,0 +1,6 @@
[python: */**.py]
[jinja2: */**.jinja2]
extensions=jinja2.ext.autoescape, jinja2.ext.with_
[javascript: */**.js]
extract_messages = gettext, ngettext

View File

@ -0,0 +1,441 @@
# coding=utf-8
from __future__ import absolute_import
import ssl
import urllib2
import octoprint.plugin
from flask import make_response
from octoprint.events import eventManager, Events
from octoprint.server import user_permission
from octoprint.util import RepeatedTimer
class shutdownprinterPlugin(octoprint.plugin.SettingsPlugin,
octoprint.plugin.AssetPlugin,
octoprint.plugin.TemplatePlugin,
octoprint.plugin.SimpleApiPlugin,
octoprint.plugin.EventHandlerPlugin,
octoprint.plugin.StartupPlugin):
def __init__(self):
self.url = ""
self.previousEventIsCancel = False
self.gcode = "M81"
self._mode_shutdown_gcode = True
self._mode_shutdown_api = False
self._mode_shutdown_api_custom = False
self.api_custom_GET = False
self.api_custom_POST = False
self.api_custom_PUT = False
self.api_custom_url = ""
self.api_custom_json_header = ""
self.api_custom_body = ""
self.api_key_plugin = ""
self.api_json_command = ""
self.api_plugin_name = ""
self.api_plugin_port = 5000
self.extraCommand = ""
self.abortTimeout = 0
self.temperatureValue = 0
self.temperatureTarget = False
self.printFailed = False
self.printCancelled = False
self.rememberCheckBox = False
self.lastCheckBoxValue = False
self._shutdown_printer_enabled = True
self._timeout_value = None
self._abort_timer = None
self._abort_timer_temp = None
self.ctx = ssl.create_default_context()
self.ctx.check_hostname = False
self.ctx.verify_mode = ssl.CERT_NONE
def initialize(self):
self.gcode = self._settings.get(["gcode"])
self._logger.debug("gcode: %s" % self.gcode)
self.url = self._settings.get(["url"])
self._logger.debug("url: %s" % self.url)
self.api_key_plugin = self._settings.get(["api_key_plugin"])
self._logger.debug("api_key_plugin: %s" % self.api_key_plugin)
self._mode_shutdown_gcode = self._settings.get_boolean(["_mode_shutdown_gcode"])
self._logger.debug("_mode_shutdown_gcode: %s" % self._mode_shutdown_gcode)
self._mode_shutdown_api = self._settings.get_boolean(["_mode_shutdown_api"])
self._logger.debug("_mode_shutdown_api: %s" % self._mode_shutdown_api)
self._mode_shutdown_api_custom = self._settings.get_boolean(["_mode_shutdown_api_custom"])
self._logger.debug("_mode_shutdown_api_custom: %s" % self._mode_shutdown_api_custom)
self.api_custom_POST = self._settings.get_boolean(["api_custom_POST"])
self._logger.debug("api_custom_POST: %s" % self.api_custom_POST)
self.api_custom_GET = self._settings.get_boolean(["api_custom_GET"])
self._logger.debug("api_custom_GET: %s" % self.api_custom_GET)
self.api_custom_PUT = self._settings.get_boolean(["api_custom_PUT"])
self._logger.debug("api_custom_PUT: %s" % self.api_custom_PUT)
self.api_custom_url = self._settings.get(["api_custom_url"])
self._logger.debug("api_custom_url: %s" % self.api_custom_url)
self.api_custom_json_header = self._settings.get(["api_custom_json_header"])
self._logger.debug("api_custom_json_header: %s" % self.api_custom_json_header)
self.api_custom_body = self._settings.get(["api_custom_body"])
self._logger.debug("api_custom_body: %s" % self.api_custom_body)
self.api_json_command = self._settings.get(["api_json_command"])
self._logger.debug("api_json_command: %s" % self.api_json_command)
self.api_plugin_name = self._settings.get(["api_plugin_name"])
self._logger.debug("api_plugin_name: %s" % self.api_plugin_name)
self.api_plugin_port = self._settings.get_int(["api_plugin_port"])
self._logger.debug("api_plugin_port: %s" % self.api_plugin_port)
self.temperatureValue = self._settings.get_int(["temperatureValue"])
self._logger.debug("temperatureValue: %s" % self.temperatureValue)
self.temperatureTarget = self._settings.get_boolean(["temperatureTarget"])
self._logger.debug("temperatureTarget: %s" % self.temperatureTarget)
self.extraCommand = self._settings.get(["extraCommand"])
self._logger.debug("extraCommand: %s" % self.extraCommand)
self.abortTimeout = self._settings.get_int(["abortTimeout"])
self._logger.debug("abortTimeout: %s" % self.abortTimeout)
self.printFailed = self._settings.get_boolean(["printFailed"])
self._logger.debug("printFailed: %s" % self.printFailed)
self.printCancelled = self._settings.get_boolean(["printCancelled"])
self._logger.debug("printCancelled: %s" % self.printCancelled)
self.rememberCheckBox = self._settings.get_boolean(["rememberCheckBox"])
self._logger.debug("rememberCheckBox: %s" % self.rememberCheckBox)
self.lastCheckBoxValue = self._settings.get_boolean(["lastCheckBoxValue"])
self._logger.debug("lastCheckBoxValue: %s" % self.lastCheckBoxValue)
if self.rememberCheckBox:
self._shutdown_printer_enabled = self.lastCheckBoxValue
def get_assets(self):
return dict(js=["js/shutdownprinter.js"], css=["css/shutdownprinter.css"])
def get_template_configs(self):
return [dict(type="sidebar",
name="Shutdown Printer",
custom_bindings=False,
icon="power-off"),
dict(type="settings", custom_bindings=False)]
def get_api_commands(self):
return dict(enable=["eventView"],
status=[],
update=["eventView"],
disable=["eventView"],
shutdown=["mode", "eventView"],
abort=["eventView"])
def on_api_command(self, command, data):
if not user_permission.can():
return make_response("Insufficient rights", 403)
if command == "status":
return make_response(str(self._shutdown_printer_enabled), 200)
elif command == "enable":
self._shutdown_printer_enabled = True
elif command == "disable":
self._shutdown_printer_enabled = False
elif command == "shutdown":
self._shutdown_printer_API_CMD(data["mode"]) # mode 1 = gcode, mode 2 = api, mode 3 = custom api
elif command == "abort":
if self._abort_timer is not None:
self._abort_timer.cancel()
self._abort_timer = None
if self._abort_timer_temp is not None:
self._abort_timer_temp.cancel()
self._abort_timer_temp = None
self._timeout_value = None
self._logger.info("Shutdown aborted.")
if command == "enable" or command == "disable":
self.lastCheckBoxValue = self._shutdown_printer_enabled
if self.rememberCheckBox:
self._settings.set_boolean(["lastCheckBoxValue"], self.lastCheckBoxValue)
self._settings.save()
eventManager().fire(Events.SETTINGS_UPDATED)
if data["eventView"] == True:
self._plugin_manager.send_plugin_message(self._identifier,
dict(shutdownprinterEnabled=self._shutdown_printer_enabled,
type="timeout", timeout_value=self._timeout_value))
def on_event(self, event, payload):
# if event == Events.CLIENT_OPENED:
# self._plugin_manager.send_plugin_message(self._identifier, dict(shutdownprinterEnabled=self._shutdown_printer_enabled, type="timeout", timeout_value=self._timeout_value))
# return
if not self._shutdown_printer_enabled:
return
if event == Events.PRINT_STARTED:
# self._logger.info("Print started")
self.previousEventIsCancel = False
if event not in [Events.PRINT_DONE, Events.PRINT_FAILED, Events.PRINT_CANCELLED]:
return
return
if event == Events.PRINT_DONE:
self._temperature_target()
return
elif event == Events.PRINT_CANCELLED and self.printCancelled:
# self._logger.info("Print cancelled")
self.previousEventIsCancel = True
self._temperature_target()
return
elif event == Events.PRINT_CANCELLED:
# self._logger.info("Print cancelled")
self.previousEventIsCancel = True
return
elif event == Events.PRINT_FAILED and self.printFailed:
if self.previousEventIsCancel == True:
self.previousEventIsCancel = False
return;
# self._logger.info("Print failed")
self._temperature_target()
return
else:
self.previousEventIsCancel = False
return
def _temperature_target(self):
if self._abort_timer_temp is not None:
return
if self.temperatureTarget:
self._abort_timer_temp = RepeatedTimer(2, self._temperature_task)
self._abort_timer_temp.start()
else:
self._timer_start()
def _temperature_task(self):
if self._printer.get_state_id() == "PRINTING" and self._printer.is_printing() == True:
self._abort_timer_temp.cancel()
self._abort_timer_temp = None
return
self._temp = self._printer.get_current_temperatures()
tester = 0;
number = 0;
for tool in self._temp.keys():
if not tool == "bed":
if self._temp[tool]["actual"] <= self.temperatureValue:
tester += 1
number += 1
if tester == number:
self._abort_timer_temp.cancel()
self._abort_timer_temp = None
self._timer_start()
def _timer_start(self):
if self._abort_timer is not None:
return
self._logger.info("Starting abort shutdown printer timer.")
self._timeout_value = self.abortTimeout
self._abort_timer = RepeatedTimer(1, self._timer_task)
self._abort_timer.start()
def _timer_task(self):
if self._timeout_value is None:
return
self._timeout_value -= 1
self._plugin_manager.send_plugin_message(self._identifier,
dict(shutdownprinterEnabled=self._shutdown_printer_enabled,
type="timeout", timeout_value=self._timeout_value))
if self._printer.get_state_id() == "PRINTING" and self._printer.is_printing() == True:
self._timeout_value = 0
self._plugin_manager.send_plugin_message(self._identifier,
dict(shutdownprinterEnabled=self._shutdown_printer_enabled,
type="timeout", timeout_value=self._timeout_value))
self._abort_timer.cancel()
self._abort_timer = None
return
if self._timeout_value <= 0:
if self._abort_timer is not None:
self._abort_timer.cancel()
self._abort_timer = None
self._shutdown_printer()
def _shutdown_printer(self):
if self._mode_shutdown_gcode == True:
self._shutdown_printer_by_gcode()
elif self._mode_shutdown_api == True:
self._shutdown_printer_by_API()
else:
self._shutdown_printer_by_API_custom()
def _shutdown_printer_API_CMD(self, mode):
if mode == 1:
self._shutdown_printer_by_gcode()
elif mode == 2:
self._shutdown_printer_by_API()
elif mode == 3:
self._shutdown_printer_by_API_custom()
def _extraCommand(self):
if self.extraCommand != "":
process = subprocess.Popen(mCmdFound, shell=True, stdin=None, stdout=subprocess.PIPE)
self.extraCommand = process.communicate()
self._logger.info("response extraCommand: %s" % mCmdFound.rstrip().strip())
def _shutdown_printer_by_API(self):
url = "http://127.0.0.1:" + str(self.api_plugin_port) + "/api/plugin/" + self.api_plugin_name
headers = {'Content-Type': 'application/json', 'X-Api-Key': self.api_key_plugin}
data = self.api_json_command
self._logger.info("Shutting down printer with API")
try:
request = urllib2.Request(url, data=data, headers=headers)
request.get_method = lambda: "POST"
contents = urllib2.urlopen(request, timeout=30, context=self.ctx).read()
self._logger.debug("call response (POST API octoprint): %s" % contents)
self._extraCommand()
except Exception as e:
self._logger.error("Failed to connect to call api: %s" % e.message)
return
def _shutdown_printer_by_API_custom(self):
headers = {}
if self.api_custom_json_header != "":
headers = eval(self.api_custom_json_header)
if self.api_custom_PUT == True:
data = self.api_custom_body
self._logger.info("Shutting down printer with API custom (PUT)")
try:
request = urllib2.Request(self.api_custom_url, data=data, headers=headers)
request.get_method = lambda: "PUT"
contents = urllib2.urlopen(request, timeout=30, context=self.ctx).read()
self._logger.debug("call response (PUT): %s" % contents)
self._extraCommand()
except Exception as e:
self._logger.error("Failed to connect to call api: %s" % e.message)
return
if self.api_custom_POST == True:
data = self.api_custom_body
self._logger.info("Shutting down printer with API custom (POST)")
try:
request = urllib2.Request(self.api_custom_url, data=data, headers=headers)
request.get_method = lambda: "POST"
contents = urllib2.urlopen(request, timeout=30, context=self.ctx).read()
self._logger.debug("call response (POST): %s" % contents)
self._extraCommand()
except Exception as e:
self._logger.error("Failed to connect to call api: %s" % e.message)
return
elif self.api_custom_GET == True:
self._logger.info("Shutting down printer with API custom (GET)")
try:
request = urllib2.Request(self.api_custom_url, headers=headers)
contents = urllib2.urlopen(request, timeout=30, context=self.ctx).read()
self._logger.debug("call response (GET): %s" % contents)
self._extraCommand()
except Exception as e:
self._logger.error("Failed to connect to call api: %s" % e.message)
return
def _shutdown_printer_by_gcode(self):
self._printer.commands(self.gcode + " " + self.url)
self._logger.info("Shutting down printer with command: " + self.gcode + " " + self.url)
self._extraCommand()
def on_after_startup(self):
self._logger.info("Hello World!")
def get_settings_defaults(self):
return dict(
gcode="M81",
url="",
api_key_plugin="",
abortTimeout=30,
extraCommand="",
_mode_shutdown_gcode=True,
_mode_shutdown_api=False,
_mode_shutdown_api_custom=False,
api_custom_POST=False,
api_custom_GET=False,
api_custom_PUT=False,
api_custom_url="",
api_custom_json_header="",
api_custom_body="",
api_plugin_port=5000,
temperatureValue=110,
_shutdown_printer_enabled=True,
printFailed=False,
printCancelled=False,
rememberCheckBox=False,
lastCheckBoxValue=False
)
def on_settings_save(self, data):
octoprint.plugin.SettingsPlugin.on_settings_save(self, data)
self.gcode = self._settings.get(["gcode"])
self.url = self._settings.get(["url"])
self.api_key_plugin = self._settings.get(["api_key_plugin"])
self._mode_shutdown_gcode = self._settings.get_boolean(["_mode_shutdown_gcode"])
self._mode_shutdown_api = self._settings.get_boolean(["_mode_shutdown_api"])
self._mode_shutdown_api_custom = self._settings.get_boolean(["_mode_shutdown_api_custom"])
self.api_custom_POST = self._settings.get_boolean(["api_custom_POST"])
self.api_custom_GET = self._settings.get_boolean(["api_custom_GET"])
self.api_custom_PUT = self._settings.get_boolean(["api_custom_PUT"])
self.api_custom_url = self._settings.get(["api_custom_url"])
self.api_custom_json_header = self._settings.get(["api_custom_json_header"])
self.api_custom_body = self._settings.get(["api_custom_body"])
self.api_json_command = self._settings.get(["api_json_command"])
self.api_plugin_name = self._settings.get(["api_plugin_name"])
self.api_plugin_port = self._settings.get_int(["api_plugin_port"])
self.temperatureValue = self._settings.get_int(["temperatureValue"])
self.temperatureTarget = self._settings.get_int(["temperatureTarget"])
self.extraCommand = self._settings.get(["extraCommand"])
self.printFailed = self._settings.get_boolean(["printFailed"])
self.printCancelled = self._settings.get_boolean(["printCancelled"])
self.abortTimeout = self._settings.get_int(["abortTimeout"])
self.rememberCheckBox = self._settings.get_boolean(["rememberCheckBox"])
self.lastCheckBoxValue = self._settings.get_boolean(["lastCheckBoxValue"])
def get_update_information(self):
return dict(
shutdownprinter=dict(
displayName="Shutdown Printer",
displayVersion=self._plugin_version,
# version check: github repository
type="github_release",
user="devildant",
repo="OctoPrint-ShutdownPrinter",
current=self._plugin_version,
# update method: pip w/ dependency links
pip="https://github.com/devildant/OctoPrint-ShutdownPrinter/archive/{target_version}.zip"
)
)
__plugin_name__ = "Shutdown Printer"
def __plugin_load__():
global __plugin_implementation__
__plugin_implementation__ = shutdownprinterPlugin()
global __plugin_hooks__
__plugin_hooks__ = {
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information
}

View File

@ -0,0 +1,38 @@
/* #touch body #sidebar_plugin_shutdownprinter_wrapper .accordion-heading { */
/* display: block !important; */
/* pointer-events: none; */
/* margin: 40px -30px 0; */
/* padding: .5rem 30px; */
/* background-color: #00B0FF; */
/* color: black; */
/* } */
/* #touch body #sidebar_plugin_shutdownprinter_wrapper .accordion-heading>a, #touch body #sidebar_plugin_shutdownprinter_wrapper .accordion-heading>a i { */
/* color: black; */
/* font-size: 1.4375rem; */
/* padding-right: 0; */
/* padding-left: 0; */
/* } */
/* #touch body #sidebar_plugin_shutdownprinter > label { */
/* display: block; */
/* background:#333; */
/* padding-left: 50px; */
/* padding-top: 15px; */
/* padding-bottom: 15px; */
/* } */
/* #touch body #sidebar_plugin_shutdownprinter { */
/* pointer-events: auto; */
/* margin: 0px -30px 0; */
/* padding-right: 15px; */
/* padding-left: 15px; */
/* } */
.shutdownPrinterHideCancelBtnConfirm {
display:none;
}
#touch body #tabs #sidebar_plugin_shutdownprinter_wrapper_link a:before, #touch body #navbar #all_touchui_settings #sidebar_plugin_shutdownprinter_wrapper_link a:before,#touch body #tabs #sidebar_plugin_shutdownprinter_wrapper_link2 a:before, #touch body #navbar #all_touchui_settings #sidebar_plugin_shutdownprinter_wrapper_link2 a:before {
content: "\f011";
}

View File

@ -0,0 +1,292 @@
$(function() {
function ShutdownPrinterViewModel(parameters) {
var self = this;
self.loginState = parameters[0];
self.settings = parameters[1];
self.printer = parameters[2];
self.shutdownprinterEnabled = ko.observable();
self.testButtonChangeStatus = function (stat) {
$("#tester_shutdownprinter_gcode").prop("disabled", stat);
$("#tester_shutdownprinter_api").prop("disabled", stat);
$("#tester_shutdownprinter_api_custom").prop("disabled", stat);
}
self.eventChangeCheckToRadio = function (id, listOff) {
$(id).on("change", function () {
if ($(this).prop("checked") == true)
{
listOff.forEach(function(element) {
if (id != element.id)
{
if ($(element.id).prop("checked") == true)
{
$(element.id).unbind("change");
$(element.id).trigger("click");
self.eventChangeCheckToRadio(element.id, listOff);
}
}
});
}
})
}
$("#tester_shutdownprinter_gcode").on("click", function () {
self.settings.saveData();
$(this).children("i").show();
setTimeout(function (current) {
$.ajax({
url: API_BASEURL + "plugin/shutdownprinter",
type: "POST",
dataType: "json",
data: JSON.stringify({
command: "shutdown",
mode: 1,
eventView : true
}),
contentType: "application/json; charset=UTF-8"
}).done(function() {
current.children("i").hide();
});
}, 1000, $(this));
});
$("#tester_shutdownprinter_api").on("click", function () {
self.settings.saveData();
$(this).children("i").show();
setTimeout(function (current) {
$.ajax({
url: API_BASEURL + "plugin/shutdownprinter",
type: "POST",
dataType: "json",
data: JSON.stringify({
command: "shutdown",
mode: 2,
eventView : true
}),
contentType: "application/json; charset=UTF-8"
}).done(function() {
current.children("i").hide();
});
}, 1000, $(this));
});
$("#tester_shutdownprinter_api_custom").on("click", function () {
self.settings.saveData();
$(this).children("i").show();
setTimeout(function (current) {
$.ajax({
url: API_BASEURL + "plugin/shutdownprinter",
type: "POST",
dataType: "json",
data: JSON.stringify({
command: "shutdown",
mode: 3,
eventView : true
}),
contentType: "application/json; charset=UTF-8"
}).done(function() {
current.children("i").hide();
});
}, 1000, $(this));
});
self.listOffMode = [
{"id" : "#shutdownprinter_mode_shutdown_gcode"},
{"id" : "#shutdownprinter_mode_shutdown_api"},
{"id" : "#shutdownprinter_mode_shutdown_api_custom"},
]
self.listOffHTTPMethode = [
{"id" : "#shutdownprinter_api_custom_GET"},
{"id" : "#shutdownprinter_api_custom_POST"},
{"id" : "#shutdownprinter_api_custom_PUT"}
]
self.eventChangeCheckToRadio("#shutdownprinter_mode_shutdown_gcode", self.listOffMode);
self.eventChangeCheckToRadio("#shutdownprinter_mode_shutdown_api", self.listOffMode);
self.eventChangeCheckToRadio("#shutdownprinter_mode_shutdown_api_custom", self.listOffMode);
self.eventChangeCheckToRadio("#shutdownprinter_api_custom_GET", self.listOffHTTPMethode);
self.eventChangeCheckToRadio("#shutdownprinter_api_custom_POST", self.listOffHTTPMethode);
self.eventChangeCheckToRadio("#shutdownprinter_api_custom_PUT", self.listOffHTTPMethode);
// Hack to remove automatically added Cancel button
// See https://github.com/sciactive/pnotify/issues/141
//PNotify.prototype.options.confirm.buttons = [];
//another way use, add custom style class for hide cancel button
self.timeoutPopupText = gettext('Shutting down printer in ');
self.timeoutPopupOptions = {
title: gettext('Shutdown Printer'),
type: 'notice',
icon: true,
hide: false,
confirm: {
confirm: true,
buttons: [{
text: 'Abort Shutdown Printer',
addClass: 'btn-block btn-danger',
promptTrigger: true,
click: function(notice, value){
notice.remove();
notice.get().trigger("pnotify.cancel", [notice, value]);
}
}, {
addClass: 'shutdownPrinterHideCancelBtnConfirm',
promptTrigger: true,
click: function(notice, value){
notice.remove();
}
}]
},
buttons: {
closer: false,
sticker: false,
},
history: {
history: false
}
};
//for touch ui
self.touchUIMoveElement = function (self, counter) {
var hash = window.location.hash;
if (hash != "" && hash != "#printer" && hash != "#touch")
{
return;
}
if (counter < 10) {
if (document.getElementById("touch") != null && document.getElementById("printer") != null && document.getElementById("printer") != null && document.getElementById("touch").querySelector("#printer").querySelector("#files_wrapper")) {
var newParent = document.getElementById("files_wrapper").parentNode;
newParent.insertBefore(document.getElementById('sidebar_plugin_shutdownprinter_wrapper'), document.getElementById("files_wrapper"));
} else {
setTimeout(self.touchUIMoveElement, 1000, self, ++counter);
}
}
}
//add octoprint event for check finish
self.onStartupComplete = function () {
//self.touchUIMoveElement(self, 0);
if (self.printer.isPrinting())
{
self.testButtonChangeStatus(true);
} else {
self.testButtonChangeStatus(false);
}
};
self.onUserLoggedIn = function() {
$.ajax({
url: API_BASEURL + "plugin/shutdownprinter",
type: "POST",
dataType: "json",
data: JSON.stringify({
command: "update",
eventView : false
}),
contentType: "application/json; charset=UTF-8"
})
$.ajax({
url: API_BASEURL + "plugin/shutdownprinter",
type: "POST",
data: JSON.stringify({
command: "status"
}),
context:self,
contentType: "application/json; charset=UTF-8"
}).done(function(data, textStatus, jqXHR ){
this.shutdownprinterEnabled(data == "True" ? true : false);
})
}
self.onUserLoggedOut = function() {
}
self.onEventPrinterStateChanged = function(payload) {
if (payload.state_id == "PRINTING" || payload.state_id == "PAUSED"){
self.testButtonChangeStatus(true);
} else {
self.testButtonChangeStatus(false);
}
}
self.onShutdownPrinterEvent = function() {
if (self.shutdownprinterEnabled()) {
$.ajax({
url: API_BASEURL + "plugin/shutdownprinter",
type: "POST",
dataType: "json",
data: JSON.stringify({
command: "enable",
eventView : false
}),
contentType: "application/json; charset=UTF-8"
})
} else {
$.ajax({
url: API_BASEURL + "plugin/shutdownprinter",
type: "POST",
dataType: "json",
data: JSON.stringify({
command: "disable",
eventView : false
}),
contentType: "application/json; charset=UTF-8"
})
}
}
self.shutdownprinterEnabled.subscribe(self.onShutdownPrinterEvent, self);
self.onDataUpdaterPluginMessage = function(plugin, data) {
if (plugin != "shutdownprinter" && plugin != "octoprint_shutdownprinter") {
return;
}
self.shutdownprinterEnabled(data.shutdownprinterEnabled);
if (data.type == "timeout") {
if ((data.timeout_value != null) && (data.timeout_value > 0)) {
self.timeoutPopupOptions.text = self.timeoutPopupText + data.timeout_value;
if (typeof self.timeoutPopup != "undefined") {
self.timeoutPopup.update(self.timeoutPopupOptions);
} else {
self.timeoutPopup = new PNotify(self.timeoutPopupOptions);
self.timeoutPopup.get().on('pnotify.cancel', function() {self.abortShutdown(true);});
}
} else {
if (typeof self.timeoutPopup != "undefined") {
self.timeoutPopup.remove();
self.timeoutPopup = undefined;
}
}
}
}
self.abortShutdown = function(abortShutdownValue) {
self.timeoutPopup.remove();
self.timeoutPopup = undefined;
$.ajax({
url: API_BASEURL + "plugin/shutdownprinter",
type: "POST",
dataType: "json",
data: JSON.stringify({
command: "abort",
eventView : true
}),
contentType: "application/json; charset=UTF-8"
})
}
}
OCTOPRINT_VIEWMODELS.push([
ShutdownPrinterViewModel,
["loginStateViewModel", "settingsViewModel", "printerStateViewModel"],
$(".sidebar_plugin_shutdownprinter").get(0)
]);
});

View File

@ -0,0 +1,181 @@
<form class="form-horizontal">
<h4>General</h4>
<hr>
<h5>Mode GCODE</h5>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" id="shutdownprinter_mode_shutdown_gcode" data-bind="checked: settings.plugins.shutdownprinter._mode_shutdown_gcode">activate this mode
</label>
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('GCODE') }}</label>
<div class="controls">
<input type="text" class="input-block-level" data-bind="value: settings.plugins.shutdownprinter.gcode">
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('Parameter (IP or other)') }}</label>
<div class="controls">
<input type="text" class="input-block-level" data-bind="value: settings.plugins.shutdownprinter.url">
</div>
</div>
<div class="control-group">
<div class="controls">
<button id="tester_shutdownprinter_gcode" type="button" class="btn btn-primary pull-right"><i class="fa fa-spinner fa-spin" data-bind="visible: sending" style="display: none;"></i>Test</button>
</div>
</div>
<hr>
<h5>Mode API</h5>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" id="shutdownprinter_mode_shutdown_api" data-bind="checked: settings.plugins.shutdownprinter._mode_shutdown_api">activate this mode
</label>
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('api key (key octoprint)') }}</label>
<div class="controls">
<div class="input-append">
<input type="text" class="input" data-bind="value: settings.plugins.shutdownprinter.api_key_plugin">
</div>
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('Plugin ID') }}</label>
<div class="controls">
<div class="input-append">
<input type="text" class="input" data-bind="value: settings.plugins.shutdownprinter.api_plugin_name">
</div>
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('Port') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" min='0' class="input-mini text-right" data-bind="value: settings.plugins.shutdownprinter.api_plugin_port">
</div>
</div>
</div>
<div class="control-group">
<label class="control-label">JSON</label>
<div class="controls">
<textarea rows="4" class="block" data-bind="value: settings.plugins.shutdownprinter.api_json_command"></textarea>
</div>
</div>
<div class="control-group">
<div class="controls">
<button id="tester_shutdownprinter_api" type="button" class="btn btn-primary pull-right"><i class="fa fa-spinner fa-spin" data-bind="visible: sending" style="display: none;"></i>Test</button>
</div>
</div>
<hr>
<h5>Mode API Custom</h5>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" id="shutdownprinter_mode_shutdown_api_custom" data-bind="checked: settings.plugins.shutdownprinter._mode_shutdown_api_custom">activate this mode
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" id="shutdownprinter_api_custom_GET" data-bind="checked: settings.plugins.shutdownprinter.api_custom_GET">GET
</label>
<label class="checkbox">
<input type="checkbox" id="shutdownprinter_api_custom_POST" data-bind="checked: settings.plugins.shutdownprinter.api_custom_POST">POST
</label>
<label class="checkbox">
<input type="checkbox" id="shutdownprinter_api_custom_PUT" data-bind="checked: settings.plugins.shutdownprinter.api_custom_PUT">PUT
</label>
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('URL') }}</label>
<div class="controls">
<input type="text" class="input-block-level" data-bind="value: settings.plugins.shutdownprinter.api_custom_url">
</div>
</div>
<div class="control-group">
<label class="control-label">header (json format)</label>
<div class="controls">
<textarea rows="4" class="block" data-bind="value: settings.plugins.shutdownprinter.api_custom_json_header"></textarea>
</div>
</div>
<div class="control-group">
<label class="control-label">body</label>
<div class="controls">
<textarea rows="4" class="block" data-bind="value: settings.plugins.shutdownprinter.api_custom_body"></textarea>
</div>
</div>
<div class="control-group">
<div class="controls">
<button id="tester_shutdownprinter_api_custom" type="button" class="btn btn-primary pull-right"><i class="fa fa-spinner fa-spin" data-bind="visible: sending" style="display: none;"></i>Test</button>
</div>
</div>
<hr>
<h5>Common options</h5>
<div class="control-group">
<label class="control-label">Abort Timeout</label>
<div class="controls">
<div class="input-append">
<input type="number" class="input-mini text-right" data-bind="value: settings.plugins.shutdownprinter.abortTimeout">
<span class="add-on">sec</span>
</div>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: settings.plugins.shutdownprinter.rememberCheckBox"> Remember the value of "Shutdown Printer after print finishes"
</label>
</div>
</div>
<hr>
<h4>Events catch</h4>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: settings.plugins.shutdownprinter.printFailed"> Event print failed
</label>
</div>
</div>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" data-bind="checked: settings.plugins.shutdownprinter.printCancelled"> Event print cancelled
</label>
</div>
</div>
<hr>
<h4>Nozzle temperature target</h4>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="checkbox" shutdownPrinterTemperatureTarget="true" data-bind="checked: settings.plugins.shutdownprinter.temperatureTarget"> Enable temperature target
</label>
</div>
</div>
<h4>Extra command/script</h4>
<div class="control-group">
<div class="controls">
<label class="checkbox">
<input type="text" class="input" data-bind="value: settings.plugins.shutdownprinter.extraCommand">
</label>
</div>
</div>
<div class="control-group">
<label class="control-label">{{ _('Temperature') }}</label>
<div class="controls">
<div class="input-append">
<input type="number" min='0' class="input-mini text-right" data-bind="value: settings.plugins.shutdownprinter.temperatureValue">
<span class="add-on">°C</span>
</div>
</div>
</div>
</form>

View File

@ -0,0 +1,6 @@
<div class="sidebar_plugin_shutdownprinter">
<label class="checkbox">
<input type="checkbox" data-bind="enable: loginState.isUser(), checked: shutdownprinterEnabled">
{{ _('Shutdown Printer after print finishes') }}
</label>
</div>

9
requirements.txt Normal file
View File

@ -0,0 +1,9 @@
###
# This file is only here to make sure that something like
#
# pip install -e .
#
# works as expected. Requirements can be found in setup.py.
###
.

94
setup.py Normal file
View File

@ -0,0 +1,94 @@
# coding=utf-8
########################################################################################################################
### Do not forget to adjust the following variables to your own plugin.
# The plugin's identifier, has to be unique
plugin_identifier = "mystromswitch"
# The plugin's python package, should be "octoprint_<plugin identifier>", has to be unique
plugin_package = "octoprint_mystromswitch"
# The plugin's human readable name. Can be overwritten within OctoPrint's internal data via __plugin_name__ in the
# plugin module
plugin_name = "OctoPrint-MyStromSwitch"
# The plugin's version. Can be overwritten within OctoPrint's internal data via __plugin_version__ in the plugin module
plugin_version = "1.0.7"
# The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin
# module
plugin_description = "Plugin to Control myStrom Switch"
# The plugin's author. Can be overwritten within OctoPrint's internal data via __plugin_author__ in the plugin module
plugin_author = "David Zingg"
# The plugin's author's mail address.
plugin_author_email = ""
# 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/devildant/OctoPrint-ShutdownPrinter"
# 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 = []
### --------------------------------------------------------------------------------------------------------------------
### More advanced options that you usually shouldn't have to touch follow after this point
### --------------------------------------------------------------------------------------------------------------------
# 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 = []
# Any additional python packages you need to install with your plugin that are not contains in <plugin_package>.*
plugin_addtional_packages = []
# Any python packages within <plugin_package>.* you do NOT want to install with your plugin
plugin_ignored_packages = []
# Additional parameters for the call to setuptools.setup. If your plugin wants to register additional entry points,
# define dependency links or other things like that, this is the place to go. Will be merged recursively with the
# default setup parameters as provided by octoprint_setuptools.create_plugin_setup_parameters using
# octoprint.util.dict_merge.
#
# Example:
# plugin_requires = ["someDependency==dev"]
# additional_setup_parameters = {"dependency_links": ["https://github.com/someUser/someRepo/archive/master.zip#egg=someDependency-dev"]}
additional_setup_parameters = {}
########################################################################################################################
from setuptools import setup
try:
import octoprint_setuptools
except:
print("Could not import OctoPrint's setuptools, are you sure you are running that under "
"the same python installation that OctoPrint is installed under?")
import sys
sys.exit(-1)
setup_parameters = octoprint_setuptools.create_plugin_setup_parameters(
identifier=plugin_identifier,
package=plugin_package,
name=plugin_name,
version=plugin_version,
description=plugin_description,
author=plugin_author,
mail=plugin_author_email,
url=plugin_url,
license=plugin_license,
requires=plugin_requires,
additional_packages=plugin_addtional_packages,
ignored_packages=plugin_ignored_packages,
additional_data=plugin_additional_data
)
if len(additional_setup_parameters):
from octoprint.util import dict_merge
setup_parameters = dict_merge(setup_parameters, additional_setup_parameters)
setup(**setup_parameters)