Не так давно я выиграл проект на Elance — сделать простое приложение WinForms на Visual Basic, которое будет отображать данные с весов Mettler Toledo PS60. К счастью, эти весы представляют собой HID-устройство, подключаемое через USB. В этом посте я опишу, как работать с подобными HID-устройствами в Visual Basic (и вообще в .
Net) Я немного погуглил и нашел несколько интересных ссылок.
В основном рекомендуется использовать библиотеку «Библиотека USB HID Майка О'Брайена» .
Вот статья, в которой эта библиотека используется для чтения данных из аналогичных шкал: nicholas.piasecki.name/blog/2008/11/reading-a-stamps-com-usb-scale-from-c-sharp Что мне не понравилось, так это угадывание формата данных.
Кроме того, поделившись ссылкой с заказчиком, я получил ответ, что вся библиотека ему не нужна и вообще он предпочел бы, чтобы проблему я решил сам.
Ладно, вооружимся MSDN, а также спецификацией на весы: «Руководство по эксплуатации и техническому обслуживанию весов PS 64067860.pdf» — легко найти в Google. Чтение данных с HID-устройства, если не требует особых сложностей (о чтении ACS NFC SmartCard Reader постараюсь написать позже), довольно простое: 1) нам нужно получить DevicePath нужного нам устройства, вот так: (\?\usb#vid_04a9&pid_1097#207946#{28d78fad-5a12-11d1-ae5b-0000f803a8c2}) 2) откройте этот DevicePath, используя наиболее распространенную функцию CreateFile с доступом GENERIC_READ.
3) Прочитайте с помощью ReadFile.NativeMethods.CreateFile(DeviceInterfaceDetailData.DevicePath, NativeMethods.GENERIC_READ, NativeMethods.FILE_SHARE_READ + NativeMethods.FILE_SHARE_WRITE, security, NativeMethods.OPEN_EXISTING, 0, 0)
res = NativeMethods.ReadFile(ioHandle, bufPtr, 10, bytesRead, IntPtr.Zero)
Как получить DevicePath. Задача не сложная.
Вам необходимо получить список всех устройств, найти шкалы и прочитать структуру HIDD_ATTRIBUTES с помощью функции HidD_GetAttributes(hidHandle, deviceAttributes) Шаг за шагом: 1) Получите руководство по классу устройства.
NativeMethods.HidD_GetHidGuid(hidClass)
2) Создайте перечислитель для класса устройства.
DeviceInfoSet = NativeMethods.SetupDiGetClassDevs(hidClass, IntPtr.Zero, 0, NativeMethods.DIGCF_PRESENT + NativeMethods.DIGCF_DEVICEINTERFACE)
3) Пройдитесь по списку устройств Do While NativeMethods.SetupDiEnumDeviceInfo(DeviceInfoSet, deviceIndex, DeviceInfoData)
4) Используя вложенный цикл, проходим по списку интерфейсов устройства.
Do While NativeMethods.SetupDiEnumDeviceInterfaces(DeviceInfoSet, DeviceInfoData, hidClass, deviceIfaceIndex, DeviceInterfaceData)
5) Получить DevicePath success = NativeMethods.SetupDiGetDeviceInterfaceDetailBuffer(DeviceInfoSet, DeviceInterfaceData, IntPtr.Zero, 0, RequiredSize, IntPtr.Zero) ' Obtain buffer size
success = NativeMethods.SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, DeviceInterfaceData, DeviceInterfaceDetailData, RequiredSize, RequiredSize, DeviceInfoData) ' Get device information using previously recieved buffer size
Вот небольшой трюк с передачей значения null, чтобы получить правильный размер буфера для данных.
Половина задачи выполнена — у нас есть DevicePath. 6) Теперь нужно понять, устройство ли это.
NativeMethods.CreateFile(DeviceInterfaceDetailData.DevicePath, NativeMethods.ACCESS_NONE, NativeMethods.FILE_SHARE_READ + NativeMethods.FILE_SHARE_WRITE, security, NativeMethods.OPEN_EXISTING, 0, 0)
Открываем устройство с ACCESS_NONE (нам нужен только pid&vid, для этого нет необходимости открывать устройство на чтение, большинство устройств не дадут нам этого сделать и будет исключение)
7) И читаем атрибуты Dim deviceAttributes As NativeMethods.HIDD_ATTRIBUTES
deviceAttributes.cbSize = Marshal.SizeOf(deviceAttributes)
NativeMethods.HidD_GetAttributes(hidHandle, deviceAttributes)
8) Теперь просто сравните deviceAttributes.VendorID и deviceAttributes.ProductID с константами и если это то, что вам нужно, то можете выйти из циклов
Теперь займемся весами.
При чтении данных нам дают 6 байт, с которыми нам нужно разобраться.
Согласно спецификации, первый байт пакета — это идентификатор отчета.
Во-вторых, это статус измерения.
Бывает: ошибка, стабильный вес, меньше нуля, колебания и т. д. Полный список есть в коде и в спецификации.
Третий – единицы измерения.
Это и понятно – миллиграммы, граммы, килограммы и т. д. Хоть тройская унция.
Следующие три байта — это фактический вес.
Первый байт веса — это степень десяти, следующие два — фактическое значение.
Таким образом, чтобы получить значение веса, нужно проделать простую операцию: (б[5]*256+b[4])*10^b[3] Вот и все – это довольно просто.
Источник: NativeMethods.vb Public Class NativeMethods
Public Const DIGCF_PRESENT = &H2
Public Const DIGCF_DEVICEINTERFACE = &H10
Public Const FILE_FLAG_OVERLAPPED = &H40000000
Public Const FILE_SHARE_READ = 1
Public Const FILE_SHARE_WRITE = 2
Public Const GENERIC_READ = &H80000000
Public Const GENERIC_WRITE = &H40000000
Public Const ACCESS_NONE = 0
Public Const INVALID_HANDLE_VALUE = -1
Теги: #toledo #scale #visual Basic .
net #usb #hid #.
NET
-
Электронный Микроскоп
19 Oct, 24 -
Ускорить Вход По Ssh В Ubuntu В 100 Раз
19 Oct, 24 -
Top4Top Продает 56 Серверов И Оргтехники
19 Oct, 24 -
Медиапиратство В 21 Веке
19 Oct, 24 -
Статистика Steam-Системы
19 Oct, 24 -
Google Обнаружил Маскировку Сайта Volkswagen
19 Oct, 24