react-native-esc-pos-printer icon indicating copy to clipboard operation
react-native-esc-pos-printer copied to clipboard

simultaneously printing: Error: ERR_ILLEGAL

Open saranadshi5 opened this issue 2 years ago • 26 comments

when printer multiple print as same time one of them printed and another one not printed and causing Error: ERR_ILLEGAL

saranadshi5 avatar Mar 20 '23 14:03 saranadshi5

Same here @tr3v3r

tolypash avatar May 30 '23 15:05 tolypash

+1 Same

manage-some avatar May 30 '23 17:05 manage-some

when printer multiple print as same time one of them printed and another one not printed and causing Error: ERR_ILLEGAL

I solved by adding into Queue instead of printing directly

saranRajendiran avatar May 30 '23 17:05 saranRajendiran

Also wrapped the package with a class that creates print jobs. But if I could send prints simultaneously somehow would be great :)

tolypash avatar May 30 '23 20:05 tolypash

Actually, the SDK itself allows printing on multiple devices

But the RN part doesn't have all the features like in single printing. I have a plan to rework it in the future

For now, you can take a look at this example. It provides this functionality: https://github.com/tr3v3r/react-native-esc-pos-printer/blob/main/example/src/MultiPrint.tsx

tr3v3r avatar May 31 '23 11:05 tr3v3r

Thanks for the response @tr3v3r ! Looks good! 👍 Wanted to ask, do you recommend using instantiate for each printer on discovery or initPrinter before printing?

tolypash avatar May 31 '23 11:05 tolypash

Instantiate for multiple printing but as I said it could not contain some features. i.e. You have to disconnect manually and I'm not sure that the monitor feature working properly. So you can try at least :D

tr3v3r avatar May 31 '23 12:05 tr3v3r

@tr3v3r Sounds good, I will instantiate them then :)

tolypash avatar May 31 '23 12:05 tolypash

@tr3v3r is there options to send multiple printing for a single printer? and Instantiate for multiple to connect printer is am right?

saranadshi5 avatar May 31 '23 12:05 saranadshi5

@saranadshi5 I tested it by sending multiple print jobs one after the other and it works using instantiate. Only issue is with print errors not getting thrown.

tolypash avatar Jun 10 '23 20:06 tolypash

when printer multiple print as same time one of them printed and another one not printed and causing Error: ERR_ILLEGAL

I solved by adding into Queue instead of printing directly

How to use queue here?

ahmad71666 avatar Nov 21 '23 09:11 ahmad71666

We have successfully implemented a permanent solution for an issue on iOS and are currently working on resolving the same issue on Android. However, we are facing a challenge with the handleCommand function in Android, as it doesn't throw any errors like it does in iOS. We are hoping that @tr3v3r can help us with this, as the way the function is handled in Objective-C is different from how it's handled in Java. Below are snippets of both implementations for comparison.

