flashforge-python-api 1.3.4__py3-none-any.whl → 1.3.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
flashforge/__init__.py CHANGED
@@ -128,7 +128,7 @@ from .tcp import (
128
128
  )
129
129
 
130
130
  FiveMClient = FlashForgeClient
131
- __version__ = "1.3.4"
131
+ __version__ = "1.3.5"
132
132
  __author__ = "FlashForge Python API Contributors"
133
133
  __email__ = "notghosttypes@gmail.com"
134
134
  __description__ = "Python library for controlling FlashForge 3D printers"
@@ -69,8 +69,19 @@ class Files:
69
69
  async def get_recent_file_list(self) -> list[FFGcodeFileEntry]:
70
70
  """
71
71
  Retrieves a list of the 10 most recently printed files from the printer's API.
72
- For AD5X and newer printers, returns detailed file entries with material info.
73
- For older printers, returns basic file entries with normalized data.
72
+
73
+ Only the **AD5X** answers with `gcodeListDetail`, the per-file block carrying
74
+ print time, filament weight, and the per-tool material data that material
75
+ matching is built from. Every other model - the 5M, the 5M Pro, **and the
76
+ Creator 5 / Creator 5 Pro** - returns bare file names, and their entries come
77
+ back with `gcode_tool_datas=None` and `printing_time=0`.
78
+
79
+ The Creator 5 is the surprise there, and it is firmware, not a parsing gap:
80
+ it is a newer printer than the AD5X but reports less (confirmed against a
81
+ Creator 5 Pro, 2026-08-05). Do not describe this method as "AD5X and newer" -
82
+ that phrasing cost a downstream integration three releases of chasing a bug
83
+ that was never in the code. Callers that need per-tool data on a Creator 5
84
+ must parse the 3mf themselves at upload time.
74
85
 
75
86
  Returns:
76
87
  A list of FFGcodeFileEntry objects. Returns an empty list if the request fails or an error occurs.
@@ -125,7 +136,8 @@ class Files:
125
136
  return entries
126
137
  return []
127
138
 
128
- # AD5X and newer printers provide detailed info in gcodeListDetail
139
+ # Only the AD5X provides detailed info in gcodeListDetail. The
140
+ # Creator 5 series does not, despite being the newer hardware.
129
141
  if result.gcode_list_detail and len(result.gcode_list_detail) > 0:
130
142
  return result.gcode_list_detail
131
143
 
@@ -302,7 +302,21 @@ class MachineInfoParser:
302
302
 
303
303
  @staticmethod
304
304
  def _get_machine_state(status: str) -> MachineState:
305
- """Map raw status strings into the public machine state enum."""
305
+ """Map raw status strings into the public machine state enum.
306
+
307
+ An unmapped value costs the consumer everything the field is for: it
308
+ becomes ``UNKNOWN``, which in Home Assistant renders as "unknown" - the
309
+ one state that says nothing, at the moment the user most needs to know
310
+ what the printer is doing. Both additions below were found that way, in
311
+ a log full of `Unknown machine status received` while a Creator 5 Pro sat
312
+ paused on a detected clog.
313
+
314
+ Consumers may map this enum onto a fixed set of values - the Home
315
+ Assistant integration's Machine Status sensor is a `device_class=ENUM`
316
+ with an explicit `options` list - so a *new* member is a breaking change
317
+ for them, while mapping onto an existing one is not. Prefer the closest
318
+ existing state unless a new one is worth coordinating.
319
+ """
306
320
  valid_status = status.lower() if isinstance(status, str) else ""
307
321
  state_mapping = {
308
322
  "ready": MachineState.READY,
@@ -312,9 +326,20 @@ class MachineInfoParser:
312
326
  "heating": MachineState.HEATING,
313
327
  "printing": MachineState.PRINTING,
314
328
  "pausing": MachineState.PAUSING,
329
+ # The Creator 5 Pro reports "pause" for a print that is paused,
330
+ # where the documented value is "paused" - both are mapped, because
331
+ # firmware that reports one is not a reason to drop the other.
332
+ # Observed on pid 41, firmware 1.9.4, whenever the printer paused
333
+ # itself on a detected clog.
334
+ "pause": MachineState.PAUSED,
315
335
  "paused": MachineState.PAUSED,
316
336
  "cancel": MachineState.CANCELLED,
317
337
  "completed": MachineState.COMPLETED,
338
+ # Reported while a file is being transferred to the printer. Not a
339
+ # print, but not idle either, so BUSY is the honest existing fit; a
340
+ # dedicated state would need consumers to add it to their option
341
+ # lists first.
342
+ "downloading": MachineState.BUSY,
318
343
  }
319
344
 
320
345
  if valid_status in state_mapping:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flashforge-python-api
3
- Version: 1.3.4
3
+ Version: 1.3.5
4
4
  Summary: A comprehensive Python library for controlling FlashForge 3D printers
5
5
  Project-URL: Homepage, https://github.com/GhostTypes/ff-5mp-api-py
6
6
  Project-URL: Documentation, https://github.com/GhostTypes/ff-5mp-api-py#readme
@@ -1,4 +1,4 @@
1
- flashforge/__init__.py,sha256=pTj91BlyK6rFMy9yD03q8IowcSrUm9ra-b1vMCYEJDo,5472
1
+ flashforge/__init__.py,sha256=rWsmx8X1akurtqwcS_cSeZGkzbSXc3Nnd1xeNsnAAj4,5472
2
2
  flashforge/client.py,sha256=nDtnv3y9XlEQknIkgIUiuOYAiyTEGbQ7tHBdCs2fg1I,21432
3
3
  flashforge/exceptions.py,sha256=rZwBJHyqqtoI6cgd8iGOvPH8EDcytA3lyU3FoVMJgyU,1732
4
4
  flashforge/api/__init__.py,sha256=vQz-DkG6LTH39bI4fyiUc0D9jQzemLh45pORLptSOlg,335
@@ -8,8 +8,8 @@ flashforge/api/constants/endpoints.py,sha256=oZtOFfkU64THDeCMUIVv6_0L-BOUZzgLKAU
8
8
  flashforge/api/controls/__init__.py,sha256=53s-H25Pjwr0kvPk8MZ2Twy8VHGqGcO6Q6uBphhEOh4,293
9
9
  flashforge/api/controls/control.py,sha256=OgE7K6NkFLwFN1r_q5g1RPwYC8MCt0f6L5CZxDW44d8,15151
10
10
  flashforge/api/controls/creator5_palette.py,sha256=zdD3PIXx7hCVj2Fmv1CSFOaqogRUPeBaymgY2DFiMxk,8835
11
- flashforge/api/controls/files.py,sha256=25yxln9NROas9TtFMZR9e8LtA8ruk8RUu2C81vpNgTk,8043
12
- flashforge/api/controls/info.py,sha256=AZ5529HbB1LBfae6voz_4mz30pQd8R8HpcRrPa5qXCw,22451
11
+ flashforge/api/controls/files.py,sha256=Jk2ySrJdw2QDk1CJlGfY4bTmZJocx4GXztkEqE4rRaI,8830
12
+ flashforge/api/controls/info.py,sha256=O6NVGSRwhArUqxCGXHK5WV20-Nn_8rHGUMbZheXXEjs,23973
13
13
  flashforge/api/controls/job_control.py,sha256=NnACm4LPUz4n8lnRiUl33jilWekS1b6HQTbP--nDzZc,33225
14
14
  flashforge/api/controls/temp_control.py,sha256=EOO5TkODirjFcnQ7rZrirxAweHBdVin032AWj-Z8VQs,13040
15
15
  flashforge/api/filament/__init__.py,sha256=isT2dl0hzUS0xMTXMm4Tip0GTG1gCsm8LKWa9xPu4Y8,104
@@ -42,8 +42,8 @@ flashforge/tcp/parsers/print_status.py,sha256=C-KzukhK0TR86AP3t3XrMH4dief6pa3I-y
42
42
  flashforge/tcp/parsers/printer_info.py,sha256=CHPs6nJfEByXyG3co7Nb8_ygggxkYuc7A9O9bpQEqXE,5441
43
43
  flashforge/tcp/parsers/temp_info.py,sha256=9wRGUM9cKvDiZD3SIxBx_qVLZbeXoYsoY3-R3vN3H4g,7938
44
44
  flashforge/tcp/parsers/thumbnail_info.py,sha256=1U1S_gcIZ2lDpEA4622ywUew6TVw0BnzjlBAiihQwzk,10478
45
- flashforge_python_api-1.3.4.dist-info/METADATA,sha256=Kdqkl6GJBRr3vRFf6p6Qk-qZ_8TtSUCNS0jdzEIxvHE,4970
46
- flashforge_python_api-1.3.4.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
47
- flashforge_python_api-1.3.4.dist-info/entry_points.txt,sha256=AkOxlsLvQ7cvMLxn7tlzfKp_DCH2hXhbVceHIXxawpU,66
48
- flashforge_python_api-1.3.4.dist-info/licenses/LICENSE,sha256=-cTA-hrmvlb3pqlQrBZQXUnKayhUjsLJMPb7TD91frM,1067
49
- flashforge_python_api-1.3.4.dist-info/RECORD,,
45
+ flashforge_python_api-1.3.5.dist-info/METADATA,sha256=oSmQO3OQPkDynC5evAjLOdK6jpCaD2SmT7DZk6lC5CY,4970
46
+ flashforge_python_api-1.3.5.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
47
+ flashforge_python_api-1.3.5.dist-info/entry_points.txt,sha256=AkOxlsLvQ7cvMLxn7tlzfKp_DCH2hXhbVceHIXxawpU,66
48
+ flashforge_python_api-1.3.5.dist-info/licenses/LICENSE,sha256=-cTA-hrmvlb3pqlQrBZQXUnKayhUjsLJMPb7TD91frM,1067
49
+ flashforge_python_api-1.3.5.dist-info/RECORD,,