Реализация сканера штрих-кода на Java

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

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

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


person user976123    schedule 16.11.2011    source источник
comment
Если ваш курсор находится в текстовом поле или поле ввода, сканер просто «запишет» туда код. В сканере нет ничего особенного. Вы не получите событие. Однако, если у вас есть веб-страница, вы можете попробовать что-то вроде события OnChange JS.   -  person Nishant    schedule 16.11.2011


Ответы (4)


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

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

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

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

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

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

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

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

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

Если вы не знакомы с API javax.comm. Пожалуйста, прочтите введение в этом примере Рика Проктора — там рассказывается вам, где взять банку и куда поместить файлы (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);
        }
    };    
}
person egerardus    schedule 23.12.2011
comment
Похоже, что эти драйверы предназначены только для Windows, поэтому вы не сможете использовать свою программу в других операционных системах, кроме Windows, если сделаете это таким образом. - person stommestack; 27.06.2013
comment
Может быть, мне это нужно было только для окон. Я не искал глубоко, но должно быть что-то, что преобразует USB в COM-порт для Linux или MAC. - person egerardus; 28.06.2013
comment
@Geronimo: где я могу найти этот файл config.properties. - person Farhan Shirgill Ansari; 15.05.2015
comment
@ShirgillAnsari Я думаю, что единственное, что код примера считывает из config.properties, — это COM-порт, например: COM1, COM2, COM3 и т. д., независимо от того, к какому последовательному порту подключен ваш сканер штрих-кода. - person egerardus; 17.05.2015
comment
Этот код использует порт USB или последовательный порт? - person Nauman Khalid; 23.05.2016
comment
@NaumanKhalid Он считывает USB-сканер штрих-кода, который эмулирует последовательный порт (пожалуйста, смотрите текст над кодом). - person egerardus; 23.05.2016
comment
@Geronimo Я использую устройство чтения штрих-кода TVS Usb, когда я пишу COM1 или COM2, оно показывает нулевое значение, и я получаю javax.comm.NoSuchPortException - person Rohitesh; 24.12.2016
comment
@Geronimo, ты имеешь в виду код JNI? кивать JNDI? - person Denys; 09.02.2018
comment
@ Денис, спасибо, JNI. должно быть, делал некоторую конфигурацию Tomcat, когда я писал это... - person egerardus; 30.11.2018

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

person prunge    schedule 16.11.2011
comment
Можно поинтересоваться, какая модель у вас? - person user976123; 16.11.2011
comment
@user976123 user976123 Это было много лет назад на предыдущей работе, извините, я не могу вспомнить модель. - person prunge; 16.11.2011

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

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

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

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

person Pavel Kucera    schedule 21.01.2015
comment
Добро пожаловать в stackoverflow.com. Пожалуйста, попробуйте отформатировать свой ответ в редакторе. - person Nagama Inamdar; 21.01.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] тем, что вы ожидаете от сканера.

person philosowaffle    schedule 19.08.2015