Процедурный интерфейс для кассовых аппаратов с протоколом EQL

 

Процедурный интерфейс предназначен для вызова кассовых процедур прикладными программами. Кассовые процедуры объединены в группы в зависимости от их назначения. Каждая группа оформлена в виде COM-интерфейса. Каждая модель кассового аппарата поддерживает определённый набор интерфейсов. Технология COM позволяет выяснить, поддерживается ли конкретный интерфейс кассовым аппаратом, с которым прикладная программа создала соединение. Это даёт возможность создавать прикладные программы, адаптирующиеся к возможностям подключенного кассового аппарата.

 

Данный документ состоит из следующих разделов:

- примеры работы с процедурным интерфейсом на разных языках программирования

- справочник по свойствам  процедурного интерфейса

- справочник по существующим группам кассовых процедур (интерфейсам)

 

Процедурный интерфейс может быть получен двумя способами:

1. Из ADO-соединения. Путём чтения поля "Procedure" из служебной таблицы "EQL_service".

2. Путём создания специализированного COM-объекта, который далее в этом документе будет называться объектом EQLProc.

 

Объект EQLProc имеет имя "EQLProc.EQLProcedure" и предоставляет собой интерфейс IDispatch для вызова процедур кассового аппарата. В этом же интерфейсе реализованы свойства, которые позволяют управлять соединением с кассой.

 

Примеры работы с процедурным интерфейсом

 

1С:Предприятие

 

Procedure Go()
        // создание объекта
        proc = CreateObject("EQLProc.EQLProcedure");
        // установка свойств объекта перед соединением с кассой
        Если СвязьПоУпрощённомуПротоколу Тогда
                proc.Number = "1;0"; // касса подключена к порту COM1
                proc.Protocol = "L2Com.HcComSessionCreator";
        ИначеЕсли СвязьПоСетевомуНомеру Тогда
                proc.Number = "1;1"; // порт COM1/сетевой номер 1
        Иначе // связь по логическому номеру
                proc.Number = 1; // логический номер 1
        КонецЕсли;

        proc.User = 1;
        proc.Password = 0;

        // Соединение с кассой
        proc.Connect = -1; //True
        // Процедуры работают только если установлена связь с кассой
        Если proc.Connect = -1 Тогда
                // Формируем чек
                proc.SmenBegin();
                proc.BegChk();
                proc.FullProd(322233,3,1,1,1,1,"Пиво");
                proc.Oplata(0,0,0);
                proc.EndChk();
        Иначе
                // Отображаем пользователю код ошибки (свойство ErrNum)
                // и/или описание ошибки (свойство ErrDescr)
                proc.ErrNum;
                proc.ErrDescr;
        КонецЕсли;
EndProcedure

 

Visual Basic

Для Visual Basic имеется два варианта подключения. Первый способ аналогичен подключению в 1С:Предприятии:

 

Dim fisc As Object
Set fisc = CreateObject("EQLProc.EQLProcedure")
On Error Resume Next
fisc.Number = 1
fisc.User = 1
fisc.Password = 0
fisc.Connect = True
If fisc.Connect = True Then
        fisc.BegChk
        fisc.PrintComment "Hello world!"
        fisc.EndChk
Else
        // Отображаем пользователю код ошибки (свойство ErrNum)
        // и/или описание ошибки (свойство ErrDescr)
        MsgBox "Связь с кассой не установлена! Ошибка 0x" & Hex(fisc.ErrNum) & ": " & fisc.ErrDescr
End If

 

Второй способ использует библиотеки типов. Для этого в редакторе Visual Basic в меню “Tools/References…” надо подключить ссылки: “EQLProc 1.0 Type Library” и “Help Co Common Cash Register Interfaces”.

Информацию о поддерживаемых интерфейсах можно просмотреть открыв Object Browser c помощью клавиши F2 и выбрав HcTLB из списка доступных библиотек типов.

 

