Merge branch 'mod-43'

This commit is contained in:
edo-neo 2025-07-25 09:25:36 +02:00
commit 74458701a6
4 changed files with 200 additions and 14 deletions

View File

@ -21,12 +21,13 @@
^PW354
^LL189
^LS0
^FT185,164^BQN,2,6
^FT185,164^BQN,2,4
^FH\^FDLA,{BCODE}^FS
^FT17,37^A0N,17,15^FH\^CI28^FDLAMBORGHINI^FS^CI27
^FT17,73^A0N,16,15^FH\^CI28^FDMade in Italy^FS^CI27
^FT17,106^A0N,17,18^FH\^CI28^FD{PART}^FS^CI27
^FT17,142^A0N,17,18^FH\^CI28^FD07N 103 L01^FS^CI27
^FT17,169^A0N,13,13^FH\^CI28^FD>PA66+GF35; PA12+GF20; FKM; PA6+GF50; PPA<^FS^CI27
^FT17,34^A0N,17,15^FH\^CI28^FDLAMBORGHINI^FS^CI27
^FT17,63^A0N,16,15^FH\^CI28^FDMade in Italy^FS^CI27
^FT17,92^A0N,17,18^FH\^CI28^FD{PART}^FS^CI27
^FT17,121^A0N,17,18^FH\^CI28^FD07N 103 L01^FS^CI27
^FT17,150^A0N,17,18^FH\^CI28^FD{DD}/{MO}/{YY}^FS^CI27
^FT17,179^A0N,13,13^FH\^CI28^FD>PA66+GF35; PA12+GF20; FKM; PA6+GF50; PPA<^FS^CI27
^PQ1,0,1,Y
^XZ
^XZ

View File

@ -45,8 +45,8 @@ description_field: descrizione
[label_printer]
platform: linux
printer: Zebra_Technologies_ZTC_ZD421-203dpi_ZPL
risoluzione: 203
printer: ZTC-ZD421-300dpi-ZPL-2
risoluzione: 300
[recipes_defaults]
tester_discharge_enable: yes

View File

@ -8,10 +8,10 @@ from src.lib.helpers import ConfigReader
SYSTEM_ID = "test-linux"
START_SN = 100
QTY = 100
QTY = 1
STOP_SN = START_SN + QTY
TEMPLATE = "lamborghini_30x16_203.prn"
TEMPLATE = "Lamborghini_30x16_203.prn"
PRINTER_NAME = "zd421"
PN = "07N131628A"
#PN = "07N131597A"

View File

