Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into honeybee
Browse files Browse the repository at this point in the history
# Conflicts:
#	prusaerrors/shared/codes.py
  • Loading branch information
LukasLendvorsky committed Jan 13, 2025
2 parents 5f33ab8 + 5ef5a9d commit 0c24664
Show file tree
Hide file tree
Showing 13 changed files with 752 additions and 271 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ jobs:
run: |
pip install .
- name: Lint with pylint
id: pylint
run: |
python3 -m pylint --version
python3 -m pylint --persistent=n --jobs 0 --max-line-length=120 prusaerrors
- name: Test
# Run the step even if the pylint step has failed
if: success() || (failure() && steps.pylint.conclusion == 'failure')
run: |
export PATH="${PATH}:$(pwd)"
coverage run -m unittest discover --failfast --verbose tests
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ Example: 12201
* 13 `MK4` - Original Prusa MK4
* 16 `iX` - AFS IX
* 17 `XL` - Original Prusa XL
* 21 `MK3.9` - Original Prusa MK3.9
* 23 `MK3.5` - Original Prusa MK3.5
* 26 `MK4S` - Original Prusa MK4S
* 27 `MK3.9S` - Original Prusa MK3.9S
* 28 `MK3.5S` - Original Prusa MK3.5S
* 29 `M1` - Original Medical One
* 31 `COREONE` - Prusa Core One

## Error categories
1. Mechanical - XYZ motors, tower, axis range
Expand Down
1 change: 1 addition & 0 deletions include/button_operations.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ enum class ButtonOperations : uint8_t {
Unload = 4,
StopPrint = 5,
DisableMMU = 6,
Skip = 7,
};
61 changes: 34 additions & 27 deletions prusaerrors/connect/codes.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# This file is part of the SL1 firmware
# Copyright (C) 2020 Prusa Research a.s. - www.prusa3d.com
# SPDX-License-Identifier: GPL-3.0-or-later

"""
All printer type error/attention codes
Expand All @@ -12,11 +11,13 @@
from typing import Optional

import yaml
from prusaerrors.shared.codes import (Category, Code, Codes, Printer,
unique_codes)

from prusaerrors.shared.codes import unique_codes, Codes, Printer, Code, Category


BUDDY = ['MINI', 'MK4', 'IX', 'XL', 'MK35', 'MK39']
BUDDY = [
'MINI', 'MK4', 'IX', 'XL', 'MK3.5', 'MK4S', 'MK3.9', 'MK3.9S', 'MK3.5S',
'COREONE'
]


class PrinterCode(Code):
Expand All @@ -26,18 +27,23 @@ class PrinterCode(Code):
"""

# pylint: disable = too-many-arguments
# pylint: disable = too-many-positional-arguments
def __init__(
self,
printer: Printer,
category: Category,
error: int,
title: str,
message: str,
approved: bool,
id_: str,
self,
printer: Printer,
category: Category,
error: int,
title: str,
message: str,
approved: bool,
id_: str,
):
super().__init__(printer=printer, category=category, error=error,
title=title, message=message, approved=approved)
super().__init__(printer=printer,
category=category,
error=error,
title=title,
message=message,
approved=approved)
self.id = id_

@property
Expand All @@ -60,10 +66,9 @@ def decor(cls):
data = yaml.safe_load(src_file)
assert "Errors" in data

code_re = re.compile(
r"^(?P<printer>([0-9][0-9]|XX))"
r"(?P<category>[0-9])"
r"(?P<error>[0-9][0-9])$")
code_re = re.compile(r"^(?P<printer>([0-9][0-9]|XX))"
r"(?P<category>[0-9])"
r"(?P<error>[0-9][0-9])$")
for entry in data["Errors"]:
code_parts = code_re.match(entry["code"]).groupdict()
category = Category(int(code_parts["category"]))
Expand All @@ -73,24 +78,26 @@ def decor(cls):
if code_parts["printer"] == 'XX':
if printers := entry.get("printers"):
if 'MK4' in printers:
printers.append('MK39')
printers.extend(('MK4S', 'MK3.9', 'MK3.9S'))
elif 'MK3.5' in printers:
printers.append('MK3.5S')
else: # if no printers specified code is valid for all buddy
printers = BUDDY

