Skip to content

Commit

Permalink
Fix issues with app registration
Browse files Browse the repository at this point in the history
  • Loading branch information
crysxd committed Nov 18, 2023
1 parent c5e765b commit 9f51390
Show file tree
Hide file tree
Showing 13 changed files with 218 additions and 105 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ dist
*.zip
py2venv/*
py3venv/*
venv
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"--debug",
"--port=5500",
"--basedir",
"/Users/christian/Projects/OctoPrdint/src/"
"/Users/christian/Projects/OctoPrint2/src/"
]
},
{
Expand Down
28 changes: 14 additions & 14 deletions octoapp/appsstorage.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

from sentry import Sentry
from octoapp.sentry import Sentry
import threading
import time

Expand All @@ -17,7 +17,7 @@ def __init__(
appBuild:int,
appLanguage:str,
lastSeenAt:float,
expiresAt:float,
expireAt:float,
):
self.FcmToken = fcmToken
self.FcmFallbackToken = fcmFallbackToken
Expand All @@ -29,11 +29,11 @@ def __init__(
self.AppBuild = appBuild
self.AppLanguage = appLanguage
self.LastSeenAt = lastSeenAt
self.ExpireAt = expiresAt
self.ExpireAt = expireAt


def ToDict(self):
dict(
return dict(
fcmToken=self.FcmToken,
fcmTokenFallback=self.FcmFallbackToken,
instanceId=self.InstanceId,
Expand All @@ -49,7 +49,7 @@ def ToDict(self):

@staticmethod
def FromDict(dict:dict):
AppInstance(
return AppInstance(
fcmToken=dict["fcmToken"],
fcmFallbackToken=dict["fcmTokenFallback"],
instanceId=dict["instanceId"],
Expand All @@ -60,7 +60,7 @@ def FromDict(dict:dict):
appBuild=dict["appBuild"],
appLanguage=dict["appLanguage"],
lastSeenAt=dict["lastSeenAt"],
expiresAt=dict["expireAt"],
expireAt=dict["expireAt"],
)


Expand Down Expand Up @@ -142,12 +142,12 @@ def GetIosApps(self, apps):

def GetActivities(self, apps):
return list(filter(lambda app: app.fcmToken.startswith("activity:"), apps))

def GetDefaultExpirationFromNow(self):
return (time.time() + 2592000)

def LogApps(self):
apps = self.GetApps()
Sentry.Debug("APPS", "Now %s apps registered")
for app in apps:
Sentry.Debug("APPS", " => %s" % app.fcmToken[0:100])
self.AppStoragePlatformHelper.LogAllApps()

def RemoveTemporaryApps(self, for_instance_id=None):
apps = self.GetApps()
Expand All @@ -161,11 +161,11 @@ def RemoveTemporaryApps(self, for_instance_id=None):

self.SetApps(apps)

def GetApps(self) -> [AppInstance]:
apps = self.AppStoragePlatformHelper.GetApps()
def GetAllApps(self) -> [AppInstance]:
apps = self.AppStoragePlatformHelper.GetAllApps()
Sentry.Debug("APPS", "Loading %s apps" % len(apps))
return apps

def SetApps(self, apps:[AppInstance]):
def SetAllApps(self, apps:[AppInstance]):
Sentry.Debug("APPS", "Storing %s apps" % len(apps))
self.AppStoragePlatformHelper.SetApps(apps)
self.AppStoragePlatformHelper.SetAllApps(apps)
1 change: 0 additions & 1 deletion octoapp/commandhandler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import json

from .octostreammsgbuilder import OctoStreamMsgBuilder
from .octohttprequest import OctoHttpRequest
from .octohttprequest import PathTypes
from .webcamhelper import WebcamHelper
Expand Down
4 changes: 2 additions & 2 deletions octoapp/sentry.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#import logging
import logging
import time
import traceback

Expand Down Expand Up @@ -92,7 +92,7 @@ def _beforeSendFilter(event, hint):
@staticmethod
def Info(tag, msg):
paddedTag = "{:<15}".format(tag).upper()
Sentry.logger.log(paddedTag + " | " + msg)
Sentry.logger.info(paddedTag + " | " + msg)

@staticmethod
def Debug(tag, msg):
Expand Down
85 changes: 25 additions & 60 deletions octoprint_octoapp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,18 @@

import time
import flask
from flask_babel import gettext
import requests
import octoprint.plugin
import logging
import logging.handlers
from flask_babel import gettext

from octoprint.access.permissions import ADMIN_GROUP, USER_GROUP, READONLY_GROUP
from octoprint.events import Events

from octoapp.webcamhelper import WebcamHelper
from octoapp.octoeverywhereimpl import OctoEverywhere
from octoapp.octohttprequest import OctoHttpRequest
from octoapp.notificationshandler import NotificationsHandler
from octoapp.octopingpong import OctoPingPong
from octoapp.telemetry import Telemetry
from octoapp.sentry import Sentry
from octoapp.mdns import MDns
from octoapp.hostcommon import HostCommon
from octoapp.Proto.ServerHost import ServerHost
from octoapp.commandhandler import CommandHandler
from octoapp.compat import Compat
from octoapp.appsstorage import AppStorageHelper
Expand All @@ -34,7 +28,6 @@
from .printerfirmware import OctoAppPrinterFirmwareSubPlugin
from .mmu2filamentselect import OctoAppMmu2FilamentSelectSubPlugin
from .webcamsnapshots import OctoAppWebcamSnapshotsSubPlugin

from .printerstateobject import PrinterStateObject
from .octoprintcommandhandler import OctoPrintCommandHandler
from .octoprintwebcamhelper import OctoPrintWebcamHelper
Expand Down Expand Up @@ -62,6 +55,7 @@ def __init__(self):
self.CachedConfig = self.DefaultConfig
self.CachedConfig_at = 0
self.PluginState = {}
self.SubPlugins = []
self.LastSentPluginState = {}
# Default the handler to None since that will make the var name exist
# but we can't actually create the class yet until the system is more initialized.
Expand All @@ -80,12 +74,7 @@ def on_startup(self, host, port):
# Setup Sentry to capture issues.
self._init_logger()
Sentry.Init(self._logger, self._plugin_version, False)
Sentry.Info("PLUGIN", "OctoApp starting" % self._plugin_version)

#
# Due to settings bugs in OctoPrint, as much of the generated values saved into settings should be set here as possible.
# For more details, see SaveToSettingsIfUpdated()
#
Sentry.Info("PLUGIN", "OctoApp starting %s" % self._plugin_version)

# Init the static snapshot helper
WebcamHelper.Init(self._logger, OctoPrintWebcamHelper(self._logger, self._settings))
Expand All @@ -94,7 +83,7 @@ def on_startup(self, host, port):
printerStateObject = PrinterStateObject(self._logger, self._printer)

# Setup App storage
octoPrintAppStorage = OctoPrintAppStorageSubPlugin()
octoPrintAppStorage = OctoPrintAppStorageSubPlugin(self)
AppStorageHelper.Init(octoPrintAppStorage)

# Create the notification object now that we have the logger.
Expand All @@ -104,28 +93,27 @@ def on_startup(self, host, port):
# Create our command handler and our platform specific command handler.
CommandHandler.Init(self._logger, self.NotificationHandler, OctoPrintCommandHandler(self._logger, self._printer, printerStateObject, self))

self.sub_plugins = [
self.SubPlugins = [
octoPrintAppStorage,
OctoAppNotificationsSubPlugin(NotificationsHandler),
OctoAppNotificationsSubPlugin(self, self.NotificationHandler),
OctoAppPrinterMessageSubPlugin(self),
OctoAppPrinterFirmwareSubPlugin(self),
OctoAppMmu2FilamentSelectSubPlugin(self, NotificationsHandler),
OctoAppMmu2FilamentSelectSubPlugin(self, self.NotificationHandler),
OctoAppWebcamSnapshotsSubPlugin(self)
]

for sp in self.sub_plugins:
for sp in self.SubPlugins:
sp.config = self.DefaultConfig

# Indicate this has been called and things have been inited.
self.HasOnStartupBeenCalledYet = True

def on_after_startup(self):
self._logger_handler()
Sentry.Info("PLUGIN", "OctoApp started, updating config, version is %s" % self._plugin_version)
self.update_config()
self._settings.set(["version"], self._plugin_version)

for sp in self.sub_plugins:
for sp in self.SubPlugins:
try:
sp.on_after_startup()
except Exception as e:
Expand All @@ -141,11 +129,11 @@ def _init_logger(self):
self._logger_handler.setLevel(logging.DEBUG)
self._logger.addHandler(self._logger_handler)
self._logger.setLevel(logging.DEBUG)
self._logger.propagate = False
self._logger.propagate = True


def on_firmware_info_received(self, comm_instance, firmware_name, firmware_data, *args, **kwargs):
for sp in self.sub_plugins:
for sp in self.SubPlugins:
try:
sp.on_firmware_info_received(comm_instance, firmware_name, firmware_data, args, kwargs)
except Exception as e:
Expand All @@ -154,7 +142,7 @@ def on_firmware_info_received(self, comm_instance, firmware_name, firmware_data,
def on_api_command(self, command, data):
Sentry.Info("PLUGIN", "Recevied command %s" % command)

for sp in self.sub_plugins:
for sp in self.SubPlugins:
try:
res = sp.on_api_command(command=command, data=data)
if res != None:
Expand All @@ -167,7 +155,7 @@ def on_api_command(self, command, data):


def on_emit_websocket_message(self, user, message, type, data):
for sp in self.sub_plugins:
for sp in self.SubPlugins:
try:
sp.on_emit_websocket_message(user=user, message=message, type=type, data=data)
except Exception as e:
Expand All @@ -178,14 +166,14 @@ def on_emit_websocket_message(self, user, message, type, data):


def on_print_progress(self, storage, path, progress):
for sp in self.sub_plugins:
for sp in self.SubPlugins:
try:
sp.on_print_progress(storage=storage, path=path, progress=progress)
except Exception as e:
Sentry.ExceptionNoSend("Failed to handle progress", e)

def on_event(self, event, payload):
for sp in self.sub_plugins:
for sp in self.SubPlugins:
try:
sp.on_event(event=event, payload=payload)
except Exception as e:
Expand All @@ -196,22 +184,22 @@ def on_event(self, event, payload):


def on_gcode_queued(self, comm_instance, phase, cmd, cmd_type, gcode, *args, **kwargs):
for sp in self.sub_plugins:
for sp in self.SubPlugins:
try:
sp.on_gcode_queued(comm_instance=comm_instance, phase=phase, cmd=cmd, cmd_type=cmd_type, gcode=gcode, args=args, kwargs=kwargs)
except Exception as e:
Sentry.ExceptionNoSend("Failed to handle gcode queued", e)

def on_gcode_sent(self, comm_instance, phase, cmd, cmd_type, gcode, *args, **kwargs):
for sp in self.sub_plugins:
for sp in self.SubPlugins:
try:
sp.on_gcode_sent(comm_instance=comm_instance, phase=phase, cmd=cmd, cmd_type=cmd_type, gcode=gcode, args=args, kwargs=kwargs)
except Exception as e:
Sentry.ExceptionNoSend("Failed to handle gcode sent", e)


def on_gcode_received(self, comm_instance, line, *args, **kwargs):
for sp in self.sub_plugins:
for sp in self.SubPlugins:
try:
sp.on_gcode_received(comm_instance=comm_instance, line = line, args=args, kwargs=kwargs)
except Exception as e:
Expand All @@ -221,8 +209,7 @@ def send_plugin_state_message(self, forced=False):
# Only send if we are forced to update or the state actually changed
if forced or self.LastSentPluginState != self.PluginState:
self.LastSentPluginState = self.PluginState.copy()
self._plugin_manager.send_plugin_message(
self._identifier, self.PluginState)
self._plugin_manager.send_plugin_message(self._identifier, self.PluginState)

#
# CONFIG
Expand Down Expand Up @@ -252,7 +239,7 @@ def do_update_config(self):
self.CachedConfig = r.json()
self.CachedConfig_at = time.time()

for sp in self.sub_plugins:
for sp in self.SubPlugins:
sp.config = self.DefaultConfig
except Exception as e:
Sentry.ExceptionNoSend("Failed to fetch config using defaults for 5 minutes", e)
Expand Down Expand Up @@ -319,29 +306,7 @@ def get_assets(self):
)


# Saves the value into to the settings object if the value changed.
def SaveToSettingsIfUpdated(self, name, value):
#
# A quick note about settings and creating / saving settings during startup!
#
# Notes about _settings:
# - The force=True MUST ALWAYS BE USED for the .set() function. This is because we don't offer any default settings in get_settings_defaults, and if we don't use the force flag
# the setting doesn't match an existing path is ignored.
# - We should only set() and save() the settings when things actually change to prevent race conditions with anything else in OctoPrint writing to or saving settings.
# - Ideally anything that needs to be generated and written into the settings should happen IN SYNC during the on_startup or on_after_startup calls.
#
# We had a bug where OctoEverywhere would put OctoPrint into Safe Mode on the next reboot. After hours of debugging
# we realized it was because when we updated and saved settings. The OctoPrint safe mode can get triggered when the var `incompleteStartup` remains set to True in the OctoPrint config.
# This flag is set to true on startup and then set to false after `on_after_startup` is called on all plugins. The problem was our logic in on_after_startup raced the clearing logic of
# that flag and sometimes resulted in it not being unset.
#
curValue = self.GetFromSettings(name, None)
if curValue is None or curValue != value:
self._logger.info("Value "+str(name)+" has changed so we are updating the value in settings and saving.")
self._settings.set([name], value, force=True)
self._settings.save(force=True)

__plugin_name__ = "OctoEverywhere!"
__plugin_name__ = "OctoApp"
__plugin_pythoncompat__ = ">=3.0,<4" # Only PY3

def __plugin_load__():
Expand All @@ -355,9 +320,9 @@ def __plugin_load__():
global __plugin_hooks__
__plugin_hooks__ = {
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information,
"octoprint.comm.protocol.gcode.received": __plugin_implementation__.received_gcode,
"octoprint.comm.protocol.gcode.sent": __plugin_implementation__.sent_gcode,
"octoprint.comm.protocol.gcode.queuing": __plugin_implementation__.queuing_gcode,
"octoprint.comm.protocol.gcode.received": __plugin_implementation__.on_gcode_received,
"octoprint.comm.protocol.gcode.sent": __plugin_implementation__.on_gcode_sent,
"octoprint.comm.protocol.gcode.queuing": __plugin_implementation__.on_gcode_queued,
"octoprint.comm.protocol.firmware.info": __plugin_implementation__.on_firmware_info_received,
"octoprint.access.permissions": __plugin_implementation__.get_additional_permissions,
"octoprint.server.sockjs.emit": __plugin_implementation__.on_emit_websocket_message,
Expand Down
2 changes: 1 addition & 1 deletion octoprint_octoapp/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class OctoAppNotificationsSubPlugin(OctoAppSubPlugin):

def __init__(self, parent, notification_handler: NotificationsHandler):
super().__init__(parent)
self.notifications = notification_handler
self.NotificationHandler = notification_handler

def on_print_progress(self, storage, path, progress):
if self.NotificationHandler is not None:
Expand Down
Loading

0 comments on commit 9f51390

Please sign in to comment.