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

Кратко по конфигурации: сервер на Кубунту 18.04, на нем VirtualBox, под которым запускается Win7 для терминального доступа к 1С. На RaspberryPi установлен Raspbian и FreeRDP для подключения к удаленной сессии и usbip для передачи сканера и принтера по локальной сети к линукс-серверу, который в свою очередь штатными настройками VirtualBox передает их в уиндовс.

Вначале были попытки перевести сканер в режим клавиатуры и соединять его посредством RDP. Сплошные минусы — при задержке передачи часто пропадают цифры. В 1С невозможно включить штатную обработку, она рассчитана на использование COM-портов, а без нее надо тыкать мышей в нужное для заполнения поле. Вот если-бы через сеть передать сразу USB… Решение есть и  будет описано ниже. Протестировано на USB сканере  Honeywell MS5145, переведенный в режим com-порта и USB принтере чеков Posiflex.

читать дальше

Установка USBIP.
Используется для проброса портов USB от клиента к серверу,  при этом на клиенте ставим сервер USBIP, а с сервера будем подключаться к его (клиента) USB портам.
На Pi установлен:
pi@raspberrypi:~ $ lsb_release -a
Distributor ID: Raspbian
Description: Raspbian GNU/Linux 9.3 (stretch)
Release: 9.3
Codename: stretch

версия ставится из дистрибутива:

sudo apt install usbip

подгружаем модули:

sudo modprobe usbip-core
sudo modprobe usbip-host
sudo modprobe vhci-hcd

Добавляем модули в автозагрузку:
sudo nano /etc/modules
usbip-core
usbip-host
vhci-hcd

смотрим доступные устройства:

pi@raspberrypi:~ $ sudo usbip list -l, —local
— busid 1-1.1 (0424:ec00)
Standard Microsystems Corp. : SMSC9512/9514 Fast Ethernet Adapter (0424:ec00)

— busid 1-1.2 (04d9:1203)
Holtek Semiconductor, Inc. : Keyboard (04d9:1203)

— busid 1-1.3 (0458:003a)
KYE Systems Corp. (Mouse Systems) : NetScroll+ Mini Traveler / Genius NetScroll 120 (0458:003a)

— busid 1-1.4 (0d3a:0369)
Posiflex Technologies, Inc. : unknown product (0d3a:0369)

— busid 1-1.5 (0c2e:0720)
Metrologic Instruments : Metrologic MS7120 Barcode Scanner (bi-directional serial mode) (0c2e:0720)

Расшариваем нужные устройства:

sudo usbip bind --busid=1-1.4
sudo usbip bind --busid=1-1.5

если все без проблем, то будет такой ответ:
usbip: info: bind device on busid 1-1.5: complete

запускаем демона:
sudo usbipd -D  (добавить в автозапуск!)

Посмотреть доступные устройства можно командой:
sudo usbip list -r localhost

Exportable USB devices
======================
— localhost
1-1.5: Metrologic Instruments : Metrologic MS7120 Barcode Scanner (bi-directional serial mode) (0c2e:0720)
: /sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5
: (Defined at Interface level) (00/00/00)

1-1.4: Posiflex Technologies, Inc. : unknown product (0d3a:0369)
: /sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.4
: (Defined at Interface level) / unknown subclass / unknown protocol (00/00/02)

Синим цветом выделены значения портов, по которым можно выключить раздачу соответствующей командой:
usbip detach —port=00

Подключение с клиентской машины (в нашем случае от сервера с 1С к Rpi).

Сервер с Ubuntu 18.04. смотрим установленное ядро:

uname -a

Linux valery-desktop 4.15.0-21-generic

отдельного пакета для usbip нет, тут он в составе linux-tools, их и установим:

sudo apt install linux-tools-4.15.0-21-generic

P.S. вообще-то достаточно, и правильно. установить sudo apt install linux-tools-generic
и тогда команда будет находится в /usr/bin/usbip

так-же необходимо подключить модули usbip-core usbip-host vhci-hcd и поставить их в автозагрузку (аналогично ранее описанному).

