2
votes

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.

  1. In the first image there are 2 printers setup. Notice the different ip addresses.
  2. In the second image we log what EpsonPrinter instance is being used while printing. Notice the ip address is clearly the first printer.
  3. In the third image we trace the network. Notice the ip address that is actually used (ignore the error).

enter image description here

enter image description here

enter image description here

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.

4

4 Answers

1
votes

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).

0
votes

For use your class EpsonPrinter, i add also myPrinters class after your class:

class myPrinters {
    printers = null;
    cantidad = 0;

    constructor() {
        console.log("Creo la coleccion de printers");
        this.printers = [];
    }

    inicializarConeccionImpresora(idImpresora, ip, puerto, _deviceId) {
        let ipAddress = ip;
        let port = puerto;
        let deviceId = _deviceId;
        console.log("Agrego una impresora");
        let myPrinter = new EpsonPrinter(ipAddress);
        myPrinter.port = port;
        myPrinter.deviceId = deviceId;
        myPrinter.id = idImpresora;
        console.log('Id impresora antes de connect es: ' + idImpresora);
        myPrinter.connect();
        this.printers[this.cantidad] = myPrinter;
        this.cantidad ++;   
    }

    imprimirPruebaJS(idImpresora) {
        let printer = null;
        let printerTemp = null
        for(var i = 0; i < this.printers.length; i++) {
            printerTemp = this.printers[i];
            if (printerTemp.id == idImpresora) {
                printer = printerTemp.printer;
            }
        }

        if (printer == null) {
            console.log("La impresora no esta iniciada en clase myPrinters");
            return;
        }

        printer.addText('Hola mundo texto normal\n');
        printer.addFeed();
        printer.addCut(printer.CUT_FEED);
    }
}

call myPrinters class in this way :

myEpsonPrinters = new myPrinters();

myEpsonPrinters.inicializarConeccionImpresora(1, '192.168.0.51', 8008, 'local_printer');
myEpsonPrinters.inicializarConeccionImpresora(2, '192.168.0.52', 8008, 'local_printer');

myEpsonPrinters.imprimirPruebaJS(1)
or
myEpsonPrinters.imprimirPruebaJS(2)

Test it and tell me. Juan

0
votes

Just create multiple objects for printing simple as this

this.eposdev = [];

let printersCnt = 3;

let self = this;

for(let i=1 ; i <= printersCnt ; i++){

    this.eposdev[i] = new window.epson.ePOSDevice()

    this.eposdev[i].onreconnecting = function (){
        this.consoleLog('reConnecting')
    }

    this.eposdev[i].onreconnect =  function (){
       this.consoleLog('onReconnect')
    }

    this.eposdev[i].ondisconnect = function (){
        this.consoleLog('onDisconnect')
    }    
} 


function connect(printerKey) => {

    this.consoleLog('connect')

    this.eposdev.ondisconnect = null
    this.eposdev.disconnect()

    this.eposdev.connect(self.ipAddress[printerKey], self.port[printerKey], function(){

        clearInterval(self.intervalID)

        self.intervalID = null
        self.eposdev[i].ondisconnect = self.ondisconnect

        if (data === 'OK' || data === 'SSL_CONNECT_OK') {

            console.log('create device, try: ' + self.restry)

            const options = {
              crypto: self.crypto,
              buffer: self.buffer
            }

            self.eposdev[printerKey].createDevice(self.deviceId, self.eposdev[printerKey].DEVICE_TYPE_PRINTER, options, function(deviceObj, code){
                this.restry++

                if (code === 'OK') {
                  self.printer[printerKey] = deviceObj
                  self.printer.onreceive = function(){
                      console.log("onreceive");
                  }
                } else if (code === 'DEVICE_IN_USE') {
                  if (self.restry < 5) {
                    setTimeout(() => self.createDevice(printerKey), 3000)
                  }
                })
            }


        } else {
          setTimeout(() => self.reconnect(printerKey), 5000)
        }

    })
} 
-2
votes

Epson says that with version 2.12.0 you can add more than one printer.