Coverage for src / zooc / zooc_core.py: 70%

42 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-11 21:45 +0000

1"""The core functionality of the ZOOC module.""" 

2import logging 

3from dataclasses import dataclass 

4 

5from .data.calibration_data import CalibrationData 

6from .data.temps import Temps 

7 

8logger = logging.getLogger(__name__) 

9 

10 

11class ZoocError(Exception): 

12 """Custom exception for ZOOC errors.""" 

13 

14 

15@dataclass 

16class ZoocCore: 

17 """Utilities to calculate Z-offsets for the given temperature and handle fixed offsets.""" 

18 

19 temps_ref: Temps 

20 allowed_offset_range: tuple[float, float] 

21 fixed_offsets: dict[str, float] 

22 calibration_data: CalibrationData 

23 

24 def set_calibration_data(self, calibration_data: CalibrationData) -> None: 

25 """Set new ZOOC calibration data. 

26 

27 :param calibration_data: New ZOOC calibration data. 

28 """ 

29 self.calibration_data = calibration_data 

30 

31 def get_fixed_offsets(self, fixed_offsets: str, allow_missing: bool = True) -> dict[str, float]: 

32 """Get fixed offsets from the comma separated string. 

33 

34 Raise ZoocError if not all fixed offsets are found and missing profiles are not allowed. 

35 

36 :param fixed_offsets: Comma separated string of fixed offsets. 

37 :param allow_missing: Allow missing fixed offsets. 

38 :return: Dictionary of fixed offsets. 

39 :raises ZoocError: If not all fixed profiles were found and allow_missing is False. 

40 """ 

41 list_fo = list(filter(lambda e: e, fixed_offsets.strip().split(','))) 

42 dict_fixed_offsets = self.filter_fixed_offsets(profiles=list_fo) 

43 if allow_missing is False and len(list_fo) != len(dict_fixed_offsets): 

44 raise ZoocError(f"Not all fixed profiles were found: {list_fo}") 

45 return dict_fixed_offsets # Add fixed offsets to final z-offset 

46 

47 def get_temp_z_offset(self, temps: Temps) -> float: 

48 """Calculate Z-offset for given temperatures. 

49 

50 :param temps: Temperatures to calculate Z-offset for 

51 :return: Z-offset at temps 

52 :raises ZoocError: If the Z-offset is outside the allowed range 

53 """ 

54 z_offset = self.calibration_data.offset_data.calculate_z_offset(self.temps_ref, temps) 

55 if not self.allowed_offset_range[0] < z_offset < self.allowed_offset_range[1]: 

56 raise ZoocError(f"Z-offset {z_offset:.6f} mm adjustment would be outside allowed range {self.allowed_offset_range} mm") 

57 return z_offset 

58 

59 def filter_fixed_offsets(self, profiles: list[str]) -> dict[str, float]: 

60 """Select the profiles with the given names. 

61 

62 :param profiles: Names of the profile. 

63 :return: Fixed offsets. 

64 """ 

65 filtered = {} 

66 for key in profiles: 

67 key_name = key.lower().strip() 

68 value = self.fixed_offsets.get(key_name) 

69 if value is None: 

70 logger.debug(f"Fixed offset for '{key_name}' was not found") 

71 continue 

72 filtered[key_name] = value 

73 return filtered 

74 

75 # noinspection PyMethodMayBeStatic 

76 def get_aggregated_temps(self, temps_pri: Temps, temps_sec: Temps) -> Temps: 

77 """Get an aggregated set of bed and extruder temperatures. 

78 

79 Use the target temperatures when given temperature is not set. 

80 

81 :param temps_pri: Primary temperatures to use if those are set. 

82 :param temps_sec: Secondary temperatures to use when primary is not set. 

83 :return: Aggregated temperatures, where both bed and extruder are set. 

84 :raises ZoocError: When temperatures are inconsistent. 

85 """ 

86 if not temps_pri.is_none_off(): 

87 raise ZoocError("Temperatures must be > 0 or disabled (None)") 

88 

89 if not temps_sec.both_on() and not temps_sec.both_off(): 

90 raise ZoocError("Both bed and extruder heaters must be on or off. Cannot calculate Z-offset") 

91 

92 # Use provided temperatures if set, otherwise use target temperatures 

93 bed = temps_pri.bed_temp if temps_pri.bed.enabled else temps_sec.bed_temp if temps_sec.bed.enabled else None 

94 extruder = temps_pri.extruder_temp if temps_pri.extruder.enabled else temps_sec.extruder_temp if temps_sec.extruder.enabled else None 

95 temps_final = Temps.create(bed=bed, extruder=extruder) 

96 if not temps_final.both_on(): 

97 raise ZoocError("Bed or extruder is off and temperatures parameters were not given") 

98 return temps_final