hms_actions.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. """HMS action lookup.
  2. Bambu printers report HMS errors with a fixed catalog of remediation actions
  3. (resume / stop / check assistant / etc.). The catalog is bundled as JSON, keyed
  4. by the 3-letter SN prefix (printer model code: 03W = A1, 31B = X1C, etc.) and
  5. the short error code with no separator.
  6. The action IDs and their string names are derived from BambuStudio's source via
  7. `scripts/update_hms_actions.py`. The data file itself is fetched from Bambu's
  8. public `e.bambulab.com/hms/GetActionImage.php` endpoint.
  9. """
  10. import json
  11. from enum import StrEnum
  12. from pathlib import Path
  13. _DATA_FILE = Path(__file__).resolve().parent.parent / "data" / "hms_actions.json"
  14. # Loaded eagerly at import — the file is ~150KB and only read once. Using an
  15. # absolute path keeps the load independent of CWD (systemd unit, Docker
  16. # entrypoint, pytest run from `backend/`).
  17. with _DATA_FILE.open("r", encoding="utf-8") as _f:
  18. _actions: dict[str, dict[str, list[str]]] = json.load(_f)
  19. class HMSAction(StrEnum):
  20. """Remediation actions a Bambu printer can offer for an HMS error.
  21. Values intentionally match the constants used in BambuStudio's source so the
  22. HMS-data fetcher can map Bambu's integer action IDs straight to these
  23. strings. The CANCLE typo is preserved verbatim — it's how BambuStudio spells
  24. it, and changing it would break the action lookup against the catalog.
  25. """
  26. RESUME_PRINTING = "RESUME_PRINTING"
  27. RESUME_PRINTING_DEFECTS = "RESUME_PRINTING_DEFECTS"
  28. RESUME_PRINTING_PROBELM_SOLVED = "RESUME_PRINTING_PROBELM_SOLVED"
  29. STOP_PRINTING = "STOP_PRINTING"
  30. CHECK_ASSISTANT = "CHECK_ASSISTANT"
  31. FILAMENT_EXTRUDED = "FILAMENT_EXTRUDED"
  32. RETRY_FILAMENT_EXTRUDED = "RETRY_FILAMENT_EXTRUDED"
  33. CONTINUE = "CONTINUE"
  34. LOAD_VIRTUAL_TRAY = "LOAD_VIRTUAL_TRAY"
  35. OK_BUTTON = "OK_BUTTON"
  36. FILAMENT_LOAD_RESUME = "FILAMENT_LOAD_RESUME"
  37. JUMP_TO_LIVEVIEW = "JUMP_TO_LIVEVIEW"
  38. NO_REMINDER_NEXT_TIME = "NO_REMINDER_NEXT_TIME"
  39. REFRESH_NOZZLE = "REFRESH_NOZZLE"
  40. IGNORE_NO_REMINDER_NEXT_TIME = "IGNORE_NO_REMINDER_NEXT_TIME"
  41. IGNORE_RESUME = "IGNORE_RESUME"
  42. PROBLEM_SOLVED_RESUME = "PROBLEM_SOLVED_RESUME"
  43. TURN_OFF_FIRE_ALARM = "TURN_OFF_FIRE_ALARM"
  44. RETRY_PROBLEM_SOLVED = "RETRY_PROBLEM_SOLVED"
  45. STOP_DRYING = "STOP_DRYING"
  46. CANCLE = "CANCLE" # sic — verbatim from BambuStudio
  47. REMOVE_CLOSE_BTN = "REMOVE_CLOSE_BTN"
  48. PROCEED = "PROCEED"
  49. OK_JUMP_RACK = "OK_JUMP_RACK"
  50. ABORT = "ABORT"
  51. DISABLE_PURIFICATION = "DISABLE_PURIFICATION"
  52. DONT_REMIND_NEXT_TIME = "DONT_REMIND_NEXT_TIME"
  53. DBL_CHECK_CANCEL = "DBL_CHECK_CANCEL"
  54. DBL_CHECK_DONE = "DBL_CHECK_DONE"
  55. DBL_CHECK_RETRY = "DBL_CHECK_RETRY"
  56. DBL_CHECK_RESUME = "DBL_CHECK_RESUME"
  57. DBL_CHECK_OK = "DBL_CHECK_OK"
  58. def get_actions_for_error_code(device: str, error_code: str) -> list[str]:
  59. """Look up the action list for a printer SN prefix + short error code.
  60. Returns the empty list if the printer model or the error code is unknown —
  61. the modal renders no buttons in that case, which is the correct fallback.
  62. """
  63. return _actions.get(device, {}).get(error_code, [])