class Photobooth: api = None printer = None lastMention = None def __init__(self, api): self.api = api self.printer = Usb(0x0416, 0x5011, 0, 0x81, 0x01) self.lastMention = self.api.GetMentions()[0].AsDict() def StartBooth(self): while True: if self.CheckForNewMention(): print("New mention! by " + self.lastMention['user']['screen_name']) self.SnapAndPrint() time.sleep(5) def CheckForNewMention(self): recentMention = api.GetMentions()[0].AsDict() if self.lastMention['id'] != recentMention['id']: self.lastMention = recentMention return True return False def SnapAndPrint(self): subprocess.run(PIC_COMMAND.split(" ")) dummy = Dummy() dummy.text("\n\n\nBravoLT - GRPS - 2019\n\n\n") dummy.image("out.jpg") dummy.text("\n\n\nBravoLT - GRPS - 2019") self.printer._raw(dummy.output)
class UsbPrinter(DummyPrinter): """ Initialize USB printer with vendor ID and product ID """ def __init__(self, config): super().__init__() vendor_id = int( config.config_dict['printer_config']['usb']['vendor_id'], 16) product_id = int( config.config_dict['printer_config']['usb']['product_id'], 16) self.p = None while self.p == None: try: self.p = Usb(vendor_id, product_id) except Exception as e: print(e) print("Trying again in 15 seconds") time.sleep(15) def print_ticket(self, order): super().print_ticket(order) y = True while y: try: self.p._raw(self.d.output) y = False except: print("might be reloading paper") time.sleep(10)
class ThermalPrinter(): def __init__(self): self.p = Usb(0x0fe6, 0x811e, 98, 0x82, 0x02) def insert_imagen(self, img_surce): self.p.image(img_surce) def insert_qr(self, content, size): self.p.qr(content, size=size) #size 1 - 16 default 3 def insert_barcode(self, code, bc, height, width): self.p.barcode(code, bc, height=height, width=width) def insert_text(self, txt): self.p.text(txt) def insert_raw_txt(self, txt): self.p._raw(txt) # harware action, may be: INIT, SELECT, RESET def hardware_operation(self, hw): self.p.hw(hw) #string for the following control sequences: # LF for Line Feed # FF for Form Feed # CR for Carriage Return # HT for Horizontal Tab # VT for Vertical Tab #pos = horizontal tab position 1 - 16 def feed_control(self, ctl, pos): self.p.control() self.p.charcode() # #def insert_textln(self, txt): # align = CENTER LEFT RIGHT default left # font_type = A or B default A # textt_type = B(bold), U(underline), U2(underline, version2), BU(for bold and underlined, NORMAL(normal text) defaul tnormal # width = width multiplier decimal 1 - 8 defaul 1 # heigh = height multiplier decimal 1 - 8 defaul 1 # density = density 0 - 8 # def set_txt(self, align, font, text_type, density, height, width): def set_txt(self, *args, **Kwargs): print(Kwargs) self.p.set(Kwargs) def cut_paper(self): self.p.cut()
def prints(self, code, align='left', qty=1): p_conf = settings.PRINTER_CONF usb_conf = p_conf['usb_conf'] printer = Usb(usb_conf['vendor_id'], usb_conf['product_id'], usb_conf['timeout'], usb_conf['input_endpoint'], usb_conf['output_endpoint']) dummy = Dummy() if align.upper() == "LEFT": dummy._raw(TXT_ALIGN_LT) else: dummy._raw(TXT_ALIGN_RT) dummy._raw(PD_P50) dummy._raw(BARCODE_HEIGHT + six.int2byte(120)) dummy._raw(BARCODE_WIDTH + six.int2byte(2)) dummy._raw(BARCODE_FONT_A) dummy._raw(BARCODE_TXT_BLW) dummy._raw(_SET_BARCODE_TYPE(2)) dummy._raw(code.encode()) printer._raw(dummy.output) printer._raw(NUL)
def do_usb_test(): from escpos.printer import Usb import io pt = EscPosPrint(encode='gb2312', temp_path='/tmp/print', width=384) with io.open('test/all.xml', 'r', encoding='utf8') as f: pt.auto_print(f.read()) import base64 # print(base64.encodebytes(pt.get_data())) # return # p = Usb(0x6868, 0x0500, in_ep=0x84, out_ep=0x3) # p = Usb(0x154f, 0x1300, in_ep=0x82, out_ep=0x01) p = Usb(0x0483, 0x5720, in_ep=0x82, out_ep=0x02) # p._raw(bytes([0x31,0x32,0x33,0x0A,0x1D,0x4C,0x50,0x00,0x31, 0x32,0x33, 0x0A]) + pt.get_data()) px = [ 0x1B, 0x53, 0x1D, 0x57, 0x80, 0x01, 0x1D, 0x4C, 0xF0, 0x00, 0x0a, # 0x31, 0x32, 0x33, 0x34, 0x34, 0x0A ] b = px + [ ord(c) for c in '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklnm\n' ] # b = [0x31, 0x32, 0x33, 0x0A, 0x1D, 0x4C, 0xE0, 0x00, 0x31, 0x32, 0x33, 0x0A] b = bytes(px) + pt.get_data()[2:] for i in b: print(hex(i)) p._raw(bytes(b)) p.close()
class PosPrinter: """ Class to interface with the POS printer. """ def __init__(self, product_id, vendor_id, test_mode=False): """ Also does error handling :param product_id: Printer product ID as integer :param vendor_id: Printer vendor ID as integer :param test_mode: boolean, when set to true modifies error messages and prevents modification of the global settings. Used for print tests (duh) :return: nil """ self.product_id = product_id self.vendor_id = vendor_id self._printer = None self.test_mode = test_mode # changes message end if test mode is true message_end = "\n\nPrinting disabled" if self.test_mode: message_end = "" self.failed = True # can be used to determine if a popup was shown - set false if successful in try below # in case printing is disabled (and test mode is disabled), just do nothing # if it's in test mode, you want it to actually do stuff and test... if not SETTINGS["printer"]["enable"] and not self.test_mode: return try: self._printer = Usb(self.product_id, self.vendor_id) self._printer.hw("INIT") self.failed = False except escpos.exceptions.USBNotFoundError: popup_message("Printer not found - please check the printer is plugged in and turned on and that the vendor" f" and product IDs correct.{message_end}", error=True) if not self.test_mode: SETTINGS["printer"]["enable"] = False except USBError as e: if "Errno 13" in str(e): popup_message(f"USB error 13 - it looks like something else is using the printer.\n\n{message_end}", error=True) if not self.test_mode: SETTINGS["printer"]["enable"] = False else: popup_message(f"{e}{message_end}", error=True) logger.exception("Unrecognised USB error") if not self.test_mode: SETTINGS["printer"]["enable"] = False except NoBackendError: print("nobackend") popup_message(f"There was an issue connecting to the printer. Please refer to the documentation.{message_end}", error=True) logger.exception("No backend was available - Possible mis-installation of libusb-1.0.dll or WinUSB driver.") if not self.test_mode: SETTINGS["printer"]["enable"] = False def print(self, data): """ Prints data if printer is initialised. :param data: binary data to send to POS printer :return: nil """ if self._printer is None: helper.add_event((lambda: True), (lambda: popup_message("Printer not initialised.\n\nPrinting disabled.", error=True))) self.failed = True if not self.test_mode: SETTINGS["printer"]["enable"] = False return self._printer._raw(data) def close(self): """ Closes printer connection :return: nil """ self._printer = None def reset(self): """ Closes and reopens printer connection :return: nil """ self.close() try: self._printer = Usb(self.product_id, self.vendor_id) except: # in the event of any error (eg NoBackendAvail) # TODO: Change to raise an exception or do something other than this self._printer = None def update_ids(self, product_id, vendor_id): """ Changes printer IDs and then resets :param product_id: printer product ID as integer :param vendor_id: printer vendor ID as integer :return: nil """ self.product_id = product_id self.vendor_id = vendor_id self.reset()
def post(self, request): sale_form = SaleFormSet(request.POST, prefix="sale") # ====================================== # Get investor who buy this checkout # ====================================== investor_id = request.POST.get('investor', '') if investor_id == "": investor_id = 0 investor = Investor.objects.filter(id=investor_id).first() if investor: buyer = investor.created_by # if buyer is not an investor, set buyer to id 0 else: buyer = User.objects.filter(id=0).first() if not buyer: buyer = User(id=0, username="******", email="*****@*****.**", first_name="None") buyer.save() # ====================================== is_checkout = False parameter = request.POST.get("parameter") # ====================================== # If checkhout finished, we add all the item in cart to checkout table # ====================================== if parameter == "checkout": is_checkout = True if request.POST.get("price") != "" and request.POST.get( "paid") != "": checkout = Checkout( price=request.POST.get("price"), paid=request.POST.get("paid"), created_by=buyer, sale_by=request.user, ) checkout.save() else: is_checkout = False parameter = "hold" # ====================================== # ====================================== # For every item in sale form, we add it into table # ====================================== item_sale_text = "" item_sale_discount_text = "" item_sale_amout = 0 item_sale_discount_amout = 0 item_sale_cashback_amout = 0 for s in sale_form: if s.is_valid() and len(s.cleaned_data) > 0: product = Product.objects.filter( id62=s.cleaned_data['product_id62']).first() item_sale = Sale( product=product, amount=int(s.cleaned_data['quantity']) * int(s.cleaned_data['price'].replace(",", "")), qty=int(s.cleaned_data['quantity']), price=int(s.cleaned_data['price'].replace(",", "")), created_by=buyer, sale_by=request.user, ) if product.applied_discount(): item_sale.discount = product.applied_discount() if is_checkout: item_sale.status = 4 item_sale.checkout = checkout item_sale.save() cashback = item_sale.sold(request.user, buyer) product.sale(int(s.cleaned_data['quantity'])) item_sale_amout += item_sale.amount item_sale_text += "%s @%d x%d %d\n" % ( product.display_name, item_sale.price, item_sale.qty, item_sale.amount) item_sale_cashback_amout += cashback if product.applied_discount(): amount_discounted = item_sale.qty * ( item_sale.price - item_sale.discounted_price) item_sale_discount_text += "%s %d%% %d\n" % ( product.display_name, item_sale.discount.reduction, amount_discounted) item_sale_discount_amout += amount_discounted else: if parameter == "cancel": item_sale.status = 2 if parameter == "hold": item_sale.status = 3 item_sale.save() else: print s.errors # ====================================== p_conf = settings.PRINTER_CONF if is_checkout and p_conf['print_on']: usb_conf = p_conf['usb_conf'] printer = Usb(usb_conf['vendor_id'], usb_conf['product_id'], usb_conf['timeout'], usb_conf['input_endpoint'], usb_conf['output_endpoint']) receipt = Dummy() receipt.set(height=2, align='center', text_type="B") receipt.text('Koperasi Warung Kita Untuk Kita\n') receipt.set(align='center') receipt.text('Tanggal: %s - Pukul: %s\n' % (datetime.datetime.now().strftime("%d-%m-%Y"), datetime.datetime.now().strftime("%H:%M"))) receipt.text('==============================================\n\n') receipt.set(align='right') receipt.text(item_sale_text) receipt.text('============================\n') receipt.text('Total : Rp. %d\n\n' % item_sale_amout) if item_sale_discount_amout > 0: receipt.set(align='center') receipt.text('Diskon\n') receipt.set(align='right') receipt.text(item_sale_discount_text) receipt.text('============================\n') receipt.text('Total Diskon: Rp.%d\n\n' % item_sale_discount_amout) receipt.set(text_type="B", align="right") receipt.text('Total Harga : Rp.%d\n' % item_sale_amout) if item_sale_discount_amout > 0: receipt.text('- Rp.%d\n' % item_sale_discount_amout) receipt.text('(Rp.%d)\n' % (item_sale_amout - item_sale_discount_amout)) receipt.text('Bayar : Rp.%s\n' % checkout.paid) receipt.text('Kembalian : Rp.%d\n\n\n' % (int(checkout.paid) - (item_sale_amout - item_sale_discount_amout))) receipt.set(height=2, align='center', text_type="B") if buyer.id > 0: receipt.text('%s %s\nTerimakasih Telah Berbelanja\n\n' % (buyer.first_name, buyer.last_name)) receipt.text('Anda Mendapatkan Cashback Sebesar Rp.%d' % item_sale_cashback_amout) else: receipt.text('Terimakasih Telah Berbelanja') if p_conf['cut_paper']: receipt.cut() if p_conf['kick_drawer']: receipt.cashdraw(2) printer._raw(receipt.output) return redirect(reverse("core:sale"))
class Receipt: def __init__(self): from escpos.printer import Usb, Dummy self.eps = Usb(0x4b8, 0x0e03) self.dps = Dummy() def print_header(self, opts): """Responsible for printing the header part of the receipt, :param:opts: include all options that could go into the header like logo, company name and all that """ if COMPANY_LOGO in opts.keys(): self.imgesprint(opts[COMPANY_LOGO]) self.esprint(LINE_BREAK) if COMPANY_NAME in opts.keys(): self.esprint(opts[COMPANY_NAME]) self.esprint(LINE_BREAK) if COMPANY_CONTACT in opts.keys(): self.esprint(TEL) self.esprint(opts[COMPANY_CONTACT]) self.esprint(LINE_BREAK) if COMPANY_LOCATION in opts.keys(): self.esprint(LOC) self.esprint(opts[COMPANY_LOCATION]) self.esprint(LINE_BREAK) self.n_char(SN_RULER, PAPER_MAX_WIDTH, w=1, h=1) self.esprint(LINE_BREAK) if RECEIPT_NAME in opts.keys(): RNO = opts[RECEIPT_NUMBER] if RECEIPT_NUMBER in opts.keys() else '' RECEIPT = opts[RECEIPT_NAME] + SPACE_CHAR + HASH_NO + RNO self.cesprint(RECEIPT) char = len(RECEIPT) self.cesprint(self.n_char_generate(DO_RULER, char), w=1, h=2) self.esprint(LINE_BREAK) if CUSTOMER_NAME in opts.keys(): self.lesprint(CUSTOMER, LEFT_PROPERTY_WIDTH) self.esprint(COLON_CHAR) self.n_char(SPACE_CHAR, LR_ALIGN) self.esprint(opts[CUSTOMER_NAME]) self.esprint(LINE_BREAK) if CASHIER_NAME in opts.keys(): self.lesprint(CASHIER, LEFT_PROPERTY_WIDTH) self.esprint(COLON_CHAR) self.n_char(SPACE_CHAR, LR_ALIGN) self.esprint(opts[CASHIER_NAME]) self.esprint(LINE_BREAK) if RECEIPT_DATE in opts.keys(): self.lesprint(DATE, LEFT_PROPERTY_WIDTH) self.esprint(COLON_CHAR) self.n_char(SPACE_CHAR, LR_ALIGN) self.esprint(opts[RECEIPT_DATE]) self.esprint(LINE_BREAK) if CURRENCY_NAME in opts.keys(): self.lesprint(CURRENCY_NAME_TITLE, LEFT_PROPERTY_WIDTH) self.esprint(COLON_CHAR) self.n_char(SPACE_CHAR, LR_ALIGN) self.esprint(opts[CURRENCY_NAME]) self.esprint(LINE_BREAK) def print_items(self, items): """Responsible for printing the receipt part of the receipt. """ self.n_char(SN_RULER, PAPER_MAX_WIDTH, w=1, h=1) self.esprint(LINE_BREAK) self.esprint(ITEM_TITLE) self.n_char(SPACE_CHAR, ITEM_TITLE_SPACE_AFTER) self.esprint(QTY_TITLE) self.n_char(SPACE_CHAR, QTY_TITLE_SPACE_AFTER) self.esprint(SP_TITLE) self.n_char(SPACE_CHAR, SP_TITLE_SPACE_AFTER) self.esprint(TOTAL_TITLE) self.n_char(SPACE_CHAR, TOTAL_TITLE_SPACE_AFTER) self.esprint(LINE_BREAK) self.n_char(DO_RULER, PAPER_MAX_WIDTH, w=1, h=2) self.esprint(LINE_BREAK) sum_total = 0 for item in items: product = item[ITEM] if len(item[ITEM]) < ITEM_MAX_WIDTH else item[ ITEM][:ITEM_MAX_WIDTH - ELIPSES_WIDTH] + ELIPSES qty = item[QTY] if isinstance(item[QTY], int) else round( str_2_num(item[QTY]), 2) price = round(str_2_num(item[SP]), 2) total = round(qty * price, 2) sum_total += total self.print_space(product, ITEM_MAX_WIDTH) self.print_space(str(qty), QTY_MAX_WIDTH) self.print_space(str(price), SP_MAX_WIDTH) self.print_space(str(total), TOTAL_MAX_WIDTH) self.esprint(LINE_BREAK) self.n_char(SN_RULER, PAPER_MAX_WIDTH, w=1, h=1) self.esprint(LINE_BREAK) self.esprint(TOTAL_TXT) leave = TOTAL_TXT_WIDTH self.n_char(SPACE_CHAR, PAPER_MAX_WIDTH - TOTAL_MAX_WIDTH - leave, w=1, h=1) self.esprint(str(sum_total)) self.esprint(LINE_BREAK) self.n_char(DO_RULER, PAPER_MAX_WIDTH, w=1, h=2) self.esprint(LINE_BREAK) def print_message(self, msg): self.cesprint(msg, char=STAR_CHAR) self.esprint(LINE_BREAK) def print_vat(self, vmsg): self.esprint(LINE_BREAK) self.cesprint(vmsg) self.esprint(LINE_BREAK) def print_me(self, me): self.esprint(me) def print_space(self, text, width, w=1, h=1): """Print text and then print space character for remaining space = width - texlen. For now texlen is not expected to be greater than width, if so just truncate to width. """ texlen = len(text) if texlen > width: text = text[:width] self.lesprint(text, width) def imgesprint(self, path, align='center'): """Responsible for image printing""" self.dps.set(align=align) self.dps.image(path) def esprint(self, text, w=1, h=1): """A prudent wrapper around printing text with [self.eps.text()]""" self.dps.set(height=h, width=w) self.dps.text(text) def escut(self): self.eps.cut() def estop(self): self.eps.close() def cesprint(self, text, width=PAPER_MAX_WIDTH, char=SPACE_CHAR, w=1, h=1): """center align text and fill space left with :param:char:""" texlen = len(text) if texlen > width: diff = width % texlen else: diff = width - texlen if diff == 0: ldiff = rdiff = 0 elif diff % 2 == 0: ldiff = rdiff = diff // 2 else: ldiff = diff // 2 rdiff = ldiff + 1 self.n_char(char, ldiff) self.esprint(text, w, h) self.n_char(char, rdiff) def resprint(self, text, width=PAPER_MAX_WIDTH, char=SPACE_CHAR, w=1, h=1): """right align text and fill space left with :param:char:""" texlen = len(text) diff = width - texlen self.n_char(char, diff) self.esprint(text, w, h) def lesprint(self, text, width=PAPER_MAX_WIDTH, char=SPACE_CHAR, w=1, h=1): """light align text and fill space left with :param:char:""" texlen = len(text) diff = width - texlen self.esprint(text, w, h) self.n_char(char, diff, w, h) def n_char(self, char, n, w=1, h=1): """Print char n times""" for i in range(n): self.esprint(char, w, h) def n_char_generate(self, char, n): """ Return string of char n time""" return char * n def get_longest_item(self, items): """Return the length of the longest Item name in the list of items """ # Assume longest is initially zero longest = 0 for item in items: # get length of item name length = len(item[ITEM]) if length > longest: longest = length return longest def esecute(self): self.eps._raw(self.dps.output)
''' This script resets the escpos printer ''' import sys from escpos.printer import Usb from escpos import exceptions VENDOR_ID = 0x0456 PRODUCT_ID = 0x0808 P_INTERFACE = 4 P_IN_ENDPOINT = 0x81 P_OUT_ENDPOINT = 0x03 p = Usb(VENDOR_ID, PRODUCT_ID, P_INTERFACE, P_IN_ENDPOINT, P_OUT_ENDPOINT) reset_cmd = b'\x1b?\n\x00' try: p._raw(reset_cmd) except Exception as e: print(e) sys.exit(1)
font = ImageFont.truetype("/home/francisco/gunplay3.ttf", 50) precio = "$30.00" codigo_barras = '1324354657687' descripcion_producto = '123456789 123456789 123456789 123456789' #Calcular el ancho y alto del font imgFont = Image.new("RGBA", (400, 200), (255, 255, 255)) drawFont = ImageDraw.Draw(imgFont) WF, HF = drawFont.textsize(precio, font=font) deltaHF = int(round((HF * 0.40))) #Calcular el tamano del lienzo para dibujar W, H = (WF + 4, HF + deltaHF) img = Image.new("RGBA", (W, H), (255, 255, 255)) draw = ImageDraw.Draw(img) #Dibujar el precio draw.text(((W - WF) / 2, 1), precio, (0, 0, 0), font=font) #Dibujar un recuadro dentro de la imagen. #draw.rectangle(((0, 0), (W-1, H-1)),outline="red") img.save("a_test.png") p.text(descripcion_producto + "\n") p.barcode(codigo_barras, 'EAN13', 64, 2, '', '') p.image("a_test.png") p.barcode(codigo_barras, 'EAN13', 34, 2, '', '') #p.cut(mode='FULL',feed=False) #El origininal tenia. self._raw(b"\n\n\n\n\n\n") #Cortar el papel y corregir fix con saltos de linea. p._raw(b"\n\n\n\n\n") p._raw(PAPER_FULL_CUT)