anycubic-cloud-api 0.4.8__tar.gz → 0.4.9__tar.gz

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.
Files changed (50) hide show
  1. {anycubic_cloud_api-0.4.8/src/anycubic_cloud_api.egg-info → anycubic_cloud_api-0.4.9}/PKG-INFO +1 -1
  2. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/pyproject.toml +1 -1
  3. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/api/functions.py +115 -0
  4. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/const/enums.py +7 -0
  5. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/data_models/printer.py +48 -0
  6. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9/src/anycubic_cloud_api.egg-info}/PKG-INFO +1 -1
  7. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/COPYRIGHT +0 -0
  8. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/LICENSE +0 -0
  9. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/MANIFEST.in +0 -0
  10. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/README.md +0 -0
  11. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/setup.cfg +0 -0
  12. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/__init__.py +0 -0
  13. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/anycubic_api.py +0 -0
  14. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/api/base.py +0 -0
  15. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/api/mqtt.py +0 -0
  16. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/const/api_endpoints.py +0 -0
  17. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/const/const.py +0 -0
  18. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/const/lan.py +0 -0
  19. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/const/mqtt.py +0 -0
  20. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/data_models/consumable.py +0 -0
  21. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/data_models/files.py +0 -0
  22. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/data_models/gcode_file.py +0 -0
  23. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/data_models/orders.py +0 -0
  24. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/data_models/print_response.py +0 -0
  25. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/data_models/print_speed_mode.py +0 -0
  26. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/data_models/printer_properties.py +0 -0
  27. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/data_models/printing_settings.py +0 -0
  28. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/data_models/project.py +0 -0
  29. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/exceptions/error_strings.py +0 -0
  30. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/exceptions/exceptions.py +0 -0
  31. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/helpers/helpers.py +0 -0
  32. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/lan/__init__.py +0 -0
  33. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/lan/client.py +0 -0
  34. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/lan/handshake.py +0 -0
  35. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/models/auth.py +0 -0
  36. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/models/cloud_upload.py +0 -0
  37. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/models/http.py +0 -0
  38. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/resources/anycubic_mqqt_tls_ca.crt +0 -0
  39. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/resources/anycubic_mqqt_tls_client.crt +0 -0
  40. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api/resources/anycubic_mqqt_tls_client.key +0 -0
  41. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api.egg-info/SOURCES.txt +0 -0
  42. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api.egg-info/dependency_links.txt +0 -0
  43. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api.egg-info/requires.txt +0 -0
  44. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/src/anycubic_cloud_api.egg-info/top_level.txt +0 -0
  45. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/tests/test_auth_mode_fallback.py +0 -0
  46. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/tests/test_axis_position.py +0 -0
  47. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/tests/test_lan_client.py +0 -0
  48. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/tests/test_lan_handshake.py +0 -0
  49. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/tests/test_lan_reports.py +0 -0
  50. {anycubic_cloud_api-0.4.8 → anycubic_cloud_api-0.4.9}/tests/test_partial_reports.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anycubic-cloud-api
3
- Version: 0.4.8
3
+ Version: 0.4.9
4
4
  Summary: Async client for the Anycubic Cloud API and its MQTT stream
5
5
  Author: WaresWichall, Nino Bondonno
6
6
  Maintainer: Nino Bondonno
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "anycubic-cloud-api"
7
- version = "0.4.8"
7
+ version = "0.4.9"
8
8
  description = "Async client for the Anycubic Cloud API and its MQTT stream"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -513,6 +513,121 @@ class AnycubicAPIFunctions(AnycubicAPIBase):
513
513
  ),
514
514
  )
515
515
 