Here a snippit of both Objective C [What happening here is that when any failure print happens the iOS will try to reprint for 4 times, the whole ePson brand has this kind of failure and we haven't found a better way then this code to handle it, even if 4 devices are printing on the same printer still this code solve the problem with no printing missing part of the page or the whole page.

`- (void)printFromBuffer:(NSArray*)buffer params:(NSDictionary *)params onSuccess: (void(^)(NSString *))onSuccess onError: (void(^)(NSString *))onError { int result = EPOS2_SUCCESS;

if (self->printer == nil) {
    NSString *errorString = [ErrorManager getEposErrorText: EPOS2_ERR_PARAM];
    onError(errorString);
    return;
}

NSUInteger length = [buffer count];
for (int j = 0; j < length; j++ ) {
    result = [self handleCommand:[buffer[j][0] intValue] params:buffer[j][1]];

    if (result != EPOS2_SUCCESS) {
        [self->printer clearCommandBuffer];
        NSString *errorString = [ErrorManager getEposErrorText: result];
        onError(errorString);
        return;
    }
}
result = [self printData:params];






// Failure handling starting by MA & Georage
__block Epos2PrinterStatusInfo *info;
int count = 0;
//Note: Check if the process overlaps with another process in time.
while(result != EPOS2_SUCCESS && count < 4 && self->printer !=nil) {
    info = [self->printer getStatus];
    if (info.getConnection == 1) {
        count++;
[NSThread sleepForTimeInterval:(double)count];
        continue;
    }

        NSUInteger length = [buffer count];
        for (int j = 0; j < length; j++ ) {
            result = [self handleCommand:[buffer[j][0] intValue] params:buffer[j][1]];

            if (result != EPOS2_SUCCESS) {
                [self->printer clearCommandBuffer];
                NSString *errorString = [ErrorManager getEposErrorText: result];
                onError(errorString);
                return;
            }
        }

        result = [self printData:params];
    count++;

}




if (result != EPOS2_SUCCESS) {
    NSString *errorString = [ErrorManager getEposErrorText: result];
    onError(errorString);
    return;
}

[self->printer clearCommandBuffer];
NSString *successString = [ErrorManager getEposErrorText: EPOS2_SUCCESS];
onSuccess(successString);

}`

Now on the other hand on the Java there are no result = and we couldn't find any way to let the for (int curr = 0; curr < bufferLength; curr++) { throw error like the iOS, so we can hande, we tried everything, try catch everything possible, but it doesn't work at all, I hope that @tr3v3r can help us with it.

`public void printFromBuffer(ReadableArray printBuffer, final ReadableMap paramsMap, MyCallbackInterface callback) { if (mPrinter == null) { String errorString = EscPosPrinterErrorManager.getEposExceptionText(Epos2Exception.ERR_PARAM); callback.onError(errorString); return; }

try {
  int bufferLength = printBuffer.size();
  for (int curr = 0; curr < bufferLength; curr++) {
    ReadableArray command = printBuffer.getArray(curr);
    handleCommand(command.getInt(0), command.getArray(1));
  }
} catch (Epos2Exception e) {
  mPrinter.clearCommandBuffer();
  int status = EscPosPrinterErrorManager.getErrorStatus(e);
  String errorString = EscPosPrinterErrorManager.getEposExceptionText(status);
  callback.onError(errorString);
  return;
} catch (IOException e){
  mPrinter.clearCommandBuffer();
  callback.onError(e.getMessage());
  return;
}
try {
    Thread.sleep(100); // Sleep for 0.1 second to solve errors
  this.printData(paramsMap);
  String successString = EscPosPrinterErrorManager.getCodeText(Epos2CallbackCode.CODE_SUCCESS);
  callback.onSuccess(successString);
} catch (InterruptedException e) {
    e.printStackTrace(); // Handle the InterruptedException exception
  }
catch (Epos2Exception e) {
  int status = EscPosPrinterErrorManager.getErrorStatus(e);
  String errorString = EscPosPrinterErrorManager.getEposExceptionText(status);
  callback.onError(errorString);
}

}`

marab2 avatar Nov 23 '23 21:11 marab2

@marab2 Hello. So the problem on a high level as I understood:

  1. You have one printer but several mobile devices. (Phone1, Phone2, Phone3, Printer )
  2. All of them connect to this printer and try to Print

Phone1 -> printData -> Printer (Success),
Phone2 -> printData -> Printer (Failure), Phone3 -> printData -> Printer (Failure) Phone4 -> printData -> Printer (Failure) 4) Fort the Phones that are failing you're trying to retry printing 5) But for Android you can not detect the error to start retrying.

Is that correct? What method you're using to init printer?

tr3v3r avatar Nov 23 '23 21:11 tr3v3r

Hi @tr3v3r, Thanks for your quick response! We've been working with the TM-20 series and have encountered similar issues across the board. When printing, we're seeing random errors like ERR_LEGAL and ERR_PARAM. This happens regardless of whether it's one printer connected to multiple devices, or multiple devices connected to multiple printers trying to print multiple copies.

We've found that handling the failure with a while loop for 4 tries helps to resolve this issue permanently. However, we're experiencing the same problems with Android. For instance, one paper gets printed correctly, while the next one misses the logo or some other part. Interestingly, Android doesn't throw any error in the for (int curr = 0; curr < bufferLength; curr++) loop like it does in iOS, and we hope if you can help us get the Android to do the same thing as we try with everything we know with Java but it doesn't work.

Our project involves handling multiple printers, including Epson. Here's how we manage the printing process with Epson from start to finish.

// / Epson Printers / // import EscPosPrinter, { getPrinterSeriesByName, IPrinter, } from 'react-native-esc-pos-printer'; import {showToast} from '../Helpers';

