Программируем лазерный считыватель на терминалах сбора данных Cipher (9300)

Программируем лазерный считыватель на CipherПришло время написать вторую публикацию по программированию считывающих устройств терминалов сбора данных. В первой публикации я приводил пример программирования лазерного считывателя на терминалах Motorola(Symbol), в этой публикации я приведу пример программирования лазерного считывателя на терминалах Cipher 9300.
Здесь я приведу простой пример создания программы на Windows CE, которая будет работать со считывателем на терминалах Cipher 93XX. В целом, исходный код данной программы будет основан на примерах, которые приведены в руководстве по программированию, но с небольшим своим усовершенствованием. Вообще удивительно, почему те кто составлял руководство и SDK для разработчиков к этому устройству, не озаботились выложить хотя бы парочку рабочих примеров.

Итак, по порядку. Начнём с того что нам потребуется для разработки.

Как я уже говорил, нам потребуется SDK, по сути нам будут нужны 3 библиотеки, две под .NET, и одна для считывателя которая просто должна быть с проектом: Reader_Ce_Net.DLL, SystemApi_Ce_Net.DLL, ReaderDll_CE.dll.

Все три библиотеки можно накопать в интернете, если очень постараться (постараться придётся очень, очень, очень). Здесь проявляется ещё одна свинья странность от специалистов CipherLab. На сайте компании вы нигде не найдёте ни SDK ни документации по разработке, для его получения вам будет предлагаться написать им письмо и попросить в нём SDK. Само SDK и документация поставляется с терминалом сбора данных вот на таком вот диске:
Диск с SDK и документацией CipherLab
хотя, как я уже говорил, если постараться можно накопать в интернете нужные библиотеки.

Предположим, что диск мы раздобыли (если есть терминал то есть и диск), приступим к разработке.

Первое что необходимо сделать, это создать проект для мобильного устройства в Visual Studio, после чего добавить в созданный проект, через Add Reference две библиотеки, о которых упоминалось ранее: Reader_Ce_Net.DLL, SystemApi_Ce_Net.DLL.

Библиотеку ReaderDll_CE.dll — необходимо в последствии просто добавить в каталог с готовой программой, эта библиотека будет необходима для работы первых двух.

После добавления библиотек, в коде прописываем:
using Cipherlab.SystemAPI;
using System.Runtime.InteropServices;
using Microsoft.WindowsCE.Forms;

Кидаем на форму TextBox и пару кнопок Button. — для отображения считанной информации.

Описываем два класса:
public class MsgWindow : MessageWindow
    {
        public UInt32 decodeMsg = 0;
        int b1 = 0;
        byte[] lpbuf = new byte[25];
        string tmp;

        public Form1 msgform;
        public MsgWindow(Form1 msgform)
        {
            this.msgform = msgform;
            decodeMsg = Win32API.RegisterWindowMessage("WM_DECODEDATA");
        }

        protected override void WndProc(ref Message msg)
        {
            if (msg.Msg == decodeMsg)
            {
                switch (msg.WParam.ToInt32())
                {
                    case 7: //Это ШК...
                        b1 = Reader.ReaderEngineAPI.GetDecodeData(ref tmp);
                        //this.msgform.textBox1.Text = tmp; //Это то как по инструкции.
                        //Мы же расширим функционал и заставим работать считыватель в множестве форм.
                        CallBackMy.callbackEventHandler(tmp);
                        break;
                    default:
                        break;
                }
            }
            base.WndProc(ref msg);
        }
    }

public class Win32API
    {
        [DllImport("coredll.dll", SetLastError = true)]
        public static extern uint RegisterWindowMessage(string lpString);
    }

Первый класс занимается непосредственно получением данных со считывателя, второй регистрирует функцию RegisterWindowMessage, необходимую первому.

Теперь, включаем всё это:
MsgWindow MsgWin;
       
public Form1()
        {
            //Слушает событие которое генерируется считыванием ШК.
            CallBackMy.callbackEventHandler = new CallBackMy.callbackEvent(this.CipherBarcode);
            InitializeComponent();
            
            //Инициируем считыватель.
            MsgWin = new MsgWindow(this);
            int b1 = 0;
            string ver = string.Empty;
            b1 = Reader.ReaderEngineAPI.GetDllVer(ref ver);
            textBox1.Text = ver;
            b1 = Reader.ReaderEngineAPI.InitReader();
        }

void CipherBarcode(string bar)
        {
            textBox1.Text = bar;
        }

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

В Program.cs описываем класс:
public static class CallBackMy
    {
        public delegate void callbackEvent(string what);
        public static callbackEvent callbackEventHandler;
    }

Добавляем в проект ещё одну форму Form2, бросаем на неё TextBox и Кнопку, код второй формы:
public Form2()
        {
            CallBackMy.callbackEventHandler = new CallBackMy.callbackEvent(this.CipherBarcode);
            InitializeComponent();
           
        }

        void CipherBarcode(string bar)
        {
            textBox1.Text = bar;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form1 frm = (Form1)this.Owner;
            frm.return_scaner();

            Close();
        }

В первой форме, добавляем по кнопке открытие второй формы, и функцию обрабатывающую возврат в первую форму:
private void button2_Click(object sender, EventArgs e)
        {
            Form2 frm = new Form2();
            frm.Owner = this;
            frm.Show();
        }

public void return_scaner()
        {
            CallBackMy.callbackEventHandler = new CallBackMy.callbackEvent(this.CipherBarcode);
        }


Функция return_scaner() — необходима, чтобы вернуть обработку события чтения ШК от второй формы обратно в первую, обработку события первая форма заберёт автоматически при создании.