516
+ async def _send_order_set_temperature(
517
+ self,
518
+ printer: AnycubicPrinter,
519
+ target_nozzle_temp: int | None = None,
520
+ target_hotbed_temp: int | None = None,
521
+ ) -> str | None:
522
+ """Set nozzle and/or bed temperature, with or without a print job.
523
+
524
+ Distinct from PRINT_SETTINGS, which the server refuses with "Print
525
+ task does not exist" unless a job is running. This is what the
526
+ slicer's One-Click Preheat uses, captured from its own traffic:
527
+
528
+ {"type": 0, "target_hotbed_temp": 0, "target_nozzle_temp": 230}
529
+ {"type": 1, "target_hotbed_temp": 90, "target_nozzle_temp": 0}
530
+ {"type": 2, "target_hotbed_temp": 60, "target_nozzle_temp": 200}
531
+
532
+ `type` says which of the two the printer should act on -- 0 nozzle,
533
+ 1 bed, 2 both -- and the unused figure is sent as 0 rather than
534
+ omitted.
535
+ """
536
+ if not printer:
537
+ return None
538
+
539
+ if target_nozzle_temp is None and target_hotbed_temp is None:
540
+ return None
541
+
542
+ if target_hotbed_temp is None:
543
+ heat_type = 0
544
+ elif target_nozzle_temp is None:
545
+ heat_type = 1
546
+ else:
547
+ heat_type = 2
548
+
549
+ return await self._send_anycubic_order(
550
+ order_request=AnycubicProjectOrderRequest(
551
+ order_id=AnycubicOrderID.SET_TEMPERATURE,
552
+ printer_id=printer.id,
553
+ project_id=0,
554
+ order_data={
555
+ 'type': heat_type,
556
+ 'target_hotbed_temp': int(target_hotbed_temp or 0),
557
+ 'target_nozzle_temp': int(target_nozzle_temp or 0),
558
+ },
559
+ ),
560
+ )
561
+
562
+ async def _send_order_set_fan_speed(
563
+ self,
564
+ printer: AnycubicPrinter,
565
+ fan_speed_pct: int | None = None,
566
+ aux_fan_speed_pct: int | None = None,
567
+ box_fan_level: int | None = None,
568
+ ) -> str | None:
569
+ """Set one fan, without needing a print job.
570
+
571
+ The slicer sends exactly one key per call -- {"fan_speed_pct": 40} --
572
+ rather than a combined object, so this mirrors that.
573
+ """
574
+ if not printer:
575
+ return None
576
+
577
+ data: dict[str, Any] = {}
578
+
579
+ if fan_speed_pct is not None:
580
+ data['fan_speed_pct'] = int(fan_speed_pct)
581
+ elif aux_fan_speed_pct is not None:
582
+ data['aux_fan_speed_pct'] = int(aux_fan_speed_pct)
583
+ elif box_fan_level is not None:
584
+ data['box_fan_level'] = int(box_fan_level)
585
+ else:
586
+ return None
587
+
588
+ return await self._send_anycubic_order(
589
+ order_request=AnycubicProjectOrderRequest(
590
+ order_id=AnycubicOrderID.SET_FAN_SPEED,
591
+ printer_id=printer.id,
592
+ project_id=0,
593
+ order_data=data,
594
+ ),
595
+ )
596
+
597
+ async def _send_order_move_axis(
598
+ self,
599
+ printer: AnycubicPrinter,
600
+ axis: int,
601
+ move_type: int,
602
+ distance: int = 0,
603
+ ) -> str | None:
604
+ """Move or home an axis.
605
+
606
+ {"axis": 1|2|3|4, "move_type": 0|1|2, "distance": mm}
607
+
608
+ axis 1 X, 2 Y, 3 Z, 4 all
609
+ move_type 0 minus, 1 plus, 2 home (distance ignored)
610
+
611
+ ⚠ The printer refuses moves until it has been homed, and its own UI
612
+ warns about nozzle-to-bed collisions -- so callers should home first
613
+ and keep steps small.
614
+ """
615
+ if not printer:
616
+ return None
617
+
618
+ return await self._send_anycubic_order(
619
+ order_request=AnycubicProjectOrderRequest(
620
+ order_id=AnycubicOrderID.MOVE_AXLE,
621
+ printer_id=printer.id,
622
+ project_id=0,
623
+ order_data={
624
+ 'axis': int(axis),
625
+ 'move_type': int(move_type),
626
+ 'distance': int(distance),
627
+ },
628
+ ),
629
+ )
630
+
516
631
  async def _send_order_multi_color_box_dry(
517
632
  self,
518
633
  printer: AnycubicPrinter,
@@ -57,6 +57,13 @@ class AnycubicOrderID(IntEnum):
57
57
  MOVE_AXLE_TURN_OFF = 1213 # Not handled
58
58
  QUERY_AXIS_POSITION = 1214 # Replies over MQTT with axis/query
59
59
  FILAMENT_CONTROL = 1215 # Not handled
60
+ # Set temperatures directly, with no print job. This is NOT
61
+ # PRINT_SETTINGS -- that one is refused unless a job is running, which
62
+ # is why preheating an idle printer looked impossible until the
63
+ # slicer's own traffic showed this order.
64
+ SET_TEMPERATURE = 1216
65
+ # Fan speeds directly, again without needing a running job.
66
+ SET_FAN_SPEED = 1221
60
67
  FEED_RESIN = 1224 # Not handled
61
68
  M7_AUTO_OPERATION = 1225 # Not handled
62
69
  CYCLIC_CLEANING = 1226 # Not handled
@@ -2945,6 +2945,54 @@ class AnycubicPrinter:
2945
2945
  slot_index_list=slot_index_list,
2946
2946
  )
