Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

Hiperion 1300g

369  
Murr патриот29.06.17 11:36
Murr
29.06.17 11:36 

Hiperion 1300g


Это - сканер штрих-кодов. Ну такой полосковый код на упаковке.

Внутри штука достаточно сложная. С программной точки зрения - тоже.


Подключение - простое - УСБ.

Внутри, однако, сканер может быть сконфигурирован как устройство на КОМ-порте.

В Device Manager он так и представляется - Hiperion 1300g (COM6).

Почему - не знаю - наследие.


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

Сейчас написано так, что порт привязки читается из конфига, затем - инициализируется

устройство посылкой команды.


Сканеров на одной машине может быть несколько, пулл и обвязку Я уже написал и врезал,

но там есть моментик - фабрике сканеров нужно/дается только имя сканера, а порт -

неизвестен. Хочу чтобы при создании сканера порт находился автоматически.


Нормально было бы опросить порт, но суппорт пока не говорит как это сделать.


Вторым вариантом было бы прочесть в реестре. Там есть информация по сканеру, но

нет (или пока не нашел) информации по привязке к порту.


Еще один вариант - через ManagementObjectSearcher. Информация по УСБ-портам есть,

по привязке к КОМ-порту - нету.


В общем - непонятно где искать инфу об привязке. Ткните носом куда смотреть...


#1 
Murr патриот29.06.17 18:01
Murr
NEW 29.06.17 18:01 
в ответ Murr 29.06.17 11:36

Таки сделал.


Имя порта лежит в Регистре (у меня):

HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Enum\usbcdcacm\VID_0C2E&PID_0B0A&MI_00\1&2b53a856&0&7_294012cb_0_0000_00\Device Parameters

Имя значения: PortName

Сложность представляет получение идентификатора устройства: VID_0C2E&PID_0B0A&MI_00\1&2b53a856&0&7_294012cb_0_0000_00

При поиске по УСБ-устройствам находится подключенный к УСБ сканер, но он имеет другой идентификатор устройства. Конвертировать из одного в другое у меня не получилось.


Потому обошел это дело поиском по всем устройствам, которые соответствуют эмуляторам КОМ-портов и имеют нужное имя.


Работающая версия для Вин7:


internal class TComPortManager
{
const string ComEmulatorKey = "USBCDCACM";
//const string DeviceName = "Hyperion 1300g";
const string select_format = @"Select * From Win32_PnPEntity WHERE DeviceID LIKE '{0}%' AND Name LIKE '{1}%'";

static List<DeviceInfo> GetDevices(string pDeviceName)
{
List<DeviceInfo> devices = new List<DeviceInfo>();

ManagementObjectCollection collection;
string select = String.Format(select_format, ComEmulatorKey, pDeviceName);
using (var searcher = new ManagementObjectSearcher(select))
collection = searcher.Get();


foreach (var device in collection)
{
try
{
DeviceInfo deviceInfo = new DeviceInfo(device);
devices.Add(deviceInfo);
}
catch (Exception ex)
{
string msg = ex.Message;
}
}

collection.Dispose();

return devices;
}

const string RegistryBase = @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\";
const string EntryName = @"\Device Parameters";

public static string[] GetComNames(string pDeviceName)
{
List<string> comms = new List<string>();

var devices = GetDevices(pDeviceName);

foreach (var device in devices)
{
string fullKey = RegistryBase + device.DeviceID + EntryName;
string portName = (string)Registry.GetValue(fullKey, "PortName", null);
comms.Add(portName);
}

return comms.ToArray();
}

}


Как сделать то же самое под НТ4 и ХР - пока не смотрел. Но там - точно по другому.


И немного про мудака билли.

Есть у него набор примеров по использованию сканеров (как HID устройств).

Так этот мудень требует Вин8 / Вин8.1 минимально... ему, блин, обязательно Метро интерфейс иметь... это - для сканера... поцик, бля...

#2 
Murr патриот30.06.17 15:02
Murr
NEW 30.06.17 15:02 
в ответ Murr 29.06.17 18:01

Непонятное.


Выросло из обработки приема на КОМ-порте.


Все элементарно просто - ожидаем первого вызова ScannerGetData_


дальше начинаются чудеса

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

- если первым обработчиком подвязан паблиц метод - количество вызовов будет... 1.