export const connectEpsonPrinter = async ( printer: any, data: any, copies: number, printers: [], init: boolean, setInit: any, setPrinting: any, ) => { if (!printers?.length) { showToast('No Epson printers discovered, please recheck'); setPrinting(false); return; } // Epson printer const pp: IPrinter | undefined = printers.find( (p: any) => p?.ip === printer?.ip, ); if (!pp) { showToast("We couldn't find your Eposn priter"); setPrinting(false); return; } if (!init) { await EscPosPrinter.init({ // @ts-ignore target: pp.target, // @ts-ignore seriesName: getPrinterSeriesByName(pp.name), language: 'EPOS2_LANG_MULTI', }); setInit(true); } let openDrawer = true; for (let i = 0; i < copies; i++) { await printOrder(data, pp, openDrawer); openDrawer = false; } setInit(false); EscPosPrinter.disconnect(); };

const printOrder = async ( items: any, printer1: IPrinter, openDrawer: boolean, ) => { try { if (printer1) { const printingAt = new EscPosPrinter.printing(); const printObj = await printingAt.initialize(); items.forEach((item: any) => { printObj.align('center');

    printObj.align('center');
    if (item.type === 'base64' && typeof item.data === 'string') {
      printObj.text('\x1B\x33\x10');
      printObj.image(
        {uri: 'data:image/jpg;base64,' + item.data},
        {width: 500},
      );
      printObj.newline();
    }
    if (item.type === 'text') {
      //To reduce white spacing in the EPSON
      printObj.text('\x1B\x33\x10');

      printObj.text(item.data);
      //To reduce white spacing in the EPSON
      printObj.text('\x1B\x33\x10');
      printObj.newline();
    }
    if (item.type === 'qr') {
      printObj.qrcode({
        value: item.data,
        level: 'EPOS2_LEVEL_M',
        width: 7,
      });
      printObj.newline();
    }
    if (item.type === 'cut') {
      printObj.cut();
    }
  });
  if (openDrawer) {
    printObj.addPulse();
  }
  await printObj.send();
}

} catch (error: any) { showToast('Error code3:', error.message); console.log('error', error); } };

marab2 avatar Nov 23 '23 21:11 marab2

Just shedding some light here, we get the same sometimes but I made it so that on print fail it shows the error on screen in a top level modal and the print job can be retried. Also, I added delays between prints. I think best solution would be to get instantiate working, so that all printers are connected in the same time, to report errors properly on print to them, and some kind of auto-retry mechanism.

tolypash avatar Nov 23 '23 21:11 tolypash

@marab2 to get it work, use promise, and add timeout like 800 900 milliseconds, that would work. I have implemented it, it works fine but when we "init" printer one by one it takes time, we have 4 printers, so the total of 1 minute and few seconds are required to print on all, You will have to print it one by one, if one printer is initialized and in use, and you send command to initialize another that will generate error, so try to do it in loop, but one after another and put delay in it..

ahmad71666 avatar Nov 23 '23 22:11 ahmad71666

@tolypash It's not about init or instantiate we even tried different libraries, all of them has the same problem, I believe it's an issue with EPson it self, if just anyone help us to get the result= same like what it's in objective C code, we can solve the issue the same way in Java.

marab2 avatar Nov 23 '23 22:11 marab2

@marab2 well maybe, but the code is working on my side, with both init and instantiate but the instantiate method does not return errors...

ahmad71666 avatar Nov 23 '23 22:11 ahmad71666

Yea it’s working for me as long as I put delays (sleep with useTimeout) between prints.

But sometimes it gets “stuck” and I have to restart app but that’s rare

I’d recommend you build a print service class that take a queue of print jobs and runs them with an interval @marab2

tolypash avatar Nov 23 '23 22:11 tolypash

@tolypash We have did that, and even the queue doesn't help. @tr3v3r I found a java file where the guy handles the error on each function can you please take a look https://github.com/nowarzz/rn-epson-tm82/blob/master/android/src/main/java/com/nowarzz/rrnepson/EpsonTM82.java

marab2 avatar Nov 23 '23 22:11 marab2

@ahmad71666 @tolypash if you want to see the big fall for Epson, try to initial print command with 5 copies of print, and see how 1-2 copies will get lost. If it success in the first time, then do it again immediately.

marab2 avatar Nov 23 '23 22:11 marab2

@marab2 yes will do that, never tried this case though, all other libraries seems outdated or unstable, only this one works, but has issues...

ahmad71666 avatar Nov 23 '23 22:11 ahmad71666

@marab2 if you need copies just do not disconnect from a printer! use any amount of copies within one buffer

printer .text() .cut() .send()

.text() .cut() .send() // <- repeat again without disconnecting ( 1 copy )

.text() .cut() .send() // <- repeat again without disconnecting ( 2 copy )

.disconnect()

P.S. Right now I'm trying to rework the printing approach.

So the new one will have better error handling and will have a job queue handle on the JS side.

Also could someone please test this (init but with multiple printing support)? It will speed up the process

tr3v3r avatar Nov 24 '23 08:11 tr3v3r

@tr3v3r Not sure if it's related but we are getting printer discovery error ERR_PROCESSING. Any ideas why?

"status": "ERR_PROCESSING" "methodName": "PrintersDiscovery.start" "name": "PrinterDiscoveryError" "timestamp": 0

UPDATE: Nevermind, an Expo OTA update has caused this. Need to update native modules as well via full update

tolypash avatar Nov 30 '23 16:11 tolypash

Instantiate for multiple printing but as I said it could not contain some features. i.e. You have to disconnect manually and I'm not sure that the monitor feature working properly. So you can try at least :D

Instantiate does not work as Init in some cases. For example with internet disconnects and reconnects

manage-some avatar Feb 24 '24 14:02 manage-some

released 4.0.0-beta.0. It should resolve all issues above

you can check the details here:

https://github.com/tr3v3r/react-native-esc-pos-printer/pull/139

tr3v3r avatar Mar 15 '24 11:03 tr3v3r