подключаем устройство:

sudo /usr/lib/linux-tools/4.15.0-21-generic/usbip attach -r 192.168.10.202 —busid=1-1.5

смотрим:

valery@valery-desktop:~$ lsusb
….
Bus 005 Device 002: ID 0c2e:0200 Metrologic Instruments MS7120 Barcode Scanner

Подключен!

Привязка устройства к определенному симлинку.

В линуксе, в отличие от виндовс, устройство получает номер устройства по очереди подключения, например первый сканер будет /dev/ttyUSB0, второй /dev/ttyUSB1 и т.д.

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

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

(взято http://hsd.net.ua/privyazka-usb-ustroystv-k-ttyusb):

Имя файла может быть произвольным, важно только расширение ".rules"
sudo nano /etc/udev/rules.d/scaner.rules
****************
SUBSYSTEM=="tty", ENV{ID_MODEL}=="Honeywell_Scanning_and_Mobility_Scanner", SYMLINK+="HoneywellScanner"
****************
нужные параметры подглядываем из:
udevadm info --query=property --name=ttyUSB0 (естественно должен быть  порт с нужным нам устройством)

sudo service udev restart

Теперь наш сканер, неважно каким способом будет подключен, через usbip либо напрямую в компьютер, естественно будет получать свой путь по своим каким-то правилам и будет может быть устройством /dev/ttyUSB0, или там /dev/ttyUSB3, но получит постоянную ссылку /dev/HoneywellScanner, которую мы указали в настройках.

подсмотреть выхлоп просто:
cat /dev/HoneywellScanner и пикнуть сканером, в терминал должны вывалиться цифры от штрихкода.

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

sudo /usr/lib/linux-tools/4.15.0-20-generic/usbip port

Imported USB devices
====================
Port 00: <Port in Use> at Low Speed(1.5Mbps)
unknown vendor : unknown product (0c2e:0720)
3-1 -> usbip://192.168.1.102:3240/1-1.4
-> remote bus/dev 001/009
Port 01: <Port in Use> at Full Speed(12Mbps)
unknown vendor : unknown product (0d3a:0369)
3-2 -> usbip://192.168.1.102:3240/1-1.2
-> remote bus/dev 001/004

отключение соответственно командой:

/usr/lib/linux-tools/4.15.0-20-generic/usbip detach —port=00

 

Для возможности подключения в VirtualBox COM  портов нужно добавить пользователя, от которого запускается виртмашина, в группу dialout:

sudo usermod -a -G dialout valery

а VirtualBox, запущенный от пользователя, может не видеть  подсоединенные USB устройства, решение:

sudo usermod -a -G vboxusers valery

и обязательно перелогинится.

В VirtualBox сканер прописываем в настройки COM-port как устройство /dev/ttyUSB0 (или если сделали привязку к симлинку как было описано выше — /dev/HoneywellScanner)

и здесь вылазит одна интересная деталь — в этом случае в винде для сканера не надо ставить никаких драйверов (в отличие от прямого подключения usb-сканера)! Будет читаться назначенный порт как стандартный с драйверами от майкрософт.

Еще один очень важный нюанс — при попытке передать сканер как usb устройство, он через VirtualBox будет читаться только при выставленных настройках портов в версию 1.1 (и нужны драйвера сканера винде), и при этом не будет возможности подключать флешки и другие высокоскоростные устройства. При настройках портов на версию 2 и 3 бокс не ругается, но сканер напрочь не читается!

В итоге настраиваем, как было сказано, подключение сканера как com, а для принтера делаем фильтр автоподключения по usb (версии 2).

Проблемы:

При всём хорошем, вылезла  проблема с VirtualBox, а именно то, что при например физическом отключении (либо если порт отключился в usbip) СОМ-порта виртуальная машина ругается на его отключение и затем его можно восстановить только перезагрузкой ВМ. То есть, например моргнет питание, сервер на UPS-e а Rpi без резервного питания — и всё,   перезагружай всех по очереди (тоже будет даже если кто-нибудь перевоткнет сканер! ). Это относится только к СОМ порту, принтер подключенный через USB работает конечно без проблем.
Надо подстраиваться под реалии:

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

Создаем с ее помощью пару устройств (до запуска ВМ) и одно из них приписываем виртуальной машине как СОМ-порт,а так как устройства создаются с произвольными (свободными) номерами /dev/pts/X есть возможность сразу создать нужные именованные линки к ним, линки размещаем в /tmp чтобы не иметь проблем с правами.

socat pty,raw,echo=0,link=/tmp/COM1 pty,raw,echo=0,link=/tmp/inpCOM1

проверяем, в одном терминале открываем

cat /tmp/COM1

во втором шлем

echo 12345678 > /tmp/inpCOM1

получаем его в первом терминале. все работает.

Для автозапуска используем systemd, обязательно указать пользователя, иначе будет от рута и не будет доступа к pts устройству

sudo nano /etc/systemd/system/com1.service


[Unit]
Description=Create pseudo COM1-ports for VirtualBox

[Service]
Type=simple
ExecStart=/usr/bin/socat pty,raw,echo=0,link=/tmp/COM1 pty,raw,echo=0,link=/tmp/inpCOM1
User=valery

[Install]
WantedBy=multi-user.target

systemctl daemon-reload
systemctl enable com1.service
systemctl start com1.service

смотрим:
valery@valery-desktop:~$ systemctl status com1.service

● com1.service — Create pseudo COM-ports for VirtualBox
Loaded: loaded (/etc/systemd/system/com1.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2018-05-24 13:21:09 +06; 2s ago
Main PID: 8295 (socat)
Tasks: 1 (limit: 4915)
CGroup: /system.slice/com1.service
└─8295 /usr/bin/socat pty,raw,echo=0,link=/tmp/COM1 pty,raw,echo=0,link=/tmp/inpCOM1

мая 24 13:21:09 valery-desktop systemd[1]: Started Create pseudo COM-ports for VirtualBox.

Теперь прописываем порт в Virtualbox:

 

 

 

 

 

 

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

 

 

 

 

 

 

 

 

 

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

valery@valery-desktop:~$ cat /dev/ttyUSB0 > /tmp/inpCOM1

пикаем сканером штрихкод и смотрим в 1С:

 

 

 

 

 

 

 

Всё замечательно проходит, теперь можно на «горячую» переподключать устройство.

Теперь создадим сервис для перенаправления ввода вместо вышеиспользованной команды cat /dev/ttyUSB0 > /tmp/inpCOM1
сервис динамический, будет запускаться с передаваемым из udev правила именем по следующему шаблону:

sudo nano /etc/systemd/system/usb2com\@.service                    # \@ слэш экранирует для bash спецсимвол «@»

[Unit] Description=Send data from usb dev to pty
After=com%i.service
BindsTo=dev-COM%i.device

[Service] Type=simple
ExecStart=/bin/dd if=/dev/COM%i of=/tmp/inpCOM%i bs=1
User=valery

systemctl daemon-reload
Запускается сервис командой systemctl start usb2com@1.service,
«1» между «@» и «.service» подставляется в юните как «%i»
BindsTo указывает сервису следить за устройством dev-COM%i.device, как только устройство исчезнет, сервис выгрузится.
Точное наименование устройства можно увидеть так:
systemctl list-units —all —full | grep «.device»
наше dev-COM1.device

Для автозапуска создадим правило в udev срабатывающее при подключении сканера:
nano /etc/udev/rules.d/scanner1.rules
SUBSYSTEM=="tty", ENV{ID_MODEL}=="Barcode_Device", ENV{ID_VENDOR_ID}=="065a", SYMLINK+="COM1", RUN+="/bin/systemctl --no-block start usb2com@1.service"
service udev restart
нужные параметры смотрим для соответствующего устройства в: udevadm info —query=property —name=ttyUSB0
срабатывание udev можно отслеживать командой
udevadm —debug monitor

Теперь при подключении данного сканера сработает првило в udev, которое создаст линк /dev/COM1 и запустит юнит usb2com@1.service, который  будет передавать данные из
/dev/COM1 во вход /tmp/inpCOM1 до тех пор, пока присутствует устройство. При отключении сканера юнит отключится, при подключении его заново запустит правило в udev.

С автоподключением сканера закончено, и неважно как он будет подключен, локально к машине либо по usbip.

 

Теперь нужно автоматизировать переподключение usbip.

проверка по порту и типу устройства, пример:

ACTION==»add»,SUBSYSTEM==»block»,DEVPATH==»/devices/pci0000:00/0000:00:14.0/usb3/3-3*»,RUN+=»/bin/su $env{valery} -c /home/valery/test.sh»

# ACTION==»remove»,SUBSYSTEM==»block»,DEVPATH==»/devices/pci0000:00/0000:00:14.0/usb3/3-3*»,RUN+=»/bin/su $env{valery} -c /home/valery/test.sh»

плохая затея ACTION==»remove», устройство переподключается при раздаче и сервис падает, но надо решать как выключать.

Рабочий вариант:

Установить sudo apt install linux-tools-generic (на x86 машинах, на Pi просто usbip)

————————————————

Автозапуск usbipd :

sudo nano /etc/systemd/system/usbipd.service

[Unit]
Description=usbipd daemon
After=network.target

[Service]
Type=forking
ExecStart=/usr/bin/usbipd -D

[Install]
WantedBy=multi-user.target

 

зарегистрировать и  в атозапуск:

systemctl daemon-reload

systemctl enable usbipd.service

systemctl start usbipd.service


Создать правило для сканера:

nano /etc/udev/rules.d/scanner.rules

ACTION==»add», SUBSYSTEM==»tty», ENV{ID_MODEL}==»Barcode_Device», ENV{ID_VENDOR_ID}==»065a», RUN+=»/bin/systemctl —no-block start usbdev@2-1.7.service»

sudo service udev resart

которое запускает Unit nano /etc/systemd/system/usbdev@.service

———————————————————————=

[Unit]
Description=usbip share device busid=%i
After=network-online.target
Requires=network-online.target

[Service]
Type=simple
ExecStart=/home/valery/.myscript/usbipdev.sh %i
User=valery

————————————————————————

sudo systemctl daemon-reload

который будет запускать скрипт слежения за устройством и подключением/переподключением при необходимости

nano /home/valery/.myscrypt/usbipdev.sh

________________________________________________________

#!/bin/bash

# USBDEV=065a:0009
SRVIP=192.168.10.63
# MYIP=192.168.10.68
MYIP=$(/bin/ip addr show eno1 | sed -En ‘s/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p’)
# echo «$MYIP»

BusID=$1

# USBDEV=$2 #херня получается, от юнита не передать, потому просто проверим что там на этом бусе сидит
VID=$(/bin/cat /sys/bus/usb/devices/$BusID/idVendor )
PID=$(/bin/cat /sys/bus/usb/devices/$BusID/idProduct )
USBDEV=»$VID:$PID»
# echo «$USBDEV»

CheckDef=60

function Sendmessage {
CURL_RESULT=$(curl -X POST «https://api.telegram.org/bot1111111111111111111111111/sendMessage» -d «chat_id=-11111111111111111111111111&text=${MESSAGE}» > /dev/null 2>&1 )
}

function LocalCheck {
# проверка на наличие устройства локально
if lsusb | grep -q «$USBDEV»; then :;
else

i=0
while [ $i -lt 5 ]; do
if lsusb | grep -q «$USBDEV»; then
StopS=0
break
else
StopS=1
i=$[$i+1] fi
sleep 1
done

if [ «$StopS» -eq 1 ]; then
MESSAGE=»Устройство $BusID не обнаружено локально, сервис будет отключен»
Sendmessage
sudo systemctl stop usbdev@$BusID.service
fi
fi
}

##########################################################################

# sudo -bn /usr/bin/usbip unbind —busid=$BusID

while true; do
# проверяем наличие сервера в сети
SRVCHK=0
while ! ping -c1 $SRVIP &>/dev/null; do
if [ $SRVCHK -eq 0 ]; then
MESSAGE=»Сервер $SRVIP недоступен с $MYIP»
Sendmessage
SRVCHK=1
fi
sleep 29
LocalCheck
done

# проверить на баинд, если нету то баиндить
if /usr/bin/usbip list -r localhost | grep -q «$USBDEV»; then :;
else
sudo -bn /usr/bin/usbip bind —busid=$BusID
MESSAGE=»Do bind bus $BusID device $USBDEV on $SRVIP»
Sendmessage
# посылаем команду серверу присоединить, коли было анбаинд, то и полюбому не присединено
ssh valery@$SRVIP sudo /usr/bin/usbip attach -r $MYIP —busid=$BusID
fi

# проверяем на сервере наличие устройства
if ssh $SRVIP lsusb | grep -q «$USBDEV»;
then Check=»$CheckDef»;
else
Check=1
MESSAGE=»Устройство $BusID на адресе $SRVIP не обнаружено, попытка переподключения»
Sendmessage
sudo -bn /usr/bin/usbip unbind —busid=$BusID
fi

sleep $Check

LocalCheck

done

exit

__________________________________________________________________________

чтобы не ругался выхлоп команды usbip list -r localhost
usbip: error: failed to open /usr/share/hwdata/usb.ids

надо скачать отсутствующий файл описания оборудования:

sudo wget http://www.linux-usb.org/usb.ids -P /usr/share/hwdata/

_____________________________________________________________________________________________________

передать ключ RSA для безпарольного входа:

со стороны Pi к серверу от пользователя:

ssh-keygen  # если ранее не генерировался

ssh-copy-id -i .ssh/id_rsa.pub адрес_сервера


дать разрешение управлять юнитом без пароля от пользователя, добавив в конец строку:

sudo visudo

ALL ALL=NOPASSWD: /usr/bin/usbip

Cmnd_Alias USBIP_CMDS = /bin/systemctl start usbdev@2-1.7.service, /bin/systemctl stop usbdev@*.service
ALL ALL=NOPASSWD: USBIP_CMDS

то-же на сервере для запуска без пароля команды usbip по ssh

ALL ALL=NOPASSWD:/usr/bin/usbip

 

Далее пойдет описание практических установок и настроек на основании вышеприведенных опытов.

Установка и настройки:

Автоподключение сканера:

переходим в root
sudo -s

Создаем сервис для перенаправления данных от пользователя valery:


user=valery; cat > /etc/systemd/system/usb2com\@.service << EOF
[Unit]
Description=Send data from usb dev to pty
After=com%i.service
BindsTo=dev-COM%i.device

[Service]
Type=simple
ExecStart=/bin/dd if=/dev/COM%i of=/tmp/inpCOM%i bs=1
User=$user

EOF

Создаем сервис для порта с номером N и запуском от пользователя valery


N=1; user=valery; cat > /etc/systemd/system/com$N.service << EOF
[Unit]
Description=Create pseudo COM$N-ports for VirtualBox

[Service]
Type=simple
ExecStart=/usr/bin/socat pty,raw,echo=0,link=/tmp/COM$N pty,raw,echo=0,link=/tmp/inpCOM$N
User=$user

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload

systemctl enable com1.service  # установить в автозагрузку только этот(эти) сервис(ы)

systemctl start com1.service

Создаем правило для udev запуска нашего usb2com сервиса (запись одной строкой без переносов!):

nano /etc/udev/rules.d/scanner1.rules

SUBSYSTEM=="tty", ENV{ID_MODEL}=="Barcode_Device", ENV{ID_VENDOR_ID}=="065a", SYMLINK+="COM1", RUN+="/bin/systemctl --no-block start usb2com@1.service"

service udev restart

 

 

 

Комментарии, обсуждение.