이후에 젯슨에 연결해야하기 때문에 까먹지 않기 위하여 연결 과정을 적어보려한다. 제발 쉽게 끝날 수 있길,,
이번 프로젝트에서 nfc칩에 데이터를 담은 단어 카드를 사용하여 치료아동의 단어 학습 놀이를 진행할거라서
nfc 리더기와 nfc 칩을 구매했다. 근데 알리에서,,
일단 컴퓨터에 리더기를 연결하고 nfc 칩을 대면 빨간불이 초록불로 바뀌면서
디바이스에 리더기와 카드가 뜨는 것을 알 수 있다.
근데 그럼 이걸 어떻게 읽어오는,,??
nfc 구매처에서 알려준 소프트웨어 다운로드 링크를 들어가면 이렇게 400에러를 직면한다.
이를 해결할 수 있는 방법
1. chat gpt 한테 찡찡거린다 -> 정품 acs 리더기가 아닌 것 같은데 얘는 그걸 모르니까 계속 acs 사이트에 가서 드라이버를 다운받으라고 한다.(실패)
2. 리더기 판매 사이트와 리뷰를 정독한다 -> 다들 대체 어떻게 했는지 후기가 좋다. 나와 같은 문제를 직면한 사람은 67명 중 두명정도 있는데 그사람들도 해결방법을 알려주진 않았다.(실패)
3. 판매자에게 연락해서 찡찡거린다 -> 해결
내가 해결하려고 하지말고 판매자에게 처음부터 찡찡거릴걸 그랬다. 아주 손쉽게 새 링크를 보내주었고
짜잔! 이제 어떡하지
라고 생각하는 순간 mp4이 있다는 사실을 알게 되었다.
사실 zip 파일이길래 열자마자 트로이목마에 감염되어버릴까봐 무섭긴해서 튜토리얼 먼저 확인했다.
일단 튜토리얼을 확인했는데 중국어가 아닌 영어라서 그나마 다행이었고,,
근데 정말 무서운 상황이다. 위험하다고 구글에서 막았다.. 이거 약간 랜섬웨어,,
일단 다 알아보고 zip 파일 멀웨어 검사를 진행한 후 압축을 해제하고 실행을 시켰다.
지금 내 컴퓨터는 여전히 살아있긴 하지만 혹시 모른다.. 앞으로 어떻게 될지,,,
여튼 드라이버 실행 파일을 클릭해서 실행시키고 리더기에 칩을 가져다대면
이렇게 nfc 칩의 UID번호를 가져온다.
찾아본 바로는 아마 사람들이 대부분 nfc 리더기를 사용하는 이유는 nfc칩이 담긴 출입증 등의 카드 내의 UID를 복제해서 다른 칩에 옮겨담고 휴대폰같은 데 부착하고 사용하기 위함인 듯하다.
우리는 복제가 아니라 칩 내부에 데이터를 담아야하기 때문에 이 프로그램으로 실행을 하면 안될 것 같고 바로 코드로 작성을 해봐야할 것 같다.
원래 spring boot를 이용하여 코드를 작성하려고 했으나 nfc를 읽어오는 라이브러리가 문제가 있는건지 실행이 안됐다.
문제를 해결하려다가 포기하고 파이썬으로 넘어왔다.
파이참으로 프로젝트를 새로 만들고 아래의 라이브러리를 설치하였다.
pip install pyscard
ACR122U 리더기를 사용하기 때문에 보통 nfc를 읽어오는 nfcpy 라이브러리가 지원되지 않았다.
NFC UID 읽어오기
import smartcard.System
from smartcard.util import toHexString
def read_nfc():
"""데이터 읽기"""
readers = smartcard.System.readers()
if not readers:
print("NFC 리더기를 찾을 수 없습니다.")
return
reader = readers[0]
connection = reader.createConnection()
connection.connect()
get_uid = [0xFF, 0xCA, 0x00, 0x00, 0x00] # UID 요청 명령
response, sw1, sw2 = connection.transmit(get_uid)
if sw1 == 0x90:
print(f"NFC 태그 UID: {toHexString(response)}")
else:
print("NFC 태그를 읽을 수 없습니다.")
if __name__ == "__main__":
read_nfc()
칩 내부에 고유한 아이디를 불러오는 코드를 작성했다.
칩을 대지 않은 상태라면 에러가 뜨는데 일단 그건 리더기가 읽어오는 시간을 지속시키면 될 것 같다.
이제 이 칩에 write로 글을 작성하면 되는데 문제가
왜때문인지 휴대폰 앱으로는 잘만 써지던 칩이 읽기전용이라는거..??
찾아본 바로는 휴대폰 앱인 NFC Tools는 iOS에서 직접 시스템 api를 사용하기 때문에 pyscard와 nfcpy보다 인식률이 높아서 쓰기도 가능하다고 한다,,
pyscard와 nfcpy 는 주로 NDEF 태그 기반 방식을 지원해서 내가 산 IsoDep를 지원하는 칩은 따로 APDU 명령을 사용해야한다고,,
- NDEF 방식 : NFC 태그에 데이터를 저장하는 표준 형식
- APDU 명령 : NFC 태그와 통신할 때 사용하는 명령어 형식. ISO 14443-4 (IsoDep) 태그에서 쓰기 작업을 할 때 사용.
# APDU 응답 예시
63 00 (쓰기 실패)
90 00 (쓰기 성공)
전체 데이터를 읽어오는 코드를 작성해보았다.
데이터를 전체를 반환하니까 내가 앱에서 작성했던 apple 텍스트가 적힌 것을 확인할 수 있다.
그래서 데이터에 저장된 텍스트 데이터 중 내가 필요한 데이터인 apple만 정제하는 코드를 작성했다.
import smartcard.System
from smartcard.util import toHexString
def extract_ndef_text():
"""NDEF 텍스트 데이터 추출"""
readers = smartcard.System.readers()
if not readers:
print(" NFC 리더기를 찾을 수 없습니다.")
return
reader = readers[0]
connection = reader.createConnection()
connection.connect()
print("NFC 태그에서 NDEF 텍스트 데이터 추출...")
# NFC 태그에서 데이터 읽기 (일반적으로 블록 4~16에 저장됨)
ndef_data = []
for block in range(4, 16):
read_command = [0xFF, 0xB0, 0x00, block, 4]
response, sw1, sw2 = connection.transmit(read_command)
if sw1 == 0x90:
ndef_data.extend(response)
else:
print(f" 블록 {block} 읽기 실패: {sw1:02X} {sw2:02X}")
break
print("\nNFC 태그의 NDEF 데이터 (HEX 출력):")
print(toHexString(ndef_data))
# NDEF 텍스트 레코드 찾기
try:
start_index = ndef_data.index(0xD1) # NDEF 텍스트 시작 위치
if ndef_data[start_index + 3] != 0x54: # 'T' (텍스트 데이터)가 있는지 확인
print(" 올바른 NDEF 텍스트 데이터가 아닙니다.")
return
text_length = ndef_data[start_index + 2] - 3 # 데이터 길이 추출
language_length = ndef_data[start_index + 4] # 언어 코드 길이
text_data = ''.join(chr(b) for b in ndef_data[start_index + 5 + language_length: start_index + 5 + language_length + text_length])
print("\nNFC 태그에 저장된 텍스트 데이터:")
print(text_data)
except ValueError:
print(" NDEF 텍스트 레코드를 찾을 수 없습니다.")
if __name__ == "__main__":
extract_ndef_text()
사과! :apple:
.
.
.
문제가 있다. 어떻게 해도 nfc칩의 쓰기기능의 잠김 상태가 해제되지 않는다는 것이다.
초기화도 해보고, 무효도 시켜봤지만 핸드폰 앱으로는 쓰기가 가능하지만 컴퓨터로는 불가능하다.
그럼 여기서 할 수 있는 방법이 있다.
1. DB에 nfc태그의 UID와 원하는 텍스트를 함께 담고 태그를 할 때 UID값으로 텍스트를 불러오기
2. 휴대폰 앱으로 칩에 미리 텍스트를 써두고 컴퓨터에서 칩을 인식시킬 때 텍스트 데이터만 받아오기
어떻게 저떻게 열심히 코드를 써보니 드디어 안에 텍스트를 적을 수 있고 변경할 수 있게 되었다.
Nfc 내에 텍스트 쓰기
import smartcard.System
from smartcard.util import toHexString
def write_ndef_text():
"""텍스트 데이터를 기록"""
readers = smartcard.System.readers()
if not readers:
print("NFC 리더기를 찾을 수 없습니다.")
return
reader = readers[0]
connection = reader.createConnection()
connection.connect()
new_text = "sumin" # 저장할 텍스트 데이터
print(f"NFC 태그에 새로운 데이터 '{new_text}' 쓰기 시작...")
# NDEF 메시지 생성 (UTF-8 텍스트 레코드)
text_bytes = new_text.encode("utf-8")
lang_bytes = "en".encode("utf-8") # 언어 코드 (영어)
text_length = len(text_bytes)
lang_length = len(lang_bytes)
# NDEF 텍스트 레코드 포맷 (4바이트 패딩 추가)
ndef_message = [0xD1, 0x01, text_length + lang_length + 1, 0x54, lang_length] + list(lang_bytes) + list(text_bytes) + [0xFE]
# 4바이트 단위로 정렬 (패딩 추가)
while len(ndef_message) % 4 != 0:
ndef_message.append(0x00) # 빈 데이터 추가하여 정렬
print("작성할 NDEF 데이터 (HEX 출력):")
print(toHexString(ndef_message))
# APDU 명령을 사용하여 블록 단위로 쓰기
for i in range(0, len(ndef_message), 4):
block = [0xFF, 0xD6, 0x00, 4 + i // 4, len(ndef_message[i:i+4])] + ndef_message[i:i+4]
response, sw1, sw2 = connection.transmit(block)
if sw1 != 0x90:
print(f"쓰기 실패 (블록 {4 + i // 4}): {sw1:02X} {sw2:02X}")
return
print("NFC 태그에 'sumin' 텍스트 데이터가 성공적으로 저장되었습니다!")
if __name__ == "__main__":
write_ndef_text()
sumin은 팀원 친구 이름인데 성공의 기쁨을 sumin에게 돌리겠다.
일단 읽기/쓰기가 되어 매우 기쁘다.
앞으로의 과업
1. 읽기 할 때 카드를 인식시킬 때까지 대기시간 주기
2. 가져온 텍스트 데이터로 db내의 이미지 띄우기와 연동시키기
여튼 나처럼 돈을 아끼겠다고 알리에서 nfc리더기를 구매하신 분이라면,, 참고하시길 바라며,,, 그게 아니여도 참고하시고,,
'공통 프로젝트' 카테고리의 다른 글
[공통 프로젝트] JWT를 사용해보자 (0) | 2025.03.02 |
---|---|
[공통 프로젝트] DB 설계, 필수 체크 리스트! (0) | 2025.01.23 |
[공통 프로젝트] Jira 사용하기 (0) | 2025.01.13 |
[공통 프로젝트]도커/쿠버네티스 실전 활용하기 (0) | 2025.01.09 |
[공통 프로젝트] 아이디어 해커톤 (1) | 2025.01.09 |