Вы здесь

CA-Visual Objects: знакомство с RFID (XR480)

rfidНекоторое время назад, читатели моего блога (дневника) могли познакомиться с историей, как я «боролся» с RFID-считывателями. И хотя, результат меня не совсем устроил (а что нас вообще устраивает?) - история получила достойное интересное продолжение. Достойное – это значит, что мне и моему заказчику – понравилось. А как иначе!

А ещё я обещал поделиться опытом, если вернусь к теме RFID. Обещал – исполняю!

 

Технология CA-VO (CA-Visual Objects) основывается на Win32 API. И это роднит его со многими языками программирования, базирующимися на языке программирования Си. Многие даже видят в нём аналогию Delphi. Действительно, они возникли практически одновременно, хотя апологеты КаВо (CA-VO) утверждают, что он «родился» раньше и имел все возможности стать «королём».

 

Но суть не в этом, а в том, что для своих целей программист КаВо (как и программисты, использующие другие языки программирования) имеет все основания и возможности использовать наработки и решения, сделанные в большом семействе, растущем от одного корня (Си). И это – главное.

 
Обычная схема поведения человека, который сталкивается с новой задачей: сначала собрать о ней всю доступную информацию. После этого, он соотносит с ней свои знания, умения и наработки. А в результате – принимает решение – стоит с этим связываться или нет. Но, мы лёгких путей не ищем. Раз попросил товарищ – в лепёшку разбейся, но помоги.

 

А значит, главное – это боевой настрой: «наше дело правое, враг будет разбит, победа будет за нами!» За дело! У товарища на предприятии применяются RFID-считыватели (XR480) компании Motorola. Они уже сняты с производства, но вполне устраивают. Поэтому, все возгласы – «фу, какая гадость» - отметаются, как идиотские. Основной сайт - http://www.symbol.com. Всё верно, эта компания поглощена Motorola.

 

Как прилежный ученик, я скачал «The Enterprise Mobility Developer Kit for C (EMDK for C) ver.2.5) с последним драйвером. И начал его разбирать. От поставщика оборудования со «скрипом» удалось истребовать API, которое поставщик считает правильным. Это оказалось XR_C-API_Rel_3.00.zip (22.06.2006). По мне, как новичку, там оказался более удачный пример на Си, чем примеры в EMDK 2.5. От этой «печки» я и начал «плясать». Ну, а дальше пошли вопросы…

 

Почему за основу взял пример от 2006-го года? Он проще и понятнее. К тому же, КаВо – это 32-ух разрядная среда разработки, которая преимущественно работает с ANSI. КаВо с Unicode тоже работает, но прямой удобной поддержки нет. EMDK старых версий ориентировалось именно на такие среды разработки. А в новой версии всегда есть реальная возможность споткнуться о новый «нюанс». Новые версии – новые «глюки».

 

Плюс, Motorola декларирует (заявляет) поддержку «снизу-вверх». Т.е., «старые» функции должны поддерживаться в более новых драйверах. Хотя, как выяснилось – отклонения есть: при детальном анализе всплыли различия в структурах (между версиями), различия в аргументах функций. Более того, изначально были только API-функции, но разработчики Motorola добавили и, так называемые, API-3 функции. Их функциональность перекрывается и, если начать работать с API, то не рекомендуется использовать API-3. И – наоборот. Более того, в более новых версиях EMDK сделан упор на MS Visual Studio (2005 и новее), а примеры для Си ++ не развиваются (т.е. содержат старый функционал). Вопросы, вопросы, вопросы…

 

Нужен «мозговой штурм» и «помощь клуба». Конечно, параллельно в интернете – я искал толковых людей, которые кодировали под RFID-считыватели. Но намного чаще я находил «гнилые плоды» пропаганды индивидуализма. Если раньше программист программисту был «друг, товарищ и брат», то сейчас никто не желает делиться информацией, даже начального уровня (типа, на чём пишите, что применяете). Всяк желает «обуть» «бедного самаритянина», и что-то с него поиметь. Любые разговоры сразу переходят к фразам: «передайте проект нам, нашим программистам…», «а сколько вы платите?», «да, мы всё умеем, всё сделаем, только передайте постановку и код…» Любая попытка получить ответ  (с той стороны) на конкретный технический вопрос – приводил лишь к жалкому мычанию и потери интереса. Это как с коммивояжёрами (в народе – «представителями канадской фирмы») или с «продавцами бога» - очередными «свидетелями евангелия».

