Skip to content

Commit d6dfecd

Browse files
authored
4.1.0 (#52)
Remove API Fix Webcam for OctoPrint 1.9.0 Consolidate cpu_info and cpu messages sent to SP servers
1 parent 9d748dd commit d6dfecd

File tree

21 files changed

+2672
-2404
lines changed

21 files changed

+2672
-2404
lines changed

octoprint_simplyprint/__init__.py

Lines changed: 149 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,31 @@
1717
# You should have received a copy of the GNU Affero General Public License
1818
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1919
#
20-
20+
import errno
2121
import json
2222
import requests
23-
import threading
23+
import sentry_sdk
2424

2525
# noinspection PyPackageRequirements
2626
import flask
27+
import serial
28+
import tornado
2729

2830
from octoprint.events import Events
2931
import octoprint.plugin
3032
import octoprint.settings
33+
from octoprint.util.commandline import CommandlineError
3134

32-
from octoprint_simplyprint.comm import SimplyPrintComm
33-
from octoprint_simplyprint.local import cron
35+
from octoprint_simplyprint.websocket import SimplyPrintWebsocket
3436

3537
SIMPLYPRINT_EVENTS = [
38+
Events.PRINTER_STATE_CHANGED,
39+
Events.TOOL_CHANGE,
3640
Events.CONNECTING,
3741
Events.CONNECTED,
3842
Events.DISCONNECTING,
3943
Events.DISCONNECTED,
44+
Events.CLIENT_AUTHED,
4045

4146
Events.STARTUP,
4247
Events.SHUTDOWN,
@@ -80,6 +85,29 @@
8085
Events.FILE_REMOVED,
8186
]
8287

88+
IGNORED_EXCEPTIONS = [
89+
# serial exceptions in octoprint.util.comm
90+
(
91+
serial.SerialException,
92+
lambda exc, logger, plugin, cb: logger == "octoprint.util.comm",
93+
),
94+
# KeyboardInterrupts
95+
KeyboardInterrupt,
96+
# IOErrors of any kind due to a full file system
97+
(
98+
IOError,
99+
lambda exc, logger, plugin, cb: exc.errorgetattr(exc, "errno") # noqa: B009
100+
and exc.errno in (getattr(errno, "ENOSPC"),), # noqa: B009
101+
),
102+
# RequestExceptions of any kind
103+
requests.exceptions.RequestException,
104+
# Tornado WebSocketErrors of any kind
105+
tornado.websocket.WebSocketError,
106+
# Tornado HTTPClientError
107+
tornado.httpclient.HTTPClientError,
108+
# error from windows for linux specific commands related to wifi
109+
CommandlineError
110+
]
83111

84112
class SimplyPrint(
85113
octoprint.plugin.SettingsPlugin,
@@ -94,47 +122,97 @@ class SimplyPrint(
94122
_files_analyzed = []
95123

96124
simply_print = None
97-
98-
host = "127.0.0.1"
99125
port = "5000"
100126

101127
def initialize(self):
102128
# Called once the plugin has been loaded by OctoPrint, all injections complete
103-
self.simply_print = SimplyPrintComm(self)
129+
sp_cls = SimplyPrintWebsocket
130+
self.simply_print = sp_cls(self)
104131

105132
def on_startup(self, host, port):
133+
# Initialize sentry.io for error tracking
134+
self._initialize_sentry()
106135
# Run startup thread and run the main loop in the background
107-
self.simply_print.start_startup()
108-
self.simply_print.start_main_loop()
136+
self.simply_print.on_startup()
109137

110-
self.host = host
111138
# Remember that this port is internal to OctoPrint, a proxy may exist.
112139
self.port = port
113-
114-
ip = host
115-
116-
if port:
117-
ip += str(port)
118-
119-
self._logger.info("Host is; " + str(host) + " and port is; " + str(port))
120-
self.send_port_ip(None, ip)
140+
if port != 5000 and port != 80 and port != 443:
141+
self.send_port_ip(port)
121142

122143
# #~~ StartupPlugin mixin
123144
def on_after_startup(self):
124-
125145
self._logger.info("SimplyPrint OctoPrint plugin started")
126146

127-
# If cron jobs don't exist, create them
128-
if not cron.check_cron_jobs():
129-
cron.create_cron_jobs()
130-
131147
# The "Startup" event is never picked up by the plugin, as the plugin is loaded AFTER startup
132148
self.on_event("Startup", {})
133149

150+
def _initialize_sentry(self):
151+
self._logger.debug("Initializing Sentry")
152+
153+
def _before_send(event, hint):
154+
if "exc_info" not in hint:
155+
# we only want exceptions
156+
return None
157+
158+
handled = True
159+
logger = event.get("logger", "")
160+
plugin = event.get("extra", {}).get("plugin", None)
161+
callback = event.get("extra", {}).get("callback", None)
162+
163+
for ignore in IGNORED_EXCEPTIONS:
164+
if isinstance(ignore, tuple):
165+
ignored_exc, matcher = ignore
166+
else:
167+
ignored_exc = ignore
168+
matcher = lambda *args: True
169+
170+
exc = hint["exc_info"][1]
171+
if isinstance(exc, ignored_exc) and matcher(
172+
exc, logger, plugin, callback
173+
):
174+
# exception ignored for logger, plugin and/or callback
175+
return None
176+
177+
elif isinstance(ignore, type):
178+
if isinstance(hint["exc_info"][1], ignore):
179+
# exception ignored
180+
return None
181+
182+
# if event.get("exception") and event["exception"].get("values"):
183+
# handled = not any(
184+
# map(
185+
# lambda x: x.get("mechanism")
186+
# and not x["mechanism"].get("handled", True),
187+
# event["exception"]["values"],
188+
# )
189+
# )
190+
#
191+
# if handled:
192+
# # error is handled, restrict further based on logger
193+
# if logger != "" and not (
194+
# logger.startswith("octoprint.plugins.SimplyPrint") or logger.startswith("octoprint.plugins.simplyprint")
195+
# ):
196+
# # we only want errors logged by our plugin's loggers
197+
# return None
198+
199+
if logger.startswith("octoprint.plugins.SimplyPrint") or logger.startswith("octoprint.plugins.simplyprint"):
200+
return event
201+
else:
202+
return None
203+
204+
sentry_sdk.init(
205+
dsn="https://[email protected]/6611344",
206+
traces_sample_rate=0.01,
207+
before_send=_before_send,
208+
release="SimplyPrint@{}".format(self._plugin_version)
209+
)
210+
if self._settings.get(["printer_id"]) != "":
211+
sentry_sdk.set_user({"id": self._settings.get(["printer_id"])})
212+
134213
def on_shutdown(self):
135214
if self.simply_print is not None:
136-
# SimplyPrintComm will stop on next loop
137-
self.simply_print.run_loop = False
215+
self.simply_print.close()
138216

139217
@staticmethod
140218
def get_settings_defaults():
@@ -163,9 +241,21 @@ def get_settings_defaults():
163241
"gcode_scripts_backed_up": False,
164242
},
165243
"debug_logging": False,
166-
"public_port": "80"
244+
"public_port": "80",
245+
# Websocket Default Settings
246+
"websocket_ready": True,
247+
"endpoint": "production",
248+
"printer_token": "",
249+
"ambient_temp": "85",
167250
}
168251

252+
def on_settings_save(self, data):
253+
octoprint.plugin.SettingsPlugin.on_settings_save(self, data)
254+
new_printer_id = self._settings.get(["printer_id"])
255+
256+
if new_printer_id != "":
257+
sentry_sdk.set_user({"id": self._settings.get(["printer_id"])})
258+
169259
def get_template_vars(self):
170260
return {
171261
"version": self._plugin_version
@@ -186,35 +276,23 @@ def get_api_commands(self):
186276
return {
187277
"setup": [], # Sets up SimplyPrintRPiSoftware
188278
"uninstall": [], # Uninstalls SimplyPrintRPiSoftware
279+
"message": ["payload"], # Inject websocket messages
189280
}
190281

191-
@staticmethod
192-
def _uninstall_sp():
193-
# All we need to do here is remove cron jobs, nothing else
194-
cron.remove_cron_jobs()
195-
196-
@staticmethod
197-
def _install_background():
198-
if not cron.check_cron_jobs():
199-
cron.create_cron_jobs()
200-
201282
def on_api_command(self, command, data):
202-
if command == "setup":
203-
self._uninstall_sp()
204-
elif command == "uninstall":
205-
self._uninstall_sp()
283+
if command == "message" and self.simply_print.test:
284+
msg = json.dumps(data["payload"])
285+
# Generally we do NOT want to access methods marked
286+
# as private, however this is for testing only
287+
self.simply_print._process_message(msg)
288+
return
206289

207290
# Send public port to outside system
208-
def send_port_ip(self, port=None, ip=None):
291+
def send_port_ip(self, port=None):
209292
self._settings.set(["public_port"], port)
210293
self._settings.save()
211294

212295
def on_api_get(self, request):
213-
import flask
214-
import subprocess
215-
# self.log(str(request))
216-
# self.log(str(request.args))
217-
218296
if request.args is not None:
219297
if request.args.get("install", default=None, type=None) is not None:
220298
# Install
@@ -274,9 +352,14 @@ def on_event(self, event, payload):
274352
if event in SIMPLYPRINT_EVENTS:
275353
self.simply_print.on_event(event, payload)
276354

277-
# def gcode_sent(self, comm_instance, phase, cmd, cmd_type, gcode, *args, **kwargs):
278-
# if gcode and gcode == "M106":
279-
# self._logger.info("Just sent M106: {cmd}".format(**locals()))
355+
def gcode_sent(self, comm_instance, phase, cmd, cmd_type, gcode, *args, **kwargs):
356+
# if gcode and gcode == "M106":
357+
# self._logger.info("Just sent M106: {cmd}".format(**locals()))
358+
tags = kwargs.get("tags", [])
359+
if tags is None:
360+
return
361+
if "source:api" in tags or "plugin:octoprint_simplyprint" in tags:
362+
self.simply_print.on_gcode_sent(cmd)
280363

281364
def gcode_received(self, comm_instance, line, *args, **kwargs):
282365
if line.strip() not in ["echo:busy: paused for user", "echo:busy: processing", "Unknown M code: M118 simplyprint unpause", "simplyprint unpause"]:
@@ -290,24 +373,26 @@ def gcode_received(self, comm_instance, line, *args, **kwargs):
290373
self._logger.debug("received line: echo:busy: processing, setting user_input_required False")
291374
self.simply_print.user_input_required = False
292375

376+
self.simply_print.on_gcode_received(line)
377+
293378
return line
294379

295380
def process_at_command(self, comm, phase, command, parameters, tags=None, *args, **kwargs):
296381
if command.lower() not in ["simplyprint", "pause"]:
297382
return
298383

299-
url_parameters = ""
300-
if command.lower() == "pause":
301-
url_parameters += "&pause_message={}".format(parameters)
302-
elif command.lower() == "simplyprint":
303-
if parameters:
304-
parameters_list = parameters.split(" ")
305-
if parameters_list[0] == "layer":
306-
url_parameters += "&layer={}".format(parameters_list[1])
307-
308-
if url_parameters != "":
309-
self.simply_print.ping(url_parameters)
310-
384+
cmd = command.lower()
385+
if cmd == "pause":
386+
self.simply_print.on_pause_at_command(parameters)
387+
elif cmd == "simplyprint":
388+
params = parameters.strip().split(" ")
389+
if params and params[0] == "layer":
390+
try:
391+
layer = int(params[1])
392+
except Exception:
393+
pass
394+
else:
395+
self.simply_print.on_layer_change(layer)
311396
return
312397

313398
def get_update_information(self):
@@ -341,13 +426,9 @@ def get_update_information(self):
341426

342427

343428
__plugin_name__ = "SimplyPrint Cloud"
344-
__plugin_pythoncompat__ = ">=2.7,<4"
345-
__plugin_disabling_discouraged__ = """
346-
Please uninstall SimplyPrint Cloud rather than just disable it, since it sets up some background scripts
347-
that will continue to run if you disable it.
348-
"""
429+
__plugin_pythoncompat__ = ">=3.7,<4"
349430
# Remember to bump the version in setup.py as well
350-
__plugin_version__ = "3.1.2"
431+
__plugin_version__ = "4.1.0rc1"
351432

352433

353434
def __plugin_load__():
@@ -357,5 +438,5 @@ def __plugin_load__():
357438
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information,
358439
"octoprint.comm.protocol.atcommand.sending": __plugin_implementation__.process_at_command,
359440
"octoprint.comm.protocol.gcode.received": __plugin_implementation__.gcode_received,
360-
# "octoprint.comm.protocol.gcode.sent": __plugin_implementation__.gcode_sent
441+
"octoprint.comm.protocol.gcode.sent": __plugin_implementation__.gcode_sent
361442
}

octoprint_simplyprint/comm/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@
1818
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1919
#
2020

21-
from .simplyprint import SimplyPrintComm
21+
2222

octoprint_simplyprint/comm/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@
2323
API_VERSION = "0.0.3"
2424
WEBCAM_SNAPSHOT_URL = "https://livestream.simplyprint.io/"
2525
SIMPLYPRINT_PLUGIN_INSTALL_URL = "https://github.com/SimplyPrint/OctoPrint-SimplyPrint/archive/master.zip"
26+
WS_CHECK_ENDPOINT = f"https://api.simplyprint.io/ws_check.php"
27+
TEST_WS_CHECK_ENDPOINT = f"https://testapi.simplyprint.io/ws_check.php"

octoprint_simplyprint/comm/get_ip.sh

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)