shtrih-m / javapos_shtrih

Реализация JavaPOS драйвера принтера фискального регистратора для устройств Штрих-М
http://www.shtrih-m.ru
MIT License
33 stars 16 forks source link

Ошибка подключения к ККТ Штрих Мобайл при повторном подключении #160

Closed vladislav-larionov closed 1 year ago

vladislav-larionov commented 1 year ago

При повторном сопряжении с устройством через драйвер появляется ошибка ErrorCode: 112, ErrorCodeExtended: 0, "read failed, socket might closed or timeout, read ret: -1", time = 7122 ms. После появления такой ошибки повторное подключение автоматически не запускается. Если вручную потом ещё раз попытаться подключиться, то соединение выполнится. Если ещё раз вызвать соединение, то опять появится ошибка. Также после такой ошибки и повторного подключения теряется возможность повторно распечатать последний чек. Ошибка JposException. ErrorCode: 114, ErrorCodeExtended: 386, "86, Нет документа для повтора", time = 1159 ms.

Описанное поведение проявилось на версии драйвера 690 на Штрих Мобайл (версия ПО: A.4, сборка ПО: 20045).

Тот же самый сценарий на версии драйвера 617 выполняется по-другому: автоматически выполняется повторная попытка подключения, причём успешная, и при первой провалившейся попытке подключения в логе нет вывода об обращении к null-объекту, но есть вывод от BluetoothSocket. Для сравнения лог версии драйвера 617 и версии 690.

Отсюда есть три вопроса относительно актуальной версии версии драйвера 690:

  1. Нормально ли, что не выполняется автоматически повторное подключение?
  2. Нормально ли, что в логе есть обращение к null-объекту внутри драйвера?
  3. Нормально ли, что после такой ошибки пропадает возможность повторной печати последнего чека?

Фрагмент лога ошибки, полученный на версии драйвера 690:

02.03.2023 11:19:55.046 [pool-9-thread-1] c.s.j.f.JposExceptionHandler - JposException. ErrorCode: 112, ErrorCodeExtended: 0, "read failed, socket might closed or timeout, read ret: -1", time = 7122 ms
02.03.2023 11:19:55.049 [pool-9-thread-1] c.s.j.f.FiscalPrinterService - close()
02.03.2023 11:19:55.055 [pool-9-thread-1] c.s.j.f.FiscalPrinterImpl - saveProperties
java.lang.NullPointerException: Attempt to invoke interface method 'com.shtrih.jpos.fiscalprinter.ReceiptLines com.shtrih.jpos.fiscalprinter.PrinterHeader.getHeaderLines()' on a null object reference
    at com.shtrih.jpos.fiscalprinter.XmlPropWriter.writePrinterHeader(XmlPropWriter.java:91) ~[na:0.0]
    at com.shtrih.jpos.fiscalprinter.FiscalPrinterImpl.saveProperties(FiscalPrinterImpl.java:4577) ~[na:0.0]
    at com.shtrih.jpos.fiscalprinter.FiscalPrinterImpl.release(FiscalPrinterImpl.java:2335) ~[na:0.0]
    at com.shtrih.jpos.fiscalprinter.FiscalPrinterImpl.close(FiscalPrinterImpl.java:2114) ~[na:0.0]
    at com.shtrih.jpos.fiscalprinter.FiscalPrinterService.close(FiscalPrinterService.java:245) ~[na:0.0]
    at jpos.BaseJposControl.close(BaseJposControl.java:391) ~[na:0.0]
    at com.shtrih.fiscalprinter.ShtrihFiscalPrinter113.close(ShtrihFiscalPrinter113.java:1014) ~[na:0.0]
    at ru.ftc.fsg.mobilepost.ca.feature.printer.data.ShtrihPrinterApi.closePrinter(ShtrihPrinterApi.kt:320) ~[na:0.0]
    at ru.ftc.fsg.mobilepost.ca.feature.printer.data.ShtrihPrinterApi.closePrinter(ShtrihPrinterApi.kt:56) ~[na:0.0]
    at ru.ftc.fsg.mobilepost.ca.feature.printer.data.BasePrinterApi.closePrinter(BasePrinterApi.kt:122) ~[na:0.0]
    at ru.ftc.fsg.mobilepost.ca.feature.printer.data.BasePrinterApi.onDriverExceptionOccurred(BasePrinterApi.kt:111) ~[na:0.0]
    at ru.ftc.fsg.mobilepost.ca.feature.printer.data.BasePrinterApi.access$onDriverExceptionOccurred(BasePrinterApi.kt:16) ~[na:0.0]
    at ru.ftc.fsg.mobilepost.ca.feature.print