- Дяденька, дай денег, дай денег! А!

 

Ничего, «на каждого мудреца – довольно простоты». Проделав подготовительную работу, я составил список наиболее важных вопросов. Особой проблемой для меня было то, что я писал код дистанционно, не имея доступ к оборудованию. Кроме того, поставщик не настроил полноценную работу оборудования, не дал документацию и всего остального (как я понял, покупали б/у). Заказчик оборудования не умел полноценно с ним работать. Т.е., действовали по принципу: вы хотели купить – мы продали. Если что спросите – может, скажем, нет – значит, нет… Типичная ситуация, когда люди заказчика слабы в «теме», но чего-то очень хотят. Может, ещё и поэтому по-дружески обратились ко мне: помоги с программой, заодно расскажешь, как с этим работать и как его настроить…

 

По большому счёту, мне нужно было написать тестовую программу. Выше, я указал, что почти определился, на основе какого драйвера писать, но мне нужно было подтверждение, что мой подход правильный (всё-таки писал код для оборудования, которого не было «под рукой»). А тут никто даже не хочет сказать, какую библиотеку использует… Тогда я сделал стандартный ход: вы хотите в проект? – пришлите демо. Естественно, демо приходит с библиотекой (странные люди: какую библиотеку используют – не говорят, но присылают её с демо-версией!). Так стало ясно, что большинство использовало библиотеку 2006 года (XR_C-API_Rel_3.00). После этого, я с чистым сердцем закончил тестовый код. И, хотя, я начал разбираться с примера в XR_C-API_Rel_3.00, но вскоре нашёл ещё более удачный, описанный в файле sign_73028.pdf, который скачивается с официального сайта.

 

Что можно добавить? Могу «обрадовать», что примеры из EMDK содержат ошибки (покажите мне программиста, который пишет сразу и без ошибок). Это вполне решаемо для тех, у кого есть глаза и мозги. Переживём! При переносе и адаптации кода (с Си на КаВо), я обратился за помощью на форум http://clipper.borda.ru в раздел «С/С++», где встретил двух очень отзывчивых и терпеливых людей: «Сыроежка», он же Григорьев Владимир и «Sergey Spirin» (Спирин Сергей). Большое им спасибо!!! Благодаря им, я смог одолеть «непонятки» и сделать рывок к финишу.

 

 

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

  1. Функция RFID_GetCommandStatusText() возвращала Unicode-строку (а не ANSI), поэтому в КаВо «в лоб» она не работала. Проблему осознал, рассмотрев результат в массиве. Написал перевод из Unicode в ANSI.
  2. Не с первого раза, но получилось подсоединиться к устройству RFID-считывателя.
  3. Но, не удалось снять с него информацию о серийном номере и прошивке.
  4. И не удалось снять собранную информацию о считанных RFID-метках. Точнее, информация считывалась, но относилась к группе неверно считанных меток (см. структуры TAG_LIST и TAG_LIST_EX).

 

Дальнейшие эксперименты и исследования показали, что программа, собранная под новый драйвер – не работает со старым, а если собрать под «старый» (2006-го года) драйвер – не будет работать с новым. Т.е., Motorola заявляет поддержку «снизу-вверх», но она полноценно не работает. Только на уровне описания функций (но, как я писал выше, реально отличаются и структуры и некоторые переменные). Так же выяснилось, что заказчик теперь хочет использовать и более новые модели считывателей… Значит, нужен самый новый драйвер.

 

