Browse Source

Initial commit

master
Macoy Madson 6 months ago
parent
commit
812785a272
8 changed files with 199 additions and 2 deletions
  1. +3
    -0
      .gitmodules
  2. +0
    -2
      README.md
  3. +18
    -0
      ReadMe.org
  4. +9
    -0
      TestPrint.org
  5. +166
    -0
      ThermalPrinterConverter.py
  6. +1
    -0
      modules/zj-58
  7. +2
    -0
      printOutput.sh
  8. BIN
      reference/ESCPOS_Command_Manual.pdf

+ 3
- 0
.gitmodules View File

@@ -0,0 +1,3 @@
[submodule "modules/zj-58"]
path = modules/zj-58
url = https://github.com/klirichek/zj-58

+ 0
- 2
README.md View File

@@ -1,2 +0,0 @@
# thermal-printer-converter
An Org Mode to ESCPOS converter

+ 18
- 0
ReadMe.org View File

@@ -0,0 +1,18 @@
#+TITLE:Thermal Printer Converter
I bought a ~Zijiang-ZJ-58~ from Amazon, but found that the existing Linux software did not print in the correct format, or not how I wanted. These scripts output in the ESCPOS format, which is what the printer uses internally.

* TODO Setup
[[http://scruss.com/blog/2015/07/12/thermal-printer-driver-for-cups-linux-and-raspberry-pi-zj-58/][Article]]
[[https://github.com/klirichek/zj-58][Driver]]

#+BEGIN_SRC sh
sudo apt install build-essential cmake libcups2-dev libcupsimage2-dev
sudo apt install -y system-config-printer
#+END_SRC

[[https://www.techrepublic.com/article/control-printers-in-linux-from-the-command-line/][Command line operation]]
* Use
#+BEGIN_SRC sh
python3 EpsonESCPOSConverter.py
./printOutput.sh
#+END_SRC

+ 9
- 0
TestPrint.org View File

@@ -0,0 +1,9 @@
#+TITLE:Big Title with some text that needs wrapping
* Heading
Welcome to the test print.
** Subheading 1
This is some text which is going to cause the printer to wrap the line. Is it going to wrap the line properly? Only time will tell.
*** This is a deeper heading
Any heading as deep or deeper will look the same as this one.
** Subheading 2
Here's another heading.

+ 166
- 0
ThermalPrinterConverter.py View File

@@ -0,0 +1,166 @@
import textwrap

# Output a binary file which a ESCPOS thermal printer will understand
# References:
# - Command manual PDF, in this repository
# - https://www.neodynamic.com/articles/How-to-print-raw-ESC-POS-commands-from-Javascript/

outputFilename = "output.bin"

esc = '\x1B'; # ESC byte in hex notation
newLine = '\x0A'; # LF byte in hex notation

# Emphasized + Double-height + Double-width mode selected (ESC ! (8 + 16 + 32)) 56 dec => 38 hex
TextStyle_Large = '\x38'
TextStyle_DoubleWidth = '\x20'
TextStyle_RegularEmphasis = '\x08' # Regular size + emphasis (0 + 8)
TextStyle_Regular = '\x00'

# Format specifier, column width
lineWrapColumns = {TextStyle_Large:16, TextStyle_DoubleWidth:16,
TextStyle_RegularEmphasis:32, TextStyle_Regular:32}

gOutputBuffer = ''
gCurrentTextStyle = TextStyle_Regular

def writeOutputBuffer():
global gOutputBuffer
encodedString = gOutputBuffer.encode("ascii")
# I think the printer needs to be told this is the desired format
# encodedString = gOutputBuffer.encode("gb18030")
print("Outputting to {}".format(outputFilename))
outFile = open(outputFilename, "wb")
outFile.write(encodedString)
outFile.close()

def setTextStyle(styleSpecifier):
global gCurrentTextStyle
if styleSpecifier not in lineWrapColumns:
print("Warning: style specifier '{}' not fully supported".format(styleSpecifier))

outputRaw(esc + '!' + styleSpecifier)
gCurrentTextStyle = styleSpecifier

def outputInitializationCode():
# Initializes the printer (ESC @)
outputRaw(esc + "@")
setTextStyle(TextStyle_Regular)

# Don't fix up newlines or anything
def outputRaw(outString):
global gOutputBuffer
gOutputBuffer += outString

# Wrap lines and convert newlines to the appropriate format character
# TODO: Make empty lines newlines still show up instead of being removed by this
def outputTextBlock(outString):
global gOutputBuffer

wrapWidth = lineWrapColumns[gCurrentTextStyle]
# Fix newlines and wrap
# lines = outString.replace('\n', newLine).split(newLine)
# print("'" + outString + "'")
lines = outString.split("\n")
wrappedLines = []
for line in lines:
wrappedLines += textwrap.wrap(line, width=wrapWidth)
# print(wrappedLines)
# exit()
for line in wrappedLines:
print('"' + line + '"')
if line:
gOutputBuffer += line + newLine
# print(line)
else:
gOutputBuffer += newLine
# print("")

def lineHasTagExactly(line, tag):
return len(line) >= len(tag) and tag in line[:len(tag)]

def lineGetTaggedValue(line, tag):
return line[len(tag):]
def orgModeToEscPos(orgLines):
for line in orgLines:
if lineHasTagExactly(line, '#+TITLE:'):
setTextStyle(TextStyle_Large)
outputTextBlock("\n" + lineGetTaggedValue(line, '#+TITLE:'))
# Headings
elif lineHasTagExactly(line, '* '):
setTextStyle(TextStyle_DoubleWidth)
outputTextBlock("\n" + lineGetTaggedValue(line, '* '))
elif lineHasTagExactly(line, '** '):
setTextStyle(TextStyle_RegularEmphasis)
outputTextBlock("\n" + lineGetTaggedValue(line, '** '))
# All deeper headings are just bolded and have a space at the start
elif line[0] == "*":
setTextStyle(TextStyle_RegularEmphasis)
outputTextBlock("\n" + line[line.find(" "):])
# Body text
else:
setTextStyle(TextStyle_Regular)
outputTextBlock(line, TextStyle_Regular)

def main():
outputInitializationCode()

orgFile = open("TestPrint.org", "r")
orgLines = orgFile.readlines()
orgFile.close()

orgModeToEscPos(orgLines)

writeOutputBuffer()

return

# Bit image mode (doesn't work)
# outputRaw(esc + '*' + TextStyle_Regular + TextStyle_RegularEmphasis + TextStyle_RegularEmphasis +
# '\x08\x00\x08\x08\x00\x08\x00\x08' +
# '\x08\x00\x08\x08\x00\x08\x00\x08' +
# '\x08\x00\x08\x08\x00\x08\x00\x08' +
# '\x08\x00\x08\x08\x00\x08\x00\x08' +
# '\x08\x00\x08\x08\x00\x08\x00\x08')

# outputRaw('\x1D' + '\x2A' + TextStyle_DoubleWidth + TextStyle_DoubleWidth + TextStyle_RegularEmphasis +
# '\x08\x00\x08\x08\x00\x08\x00\x08' +
# '\x08\x00\x08\x08\x00\x08\x00\x08' +
# '\x08\x00\x08\x08\x00\x08\x00\x08' +
# '\x08\x00\x08\x08\x00\x08\x00\x08' +
# '\x08\x00\x08\x08\x00\x08\x00\x08')

# Style showcase (won't work properly anymore)
# outputRaw( esc + '!' + TextStyle_Regular) #Regular size
# outputTextBlock(journalString)
# Emphasized + Double-height + Double-width mode selected (ESC ! (8 + 16 + 32)) 56 dec => 38 hex
# outputRaw( esc + '!' + TextStyle_Large)
# outputTextBlock("cookies and milk")
# outputRaw( esc + '!' + '\x01') # Small size
# outputTextBlock("Small cookies and milk")
# outputRaw( esc + '!' + '\x09') # Small size + emphasis (1 + 8)
# outputTextBlock("Small cookies and milk?")
# outputRaw( esc + '!' + '\x10') # Double height regular
# outputTextBlock("Tall text")
# outputRaw( esc + '!' + '\x11') # Double height small
# outputTextBlock("Small tall text")
# outputRaw( esc + '!' + TextStyle_DoubleWidth) # Double width regular
# outputTextBlock("Double width regular")
# outputRaw( esc + '-') # Double width small underline (20h + 80h + 1h)
# outputTextBlock("Double width regular underline?")

# Something about this confuses my printer such that it starts printing corrupt data
# From package escpos
# escposStrOutputter = printer.Dummy()
# It does not actually support Japanese like this
# escposStrOutputter.text("このは、テストです。素晴しいですね。\n")
# escposStrOutputter.text(journalString)
# escposStrOutputter.image("test384.png")
# print(escposStrOutputter.output)
# outputRaw(escposStrOutputter.output)
# outFile = open("output.bin", "wb")
# outFile.write(escposStrOutputter.output)
# outFile.close()

if __name__ == "__main__":
main()

+ 1
- 0
modules/zj-58

@@ -0,0 +1 @@
Subproject commit 64743565df4379098b68a197d074c86617a8fc0a

+ 2
- 0
printOutput.sh View File

@@ -0,0 +1,2 @@
#!/bin/sh
lpr -P Zijiang-ZJ-58 output.bin

BIN
reference/ESCPOS_Command_Manual.pdf View File


Loading…
Cancel
Save