#!/bin/python import shimatta_label.storage_label import shimatta_label.component_label import shimatta_label.brother_ql_wrapper as ql_wrapper import sys import requests import urllib.parse import getpass import json import re MICE_TOILET_TEMPLATE = 'https://parts.shimatta.net/api/v1/parts/storages/075acbaf-ed60-47b9-9bd5-98bfbc3a79ea/' SMD_STRAP_PAGE_TEMPLATE = 'https://parts.shimatta.net/api/v1/parts/storages/4df58899-7338-48f5-9d93-cf5a59a6a400/' def get_child_storages(storage_query_url, token, uuid, expected_amount): # get children query_res = requests.get(storage_query_url, headers={'Authorization': f'Token {token}'}, params={'parent_storage':uuid, 'expand_stocks': True}) if query_res.status_code != 200: print('Request for children unsuccessful') sys.exit(-3) storage_json = query_res.json() if storage_json['count'] != expected_amount: print('Storage json does not contain correct amount of storage entries') sys.exit(-1) # pagination storage_list = storage_json['results'] while storage_json['next']: query_res = requests.get(storage_json['next'], headers={'Authorization': f'Token {token}'}, params={'parent_storage':uuid}) storage_json = query_res.json() storage_list.extend(storage_json['results']) return {storage['name']: storage for storage in storage_list} def get_component_print_name(comp): ''' Generates a human readeable string from the parameters depending on the type ''' param_dict = {param['ro_parameter_type']: param for param in comp['ro_parameters']} if comp['ro_component_type'] in ['Resistor', 'Resistor NTC']: resistor_value = param_dict['Resistance']['value'] if resistor_value >= 10e8: comp_name = f'{int(resistor_value / 10e8)}G{str(int(resistor_value % 10e8)).rstrip('0')}' elif resistor_value >= 10e5: comp_name = f'{int(resistor_value / 10e5)}M{str(int(resistor_value % 10e5)).rstrip('0')}' elif resistor_value >= 10e2: comp_name = f'{int(resistor_value / 10e2)}K{str(int(resistor_value % 10e2)).rstrip('0')}' elif resistor_value >= 1.0: comp_name = f'{int(resistor_value)}R{str(round(resistor_value % 1, 6))[2:].rstrip('0')}' elif resistor_value == 0.0: comp_name = '0R' else: comp_name = f'R{str(round(resistor_value % 1, 6))[2:]}' if comp['ro_component_type'] == 'Resistor NTC': comp_name += ' NTC' if param_dict['Resistor technology']['text_value'] == 'laser trim': comp_name += ' L' else: print(f'Unknown component type: {comp['ro_component_type']}') return None return comp_name def char_range(c1, c2): """Generates the characters from `c1` to `c2`, exclusive.""" for c in range(ord(c1), ord(c2)): yield chr(c) def handle_storage_qr_code(base_url, token, uuid): storage_query_url = urllib.parse.urljoin(base_url, 'api/v1/parts/storages/') query_res = requests.get(storage_query_url, headers={'Authorization': f'Token {token}'}, params={'id':uuid}) if query_res.status_code != 200: print('Request unsuccessful') sys.exit(-3) print('Storage found: ') storage_json = query_res.json() if storage_json['count'] != 1: print('Storage json does not contain correct amount of storage entries') sys.exit(-1) storage = storage_json['results'][0] print(f'ID: {storage["id"]}') print(f'Path: {storage["full_path"]}') labels = [] if storage['template'] == MICE_TOILET_TEMPLATE: side = input('Select type to be printed (top, bottom, storage) [t,b,s]:') if side not in ['t', 'b', 's']: print('Error - invalid side') return None if side == 's': label = shimatta_label.storage_label.StorageLabelSmdMiceToilet() storage = storage_json['results'][0] label.put_content(f'[stor_uuid]{storage["id"]}', storage['full_path'], storage['verbose_name']) return [label] row = input('Select which row shall be printed [1..3]:') if row not in char_range('1', '4'): print('Error - invalid row') return None row = int(row) storage_dict = get_child_storages(storage_query_url, token, uuid, 24) if side == 'b': for column in char_range('a','i'): label = shimatta_label.storage_label.StorageLabelSmdMiceToiletBottomQR() field_uuid = storage_dict[f'{column}{row}']['id'] label.put_content(f'[stor_uuid]{field_uuid}') labels.append(label) elif side == 't': for column in char_range('a','i'): label = shimatta_label.storage_label.StorageLabelSmdMiceToiletTop() if not storage_dict[f'{column}{row}']['ro_stocks']: print("Only printing start of row!!!") break comp = storage_dict[f'{column}{row}']['ro_stocks'][0]['ro_component'] param_dict = {param['ro_parameter_type']: param for param in comp['ro_parameters']} comp_name = get_component_print_name(comp) if not comp_name: return[] label.put_content(comp_name, f"{param_dict['Tolerance']['value']}% {comp['package_data']['name']}", comp['ro_manufacturer_name']) labels.append(label) elif storage['template'] == SMD_STRAP_PAGE_TEMPLATE: type = input('Select type to be printed (components, storage) [c,s]:') if type not in ['c', 's']: print('Error - invalid type') return None if type == 's': label = shimatta_label.storage_label.StorageLabelSmdStrap() label.put_content(f'[stor_uuid]{uuid}', storage['full_path'], storage['verbose_name']) labels.append(label) return [label] storage_dict = get_child_storages(storage_query_url, token, uuid, 12) for row in range(1,13): label = shimatta_label.component_label.StorageComponentLabelSmdBook() if not storage_dict[f'{row}']['ro_stocks']: print("Only printing start of column!!!") break storage_uuid = storage_dict[f'{row}']['id'] stock_uuild = storage_dict[f'{row}']['ro_stocks'][0]['id'] comp = storage_dict[f'{row}']['ro_stocks'][0]['ro_component'] param_dict = {param['ro_parameter_type']: param for param in comp['ro_parameters']} comp_name = get_component_print_name(comp) if not comp_name: return[] label.put_content(f'[stor_uuid]{storage_uuid}', f'[stck_uuid]{stock_uuild}', comp_name, f"{param_dict['Tolerance']['value']}% {comp['package_data']['name']}", comp['ro_manufacturer_name']) labels.append(label) pass else: label = shimatta_label.storage_label.StorageLabel() label.put_content(f'[stor_uuid]{uuid}', storage['full_path'], storage['verbose_name']) labels.append(label) return labels def handle_component_qr_code(base_url, token, uuid): query_url = urllib.parse.urljoin(base_url, 'api/v1/parts/components/') query_res = requests.get(query_url, headers={'Authorization': f'Token {token}'}, params={'id': uuid}) if query_res.status_code != 200: print('Request unsuccessful') sys.exit(-3) component = json.loads(query_res.content) if component['count'] != 1: sys.exit(-1) component = component['results'][0] pkg = '' name = component['name'] if component.get('package_data') is not None: pkg = component['package_data']['name'] manufacturer = component.get('ro_manufacturer_name') if manufacturer is None: manufacturer = '' print(f'Component found: Name: {name}, Package: {pkg}, Manufacturer: {manufacturer}') labels = [] label = shimatta_label.component_label.ComponentLabelSmall() comp_name = get_component_print_name(component) if not comp_name: return[] label.put_content(f'[comp_uuid]{uuid}', comp_name, manufacturer, pkg) labels.append(label) return labels if len(sys.argv) < 2: print(f'Usage: {sys.argv[0]} ') sys.exit(-1) qr_re = re.compile(r'^\[(?P[a-zA-Z_]+)\](?P[a-fA-F0-9\-]+)') kenkyusho_url = sys.argv[1] print(f"Shimatta Kenkyusho instance: {kenkyusho_url}") login_url = urllib.parse.urljoin(kenkyusho_url, 'api/v1/token-auth/') print(f'Token auth url: {login_url}') username = input('Username: ') password = getpass.getpass() ans = requests.post(login_url, data= {'username': username, 'password': password}) if ans.status_code != 200: print(f'Got status code {ans.status_code}') sys.exit(-1) login_token = json.loads(ans.content)['token'] while True: qr = input('Please scan Storage or Component QR: ') try: matches = qr_re.match(qr) if matches.group('prefix') == 'stor_uuid' : labels = handle_storage_qr_code(kenkyusho_url, login_token, matches.group('uuid')) elif matches.group('prefix') == 'comp_uuid': labels = handle_component_qr_code(kenkyusho_url, login_token, matches.group('uuid')) else: print('Invalid QR code!') continue if labels: ql_wrapper.print_labels(labels) except Exception as ex: print("Something went wrong:", ex)