Благодаря основательной информационной подготовке, я уже знал, что если использовать более новый драйвер, например  RFIDAPI32PC v.5.2.0.10 (из EMDK v.2.5), то для RFID-считывателей необходимо включить поддержку протокола LLRP. Это можно сделать через WEB-интерфейс. Таким образом, заказчик наконец-то открыл настройки и узнал, что на XR480 у него стоит старая версия прошивки, которая не поддерживает этот протокол. И это объяснило тайну, почему ранее присланная демонстрационная версия (использующая более современный драйвер) от другого программиста не смогла заработать. Проделав, ещё несколько манипуляций я так же предположил, что для полноценной работы драйвера программы нужна не всякая, но «подходящая» прошивка. Т.к., на мой взгляд, только это могло объяснить, что с текущей прошивкой одни драйвера работают, а другие – нет. К тому же, на это – были «мутные» намёки на некоторых «западных» форумах.

 

Что ж, сделав лицо «попроще», я удалился. Осталось только ждать, когда они свяжутся с поставщиком, согласуют действия, поставят новую прошивку и снова попробуют тестовую программу.

 

 

И тут произошло чудо: поставщик, поняв, что заказчик уже начал разбираться с прошивками – «прозрел», перестал «волынить» и сразу сказал, что нужна новая прошивка XR Series rev. 3.4.4 (11.05.2011г.) Скачать её можно с официального сайта. После установления новой прошивки – всё стало работать заметно лучше: «слепые – стали говорить, а немые – бегать». На предложение посотрудничать, программист поставщика ответил положительно и прислал «лично им написанную» демку. Ха-ха, это был стандартный пример из EMDK 2.4, собранный в Visual Studio 2008! Когда ему на это указали и объяснили, что задача вообще-то сложнее – программист загрустил и заёрзал…

 

Прошло ещё некоторое время, снова обратились ко мне… Тут уж основной проблемой стало то, что заказчик слабо представлял, что и как должно работать (не было непротиворечивой постановки задачи). Обычная ситуация. И, хотя меня это несколько раздражает, но тут, как у хирурга – чувства с опытом притупляются. Фактически, постановку задачи пришлось формулировать самостоятельно. А потом ещё и доказывать, что всё правильно. Благо, коллектив был настроен максимально доброжелательно и конструктивно. А это – главное!

 

Вопрос с тем, что в программе, считанные метки (таги) попадали в раздел ошибочных – решился очень просто. Дело в том, что демо-программа содержала код из примера, где настраивались поддерживаемые типы EPC. Как известно, «родными» для XR480 являются EPC_CLASS0, EPC_CLASS0PLUS, EPC_CLASS0ZUMA, EPC_CLASS1, EPC_CLASSG2. Но считыватели могут работать и с другими типами радио-меток. В общем, так и было – это стало понятно, когда я получил доступ к WEB-интерфейсу настроек считывателей. Там стояла «галочка» на «поддержке других типов TAG». Т.е., если вы используете не конкретные типы тагов (меток), то в программе не стоит их ограничивать.

 

Что ещё добавить?.. Новая прошивка RFID-считывателей решила почти все проблемы, но серийный номер устройств, как ни старался – получить не удалось, хотя с удовольствием выдавало информацию о FirmWare и пр. Видимо, Motorola, это решит в дальнейшем. Глядишь, с новой версией и это заработает.

 

По программе. В программе применил многопоточную обработку (см. Thread). Здесь есть «некоторая проблема» в КаВо (я делал в версии 2.7) в том, что. реализованы не все функции, а только минимальный набор. В принципе, для нормальных программистов, пишущих чистые («безглючные») программы – этого вполне достаточно. Конечно, можно использовать API-функции самого Windows. Но, всё-таки, лучше – из КаВо. Связано это с тем, что в КаВо «своеобразная» очистка памяти, и свои функции – они адаптировали. Примеров по многопотоковой обработке в КаВо несколько. Могу только добавить, что для лучшей согласованности потоковых функций с классами, в которых запускаются эти потоки, функции лучше объявлять как STATIC (см. «static/early binding» – раннее связывание). Почему-то на это как-то не обращается внимание.

 