for printer in printers:
printer = Printer[printer.upper().replace(".", "")]
code = PrinterCode(
printer, category, error, entry["title"],
entry["text"], entry.get("approved", False),
entry["id"])
code = PrinterCode(printer, category, error,
entry["title"], entry["text"],
entry.get("approved",
False), entry["id"])
setattr(cls, str(code), code)

# code contains printer number
else:
printer = Printer(int(code_parts["printer"]))
code = PrinterCode(printer, category, error, entry["title"],
entry["text"], entry.get("approved", False),
entry["id"])
code = PrinterCode(printer, category, error,
entry["title"], entry["text"],
entry.get("approved", False), entry["id"])
setattr(cls, str(code), code)
return cls

Expand Down
106 changes: 75 additions & 31 deletions prusaerrors/shared/codes.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
# This file is part of the Prusa firmware
# Copyright (C) 2020 Prusa Research a.s. - www.prusa3d.com
# SPDX-License-Identifier: GPL-3.0-or-later

"""
Base classes for SL1 errors and warnings
"""

import functools
import json
import re
from enum import unique, IntEnum
from enum import IntEnum, unique
from pathlib import Path
from typing import List, TextIO, Dict
from typing import Dict, List, TextIO, Optional

import yaml

Expand All @@ -31,17 +30,23 @@ class Printer(IntEnum):
MK4 = 0x000D
IX = 0x0010
XL = 0x0011
MK35 = 0x0017
MK39 = 0x0015
NEXT = 0x0019
MK35 = 0x0017
HONEYBEE = 0x0019
MK4S = 0x001A
MK39S = 0x001B
MK35S = 0x001C
M1 = 0x001D
COREONE = 0x001F


@unique
class Category(IntEnum):
"""
Prusa error category codes
This mapping is taken from general Prusa guidelines on errors, do not modify.
This mapping is taken from general Prusa guidelines on errors, do not
modify.
"""

MECHANICAL = 1 # Mechanical failures, engines XYZ, tower
Expand All @@ -62,16 +67,15 @@ class Code:
"""

# pylint: disable = too-many-arguments
def __init__(
self,
printer: Printer,
category: Category,
error: int,
title: str,
message: str,
approved: bool,
action: List[str] = None
):
# pylint: disable = too-many-positional-arguments
def __init__(self,
printer: Printer,
category: Category,
error: int,
title: str,
message: str,
approved: bool,
action: Optional[List[str]] = None):
if printer.value < 0 or printer.value > 99:
raise ValueError(f"Printer class {printer} out of range")
if category.value < 0 or category.value > 9:
Expand Down Expand Up @@ -165,8 +169,9 @@ def approved(self):
"""
Whenever the message text was approved for use in production system
Unapproved tests are not supposed to be translated. This is planed to raise warnings and prevent the resulting
build from being used in production.
Unapproved tests are not supposed to be translated. This is planed
to raise warnings and prevent the resulting build from being used in
production.
"""
return self._approved

Expand Down Expand Up @@ -212,7 +217,10 @@ def get_codes(cls) -> Dict[str, Code]:
:return: Member code dict
"""
return {item: var for item, var in vars(cls).items() if isinstance(var, Code)}
return {
item: var
for item, var in vars(cls).items() if isinstance(var, Code)
}

@classmethod
def get(cls, code: str):
Expand All @@ -225,7 +233,10 @@ def get(cls, code: str):
:return: Code instance
"""
if not cls._code_map:
cls._code_map = {code.code: code for code in cls.get_codes().values()}
cls._code_map = {
code.code: code
for code in cls.get_codes().values()
}
return cls._code_map[code]

@classmethod
Expand All @@ -236,7 +247,13 @@ def dump_json(cls, file: TextIO) -> None:
:param file: Where to dump
:return: None
"""
obj = {name.lower(): {"code": code.code, "message": code.message} for name, code in cls.get_codes().items()}
obj = {
name.lower(): {
"code": code.code,
"message": code.message
}
for name, code in cls.get_codes().items()
}
return json.dump(obj, file, indent=True)