Sub test_eqlproc()
        Dim procobj As New EQLProcedure
        Dim fp As IHcFReg
        Dim fpext As IHcFRegEx
        procobj.Number = "1;1"
        procobj.User = 1
        procobj.Password = 0
        procobj.Connect = True
        If procobj.Connect = True Then
                MsgBox CStr(procobj.SerLet) + CStr(procobj.SerNum)
                ' последующее присваивание возможно только после подключения кассы. Только теперь
                ' объект знает набор интерфейсов, которые поддерживает подключенный кассовый
                ' аппарат.
                Set fp = procobj
                Set fpext = procobj
                ' Выдача чека
                fp.SmenBegin
                fp.BegChk
                fpext.FullProd 12346, 12, 2, 1, 1, 1, "Робот"
                fp.Oplata 0, 0, 0
                fp.EndChk
        Else
                // Отображаем пользователю код ошибки (свойство ErrNum)
                // и/или описание ошибки (свойство ErrDescr)
                MsgBox "Связь с кассой не установлена! Ошибка 0x" & Hex(procobj.ErrNum) & ": " & procobj.ErrDescr
        End If
End Sub

 

Visual C++

 

#import "EQLProc.dll" no_namespace
#import "HcTLB.tlb" no_namespace

void print() {
        IEQLProDispPtr procobj("EQLProc.EQLProcedure");
        procobj->Number = "1;1";
        procobj->User = 1L;
        procobj->Password = 0L;
        procobj->Connect = 1L; // тут происходит установление соединения с кассой
        if(procobj->Connect != 0L){ // если соединение установлено:
                char buf[64];
                sprintf(buf,"%s%s",(char*)_bstr_t(procobj->SerLet),(char*)_bstr_t(procobj->SerNum));
                ::MessageBox(NULL,buf,"ECR",0);
                // последующее присваивание возможно только после подключения кассы. Только теперь
                // объект знает набор интерфейсов, которые поддерживает подключенный кассовый аппарат.
                IHcFRegPtr fp = procobj;
                IHcFRegExPtr fpext = procobj;
                fp->BegChk();
                fpext->FullProd(12347L,15L,3L,1L,1L,1L,"Щетка");
                fp->Oplata(0L,0L,0L);
                fp->EndChk();
        }
        else{
                // Отображаем пользователю код ошибки (свойство ErrNum)
                // и/или описание ошибки (свойство ErrDescr)
                TCHAR msg[256];
                _sntprintf(msg, sizeof(msg)/sizeof(msg[0]),
                        _T(
"Соединение не установлено! Ошибка %#x: %s"),
                        long(procobj->ErrNum),
                        LPCTSTR(_bstr_t(procobj->ErrDescr)));
                ::MessageBox(NULL, msg,
"ECR", 0);
        }
        return 0;
}

 

Справочник по свойствам процедурного интерфейса

Установление соединения

Данные свойства имеются только в том случае, когда процедурный интерфейс получен путём создания объекта EQLProc. Если процедурный интерфейс получен из ADO-соединения, то в данных свойствах нет необходимости, так как настройки параметров соединения производятся при создании объекта соединения ADO (ADODB.Connection).

Свойство Number

Свойство User

Свойство Password

Свойство Location

Свойство Protocol

Свойство Connect

Свойство InitTMO

Свойство NoInitTxt

Свойство OffTxt

Свойство NoDataTxt

Информация об устройстве

Эти свойства позволяют получить информацию об устройстве после установления соединения. Доступны только для чтения.

Свойство SerLet

Свойство SerNum

Свойство Schema

Вспомогательные свойства

Свойство ErrNum

Свойство ErrDescr

Свойство CacheProc

Свойство Out

Функция IsStrEq

Описание свойств

 

Number

Номер аппарата.

Тип: строка

Умолчание: "1"

 

Позволяет указать кассовый аппарат для работы в виде:

  1. Логический номер (в виде "число")
  2. Комбинация номер порта, сетевой номер кассы (в виде "порт;сетевойномер")
  3. Комбинация номер порта, сетевой номер кассы, скорость обмена (в виде "порт;сетевойномер;скорость")

Если в момент установки значения свойства сеанс связи с аппаратом был установлен, он закрывается.

При использовании логического номера он должен совпадать с логическим номером, запрограммированным в кассе в параметрах связи с компьютером.

Если используется сетевой номер, то он должен совпадать с сетевым номером, запрограммированным в кассе в параметрах связи с компьютером.

Возможные значения скорости: 9600, 19200, 38400, 57600, 115200. Однако некоторые модели касс не поддерживают скорости 57600 и 115200. Указанная скорость должна совпадать со скоростью обмена с компьютером, запрограммированной в кассе.

