flashforge-python-api 1.0.2__py3-none-any.whl → 1.1.0__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 +62 -29
- flashforge/api/__init__.py +1 -0
- flashforge/api/constants/__init__.py +1 -0
- flashforge/api/constants/commands.py +1 -0
- flashforge/api/constants/endpoints.py +1 -0
- flashforge/api/controls/__init__.py +1 -0
- flashforge/api/controls/control.py +64 -61
- flashforge/api/controls/files.py +28 -26
- flashforge/api/controls/info.py +84 -85
- flashforge/api/controls/job_control.py +120 -82
- flashforge/api/controls/temp_control.py +14 -11
- flashforge/api/misc/__init__.py +1 -1
- flashforge/api/network/__init__.py +2 -1
- flashforge/api/network/utils.py +7 -8
- flashforge/client.py +131 -63
- flashforge/discovery/__init__.py +30 -3
- flashforge/discovery/discovery.py +637 -308
- flashforge/models/__init__.py +11 -10
- flashforge/models/machine_info.py +220 -100
- flashforge/models/responses.py +103 -43
- flashforge/tcp/__init__.py +25 -17
- flashforge/tcp/a3_client.py +405 -0
- flashforge/tcp/ff_client.py +93 -90
- flashforge/tcp/gcode/__init__.py +4 -2
- flashforge/tcp/gcode/a3_gcode_controller.py +109 -0
- flashforge/tcp/gcode/gcode_controller.py +48 -36
- flashforge/tcp/gcode/gcodes.py +7 -1
- flashforge/tcp/parsers/__init__.py +11 -11
- flashforge/tcp/parsers/endstop_status.py +103 -132
- flashforge/tcp/parsers/location_info.py +26 -13
- flashforge/tcp/parsers/print_status.py +49 -56
- flashforge/tcp/parsers/printer_info.py +38 -48
- flashforge/tcp/parsers/temp_info.py +46 -47
- flashforge/tcp/parsers/thumbnail_info.py +65 -40
- flashforge/tcp/tcp_client.py +296 -293
- {flashforge_python_api-1.0.2.dist-info → flashforge_python_api-1.1.0.dist-info}/METADATA +35 -14
- flashforge_python_api-1.1.0.dist-info/RECORD +45 -0
- {flashforge_python_api-1.0.2.dist-info → flashforge_python_api-1.1.0.dist-info}/WHEEL +1 -1
- flashforge_python_api-1.0.2.dist-info/RECORD +0 -43
- {flashforge_python_api-1.0.2.dist-info → flashforge_python_api-1.1.0.dist-info}/entry_points.txt +0 -0
- {flashforge_python_api-1.0.2.dist-info → flashforge_python_api-1.1.0.dist-info}/licenses/LICENSE +0 -0
flashforge/client.py
CHANGED
|
@@ -4,8 +4,9 @@ FlashForge Python API - Main Unified Client
|
|
|
4
4
|
This module provides the main FlashForgeClient class that orchestrates both HTTP and TCP
|
|
5
5
|
communication layers for controlling FlashForge 3D printers.
|
|
6
6
|
"""
|
|
7
|
+
|
|
7
8
|
import asyncio
|
|
8
|
-
from
|
|
9
|
+
from dataclasses import dataclass
|
|
9
10
|
|
|
10
11
|
import aiohttp
|
|
11
12
|
|
|
@@ -13,24 +14,40 @@ from .api.constants.endpoints import Endpoints
|
|
|
13
14
|
from .api.controls import Control, Files, Info, JobControl, TempControl
|
|
14
15
|
from .api.controls.info import MachineInfoParser
|
|
15
16
|
from .api.network.utils import NetworkUtils
|
|
16
|
-
from .models import FFMachineInfo, ProductResponse
|
|
17
|
+
from .models import FFMachineInfo, Product, ProductResponse
|
|
17
18
|
from .tcp import FlashForgeClient as TcpClient
|
|
18
|
-
from .tcp import PrinterInfo
|
|
19
|
+
from .tcp import FlashForgeTcpClientOptions, PrinterInfo
|
|
20
|
+
from .tcp.parsers.temp_info import TempInfo
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(slots=True)
|
|
24
|
+
class FiveMClientConnectionOptions:
|
|
25
|
+
"""Optional connection and feature overrides for FiveMClient-compatible clients."""
|
|
26
|
+
|
|
27
|
+
http_port: int | None = None
|
|
28
|
+
tcp_port: int | None = None
|
|
29
|
+
led_control_override: bool | None = None
|
|
19
30
|
|
|
20
31
|
|
|
21
32
|
class FlashForgeClient:
|
|
22
33
|
"""
|
|
23
34
|
Main client for interacting with a FlashForge 3D printer.
|
|
24
|
-
|
|
35
|
+
|
|
25
36
|
This class provides methods for controlling the printer, managing print jobs,
|
|
26
37
|
retrieving information, and handling file operations. It orchestrates both
|
|
27
38
|
HTTP and TCP communication layers to provide a unified interface.
|
|
28
39
|
"""
|
|
29
40
|
|
|
30
|
-
def __init__(
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
ip_address: str,
|
|
44
|
+
serial_number: str,
|
|
45
|
+
check_code: str,
|
|
46
|
+
options: FiveMClientConnectionOptions | None = None,
|
|
47
|
+
):
|
|
31
48
|
"""
|
|
32
49
|
Creates an instance of FlashForgeClient.
|
|
33
|
-
|
|
50
|
+
|
|
34
51
|
Args:
|
|
35
52
|
ip_address: The IP address of the printer
|
|
36
53
|
serial_number: The serial number of the printer
|
|
@@ -42,15 +59,19 @@ class FlashForgeClient:
|
|
|
42
59
|
self.check_code = check_code
|
|
43
60
|
|
|
44
61
|
# Constants
|
|
45
|
-
self._PORT = 8898
|
|
62
|
+
self._PORT = options.http_port if options and options.http_port is not None else 8898
|
|
46
63
|
self._HTTP_TIMEOUT = 5.0
|
|
47
64
|
|
|
48
65
|
# HTTP client state
|
|
49
|
-
self._http_session:
|
|
50
|
-
self.
|
|
66
|
+
self._http_session: aiohttp.ClientSession | None = None
|
|
67
|
+
self._http_client_event = asyncio.Event()
|
|
68
|
+
self._http_client_event.set() # Not busy initially
|
|
51
69
|
|
|
52
70
|
# TCP client setup
|
|
53
|
-
|
|
71
|
+
tcp_options = None
|
|
72
|
+
if options and options.tcp_port is not None:
|
|
73
|
+
tcp_options = FlashForgeTcpClientOptions(port=options.tcp_port)
|
|
74
|
+
self.tcp_client = TcpClient(ip_address, tcp_options)
|
|
54
75
|
|
|
55
76
|
# Control instances
|
|
56
77
|
self.control = Control(self)
|
|
@@ -68,12 +89,22 @@ class FlashForgeClient:
|
|
|
68
89
|
self.mac_address: str = ""
|
|
69
90
|
self.flash_cloud_code: str = ""
|
|
70
91
|
self.polar_cloud_code: str = ""
|
|
92
|
+
self.camera_stream_url: str = ""
|
|
71
93
|
self.lifetime_print_time: str = ""
|
|
72
94
|
self.lifetime_filament_meters: str = ""
|
|
95
|
+
self.product_info: Product | None = None
|
|
73
96
|
|
|
74
97
|
# Control states
|
|
75
98
|
self.led_control: bool = False
|
|
76
99
|
self.filtration_control: bool = False
|
|
100
|
+
self._detected_led_control: bool = False
|
|
101
|
+
self._detected_filtration_control: bool = False
|
|
102
|
+
self._led_control_override = (
|
|
103
|
+
options.led_control_override
|
|
104
|
+
if options and options.led_control_override is not None
|
|
105
|
+
else None
|
|
106
|
+
)
|
|
107
|
+
self._apply_feature_overrides()
|
|
77
108
|
|
|
78
109
|
@property
|
|
79
110
|
def is_ad5x(self) -> bool:
|
|
@@ -85,35 +116,37 @@ class FlashForgeClient:
|
|
|
85
116
|
"""
|
|
86
117
|
return self._is_ad5x
|
|
87
118
|
|
|
88
|
-
async def __aenter__(self):
|
|
119
|
+
async def __aenter__(self) -> "FlashForgeClient":
|
|
89
120
|
"""Async context manager entry."""
|
|
90
121
|
await self._ensure_http_session()
|
|
91
122
|
await self.initialize()
|
|
92
123
|
return self
|
|
93
124
|
|
|
94
|
-
async def __aexit__(
|
|
125
|
+
async def __aexit__(
|
|
126
|
+
self,
|
|
127
|
+
exc_type: type[BaseException] | None,
|
|
128
|
+
exc_val: BaseException | None,
|
|
129
|
+
exc_tb: object,
|
|
130
|
+
) -> None:
|
|
95
131
|
"""Async context manager exit."""
|
|
96
132
|
await self.dispose()
|
|
97
133
|
|
|
98
134
|
async def _ensure_http_session(self) -> aiohttp.ClientSession:
|
|
99
135
|
"""
|
|
100
136
|
Ensures that an HTTP session is available.
|
|
101
|
-
|
|
137
|
+
|
|
102
138
|
Returns:
|
|
103
139
|
The HTTP session instance
|
|
104
140
|
"""
|
|
105
141
|
if self._http_session is None or self._http_session.closed:
|
|
106
142
|
timeout = aiohttp.ClientTimeout(total=self._HTTP_TIMEOUT)
|
|
107
|
-
self._http_session = aiohttp.ClientSession(
|
|
108
|
-
timeout=timeout,
|
|
109
|
-
headers={"Accept": "*/*"}
|
|
110
|
-
)
|
|
143
|
+
self._http_session = aiohttp.ClientSession(timeout=timeout, headers={"Accept": "*/*"})
|
|
111
144
|
return self._http_session
|
|
112
145
|
|
|
113
146
|
async def initialize(self) -> bool:
|
|
114
147
|
"""
|
|
115
148
|
Initializes the FlashForgeClient and verifies the connection to the printer.
|
|
116
|
-
|
|
149
|
+
|
|
117
150
|
Returns:
|
|
118
151
|
True if initialization is successful, False otherwise
|
|
119
152
|
"""
|
|
@@ -123,17 +156,35 @@ class FlashForgeClient:
|
|
|
123
156
|
print("Failed to connect to printer")
|
|
124
157
|
return False
|
|
125
158
|
|
|
159
|
+
@property
|
|
160
|
+
def _http_client_busy(self) -> bool:
|
|
161
|
+
"""
|
|
162
|
+
Legacy property to maintain internal API compatibility.
|
|
163
|
+
Returns True if the client is busy (event is not set), False otherwise.
|
|
164
|
+
"""
|
|
165
|
+
return not self._http_client_event.is_set()
|
|
166
|
+
|
|
167
|
+
@_http_client_busy.setter
|
|
168
|
+
def _http_client_busy(self, value: bool) -> None:
|
|
169
|
+
"""
|
|
170
|
+
Sets the busy state using the event.
|
|
171
|
+
True means busy (clear event), False means not busy (set event).
|
|
172
|
+
"""
|
|
173
|
+
if value:
|
|
174
|
+
self._http_client_event.clear()
|
|
175
|
+
else:
|
|
176
|
+
self._http_client_event.set()
|
|
177
|
+
|
|
126
178
|
async def is_http_client_busy(self) -> bool:
|
|
127
179
|
"""
|
|
128
180
|
Checks if the HTTP client is currently busy.
|
|
129
|
-
|
|
181
|
+
Waits until the client is not busy before returning.
|
|
182
|
+
|
|
130
183
|
Returns:
|
|
131
|
-
|
|
184
|
+
False (always returns False after waiting, for compatibility)
|
|
132
185
|
"""
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
await asyncio.sleep(0.01)
|
|
136
|
-
return self._http_client_busy
|
|
186
|
+
await self._http_client_event.wait()
|
|
187
|
+
return False
|
|
137
188
|
|
|
138
189
|
def release_http_client(self) -> None:
|
|
139
190
|
"""Releases the HTTP client, allowing it to be used for new requests."""
|
|
@@ -142,9 +193,9 @@ class FlashForgeClient:
|
|
|
142
193
|
async def init_control(self) -> bool:
|
|
143
194
|
"""
|
|
144
195
|
Initializes the control interface with the printer.
|
|
145
|
-
|
|
196
|
+
|
|
146
197
|
This involves sending a product command and initializing TCP control.
|
|
147
|
-
|
|
198
|
+
|
|
148
199
|
Returns:
|
|
149
200
|
True if control initialization is successful, False otherwise
|
|
150
201
|
"""
|
|
@@ -155,20 +206,22 @@ class FlashForgeClient:
|
|
|
155
206
|
|
|
156
207
|
async def dispose(self) -> None:
|
|
157
208
|
"""
|
|
158
|
-
Disposes of the FlashForgeClient instance, stopping keep-alive messages
|
|
209
|
+
Disposes of the FlashForgeClient instance, stopping keep-alive messages
|
|
159
210
|
and cleaning up resources.
|
|
160
211
|
"""
|
|
161
212
|
# Stop TCP keep-alive and dispose
|
|
162
|
-
if hasattr(self.tcp_client,
|
|
213
|
+
if hasattr(self.tcp_client, "stop_keep_alive"):
|
|
163
214
|
await self.tcp_client.stop_keep_alive(True)
|
|
164
|
-
if hasattr(self.tcp_client,
|
|
215
|
+
if hasattr(self.tcp_client, "dispose"):
|
|
165
216
|
await self.tcp_client.dispose()
|
|
166
217
|
|
|
167
218
|
# Close HTTP session
|
|
168
219
|
if self._http_session and not self._http_session.closed:
|
|
169
220
|
await self._http_session.close()
|
|
170
221
|
|
|
171
|
-
|
|
222
|
+
self.camera_stream_url = ""
|
|
223
|
+
|
|
224
|
+
def cache_details(self, info: FFMachineInfo | None) -> bool:
|
|
172
225
|
"""
|
|
173
226
|
Caches machine details from the provided FFMachineInfo object.
|
|
174
227
|
|
|
@@ -183,29 +236,30 @@ class FlashForgeClient:
|
|
|
183
236
|
|
|
184
237
|
# Cache all printer information
|
|
185
238
|
self.printer_name = info.name or ""
|
|
239
|
+
self.is_pro = info.is_pro
|
|
186
240
|
self.firmware_version = info.firmware_version or ""
|
|
187
|
-
self.firmware_ver = info.firmware_version.split(
|
|
241
|
+
self.firmware_ver = info.firmware_version.split("-")[0] if info.firmware_version else ""
|
|
188
242
|
self.mac_address = info.mac_address or ""
|
|
189
243
|
self.flash_cloud_code = info.flash_cloud_register_code or ""
|
|
190
244
|
self.polar_cloud_code = info.polar_cloud_register_code or ""
|
|
245
|
+
self.camera_stream_url = info.camera_stream_url or ""
|
|
191
246
|
self.lifetime_print_time = info.formatted_total_run_time or ""
|
|
192
247
|
self._is_ad5x = info.is_ad5x
|
|
193
248
|
|
|
194
249
|
# Format filament usage
|
|
195
|
-
if info.cumulative_filament is not None
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
self.lifetime_filament_meters = "0.00m"
|
|
250
|
+
filament_value = info.cumulative_filament if info.cumulative_filament is not None else 0.0
|
|
251
|
+
self.lifetime_filament_meters = f"{filament_value:.2f}m"
|
|
252
|
+
self._apply_feature_overrides()
|
|
199
253
|
|
|
200
254
|
return True
|
|
201
255
|
|
|
202
256
|
def get_endpoint(self, endpoint: str) -> str:
|
|
203
257
|
"""
|
|
204
258
|
Constructs the full API endpoint URL.
|
|
205
|
-
|
|
259
|
+
|
|
206
260
|
Args:
|
|
207
261
|
endpoint: The specific API endpoint path
|
|
208
|
-
|
|
262
|
+
|
|
209
263
|
Returns:
|
|
210
264
|
The full URL for the API endpoint
|
|
211
265
|
"""
|
|
@@ -214,7 +268,7 @@ class FlashForgeClient:
|
|
|
214
268
|
async def verify_connection(self) -> bool:
|
|
215
269
|
"""
|
|
216
270
|
Verifies the connection to the printer by retrieving machine details and TCP information.
|
|
217
|
-
|
|
271
|
+
|
|
218
272
|
Returns:
|
|
219
273
|
True if the connection is verified, False otherwise
|
|
220
274
|
"""
|
|
@@ -232,12 +286,14 @@ class FlashForgeClient:
|
|
|
232
286
|
return False
|
|
233
287
|
|
|
234
288
|
# Get TCP printer information to check for Pro model
|
|
235
|
-
tcp_info:
|
|
289
|
+
tcp_info: PrinterInfo | None = await self.tcp_client.get_printer_info()
|
|
236
290
|
if tcp_info:
|
|
237
|
-
if "Pro" in tcp_info.type_name:
|
|
291
|
+
if "Pro" in tcp_info.type_name and not machine_info.is_pro and not machine_info.is_ad5x:
|
|
238
292
|
self.is_pro = True
|
|
239
293
|
else:
|
|
240
|
-
print(
|
|
294
|
+
print(
|
|
295
|
+
"Warning: Unable to get PrinterInfo from TCP API, some features might not work"
|
|
296
|
+
)
|
|
241
297
|
|
|
242
298
|
# Cache the details
|
|
243
299
|
return self.cache_details(machine_info)
|
|
@@ -249,28 +305,24 @@ class FlashForgeClient:
|
|
|
249
305
|
async def send_product_command(self) -> bool:
|
|
250
306
|
"""
|
|
251
307
|
Sends a product command to the printer to retrieve control states.
|
|
252
|
-
|
|
308
|
+
|
|
253
309
|
This method sets the http_client_busy flag while the request is in progress.
|
|
254
|
-
|
|
310
|
+
|
|
255
311
|
Returns:
|
|
256
|
-
True if the product command is sent successfully and valid data is received,
|
|
312
|
+
True if the product command is sent successfully and valid data is received,
|
|
257
313
|
False otherwise
|
|
258
314
|
"""
|
|
259
315
|
self._http_client_busy = True
|
|
260
316
|
|
|
261
|
-
payload = {
|
|
262
|
-
"serialNumber": self.serial_number,
|
|
263
|
-
"checkCode": self.check_code
|
|
264
|
-
}
|
|
317
|
+
payload = {"serialNumber": self.serial_number, "checkCode": self.check_code}
|
|
265
318
|
|
|
266
319
|
try:
|
|
267
320
|
session = await self._ensure_http_session()
|
|
268
321
|
async with session.post(
|
|
269
322
|
self.get_endpoint(Endpoints.PRODUCT),
|
|
270
323
|
json=payload,
|
|
271
|
-
headers={"Content-Type": "application/json"}
|
|
324
|
+
headers={"Content-Type": "application/json"},
|
|
272
325
|
) as response:
|
|
273
|
-
|
|
274
326
|
if response.status != 200:
|
|
275
327
|
return False
|
|
276
328
|
|
|
@@ -282,6 +334,7 @@ class FlashForgeClient:
|
|
|
282
334
|
# Fallback: manually parse as JSON if Content-Type is malformed
|
|
283
335
|
text = await response.text()
|
|
284
336
|
import json
|
|
337
|
+
|
|
285
338
|
data = json.loads(text)
|
|
286
339
|
|
|
287
340
|
# Validate response structure
|
|
@@ -292,11 +345,12 @@ class FlashForgeClient:
|
|
|
292
345
|
product_response = ProductResponse(**data)
|
|
293
346
|
if product_response and product_response.product:
|
|
294
347
|
product = product_response.product
|
|
295
|
-
self.
|
|
296
|
-
self.
|
|
297
|
-
|
|
298
|
-
product.externalFanCtrlState == 0
|
|
348
|
+
self.product_info = product
|
|
349
|
+
self._detected_led_control = product.lightCtrlState != 0
|
|
350
|
+
self._detected_filtration_control = not (
|
|
351
|
+
product.internalFanCtrlState == 0 or product.externalFanCtrlState == 0
|
|
299
352
|
)
|
|
353
|
+
self._apply_feature_overrides()
|
|
300
354
|
return True
|
|
301
355
|
|
|
302
356
|
except Exception as error:
|
|
@@ -310,7 +364,7 @@ class FlashForgeClient:
|
|
|
310
364
|
async def get_http_session(self) -> aiohttp.ClientSession:
|
|
311
365
|
"""
|
|
312
366
|
Gets the HTTP session for making requests.
|
|
313
|
-
|
|
367
|
+
|
|
314
368
|
Returns:
|
|
315
369
|
The HTTP session instance
|
|
316
370
|
"""
|
|
@@ -318,19 +372,19 @@ class FlashForgeClient:
|
|
|
318
372
|
|
|
319
373
|
# Additional convenience methods for direct access to common operations
|
|
320
374
|
|
|
321
|
-
async def get_printer_status(self) ->
|
|
375
|
+
async def get_printer_status(self) -> FFMachineInfo | None:
|
|
322
376
|
"""
|
|
323
377
|
Gets the current printer status and information.
|
|
324
|
-
|
|
378
|
+
|
|
325
379
|
Returns:
|
|
326
380
|
FFMachineInfo object with current printer status, or None if failed
|
|
327
381
|
"""
|
|
328
382
|
return await self.info.get()
|
|
329
383
|
|
|
330
|
-
async def get_temperatures(self):
|
|
384
|
+
async def get_temperatures(self) -> TempInfo | None:
|
|
331
385
|
"""
|
|
332
386
|
Gets current temperature readings from the printer.
|
|
333
|
-
|
|
387
|
+
|
|
334
388
|
Returns:
|
|
335
389
|
Temperature information from the TCP client
|
|
336
390
|
"""
|
|
@@ -339,7 +393,7 @@ class FlashForgeClient:
|
|
|
339
393
|
async def home_all_axes(self) -> bool:
|
|
340
394
|
"""
|
|
341
395
|
Homes all axes (X, Y, Z) of the printer.
|
|
342
|
-
|
|
396
|
+
|
|
343
397
|
Returns:
|
|
344
398
|
True if successful, False otherwise
|
|
345
399
|
"""
|
|
@@ -348,7 +402,7 @@ class FlashForgeClient:
|
|
|
348
402
|
async def emergency_stop(self) -> bool:
|
|
349
403
|
"""
|
|
350
404
|
Performs an emergency stop of the printer.
|
|
351
|
-
|
|
405
|
+
|
|
352
406
|
Returns:
|
|
353
407
|
True if successful, False otherwise
|
|
354
408
|
"""
|
|
@@ -357,7 +411,7 @@ class FlashForgeClient:
|
|
|
357
411
|
async def pause_print(self) -> bool:
|
|
358
412
|
"""
|
|
359
413
|
Pauses the current print job.
|
|
360
|
-
|
|
414
|
+
|
|
361
415
|
Returns:
|
|
362
416
|
True if successful, False otherwise
|
|
363
417
|
"""
|
|
@@ -366,12 +420,26 @@ class FlashForgeClient:
|
|
|
366
420
|
async def resume_print(self) -> bool:
|
|
367
421
|
"""
|
|
368
422
|
Resumes a paused print job.
|
|
369
|
-
|
|
423
|
+
|
|
370
424
|
Returns:
|
|
371
425
|
True if successful, False otherwise
|
|
372
426
|
"""
|
|
373
427
|
return await self.job_control.resume_print_job()
|
|
374
428
|
|
|
429
|
+
def set_feature_overrides(self, *, led_control: bool | None = None) -> None:
|
|
430
|
+
"""Apply manual feature overrides for integrations that need UI-level capability control."""
|
|
431
|
+
self._led_control_override = led_control
|
|
432
|
+
self._apply_feature_overrides()
|
|
433
|
+
|
|
434
|
+
def _apply_feature_overrides(self) -> None:
|
|
435
|
+
"""Apply any configured manual capability overrides to the cached client state."""
|
|
436
|
+
self.led_control = (
|
|
437
|
+
self._led_control_override
|
|
438
|
+
if self._led_control_override is not None
|
|
439
|
+
else self._detected_led_control
|
|
440
|
+
)
|
|
441
|
+
self.filtration_control = self._detected_filtration_control
|
|
442
|
+
|
|
375
443
|
def __repr__(self) -> str:
|
|
376
444
|
"""String representation of the client."""
|
|
377
445
|
return (
|
flashforge/discovery/__init__.py
CHANGED
|
@@ -4,9 +4,36 @@ FlashForge Python API - Discovery Package
|
|
|
4
4
|
UDP-based printer discovery for finding FlashForge printers on the local network.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from .discovery import
|
|
7
|
+
from .discovery import (
|
|
8
|
+
DiscoveredPrinter,
|
|
9
|
+
DiscoveryError,
|
|
10
|
+
DiscoveryMonitor,
|
|
11
|
+
DiscoveryOptions,
|
|
12
|
+
DiscoveryProtocol,
|
|
13
|
+
DiscoveryTimeoutError,
|
|
14
|
+
FlashForgePrinter,
|
|
15
|
+
FlashForgePrinterDiscovery,
|
|
16
|
+
InvalidResponseError,
|
|
17
|
+
PrinterDiscovery,
|
|
18
|
+
PrinterModel,
|
|
19
|
+
PrinterStatus,
|
|
20
|
+
SocketCreationError,
|
|
21
|
+
main,
|
|
22
|
+
)
|
|
8
23
|
|
|
9
24
|
__all__ = [
|
|
10
|
-
|
|
11
|
-
|
|
25
|
+
"PrinterDiscovery",
|
|
26
|
+
"DiscoveredPrinter",
|
|
27
|
+
"DiscoveryOptions",
|
|
28
|
+
"PrinterModel",
|
|
29
|
+
"DiscoveryProtocol",
|
|
30
|
+
"PrinterStatus",
|
|
31
|
+
"DiscoveryMonitor",
|
|
32
|
+
"DiscoveryError",
|
|
33
|
+
"InvalidResponseError",
|
|
34
|
+
"SocketCreationError",
|
|
35
|
+
"DiscoveryTimeoutError",
|
|
36
|
+
"FlashForgePrinter",
|
|
37
|
+
"FlashForgePrinterDiscovery",
|
|
38
|
+
"main",
|
|
12
39
|
]
|