diff --git a/pybgcode/pybgcode/__init__.py b/pybgcode/pybgcode/__init__.py index 3c076f5..d448839 100644 --- a/pybgcode/pybgcode/__init__.py +++ b/pybgcode/pybgcode/__init__.py @@ -135,3 +135,79 @@ def read_metadata(gcodefile: FILEWrapper, type: str = 'printer'): return get_metadata(gcodefile, header, block_header, metadata_block_class) +# this list was taken from gcode-metadata library +connect_metadata_keys = [ + "filament used [cm3]", "filament used [mm]", "filament used [g]", + "filament cost", "filament_type", "temperature", "bed_temperature", + "nozzle_diameter", "estimated printing time (normal mode)", + "printer_model", "layer_height", "fill_density", "brim_width", + "support_material", "ironing", "quiet_percent_present", + "quiet_left_present", "quiet_change_in_present", "normal_percent_present", + "normal_left_present", "normal_change_in_present", "layer_info_present", + "max_layer_z"] + + +def filter_connect_metadata(output: dict) -> dict: + all_metadata = {**output['print'], **output['printer']} + connect_metadata = { + key: item for key, item in all_metadata.items() + if key in connect_metadata_keys} + return {'thumbnails': output['thumbnails'], 'metadata': connect_metadata} + + +def read_connect_metadata(wrapper: FILEWrapper): + """Read metadata from binary gcode file.""" + output = {'print': None, 'thumbnails': [], 'printer': None} + + # read file header + res, header = get_header(wrapper) + block_header = BlockHeader() + while True: + # read next block header + res = read_next_block_header(wrapper, header, block_header) + if res != EResult.Success: + raise ResultError(res) + if block_header.type == 0: + # file metadata - we do not need them + metadata_block = FileMetadataBlock() + res = metadata_block.read_data( + wrapper, header, block_header) + if res != EResult.Success: + raise ResultError(res) + elif block_header.type in (1, 2): + # GCode block or Slicer metadata block - no more metadata + return filter_connect_metadata(output) + elif block_header.type == 3: + # printer metadata - we need them + metadata_block = PrinterMetadataBlock() + res = metadata_block.read_data( + wrapper, header, block_header) + if res != EResult.Success: + raise ResultError(res) + output['printer'] = dict( + metadata_block.raw_data) if metadata_block else None + elif block_header.type == 4: + # print metdata - we need them + metadata_block = PrintMetadataBlock() + res = metadata_block.read_data( + wrapper, header, block_header) + if res != EResult.Success: + raise ResultError(res) + output['print'] = dict( + metadata_block.raw_data) if metadata_block else None + return filter_connect_metadata(output) + elif block_header.type == 5: + # thumbnails block + thumbnail_block = ThumbnailBlock() + res = thumbnail_block.read_data(wrapper, header, block_header) + if res != EResult.Success: + raise ResultError(res) + output['thumbnails'].append( + {"meta": thumbnail_block.params, + "bytes": thumbnail_block.data()}) + else: + # not documented value + return filter_connect_metadata(output) + + + diff --git a/pybgcode/tests/test_convert.py b/pybgcode/tests/test_convert.py index 4572e57..0c89df9 100644 --- a/pybgcode/tests/test_convert.py +++ b/pybgcode/tests/test_convert.py @@ -8,7 +8,9 @@ EResult, EThumbnailFormat, read_thumbnails, - read_metadata + read_metadata, + read_connect_metadata, + connect_metadata_keys ) # pylint: disable=missing-function-docstring @@ -82,6 +84,11 @@ def test_main(): assert print_metadata == TEST_PRINT_METADATA slicer_metadata = read_metadata(thumb_f, 'slicer') assert len(slicer_metadata) == TEST_LEN_SLICER_METADATA + + all_metadata = read_connect_metadata(thumb_f) + assert len(all_metadata['thumbnails']) == TEST_THUMBNAILS + for key in all_metadata['metadata'].keys(): + assert key in connect_metadata_keys pybgcode.close(thumb_f) # write thumbnails to png files