Управление работой с потоком организовал с помощью событий. Делать надо именно так. В противном случае – время от времени в списке считанных меток начинает появляться «пустая» метка. Устройство само прекрасно «понимает», что реально считалось, а что нет. И если не хочется разгребать «руками», то стоит полагаться на событие считывания самого устройства, а не на что-либо другое.

 

Так же важно сделать проверку на правильность считывания – в структуре есть отметка об этом. Имеется ввиду CRC, превышение длины кода и т.д. и т.п. Я столкнулся с этим при испытаниях: применялись разнообразные «левые» метки, что дало «богатую пищу для размышлений». Ещё пример: некоторое время я был в замешательстве, когда заметил, что снимаются одни и те же коды меток (TAG-ов). Естественно, начал искать проблемы в коде. А всё оказалось много проще – их аппликатор (устройство для кодирования меток) работал неправильно. Проблему удалось решить только с немцами, на что ушло несколько дней.

 

С какими проблемами столкнулся ещё? При использовании протокола LLRP установка режима по запросу (on demand mode) фактически отключает работу считывателя. Т.е., реально данные можно собирать только в автономном режиме (on autonomous mode). Но, как только мы делаем нужную установку – программа начинает «отъедать» по 50% процессорного времени на одно устройство. Понятно, что реально процессор грузится не сильно. Но возникают вопросы…

 

Хорошо, допустим, вернулись назад (отказались от LLRP), и используем режим по запросу. В этом режиме процессорное время «не кушается». Замечательно. Но, при снятии данных функцией RFID_ReadTagInventory (или RFID_ReadTagInventoryEX) загрузка процессора снова подскакивает и … снимает данные почему-то около 10-15 секунд. Конечно, в описании (в помощи) было указано, что в режиме по запросу съём данных идёт медленнее, но не настолько же… Поэтому, альтернативы работы в автономном режиме я не увидел.

 

Конечно же, своё приложение я перевёл в фоновый режим (снизил приоритет). Вставил рекомендованные ожидания в цикл сбора данных (чтобы спокойнее отдавало свои кванты времени другим приложениям). И хотя, это прямо не привело к освобождению процессорного времени, но является правильным шагом. Реально же процессорное время удалось несколько снизить лишь за счёт периодического перевода устройств в режим по требованию. Да, но его максимальная длительность определяется физическим расположением антенн (расстояние до метки) и скоростью движения метки. С помощью этого трюка мне удалось снизить нагрузку до 30% на одно устройство считывателя. Но, позже – пришлось отказаться, т.к. эти параметры для разных устройств оказались разными и постоянно менялись (настройки на предприятии не закончились).

 

Ещё одна неприятность. При отключении питания на считывателе, функция RFID_ReadTagInventory (RFID_ReadTagInventoryEX) продолжает «исправно» работать, не генерируя ошибки. Так что, пришлось просто оставить инструкцию пользователям, что при выключении устройства – его надо перезапускать и в программе. Возможно, что все эти проблемы решены в API3 (RFIDAPI32PC). Но, к своему сожалению, до этого я ещё не дотянулся. Всему своё время. Есть время вопросов, будет время ответов.

 

Что ещё? Знаю, что всё-таки как-то можно ограничить максимальную процессорную нагрузку. Достигается это некоторыми манипуляциями. Можно распределить нагрузку по ядрам и процессам. Но это не окончательный выход… Есть для этого и некоторые утилитки, типа ThreadMaster. Но, хочется научиться делать это самостоятельно. Может, кто подскажет?.. А я об этом напишу статейку.

 

 

На сим – позвольте откланяться, но не прощаюсь. А пока… «рука бойца – колоть устала».

 

09.04.2012 г. Карандаш.

 

P.S.: Да, чуть не забыл – неплохим подспорьем для программиста может стать книга Джеффри Рихтера «Windows для профессионалов». Рекомендую.

 

Theme by Danetsoft and Danang Probo Sayekti inspired by Maksimer