Match the current printer-db format.
This commit is contained in:
parent
216184f43f
commit
a07f84a5bc
3
setup.py
3
setup.py
|
@ -83,7 +83,8 @@ setup(
|
|||
platforms='any',
|
||||
package_dir={"": "src"},
|
||||
packages=find_packages(where="src", exclude=["tests", "tests.*"]),
|
||||
package_data={'': ['COPYING']},
|
||||
package_data={'': ['COPYING', 'src/escpos/capabilities.json']},
|
||||
include_package_data=True,
|
||||
classifiers=[
|
||||
'Development Status :: 4 - Beta',
|
||||
'Environment :: Console',
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,40 +1,53 @@
|
|||
import re
|
||||
import six
|
||||
from os import path
|
||||
import yaml
|
||||
|
||||
|
||||
with open(path.join(path.dirname(__file__), 'capabilities.yml')) as f:
|
||||
PROFILES = yaml.load(f)
|
||||
# Load external printer database
|
||||
with open(path.join(path.dirname(__file__), 'capabilities.json')) as f:
|
||||
CAPABILITIES = yaml.load(f)
|
||||
PROFILES = CAPABILITIES['profiles']
|
||||
ENCODINGS = CAPABILITIES['encodings']
|
||||
|
||||
|
||||
class Profile(object):
|
||||
class NotSupported(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class BaseProfile(object):
|
||||
"""This respresents a printer profile.
|
||||
|
||||
A printer profile knows about the number of columns, supported
|
||||
features, colors and more.
|
||||
"""
|
||||
|
||||
profile_data = {}
|
||||
|
||||
def __init__(self, columns=None):
|
||||
self.default_columns = columns
|
||||
|
||||
def __getattr__(self, name):
|
||||
return self.profile_data[name]
|
||||
|
||||
def get_font(self, font):
|
||||
"""Return the escpos index for `font`. Makes sure that
|
||||
the requested `font` is valid.
|
||||
"""
|
||||
font = {'a': 0, 'b': 1}.get(font, font)
|
||||
if not six.text_type(font) in self.fonts:
|
||||
raise NotSupported(
|
||||
'"%s" is not a valid font in the current profile' % font)
|
||||
return font
|
||||
|
||||
def get_columns(self, font):
|
||||
""" Return the number of columns for the given font.
|
||||
"""
|
||||
if self.default_columns:
|
||||
return self.default_columns
|
||||
|
||||
if 'columnConfigs' in self.profile_data:
|
||||
columns_def = self.columnConfigs[self.defaultColumnConfig]
|
||||
|
||||
elif 'columns' in self.profile_data:
|
||||
columns_def = self.columns
|
||||
|
||||
if isinstance(columns_def, int):
|
||||
return columns_def
|
||||
return columns_def[font]
|
||||
font = self.get_font(font)
|
||||
return self.fonts[six.text_type(font)]['columns']
|
||||
|
||||
|
||||
def get_profile(name=None, **kwargs):
|
||||
"""Get the profile by name; if no name is given, return the
|
||||
default profile.
|
||||
"""
|
||||
if isinstance(name, Profile):
|
||||
return name
|
||||
|
||||
|
@ -42,15 +55,19 @@ def get_profile(name=None, **kwargs):
|
|||
return clazz(**kwargs)
|
||||
|
||||
|
||||
|
||||
CLASS_CACHE = {}
|
||||
|
||||
|
||||
def get_profile_class(name):
|
||||
"""For the given profile name, load the data from the external
|
||||
database, then generate dynamically a class.
|
||||
"""
|
||||
if not name in CLASS_CACHE:
|
||||
profile_data = resolve_profile_data(name)
|
||||
class_name = '%sProfile' % clean(name)
|
||||
new_class = type(class_name, (Profile,), {'profile_data': profile_data})
|
||||
profile_data = PROFILES[name]
|
||||
profile_name = clean(name)
|
||||
class_name = '{}{}Profile'.format(
|
||||
profile_name[0].upper(), profile_name[1:])
|
||||
new_class = type(class_name, (BaseProfile,), {'profile_data': profile_data})
|
||||
CLASS_CACHE[name] = new_class
|
||||
|
||||
return CLASS_CACHE[name]
|
||||
|
@ -64,20 +81,20 @@ def clean(s):
|
|||
return str(s)
|
||||
|
||||
|
||||
def resolve_profile_data(name):
|
||||
data = PROFILES[name]
|
||||
inherits = data.get('inherits')
|
||||
if not inherits:
|
||||
return data
|
||||
# For users, who want to provide their profile
|
||||
class Profile(get_profile_class('default')):
|
||||
|
||||
def __init__(self, columns=None):
|
||||
super(Profile, self).__init()
|
||||
|
||||
self.columns = columns
|
||||
|
||||
def get_columns(self, font):
|
||||
if self.columns is not None:
|
||||
return columns
|
||||
|
||||
return super(Profile, self).get_columns(font)
|
||||
|
||||
if not isinstance(inherits, (tuple, list)):
|
||||
inherits = [inherits]
|
||||
|
||||
merged = {}
|
||||
for base in reversed(inherits):
|
||||
base_data = resolve_profile_data(base)
|
||||
merged.update(base_data)
|
||||
merged.update(data)
|
||||
return merged
|
||||
|
||||
|
||||
|
|
|
@ -1,252 +0,0 @@
|
|||
# Define code pages that implementors are likely not to find in iconv etc.
|
||||
codepages:
|
||||
blank: [
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
]
|
||||
TCVN-3-1: [
|
||||
" ",
|
||||
" ",
|
||||
" ăâêôơưđ ",
|
||||
" àảãáạ ằẳẵắ ",
|
||||
" ặầẩẫấậè ẻẽ",
|
||||
"éẹềểễếệìỉ ĩíịò",
|
||||
" ỏõóọồổỗốộờởỡớợù",
|
||||
" ủũúụừửữứựỳỷỹýỵ ",
|
||||
]
|
||||
TCVN-3-2: [
|
||||
" ",
|
||||
" ",
|
||||
" ĂÂ Ð ÊÔƠƯ ",
|
||||
" ÀẢÃÁẠ ẰẲẴẮ ",
|
||||
" ẶẦẨẪẤẬÈ ẺẼ",
|
||||
"ÉẸỀỂỄẾỆÌỈ ĨÍỊÒ",
|
||||
" ỎÕÓỌỒỔỖỐỘỜỞỠỚỢÙ",
|
||||
" ỦŨÚỤỪỬỮỨỰỲỶỸÝỴ "
|
||||
]
|
||||
|
||||
|
||||
commands:
|
||||
LineFeed:
|
||||
name: Line feed
|
||||
FeedAndCut:
|
||||
name: Feed and cut
|
||||
SetAbsolutePrintPos:
|
||||
name: Set absolute print position
|
||||
GraphicsData:
|
||||
name: Graphics data
|
||||
|
||||
|
||||
profiles:
|
||||
default:
|
||||
name: Default profile
|
||||
description: Many recent Epson-branded thermal receipt printers
|
||||
commands:
|
||||
BarcodeB: true
|
||||
BitImage: true
|
||||
GraphicsData: true
|
||||
QrCode: true
|
||||
features:
|
||||
starCommands: false
|
||||
font:
|
||||
0:
|
||||
columns: 40
|
||||
1:
|
||||
columns: 50
|
||||
colors:
|
||||
- black
|
||||
# Commented-out slots are TODO (might just need uncomment, might
|
||||
# need verification/research)
|
||||
codepages:
|
||||
0: CP437
|
||||
1: CP932
|
||||
2: CP850
|
||||
3: CP860
|
||||
4: CP863
|
||||
5: CP865
|
||||
#6: // Hiragana
|
||||
#7: // One-pass printing Kanji characters
|
||||
#8: // Page 8 [One-pass printing Kanji characters]
|
||||
11: CP851
|
||||
12: CP853
|
||||
13: CP857
|
||||
14: CP737
|
||||
15: ISO8859_7
|
||||
16: CP1252
|
||||
17: CP866
|
||||
18: CP852
|
||||
19: CP858
|
||||
#20: // Thai Character Code 42
|
||||
#21: // Thai Character Code 1
|
||||
#22: // Thai Character Code 13
|
||||
#23: // Thai Character Code 14
|
||||
#24: // Thai Character Code 16
|
||||
#25: // Thai Character Code 17
|
||||
#26: // Thai Character Code 18
|
||||
30: 'TCVN-3-1' # TCVN-3: Vietnamese
|
||||
31: 'TCVN-3-2' # TCVN-3: Vietnamese
|
||||
32: CP720
|
||||
33: CP775
|
||||
34: CP855
|
||||
35: CP861
|
||||
36: CP862
|
||||
37: CP864
|
||||
38: CP869
|
||||
39: ISO8859_2
|
||||
40: ISO8859_15
|
||||
41: CP1098
|
||||
42: CP774
|
||||
43: CP772
|
||||
44: CP1125
|
||||
45: CP1250
|
||||
46: CP1251
|
||||
47: CP1253
|
||||
48: CP1254
|
||||
49: CP1255
|
||||
50: CP1256
|
||||
51: CP1257
|
||||
52: CP1258
|
||||
53: RK1048
|
||||
#66: // Devanagari
|
||||
#67: // Bengali
|
||||
#68: // Tamil
|
||||
#69: // Telugu
|
||||
#70: // Assamese
|
||||
#71: // Oriya
|
||||
#72: // Kannada
|
||||
#73: // Malayalam
|
||||
#74: // Gujarati
|
||||
#75: // Punjabi
|
||||
#82: // Marathi
|
||||
#254:
|
||||
#255:
|
||||
|
||||
|
||||
# Designed for non-Epson printers sold online. Without knowing
|
||||
# their character encoding table, only CP437 output is assumed,
|
||||
# and graphics() calls will be disabled, as it usually prints junk
|
||||
# on these models.
|
||||
simple:
|
||||
inherits: default
|
||||
name: Simple profile
|
||||
codePages:
|
||||
0: CP437
|
||||
commands:
|
||||
graphicsData: false
|
||||
|
||||
|
||||
star:
|
||||
name: Star-branded printers
|
||||
inherits: default
|
||||
features:
|
||||
starCommands: false
|
||||
|
||||
|
||||
printers:
|
||||
P-822D:
|
||||
inherits: default
|
||||
manufacturer: "Epson"
|
||||
commands:
|
||||
graphicsData: false
|
||||
|
||||
# http://support.epostraders.co.uk/support-files/documents/3/l7O-TM-T88II_TechnicalRefGuide.pdf
|
||||
TM-T88II:
|
||||
inherits: default
|
||||
manufacturer: "Epson"
|
||||
fonts:
|
||||
a:
|
||||
columns: 42
|
||||
b:
|
||||
columns: 56
|
||||
codePages:
|
||||
0: PC437
|
||||
1: Katakana
|
||||
2: PC850
|
||||
3: PC860
|
||||
4: PC863
|
||||
5: PC865
|
||||
19: PC858
|
||||
255: blank
|
||||
|
||||
# http://support.epostraders.co.uk/support-files/documents/3/l7O-TM-T88II_TechnicalRefGuide.pdf
|
||||
TM-T88III:
|
||||
inherits: default
|
||||
manufacturer: "Epson"
|
||||
fonts:
|
||||
a:
|
||||
columns: 42
|
||||
b:
|
||||
columns: 56
|
||||
codePages:
|
||||
- PC437 # 0
|
||||
- Katakana # 1
|
||||
- PC850 # 2
|
||||
- PC860 # 3
|
||||
- PC863 # 4
|
||||
- PC865 # 5
|
||||
- WPC1252 # 16
|
||||
- PC866 # 17
|
||||
- PC852 # 18
|
||||
- PC858 # 19
|
||||
- blank
|
||||
|
||||
TM-P80:
|
||||
inherits: default
|
||||
manufacturer: "Epson"
|
||||
fonts:
|
||||
a:
|
||||
columns: 48
|
||||
b:
|
||||
columns: 64
|
||||
kanji:
|
||||
columns: 24
|
||||
|
||||
TM-P80 (42 column emulation mode):
|
||||
inherits: TM-P80
|
||||
fonts:
|
||||
a:
|
||||
columns: 42
|
||||
b:
|
||||
columns: 60
|
||||
kanji:
|
||||
columns: 21
|
||||
|
||||
TM-P60II 2 (58mm):
|
||||
inherits: default
|
||||
manufacturer: "Epson"
|
||||
media:
|
||||
width:
|
||||
mm: 58
|
||||
fonts:
|
||||
a: {columns: 35}
|
||||
b: {columns: 42}
|
||||
c: {columns: 52}
|
||||
|
||||
TM-P60II 2 (60mm):
|
||||
inherits: default
|
||||
manufacturer: "Epson"
|
||||
media:
|
||||
width:
|
||||
mm: 60
|
||||
fonts:
|
||||
a: {columns: 36}
|
||||
b: {columns: 43}
|
||||
c: {columns: 54}
|
||||
|
||||
TM-P20 2:
|
||||
inherits: default
|
||||
manufacturer: "Epson"
|
||||
fonts: [a, b c, d, e, f]
|
||||
|
||||
TM-T90:
|
||||
inherits: default
|
||||
manufacturer: "Epson"
|
||||
colors:
|
||||
- black
|
||||
- red
|
|
@ -93,14 +93,17 @@ TXT_UNDERL_ON = ESC + b'\x2d\x01' # Underline font 1-dot ON
|
|||
TXT_UNDERL2_ON = ESC + b'\x2d\x02' # Underline font 2-dot ON
|
||||
TXT_BOLD_OFF = ESC + b'\x45\x00' # Bold font OFF
|
||||
TXT_BOLD_ON = ESC + b'\x45\x01' # Bold font ON
|
||||
TXT_FONT_A = ESC + b'\x4d\x00' # Font type A
|
||||
TXT_FONT_B = ESC + b'\x4d\x01' # Font type B
|
||||
TXT_ALIGN_LT = ESC + b'\x61\x00' # Left justification
|
||||
TXT_ALIGN_CT = ESC + b'\x61\x01' # Centering
|
||||
TXT_ALIGN_RT = ESC + b'\x61\x02' # Right justification
|
||||
TXT_INVERT_ON = GS + b'\x42\x01' # Inverse Printing ON
|
||||
TXT_INVERT_OFF = GS + b'\x42\x00' # Inverse Printing OFF
|
||||
|
||||
# Fonts
|
||||
SET_FONT = lambda n: ESC + b'\x4d' + n
|
||||
TXT_FONT_A = SET_FONT(b'\x00') # Font type A
|
||||
TXT_FONT_B = SET_FONT(b'\x01') # Font type B
|
||||
|
||||
# Char code table
|
||||
CHARCODE_PC437 = ESC + b'\x74\x00' # USA: Standard Europe
|
||||
CHARCODE_JIS = ESC + b'\x74\x01' # Japanese Katakana
|
||||
|
|
|
@ -452,8 +452,8 @@ class Escpos(object):
|
|||
col_count = self.profile.get_columns(font) if columns is None else columns
|
||||
self.text(textwrap.fill(txt, col_count))
|
||||
|
||||
def set(self, align='left', font='a', text_type='normal', width=1, height=1, density=9, invert=False, smooth=False,
|
||||
flip=False):
|
||||
def set(self, align='left', font='a', text_type='normal', width=1,
|
||||
height=1, density=9, invert=False, smooth=False, flip=False):
|
||||
""" Set text properties by sending them to the printer
|
||||
|
||||
:param align: horizontal position for text, possible values are:
|
||||
|
@ -463,7 +463,9 @@ class Escpos(object):
|
|||
* RIGHT
|
||||
|
||||
*default*: LEFT
|
||||
:param font: font type, possible values are A or B, *default*: A
|
||||
|
||||
:param font: font given as an index, a name, or one of the
|
||||
special values 'a' or 'b', refering to fonts 0 and 1.
|
||||
:param text_type: text type, possible values are:
|
||||
|
||||
* B for bold
|
||||
|
@ -528,10 +530,8 @@ class Escpos(object):
|
|||
self._raw(TXT_BOLD_OFF)
|
||||
self._raw(TXT_UNDERL_OFF)
|
||||
# Font
|
||||
if font.upper() == "B":
|
||||
self._raw(TXT_FONT_B)
|
||||
else: # DEFAULT FONT: A
|
||||
self._raw(TXT_FONT_A)
|
||||
self._raw(SET_FONT(six.int2byte(self.profile.get_font(font))))
|
||||
|
||||
# Align
|
||||
if align.upper() == "CENTER":
|
||||
self._raw(TXT_ALIGN_CT)
|
||||
|
|
Loading…
Reference in New Issue