На этом пожалуй и всё, должно получится примерно вот так:
Пример работы сканера Cipher 9300Пример работы сканера Cipher 9300

Скачать исходник примера: CipherTestReader.rar
  • 5 июня 2011, 20:15
  •      
  • Roman


Комментарии (5)

RSS свернуть / развернуть
+
0
Добрый день, при отладке проекта возникли ошибки на строке 29 формы1: «b1 = Reader.ReaderEngineAPI.GetDllVer(ref ver);» Ошибка: Can't find PInvoke DLL 'ReaderDLL_CE.dll'."
Не подскажите с чем может быть связана ошибка? Для отладки выбираю пока платформу: «Windows Mobile 5.0 Pocket PC SDK Эмулятор» правильно ли выбирать эмулятор при отладке? В дальнейшем хочу отладить на аппарате Cipher (9500). и еще маленький вопрос: из-за чего при создании нового проекта автоматом не добавилось пространство имен Microsoft.Windowsce.Forms.dll. Я вручную добавлял библиотеку из католога c:\Program Files (x86)\Microsoft.NET\SDK\CompactFramework\v3.5\WindowsCE Я только начинаю в Visual Studio… Очень срочно нужно написать внешнюю компоненту для 1С
avatar

SergeySh

  • 7 июля 2011, 16:10
+
0
В папку, в которую компилируется проект (bin\Release или bin\Debug) надо добавить библиотеку ReaderDLL_CE.dll.

Такая ошибка может быть из-за этого, но в вашем случае скорее всего из-за эмулятора.

Правильно тестировать такие специфичные вещи на самом устройстве.

То что Microsoft.Windowsce.Forms.dll не добавилось само, это нормально, так и должно быть, по умолчанию они не включаются, добавлять надо в ручную — так-что здесь всё сделали правильно.

А что-за компоненту пишете?
avatar

Roman

  • 7 июля 2011, 16:49
+
0
Есть ещё кое какие особенности.
Если вы используете терминал с Win.CE то лучше создавать и проект на CE.
Если с Win.Mobile то и проект на Mobile.

И ещё, если в ТСД не используется GSM или GPRS модуль — то смысла в Win.Mobile нет, по моему опыту работает только хуже. (CE глючит меньше и работает пошустрее)

И ещё в Win.CE можно в настройках распределять память между программной памятью и памятью для данных (бегунок там такой в настройках есть), в Win.Mob такого бегунка нет, память распределяется одному богу известно, каким методом.
avatar

Roman

  • 7 июля 2011, 17:02
+
0
Библиотека в каталогe bin\Debug присутствует.(Я же ваш проект пытаюсь скомпилировать) Пробовал платформу поставить свой SDK — CE9500 и подключить устройство — устройство подключается успешно. Но при отладке выдает ту же ошибку. Может быть это из за того что у меня SDK и библиотека в комплекте другие и методы в коде этого примера не подойдут для меня? Вроде устройства схожие…
А приложение exe, что в папке Release в вашем архиве должно в windows 7 запускаться? у меня не запускается…
Пишу компоненту чтобы подключить ТСД к 1С Расширение для КПК. Дело в том что 1С в комплекте поставляет библиотеку для работы с ТСД только для устройств Symbol. И исходный код этой библиотеки по видимому написанный в программе eMbedded C++ 4.0. Как думаете там координально весь код нужно менять в исходниках (так как написано для Symbol и с использованием SDK для Symbol) или можно только платформу(SDK) в исходниках подставить свою и скомпилировать?
Еще есть у меня на диске библиотека 9500CE_DLL.dll и к ней 2 файла 9500CE_DLL.lib и ReaderDll.h но эта библиотека на загружается в 1С, так как 1С выпустила свои требования/методы для работы с вн компонентами.(там есть инструкции по созданию внешних компонент, в которых содержатся только методы которые переваривает 1с) Не подскажите в каком направлении лучше двигаться чтобы достичь результата?)
avatar

SergeySh

  • 7 июля 2011, 18:21
+
0
Запускать проект с использованием библиотек для считывателя только на устройстве, а для тестов компилировать без поддержки считывателя — тогда и на эмуляторе запустится.
Сделать это можно при помощи условной компиляции — здесь об этом.

По поводу связи с 1С — я использую другой вариант, терминал связывается с БД MySQL (можно любой другой, не суть важно, важно что не с 1С) так и проще и надёжнее. А 1С — связывается не с терминалом а с этой самой БД.

С одной стороны, прослойка и кажется что несколько усложняется архитектура системы. На деле всё оказывается гораздо проще и надёжнее чем лезть с терминала в 1С на прямую.

Во первых реализовать взаимодействие из 1С с любой БД не проблема и гораздо проще чем извне лезть в 1С. Вот здесь пример.

Во вторых работа с ТСД перестаёт зависеть от загруженности 1С, то-есть нагрузка на сервер 1С никак не влияет на работу устройств.

Если хотите реализовать работу с ордерами заказов, мягкими чеками или чем-то подобным довольно сложным. На мой взгляд архитектура с промежуточной БД — больше подходит.

Да и вообще в миру даже есть разделение такого рода систем на Бэк офис (это 1С и ей подобные) и Фронт офис (это те системы которые взаимодействуют с оборудованием и клиентами, скажем так, находятся на передовой и их скорость, надёжность и производительность порою гораздо важнее).

Что касается библиотек для 1С — большей частью всё что видел (по крайней мере для стандартных конфигураций торговли) весьма стандартнеько и очень не функционально. Скажу так, оно и само не всегда работает адекватно, а когда необходимо сделать что-то (скажем с терминалом) сложнее чем просто провести инвентаризацию или собрать документ становится совсем грустно.
avatar

Roman

  • 7 июля 2011, 18:51

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.