er.data.BasePrinterApi$connectPrinter$$inlined$runSafety$1.run(BasePrinterApi.kt:265) ~[na:0.0]
    at io.reactivex.internal.operators.completable.CompletableFromAction.subscribeActual(CompletableFromAction.java:35) ~[na:0.0]
    at io.reactivex.Completable.subscribe(Completable.java:2309) ~[na:0.0]
    at io.reactivex.internal.operators.single.SingleFlatMapCompletable$FlatMapCompletableObserver.onSuccess(SingleFlatMapCompletable.java:91) ~[na:0.0]
    at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.onSuccess(SingleSubscribeOn.java:68) ~[na:0.0]
    at io.reactivex.internal.operators.single.SingleFromCallable.subscribeActual(SingleFromCallable.java:56) ~[na:0.0]
    at io.reactivex.Single.subscribe(Single.java:3666) ~[na:0.0]
    at io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89) ~[na:0.0]
    at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:38) ~[na:0.0]
    at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:26) ~[na:0.0]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:0.0]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) ~[na:0.0]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) ~[na:0.0]
    at java.lang.Thread.run(Thread.java:923) ~[na:0.0]
02.03.2023 11:19:55.057 [pool-9-thread-1] c.s.j.f.FiscalPrinterImpl - setDeviceEnabled(false)
VitalyKravtsov2016 commented 1 year ago
  1. Повторное подключение подключение проверю.
  2. Обращение к null-объекту внутри драйвера - нехорошо. Поправлю.
  3. В логе видно, что ошибку возвращает ФР: "86, Нет документа для повтора" ФР в некоторых случаях очищает копию последнего документа, например если открыть чек и отменить его. Это особенность реализации ФР.
VitalyKravtsov2016 commented 1 year ago

Новая версия драйвера: https://github.com/shtrih-m/javapos_shtrih/releases/tag/691

vladislav-larionov commented 1 year ago

Обращения к null-объекту внутри драйвера пропали, спасибо.

А проблему с повторным подключением удалось воспроизвести? У меня она осталась. Также, если 5-6 минут не использовать ККТ, то связь с ним обрывается, и появляется ошибка Incorrect frame number. Нормально ли это? shtrih.log

Tango600 commented 1 year ago

Может надо каждый раз при обращении к методам первым в цепочке действий заново пытаться установить подключение?

if (printer != null && !chkConnectionEntrance) {
    String MAC = getDeviceMac();
    if (StringHelper.isNullOrEmpty(MAC)) {
        throw new InterruptedException("Подключение к ККМ отсутствует. Сопряжение не было выполнено.");
    } else {
        chkConnectionEntrance = true;
        try {
            connectToDevice(MAC, SettingsKkmManagement.getInstance().isUseBTLowEnergyMode(), true);
        } catch (Exception ex) {
            chkConnectionEntrance = false;
            throw ex;
        }
    }
    chkConnectionEntrance = false;
}
VitalyKravtsov2016 commented 1 year ago

Ошибку "Incorrect frame number" сейчас поправлю. По повторному подключению шаги можете описать?

vladislav-larionov commented 1 year ago

Шаги повторного подключения:

  1. Подключаемся к устройству из списка. Это создание экземпляра класса ShtrihFiscalPrinter(FiscalPrinter()). После создания вызывается метод:

    override fun ShtrihFiscalPrinter.onInitPrinter() {
    logDebug("Инициализация Штрих.")
    JposConfig.configure("ShtrihFptr", macAddress)
    if (state != jpos.JposConst.JPOS_S_CLOSED) {
        logDebug("Закрытие старого открытого соединения.")
        close()
    }
    logDebug("Установка соединения...")
    open("ShtrihFptr")
    claim(TIMEOUT_IN_MILLIS)
    deviceEnabled = true
    logDebug("Соединение установлено.")
    if (state != jpos.JposConst.JPOS_S_CLOSED) {
        logDebug("Сброс ФР.")
        resetPrinter()
    }
    if (!subject.isNullOrBlank())
        setPOSID("1", subject)
    initCliche()
    logDebug("Штрих успешно инициализирован.")
    }

    Потом выполняется вызов метода драйвера close().

  2. Потом при успешной авторизации в приложении выполняется такое же повторное подключение к устройству. Тут появляется ошибка. Если ошибка не появилась, то можно повторить первый шаг один-два раза и она появится. Лог, полученный по этим шагам shtrih.log.

Tango600 commented 1 year ago

А приложение "закрывается", перед повторным подключением? Дело в том что приложение нужно действительно закрывать, что бы даже огрызок в памяти не висел.

vladislav-larionov commented 1 year ago

Нет, приложения не закрывается перед повторным подключением. А без закрытия описанный выше сценарий не реализовать? У нас перед оплатой вызывается метод драйвера resetPrinter. Может его нужно вызвать перед шагом 2? Кроме того, после появления ошибки подключения, следующая попытка всегда оказывалась успешной.

Tango600 commented 1 year ago

Это я описал ситуацию, когда приложение "закрылось", а потом новый экземпляр уже не может подключиться, драйвер занят.

Tango600 commented 1 year ago

У меня в продолжении приведённого мной выше кода, да, вызывается resetPrinter.

VitalyKravtsov2016 commented 1 year ago

Поправил: https://github.com/shtrih-m/javapos_shtrih/releases/tag/692