@classmethod
Expand Down Expand Up @@ -284,7 +301,9 @@ def dump_qml_dictionary(cls, file: TextIO):
:return: None
"""
file.write("import QtQuick 2.10\n")
file.write("/* Generated by sla-errors. Your edits to this file will be lost. */\n")
file.write(
"/* Generated by sla-errors. Your edits to this file will be lost. */\n"
)
file.write("pragma Singleton\n")
file.write("Item {\n")
file.write("\treadonly property var messages:{\n")
Expand All @@ -304,7 +323,9 @@ def dump_cpp_ts(cls, file: TextIO):
:param file: Where to dump
:return: None
"""
file.write("// Generated translation string definitions for all defined error messages\n")
file.write(
"// Generated translation string definitions for all defined error messages\n"
)
for code in cls.get_codes().values():
if code.message:
file.write(f"QT_TR_NOOP({code.raw_message});\n")
Expand All @@ -329,7 +350,9 @@ def dump_google_docs(cls, file: TextIO) -> None:
for name, code in cls.get_codes().items():
message = code.message if code.message else ""
category = f"{c2docs[code.category]}\t{code.category.value}"
file.write(f'SL1\t10\t{category}\t{code.error}\t"{name}"\t"{message}"\t{code.code}\n')
file.write(
f'SL1\t10\t{category}\t{code.error}\t"{name}"\t"{message}"\t{code.code}\n'
)

@classmethod
def dump_yaml(cls, file: TextIO) -> None:
Expand All @@ -342,9 +365,13 @@ def dump_yaml(cls, file: TextIO) -> None:
codes = []

for name, code in cls.get_codes().items():
codes.append(
{"code": code.raw_code, "title": name, "text": code.message, "id": name, "approved": code.approved, }
)
codes.append({
"code": code.raw_code,
"title": name,
"text": code.message,
"id": name,
"approved": code.approved,
})

yaml.dump({"Errors": codes}, file, sort_keys=False)

Expand All @@ -359,7 +386,8 @@ def unique_codes(cls):
used = set()
for name, code in cls.get_codes().items():
if code.code in used:
raise ValueError(f"Code {name} with value {code.code} is duplicate!")
raise ValueError(
f"Code {name} with value {code.code} is duplicate!")
used.add(code.code)

return cls
Expand All @@ -375,7 +403,8 @@ def unique_titles(cls):
used = set()
for name, code in cls.get_codes().items():
if code.title in used:
raise ValueError(f"Code {name} with title {code.title} is duplicate!")
raise ValueError(
f"Code {name} with title {code.title} is duplicate!")
used.add(code.title)

return cls
Expand Down Expand Up @@ -407,8 +436,23 @@ def yaml_codes(src_path: Path):
"""

def decor(cls):
for identifier, code in decode_yaml(src_path):
setattr(cls, identifier, code)
with src_path.open("r") as src_file:
data = yaml.safe_load(src_file)
assert "Errors" in data

code_re = re.compile(
r"^(?P<printer>[0-9][0-9])(?P<category>[0-9])(?P<error>[0-9][0-9])$"
)
for entry in data["Errors"]:
code_parts = code_re.match(entry["code"]).groupdict()
printer = Printer(int(code_parts["printer"]))
category = Category(int(code_parts["category"]))
error = int(code_parts["error"])
action = entry.get("action", [])
setattr(
cls, entry["id"],
Code(printer, category, error, entry["title"], entry["text"],
entry["approved"], action))
return cls

return decor
4 changes: 4 additions & 0 deletions prusaerrors/sl1/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# pylint: disable = missing-module-docstring
from pathlib import Path

PRINTER_MODEL_PATH = Path("/run/model")
Loading

0 comments on commit 0c24664

Please sign in to comment.