Настройка декодирования для Mifare (подробно) 1. У тебя есть читалка (допустим z-2) и читалка турникета (matrix)2. Главная задача это привести треки получаемые со считалок в один единый вид (в 10 формате)3. Если3.1 Mifare3.1.1 Скачиваешь утилиту Putty3.1.2 Подключаешься через Putty к читалке3.1.3 Сканируешь карту и получаешь трек Mifare[A1B2C3D4] (какая то номерная последовательность, которая совершенно не интересна нам) <терминальные символы>3.1.4 Открываешь version.txt из каталогов TCPCardReader и decodercards (лежит в сборке в UTILS)3.1.5 Начинаешь читать и разбираться какие параметры нужны3.1.6 Итак, сперва, чтобы настроить декодирование в TCPCardRead нам нужно отделить искомую последовательность от остальной информации. В данном случае необходимо вытащить UID из трека Mifare[A1B2C3D4] (какая то номерная последовательность, которая совершенно не интересна нам) <терминальные символы> (выделено жирным, без скобок !).3.1.7 Открываем TcpCardReader.ini удаляем от туда секцию [TCPCARDREADER] (если есть (мы её не используем))3.1.8 Смотрим секции типа [READER1], [READER2], ... [READERN] - эти секции отвечаю за каждую свою подключённую читалку. Если нам нужна 1 читалка, то делаем секцию [READER1], если две, то записываем секцию [READER2] и т.д.3.1.9 Итак, настроим, например, только 1 считыватель. Смотрим секцию [READER1] [READER1] COMPORT=9 COMPORTPARAMS=baud=4800 data=8 parity=N stop=1 ;Параметр Prefix задаёт строку, которая передаётся клиентам перед первым прочтенным символом Prefix= ;Параметр Postfix задаёт строку, которая передаётся клиентам после последнего прочтенного символа Postfix= ;Использовать decodecards.dll useDecodeCards=0 StartTermChars=; FinishTermChars=?#13;#10;#0; ;Файл логирования треков TrackLogFile= ConvertTrackLog=0 IncludeTypeStartTermChar=0 IncludeStartTermChar=0 NeedCheckAndReopenCom=1 3.1.10 Смотрим параметры из version.txt ( например, через NotePad++ ) {COMPORT=9 - номер порта берется из диспетчера устройств. (диспетчер устройств -> порты)COMPORTPARAMS=baud=4800 data=8 parity=N stop=1 (параметры подключения) практически некогда не меняется (берется из свойств порта. см. диспетчер устройств)};Параметр Prefix задаёт строку, которая передаётся клиентам перед первым прочтенным символомPrefix= (строка №7 из version.txt) (";Параметр Prefix задаёт строку, которая передаётся клиентам перед первым прочтенным символом") Это означает, что передаваемый трек клиентам будет начинаться с установленного префикса. Например, если предположим, что декодирование настроено, то пусть наш трек выглядит так 1200. Мы хотим передавать трек с префиксом ;, то устанавливаем в параметр Prefix=; При передаче трека клиентам (abonementmanager, connecter, ...) передастся трек ;1200 . Если мы хотим передать трек с префиксом mrgreen, то ставим в параметрах Prefix=mrgreen. Соответственно при передаче трека клиентам, они получат mrgree1200 ;Параметр Postfix задаёт строку, которая передаётся клиентам после последнего прочтенного символаPostfix= (строка №9 из version.txt) (";Параметр Postfix задаёт строку, которая передаётся клиентам после последнего прочтенного символа") По аналогии с суффиксом. Это означает, что передаваемый трек клиентам, оканчивается на установленный суффикс. Например, хотим передать суффикс ?, то Postfix=?. Клиенты получат трек 1200?. Если хотим передать суффикс ?#, то ставим Postfix=?#. Клиенты получат трек 1200@?#.Таким образом, если установлены параметры Prefix=; и Postfix=?, то клиенты получат трек ;1200? ;Использовать decodecards.dlluseDecodeCards=0 (строка №27 из version.txt) использовать= 1 - не использовать=0 decodecards.dll для извлечения номера. По умолчанию 0 - не использовать. StartTermChars=; (строка №28 из version.txt) "Стартовые символы. Используются, если useDecodeCards=1" Стартовые символы или управляющие. Это символ(ы), с которого идет наш необработанный трек, передаваемый в decodercards. FinishTermChars=?#13;#10;#0; (строка №29 из version.txt) Терминальные символы. Используются, если useDecodeCards=1. Это символ(ы), с которого идет наш не обротанный трек, передаваемый в decodercards. Т.е.Допустим Трек Mifare[A1B2C3D4] (какая то номерная последовательность, которая совершенно не интересна нам) <терминальные символы> (терминальный символ зависит от прошивки/настройки устройства, он передается вместе с данными, как правило это перевод на новую строку и возврат каретки и - №10 и №13 символы таблицы ASCII https://ru.wikipedia.org/wiki/ASCII ; получаемая последовательность со считывателя в TPCCardReader или Putty выглядит наподобие Mifare[A1B2C3D4] (....) ). Если сделаем StartTermChars=i и FinishTermChars=?#13;#10;#0; то будет следующее:1. В треке находиться начальный символ, указанный в StartTermChars, это i. В нашем случае M i fare[A1B2C3D4] (....) 2. Затем ищется окончание (последний символ), указанные в FinishTermChars (можно указывать несколько подряд).Т.е. смотрим на Mifare[A1B2C3D4] (....) ,есть ли в данном треке символ "?" - нетуесть ли символ #13; (синтаксис 13 элемента в таблице в TCPCardReader - это возврат каретки), есть Mifare[A1B2C3D4] (....)  Ага, последовательность найдена и результат будет : fare[A1B2C3D4] (....) и он уже передается на обработку в decodercards.dll ;Файл логирования трековTrackLogFile=ConvertTrackLog=0(строка №107 из version.txt) Если TrackLogFile определен, то используется дополнительный параметр ConvertTrackLog.Он определяет, каким образом логировать невизуальные символы. По умолчанию ConvertTrackLog=0 (не конвертировать).Если ConvertTrackLog=1, то невизуальные символы конвертируются в их код. IncludeTypeStartTermChar=0 - (строка №126 из version.txt) 1.1. IncludeTypeStartTermChar - тип обработки стартового символаИмеет смысл, если useDecodeCards=1, IncludeStartTermChar=1 и UseOriginalTrack=0Если IncludeTypeStartTermChar=0 (по умолчанию), то стартовый символ НЕ передается в decodecards, а подставляется перед истинным номером как дополнительный префиксЕсли IncludeTypeStartTermChar=1 , то стартовый символ передается в decodecards и участвует в извлечении истинного номера Обычно используем по умолчанию NeedCheckAndReopenCom=1 - (строка №135 из version.txt) Если NeedCheckAndReopenCom=1 (по умолчанию), то постоянно контролируется состояние соединения. Если связь потеряна, то происходит попытка переподключиться.NeedCheckAndReopenCom=0 можно устанавливать, если устройство подключается не к USB, а к COM-порту. Оставляем 1.3.1.11 Смотря пункт 3.1.10, составляем следующую конфигурацию в секции [READER1] COMPORT=9 COMPORTPARAMS=baud=4800 data=8 parity=N stop=1 ;Параметр Prefix задаёт строку, которая передаётся клиентам перед первым прочтенным символом Prefix=; ;Параметр Postfix задаёт строку, которая передаётся клиентам после последнего прочтенного символа Postfix=? ;Использовать decodecards.dll useDecodeCards=1 StartTermChars=i FinishTermChars=?#13;#10;#0; 3.1.12 Итак, получили на входе в decodercards.dll трек на обработку fare[A1B2C3D4] (....) 3.1.13 Разбираемся с декодированием. Открываем ini из сборки и видим [frf] fsUnit=fsdecodecard.upas [general] usemask=1 TrackResultLog= [mask] card = 05015005* card2= 778=12345678=* cardfile=file://cards.txt [cards] CardPrefix = 05015005 ; 05015005280507210 CardPrefix = 750= CardPrefix = 778=999999999= CardPrefix = 778=123456789= StaffCardPrefix = 778=87121234= StaffCardPrefix = 778=201050001 RegularCardPrefix = 778=444444444= PDSCardPrefix = 811q [cards.cardREPLACECARDNO] ExcludedPrefix= code=2 CardDecodeType = REPLACECARDNO NewCardNo = 5678956 [cards.ARRAYOFBYTES] CardDecodeType = MASK mask=*cccc* bitmask=$7FFFFFFF MaskType=ARRAYOFBYTES code=2 [cards.Card2] ExcludedPrefix=778=12345678= ; CardDecodeType = ANGSTREMCARD ; CardDecodeType = ANGSTREMBRASLET code=2 ; CardDecodeType = LAST8 ; CardDecodeType = LAST9 ;CardDecodeType = MASK mask=hhhhhhhh* bitmask=$7FFFFFFF [cards.Card] ExcludedPrefix=05015005 ; CardDecodeType = ANGSTREMCARD ; CardDecodeType = ANGSTREMBRASLET code=2 ; CardDecodeType = LAST8 ; CardDecodeType = LAST9 CardDecodeType = MASK mask=ddd ;mask=hhhhhhhh* bitmask=$FFFFFFFF DecodeTypeEx = 0 [cards.RegularCard] ; CardDecodeType = ANGSTREMCARD ; CardDecodeType = ANGSTREMBRASLET code=22 [cards.StaffCard] ; CardDecodeType = ANGSTREMCARD ; CardDecodeType = ANGSTREMBRASLET code=21 [cards.PDSCard] ; CardDecodeType = ANGSTREMCARD ; CardDecodeType = ANGSTREMBRASLET code=24 3.1.14 Разберем по секциям [frf] fsUnit=fsdecodecard.upas Эта секция отвечает подключение файла со скриптом (FastScript). Можно написать свой алгоритм для обработки трека. [general] usemask=1 TrackResultLog= TrackResultLog= - имя файла, в котором будет результат обработки трека. (если надо делаем, обычно убираем) usemask=1 (version.txt строка 41) Если usemask=1, то секция [cards] игнорируетсяЕсли usemask=1, тогда при декодировании проверяется, какой маске соответствует считанный трек.После этого происходит обращение к секции [cards.ИМЯ МАСКИ] Ставим единичку и создаем секцию [mask] (если нет), в ней прописываемcard_mi (произвольное имя) = (маска, по которой смотрим в какую секцию отправить на обработку трек)В наем примере сделаем так: card_mi = fare* (fare* берется из трека fare[A1B2C3D4] (....) , * - любой символ) Таким образом, все треки, которые содержат fare будут определяться и направляться на обработку в секцию card_mi Также в этом случае необходимо создать секцию [cards.card_mi], если её нет ! В этой секции могу содержаться различные параметры (см. version.txt), но рассмотрим под наш случай.Нужно будет для обработки трека полученного fare[A1B2C3D4] (....) использовать следующие параметры: ExcludedPrefix, code, CardDecodeType, mask. ExcludedPrefix-Отрезаем от трека префикс.Для того, чтобы корректно обработать наш трек fare[A1B2C3D4] (....) , необходимо удалить fare[.Тогда необходимо прописать в параметре ExcludedPrefix следующее: ExcludedPrefix=fare[Таким образом, мы получим внутри decodercards следующую последовательность трека A1B2C3D4] (....) , где жирным указано интересующая нас последовательность в шестнадцатеричной системе. Далее используется параметр CardDecodeType - этот параметр определяет алгоритм декодирования. Существуют несколько вариантов, например, LAST8, LAST9, MASK, FastScript и т.п.В нашем случае мы используем MASK (накладываем маску и сравниваем с нашим треком) CardDecodeType = MASKдалее необходимо добавить параметр mask, который собственно, и определяет её. Из version.txt строка 32 описание следующее mask=**hh* - взять 3-й и 4-й символ как цифры в шестнадцатеричном форматеилиmask=**dd* - взять 3-й и 4-й символ как цифры в десятичном формате Поскольку нам из трека A1B2C3D4 ] (....) интересна лишь последовательность A1B2C3D4, то наша маска выглядит следующим образом: mask = hhhhhhhh. Т.е. берем символы с 1 по 8 в шестнадцатеричном формате и преобразуем в конечный вариант в десятичный формат (DEC). Остается для обработки добавить лишь параметр code - он отвечает за тип карты.code=2 (фичи с ним на обучении только, либо сами) На выходе при треке A1B2C3D4 должны получить 2712847316 3.1.15 Таким образом получаем следующую конфигурацию decodercards.ini при TCPCardReader [frf] fsUnit=fsdecodecard.upas [general] usemask=1 [mask] card_mi = fare* [cards.card_mi] ExcludedPrefix=fare[ code=2 CardDecodeType = MASK mask=hhhhhhhh 3.1.16 Можно проверить правильность настроек с помощью теста в TCPCardReader. В поле слева от кнопки тест, вводиться трек, который должен передаться в decodercards.dll В отображение вы должны получить последовательность отправки символов клиентам (трек). Если вместо этого получаете : CHR OUT> ;CHR OUT> 0CHR OUT> ?Вы неправильно настроили декодирования - повторяете изучение материала с 1 пункта 3.1.16 Можно также убедиться по логам decodercards, при использовании декодировании в логах TCPCardReader можно увидеть только информацию отправляемую клиентам. Лог правильно настроенного TCPCardReader: 22.09.2021 18:05:35 581059359 2C74> CALL extractcardnoexp_int64: track=fare[F2D1BF1F] 191,53746 1K (0004,08) ; term0= , term1= 22.09.2021 18:05:35 581059359 2C74> CALL extractcardnoex: track=fare[F2D1BF1F] 191,53746 1K (0004,08) ; term0= , term1= 22.09.2021 18:05:35 581059359 2C74> UseMask2: UseMask=1 22.09.2021 18:05:35 581059359 2C74> CALL extractcardnoex2: track=fare[F2D1BF1F] 191,53746 1K (0004,08) ; term0= , term1= 22.09.2021 18:05:35 581059375 2C74> EXIT extractcardnoex2: result=4073832223 , cardcode=2 , ExtractWithoutPrefix2=F2D1BF1F] 191,53746 1K (0004,08), ci=card_mi 22.09.2021 18:05:35 581059375 2C74> EXIT extractcardnoexp_int64: result=4073832223 , cardcode=2 CALL extractcardnoexp_int64: track=fare[F2D1BF1F] 191,53746 1K (0004,08) ; term0= , term1= | - прилетел трек EXIT extractcardnoex2: result=4073832223 , cardcode=2 , ExtractWithoutPrefix2=F2D1BF1F] 191,53746 1K (0004,08), ci=card_mi | ci - имя секции, по которой трек обрабатывается; ExtractWithoutPrefix2=F2D1BF1F] 191,53746 1K (0004,08) - результат после исключения из трека префикса, | result=4073832223 -результат декодированияEXIT extractcardnoexp_int64: result=4073832223 , cardcode=2 | результат на выходе из decodercards.dll !!! 3.1.17 После правильного настроенного TCPCardReader, необходимо настроить decodercards.ini при abonementmanager или при коннекторе, или при gkhostconnect.Рассмотрим простой и стандартный вариант- это Abonementmanager3.1.18 Открываем decodercards.ini и видим [frf] fsUnit=fsdecodecard.upas [general] usemask=1 TrackResultLog= [mask] card = 05015005* card2= 778=12345678=* cardfile=file://cards.txt [cards] CardPrefix = 05015005 ; 05015005280507210 CardPrefix = 750= CardPrefix = 778=999999999= CardPrefix = 778=123456789= StaffCardPrefix = 778=87121234= StaffCardPrefix = 778=201050001 RegularCardPrefix = 778=444444444= PDSCardPrefix = 811q [cards.cardREPLACECARDNO] ExcludedPrefix= code=2 CardDecodeType = REPLACECARDNO NewCardNo = 5678956 [cards.ARRAYOFBYTES] CardDecodeType = MASK mask=*cccc* bitmask=$7FFFFFFF MaskType=ARRAYOFBYTES code=2 [cards.Card2] ExcludedPrefix=778=12345678= ; CardDecodeType = ANGSTREMCARD ; CardDecodeType = ANGSTREMBRASLET code=2 ; CardDecodeType = LAST8 ; CardDecodeType = LAST9 ;CardDecodeType = MASK mask=hhhhhhhh* bitmask=$7FFFFFFF [cards.Card] ExcludedPrefix=05015005 ; CardDecodeType = ANGSTREMCARD ; CardDecodeType = ANGSTREMBRASLET code=2 ; CardDecodeType = LAST8 ; CardDecodeType = LAST9 CardDecodeType = MASK mask=ddd ;mask=hhhhhhhh* bitmask=$FFFFFFFF DecodeTypeEx = 0 [cards.RegularCard] ; CardDecodeType = ANGSTREMCARD ; CardDecodeType = ANGSTREMBRASLET code=22 [cards.StaffCard] ; CardDecodeType = ANGSTREMCARD ; CardDecodeType = ANGSTREMBRASLET code=21 [cards.PDSCard] ; CardDecodeType = ANGSTREMCARD ; CardDecodeType = ANGSTREMBRASLET code=24 3.1.18 Приводим к этому виду, удалив и почистив почти все [general] usemask=1 [mask] card_all = * [cards.card_all] code=2 [cards.Card] code=2 [cards.RegularCard] code=22 [cards.StaffCard] code=21 [cards.PDSCard] code=24 Подробнее [mask] card_all = * Как и по аналогии с TCPCardReader делаем настройку по маске.card_all = * | * - все получаемые треки. Поскольку abonementmanager подключается к TCPCardRead, на стороне которого происходят все преобразования треков, получаемых со считывателей, в абонемент manager прилетает TCP только трек в десятичном формате. Т.е. исходя из выше обработанного к нам прилетает 2712847316. Соответственно, мы уже получили почти готовый трек.Создаем секцию [cards.card_all]И устанавливаем "физический" тип карты code=2. Также для того, чтобы корректно отрабатывалось определение физического типа рекомендуется использовать во всех клиент с decodercards.dll данные секции: [cards.Card] - гостеваяcode=2 [cards.RegularCard] - постояннаяcode=22 [cards.StaffCard] - карта персоналаcode=21 [cards.PDSCard] - ПДСcode=24 Соответственно, при прикреплении карты в базу будет прикрепляться трек с физическим типом 2. При наличии служебных секций он определится, как гостевой 3.1.19 Осталось настроить декодирование при gkhostconnect 3.1.20 При использовании GKHOST в GKHOSTCONNECT на основе выше перечисленного трека прилетают карты вида CARD A1 B2 D3 C4 ! На конце обычно еще бывает F (*CARD A1 B2 D3 C4*FF ...) зависит от прошивки считывателя 3.1.21 Открываем decodercards.ini при gkhostconnect и удаляем все, оставляя только необходимое и приводим к следующему виду [frf] fsUnit=fsdecodecard.upas [general] usemask=1 TrackResultLog= [mask] card = * [cards.card] code=2 CardDecodeType = MASK mask=hhhhhhhh Поскольку к нам прилетает карта сразу HEX значении. А при передаче в decodercards элементы #### CARD откидываются автоматически, остается лишь преобразовать hex в dec. И поставить корректный тип карты в нашем случае это 2. 4. Готово. (отходим и нервно курим в сторонке) Дополнительные материалы Настройка_decodecards_.txt version (decodercards).txt version (TCPCardReader).txt