Если касса подключена к компьютеру и в её настройках разрешён обмен с компьютером, то с помощью утилиты comtest.exe вы можете выяснить, на какой скорости работает касса, какой протокол она использует для обмена (упрощённый или полный) и какой имеет сетевой номер. Эти данные помогут вам правильно сформировать строку для свойства Number. Иконка comtest.exe устанавливается на рабочем столе Windows большинством инсталляторов, которые устанавливают драйверы EQL..

 

User

Номер кассира

Тип: число

Умолчание: 1

 

Номер кассира, от которого открывается сеанс связи.

Если в момент установки значения свойства сеанс связи с аппаратом был установлен, он закрывается.

 

Password

Пароль кассира

Тип: число

Умолчание: 1

 

Пароль кассира. Для установки сеанса связи пароль должен совпадать с паролем этого кассира, сохраненным в кассовом аппарате.

Если в момент установки значения свойства сеанс связи с аппаратом был установлен, он закрывается.

 

Location

Имя компьютера, к которому физически подключена касса.

Тип: строка

Умолчание: пустая строка

 

Позволяет создать сеанс связи с кассой, подключенной к другому компьютеру. На том компьютере, к которому подключена касса, должны быть установлены драйвера EQL.

Для обмена между компьютерами используется технология DCOM. Поэтому для установления связи с кассой, подключенной к другому компьютеру, необходимо настроить параметры безопасности DCOM таким образом, чтобы они не мешали установлению связи. В общем случае это весьма нетривиальная задача.

Если в момент установки значения свойства сеанс связи с аппаратом был установлен, он закрывается.

 

Protocol

Объект протокола нижнего уровня, по которому подключена касса. Пустая строка соответствует полному протоколу нижнего уровня. Для связи по упрощенному протоколу используется строка L2Com.HcComSessionCreator.

Тип: строка

Умолчание: пусто

 

Если в момент установки значения свойства сеанс связи с аппаратом был установлен, он закрывается.

 

Connect

Установка и проверка активности сеанса связи.

Тип: булевский

Умолчание: ЛОЖЬ

 

Переключение значения свойства из ЛОЖЬ в ИСТИНА приводит к установке сеанса связи с аппаратом с текущими значениями управляющих свойств. Обратное переключение приводит к разрыву сеанса связи. Проверка значения свойства показывает открыт или закрыт сеанс связи с аппаратом.

Коды ошибок в свойстве ErrNum после неудачной попытки установить связь:

0x80040731

Соединение не создано, так как запущена другая программа, которая создала соединение с кассой и при этом использовала тот же номер кассира, который был задан в свойстве User.

Для устранения этой ошибки можно попробовать использовать в параметрах соединения другой номер кассира, так как большинство кассовых аппаратов поддерживают два одновременных соединения по полному протоколу (соединения должны использовать разные номера кассиров).

0x80040732

В параметрах соединения задан неверный пароль кассира.

0x80040801

Данная ошибка возникает когда пользователь нажимает отмену в вэйтере либо вэйтер отменяется по таймауту. Первопричина появления вэйтера - отсутствие кассы, подключенной к компьютеру и соответствующей заданным параметрам соединения.

Возможные причины:

- касса выключена;

- касса подключена к другому порту компьютера (не к тому, который указан в параметрах соединения);

- кабель подсоединен к порту кассы, не предназначенному для обмена с компьютером;

- кабель неисправен (имеет обрывы) или неправильно распаян (предназначен для другой модели кассы);

- в настройках кассы запрещена связь с компьютером;

- касса настроена для работы по другому протоколу (настройки кассы не совпадают с протоколом заданным в параметрах соединения объекта EQLProc. Если в параметрах соединения объекта EQLProc протокол не указан, то по умолчанию используется полный протокол);

- касса настроена для работы на скорости, не совпадающей со скоростью обмена, используемой драйвером. По умолчанию драйверы используют скорость обмена 38400 бод.

0x80040805

В свойстве Number задан несуществующий порт или порт, занятый другим приложением.

0x80040B0X

Ошибки, связанные с файлами схем. Идентификатор схемы и имя файла схемы указаны в свойстве ErrDescr.

0x80040C01

Неправильно задана первая часть в свойстве Number. Это значение не может быть равно нулю.

0x80040C02

Неправильно задана скорость обмена в свойстве Number. Допустимые скорости обмена перечислены в описании свойства Number.

