dsf-python 3.5.0.2rc2__py3-none-any.whl → 3.6.0b2__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.
dsf/commands/code.py CHANGED
@@ -134,7 +134,7 @@ class Code(BaseCommand):
134
134
  if self.type == CodeType.Comment:
135
135
  return "(comment)"
136
136
 
137
- prefix = "G53 " if self.flags & CodeFlags.EnforceAbsolutePosition != 0 else ""
137
+ prefix = "G53 " if self.is_flag_set(CodeFlags.EnforceAbsolutePosition) else ""
138
138
  if self.majorNumber is not None:
139
139
  if self.minorNumber is not None:
140
140
  return f"{prefix}{self.type}{self.majorNumber}.{self.minorNumber}"
@@ -158,3 +158,6 @@ class Code(BaseCommand):
158
158
  KeywordType.Echo: "echo",
159
159
  KeywordType.Global: "global",
160
160
  }.get(self.keyword)
161
+
162
+ def is_flag_set(self, flag: CodeFlags):
163
+ return self.flags & flag != 0
@@ -28,4 +28,4 @@ def resolve_code(rtype: MessageType, content: Optional[str]):
28
28
  raise TypeError("rtype must be a MessageType")
29
29
  if content is not None and not isinstance(content, str):
30
30
  raise TypeError("content must be None or a string")
31
- return BaseCommand("Resolve", **{"Type": rtype, "Content": content})
31
+ return BaseCommand("Resolve", **{"type": rtype, "content": content})
dsf/commands/files.py CHANGED
@@ -9,15 +9,16 @@ def get_file_info(file_name: str, read_thumbnail_content: bool = False):
9
9
  """
10
10
  if not isinstance(file_name, str) or not file_name:
11
11
  raise TypeError("file_name must be a string")
12
- return BaseCommand("GetFileInfo", **{"FileName": file_name, "ReadThumbnailContent": read_thumbnail_content})
12
+ return BaseCommand("GetFileInfo", **{"fileName": file_name, "readThumbnailContent": read_thumbnail_content})
13
13
 
14
14
 
15
- def resolve_path(path: str):
15
+ def resolve_path(path: str, base_directory: str = None):
16
16
  """
17
17
  Resolve a RepRapFirmware-style path to an actual file path
18
18
  :param path: Path that is RepRapFirmware-compatible
19
+ :param base_directory: Optional base directory to resolve the path relative to
19
20
  :returns: The resolved path
20
21
  """
21
22
  if not isinstance(path, str) or not path:
22
23
  raise TypeError("path must be a string")
23
- return BaseCommand("ResolvePath", **{"Path": path})
24
+ return BaseCommand("ResolvePath", **{"path": path, "baseDirectory": base_directory})
dsf/commands/generic.py CHANGED
@@ -17,7 +17,7 @@ def check_password(password: str):
17
17
  """
18
18
  if not isinstance(password, str) or not password:
19
19
  raise TypeError("password must be a string")
20
- return BaseCommand("CheckPassword", **{"Password": password})
20
+ return BaseCommand("CheckPassword", **{"password": password})
21
21
 
22
22
 
23
23
  def evaluate_expression(channel: CodeChannel, expression: str):
@@ -33,7 +33,7 @@ def evaluate_expression(channel: CodeChannel, expression: str):
33
33
  raise TypeError("channel must be a CodeChannel")
34
34
  if not isinstance(expression, str) or not expression:
35
35
  raise TypeError("expression must be a string")
36
- return BaseCommand("EvaluateExpression", **{"Channel": channel, "Expression": expression})
36
+ return BaseCommand("EvaluateExpression", **{"channel": channel, "expression": expression})
37
37
 
38
38
 
39
39
  def flush(channel: CodeChannel, sync_file_streams: bool = False, if_executing: bool = True):
@@ -57,7 +57,7 @@ def flush(channel: CodeChannel, sync_file_streams: bool = False, if_executing: b
57
57
  if not isinstance(if_executing, bool):
58
58
  raise TypeError("if_executing must be a boolean")
59
59
  return BaseCommand("Flush",
60
- **{"Channel": channel, "SyncFileStreams": sync_file_streams, "IfExecuting": if_executing})
60
+ **{"channel": channel, "syncFileStreams": sync_file_streams, "ifExecuting": if_executing})
61
61
 
62
62
 
63
63
  def invalidate_channel(channel: CodeChannel):
@@ -70,7 +70,7 @@ def invalidate_channel(channel: CodeChannel):
70
70
  """
71
71
  if not isinstance(channel, CodeChannel):
72
72
  raise TypeError("channel must be a CodeChannel")
73
- return BaseCommand("InvalidateChannel", **{"Channel": channel})
73
+ return BaseCommand("InvalidateChannel", **{"channel": channel})
74
74
 
75
75
 
76
76
  def set_update_status(updating: bool):
@@ -81,7 +81,7 @@ def set_update_status(updating: bool):
81
81
  """
82
82
  if not isinstance(updating, bool):
83
83
  raise TypeError("updating must be a boolean")
84
- return BaseCommand("SetUpdateStatus", **{"Updating": updating})
84
+ return BaseCommand("SetUpdateStatus", **{"updating": updating})
85
85
 
86
86
 
87
87
  def simple_code(code: str, channel: CodeChannel = CodeChannel.DEFAULT_CHANNEL, async_exec: bool = False):
