Intro
We're developing this javascript based web application that is supposed to print receipts using the epson javascript sdk.
Right now we've got this poc where multiple printers can be added to the app and where receipts can be printed per individual printer.
The problem is that the receipt will ONLY be printer from the last added printer.
Further investigating tells us that the sdk just uses the last added (connected) printer. This can be seen at the following images.
EpsonPrinter
instance is being used while printing. Notice the ip address is clearly the first printer.We created our own EpsonPrinter
class that can be found here or here below.
EpsonPrinter
export default class EpsonPrinter {
name = null
ipAddress = null
port = null
deviceId = null
crypto = false
buffer = false
eposdev = null
printer = null
intervalID = null
restry = 0
constructor (props) {
const {
name = 'Epson printer',
ipAddress,
port = 8008,
deviceId = 'local_printer',
crypto = false,
buffer = false
} = props
this.name = name
this.ipAddress = ipAddress
this.port = port
this.deviceId = deviceId
this.crypto = crypto
this.buffer = buffer
this.eposdev = new window.epson.ePOSDevice()
this.eposdev.onreconnecting = this.onReconnecting
this.eposdev.onreconnect = this.onReconnect
this.eposdev.ondisconnect = this.onDisconnect
this.connect()
}
onReconnecting = () => {
this.consoleLog('reconnecting')
}
onReconnect = () => {
this.consoleLog('reconnect')
}
onDisconnect = () => {
this.consoleLog('disconnect')
if (this.intervalID === null ){
this.intervalID = setInterval(() => this.reconnect(), 5000)
}
}
connect = () => {
this.consoleLog('connect')
this.eposdev.ondisconnect = null
this.eposdev.disconnect()
this.eposdev.connect(this.ipAddress, this.port, this.connectCallback)
}
reconnect = () => {
this.consoleLog('(Re)connect')
this.eposdev.connect(this.ipAddress, this.port, this.connectCallback)
}
connectCallback = (data) => {
clearInterval(this.intervalID)
this.intervalID = null
this.eposdev.ondisconnect = this.onDisconnect
if (data === 'OK' || data === 'SSL_CONNECT_OK') {
this.createDevice()
} else {
setTimeout(() => this.reconnect(), 5000)
}
}
createDevice = () => {
console.log('create device, try: ' + this.restry)
const options = {
crypto: this.crypto,
buffer: this.buffer
}
this.eposdev.createDevice(this.deviceId, this.eposdev.DEVICE_TYPE_PRINTER, options, this.createDeviceCallback)
}
createDeviceCallback = (deviceObj, code) => {
this.restry++
if (code === 'OK') {
this.printer = deviceObj
this.printer.onreceive = this.onReceive
} else if (code === 'DEVICE_IN_USE') {
if (this.restry < 5) {
setTimeout(() => this.createDevice(), 3000)
}
}
}
onReceive = (response) => {
this.consoleLog('on receive: ', response)
let message = `Print ${this.name} ${response.success ? 'success' : 'failute'}\n`
message += `Code: ${response.code}\n`
message += `Status: \n`
if (response.status === this.printer.ASB_NO_RESPONSE) { message += ' No printer response\n' }
if (response.status === this.printer.ASB_PRINT_SUCCESS) { message += ' Print complete\n' }
if (response.status === this.printer.ASB_DRAWER_KICK) { message += ' Status of the drawer kick number 3 connector pin = "H"\n' }
if (response.status === this.printer.ASB_OFF_LINE) { message += ' Offline status\n' }
if (response.status === this.printer.ASB_COVER_OPEN) { message += ' Cover is open\n' }
if (response.status === this.printer.ASB_PAPER_FEED) { message += ' Paper feed switch is feeding paper\n' }
if (response.status === this.printer.ASB_WAIT_ON_LINE) { message += ' Waiting for online recovery\n' }
if (response.status === this.printer.ASB_PANEL_SWITCH) { message += ' Panel switch is ON\n' }
if (response.status === this.printer.ASB_MECHANICAL_ERR) { message += ' Mechanical error generated\n' }
if (response.status === this.printer.ASB_AUTOCUTTER_ERR) { message += ' Auto cutter error generated\n' }
if (response.status === this.printer.ASB_UNRECOVER_ERR) { message += ' Unrecoverable error generated\n' }
if (response.status === this.printer.ASB_AUTORECOVER_ERR) { message += ' Auto recovery error generated\n' }
if (response.status === this.printer.ASB_RECEIPT_NEAR_END) { message += ' No paper in the roll paper near end detector\n' }
if (response.status === this.printer.ASB_RECEIPT_END) { message += ' No paper in the roll paper end detector\n' }
if (response.status === this.printer.ASB_SPOOLER_IS_STOPPED) { message += ' Stop the spooler\n' }
if (!response.success) {
alert(message)
// TODO: error message?
} else {
// TODO: success -> remove from queue
}
}
printReceipt = () => {
this.consoleLog(`Print receipt, `, this)
try {
if (!this.printer) {
throw `No printer created for ${this.name}`
}
this.printer.addPulse(this.printer.DRAWER_1, this.printer.PULSE_100)
this.printer.addText(`Printed from: ${this.name}\n`)
this.printer.send()
} catch (err) {
let message = `Print ${this.name} failure\n`
message += `Error: ${err}`
alert(message)
}
}
consoleLog = (...rest) => {
console.log(`${this.name}: `, ...rest)
}
}
Poc
The full working poc can be found here.
Epson javascript sdk
2.9.0
Does anyone have any experience with the epson sdk? It it supposed to be able to support multiple connections on the same time? Please let use know.
For the ones looking for a way to handle multiple printers using this SDK. We came up with the following work around:
We created a separated 'printer app' that is responsible for handling ONE printer connection and hosted it online. We then 'load' this printer app into our app that needs multiple connections using Iframes. Communication between app and printer app is done by means of window.PostMessage API to, for example, initialise the printer with the correct printer connection and providing data that has to be printed.
It takes some effort but was the most stable solution we could come up with handling multiple connections.
If anyone else comes up with a better approach please let me know!
You can checkout our printer app here for inspiration (inspect the app because it doesn't show much visiting it just like that).