0x80070057

Если данная ошибка возникла при установлении связи по упрощённому протоколу, то это может означать, что в свойстве Number задан несуществующий порт или порт, занятый другим приложением.

 

 

 

InitTMO

Таймаут установки связи с кассой (мс).

Тип: число

Умолчание: 30000 (30 сек.)

 

Таймаут для установки следующего сеанса связи с кассой. Установка параметра не влияет на активный сеанс, если он есть.

 

NoInitTxt

Сообщение при установке связи с кассой.

Тип: строка

Умолчание: «Wait for init device ...»

 

Позволяет установить текст сообщения в окне, которое появляется при первоначальном установлении сеанса связи с кассой. Если присвоить пустое значение, окно не будет появляться вообще. Окно появляется на время InitTMO.

Установка параметра не влияет на активный сеанс, если он есть.

 

OffTxt

Сообщение при потере связи с аппаратом.

Тип: строка

Умолчание: « Wait for device turn on ...»

 

Текст окна, которое появляется, если кассовый аппарат не отзывается при установленном сеансе связи с ним (Например, после установки сеанса связи он был выключен или с ним нарушено физическое соединение). Если значение свойства непустое, то попытка восстановить сеанс будет продолжаться до восстановления сеанса или до нажатия пользователем кнопки “Cancel” в окне сообщения. Если значение свойства пустое – окно не показывается, и программа пытается восстановить сеанс на протяжении 30 сек.

Установка параметра не влияет на активный сеанс, если он есть.

 

 

NoDataTxt

Сообщение об отсутствии ответа от аппарата.

Тип: строка.

Умолчание: «Wait for device data ...»

 

Текст окна, которое появляется, когда аппарат занят выполнением длительной операции, например, печать дневного отчета и не может ответить на команду от компьютера до выполнения этой операции. Если значение свойства непустое, то попытка восстановить сеанс будет продолжаться до успешного ответа аппарата или до нажатия пользователем кнопки “Cancel” в окне сообщения. Если значение свойства пустое – окно не показывается, и программа ждет ответа от аппарата на протяжении 30 сек.

Установка параметра не влияет на активный сеанс, если он есть.

 

SerLet

Буквы серийного номера аппарата.

Тип: строка

Умолчание: нет

 

Буквы в серийном номере аппарата. Свойство доступно только для чтения после того, как было установлено соединение с аппаратом (см. свойство Connect).

В случае, если системная плата аппарата поддерживает перепрошивку, вместо серийного номера возвращается номер системной платы.

 

SerNum

Цифры серийного номера аппарата.

Тип: число

Умолчание: нет

 

Цифры в серийном номере аппарата. Свойство доступно только для чтения после того, как было установлено соединение с аппаратом (см. свойство Connect).

В случае, если системная плата аппарата поддерживает перепрошивку, вместо серийного номера возвращается номер системной платы.

 

Schema

Уникальный идентификатор модели аппарата.

Тип: число

Умолчание: нет

 

Уникальный идентификатор модели аппарата. Свойство доступно только для чтения после того, как было установлено соединение с аппаратом (см. свойство Connect).

 

ErrNum

Код ошибки последней операции.

Тип: число

Умолчание: 0

 

Код последней ошибки. Свойство доступно только для чтения. Свойство используется для диагностики причин неустановления связи или ошибок при исполнении кассовых процедур.

Если программа присвоила истину свойству Connect, а затем прочитала из свойства Connect ложь, то свойство ErrNum будет содержать код, описывающий причину, по которой связь не установилась. Коды ошибок, которые могут возникнуть при установлении соединения, приведены в описании свойства Connect.

Если вызов кассовой процедуры закончился неудачно, то свойство ErrNum также будет содержать код, описывающий кассовую ошибку или ошибку передачи данных.

Все ошибки, источником которых является касса, имеют вид 0x800407XX, где XX является внутренним кодом кассовой ошибки. Коды кассовых ошибок приведены в описании кассовых процедур.

 

ErrDescr

Описание последней ошибки.

Тип: строка

Умолчание: пустая строка

 

Описание последней ошибки. Свойство доступно только для чтения. Содержит дополнительную информацию об ошибки в тех случаях, когда свойство ErrNum имеет ненулевое значение.

 

CacheProc

Управление кэшированием вызовов процедур.

Тип: число