Вроде как во втором случае все правильно, но тест - провалится...


Кто-то выскажется по поводу?


#3 
NightWatch коренной житель01.07.17 11:46
NightWatch
NEW 01.07.17 11:46 
в ответ Murr 30.06.17 15:02, Последний раз изменено 01.07.17 12:05 (NightWatch)

Да тут как бы все просто. Кривой код.

Line 19:

worker.RunWorkerAsync();
worker.ScannerGetData += ScannerGetData_1;
worker.ScannerGetData -= ScannerGetData_2;

Что делает -= во втором случае не понятно.

Подвязывание делегатов после RunWorkerAsync - race condition.


Line 36:

public void ScannerGetData_1(string data)
{
    ++exceptions;
    throw new Exception("Data recived");
}

После выброса исключения в обработчике события следующие за ним оставшиеся делегаты не будут вызваны.

Как следствие private void MyWork(object sender, System.ComponentModel.DoWorkEventArgs e) вываливается с исключением, и цикл

for (int i = 0; i < 5; ++i)
{
    System.Threading.Thread.Sleep(1000);
    worker.SleepCondition = false;
}

работает вхолостую.


Line 33:

Assert.Fail("Exception didn't happen, but accounted " + exceptions.ToString() + " times.");

Бессмысленно ждать исключения, которое было брошено в другом потоке. Для этого существует AsyncCompletedEventArgs.Error.

#4 
Murr патриот03.07.17 18:40
Murr
NEW 03.07.17 18:40 
в ответ NightWatch 01.07.17 11:46

Кривой код.

-----

Вот что значит делать что-то в тяпницу после обеда...



Лине 19

-----

описался и не заметил. Вопрос об вызове приватного метода снят - вроде работает.



race condition.

-----

В данном случае - без разницы, специфика имплементации.

Есть однако зависимость от внутренней реализации воркера - может и вообще не реагировать ни на какие назначения после запуска... вот треад-статиk он не понимает...



Line 36:

-----

Ожидалось не это.

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

Вот это и мешает... бо воркер - жив, хотя уже и не работает...

Ожидалось, что воркер занулится - нулл-эхцептион.



Для этого существует AsyncCompletedEventArgs.Error.

-----

Только он, увы, не доступен в рун-методе воркера.

#5 
NightWatch коренной житель03.07.17 19:13
NightWatch
NEW 03.07.17 19:13 
в ответ Murr 03.07.17 18:40
В данном случае - без разницы, специфика имплементации.

Именно в данном случае race condition.

Как у тебя worker в реальном проекте выглядит, я не знаю.


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

BackgroundWorker - это не просто поток, но еще чуток кода. Так что советую почитать доку по нему.


Только он, увы, не доступен в рун-методе воркера.

Он доступен в другом месте. Читай https://msdn.microsoft.com/en-us/library/system.componentm...

#6 
Murr патриот04.07.17 10:42
Murr
NEW 04.07.17 10:42 
в ответ NightWatch 03.07.17 19:13

Именно в данном случае race condition.

-----

В данном случае у меня управление вызовом - внешнее. Т.е. Я точно знаю, что назначение (+=) будет сделано ДО того как потребуется вызов.

То, что фактическая имплементация допускает возникновение расе кондитион - это уже отдельно.

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


Так что советую почитать доку по нему.

-----

Читал. Не помогает.

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



Читай

-----

Видимо ты меня хотел вот сюда послать: https://msdn.microsoft.com/en-us/library/system.componentm...

Увы, у меня это не используется.

У меня либо есть данные и тогда вызывается метод обработки, либо данных нет и тогда все спит.

Руннер, как видно из примера, находится в том же воркере и поставляет наружу только корректные

данные.

Завершение работы - не предусмотрено. Совсем. Все возможные ошибки данных - обрабатываются

в вызываемом методе. Ошибки коммуникации с ком-портом - в руннере.

Хотя, скорее всего, следующим шагом будет проверка на жив ли поток и перезапуск если сдох...


#7 
NightWatch коренной житель04.07.17 16:49
NightWatch
NEW 04.07.17 16:49 
в ответ Murr 04.07.17 10:42

Тогда к коду претензий нет. Видать и правда Билли намудрил что-то.

#8