Skip to content

Commit d9490c6

Browse files
committed
♻️ Let checks decide when to become inactive
That will allow us to check past M115 responses.
1 parent d91f588 commit d9490c6

4 files changed

Lines changed: 94 additions & 35 deletions

File tree

octoprint_firmware_check/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ def on_firmware_info_received(self, comm_instance, firmware_name, firmware_data)
9292
to_unicode(firmware_name, errors="replace"),
9393
dict((to_unicode(key, errors="replace"), to_unicode(value, errors="replace"))
9494
for key, value in firmware_data.items()))
95-
self._scan_received = False
9695

9796
##~~ Firmware capability hook handler
9897

@@ -136,6 +135,7 @@ def get_update_information(self):
136135
def _run_checks(self, check_type, *args, **kwargs):
137136
changes = False
138137

138+
still_active = False
139139
for warning_type, check_data in FIRMWARE_CHECKS.items():
140140
checks = check_data.get("checks")
141141
message = check_data.get("message")
@@ -179,6 +179,11 @@ def _run_checks(self, check_type, *args, **kwargs):
179179
check.evaluate_timeout()
180180
self._logger.debug("Check {} active? {}".format(check, check.active))
181181

182+
still_active = any(check.active for check in checks) or still_active
183+
184+
self._scan_received = still_active
185+
self._logger.debug("Scanning received lines enabled? {}".format(self._scan_received))
186+
182187
if changes:
183188
self._ping_clients()
184189

octoprint_firmware_check/checks/__init__.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,83 @@ def reset(self):
5555
self._start_time = None
5656

5757

58+
class LineCheck(Check):
59+
def __init__(self):
60+
Check.__init__(self)
61+
self._matches = None
62+
63+
def received(self, line):
64+
if not line:
65+
return
66+
67+
if self._is_match(line):
68+
self._matches = True
69+
elif self._is_ruled_out(line):
70+
self._matches = False
71+
72+
self._evaluate()
73+
74+
def m115(self, name, data):
75+
# M115 usually means we stop scanning received lines
76+
if self._matches is None:
77+
self._matches = False
78+
self._evaluate()
79+
80+
def _evaluate(self):
81+
if self._matches is None:
82+
return
83+
self._triggered = self._matches
84+
self._active = False
85+
86+
def reset(self):
87+
Check.reset(self)
88+
self._matches = None
89+
90+
def _is_match(self, line):
91+
return False
92+
93+
def _is_ruled_out(self, line):
94+
return False
95+
96+
97+
class CapCheck(Check):
98+
CAP = None
99+
100+
def __init__(self):
101+
Check.__init__(self)
102+
self.cap_seen = False
103+
104+
def cap(self, cap, enabled):
105+
self.cap_seen = True
106+
if cap == self.CAP:
107+
self._triggered = self._eval(enabled)
108+
self._active = False
109+
110+
def received(self, line):
111+
if self.cap_seen and not line.startswith("Cap:"):
112+
# first non cap line after cap report: cap report over, deactivate
113+
self._active = False
114+
115+
def _eval(self, enabled):
116+
# trigger when enabled
117+
return enabled
118+
119+
120+
class NegativeCapCheck(CapCheck):
121+
def _eval(self, enabled):
122+
# trigger when NOT enabled
123+
return not enabled
124+
58125

59126
class AuthorCheck(Check):
60127
authors = ()
61128

62129
AUTHOR = "| Author: ".lower()
63130

131+
def m115(self, name, data):
132+
# M115 usually means we stop scanning received lines
133+
self._active = False
134+
64135
def received(self, line):
65136
if not line:
66137
return

octoprint_firmware_check/checks/firmware_broken.py

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
__copyright__ = "Copyright (C) 2020 The OctoPrint Project - Released under terms of the AGPLv3 License"
66

77
from flask_babel import gettext
8-
from . import Check, Severity
8+
from . import LineCheck, Severity
99

1010
class FirmwareBrokenChecks(object):
1111
@classmethod
@@ -17,36 +17,15 @@ def as_dict(cls):
1717
severity=Severity.INFO)
1818

1919

20-
class CbdCheck(Check):
20+
class CbdCheck(LineCheck):
2121
name = "cbd"
2222
url = "https://faq.octoprint.org/warning-firmware-broken-cbd"
23+
FRAGMENT = "CBD make it".lower()
2324

24-
CRITICAL_FRAGMENT = "CBD make it".lower()
25+
def _is_match(self, line):
26+
return self.FRAGMENT in line.lower()
2527

26-
def __init__(self):
27-
Check.__init__(self)
28-
self._fragment_matches = None
29-
30-
def received(self, line):
31-
if not line:
32-
return
33-
34-
lower_line = line.lower()
35-
if self.CRITICAL_FRAGMENT in lower_line:
36-
self._fragment_matches = True
37-
38-
self._evaluate()
39-
40-
def _evaluate(self):
41-
if self._fragment_matches is None:
42-
return
43-
self._triggered = self._fragment_matches
44-
self._active = False
45-
46-
def reset(self):
47-
Check.reset(self)
48-
self._fragment_matches = None
4928

5029
class ZwlfCheck(CbdCheck):
5130
name = "zwlf"
52-
CRITICAL_FRAGMENT = "ZWLF make it".lower()
31+
FRAGMENT = "ZWLF make it".lower()

octoprint_firmware_check/checks/firmware_unsafe.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from flask_babel import gettext
88
from octoprint.util.version import get_comparable_version
9-
from . import Check, AuthorCheck, Severity
9+
from . import Check, NegativeCapCheck, AuthorCheck, Severity
1010

1111
class FirmwareUnsafeChecks(object):
1212
@classmethod
@@ -52,6 +52,14 @@ def __init__(self):
5252
self._author_matches = None
5353
self._version_matches = None
5454

55+
def m115(self, name, data):
56+
# make sure we stop scanning once we see the response to M115
57+
if self._author_matches is None:
58+
self._author_matches = False
59+
if self._version_matches is None:
60+
self._version_matches = False
61+
self._evaluate()
62+
5563
def received(self, line):
5664
if not line:
5765
return
@@ -169,13 +177,9 @@ def _extract_repetier_version(self, name):
169177
version = get_comparable_version(version, base=True)
170178
return version
171179

172-
class ThermalProtectionCapCheck(Check):
180+
class ThermalProtectionCapCheck(NegativeCapCheck):
173181
"""
174182
Firmware reporting disabled THERMAL_PROTECTION capability
175183
"""
176184
name = "capability"
177-
178-
def cap(self, cap, enabled):
179-
if cap == "THERMAL_PROTECTION":
180-
self._triggered = not enabled
181-
self._active = False
185+
CAP = "THERMAL_PROTECTION"

0 commit comments

Comments
 (0)