Repository: bitsy-ai/octoprint-nanny-plugin (language: python)

Issue:
Bump websockets lib to 9.1



Discussion / hints:

Fix patch:
diff --git a/octoprint_nanny/__init__.py b/octoprint_nanny/__init__.py
index 2ff881eb..23cc67a2 100644
--- a/octoprint_nanny/__init__.py
+++ b/octoprint_nanny/__init__.py
@@ -10,7 +10,7 @@
 
 __plugin_pythoncompat__ = ">=3,<4"  # only python 3
 
-__plugin_version__ = "0.6.4"
+__plugin_version__ = "0.6.5"
 
 
 def __plugin_load__():
diff --git a/octoprint_nanny/clients/mqtt.py b/octoprint_nanny/clients/mqtt.py
index 4fa3f62b..aca4da16 100644
--- a/octoprint_nanny/clients/mqtt.py
+++ b/octoprint_nanny/clients/mqtt.py
@@ -281,7 +281,9 @@ def publish(self, payload, topic=None, retain=False, qos=1):
         return self.client.publish(topic, payload, qos=qos, retain=retain)
 
     def publish_octoprint_event(self, event, retain=False, qos=1):
-        logger.info(f"Publishing event on {self.octoprint_event_topic}: {event}")
+        logger.info(
+            f"Publishing event_type={event.get('event_type')} on {self.octoprint_event_topic}: {event}"
+        )
         payload = json.dumps(event, cls=NumpyEncoder)
         return self.publish(
             payload, topic=self.octoprint_event_topic, retain=retain, qos=qos
diff --git a/octoprint_nanny/manager.py b/octoprint_nanny/manager.py
index 7d677dd6..60e53f4f 100644
--- a/octoprint_nanny/manager.py
+++ b/octoprint_nanny/manager.py
@@ -143,7 +143,9 @@ async def shutdown(self):
         await self.monitoring_manager.stop()
 
         await self.plugin.settings.rest_client.update_octoprint_device(
-            self.plugin.settings.octoprint_device_id, monitoring_active=False
+            self.plugin.settings.octoprint_device_id,
+            monitoring_active=False,
+            printer_state="Offline",
         )
 
         self.mqtt_manager.stop()
diff --git a/octoprint_nanny/plugins.py b/octoprint_nanny/plugins.py
index 6e1aaddc..f71f1fef 100644
--- a/octoprint_nanny/plugins.py
+++ b/octoprint_nanny/plugins.py
@@ -1,27 +1,42 @@
 import asyncio
 import logging
 import base64
-import concurrent
-import glob
 import hashlib
 import io
 import json
 import os
 import platform
-import platform
-import queue
-import re
-import threading
 import uuid
-from datetime import datetime
-from pathlib import Path
 import socket
-from datetime import datetime
-import time
 import requests
+import beeline
+import aiohttp.client_exceptions
+import flask
+import octoprint.plugin
+import octoprint.util
+import pytz
 
+from pathlib import Path
+from datetime import datetime
+from octoprint.events import Events
+
+import print_nanny_client
 from octoprint.logging.handlers import CleaningTimedRotatingFileHandler
 
+import octoprint_nanny.exceptions
+from octoprint_nanny.clients.rest import RestAPIClient, API_CLIENT_EXCEPTIONS
+from octoprint_nanny.manager import WorkerManager
+from octoprint_nanny.clients.honeycomb import HoneycombTracer
+from octoprint_nanny.exceptions import PluginSettingsRequired
+from octoprint_nanny.types import MonitoringModes
+from print_nanny_client import (
+    PrintNannyPluginEventEventTypeEnum as PrintNannyPluginEventType,
+    RemoteCommandEventEventTypeEnum as RemoteCommandEventType,
+    TelemetryEvent,
+    OctoprintEnvironment,
+    OctoprintPrinterData,
+)
+
 logger = logging.getLogger("octoprint.plugins.octoprint_nanny")
 
 
@@ -44,26 +59,6 @@ def configure_logger(logger, logfile_path):
     logger.info(f"Logger file handler added {file_logging_handler}")
 
 
-import beeline
-import aiohttp.client_exceptions
-import flask
-import octoprint.plugin
-import octoprint.util
-import uuid
-import numpy as np
-
-from octoprint.events import Events, eventManager
-
-import print_nanny_client
-
-import octoprint_nanny.exceptions
-from octoprint_nanny.clients.rest import RestAPIClient, API_CLIENT_EXCEPTIONS
-from octoprint_nanny.manager import WorkerManager
-from octoprint_nanny.clients.honeycomb import HoneycombTracer
-from octoprint_nanny.types import MonitoringModes, PluginEvents, RemoteCommands
-from octoprint_nanny.exceptions import PluginSettingsRequired
-
-
 DEFAULT_API_URL = os.environ.get(
     "OCTOPRINT_NANNY_API_URL", "https://print-nanny.com/api/"
 )
@@ -167,11 +162,38 @@ async def _test_mqtt_async(self):
                 payload=dict(error="Missing device registration"),
             )
         try:
-            payload = {
+            event = {
                 "event_type": "plugin_octoprint_nanny_connect_test_mqtt_ping",
-                "metadata": self.settings.metadata.to_dict(),
-                "octoprint_job": self.settings.get_current_octoprint_job(),
             }
+            environment = self._environment
+            environment = OctoprintEnvironment(
+                os=environment.get("os", {}),
+                python=environment.get("python", {}),
+                hardware=environment.get("hardware", {}),
+                pi_support=environment.get("plugins", {}).get("pi_support", {}),
+            )
+            printer_data = self._printer.get_current_data()
+            currentZ = printer_data.pop("currentZ")
+            logger.info(f"printer_data={printer_data}")
+            printer_data = OctoprintPrinterData(current_z=currentZ, **printer_data)
+            print_session = (
+                self.settings.print_session.id
+                if self.settings.print_session
+                else self.settings.print_session
+            )
+            payload = TelemetryEvent(
+                print_session=print_session,
+                octoprint_environment=environment,
+                octoprint_printer_data=printer_data,
+                temperature=self._printer.get_current_temperatures(),
+                print_nanny_plugin_version=self._plugin_version,
+                print_nanny_client_version=print_nanny_client.__version__,
+                octoprint_version=octoprint.util.version.get_octoprint_version_string(),
+                octoprint_device=self.settings.octoprint_device_id,
+                ts=datetime.now(pytz.timezone("UTC")).timestamp(),
+                **event,
+            )
+            payload = payload.to_dict()
             mqtt_client.publish_octoprint_event(payload)
             self._event_bus.fire(
                 Events.PLUGIN_OCTOPRINT_NANNY_CONNECT_TEST_MQTT_PING_SUCCESS,
@@ -684,8 +706,12 @@ def test_auth_token(self):
             return flask.json.jsonify(response.to_dict())
 
     def register_custom_events(self):
-        plugin_events = [x.value for x in PluginEvents]
-        remote_commands = [x.value for x in RemoteCommands]
+        # remove plugin event prefix when registering events (octoprint adds prefix)
+        plugin_events = [
+            x.replace(self.octoprint_event_prefix, "")
+            for x in PrintNannyPluginEventType.allowable_values
+        ]
+        remote_commands = RemoteCommandEventType.allowable_values
         local_only = [
             "monitoring_frame_b64",  # not sent via event telemetry
         ]
@@ -741,7 +767,7 @@ def on_event(self, event_type, event_data):
             logger.debug(f"Ignoring event_type={event_type} event_data={event_data}")
 
         else:
-            logger.info(f"Ignoring event_type={event_type} event_data{event_data}")
+            logger.info(f"Ignoring event_type={event_type} event_data={event_data}")
 
     @beeline.traced(name="OctoPrintNannyPlugin.on_settings_initialized")
     def on_settings_initialized(self):
diff --git a/octoprint_nanny/settings.py b/octoprint_nanny/settings.py
index 78893b4b..b2623287 100644
--- a/octoprint_nanny/settings.py
+++ b/octoprint_nanny/settings.py
@@ -1,4 +1,3 @@
-import asyncio
 from datetime import datetime
 import logging
 import pytz
@@ -11,18 +10,18 @@
 import beeline
 import uuid
 
-from print_nanny_client.models.octo_print_event_event_type_enum import (
-    OctoPrintEventEventTypeEnum,
+from print_nanny_client import (
+    PrintNannyPluginEventEventTypeEnum as PrintNannyPluginEventType,
+    OctoPrintEventEventTypeEnum as OctoPrintEventType,
+    PrintJobStatusEnum,
+    RemoteCommandEventEventTypeEnum as RemoteCommandEventType,
 )
 
 from octoprint_nanny.clients.mqtt import MQTTClient
-from octoprint_nanny.clients.rest import RestAPIClient, API_CLIENT_EXCEPTIONS
+from octoprint_nanny.clients.rest import RestAPIClient
 from octoprint_nanny.exceptions import PluginSettingsRequired
 from octoprint_nanny.types import (
     MonitoringModes,
-    PluginEvents,
-    TrackedOctoPrintEvents,
-    RemoteCommands,
     Metadata,
 )
 import print_nanny_client
@@ -144,84 +143,12 @@ def get_current_octoprint_profile(self):
         """
         return self.plugin._printer_profile_manager.get_current_or_default()
 
-    @beeline.traced("PluginSettingsMemoize.get_current_octoprint_temperatures")
     def get_current_octoprint_temperatures(self):
         return self.plugin._printer.get_current_temperatures()
 
-    @beeline.traced("PluginSettingsMemoize.get_current_octoprint_printer_state")
     def get_current_octoprint_printer_state(self):
         """
-        HTTP/1.1 200 OK
-        Content-Type: application/json
-
-        {
-            "temperature": {
-                "tool0": {
-                "actual": 214.8821,
-                "target": 220.0,
-                "offset": 0
-                },
-                "tool1": {
-                "actual": 25.3,
-                "target": null,
-                "offset": 0
-                },
-                "bed": {
-                "actual": 50.221,
-                "target": 70.0,
-                "offset": 5
-                },
-                "history": [
-                {
-                    "time": 1395651928,
-                    "tool0": {
-                    "actual": 214.8821,
-                    "target": 220.0
-                    },
-                    "tool1": {
-                    "actual": 25.3,
-                    "target": null
-                    },
-                    "bed": {
-                    "actual": 50.221,
-                    "target": 70.0
-                    }
-                },
-                {
-                    "time": 1395651926,
-                    "tool0": {
-                    "actual": 212.32,
-                    "target": 220.0
-                    },
-                    "tool1": {
-                    "actual": 25.1,
-                    "target": null
-                    },
-                    "bed": {
-                    "actual": 49.1123,
-                    "target": 70.0
-                    }
-                }
-                ]
-            },
-            "sd": {
-                "ready": true
-            },
-            "state": {
-                "text": "Operational",
-                "flags": {
-                "operational": true,
-                "paused": false,
-                "printing": false,
-                "cancelling": false,
-                "pausing": false,
-                "sdReady": true,
-                "error": false,
-                "ready": true,
-                "closedOrError": false
-                }
-            }
-        }
+        {'state': {'text': 'Offline', 'flags': {'operational': False, 'printing': False, 'cancelling': False, 'pausing': False, 'resuming': False, 'finishing': False, 'closedOrError': True, 'error': False, 'paused': False, 'ready': False, 'sdReady': False}, 'error': ''}, 'job': {'file': {'name': None, 'path': None, 'size': None, 'origin': None, 'date': None}, 'estimatedPrintTime': None, 'lastPrintTime': None, 'filament': {'length': None, 'volume': None}, 'user': None}, 'currentZ': None, 'progress': {'completion': None, 'filepos': None, 'printTime': None, 'printTimeLeft': None, 'printTimeOrigin': None}, 'offsets': {}, 'resends': {'count': 0, 'ratio': 0}}
         """
         return self.plugin._printer.get_current_data()
 
@@ -402,10 +329,12 @@ def event_is_tracked(self, event_type):
         prefix = self.plugin.octoprint_event_prefix
         prefix_stripped = event_type.replace(prefix, "")
         return (
-            TrackedOctoPrintEvents.is_member(event_type)
-            or TrackedOctoPrintEvents.is_member(prefix_stripped)
-            or RemoteCommands.is_member(event_type)
-            or RemoteCommands.is_member(prefix_stripped)
-            or PluginEvents.is_member(event_type)
-            or PluginEvents.is_member(prefix_stripped)
+            event_type in PrintNannyPluginEventType.allowable_values
+            or prefix_stripped in PrintNannyPluginEventType.allowable_values
+            or event_type in OctoPrintEventType.allowable_values
+            or prefix_stripped in OctoPrintEventType.allowable_values
+            or event_type in PrintJobStatusEnum.allowable_values
+            or prefix_stripped in PrintJobStatusEnum.allowable_values
+            or event_type in RemoteCommandEventType.allowable_values
+            or prefix_stripped in RemoteCommandEventType.allowable_values
         )
diff --git a/octoprint_nanny/types.py b/octoprint_nanny/types.py
index 077c8e38..94ea869c 100644
--- a/octoprint_nanny/types.py
+++ b/octoprint_nanny/types.py
@@ -4,17 +4,6 @@
 import numpy as np
 from typing import Optional, Dict
 
-from print_nanny_client import (
-    OctoPrintPluginEventEventTypeEnum as OctoPrintPluginEventTypes,
-)
-from print_nanny_client import (
-    OctoPrintEventEventTypeEnum as OctoPrintEventTypes,
-)
-from print_nanny_client.models.command_enum import CommandEnum
-
-
-PLUGIN_PREFIX = "octoprint_nanny_"
-
 
 @dataclass
 class Image:
@@ -67,78 +56,3 @@ def to_dict(self):
 class MonitoringModes(Enum):
     ACTIVE_LEARNING = "active_learning"
     LITE = "lite"
-
-
-class ClassMemberMixin(object):
-    """
-    Utility for checking Enum membership on strings
-    For sanity, membership is checked using the value and OctoPrint's generated event value
-    e.g. "octoprint_nanny_value"
-    """
-
-    @classmethod
-    def to_octoprint_event(cls, value: str):
-        if isinstance(value, Enum):
-            if PLUGIN_PREFIX not in value.value:
-                value = f"{PLUGIN_PREFIX}{value.value}"
-        elif isinstance(value, str):
-            if PLUGIN_PREFIX not in value:
-                value = f"{PLUGIN_PREFIX}{value}"
-        return value
-
-    @classmethod
-    def from_octoprint_event(cls, value: str):
-        return value.replace(PLUGIN_PREFIX, "")
-
-    @classmethod
-    def _octoprint_event_member(cls, value: str):
-        value = cls.from_octoprint_event(value)
-        return cls(value)
-
-    @classmethod
-    def is_member(cls, value):
-        return value in cls._value2member_map_
-
-    @classmethod
-    def member(cls, value: str):
-        """
-        Returns Member if event string matches value (with or without plugin prefix)
-        """
-        if PLUGIN_PREFIX in value:
-            return cls._octoprint_event_member(value)
-
-        return cls(value)
-
-
-class EnumBase(ClassMemberMixin, Enum):
-    pass
-
-
-PluginEvents = EnumBase(
-    "OctoPrintPluginEvents",
-    {
-        attr: getattr(OctoPrintPluginEventTypes, attr)
-        for attr in dir(OctoPrintPluginEventTypes)
-        if getattr(OctoPrintPluginEventTypes, attr)
-        in OctoPrintPluginEventTypes.allowable_values
-    },
-)
-
-RemoteCommands = EnumBase(
-    "RemoteCommands",
-    {
-        attr: getattr(CommandEnum, attr)
-        for attr in dir(CommandEnum)
-        if getattr(CommandEnum, attr) in CommandEnum.allowable_values
-    },
-)
-
-
-TrackedOctoPrintEvents = EnumBase(
-    "TrackedOctoPrintEvents",
-    {
-        attr: getattr(OctoPrintEventTypes, attr)
-        for attr in dir(OctoPrintEventTypes)
-        if getattr(OctoPrintEventTypes, attr) in OctoPrintEventTypes.allowable_values
-    },
-)
diff --git a/octoprint_nanny/workers/monitoring.py b/octoprint_nanny/workers/monitoring.py
index ed5c1116..1d6f5bef 100644
--- a/octoprint_nanny/workers/monitoring.py
+++ b/octoprint_nanny/workers/monitoring.py
@@ -36,7 +36,6 @@
 from octoprint_nanny.clients.honeycomb import HoneycombTracer
 from octoprint.events import Events
 from octoprint_nanny.types import (
-    PluginEvents,
     MonitoringModes,
     MonitoringFrame,
     Image,
@@ -102,7 +101,7 @@ def __init__(
     async def load_url_buffer(self):
         async with aiohttp.ClientSession() as session:
             async with session.get(self._snapshot_url) as res:
-                assert res.headers["content-type"] == "image/jpeg"
+                # assert res.headers["content-type"] == "image/jpeg"
                 b = await res.read()
                 return b
 
@@ -331,7 +330,6 @@ async def start(self, print_session=None, **kwargs):
             await self.plugin.settings.rest_client.update_octoprint_device(
                 self.plugin.settings.octoprint_device_id,
                 monitoring_active=True,
-                last_session=self.plugin.settings.print_session.id,
             )
         else:
             logger.warning(
diff --git a/octoprint_nanny/workers/mqtt.py b/octoprint_nanny/workers/mqtt.py
index 7ae9fe74..fdcce75e 100644
--- a/octoprint_nanny/workers/mqtt.py
+++ b/octoprint_nanny/workers/mqtt.py
@@ -2,26 +2,31 @@
 import asyncio
 import concurrent
 import inspect
-import io
 import json
 import logging
 import os
 import queue
 import threading
-
+from datetime import datetime
 import logging
+import pytz
 
 import beeline
 
 import print_nanny_client
 
 from octoprint.events import Events
-
+import octoprint
+from print_nanny_client import (
+    TelemetryEvent,
+    OctoprintEnvironment,
+    OctoprintPrinterData,
+)
 from octoprint_nanny.clients.rest import API_CLIENT_EXCEPTIONS
 from octoprint_nanny.exceptions import PluginSettingsRequired
 
 from octoprint_nanny.clients.honeycomb import HoneycombTracer
-from octoprint_nanny.types import PluginEvents, MonitoringModes
+from octoprint_nanny.types import MonitoringModes
 
 logger = logging.getLogger("octoprint.plugins.octoprint_nanny.workers.mqtt")
 
@@ -135,19 +140,40 @@ def run(self, halt):
         loop = asyncio.new_event_loop()
         asyncio.set_event_loop(loop)
         loop.set_default_executor(concurrent.futures.ThreadPoolExecutor(max_workers=4))
-
         return loop.run_until_complete(asyncio.ensure_future(self.loop_forever()))
 
     async def publish_octoprint_event_telemetry(self, event):
-        event_type = event.get("event_type")
-        event.update(
-            {
-                "metadata": self.plugin.settings.metadata.to_dict(),
-                "octoprint_job": self.plugin.settings.get_current_octoprint_job(),
-            }
+        environment = self.plugin._environment
+        environment = OctoprintEnvironment(
+            os=environment.get("os", {}),
+            python=environment.get("python", {}),
+            hardware=environment.get("hardware", {}),
+            pi_support=environment.get("plugins", {}).get("pi_support", {}),
+        )
+        printer_data = self.plugin._printer.get_current_data()
+        currentZ = printer_data.pop("currentZ")
+        logger.info(f"printer_data={printer_data}")
+        printer_data = OctoprintPrinterData(current_z=currentZ, **printer_data)
+        print_session = (
+            self.plugin.settings.print_session.id
+            if self.plugin.settings.print_session
+            else self.plugin.settings.print_session
+        )
+        payload = TelemetryEvent(
+            print_session=print_session,
+            octoprint_environment=environment,
+            octoprint_printer_data=printer_data,
+            temperature=self.plugin._printer.get_current_temperatures(),
+            print_nanny_plugin_version=self.plugin._plugin_version,
+            print_nanny_client_version=print_nanny_client.__version__,
+            octoprint_version=octoprint.util.version.get_octoprint_version_string(),
+            octoprint_device=self.plugin.settings.octoprint_device_id,
+            ts=datetime.now(pytz.timezone("UTC")).timestamp(),
+            **event,
         )
+        payload = payload.to_dict()
 
-        self.plugin.settings.mqtt_client.publish_octoprint_event(event)
+        return self.plugin.settings.mqtt_client.publish_octoprint_event(payload)
 
     async def _loop(self):
         try:
diff --git a/octoprint_nanny/workers/websocket.py b/octoprint_nanny/workers/websocket.py
index 729525f5..6436047e 100644
--- a/octoprint_nanny/workers/websocket.py
+++ b/octoprint_nanny/workers/websocket.py
@@ -20,7 +20,6 @@
 
 from octoprint_nanny.utils.encoder import NumpyEncoder
 from octoprint_nanny.clients.honeycomb import HoneycombTracer
-from octoprint_nanny.types import PluginEvents
 
 # @ todo configure logger from ~/.octoprint/logging.yaml
 logger = logging.getLogger("octoprint.plugins.octoprint_nanny.clients.websocket")
@@ -78,11 +77,22 @@ async def send(self, msg=None):
                 msg = {"event_type": "ping"}
             await websocket.send(msg)
 
+    @backoff.on_exception(
+        backoff.expo,
+        ConnectionClosedError,
+        jitter=backoff.random_jitter,
+        logger=logger,
+        max_time=120,
+    )
     def run(self, halt):
         self._halt = halt
         loop = asyncio.new_event_loop()
+        loop.set_debug(True)
         asyncio.set_event_loop(loop)
-        return loop.run_until_complete(asyncio.ensure_future(self.relay_loop()))
+        task = asyncio.ensure_future(self.relay_loop())
+        result = loop.run_until_complete(task)
+        logger.warning(f"Websocket exited with result {result}")
+        loop.close()
 
     async def _loop(self, websocket):
         try:
@@ -91,13 +101,6 @@ async def _loop(self, websocket):
         except queue.Empty as e:
             return
 
-    # @backoff.on_exception(
-    #     backoff.expo,
-    #     ConnectionClosedError,
-    #     jitter=backoff.random_jitter,
-    #     logger=logger,
-    #     max_time=60,
-    # )
     async def relay_loop(self):
         logging.info(f"Initializing websocket {self._url}")
         async with websockets.connect(
@@ -107,3 +110,4 @@ async def relay_loop(self):
             while not self._halt.is_set():
                 await self._loop(websocket)
             logger.warning("Halt event set, worker will exit soon")
+            return True
diff --git a/requirements.txt b/requirements.txt
index ec0bb046..065bec8f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -28,7 +28,7 @@ cachelib==0.1.1
     # via octoprint
 cchardet==2.1.7
     # via aiohttp
-certifi==2020.12.5
+certifi==2021.5.30
     # via
     #   requests
     #   sentry-sdk
@@ -69,7 +69,7 @@ flatbuffers==1.12
     # via OctoPrint-Nanny (setup.py)
 future==0.18.2
     # via octoprint
-honeycomb-beeline==2.16.2
+honeycomb-beeline==2.17.0
     # via OctoPrint-Nanny (setup.py)
 idna==2.10
     # via
@@ -102,7 +102,7 @@ multidict==5.1.0
     #   yarl
 netaddr==0.8.0
     # via octoprint
-netifaces==0.10.9
+netifaces==0.11.0
     # via octoprint
 numpy==1.20.3
     # via
@@ -110,7 +110,7 @@ numpy==1.20.3
     #   pyarrow
 octoprint-filecheck==2021.2.23
     # via octoprint
-octoprint-firmwarecheck==2021.2.4
+octoprint-firmwarecheck==2021.5.31
     # via octoprint
 octoprint-pisupport==2021.3.26.post2
     # via octoprint
@@ -124,7 +124,7 @@ pillow==8.2.0
     # via OctoPrint-Nanny (setup.py)
 pkginfo==1.7.0
     # via octoprint
-print-nanny-client==0.6.4rc2
+print-nanny-client==0.6.5rc24
     # via OctoPrint-Nanny (setup.py)
 psutil==5.8.0
     # via octoprint
@@ -180,7 +180,7 @@ typing-extensions==3.10.0.0 ; python_version < "3.8"
     #   yarl
 unidecode==0.4.21
     # via octoprint
-urllib3==1.26.4
+urllib3==1.26.5
     # via
     #   print-nanny-client
     #   requests
@@ -191,7 +191,7 @@ webassets==2.0
     # via flask-assets
 websocket-client==0.59.0
     # via octoprint
-websockets==9.0.2
+websockets==9.1
     # via OctoPrint-Nanny (setup.py)
 werkzeug==1.0.1
     # via
diff --git a/setup.cfg b/setup.cfg
index b2a372bc..515eed27 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 0.6.4
+current_version = 0.6.5
 commit = True
 tag = True
 parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)((?P<release>(dev|rc))+(?P<build>\d+))?
diff --git a/setup.py b/setup.py
index bc9f39a2..85c2cbc6 100644
--- a/setup.py
+++ b/setup.py
@@ -22,7 +22,7 @@
 plugin_name = "OctoPrint Nanny"
 
 # The plugin's version. Can be overwritten within OctoPrint's internal data via __plugin_version__ in the plugin module
-plugin_version = "0.6.4"
+plugin_version = "0.6.5"
 
 # The plugin's description. Can be overwritten within OctoPrint's internal data via __plugin_description__ in the plugin
 # module
@@ -156,8 +156,8 @@ class CPUNotSupported(Exception):
     "typing_extensions ; python_version < '3.8'",
     "pytz",
     "aiohttp[speedups]>=3.7.4",
-    "print-nanny-client>=0.6.4rc2",
-    "websockets>=9.0.1",
+    "print-nanny-client>=0.6.5rc24",
+    "websockets>=9.1",
     "backoff>=1.10.0",
     "pyjwt>=2.0.1",
     "paho-mqtt>=1.5.1",


Test patch:
diff --git a/tests/test_constants.py b/tests/test_constants.py
deleted file mode 100644
index e44f6342..00000000
--- a/tests/test_constants.py
+++ /dev/null
@@ -1,43 +0,0 @@
-import pytest
-from octoprint_nanny.types import PluginEvents, RemoteCommands
-
-
-def test_octoprint_event_member_in_plugin_events():
-
-    event = "octoprint_nanny_device_register_start"
-    assert PluginEvents.member(event) == PluginEvents.DEVICE_REGISTER_START
-
-
-def test_unprefixed_event_to_octoprint_event():
-
-    event = "device_register_start"
-    expected = "octoprint_nanny_device_register_start"
-
-    assert PluginEvents.to_octoprint_event(event) == expected
-
-
-def test_octoprint_event_to_octoprint_event():
-
-    event = "octoprint_nanny_device_register_start"
-    expected = "octoprint_nanny_device_register_start"
-
-    assert PluginEvents.to_octoprint_event(event) == expected
-
-
-def test_unprefixed_event_from_octoprint_event():
-
-    expected = "device_register_start"
-    event = "octoprint_nanny_device_register_start"
-
-    assert PluginEvents.from_octoprint_event(event) == expected
-
-
-def test_unprefixed_event_from_unprefixed_event():
-    """
-    it should have no negative side-effects if a non-octoprint prefixed event is passed
-    """
-
-    expected = "device_register_start"
-    event = "device_register_start"
-
-    assert PluginEvents.from_octoprint_event(event) == expected
diff --git a/tests/test_manager.py b/tests/test_manager.py
index 4fc59fd7..50294c7a 100644
--- a/tests/test_manager.py
+++ b/tests/test_manager.py
@@ -1,6 +1,6 @@
 import asyncio
 import pytest
-from asynctest import CoroutineMock, patch
+from asynctest import patch
 
 from unittest.mock import PropertyMock
 
@@ -8,7 +8,6 @@
 from octoprint_nanny.manager import WorkerManager
 from octoprint_nanny.exceptions import PluginSettingsRequired
 from octoprint.events import Events
-from octoprint_nanny.types import PluginEvents
 
 
 def get_default_setting(key):
diff --git a/tests/workers/test_monitoring.py b/tests/workers/test_monitoring.py
index ba9f528c..f3a5ebba 100644
--- a/tests/workers/test_monitoring.py
+++ b/tests/workers/test_monitoring.py
@@ -2,10 +2,9 @@
 import concurrent
 import asyncio
 import threading
-from asynctest import CoroutineMock, patch
-import unittest.mock
+from asynctest import patch
 
-from octoprint_nanny.types import PluginEvents, MonitoringModes
+from octoprint_nanny.types import MonitoringModes
 from octoprint_nanny.workers.monitoring import (
     MonitoringWorker,
     MonitoringManager,