Промышленные сканеры Symbol - штука недешевая. Зато имеют надежное исполнение, абсолютно всеядные и универсальные, беспроводные, а самое интересное - имеют расширенные возможности управления через собственный протокол SNAPI (ну, есть и попроще у них сканеры, но я про самые вкусные - беспроводные и со SNAPI). Эти возможности позволяют реализовать эффективные сценарии работы.
Одна проблема - нигде не смог найти примеры для работы из 1С по этому протоколу. Все стандартные протоколы поддерживаются, но ведь смак именно в расширенных возможностях!
Поэтому пришлось копаться самому...
(1) Не сталкивался. Админы поделились сакральным знанием о том, что требуемой стабильности работы при работе через терминал им добиться не удалось (периодически были какие-то проблемы), поэтому этот вариант при мне уже не рассматривался.
Сейчас поглядываем в сторону перехода на андроидные терминалы с мобильным клиентом 1С на них (покрыв всю складскую зону вайфаем). Но сам пока еще ничего не щупал.
Здравствуйте!
Не передать команду воспроизведения сигнала на сканер. Делал сначала по примеру Вашего кода в статье. Заставил сканер сканировать штрихкод, с этим все просто. По аналогии и с использованием документации Zebra Scanner SDK добавил команду SET_ACTION. Но сканер молчит. В итоге скачал Вашу обработку, но Ваш код абсолютно идентичен и тоже не работает. Через приложение SDK - C++ Sample App сканер издает звук, а через 1С - нет. Сканер Zebra DS2278. Так же пытался передать прочие команды на сканер. Заработала только команда перезагрузки сканера REBOOT_SCANNER. Остальные, которые пытался, не работают. Нужен только сигнал, остальные команды не нужны. Можете что-нибудь подсказать?
(3) В новых редакциях сканера сканер и база определяются как разные устройства (а может и раньше так было, не суть). Если берется просто первое устройство из списка (как в обработке), то это скорее всего база. Но если раньше можно было посылать сигнал на базу и это успешно работало (сканер пикал), то в новых редакциях сканера (той же модели) "пикнуть" сканером (а также выполнить некоторые другие команды) стало возможно только послав сигнал именно на устройство сканера (как правило, это второе устройство в списке устройств).
Сам не ожидал такого нарушения обратной совместимости для серьезного промышленного производителя. Хотя причины, в принципе, понятны. Но тем не менее. Просто теперь нужно сканер и базу получать через API как отдельные устройства и посылать им команды раздельно.
Возможно, позже допилю обработку под этот новый ньюанс.
ЗЫ. Пока что внес дополнение в статью. Спасибо за замечание.
Кстати, эксперимент с андроидными ТСД завершился успешно (тоже Zebra). Удалось организовать аналогичный по обратной связи сценарий через мобильный клиент 1С. С помощью ВК от IgorKissil, честь ему и хвала.
Здравствуйте!
Подключился к сканеру, удалось выполнить команду издания сигнала. Не удается подключить обработчик события, при вызове метода регистрации обработчика ошибок нет, успешно отрабатывает, возвращает 0. Но при попытке сканирования штрихкод не обрабатывается пробовал и на клиенте и на сервере, (во внешней обработке), в чем может быть проблема?
(9) Прошу прощения. Ввел в заблуждение. Логический номер сканера/базы нужно указывать не в Open/Close, а при посылке команды на сканер в параметре ScannerID. Ниже в комментариях будет подробнее.
(8) Проблема может быть в том, что при обновлении некоторых моделей (для тех же самых моделей!) производитель изменил логику работы. В них с базой и со сканером нужно работать как с разными логическими устройствами. В примере и в обработке идет работа с логическим устройством номер 0. У вас может оказаться так, что 0 - это база, а сканер имеет номер 1. Соответственно нужно в вызовах методов компоненты Open и Close изменить 0 на 1 в параметрах вызова. А при необходимости мигать и "бипать" именно базой - подключаться к ней отдельно как к логическому устройству с номером 0.
День добрый.
Скачал обработку. Пытаюсь отправить на сканер Beep, но выдаёт ошибку:
Error beeping: 112 ERROR_DEVICE_UNAVAILABLE
Сканер Zebra DS2278
Нужно что бы пикал именно сканер, а не база.
Попробовал через SDK - C# Sample App и вот лог:
1. CLOSE - Command success.
2. OPEN - Command success.
3. REGISTER_FOR_EVENTS - Command success.
4. GET_SCANNERS - Command success.
5. GET_PAIRING_BARCODE - Command failed. Error:118
6. SET_ACTION - Command failed. Error:116
НО! Если сначала запускаю 123Scan, потом SDK - C# Sample App, то санер определяется не как HIDkeybord, а как два устройства SNAPI и при посылке Beep на 3 устройство всё бикает как надо
Подскажите как быть, а вернее заставить пиликать в 1С?
Всё разобрался. При переключении всего и вся в SNAPI - всё заработало. Кстати сам сканер имеет ID = 3. В наличии пять комплектов - у кого ID = 3 у кого ID = 2. Жесть.
P.S. Правда в таком режиме не работает NativeApi в 1С, со всеми вытекающими. Получается надо переписывать обработку события в 1С или может есть способ как малой кровью сделать так что бы и стандартный NativeApi работал и SNAPI?
(12) Логический номер базы/сканера указывается в параметре scannerID при посылке команды (в xml с параметрами команды, который передается вторым параметром методу ExecCommand). В обработке логические номера захардкожены, так как в старых партиях DS2278 (желтого цвета) которые использовались у нас с этим никогда проблем не возникало. А вот с появлением новых партий (черных с зелеными вставками) тоже началась чехарда с логическими номерами. И если они не совпадают с захардкоженными в обработке, то она не будет работать так как надо. Нужно изменить их на те, что у вас в реальности.
В продакшене для автоматического определения номера сканера я использовал такую затычку:
// уточнение ID устройства
ПараметрыПодключения.Вставить("ИДУстройства", 1);
Статус = -1; КоличествоСканеров = 0; Ответ = "";
СписокID = new COMSafeArray("VT_I4", 255);
ОбъектДрайвера.GetScanners(КоличествоСканеров, СписокID, Ответ, Статус);
Если Статус = 0 Тогда
НачалоПодстрокиID = Найти(Ответ, "<scannerID>");
Пока НачалоПодстрокиID > 0 Цикл
Ответ = Сред(Ответ, НачалоПодстрокиID + 11);
НачалоПодстрокиМодели = Найти(Ответ, "<modelnumber>");
Если НачалоПодстрокиМодели > 0 Тогда
Если Сред(Ответ, НачалоПодстрокиМодели + 13, 2) = "DS" Тогда // нашли именно сканер, а не базу
КонецПодстрокиID = Найти(Ответ, "</scannerID>");
ПараметрыПодключения.Вставить("ИДУстройства", Число(Сред(Ответ, 1, КонецПодстрокиID - 1)));
Прервать;
КонецЕсли;
КонецЕсли;
НачалоПодстрокиID = Найти(Ответ, "<scannerID>");
КонецЦикла;
КонецЕсли;
Показать
ЗЫ. Если у вас типовая с БПО, то обработку события переписывать не нужно. Просто реализовать в рамках идеологии БПО работу со сканером в режиме SNAPI как работу с отдельным устройством (реализовать соответствующие обертки команд). В итоге при подключении сканера к рабочему месту будет просто выбираться не стандартный драйвер сканера, а какой-нибудь "Сканер SNAPI".
(14) Да уже всё сделал, но всё равно спасибо за ответ :) Ещё сделал проверку, что сканер должен быть в режиме SNAPI:
CoreScanner.ExecCommand(ScannerCommands["GET_DEVICE_TOPOLOGY"],"<inArgs><scannerID>1</scannerID></inArgs>", Response, Status);
ScannerTypeStart = StrFind(Response, "SNAPI");
Если ScannerTypeStart = 0 Тогда
Возврат;
КонецЕсли;
Там же и номер сканера вытаскиваю.
Если у вас типовая с БПО, то обработку события переписывать не нужно.
Конфа типовая, но сииильно переписанная. В итоге подключается и стандартный драйвер и SNAPI одновременно. Если наш сканер в режиме SNAPI, то типовой драйвер не обрабатывает событие и соотв. наоборот.
(15) О, спасибо. Может, кому пригодится. У нас только в SNAPI и работают, так как блокировка сканировки и обратная связь на сканер - обязательные требования.
Если наш сканер в режиме SNAPI, то типовой драйвер не обрабатывает событие и соотв. наоборот.
Логично. Типовой драйвер в SNAPI не умеет, а через дрова производителя меня интересовал только SNAPI. Но если раскопать, то по-идее можно и другие режимы подтянуть.
А если в ШК будут нечитаемые спец символы - таких не мало может быть в коде, а про 2D я вообще молчу особенно всякие ЕГАИСы маркировки шин лекарств и т.д. в которых идёт крипто-хвост в коде. Ну в общем как-то меня это напрягает. С простыми ШК всё ок, а вот со сложными могут быть нюансы.
(17) Да, это простейший "костыль" для исключительно цифровых штрихкодов. Для более сложных штрихкодов потребуется более интеллектуальная обработка.
Но там относительно просто. <datalabel> содержит коды символов штрихкода через пробел с префиксом "0x". То есть если просто разбить эту строку по пробелам, убрать в каждом слове "0x" и преобразовать к числу - то получим честный массив кодов штрихкода, включая спец-символы и прочее.
ЗЫ. И еще ньюанс. Раз цифры начинаются с 0x30 - то выходит что коды символов там в шестнадцатеричке. Т.е. перед преобразованием к числу нужно будет еще в десятичку перевести.
(18) Вот тут я не очень понял :(
Вот есть у нас простейший ШК: 00346200942800000019
Получили datalabel: <datalabel>0x30 0x30 0x33 0x34 0x36 0x32 0x30 0x30 0x39 0x34 0x32 0x38 0x30 0x30 0x30 0x30 0x30 0x30 0x31 0x39</datalabel>
содержит коды символов штрихкода через пробел с префиксом "0x"
30 30 33 34 36 32 30 30 39 34 32 38 30 30 30 30 30 30 31 39
И? а дальше что? Не пойму :( что к числу преобразовывать?
(19) 30 30 33 34 36 32 30 30 39 34 32 38 30 30 30 30 30 30 31 39 - это шестнадцатиричные коды символов штрихкода со сканера.
В десятичке это 48 48 51 52 и т.д.
Просто в ASCII коды символов цифр 0,1,2,3 и т.д. начинаются с 48 (шестнадцатеричной 30). И поэтому достаточно вычесть 48 из кода символа, чтобы получить нужную цифру (ну или просто отбросить троечку в шестнадцатеричке, как сделано в обработке). Но универсальным способом для любых символов будет банальное одинэсное Символ(КодСимвола). А если тебе нужно работать с криптохвостом не на уровне символов, а на уровне их кодов - то вот они сразу и есть.
(10)
Спасибо, что откликнулись! Подписываюсь на события следующим образом
//1001 - REGISTER_FOR_EVENTS
CoreScanner.ExecCommand(1001,
StrTemplate("<inArgs><scannerID>1</scannerID><cmdArgs><arg-int>%1</arg-int><arg-int>%2</arg-int></cmdArgs></inArgs>",
6, // number of events
"1,2,4,8,16,32"),
Response, Status);
Пробовал и с id и без id, и id обеих устройств подряд. id брал из результата процедуры GetScanners.
Метод во всех случаях отрабатывает, возвращает Status 0, только при сканировании 1с ни холодно ни жарко.
Проблема, предполагаю, где-то в обратной связи 1с с com объектом, хотя, при добавлении обработчика (AddHandler) в 1с, ругается, если в процедуре-обработчике параметров меньше чем указано в документации, т.е "событие" он видит. Процедуру обработчик объявлял и на клиенте и на сервере и с клиента на сервере.
Смотрю исходники Sampleapp.cpp, идут в комплекте с SDK, примерно тоже самое написано, только у них все работает, в режиме snapi штрихкод успешно выводится на экран.
пробовал и на другом пк с такой же win7 x64, база файловая, 1с 8.3.15. Сканер DS2278. Вашу обработку правда не использовал, но думаю вряд ли картина будет отличаться.
Была 1 попытка использовать метод из статьи https://infostart.ru/1c/articles/714025/, через эмулятор ничего не вышло
Ищу дальше..
(22) Даже не знаю, что сказать.
В статье подключение к сканеру, регистрации события и подключение обработчика описаны без купюр(все это нужно делать конечно же на клиенте, включая обработчик). В обработке тоже самое. Поэтому если не работает, то обработку скачивать смысла нет.
На всякий случай акцентирую (хотя это вроде очевидно): ссылка на компоненту должна оставаться "живой" после подключения и регистрации. Или событие ловить будет просто некому. То есть должна быть либо клиентской переменной модуля формы (как в обработке)
&AtClient
var CoreScanner
Либо "жить" в экспортных переменных модуля управляемого приложения (как в БПО)
(23) Сейчас понял какой я болван. Действительно абсолютно очевидная вещь, но, видимо в силу отсутствия опыта работы с событиями из внешних компонент даже в голову не пришло ничего подобное. Наверное акцент на объявление переменной нужно сделать в статье, вдруг найдется второй такой же ... вроде меня. Спасибо огромное!
25.
G_114492037554344237850
14.02.21 17:04 Сейчас в теме
Если пользователь долго работает со сканером и не трогает клаву/мышь, то ПК уходит в сон, потому что включён zebra snapi. Кто-нибудь нашёл какое-нибудь элегантное решение этой проблемы?