@ -33,6 +33,14 @@ from components import ArchiveSynchronizer
class Test(Widget):
# Modulo 43 assignment table for checksum calculation
MODULO43_ASSIGNMENT_TABLE = {
'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
'A': 10, 'B': 11, 'C': 12, 'D': 13, 'E': 14, 'F': 15, 'G': 16, 'H': 17, 'I': 18,
'J': 19, 'K': 20, 'L': 21, 'M': 22, 'N': 23, 'O': 24, 'P': 25, 'Q': 26, 'R': 27,
'S': 28, 'T': 29, 'U': 30, 'V': 31, 'W': 32, 'X': 33, 'Y': 34, 'Z': 35,
'-': 36, '.': 37, ' ': 38, '$': 39, '/': 40, '+': 41, '%': 42
}
def __init__(self, config, components=None, main_window=None):
super().__init__()
@ -70,6 +78,10 @@ class Test(Widget):
else:
self.flag_label.setVisible(False)
# Initialize barcode formatting variables
self.barcode_prefix = ""
self.barcode_suffix = "*="
self.active_errors = [] # List to hold current errors (type: tuples of (message, is_error))
self.current_error_index = 0 # Keeps track of the current error index during alternation
@ -841,6 +853,11 @@ class Test(Widget):
# LABEL PRINT
recipe = archived.test_data.get("recipe", {})
# Define barcode format variables
self.module_data_format = "1IT ECE{SN7}"
# Use suffix_mod_43 from print step editor if available, otherwise use default
self.barcode_format = self.print_step.spec.get("barcode")
leak_test_1 = archived.test_data.get("leak_1", {})
leak_test_1_step = leak_test_1.get("step", {})
leak_test_1_step_spec = leak_test_1_step.get("spec", {})
@ -944,10 +961,12 @@ class Test(Widget):
#TESTING BROTHER
label_brother = context.get("RECIPE_TO_PRINT", "-") + context.get("DD","-") + context.get("MO","-") + context.get("YY","-") + context.get("SN5","-")
barcode = str(label_brother)
barcode_format = self.print_step.spec.get("barcode", "-")
self.printed_barcode = barcode_format.format_map(context)
formatted_barcode = barcode_format.format(**context)
# Process any {M43:X:Y} patterns in the barcode format
processed_barcode_format = self.process_m43_patterns(self.barcode_format, context)
formatted_barcode = processed_barcode_format.format(**context)
context['BCODE'] = formatted_barcode
self.printed_barcode = formatted_barcode
if self.archived is not None:
self.archived.barcode = self.printed_barcode
@ -1099,3 +1118,169 @@ class Test(Widget):
self.flag_label.setVisible(True) # Ensure the label is visible
else: # No args provided
self.flag_label.setVisible(False) # Hide label
def process_m43_patterns(self, barcode_format, context):
"""
Process any {M43:X:Y} patterns in the barcode format string.
The pattern {M43:X:Y} is replaced with the modulo 43 check digit calculated
for the substring of the formatted barcode starting at position X and
containing Y characters.
Args:
barcode_format: The barcode format string that may contain {M43:X:Y} patterns.
context: The context dictionary used for formatting.
Returns:
The processed barcode format string with {M43:X:Y} patterns replaced by
placeholders that will be filled with the calculated check digits.
"""
import re
# If barcode_format is None or empty, return it as is
if not barcode_format:
self.log.warning("Empty barcode format provided")
return barcode_format
# Log the input barcode format and context
self.log.info(f"Processing barcode format: '{barcode_format}'")
self.log.info(f"Context keys: {list(context.keys())}")
# Create a temporary copy of the barcode format for processing
processed_format = barcode_format
# Find all {M43:X:Y} patterns in the barcode format
pattern = r'\{M43:(\d+):(\d+)\}'
matches = list(re.finditer(pattern, barcode_format))
self.log.info(f"Found {len(matches)} M43 patterns in barcode format")
# If no M43 patterns found, return the original format
if not matches:
self.log.info("No M43 patterns found in barcode format")
return barcode_format
# Process each match
for i, match in enumerate(matches):
# Extract X and Y values
x = int(match.group(1))
y = int(match.group(2))
self.log.info(f"Processing M43 pattern {i+1}: X={x}, Y={y}")
# Create a placeholder for this check digit
placeholder = f"{{m43_check_{i}}}"
# Replace the {M43:X:Y} pattern with the placeholder
processed_format = processed_format.replace(match.group(0), placeholder)
# Format the barcode without the M43 patterns to get the base string
# First, create a temporary format string with all M43 patterns removed
temp_format = barcode_format
for m in matches:
temp_format = temp_format.replace(m.group(0), "")
# Format the temporary string with the context
try:
base_string = temp_format.format(**context)
self.log.info(f"Base string for checksum calculation: '{base_string}'")
except KeyError as e:
self.log.error(f"KeyError when formatting base string: {e}")
context[f"m43_check_{i}"] = "?"
continue
# Extract the substring for checksum calculation
if x < len(base_string) and x + y <= len(base_string):
substring = base_string[x:x+y]
# Log the substring and its length for debugging
self.log.info(f"M43 substring for checksum calculation: '{substring}', length: {len(substring)}")
# Remove any characters that are not valid for checksum calculation
# Check if the substring contains any invalid characters
invalid_chars = [c for c in substring if c not in self.MODULO43_ASSIGNMENT_TABLE]
if invalid_chars:
original_substring = substring
substring = ''.join(c for c in substring if c in self.MODULO43_ASSIGNMENT_TABLE)
self.log.info(f"Removed invalid characters {invalid_chars} from substring: '{original_substring}' -> '{substring}'")
# Check if the substring is empty or contains only whitespace
if not substring or substring.isspace():
self.log.warning(f"Empty or whitespace-only substring for M43 pattern {i+1}")
context[f"m43_check_{i}"] = "?"
continue
# Calculate the check digit
try:
check_digit = self.calculate_modulo43_checksum(substring)
# Log the calculated check digit
self.log.info(f"Calculated check digit: '{check_digit}' for substring: '{substring}'")
# Add the check digit to the context
context[f"m43_check_{i}"] = check_digit
except ValueError as e:
self.log.error(f"Error calculating checksum: {e}")
context[f"m43_check_{i}"] = "?"
else:
# Handle out-of-range indices
self.log.warning(f"M43 pattern with X={x}, Y={y} is out of range for string of length {len(base_string)}")
context[f"m43_check_{i}"] = "?"
self.log.info(f"Processed barcode format: '{processed_format}'")
return processed_format
def calculate_modulo43_checksum(self,data_sequence: str) -> str:
"""
Calculates the Modulo 43 checksum for a given data sequence.
The function determines the checksum value for each character based on a
predefined assignment table, calculates the total sum of these values,
and then finds the remainder of the division by 43. The character
corresponding to this remainder is the check digit.
Args:
data_sequence: The input string for which to calculate the checksum.
Returns:
The Modulo 43 check digit as a single character.
Raises:
ValueError: If the data_sequence contains a character not found in the
assignment table.
"""
# If the data sequence is empty, return a default value
if not data_sequence:
self.log.warning("Empty data sequence provided for checksum calculation")
return "?"
# Use the class variable for the assignment table
assignment_table = self.MODULO43_ASSIGNMENT_TABLE
# Log the input data sequence
self.log.info(f"Calculating checksum for data sequence: '{data_sequence}'")
total_sum = 0
char_values = []
for char in data_sequence:
if char in assignment_table:
char_value = assignment_table[char]
total_sum += char_value
char_values.append((char, char_value))
else:
self.log.error(f"Character '{char}' is not valid for checksum calculation.")
raise ValueError(f"Character '{char}' is not valid for checksum calculation.")
# Log the character values and total sum
self.log.info(f"Character values: {char_values}")
self.log.info(f"Total sum: {total_sum}")
remainder = total_sum % 43
self.log.info(f"Remainder (total_sum % 43): {remainder}")
# Invert the assignment_table to map the remainder back to the character
for char, value in assignment_table.items():
if value == remainder:
self.log.info(f"Check digit for remainder {remainder}: '{char}'")
return char
# This part of the code should be unreachable given the logic
self.log.error(f"No character found for remainder {remainder}")
return "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"