@@ -101,7 +101,7 @@ def simple_code(code: str, channel: CodeChannel = CodeChannel.DEFAULT_CHANNEL, a
101
101
  raise TypeError("code must be a string")
102
102
  if not isinstance(channel, CodeChannel):
103
103
  raise TypeError("channel must be a CodeChannel")
104
- return BaseCommand("SimpleCode", **{"Code": code, "Channel": channel, "ExecuteAsynchronously": async_exec})
104
+ return BaseCommand("SimpleCode", **{"code": code, "channel": channel, "executeAsynchronously": async_exec})
105
105
 
106
106
 
107
107
  def write_message(
@@ -129,9 +129,9 @@ def write_message(
129
129
  return BaseCommand(
130
130
  "WriteMessage",
131
131
  **{
132
- "Type": message_type,
133
- "Content": content,
134
- "OutputMessage": output_message,
135
- "LogLevel": log_level,
132
+ "type": message_type,
133
+ "content": content,
134
+ "outputMessage": output_message,
135
+ "logLevel": log_level,
136
136
  },
137
137
  )
@@ -25,10 +25,10 @@ def add_http_endpoint(endpoint_type: HttpEndpointType, namespace: str, path: str
25
25
  return BaseCommand(
26
26
  "AddHttpEndpoint",
27
27
  **{
28
- "EndpointType": endpoint_type,
29
- "Namespace": namespace,
30
- "Path": path,
31
- "IsUploadRequest": is_upload_request,
28
+ "endpointType": endpoint_type,
29
+ "namespace": namespace,
30
+ "path": path,
31
+ "isUploadRequest": is_upload_request,
32
32
  },
33
33
  )
34
34
 
@@ -49,5 +49,5 @@ def remove_http_endpoint(endpoint_type: HttpEndpointType, namespace: str, path:
49
49
  raise TypeError("path must be a string")
50
50
  return BaseCommand(
51
51
  "RemoveHttpEndpoint",
52
- **{"EndpointType": endpoint_type, "Namespace": namespace, "Path": path},
52
+ **{"endpointType": endpoint_type, "namespace": namespace, "path": path},
53
53
  )
@@ -24,7 +24,7 @@ def patch_object_model(key: str, patch: str):
24
24
  raise TypeError("key must be a string")
25
25
  if not isinstance(patch, str) or not patch:
26
26
  raise TypeError("patch must be a string")
27
- return BaseCommand("PatchObjectModel", **{"Key": key, "Patch": patch})
27
+ return BaseCommand("PatchObjectModel", **{"key": key, "patch": patch})
28
28
 
29
29
 
30
30
  def set_network_protocol(protocol: str, enabled: bool):
@@ -38,7 +38,7 @@ def set_network_protocol(protocol: str, enabled: bool):
38
38
  raise TypeError("protocol must be a string")
39
39
  if not isinstance(enabled, bool):
40
40
  raise TypeError("enabled must be a boolean")
41
- return BaseCommand("SetNetworkProtocol", **{"NetworkProtocol": protocol, "Enabled": enabled})
41
+ return BaseCommand("SetNetworkProtocol", **{"networkProtocol": protocol, "enabled": enabled})
42
42
 
43
43
 
44
44
  def set_object_model(property_path: str, value: str):
@@ -53,7 +53,7 @@ def set_object_model(property_path: str, value: str):
53
53
  raise TypeError("property_path must be a string")
54
54
  if not isinstance(value, str):
55
55
  raise TypeError("value must be a string")
56
- return BaseCommand("SetObjectModel", **{"PropertyPath": property_path, "Value": value})
56
+ return BaseCommand("SetObjectModel", **{"propertyPath": property_path, "value": value})
57
57
 
58
58
 
59
59
  def sync_object_model():
dsf/commands/packages.py CHANGED
@@ -7,7 +7,7 @@ def install_system_package(package_file: str):
7
7
  """
8
8
  if not isinstance(package_file, str) or not package_file:
9
9
  raise TypeError("package_file must be a string")
10
- return BaseCommand("InstallSystemPackage", **{"PackageFile": package_file})
10
+ return BaseCommand("InstallSystemPackage", **{"packageFile": package_file})
11
11
 
12
12
 
13
13
  def uninstall_system_package(package: str):
@@ -16,4 +16,4 @@ def uninstall_system_package(package: str):
16
16
  """
17
17
  if not isinstance(package, str) or not package:
18
18
  raise TypeError("package must be a string")
19
- return BaseCommand("UninstallSystemPackage", **{"Package": package})
19
+ return BaseCommand("UninstallSystemPackage", **{"package": package})
dsf/commands/plugins.py CHANGED
@@ -8,7 +8,7 @@ def install_plugin(plugin_file: str):
8
8
  """
9
9
  if not isinstance(plugin_file, str) or not plugin_file:
10
10
  raise TypeError("plugin_file must be a string")
11
- return BaseCommand("InstallPlugin", **{"PluginFile": plugin_file})
11
+ return BaseCommand("InstallPlugin", **{"pluginFile": plugin_file})
12
12
 
13
13
 
14
14
  def reload_plugin(plugin: str):
@@ -18,7 +18,7 @@ def reload_plugin(plugin: str):
18
18
  """
19
19
  if not isinstance(plugin, str) or not plugin:
20
20
  raise TypeError("plugin must be a string")
21
- return BaseCommand("ReloadPlugin", **{"Plugin": plugin})
21
+ return BaseCommand("ReloadPlugin", **{"plugin": plugin})
22
22
 
23
23
 
24
24
  def set_plugin_data(plugin: str, key: str, value: str):
@@ -37,7 +37,7 @@ def set_plugin_data(plugin: str, key: str, value: str):
37
37
  if not isinstance(value, str):
38
38
  raise TypeError("value must be a string")
39
39
  return BaseCommand(
40
- "SetPluginData", **{"Plugin": plugin, "Key": key, "Value": value}
40
+ "SetPluginData", **{"Plugin": plugin, "key": key, "value": value}
41
41
  )
42
42
 
43
43
 
@@ -49,7 +49,7 @@ def start_plugin(plugin: str, save_state: bool = True):
49
49
  """
50
50
  if not isinstance(plugin, str) or not plugin:
51
51
  raise TypeError("plugin must be a string")
52
- return BaseCommand("StartPlugin", **{"Plugin": plugin, "SaveState": save_state})
52
+ return BaseCommand("StartPlugin", **{"plugin": plugin, "saveState": save_state})
53
53
 
54
54
 
55
55
  def start_plugins():
@@ -65,7 +65,7 @@ def stop_plugin(plugin: str, save_state: bool = True):
65
65
  """
66
66
  if not isinstance(plugin, str) or not plugin:
67
67
  raise TypeError("plugin must be a string")
68
- return BaseCommand("StopPlugin", **{"Plugin": plugin, "SaveState": save_state})
68
+ return BaseCommand("StopPlugin", **{"plugin": plugin, "saveState": save_state})
69
69
 
70
70
 
71
71
  def stop_plugins():
@@ -81,4 +81,4 @@ def uninstall_plugin(plugin: str):
81
81
  """
82
82
  if not isinstance(plugin, str) or not plugin:
83
83
  raise TypeError("plugin must be a string")
84
- return BaseCommand("UninstallPlugin", **{"Plugin": plugin})
84
+ return BaseCommand("UninstallPlugin", **{"plugin": plugin})
@@ -19,9 +19,9 @@ def add_user_session(access_level: AccessLevel, session_type: SessionType, origi
19
19
  return BaseCommand(
20
20
  "AddUserSession",
21
21
  **{
22
- "AccessLevel": access_level,
23
- "SessionType": session_type,
24
- "Origin": origin,
22
+ "accessLevel": access_level,
23
+ "sessionType": session_type,
24
+ "origin": origin,
25
25
  },
26
26
  )
27
27
 
@@ -33,4 +33,4 @@ def remove_user_session(session_id: int):
33
33
  """
34
34
  if not isinstance(session_id, int):
35
35
  raise TypeError("session_id must be an integer")
36
- return BaseCommand("RemoveUserSession", **{"Id": session_id})
36
+ return BaseCommand("RemoveUserSession", **{"id": session_id})
@@ -41,7 +41,8 @@ def intercept_init_message(
41
41
  channels: List[CodeChannel],
42
42
  filters: List[str],
43
43
  priority_codes: bool,
44
- auto_flush: bool = True):
44
+ auto_flush: bool = True,
45
+ auto_evaluate_expression: bool = True):
45
46
  """
46
47
  Enter interception mode
47
48
  Whenever a code is received, the connection must respond with one of
@@ -62,15 +63,19 @@ def intercept_init_message(
62
63
  is specified.
63
64
  This option makes extra Flush calls in the interceptor implementation obsolete.
64
65
  It is highly recommended to enable this in order to avoid potential deadlocks when dealing with macros!
66
+ :param auto_evaluate_expression: Automatically evaluate expression parameters to their final values
67
+ before sending it over to the client.
68
+ This requires auto_flush to be True and happens when the remaining codes have been processed.
65
69
  """
66
70
  return ClientInitMessage(
67
71
  ConnectionMode.INTERCEPT,
68
72
  **{
69
- "InterceptionMode": intercept_mode,
70
- "Channels": channels,
71
- "AutoFlush": auto_flush,
72
- "Filters": filters,
73
- "PriorityCodes": priority_codes,
73
+ "interceptionMode": intercept_mode,
74
+ "channels": channels,
75
+ "autoFlush": auto_flush,
76
+ "autoEvaluateExpressions": auto_evaluate_expression,
77
+ "filters": filters,
78
+ "priorityCodes": priority_codes,
74
79
  },
75
80
  )
76
81
 
@@ -85,8 +90,8 @@ def subscribe_init_message(subscription_mode: SubscriptionMode, filter_string: s
85
90
  return ClientInitMessage(
86
91
  ConnectionMode.SUBSCRIBE,
87
92
  **{
88
- "SubscriptionMode": subscription_mode,
89
- "Filter": filter_string,
90
- "Filters": filter_list,
93
+ "subscriptionMode": subscription_mode,
94
+ "filter": filter_string,
95
+ "filters": filter_list,
91
96
  },
92
97
  )
@@ -21,6 +21,9 @@ class InterceptConnection(BaseCommandConnection):
21
21
  in case a code filter is specified.
22
22
  This option makes extra Flush calls in the interceptor implementation obsolete.
23
23
  It is highly recommended to enable this in order to avoid potential deadlocks when dealing with macros!
24
+ :param auto_evaluate_expression: Automatically evaluate expression parameters to their final values
25
+ before sending it over to the client.
26
+ This requires auto_flush to be True and happens when the remaining codes have been processed.
24
27
  :param priority_codes: Defines if priority codes may be intercepted (e.g. M122 or M999)
25
28
  :param debug: Whether debugging output is turned on for this connection
26
29
  """
@@ -31,6 +34,7 @@ class InterceptConnection(BaseCommandConnection):
31
34
  channels: List[CodeChannel] = None,
32
35
  filters: List[str] = None,
33
36
  auto_flush: bool = True,
37
+ auto_evaluate_expression: bool = True,
34
38
  priority_codes: bool = False,
35
39
  debug: bool = False,
36
40
  ):
@@ -39,12 +43,18 @@ class InterceptConnection(BaseCommandConnection):
39
43
  self.channels = channels if channels is not None else CodeChannel.list()
40
44
  self.filters = filters
41
45
  self.auto_flush = auto_flush
46
+ self.auto_evaluate_expression = auto_evaluate_expression
42
47
  self.priority_codes = priority_codes
43
48
 
44
49
  def connect(self, socket_file: str = SOCKET_FILE): # noqa
45
50
  """Establishes a connection to the given UNIX socket file"""
46
51
  iim = client_init_messages.intercept_init_message(
47
- self.interception_mode, self.channels, self.filters, self.priority_codes, self.auto_flush
52
+ self.interception_mode,
53
+ self.channels,
54
+ self.filters,
55
+ self.priority_codes,
56
+ self.auto_flush,
57
+ self.auto_evaluate_expression
48
58
  )
49
59
  return super().connect(iim, socket_file)
50
60
 
@@ -5,11 +5,24 @@ class Accelerometer(ModelObject):
5
5
  """This represents an accelerometer"""
6
6
  def __init__(self):
7
7
  super(Accelerometer, self).__init__()
8
+ # Orientation of the accelerometer
9
+ # See https://docs.duet3d.com/en/Duet3D_hardware/Accessories/Duet3D_Accelerometer#orientation for a list of orientations
10
+ self._orientation = 20
8
11
  # Number of collected data points in the last run or 0 if it failed
9
12
  self._points = 0
10
13
  # Number of completed sampling runs
11
14
  self._runs = 0
12
15
 
16
+ @property
17
+ def orientation(self) -> int:
18
+ """Orientation of the accelerometer
19
+ See https://docs.duet3d.com/en/Duet3D_hardware/Accessories/Duet3D_Accelerometer#orientation for a list of orientations"""
20
+ return self._orientation
21
+
22
+ @orientation.setter
23
+ def orientation(self, value):
24
+ self._orientation = int(value)
25
+
13
26
  @property
14
27
  def points(self) -> int:
15
28
  """Number of collected data points in the last run or 0 if it failed"""
@@ -1,10 +1,11 @@
1
1
  from enum import Enum
2
- from typing import List, Union
2
+ from typing import List, Optional
3
3
 
4
4
  from .accelerometer import Accelerometer
5
5
  from .board_closed_loop import BoardClosedLoop
6
6
  from .direct_display import DirectDisplay
7
7
  from .driver import Driver
8
+ from .inductive_sensor import InductiveSensor
8
9
  from .min_max_current import MinMaxCurrent
9
10
  from ..model_collection import ModelCollection
10
11
  from ..model_object import ModelObject
@@ -42,6 +43,8 @@ class Board(ModelObject):
42
43
  closed_loop = wrap_model_property('closed_loop', BoardClosedLoop)
43
44
  # Details about a connected display or None if none is connected
44
45
  direct_display = wrap_model_property('direct_display', DirectDisplay)
46
+ # Information about an inductive sensor or None if not present
47
+ inductive_sensor = wrap_model_property('inductive_sensor', InductiveSensor)
45
48
  # Minimum, maximum, and current temperatures of the MCU or None if unknown
46
49
  mcu_temp = wrap_model_property('mcu_temp', MinMaxCurrent)
47
50
  # Minimum, maximum, and current voltages on the 12V rail or None if unknown
@@ -72,11 +75,15 @@ class Board(ModelObject):
72
75
  self._firmware_name = ""
73
76
  # Version of the firmware build
74
77
  self._firmware_version = ""
78
+ # Amount of free RAM on this board (in bytes or null if unknown)
79
+ self._free_ram = None
75
80
  # Filename of the IAP binary that is used for updates from the SBC or None if unsupported
76
81
  self._iap_file_name_SBC = None
77
82
  # Filename of the IAP binary that is used for updates from the SD card or None if unsupported
78
83
  # This is only available for the mainboard (first board item)
79
84
  self._iap_file_name_SD = None
85
+ # Information about an inductive sensor or None if not present
86
+ self._inductive_sensor = None
80
87
  # Maximum number of heaters this board can control
81
88
  self._max_heaters = 0
82
89
  # Maximum number of motors this board can drive
@@ -104,7 +111,7 @@ class Board(ModelObject):
104
111
  self._wifi_firmware_file_name = None
105
112
 
106
113
  @property
107
- def bootloader_file_name(self) -> Union[str, None]:
114
+ def bootloader_file_name(self) -> Optional[str]:
108
115
  """Filename of the bootloader binary or None if unknown"""
109
116
  return self._bootloader_file_name
110
117
 
@@ -113,7 +120,7 @@ class Board(ModelObject):
113
120
  self._bootloader_file_name = str(value) if value is not None else None
114
121
 
115
122
  @property
116
- def can_address(self) -> Union[int, None]:
123
+ def can_address(self) -> Optional[int]:
117
124
  """CAN address of this board or None if not applicable"""
118
125
  return self._can_address
119
126
 
@@ -122,7 +129,7 @@ class Board(ModelObject):
122
129
  self._can_address = int(value) if value is not None else None
123
130
 
124
131
  @property
125
- def drivers(self) -> Union[List[Driver], None]:
132
+ def drivers(self) -> Optional[List[Driver]]:
126
133
  """Drivers of this board"""
127
134
  return self._drivers
128
135
 
@@ -167,7 +174,16 @@ class Board(ModelObject):
167
174
  self._firmware_version = str(value)
168
175
 
169
176
  @property
170
- def iap_file_name_SBC(self) -> Union[str, None]:
177
+ def free_ram(self) -> Optional[int]:
178
+ """Amount of free RAM on this board (in bytes or null if unknown)"""
179
+ return self._free_ram
180
+
181
+ @free_ram.setter
182
+ def free_ram(self, value):
183
+ self._free_ram = None if value is None else int(value)
184
+
185
+ @property
186
+ def iap_file_name_SBC(self) -> Optional[str]:
171
187
  """Filename of the IAP binary that is used for updates from the SBC or None if unsupported"""
172
188
  return self._iap_file_name_SBC
173
189
 
@@ -176,7 +192,7 @@ class Board(ModelObject):
176
192
  self._iap_file_name_SBC = str(value) if value is not None else None
177
193
 
178
194
  @property
179
- def iap_file_name_SD(self) -> Union[str, None]:
195
+ def iap_file_name_SD(self) -> Optional[str]:
180
196
  """Filename of the IAP binary that is used for updates from the SD card or None if unsupported
181
197
  This is only available for the mainboard (first board item)"""
182
198
  return self._iap_file_name_SD
@@ -256,7 +272,7 @@ class Board(ModelObject):
256
272
  self._supports_direct_display = bool(value)
257
273
 
258
274
  @property
259
- def unique_id(self) -> Union[str, None]:
275
+ def unique_id(self) -> Optional[str]:
260
276
  """Unique identifier of the board or None if unknown"""
261
277
  return self._unique_id
262
278
 
@@ -0,0 +1,9 @@
1
+ from ..model_object import ModelObject
2
+
3
+
4
+ class InductiveSensor(ModelObject):
5
+ """"""
6
+
7
+ def __init__(self):
8
+ super(InductiveSensor, self).__init__()
9
+ # still empty
@@ -23,6 +23,8 @@ class Fan(ModelObject):
23
23
  self._requested_value = 0
24
24
  # Current RPM of this fan or -1 if unknown/unset
25
25
  self._rpm = -1
26
+ # Pulses per tacho revolution
27
+ self._tacho_ppr = 2.0
26
28
  # Thermostatic control parameters
27
29
  self._thermostatic = FanThermostaticControl()
28
30
 
@@ -99,6 +101,15 @@ class Fan(ModelObject):
99
101
  def rpm(self, value):
100
102
  self._rpm = int(value)
101
103
 
104
+ @property
105
+ def tacho_ppr(self) -> float:
106
+ """Pulses per tacho revolution"""
107
+ return self._tacho_ppr
108
+
109
+ @tacho_ppr.setter
110
+ def tacho_ppr(self, value):
111
+ self._tacho_ppr = float(value)
112
+
102
113
  @property
103
114
  def thermostatic(self) -> FanThermostaticControl:
104
115
  """Thermostatic control parameters"""
@@ -26,6 +26,26 @@ class AxisLetter(str, Enum):
26
26
  d = 'd'
27
27
  e = 'e'
28
28
  f = 'f'
29
+ g = 'g'
30
+ h = 'h'
31
+ i = 'i'
32
+ j = 'j'
33
+ k = 'k'
34
+ l = 'l'
35
+ m = 'm'
36
+ n = 'n'
37
+ o = 'o'
38
+ p = 'p'
39
+ q = 'q'
40
+ r = 'r'
41
+ s = 's'
42
+ t = 't'
43
+ u = 'u'
44
+ v = 'v'
45
+ w = 'w'
46
+ x = 'x'
47
+ y = 'y'
48
+ z = 'z'
29
49
  none = ''
30
50
 
31
51
 
@@ -23,10 +23,10 @@ class InputShapingType(str, Enum):
23
23
  zvddd = "zvddd"
24
24
 
25
25
  # EI2 (2-hump)
26
- ei2 = "ei2"
26
+ ei2 = "eI2"
27
27
 
28
28
  # EI3 (3-hump)
29
- ei3 = "ei3"
29
+ ei3 = "eI3"
30
30
 
31
31
  # Custom
32
32
  custom = "custom"
@@ -5,17 +5,17 @@ class MoveSegmentation(ModelObject):
5
5
  """Move segmentation parameters"""
6
6
  def __init__(self):
7
7
  super().__init__()
8
- self._segments_per_sec = 0
9
- self._min_segment_length = 0
8
+ self._segments_per_sec = 0.0
9
+ self._min_segment_length = 0.0
10
10
 
11
11
  @property
12
- def segments_per_sec(self) -> int:
12
+ def segments_per_sec(self) -> float:
13
13
  """Number of segments per second"""
14
14
  return self._segments_per_sec
15
15
 
16
16
  @segments_per_sec.setter
17
17
  def segments_per_sec(self, value):
18
- self._segments_per_sec = int(value)
18
+ self._segments_per_sec = float(value)
19
19
 
20
20
  @property
21
21
  def min_segment_length(self) -> float:
@@ -20,6 +20,7 @@ class PluginManifest(ModelObject):
20
20
  self._name = None
21
21
  self._rrf_version = None
22
22
  self._sbc_auto_restart = False
23
+ self._sbc_config_files = []
23
24
  self._sbc_dsf_version = None
24
25
  self._sbc_executable = None
25
26
  self._sbc_executable_arguments = []
@@ -137,6 +138,13 @@ class PluginManifest(ModelObject):
137
138
  @sbc_auto_restart.setter
138
139
  def sbc_auto_restart(self, value):
139
140
  self._sbc_auto_restart = bool(value)
141
+
142
+ @property
143
+ def sbc_config_files(self) -> List[str]:
144
+ """List of files in the sys or virtual SD directory that should not be overwritten on upgrade
145
+ The file may be specified either relative to 0:/sys directory (e.g. motion.conf) or relative to the
146
+ virtual SD directory (e.g. sys/motion.conf). Drive indices as in 0:/sys/motion.conf are not allowed!"""
147
+ return self._sbc_config_files
140
148
 
141
149
  @property
142
150
  def sbc_dsf_version(self) -> str:
@@ -13,6 +13,7 @@ class DSF(ModelObject):
13
13
  super().__init__()
14
14
  self._build_date_time = ""
15
15
  self._http_endpoints = ModelCollection(HttpEndpoint)
16
+ self._is64bit = False
16
17
  self._plugin_support = False
17
18
  self._root_plugin_support = False
18
19
  self._user_sessions = ModelCollection(UserSession)
@@ -27,6 +28,15 @@ class DSF(ModelObject):
27
28
  def build_date_time(self, value):
28
29
  self._build_date_time = str(value)
29
30
 
31
+ @property
32
+ def is64bit(self) -> bool:
33
+ """Indicates if the process is 64-bit"""
34
+ return self._is64bit
35
+
36
+ @is64bit.setter
37
+ def is64bit(self, value):
38
+ self._is64bit = bool(value)
39
+
30
40
  @property
31
41
  def http_endpoints(self) -> List[HttpEndpoint]:
32
42
  """List of registered third-party HTTP endpoints"""
@@ -14,9 +14,11 @@ class AnalogSensor(ModelObject):
14
14
  self._c = None
15
15
  self._last_reading = None
16
16
  self._name = None
17
+ self._offset_adj = 0.0
17
18
  self._port = None
18
19
  self._r_25 = None
19
20
  self._r_ref = None
21
+ self._slope_adj = 0.0
20
22
  self._state = TemperatureError.ok
21
23
  self._type = AnalogSensorType.Unknown
22
24
 
@@ -55,6 +57,16 @@ class AnalogSensor(ModelObject):
55
57
  @name.setter
56
58
  def name(self, value):
57
59
  self._name = str(value) if value is not None else None
60
+
61
+ @property
62
+ def offset_adj(self) -> float:
63
+ """Offset adjustment (in K)
64
+ See also M308 U"""
65
+ return self._offset_adj
66
+
67
+ @offset_adj.setter
68
+ def offset_adj(self, value):
69
+ self._offset_adj = float(value)
58
70
 
59
71
  @property
60
72
  def port(self) -> Union[str, None]:
@@ -83,6 +95,16 @@ class AnalogSensor(ModelObject):
83
95
  def r_ref(self, value):
84
96
  self._r_ref = float(value) if value is not None else None
85
97
 
98
+ @property
99
+ def slope_adj(self) -> float:
100
+ """Slope adjustment factor
101
+ See also M308 V"""
102
+ return self._slope_adj
103
+
104
+ @slope_adj.setter
105
+ def slope_adj(self, value):
106
+ self._slope_adj = float(value)
107
+
86
108
  @property
87
109
  def state(self) -> TemperatureError:
88
110
  """State of this sensor"""
@@ -1,4 +1,4 @@
1
- from typing import List, Union
1
+ from typing import List, Optional
2
2
 
3
3
  from .probe_type import ProbeType
4
4
  from ..model_object import ModelObject
@@ -20,6 +20,7 @@ class Probe(ModelObject):
20
20
  self._is_calibrated = None
21
21
  self._last_stop_height = 0
22
22
  self._max_probe_count = 1
23
+ self._measured_height = None
23
24
  self._offsets = [0, 0]
24
25
  self._recovery_time = 0
25
26
  self._scan_coefficients = None
@@ -33,7 +34,7 @@ class Probe(ModelObject):
33
34
  self._value = []
34
35
 
35
36
  @property
36
- def calib_a(self) -> Union[float, None]:
37
+ def calib_a(self) -> Optional[float]:
37
38
  """Linear coefficient for scanning probes"""
38
39
  return self._calib_a
39
40
 
@@ -42,7 +43,7 @@ class Probe(ModelObject):
42
43
  self._calib_a = float(value) if value is not None else None
43
44
 
44
45
  @property
45
- def calib_b(self) -> Union[float, None]:
46
+ def calib_b(self) -> Optional[float]:
46
47
  """Quadratic coefficient for scanning probes"""
47
48
  return self._calib_b
48
49
 
@@ -97,7 +98,7 @@ class Probe(ModelObject):
97
98
  return self._dive_heights
98
99
 
99
100
  @property
100
- def is_calibrated(self) -> Union[bool, None]:
101
+ def is_calibrated(self) -> Optional[bool]:
101
102
  """Indicates if the scanning probe is calibrated"""
102
103
  return self._is_calibrated
103
104
 
@@ -123,6 +124,15 @@ class Probe(ModelObject):
123
124
  def max_probe_count(self, value):
124
125
  self._max_probe_count = int(value)
125
126
 
127
+ @property
128
+ def measured_height(self) -> Optional[float]:
129
+ """Measured height (only applicable for scanning probes, in mm or null)"""
130
+ return self._measured_height
131
+
132
+ @measured_height.setter
133
+ def measured_height(self, value):
134
+ self._measured_height = None if value is None else float(value)
135
+
126
136
  @property
127
137
  def offsets(self) -> List[float]:
128
138
  """X+Y offsets (in mm)"""
@@ -144,7 +154,7 @@ class Probe(ModelObject):
144
154
  return self._speeds[0]
145
155
 
146
156
  @property
147
- def scan_coefficients(self) -> Union[List[float], None]:
157
+ def scan_coefficients(self) -> Optional[List[float]]:
148
158
  """Coefficients for the scanning Z-probe (4 elements, if applicable)"""
149
159
  return self._scan_coefficients
150
160
 
@@ -154,7 +164,8 @@ class Probe(ModelObject):
154
164
 
155
165
  @property
156
166
  def speeds(self) -> List[float]:
157
- """Fast and slow probing speeds (in mm/s)"""
167
+ """Fast and slow probing speeds (in mm/s)
168
+ Scanning probes may have three speeds where the last one is the movement speed while probing heightmaps"""
158
169
  return self._speeds
159
170
 
160
171
  @speeds.setter
@@ -36,3 +36,6 @@ class ProbeType(IntEnum):
36
36
 
37
37
  # Z motor stall detection
38
38
  ZMotorStall = 10
39
+
40
+ # Scanning Z Probe
41
+ ScanningZProbe = 11
@@ -1,6 +1,8 @@
1
1
  from .spindle_state import SpindleState
2
2
  from ..model_object import ModelObject
3
3
 
4
+ from typing import Union
5
+
4
6
 
5
7
  class Spindle(ModelObject):
6
8
  """Information about a CNC spindles"""
@@ -29,85 +31,85 @@ class Spindle(ModelObject):
29
31
  self._state = SpindleState.unconfigured
30
32
 
31
33
  @property
32
- def active(self) -> int:
34
+ def active(self) -> Union[int, None]:
33
35
  """Active RPM"""
34
36
  return self._active
35
37
 
36
38
  @active.setter
37
- def active(self, value: int):
38
- self._active = int(value)
39
+ def active(self, value: Union[int, None]):
40
+ self._active = None if value is None else int(value)
39
41
 
40
42
  @property
41
- def can_reverse(self) -> bool:
43
+ def can_reverse(self) -> Union[bool, None]:
42
44
  """Flags whether the spindles may spin in reverse direction"""
43
45
  return self._can_reverse
44
46
 
45
47
  @can_reverse.setter
46
- def can_reverse(self, value: bool):
47
- self._can_reverse = bool(value)
48
+ def can_reverse(self, value: Union[bool, None]):
49
+ self._can_reverse = None if value is None else bool(value)
48
50
 
49
51
  @property
50
- def current(self) -> int:
52
+ def current(self) -> Union[int, None]:
51
53
  """Current RPM, negative if anticlockwise direction"""
52
54
  return self._current
53
55
 
54
56
  @current.setter
55
- def current(self, value: int):
56
- self._current = int(value)
57
+ def current(self, value: Union[int, None]):
58
+ self._current = None if value is None else int(value)
57
59
 
58
60
  @property
59
- def frequency(self) -> int:
61
+ def frequency(self) -> Union[int, None]:
60
62
  """Frequency (in Hz)"""
61
63
  return self._frequency
62
64
 
63
65
  @frequency.setter
64
- def frequency(self, value: int):
65
- self._frequency = int(value)
66
+ def frequency(self, value: Union[int, None]):
67
+ self._frequency = None if value is None else int(value)
66
68
 
67
69
  @property
68
- def idle_pwm(self) -> float:
70
+ def idle_pwm(self) -> Union[float, None]:
69
71
  """Idle PWM value (0..1)"""
70
72
  return self._idle_pwm
71
73
 
72
74
  @idle_pwm.setter
73
- def idle_pwm(self, value: float):
74
- self._idle_pwm = float(value)
75
+ def idle_pwm(self, value: Union[float, None]):
76
+ self._idle_pwm = None if value is None else float(value)
75
77
 
76
78
  @property
77
- def max(self) -> int:
79
+ def max(self) -> Union[int, None]:
78
80
  """Maximum RPM"""
79
81
  return self._max
80
82
 
81
83
  @max.setter
82
- def max(self, value: int):
83
- self._max = int(value)
84
+ def max(self, value: Union[int, None]):
85
+ self._max = None if value is None else int(value)
84
86
 
85
87
  @property
86
- def max_pwm(self) -> float:
88
+ def max_pwm(self) -> Union[float, None]:
87
89
  """Maximum PWM value when turned on (0..1)"""
88
90
  return self._max_pwm
89
91
 
90
92
  @max_pwm.setter
91
- def max_pwm(self, value: float):
92
- self._max_pwm = float(value)
93
+ def max_pwm(self, value: Union[float, None]):
94
+ self._max_pwm = None if value is None else float(value)
93
95
 
94
96
  @property
95
- def min(self) -> int:
97
+ def min(self) -> Union[int, None]:
96
98
  """Minimum RPM when turned on"""
97
99
  return self._min
98
100
 
99
101
  @min.setter
100
- def min(self, value: int):
101
- self._min = int(value)
102
+ def min(self, value: Union[int, None]):
103
+ self._min = None if value is None else int(value)
102
104
 
103
105
  @property
104
- def min_pwm(self) -> float:
106
+ def min_pwm(self) -> Union[float, None]:
105
107
  """Minimum PWM value when turned on (0..1)"""
106
108
  return self._min_pwm
107
109
 
108
110
  @min_pwm.setter
109
- def min_pwm(self, value: float):
110
- self._min_pwm = float(value)
111
+ def min_pwm(self, value: Union[float, None]):
112
+ self._min_pwm = None if value is None else float(value)
111
113
 
112
114
  @property
113
115
  def state(self) -> SpindleState:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dsf-python
3
- Version: 3.5.0.2rc2
3
+ Version: 3.6.0b2
4
4
  Summary: Python interface to access DuetSoftwareFramework
5
5
  Home-page: https://github.com/Duet3D/dsf-python
6
6
  Author: Duet3D Ltd.
@@ -27,8 +27,8 @@ Description-Content-Type: text/markdown
27
27
  License-File: LICENSE
28
28
  Requires-Dist: python-dateutil
29
29
  Provides-Extra: dev
30
- Requires-Dist: sphinx ; extra == 'dev'
31
- Requires-Dist: tox ; extra == 'dev'
30
+ Requires-Dist: sphinx; extra == "dev"
31
+ Requires-Dist: tox; extra == "dev"
32
32
 
33
33
  # Duet Software Framework Python Bindings
34
34
 
@@ -36,7 +36,7 @@ This is also availabe as a [pip package on pypi](https://pypi.org/project/dsf-py
36
36
 
37
37
  Find out more about [Duet Software Framework](https://github.com/Duet3D/DuetSoftwareFramework).
38
38
 
39
- Find out more about [Duet Software Framework Python Bindings](https://github.com/Duet3D/dsf-python).
39
+ Examples of the [Duet Software Framework Python Bindings](https://github.com/Duet3D/dsf-python/tree/main/examples).
40
40
 
41
41
  Get in touch with the community at [Duet Software Framework Forum](https://forum.duet3d.com/category/31/dsf-development) for bug reports, discussion and any kind of exchange.
42
42
 
@@ -4,31 +4,31 @@ dsf/http.py,sha256=ZOz0dRGWyxgWDoS-1c3DqQkNmyAZuhPi9y6vtano-mU,5829
4
4
  dsf/utils.py,sha256=9GfGUu0sbeoJBJ6RuRIpI-BZ-1PKIMWaemWliknt1v0,2571
5
5
  dsf/commands/__init__.py,sha256=O4_mLIDnLnN3zLxvH8_3mx3Yx2rU4f2Ha3cm9PmFaS4,198
6
6
  dsf/commands/base_command.py,sha256=rwjaXeZ38yayAH7gYBm9Nf1xpYsg38Ul6oMexSkuCIo,378
7
- dsf/commands/code.py,sha256=UHIBBtJDVR0QJkiYpuo3TA57cvtfIMWzE8m2Z0YY-uE,5795
7
+ dsf/commands/code.py,sha256=4hP4vySeL_TQ8dbBIT-Xjbmn8amxpvW2IYEuLclzlgs,5877
8
8
  dsf/commands/code_channel.py,sha256=RiwN-eDKpFdvus7h8vxbpGRKigleDXUIbI1MZkjF4_8,1399
9
9
  dsf/commands/code_flags.py,sha256=dE7B5LrSdY2VBPquR2kF8PacjsR8ELC0BKOaPJMjPCM,2134
10
- dsf/commands/code_interception.py,sha256=sWWYVDMeOUojq8-4ElKyWlzaJj5L9_BfvfnogsdYByE,1076
10
+ dsf/commands/code_interception.py,sha256=0MD71Wq4c0Mss2VOgyKxjbj49f-DOkKOZDQ-Tz3K928,1076
11
11
  dsf/commands/code_parameter.py,sha256=7vjxgQI5LxaRRzXxEOYK_mk71fng7MKiTYBh-nZ-6h0,8145
12
12
  dsf/commands/code_type.py,sha256=NU8GNaN2AAdNRVc964yQCnlqo82E8QqJ-g31hsdOT80,456
13
13
  dsf/commands/condition_type.py,sha256=bml4YGcPdpk_TZ_aB7RHuS4o0XazpgNkuKMRcqW8XNU,563
14
- dsf/commands/files.py,sha256=feBbNtGkn_VAQuN3N6KhmCxT2OvworzYibLRgE-b9Hk,918
15
- dsf/commands/generic.py,sha256=Fvg1GUrDMKEr4iT-PLr3h27YneI9capymygqVOOIJ-g,5752
16
- dsf/commands/http_endpoints.py,sha256=TMqhtcvmyG92NQAZdziYRtWPtZUK1PjwuL7Onu6PPNM,2341
14
+ dsf/commands/files.py,sha256=wMFY3cbhfmyNh85cpBIgtqlxE7xhCk3QpawXgimBVd8,1062
15
+ dsf/commands/generic.py,sha256=hjTzFJVVjzxFSMgc3ou7AevwnQmNBrJ9WFjTXIq_8y0,5752
16
+ dsf/commands/http_endpoints.py,sha256=CevsLjAh_9GG6MQkAL7aFZKsuyRvYgNkiSCc5-jGv7g,2341
17
17
  dsf/commands/model_subscription.py,sha256=Dq4M7EfRjkHUcIbTrLjJRAxhAhMiawowLbEFS11NMEc,224
18
- dsf/commands/object_model.py,sha256=umDS0QBYke6kA_rjJzTghMUL0FZpW7m7FpgDd81AhCE,2522
19
- dsf/commands/packages.py,sha256=oAERVIeKdbFpkBiN30_yxz6R7npwnPuuhCg-YMeCH6g,712
20
- dsf/commands/plugins.py,sha256=xm5ZVF7fDEFNVLd2Q2v14EGLK6_qgcmjwkxKdrw5CcU,3020
18
+ dsf/commands/object_model.py,sha256=QDtxBbkJA7AozjicUtMAhBq9uGkB9_OHcZQIr8koJG4,2522
19
+ dsf/commands/packages.py,sha256=e7LObfz7xNygMPGi2A5o_F6OG1yFhN5fYO--U0tf5WM,712
20
+ dsf/commands/plugins.py,sha256=w_7YlIxj95w046vO89qGbAXyVzOBw_o-dlMuaqFE-JA,3020
21
21
  dsf/commands/responses.py,sha256=Q6jZwEKbmKkph96EepUdgD6LfY2VAX41MAaj6aJ1-XQ,1755
22
- dsf/commands/user_sessions.py,sha256=BKq8--kh_eoFWDJCL1byiJ4NV3HZ7h3C4jxDI8j2kWo,1312
22
+ dsf/commands/user_sessions.py,sha256=qFN_NfS8n2gVXqfdN0_kA3--kvtrX0ELYKtkxT1U7-E,1312
23
23
  dsf/connections/__init__.py,sha256=83E9M8yOZfdQqm196fnOaR7Wy4_IDYVhFwIl9BltsxI,1898
24
24
  dsf/connections/base_command_connection.py,sha256=kF-qhT_MJYey7wH2Rh1tA5LqauiFA_qNGS609in8FVA,9968
25
25
  dsf/connections/base_connection.py,sha256=U9UcGElF_68sK_7UCENpECvTgtBI2nbh1GTFWjRUrQg,5495
26
26
  dsf/connections/command_connection.py,sha256=siw-Rv2uOgE0DvNElbBpH8zGjjSVy0iSuNx5jBas8yM,478
27
27
  dsf/connections/exceptions.py,sha256=53NNjIs6fB6UtdcP0aGnIUQsH7fr5HwVM_21TDXjuZM,610
28
- dsf/connections/intercept_connection.py,sha256=2v2SuInq5oSp7FDLeGekjIc3fwztFuJy0Odi-0IlsEw,3033
28
+ dsf/connections/intercept_connection.py,sha256=sv3cPS8OT1w4wRlCrvpoIUgsu6f_cJ7to0GBQPflQBQ,3480
29
29
  dsf/connections/subscribe_connection.py,sha256=gxJ32Ojvp30d2UIgCG1udTZJTtVNHqJjAYOpr1fWwH0,2444
30
30
  dsf/connections/init_messages/__init__.py,sha256=EzPfwszMfvxl3lwrgq9HUDgqLPjRlkWgoBKme-DZMO8,56
31
- dsf/connections/init_messages/client_init_messages.py,sha256=uWBBrFUe7DT7LqRtudx66UB14QB8HvjCL0OCvFndK5c,3734
31
+ dsf/connections/init_messages/client_init_messages.py,sha256=3sdL07FXIEHegqhNedvGyHIEBImyReAYpA8wc91TpLs,4090
32
32
  dsf/connections/init_messages/server_init_message.py,sha256=87aMgtYa9n_XHa9ZKKoMYPxo1bJd41D_PEa2CR49YBE,1610
33
33
  dsf/object_model/__init__.py,sha256=UrzocKhApHnYUO8MQ3gyDNwuaEoXmwgUEe2vbx4o2RY,967
34
34
  dsf/object_model/model_collection.py,sha256=7K8C7bb5Sz_cVqlbKdGtgJi8fElJcrYjWFvizvlF9LQ,2008
@@ -37,11 +37,12 @@ dsf/object_model/model_object.py,sha256=ORySkN-m_geMjiolxwqmmvOM7QESHwn_yjHzozYm
37
37
  dsf/object_model/object_model.py,sha256=Sci1t4HYEhFLLPKq8wB0AM_2f9Qzle7QkgSzwmGjknI,5213
38
38
  dsf/object_model/utils.py,sha256=7QbKzCb4MzFmGSR5lpjx0iocg1jAETGHFx_k3y6Dff4,1602
39
39
  dsf/object_model/boards/__init__.py,sha256=LIdq7wTaYZdmDveMQlE8eyiaf9D7pA6XF7VmC3Axibo,541
40
- dsf/object_model/boards/accelerometer.py,sha256=rmEB27xCRABLxDQsNbG32x2uSTQpGoflaxrfpWEj-6g,794
40
+ dsf/object_model/boards/accelerometer.py,sha256=AVcNQpZHhEkF0jtNdQGKpEiypdiuKq9-M6_BGz9rsw8,1351
41
41
  dsf/object_model/boards/board_closed_loop.py,sha256=JXT0LDtiCYlInvE-39u-AG6AMDzvR4-DTx9vf_nTjL8,818
42
- dsf/object_model/boards/boards.py,sha256=diRAIMXTw2spWFvhLnITlYZOW3eS8x_Fuf_8bFoqh_Q,9386
42
+ dsf/object_model/boards/boards.py,sha256=uPV9zVP2BYQ5cpEFE8-mre4ud8EpHWM5I27jJwE-ixQ,10055
43
43
  dsf/object_model/boards/driver.py,sha256=Q9OEroanT1z96uSz4g7NLD5fBft0c0JyQPMJRcZl-EA,988
44
44
  dsf/object_model/boards/driver_closed_loop.py,sha256=204h78FV3VNnvDSZzRO_y3RFzWQoVSpd8eF9KvZE8d4,1958
45
+ dsf/object_model/boards/inductive_sensor.py,sha256=eYOwQxaDFVAEpELj7yNRPIvFddkeABwtLZy5WgX1BBU,183
45
46
  dsf/object_model/boards/min_max_current.py,sha256=3hgP_gawmxE49hF377zHmRLQnrOUo5fV8Y6n9y_UXc8,930
46
47
  dsf/object_model/boards/direct_display/__init__.py,sha256=MlEwefhOdonXekr5L1BqBDMrWLL3XrSB0PflRXEKn9U,428
47
48
  dsf/object_model/boards/direct_display/direct_display.py,sha256=FrOE8Q6gWCNfWjF9-LMbldZ7lKzNcx-0l8WW_3aKerg,721
@@ -53,7 +54,7 @@ dsf/object_model/directories/__init__.py,sha256=hA7GZngL3t5Fl7p95wQjlMmDbA_fKyNm
53
54
  dsf/object_model/directories/directories.py,sha256=fOg7wpl1ZG-2YKguqRgkyEwsKiA72s4v7OsgAmVE35E,2310
54
55
  dsf/object_model/fans/__init__.py,sha256=poaHZyeTxUTvvyATlGfoL6xcc5m8t2pm0od1vMRgZcw,128
55
56
  dsf/object_model/fans/fan_thermostatic_control.py,sha256=9V5p-Ek3CHv0QyyykxNeGfs5bdn0NZ_KSJ1OVFoxdek,1610
56
- dsf/object_model/fans/fans.py,sha256=Tn_GeuJ40_4iH1mmZCpW86vO9Usc_HWdZtJki8xuqes,2951
57
+ dsf/object_model/fans/fans.py,sha256=6FAmgBOA0uqd5RPuCJRcQ4q7Ts3UdtMMT8g8Rpefnnw,3235
57
58
  dsf/object_model/heat/__init__.py,sha256=iT38cPXNDOdXy0upTjKlF5J2z1aETRvZpEYwlf7yCdw,388
58
59
  dsf/object_model/heat/heat.py,sha256=-ZZ4rKIBss9Ax62dr5VIGbMSNzEI-iQbAvIp_rut3nM,1909
59
60
  dsf/object_model/heat/heater.py,sha256=LXTuoI8Igjc6kF_f7PDaPWMn-ImeLePeS80Zc0jswbU,5573
@@ -81,12 +82,12 @@ dsf/object_model/limits/limits.py,sha256=hYZKO5X6ZcxwqBzloGrOMhLgqU0x4CQqtNsPm3f
81
82
  dsf/object_model/messages/__init__.py,sha256=GCFZZNH3R7kKpxvZE5g5S1RzzhmgSjfYTdyaxARt0p0,81
82
83
  dsf/object_model/messages/messages.py,sha256=cGHFC4KqDZki6mzUpRGiOFecaQb4v2OBbp8YI_lri08,2398
83
84
  dsf/object_model/move/__init__.py,sha256=SC9H4mw28BzaxdRVctJbQXSZFA3SzliiZMnpOcDx7K4,708
84
- dsf/object_model/move/axis.py,sha256=oOa1Tx6CT70if7grQnYegQCj3XwvdCZ4Frzhyu7eUVo,7805
85
+ dsf/object_model/move/axis.py,sha256=IWSjAEWMiFJ31-4VRCa5_B-XHRdnt5EZqXhlJ6kNIB8,8045
85
86
  dsf/object_model/move/current_move.py,sha256=Qlt7-d7SrsPbYkHKAz7_SeOsrrboKvPxbd1OpfZydek,2244
86
87
  dsf/object_model/move/driver_id.py,sha256=5iMNYRgViw5IcSYxrG2LNurA7ytDSXfBC8v4meAdO-k,2202
87
88
  dsf/object_model/move/extruder.py,sha256=fFr9XRG-ePTg4lTsNcgrdjeyJoduwgCSLOYTzMt9SUQ,5164
88
89
  dsf/object_model/move/extruder_non_linear.py,sha256=C8UUZuyvA32EmgtpZu2yNYVcuLg8guamgKgfg9mvqok,976
89
- dsf/object_model/move/input_shaping.py,sha256=84KOJgJDngN4EAHxyvjOT7n8ODJvO1R1PY0qz7ETW38,2593
90
+ dsf/object_model/move/input_shaping.py,sha256=kwOar7Bfi7RC1pB_OwQCntw7iYvvQw0cTM2ben5wdJ4,2593
90
91
  dsf/object_model/move/keepout_zone.py,sha256=eMP1ramG6cB-a1IJ89Y8BG3VVYIkfh_945jP4D9IAkA,1416
91
92
  dsf/object_model/move/microstepping.py,sha256=-9qWeoLihWPYQqJrAKz4CqvnaNj-zYAtYFVDVxJ0iaE,762
92
93
  dsf/object_model/move/motors_idle_control.py,sha256=ihKMYCm7yTiIkqsA9KCLZpU6FgdkcS5h_6JmcTH1AvU,844
@@ -96,7 +97,7 @@ dsf/object_model/move/move_compensation.py,sha256=A_3CMgd-tjKLuKbDyfrZUGgCAfgA8h
96
97
  dsf/object_model/move/move_deviations.py,sha256=rnS6PC2hf9JYaoYgZ8OqTNz9vnEoZKWQ2-tU-yg9org,682
97
98
  dsf/object_model/move/move_queue_item.py,sha256=u1PSUU8Ti3zPz2M0WSIJXVfFg0dySgQUtE4ycsOpJUs,859
98
99
  dsf/object_model/move/move_rotation.py,sha256=P_rojtqWrQn1HaqMgLfcEm1vn05tTXjRetar0xSYM0g,704
99
- dsf/object_model/move/move_segmentation.py,sha256=ENWhu6xIu6Lf52p4AmkLgDScppHDeZMM1nkOcoRb5Fc,782
100
+ dsf/object_model/move/move_segmentation.py,sha256=xXd2vw22Gjv2staN3VamngnaDmFaS3aQxpuoI5Bu7ac,790
100
101
  dsf/object_model/move/probe_grid.py,sha256=bSPjMQ8FxM0S2M_9z4uK9pkexrnN39KAkqLKXNLXlXg,1284
101
102
  dsf/object_model/move/skew.py,sha256=BVvh_m2nlUdgc5OK4y9EyKTnTeA-bhIlsCOmPHlQSKI,1512
102
103
  dsf/object_model/move/kinematics/__init__.py,sha256=hG-K2GELZ8dt429LhXXaTzso_qAlIN-zUxQi9ba8Gnw,666
@@ -117,7 +118,7 @@ dsf/object_model/network/network_interface_type.py,sha256=TZyP1mmR8IlhlDhOqy4L3Y
117
118
  dsf/object_model/network/network_protocol.py,sha256=qMZQcgLST4oMk6KjWPHB3NC6SHBVdl2IrrFfHzKskys,333
118
119
  dsf/object_model/network/network_state.py,sha256=SkjP-bdfdtS4-egQdXLh7rRNL6gG9OJeU4fIvKkKidk,867
119
120
  dsf/object_model/plugins/__init__.py,sha256=bWA02R8c5xUVGV2bTU4X2NkRFrv_ox1APKR-TCFALX8,116
120
- dsf/object_model/plugins/plugin_manifest.py,sha256=A4k5KDkJndOdIcmEYz0_laNB7YhQ6HI1Legk4um4nyk,8797
121
+ dsf/object_model/plugins/plugin_manifest.py,sha256=vGn83nD-x0M1Jvz2lr_Zd8MO0uXKrlwR8kYkbQOO3NU,9261
121
122
  dsf/object_model/plugins/plugins.py,sha256=EYkHycuEO4K92xte_znIw0Oq4XPRVPWzS71CZyYcUwA,999
122
123
  dsf/object_model/plugins/sbc_permissions.py,sha256=2oyLIG81GE2nCzkUa-uSH_XXsveEypFOCRhMWFc-sss,2514
123
124
  dsf/object_model/sbc/__init__.py,sha256=zpiPaAdXcJEyWSZvy6Ur_NYCkqFGO5BB5u8bxVQh20s,69
@@ -125,7 +126,7 @@ dsf/object_model/sbc/cpu.py,sha256=vtjZRqrM4L81i07SGg7OxmwkXaA5BRoT2GZkiMLSaeo,1
125
126
  dsf/object_model/sbc/memory.py,sha256=FKGXsUj5zpJQx4HkZ4js6Ax1ruZcC9xDCvBrnjPnYSs,743
126
127
  dsf/object_model/sbc/sbc.py,sha256=Xdjpwie9F2Jkhgap7TCXZZw12obeET_GBuxkssPpMFE,2998
127
128
  dsf/object_model/sbc/dsf/__init__.py,sha256=_cJkKrrhT_nJcdE9jQyNr75_OjqNTwu3gOGrO0GD1A8,144
128
- dsf/object_model/sbc/dsf/dsf.py,sha256=C097Wv0AFpAWncr67OWkfJPzdZ5ow1wQpKNr7BpAC9E,2046
129
+ dsf/object_model/sbc/dsf/dsf.py,sha256=utbvpJnIzucaI6n5jnRbE2s6TdInI7sR4fqqtfajP-c,2287
129
130
  dsf/object_model/sbc/dsf/http_endpoint.py,sha256=hQIRNN7SLdeQOpzgTYF5nU5AaHDs2KORsw6ciNm-q8o,2305
130
131
  dsf/object_model/sbc/dsf/http_endpoint_type.py,sha256=JjtQAotrJFs6PowZkW2mrJXkIE-zqg-I3WdCcDjzRPM,554
131
132
  dsf/object_model/sbc/dsf/user_sessions/__init__.py,sha256=c8aLd_vyow01xMNVwh-Z7p0KnsvRZ5MaQ73cunMV_Ac,173
@@ -133,13 +134,13 @@ dsf/object_model/sbc/dsf/user_sessions/access_level.py,sha256=gCVS0JuVJ40i1NSYAx
133
134
  dsf/object_model/sbc/dsf/user_sessions/session_type.py,sha256=_eBDauWwEoJdO4zUs5xNgFC4yqn5LUWjG7BLJGaQ7cQ,229
134
135
  dsf/object_model/sbc/dsf/user_sessions/user_sessions.py,sha256=J76IEm-ZBAt8ZQf17OXpgkY0KX0Yn3daFArkCMB2FYg,2364
135
136
  dsf/object_model/sensors/__init__.py,sha256=Yb9OkMQI3jNF5Yx84UwMjQreckhraA8PRH0uLfaTAFg,283
136
- dsf/object_model/sensors/analog_sensor.py,sha256=slBz8Dw0k1K4pfhrR7j_4AYFwqq43_h1XWmlSliIC7E,3194
137
+ dsf/object_model/sensors/analog_sensor.py,sha256=LKmRbolM8qNa-YkFSc521kHNFBup90AXvn_7n0tGw2A,3745
137
138
  dsf/object_model/sensors/analog_sensor_type.py,sha256=IPB4--lexKFxi8_Ue8k6Cv_veHkWoGilvT2RJJucMbY,1152
138
139
  dsf/object_model/sensors/endstop.py,sha256=QqL4WJ-bmmvAYTf6keS_wlL7w3nkCXEs59UBqJVySxs,1527
139
140
  dsf/object_model/sensors/endstop_type.py,sha256=XvdO-aJtUGuqtJzOx7DStnzjT-WbbJWdbexDJHoxdJw,474
140
141
  dsf/object_model/sensors/gp_input_port.py,sha256=xNtBsEs8m7ws6nAAKqH_Wan9CNMY3RdeZ_jpBRNvcK8,413
141
- dsf/object_model/sensors/probe.py,sha256=jJYkwW103LCNQpDaFNKrdx4uuOCYjA2SP4nwWNxfTEU,6782
142
- dsf/object_model/sensors/probe_type.py,sha256=MzGQnB-Nm35J2bYJbUuRkEosdgTYYhN5Vu_f1LYyqZI,978
142
+ dsf/object_model/sensors/probe.py,sha256=mjkKcPRLxoPASn_D1oHkT8Hnk8O3iC99Xb-mQ8Lkuz8,7258
143
+ dsf/object_model/sensors/probe_type.py,sha256=eE4ImrNCQ41iz_dza7hbLcfkoUdTIBD8Kei9wm2jEfA,1026
143
144
  dsf/object_model/sensors/sensors.py,sha256=W3lU-89QESx2jbg6_CRD6U8uw6UN136tPozSNpNCjCw,1333
144
145
  dsf/object_model/sensors/temperature_error.py,sha256=ahqOv7iRzLy88HvXMMRigZCbf3mkbbwYWdiZNnQ5rXI,1232
145
146
  dsf/object_model/sensors/filament_monitors/Duet3DFilamentMonitor.py,sha256=mYm_CWuKJeD63bOoO5npXQyHgCN-Xt6F0E8sTw8upPI,2301
@@ -153,7 +154,7 @@ dsf/object_model/sensors/filament_monitors/pulsed_filament_monitor.py,sha256=hu_
153
154
  dsf/object_model/sensors/filament_monitors/rotating_magnet_filament_monitor.py,sha256=TreikhdkGpyCZXYns0zXVnQLgPArmkvY-75maIEZx_g,3811
154
155
  dsf/object_model/spindles/__init__.py,sha256=YpC_jGR6TrfF3MPo4CeiUuu52AHz9vmYPcZhBAriNEM,109
155
156
  dsf/object_model/spindles/spindle_state.py,sha256=J76S84U9h-mICoFqp58KSPcfuVxoHuSsibtpeOMqnhw,334
156
- dsf/object_model/spindles/spindles.py,sha256=VnJ0LIaweeR7lrZ5oEDq9EP-4bqdiX796KzEC2fAFYA,3291
157
+ dsf/object_model/spindles/spindles.py,sha256=BNqwHG41DFdG2cSnHpMZvFwiUUimUdQ_Nm9CNE7fDWA,3794
157
158
  dsf/object_model/state/__init__.py,sha256=aPuQU1fvoaWUJxCkUkSREh8J3JqbzYSIdyGnSnmgW5U,310
158
159
  dsf/object_model/state/beep_request.py,sha256=-Ah0obdAmVvXLsqTQMPHFCT18_gBI_MesxMSkzSPTkQ,679
159
160
  dsf/object_model/state/gp_output_port.py,sha256=Dhr8We-HIJPqPTcDPzSItIb8w656ET5lO-knmHm_h5E,710
@@ -171,8 +172,8 @@ dsf/object_model/tools/tools.py,sha256=2wOEZlXswUnVBa0cuhyGYHz1z2R-mF25fi0a7WY3W
171
172
  dsf/object_model/volumes/__init__.py,sha256=XuRDty30gqn8jshASvclpxVTachXeAeJyo2-iHKEsKc,50
172
173
  dsf/object_model/volumes/volumes.py,sha256=gqbo5kUQo037A7Wv49vxnnaBhGlNjilJydjW8V2sKZ4,3073
173
174
  dsf/utility/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
174
- dsf_python-3.5.0.2rc2.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
175
- dsf_python-3.5.0.2rc2.dist-info/METADATA,sha256=O1hzKrUHFc-nXFALmWb4sCS-unL8XbzzX9UpbFpNYic,2044
176
- dsf_python-3.5.0.2rc2.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
177
- dsf_python-3.5.0.2rc2.dist-info/top_level.txt,sha256=hrm-wnKtms7vAmVuHX6jIj3C6G5p3uKCiXZH4HwJ4LA,4
178
- dsf_python-3.5.0.2rc2.dist-info/RECORD,,
175
+ dsf_python-3.6.0b2.dist-info/LICENSE,sha256=46mU2C5kSwOnkqkw9XQAJlhBL2JAf1_uCD8lVcXyMRg,7652
176
+ dsf_python-3.6.0b2.dist-info/METADATA,sha256=BwSRQmLS4RsuytQ4UH9CUUZYgfHcE4uByQaxIGXKdDU,2054
177
+ dsf_python-3.6.0b2.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
178
+ dsf_python-3.6.0b2.dist-info/top_level.txt,sha256=hrm-wnKtms7vAmVuHX6jIj3C6G5p3uKCiXZH4HwJ4LA,4
179
+ dsf_python-3.6.0b2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5