2947
2947
 
2948
+ async def set_target_temperature(
2949
+ self,
2950
+ target_nozzle_temp: int | None = None,
2951
+ target_hotbed_temp: int | None = None,
2952
+ ) -> str | None:
2953
+ """Heat the nozzle and/or bed, print job or not.
2954
+
2955
+ Unlike change_print_setting_target_* this works on an idle printer --
2956
+ it is the order the slicer's One-Click Preheat uses.
2957
+ """
2958
+ return await self._api_parent._send_order_set_temperature(
2959
+ printer=self,
2960
+ target_nozzle_temp=target_nozzle_temp,
2961
+ target_hotbed_temp=target_hotbed_temp,
2962
+ )
2963
+
2964
+ async def set_fan_speed(
2965
+ self,
2966
+ fan_speed_pct: int | None = None,
2967
+ aux_fan_speed_pct: int | None = None,
2968
+ box_fan_level: int | None = None,
2969
+ ) -> str | None:
2970
+ """Set one fan, print job or not."""
2971
+ return await self._api_parent._send_order_set_fan_speed(
2972
+ printer=self,
2973
+ fan_speed_pct=fan_speed_pct,
2974
+ aux_fan_speed_pct=aux_fan_speed_pct,
2975
+ box_fan_level=box_fan_level,
2976
+ )
2977
+
2978
+ async def move_axis(
2979
+ self,
2980
+ axis: int,
2981
+ move_type: int,
2982
+ distance: int = 0,
2983
+ ) -> str | None:
2984
+ """Jog or home an axis. See _send_order_move_axis for the codes."""
2985
+ return await self._api_parent._send_order_move_axis(
2986
+ printer=self,
2987
+ axis=axis,
2988
+ move_type=move_type,
2989
+ distance=distance,
2990
+ )
2991
+
2992
+ async def home_axis(self, axis: int = 4) -> str | None:
2993
+ """Home an axis, or all of them. Required before any jog works."""
2994
+ return await self.move_axis(axis=axis, move_type=2, distance=0)
2995
+
2948
2996
  async def change_print_setting_speed_mode(
2949
2997
  self,
2950
2998
  new_speed: int
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anycubic-cloud-api
3
- Version: 0.4.8
3
+ Version: 0.4.9
4
4
  Summary: Async client for the Anycubic Cloud API and its MQTT stream
5
5
  Author: WaresWichall, Nino Bondonno
6
6
  Maintainer: Nino Bondonno