Реализация сканера штрих-кода на Java - PullRequest
25 голосов
/ 16 ноября 2011

Господа, у меня есть вопрос.Школьный Java-проект, над которым я сейчас работаю, требует наличия USB-сканера штрих-кода в качестве внешнего входа для подключения к моему ноутбуку.Я на самом деле не купил USB-сканер, так как он довольно дорогой для студента.Поэтому я должен собрать доказательства того, что этот сканер будет работать с моей программой.

Может ли сканер считывать штрих-код (предположительно распечатанный онлайн) и сохранять его в переменной?Если это так, правда ли, что событие действия для нажатия сканера будет читаться точно так же, как нажатие клавиши клавиатуры?Если так, то как будет выглядеть строка кода?

Кроме того, если бы вы могли опубликовать свой опыт работы со сканерами штрих-кодов или дать какой-либо совет, например, какой сканер купить, это очень помогло бы.Ура! * * 1005

Ответы [ 4 ]

31 голосов
/ 24 декабря 2011

Мне недавно пришлось внедрить систему сканера для взаимодействия с Java.

Я использовал Honeywell Voyager MS9540 USB-сканер штрих-кода.

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

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

Эта модель имеет настройку для эмуляции последовательного порта, затем вы можете прочитать отсканированные данные, используя пакет javax.comm. Для меня это было намного лучше, чем хук клавиатуры, чтобы получить данные штрих-кода, потому что программе не требуется фокусировка, прежде чем она сможет интерпретировать сканирование (я не хотел бы создавать глобальный хук клавиатуры).

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

Вероятно, вы могли бы считывать данные напрямую с любого USB-сканера (без эмуляции последовательного порта, который есть в этой модели), выполнив интенсивное кодирование JNI, но я не был готов потратить время на разработку собственного кода.

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

Для этого сканера не требуется драйвер для эмуляции последовательного порта. Я нашел инструкции по внедрению и необходимые драйверы здесь (на вкладке "программное обеспечение"). Загрузите пакет, озаглавленный «USB-последовательный драйвер Honeywell Scanning and Mobility (HSM)». В документе под названием «Руководство по началу работы с USB-драйвером последовательного порта HSM» содержатся инструкции.

Если вы не знакомы с API javax.comm. Пожалуйста, прочитайте введение в этом примере Рика Проктора - в нем рассказывается, где взять jar и куда поместить файлы (javax.comm не входит в стандартную комплектацию большинства пакетов java) .

Я уверен, что есть другие модели сканеров, которые имеют эмуляцию последовательного порта (я не работаю для Honeywell).

Вот несколько упрощенная версия моего класса считывателя штрих-кодов:

package scanhandler;


import java.awt.AWTException;
import java.awt.Robot;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Enumeration;
import java.util.Properties;
import java.util.TooManyListenersException;
import javax.comm.CommPortIdentifier;
import javax.comm.PortInUseException;
import javax.comm.SerialPort;
import javax.comm.SerialPortEvent;
import javax.comm.SerialPortEventListener;
import javax.comm.UnsupportedCommOperationException;

public class ScanHandler implements Runnable, SerialPortEventListener {

    private static CommPortIdentifier   myCommPortIdentifier;
    private static Enumeration          portList;
    private static String               TimeStamp;
    private static String               driverClass;
    private static String               connectionString;
    private static String               comPort;    

    private Connection                  myConnection;
    private InputStream                 myInputStream;
    private Robot                       myRobot;
    private SerialPort                  mySerialPort;
    private Thread                      myThread;


    public ScanHandler() {

        // open serial port
        try {
            TimeStamp = new java.util.Date().toString();
            mySerialPort = (SerialPort) myCommPortIdentifier.open("ComControl", 2000);
            //System.out.println(TimeStamp + ": " + myCommPortIdentifier.getName() + " opened for scanner input");
        } catch (PortInUseException e) {
            e.printStackTrace();
        }

        // get serial input stream
        try {
            myInputStream = mySerialPort.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // add an event listener on the port
        try {
            mySerialPort.addEventListener(this);
        } catch (TooManyListenersException e) {
            e.printStackTrace();
        }
        mySerialPort.notifyOnDataAvailable(true);

        // set up the serial port properties
        try {
            mySerialPort.setSerialPortParams(9600,
                SerialPort.DATABITS_8,
                SerialPort.STOPBITS_1,
                SerialPort.PARITY_NONE);
            mySerialPort.setDTR(false);
            mySerialPort.setRTS(false);

        } catch (UnsupportedCommOperationException e) {
            e.printStackTrace();
        }

        // make a robot to pass keyboard data
        try {
            myRobot = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }

        // create the thread
        myThread = new Thread(this);
        myThread.start();
    }

    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {}
    }