Умолчание: 0

 

Во время обычного вызова кассовой процедуры в кассу посылается команда “выполнить процедуру”, затем драйвер ждет от кассы результат выполнения процедуры и после его получения возвращает управление программе верхнего уровня, вызвавшей процедуру. Это приводит к тому, что между вызовами процедур появляются промежутки времени, связанные с задержками канала связи. Например, если в кассу посылается серия вызовов OutTone, то между издаваемыми звуками можно заметить паузы. Другой пример - серия вызовов PrintComment - комментариии печатаются на ленте как бы рывками.

Существует возможность передать кассе пакет команд на выполнение целой серии процедур не дожидаясь результатов выполнения каждой отдельной процедуры. Это позволяет сэкономить время на обмен и практически ликвидировать промежутки времени между вызовами процедур.

Управление режимами вызова процедур осуществляется  с помощью свойства CacheProc.

При чтении свойство CacheProc дает возможность узнать текущий режим исполнения процедур:

0 - Режим непосредственного исполнения процедур. Если CacheProc равно 0 и производится вызов кассовой процедуры, то этот вызов передается непосредственно в кассу, а результат её исполнения передаётся программе верхнего уровня.

1 - Режим отложенного исполнения процедур. Если CacheProc равно 1 и производится вызов кассовой процедуры, то этот вызов вместе со значениями параметров процедуры сохраняется в кэше. Никакого обмена с кассой не происходит. Кэшированные вызовы будут переданы кассе тогда, когда свойству CacheProc будет присвоено значение 0.

При записи свойство CacheProc может принимать следующие значения:

0 - Переводит объект EQLProc в режим непосредственного исполнения процедур. Если значение CacheProc изменяется с 1 на 0, то в этот момент происходит пакетное выполнение всех процедур, которые кэшировались за время действия значения 1. Если до присваивания значение CacheProc было равно 0, то такое присваивание игнорируется.

1 - Переводит объект EQLProc в режим отложенного исполнения процедур.

2 - Очищает кэш отложенных вызовов и переводит объект EQLProc в режим непосредственного исполнения процедур.

 

Out(PName)

Значение возвращаемого параметра кассовой процедуры.

Тип: вариант

Умолчание: нет

 

Некоторые кассовые процедуры имеют возвращаемые параметры. Например процедура Subtotal имеет возвращаемый параметр Sum, в котором передаётся текущее значение промежуточного итога. Система 1С не даёт программисту возможности получить значение возвращаемого параметра непосредственно при вызове процедуры через Dispatch-интерфейс. Поэтому в объекте EQLProc реализовано свойство Out, которое позволяет получить значение возвращаемого параметра по его имени.

 

IsStrEq(EStr, CStr[, Length])

Функция сравнения строк с учётом преобразования строк в кассовом аппарате.

Тип: булевский

 

Параметры:

EStr - если параметр Length не указан, то считается, что строка EStr получена из кассы и её значение перед сравнением не преобразовывается. Если параметр Length указан, то перед сравнением строка EStr преобразовывается в соответствии с кассовой кодировкой.

CStr - строка предназначенная для записи в кассу. Перед сравнением всегда преобразовывается в соответствии с кассовой кодировкой.

Length - необязательный параметр. Если параметр указан, то он задаёт количество символов, которые сравниваются в строках. Если параметр не указан, то сравнивается столько символов, сколько их есть в строке EStr.

 

Когда строка передаётся в кассовый аппарат, она преобразуется во внутреннее представление с учётом кодировки кассового аппарата. При чтении из кассы, строка преобразуется из внутреннего представления в представление Unicode. В процессе преобразований некоторые символы могут быть заменены на их аналоги или на знаки ? если во внутренней кодировке кассы отсутствует соответствующий символ. В связи с этим возникает проблема сравнения строк: если мы запишем строку CStr в кассу, то будет ли она эквивалентна строке EStr, которую мы только что прочитали из кассы. Для получения ответа на этот вопрос нужно вызвать функцию IsStrEq не указывая параметр Length: IsStrEq(EStr,CStr). При этом:

- над строкой CStr производятся преобразования с помощью файла схемы кассового аппарата, который в данный момент находится на связи;

- если строка CStr длиннее строки EStr, то лишние символы строки CStr отбрасываются;

- производится сравнение строк и возвращается истина если строки равны