    // on scan
    public void serialEvent(SerialPortEvent event) {

        if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {

            StringBuilder myStringBuilder = new StringBuilder();
            int c;
            try {

                // append the scanned data onto a string builder
                while ((c = myInputStream.read()) != 10){
                   if (c != 13)  myStringBuilder.append((char) c);
                }               

                // send to keyboard buffer if it the barcode doesn't start with '5'
                if (myStringBuilder.charAt(0) != '5') {

                    for (int i = 0; i < myStringBuilder.length(); i++) {
                        myRobot.keyPress((int) myStringBuilder.charAt(i));
                        myRobot.keyRelease((int) myStringBuilder.charAt(i));
                    }

                // here's the scanned barcode as a variable!
                } else {
                    TimeStamp = new java.util.Date().toString();
                    System.out.println(TimeStamp + ": scanned input received:" + myStringBuilder.toString());                    
                }

                // close the input stream
                myInputStream.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {

        // read ScanHandler properties
        Properties myProperties = new Properties();
        try {
            myProperties.load(new FileInputStream("config.properties"));
            comPort             = myProperties.getProperty("ScanHandler.comPort");
        } catch (IOException e) {
            e.printStackTrace();
        }              

        try {

            // get our pre-defined COM port
            myCommPortIdentifier = CommPortIdentifier.getPortIdentifier(comPort);
            ScanHandler reader = new ScanHandler();

        } catch (Exception e) {
            TimeStamp = new java.util.Date().toString();
            System.out.println(TimeStamp + ": " + comPort + " " + myCommPortIdentifier);
            System.out.println(TimeStamp + ": msg1 - " + e);
        }
    };    
}
9 голосов
/ 16 ноября 2011

Сканер штрих-кода, который я использовал, действовал как клавиатурное устройство (в операционной системе оно отображалось как USB-устройство HID-клавиатуры). Когда штрих-код был отсканирован, он отправил код, как если бы он был напечатан. Для взаимодействия с ним не требовалось никаких специальных API.

7 голосов
/ 21 января 2015

Я знаю, что это довольно старая тема, но поиск может помочь вам.

Это можно рассматривать как дополнение к ответу Джеронимо:

Для ОС Linux нет необходимости устанавливать драйверы для сканеров штрих-кода в режиме последовательной эмуляции, поскольку имеется встроенная поддержка последовательных портов USB. Мы используем несколько типов сканеров Honeywell, и все они работают «из коробки», эти сканеры с последовательной эмуляцией отображаются в наших системах как / dev / ttyACM0, / dev / ttyACM1 и т. Д.

Недавно мы перешли с javax.comm на jssc в качестве библиотеки java для интерфейса последовательных портов. Если я хорошо помню, в 64-битной системе Windows 7 библиотека javax.comm не может читать или записывать данные с / на последовательный порт, а jssc имеет очень похожие API.

0 голосов
/ 19 августа 2015

Я понимаю, что это старый вопрос, но решил добавить дополнительное решение для имитации ввода сканера штрих-кода. Это решение работает только для имитации ввода со сканера в виде данных клавиатуры.

Так как сканер часто просто использует ввод с клавиатуры, мы можем смоделировать это, используя скрипт AutoHotkey . Ниже приведен пример скрипта:

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

; Barcode 1
; Hotkey = ctrl + alt + 1
^!1::
    SendInput [BC200015]
Return

; Barcode 2
; Hotkey = ctrl + alt + 2
^!2::
    SendInput [BC300013]
Return

Просто замените [BC300013] и [BC200015] тем, что вы ожидаете от сканера.

...