Today
-
Yesterday
-
Total
-
  • ์Šค๋งˆํŠธ ์นดํŠธ ์„ค๊ณ„๊ธฐ (3) - ๊ธฐ๋Šฅ ํ•ฉ์น˜๊ธฐ, NFC ์ฝ”๋”ฉ์˜ ์‹œ์ž‘
    Soliloquy 2020. 12. 25. 00:02

    ๐Ÿ”จ

     

    ๋„ค๋น„๊ฒŒ์ด์…˜ ๊ธฐ๋Šฅ๊ณผ์˜ ์œตํ•ฉ

    ํ•œ ํ•™๊ธฐ์˜ ์ ˆ๋ฐ˜์ด ์ง€๋‚ฌ์„ ๋•Œ์ฏค, ํ„ฐํ‹€๋ด‡3์˜ ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ถ€๋ถ„์„ ๋งก์€ ์นœ๊ตฌ๊ฐ€ ์›ํ•˜๋Š” ์ขŒํ‘œ๊นŒ์ง€ ์›€์ง์ด๋Š” ๋„ค๋น„๊ฒŒ์ด์…˜ ๊ธฐ๋Šฅ์„ ๊ฑฐ์˜ ๋‹ค ์™„์„ฑํ–ˆ๋‹ค๋Š” ๋ง์„ ํ•˜์˜€๋‹ค. ์ฃผ์ œ ์„ ์ •์ด ๋น ๋ฅด๊ธฐ๋„ ํ•˜๊ณ  ๊ฐ์ž๊ฐ€ ๋‚˜๋ฆ„๋Œ€๋กœ ์ƒ๊ฐ์ด ์žˆ์—ˆ๋˜ ๋ถ„์•ผ์—ฌ์„œ ๊ทธ๋Ÿฐ์ง€ ๋‹ค๋ฅธ ์กธ์—… ์ž‘ํ’ˆ ์„ค๊ณ„ ํŒ€๋“ค๋ณด๋‹ค ์™„์„ฑ ์†๋„๊ฐ€ ์—„์ฒญ ๋นจ๋ž๋‹ค.

     

    ์•„์‰ฝ๊ฒŒ๋„ ๋„ค๋น„๊ฒŒ์ด์…˜ ๊ธฐ๋Šฅ์€ ์ƒ๊ฐ๋ณด๋‹ค ๊ณ ๋ คํ•ด์•ผ ํ•  ๋ถ€๋ถ„๋“ค์ด ๋„ˆ๋ฌด๋‚˜ ๋งŽ์•˜๊ธฐ ๋•Œ๋ฌธ์—, ์นœ๊ตฌ๊ฐ€ ๊ฐ€์ ธ์˜จ ์ฝ”๋“œ๋Š” ๋ฐ”๋‹ฅ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ์ง  ์ฝ”๋“œ๋Š” ์•„๋‹ˆ์—ˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ผ๋‹จ ๊ฐ€์žฅ ํฐ ๊ฑธ๋ฆผ๋Œ์ด์—ˆ๋˜ ๋„ค๋น„๊ฒŒ์ด์…˜ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋œ ๊ฒƒ๋งŒ์œผ๋กœ๋„ ์ •๋ง ๋‹คํ–‰์ด์—ˆ๋‹ค.


    ์นœ๊ตฌ๊ฐ€ ๊ฐ€์ง„ ์ฝ”๋“œ๋Š” Python ํŒŒ์ผ๋กœ turtlebot3_navigation์ด๋ผ๋Š” ROS ํŒจํ‚ค์ง€์— ์ขŒํ‘œ๋ฅผ ๋ณด๋‚ด ์ด๋™ํ•˜๋Š” ๊ตฌ์กฐ์˜€๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์ƒ๊ฐํ–ˆ์„ ๋•Œ ๊ฐ์ž์˜ ์ฝ”๋“œ๋ฅผ ์—ฐ๋™ํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ์‹์€ ์›น์„œ๋ฒ„ ์†Œ์Šค ํŒŒ์ผ์—์„œ ๋„ค๋น„๊ฒŒ์ด์…˜ ๊ธฐ๋Šฅ ์†Œ์Šค๋ฅผ ๋ชจ๋“ˆ์ฒ˜๋Ÿผ import๋กœ ๋ถˆ๋Ÿฌ์™€์„œ ์›น์„œ๋ฒ„ ์ฝ”๋“œ ๋‚ด์—์„œ ์ง์ ‘ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ์‹์ด์—ˆ๋‹ค.

     

    ํ•˜์ง€๋งŒ Python์— ๊ด€ํ•œ ์ง€์‹ ๋ถ€์กฑ์œผ๋กœ ์ธํ•ด ๋ชจ๋“ˆ ํ˜•์‹์œผ๋กœ import๋ฅผ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ๋‹น์‹œ์— ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ด์ „๊นŒ์ง€ ์•Œ๊ณ  ์žˆ์—ˆ๋˜ ๋ฐฉ์‹์„ ์‘์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

     

    ์šฐ๋ฆฌ๊ฐ€ ์ƒ๊ฐํ•œ ๋ฐฉ์‹์€ ์‹คํ–‰ ์‹œ ์‰˜๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค๊ณ  Flask ๋‚ด์—์„œ ํ•ด๋‹น ํŒŒ์ผ์„ Python์„ ์ด์šฉํ•˜์—ฌ ๋ณ„๋„์˜ ์‰˜๋กœ ์‹คํ–‰์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์ด์—ˆ๋‹ค. ์ผ๋‹จ์€ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๊ณ  ๋‚˜์ค‘์— ์‹œ๊ฐ„์ด ๋‚จ๋Š”๋‹ค๋ฉด ๋ชจ๋“ˆ์ฒ˜๋Ÿผ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹์„ ๊ณต๋ถ€ํ•œ ๋’ค์— ๋ฐ”๊พธ๊ธฐ๋กœ ํ–ˆ๋‹ค.


    ์นœ๊ตฌ์—๊ฒŒ ๊ทธ ์ฝ”๋“œ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ขŒํ‘œ ๊ฐ’์„ ๋ฐ›์•„์„œ ๋™์ž‘ํ•˜๋„๋ก ์ˆ˜์ •์„ ๋ถ€ํƒํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜๋Š” ๋ฌผํ’ˆ ์ƒ์„ธ ํŽ˜์ด์ง€์—์„œ ๋ฌผํ’ˆ ์ถ”์  ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด Python์˜ subprocess ๋ชจ๋“ˆ์„ ์ด์šฉํ•ด์„œ ์‰˜์—์„œ ํŒŒ์ด์ฌ ํŒŒ์ผ์„ ์‹คํ–‰์‹œํ‚ค๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ž‘๋™์‹œํ‚ค๋Š” ๋ฐ ์„ฑ๊ณตํ–ˆ๋‹ค.

     

    def send2ros(tablequery):
        print('x: ',tablequery.locationx,'y: ', tablequery.locationy,'z: ',  tablequery.locationz )
        subpro = subprocess.Popen(["python", "go_to_specific_point_on_map.py", str(tablequery.locationx), str(tablequery.locationy) ])
    

    ์œ„์น˜ ์ด๋™ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ ธ์„ ๋•Œ ์‹คํ–‰ํ•˜๋Š” ํ•จ์ˆ˜

     

    ๋„ค๋น„๊ฒŒ์ด์…˜ ๊ธฐ๋Šฅ ์ž‘๋™ ๋™์˜์ƒ

     

    NFC ๋ชจ๋“ˆ ์‚ฌ์šฉ๊ธฐ

    ์›น ํŽ˜์ด์ง€๋ฅผ ์–ด๋Š ์ •๋„ ๋งˆ๋ฌด๋ฆฌํ•˜๊ณ  ๋‚œ ๋’ค NFC ๋ชจ๋“ˆ์„ ์ž‘์—…ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. [๊ฐ์ฃผ:1]

     

    ๋งŒ๋“ค์–ด์ง„ ํ”„๋กœ๊ทธ๋žจ๋“ค ๋ชจ๋‘ Python์œผ๋กœ ์“ฐ์˜€์œผ๋‹ˆ, NFC ๋ชจ๋“ˆ ๊ตฌ๋™ ๋ฐฉ์‹๋„ Python์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ์ฝ”๋“œ ์›น์„œ๋ฒ„์™€ ์—ฐ๋™ํ•˜๊ธฐ์— ์ข€ ๋” ์œ ๋ฆฌํ•˜์ง€ ์•Š์„๊นŒ?๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์—ฌ๋Ÿฌ NFC ์ž‘๋™ ํ”„๋กœ๊ทธ๋žจ์„ ์ฐพ์•„๋ณด๋‹ค๊ฐ€, nfcpy๋ผ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ๋ˆˆ์— ๋„์—ˆ๋‹ค.

     

    nfcpy์˜ ์‚ฌ์šฉ

    nfcpy๋Š” USB๋‚˜ UART๋ฅผ ์ด์šฉํ•˜์—ฌ ์ž‘๋™ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ, ํ”„๋กœ๊ทธ๋žจ ์‚ฌ์šฉ ์„ค๋ช…์— ๊ด€ํ•œ ๋ฌธ์„œ์™€ ์˜ˆ์ œํ”„๋กœ๊ทธ๋žจ๋“ค์ด ๋งŽ์•„์„œ ์ข‹์•˜๋‹ค.


    ์‹œํ—˜ ์‚ผ์•„ ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์— GPIO๋ฅผ ์ด์šฉํ•˜์—ฌ ์—ฐ๊ฒฐ, ์˜ˆ์ œ ํ”„๋กœ๊ทธ๋žจ์„ ์ด์šฉํ•˜์—ฌ NFC ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•ด๋ณด์•˜๋‹ค. ๋‹คํ–‰ํžˆ ๋ณ„๋„์˜ ๋ณด์กฐ์ „์› ์—†์ด NFC ๋ชจ๋“ˆ์€ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•จ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

     

    ๋‹น์‹œ ํ…Œ์ŠคํŠธ ํ–ˆ์—ˆ๋˜ ์‚ฌ์ง„๋“ค ์ค‘ ์ผ๋ถ€ (์ด ๋•Œ๋Š” ํ„ฐํ‹€๋ด‡3์˜ ์ „์›์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๋‹ค.)


    ์ด์ œ ์ž‘๋™์— ์ด์ƒ์ด ์—†์Œ์„ ํ™•์ธ์„ ํ•˜๊ณ , nfcpy๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ฐ€์žฅ ๋ณต์žกํ•œ ๋ฐฉ๋ฒ•์ธ NFC ํƒœ๊ทธ๋ฅผ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘๋™์‹œ์ผœ๋ณด๋ ค๊ณ  ํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ ์•ˆํƒ€๊น๊ฒŒ๋„ nfcpy ๋ฌธ์„œ์— ๊ธฐ๋ก๋œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์ฝ”๋“œ๋ฅผ ์ž˜ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฐ”๋žŒ์— ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘์‹œํ‚ฌ ์ˆ˜ ์—†์—ˆ๋‹ค. ๋‹ค๋ฅธ ๋Œ€์•ˆ์œผ๋กœ ์˜ˆ์ œ์— ์ ํžŒ SNEP ํ”„๋กœํ† ์ฝœ์„ ์ด์šฉํ•ด ๋ณด๊ธฐ๋„ ํ–ˆ๋‹ค.


    ํ•ด๋‹น ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๋ฉด NFC ํƒœ๊ทธ๊ฐ€ ์ฝํ˜”๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์„œ ๋ณด์•ˆ ๋ฉด์—์„œ๋„ ์ƒ๋‹นํžˆ ์œ ์šฉํ•˜๋‹ค ์‹ถ์—ˆ๋Š”๋ฐ, ํœด๋Œ€ํฐ ๊ธฐ์ข…์— ๋”ฐ๋ผ ์ž‘๋™์ด ์™„๋ฒฝํžˆ ๋˜์ง€ ์•Š๋Š” ํ˜ธํ™˜์„ฑ์— ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค.[๊ฐ์ฃผ:2][๊ฐ์ฃผ:3] ํ•˜๋Š” ์ˆ˜ ์—†์ด NFC ํƒœ๊ทธ ์—๋ฎฌ๋ ˆ์ด์…˜, SNEP ํ”„๋กœํ† ์ฝœ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์€ ํฌ๊ธฐํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค. ๋Œ€์‹  NFC ์Šคํ‹ฐ์ปค์™€ ๊ฐ™์€ NFC ํƒœ๊ทธ๋ฅผ NFC ๋ชจ๋“ˆ์— ๋ณ„๋„๋กœ ๋ถ™์—ฌ์„œ NFC ๋ชจ๋“ˆ –> NFC ํƒœ๊ทธ –> ์Šค๋งˆํŠธํฐ ์‹์œผ๋กœ ์—ฐ๋™์„ ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

     

    ์ƒ๊ฐํ•œ ๋ฐฉ๋ฒ•๋Œ€๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด nfcpy ์„ค๋ช…์„œ๋ฅผ ์ฐพ์•„๋ณด๋‹ค๊ฐ€ ์˜ˆ์ œ ํŒŒ์ผ๋“ค์— ๊ด€ํ•œ ์„ค๋ช…์„ ๋ณผ ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์˜ˆ์ œ ํŒŒ์ผ ์ค‘ ๋‚˜์—๊ฒŒ ํ•„์š”ํ•œ ํŒŒ์ผ์€ tagtool.py ํŒŒ์ผ๋กœ, tagtool.py format tt2 ๋ฅผ ์‹คํ–‰ํ•œ ๋‹ค์Œ tagtool.py load ‘ndef ํŒŒ์ผ ๊ฒฝ๋กœ’๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ๋„ค๋น„๊ฒŒ์ด์…˜ ๊ธฐ๋Šฅ์„ ์›น์„œ๋ฒ„ ๊ธฐ๋Šฅ๊ณผ ํ•ฉ์น  ๋•Œ์ฒ˜๋Ÿผ, ๊ฐ„๋‹จํžˆ subprocess๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ตฌํ˜„์„ ํ•จ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ๊ฐ„๋‹จํžˆ ์œตํ•ฉํ•˜์˜€๋‹ค. ์ฐธ๊ณ ๋กœ ndef ํŒŒ์ผ์—๋Š” ์•”ํ˜ธ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋œ Flask ์„œ๋ฒ„ URL์ด ์ ํ˜€ ์žˆ๋‹ค.


    ๋‹จ, ์—ฌ๊ธฐ์„œ ํ•„์š”ํ•œ ํŒŒ์ผ์ธ ndef ํŒŒ์ผ์€ ์–ด๋–ป๊ฒŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ด์‹ฌํžˆ ์ฐพ๋‹ค๊ฐ€, ndeftool์ด๋ผ๋Š” ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์ฐพ์•˜๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ndeftool๋กœ ๋งŒ๋“ค์–ด์ง„ ํŒŒ์ผ์€ ์–ด๋–ป๊ฒŒ ๋ณด๋‚ด๊ณ  ๋ฐ›์„ ์ˆ˜ ์žˆ์„๊นŒ? ๋ผ๋Š” ๊ณ ๋ฏผ ๋์— ํ•˜๋‹ค๊ฐ€ ์•„๋ž˜์™€ ๊ฐ™์€ ๊ตฌ์ƒ์„ ํ•˜์˜€๋‹ค.

     

    1. Flask ์„œ๋ฒ„๊ฐ€ ๋กœ๊ทธ ์•„์›ƒ์ด๋‚˜ ์ดˆ๊ธฐ ์‹คํ–‰ ์‹œ ๋น„๋ฐ€ ๋ฒˆํ˜ธ๋ฅผ ํฌํ•จํ•˜์—ฌ ์‚ฌ์ดํŠธ ์ฃผ์†Œ๊ฐ€ ๋‹ด๊ธด ndefํŒŒ์ผ์„ ๋งŒ๋“ ๋‹ค. (์ฃผ์†Œ ์˜ˆ์‹œ: https://***.ipdisk.co.kr/?passcode=1234)
    2. Tcp/Ip๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์— a๋ผ๋Š” ๋ฌธ์ž๋ฅผ ๋ณด๋‚ด๋ฉด ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด๋Š” Flask ์„œ๋ฒ„์˜ ์ˆจ๊ฒจ์ง„ ๊ฒฝ๋กœ์—์„œ ndef ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œํ•œ๋‹ค.
    3. ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด๋Š” ๋‹ค์šด๋กœ๋“œ๋œ ndef ํŒŒ์ผ์„ ์ด์šฉํ•˜์—ฌ nfc ํƒœ๊ทธ์— ํ•ด๋‹น URL์„ ๊ธฐ๋กํ•œ๋‹ค.
    4. ์‚ฌ์šฉ์ž๋Š” ํœด๋Œ€ํฐ์œผ๋กœ ํ•ด๋‹น ํƒœ๊ทธ๋ฅผ ํƒœ๊น…ํ•˜์—ฌ ์›น ์„œ๋น„์Šค์— ์ ‘์†ํ•œ๋‹ค.

     

    ์ด๋ ‡๊ฒŒ ํ•œ๋‹ค๋ฉด https๋ฅผ ํ†ตํ•ด ํŒŒ์ผ์ด ์•”ํ˜ธํ™”๋˜์–ด ์ „์†ก๋˜๋ฏ€๋กœ ์ œ 3์ž๋Š” ์•”ํ˜ธ ์ฝ”๋“œ๋ฅผ ๊ฐ€๋กœ์ฑŒ ์ˆ˜ ์—†์—ˆ์œผ๋ฉฐ, ๋”ฐ๋ผ์„œ ๋ณด์•ˆ์ƒ ์œ ๋ฆฌํ•  ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ํ† ๋Œ€๋กœ  ndef ํŒŒ์ผ ์ „์†ก ๊ตฌํ˜„์— ์„ฑ๊ณตํ–ˆ์œผ๋ฉฐ, ๋™์ž‘๋„ ์ •์ƒ์ ์ž„์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

     

    context = ssl._create_unverified_context()
    def get_ndef(): ##url
        ndefdata = request.urlopen(url,context=context).read()
    with open('./urlreceived.ndef', 'wb') as f:
            f.write(ndefdata)
    if data.decode('utf-8') == 'a' :
                get_ndef()
                subpro1 = subprocess.Popen(['python', 'tagtool.py', '--device', '/dev/ttyS0', 'format', 'tt2'])
                print('subpro1 ended')
                subpro2 = subprocess.Popen(['python', 'tagtool.py', 'load', 'urlreceived.ndef'])
                print('subpro2 ended')
    

    ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์—์„œ ์‚ฌ์šฉ๋˜๋Š” Subprocess์™€ tagtool.py๋ฅผ ์‚ฌ์šฉํ•œ ์ฝ”๋“œ

     

    @app.route('/url.ndef', methods=['GET'])
    def urlndef():
    
        if request.args.get('passcode', "pass") == ndefpasskey :
            return send_from_directory(app.static_folder, request.path[1:])
        else :
            flash('Wrong url download code')
            return redirect ('/')
            
            
    def nfcdatacreate(secretword) : #On windows, pip install python-magic-bin==0.4.14
        subpro = subprocess.Popen(["ndeftool","uri",
    "https://***.ipdisk.co.kr?passcode=" + str(secretword),
    "save","--force",
    "./static/url.ndef"],
    close_fds=True)
        time.sleep(0.5) #nfcํŒŒ์ผ์ด ์ƒ๊ธธ ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์‹œ๊ฐ„

    Flask ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ฝ”๋“œ

     

    NFC Tools ์•ฑ์œผ๋กœ ๋ณธ NFC ํƒœ๊ทธ์˜ ์ƒํƒœ

     

    ์ƒ๊ฐ์ง€ ๋ชปํ•œ ๋ฌธ์ œ

    ์ž‘๋™์ด ์ž˜ ๋  ๋•Œ๋„ ์žˆ์ง€๋งŒ, ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ„ํ˜น NFC ๋ชจ๋“ˆ์„ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๋ฉด์„œ ์ž‘๋™์— ์‹คํŒจํ•˜๋Š” ๊ฒฝ์šฐ๋„ ๊ฐ€๋”์”ฉ ์žˆ์—ˆ๋‹ค. ๋‚ด๊ฐ€ ๊ฒช์€ ์ž‘๋™ ์‹คํŒจ ์ƒํ™ฉ์€ ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€ ์ƒํ™ฉ์œผ๋กœ ๋‚˜๋ˆ„์–ด์กŒ๋Š”๋ฐ, ์ฒซ ๋ฒˆ์งธ ์ƒํ™ฉ์€ ๋ถ€ํŒ… ํ›„ ์ฒ˜์Œ NFC๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ๊ทธ๋ฆฌ๊ณ  ๋‘ ๋ฒˆ์งธ ์ƒํ™ฉ์€ ์‹œ๊ฐ„์— ๊ด€๊ณ„์—†์ด ๋ฌด์ž‘์œ„๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒฝ์šฐ์˜€๋‹ค.

     

    [nfc.clf] searching for reader on path tty:S0
    [nfc.clf] searching for reader on path tty:S0
    [nfc.clf] using PN532v1.6 at /dev/ttyS0
    ** waiting for a tag **
    [nfc.clf.pn532] input/output error while waiting for ack
    [nfc.clf] [Errno 5] Input/output error
    [nfc.clf.pn532] input/output error while waiting for ack
    [nfc.clf] no reader available on path tty:S0
    [main] no contactless reader found on tty:S0
    [main] no contactless reader available

    NFC ๋ชจ๋“ˆ ์ฝ๊ธฐ์— ์‹คํŒจํ•œ ๋ฉ”์‹œ์ง€

     

    ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋Š” ์ด์œ ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ํ˜น์‹œ๋‚˜ subprocess.Popen๋ฅผ ์ด์šฉํ•œ tagtool.py์ด ๊ฑฐ์˜ ๋™์‹œ์— 2๋ฒˆ ์‚ฌ์šฉ๋˜์–ด ์ฝ๊ธฐ์ƒ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ธ๊ฐ€?๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด, ๋™์‹œ ์‹คํ–‰์ด ๋˜์ง€ ์•Š๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์€๋ฐ… ๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด์„œ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€, time.sleep(0.5) ๋กœ ๋™์‹œ ์‹คํ–‰์„ ๋ฐฉ์ง€ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

     

    subpro1 = subprocess.Popen(['python3', './tagtool.py', '--device', 'tty:S0', 'format', 'tt2'])
    time.sleep(0.5)
    subpro2 = subprocess.Popen(['python3', './tagtool.py', 'load', 'urlreceived.ndef'])

    ๊ฐ„๋‹จํžˆ time.sleep๋งŒ ์ถ”๊ฐ€ํ•œ ์ฝ”๋“œ

     

    ์ˆ˜์ •๋œ ์ฝ”๋“œ๋กœ ์‹คํ—˜์„ ํ•ด ๋ณธ ๊ฒฐ๊ณผ, ๋ฌด์ž‘์œ„๋กœ ๋‚˜ํƒ€๋‚˜๋Š” ์ธ์‹ ๋ถˆ๋Ÿ‰ ๋ฌธ์ œ์—๋Š” ํšจ๊ณผ๊ฐ€ ์กฐ๊ธˆ ์žˆ๋Š” ๋“ฏํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ, ๋ถ€ํŒ… ์งํ›„์— NFC ๋ชจ๋“ˆ์ด ์ธ์‹์ด ์•ˆ ๋˜๋Š” ํ˜„์ƒ์€ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†์—ˆ๋‹ค.

     

    ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค๋ฅธ ํ•ด๊ฒฐ์ฑ…์ด ํ•„์š”ํ•ด ๋ณด์˜€๋‹ค.

     

    NFC ๋ชจ๋“ˆ ์ธ์‹ ์‹คํŒจ์œจ์„ ์ค„์ด๊ธฐ ์œ„ํ•œ ์‹œ๋„

    ์ธ์‹ ์‹คํŒจ์œจ์„ ์ค„์ด๊ธฐ ์œ„ํ•ด ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ์•ˆ์„ ์ƒ๊ฐํ–ˆ๋‹ค.

    1. NFC ๋ชจ๋“ˆ์˜ ๊ต์ฒด
      - NFC ๋ชจ๋“ˆ์˜ ๋ถˆ๋Ÿ‰์ด๊ฑฐ๋‚˜ NFC๋ฅผใ„น ๋„ˆ๋ฌด ๋งŽ์ด ์‚ฌ์šฉํ•ด์„œ NFC ๋ชจ๋“ˆ์ด ๊ณ ์žฅ์ด ๋‚ฌ์„ ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์ƒ๊ฐ์ด์—ˆ๋‹ค.

    2. ๋ธ”๋ฃจํˆฌ์Šค ๊ธฐ๋Šฅ ๋„๊ธฐ
      - ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด3์—๋Š” ๋ธ”๋ฃจํˆฌ์Šค์™€ UART๋ฅผ ๋™์‹œ์— ์‚ฌ์šฉ ์ค‘์ด๋ฏ€๋กœ ํ˜ผ์„ ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ธ”๋ฃจํˆฌ์Šค ๋ชจ๋“ˆ์„ ๊บผ๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์€ ์‹œ๋„์ผ ๊ฒƒ ๊ฐ™์•˜๋‹ค.

    3. ๋ชจ๋“ˆ ํ†ต์‹  ๋ฐฉ์‹์˜ ์ˆ˜์ •
      - ๋‹ค๋ฅธ ํ†ต์‹  ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ์ข€ ๋” ๋‚˜์•„์ง€์ง€ ์•Š์„๊นŒ?

    4. NFC ์ž‘๋™ ๋ฐฉ์‹์˜ ์ˆ˜์ •
      - nfcpy๋ฅผ ์ด์šฉํ•˜๋Š” Tagtool.py์™€ subprocess๋กœ ์ธํ•œ ๋ฒ„๊ทธ์˜ ๋ฐœ์ƒ์ผ ๊ฒƒ์ด๋‹ค. Tagtool.py์™€ subprocess ์‚ฌ์šฉ์„ ํ•˜์ง€ ์•Š๊ณ , nfcpy๋งŒ ์ด์šฉํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ํ•ด๊ฒฐ๋  ์ˆ˜๋„ ์žˆ๋‹ค.

     

    ์šฐ์„  ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ์•ˆ์ธ NFC ๋ชจ๋“ˆ์˜ ๊ต์ฒด๋ฅผ ๋จผ์ € ํ•ด๋ณด์•˜๋‹ค. ํ•˜์ง€๋งŒ ์•ˆํƒ€๊น๊ฒŒ ๊ต์ฒด ํ›„์—๋„ ๋ฌธ์ œ๋Š” ํ•ด๊ฒฐ๋˜์ง€ ์•Š์•˜๋‹ค.

     

    ๋‘ ๋ฒˆ์งธ ๋ฐฉ์•ˆ์œผ๋กœ ๋ธ”๋ฃจํˆฌ์Šค ๋ชจ๋“ˆ์„ ๋„๊ณ  NFC ๋ชจ๋“ˆ ์ฝ๊ธฐ๋ฅผ ์‹œ๋„ํ•˜์˜€๋‹ค. ์ด๋•Œ ๋‚ด ์‹ค์ˆ˜์ธ์ง€๋Š” ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ, ๋ธ”๋ฃจํˆฌ์Šค๋ฅผ ๊บผ๋ฒ„๋ฆฌ๋‹ˆ ๊ธฐ์กด์— ttyS0๋กœ ์ž‘๋™ํ–ˆ๋˜ ์ฝ”๋“œ๊ฐ€ ์ž‘๋™์„ ์•„์˜ˆ ํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ๋” ๋ถˆ์•ˆ์ •ํ•˜๊ฒŒ ์ž‘๋™ํ–ˆ๋‹ค. ๋ธ”๋ฃจํˆฌ์Šค๋ฅผ ๋„๋Š” ๋ฐฉ๋ฒ•๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๋ฐฉ๋ฒ•์ธ ๊ฒƒ ๊ฐ™์•˜๋‹ค.

     

    ๊ทธ๋ž˜์„œ ๋Œ€์‹  ์„ธ ๋ฒˆ์งธ ๋ฐฉ์•ˆ์ธ ๋‹ค๋ฅธ ํ†ต์‹  ๋ฐฉ๋ฒ•์„ ์‹œ๋„ํ•˜๋ ค๊ณ  ํ–ˆ์œผ๋‚˜, nfcpy๋Š” ๋‹ค๋ฅธ ํ†ต์‹  ๋ฐฉ๋ฒ•์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๋“ฏํ–ˆ๋‹ค.[๊ฐ์ฃผ:4] nfcpy๋ฅผ ํฌ๊ธฐํ•˜๊ณ  ๋‹ค๋ฅธ ๋ชจ๋“ˆ์ด๋‚˜ ํ”„๋กœ๊ทธ๋žจ๋“ค์„ ์ฐพ๋Š” ๊ฒŒ ๋‚˜์„์ง€ ๊ณ ๋ฏผํ–ˆ์ง€๋งŒ, ์•„๋ฌด๋ž˜๋„ ๋„ค ๋ฒˆ์งธ ๋ฐฉ์•ˆ์ด ๋‚จ์•„ ์žˆ์œผ๋‹ˆ, ๋„ค ๋ฒˆ์งธ ๋ฐฉ์•ˆ์„ ๋จผ์ € ํ•ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค.

     

    ๋งˆ์ง€๋ง‰์œผ๋กœ ์ˆ˜๋‹จ์ธ ์ž‘๋™ ๋ฐฉ์‹์˜ ์ˆ˜์ •์ด์—ˆ๋‹ค. ์ž‘๋™ ๋ฐฉ์‹์„ ์ˆ˜์ •ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ nfcpy Python ๋ชจ๋“ˆ์˜ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๊ฐ€์•ผ ํ–ˆ๋‹ค. ๋ฌธ์„œํ™”๊ฐ€ ์ž˜ ๋˜์–ด ์žˆ์–ด์„œ ์˜ˆ์ œ๋ฅผ ์ฐธ์กฐํ•˜๋ฉด์„œ ์กฐ๊ธˆ์”ฉ ๋ฐฐ์›Œ ๋‚˜๊ฐ”๋‹ค.

     

    ๊ทธ๋ฆฌ๊ณ  ์•ฝ 3์ผ ๋™์•ˆ nfcpy ํ”„๋กœ๊ทธ๋žจ์˜ ์‚ฌ์šฉ๋ฒ•์„ ์ฐธ์กฐํ•˜๋ฉฐ ์ฝ”๋“œ๋ฅผ ํ•˜๋‚˜์”ฉ ํŒŒํ—ค์ณ ๋‚˜๊ฐ”๋‹ค. [๊ฐ์ฃผ:5] ๋‚ด๊ฐ€ ์ƒˆ๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๋Š” tagtool.py๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ„๊ฒฐํ–ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ธฐ์กด์˜ ndef ํŒŒ์ผ์„ ์ฝ๋Š” ์ ˆ์ฐจ, nfc ํƒœ๊ทธ์— URL์„ ๊ธฐ๋กํ•˜๊ธฐ ์ „ nfc ํƒœ๊ทธ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ์ ˆ์ฐจ, ๊ทธ๋ฆฌ๊ณ  time.sleep ๊ตฌ๋ฌธ์ด ํ•„์š” ์—†์–ด์กŒ๋‹ค. ๋•๋ถ„์— ์ž‘๋™ ์†๋„์™€ ์•ˆ์ „์„ฑ๋„ ํ›จ์”ฌ ์ข‹์•„์กŒ๋‹ค.

     

    if data.decode('utf-8') == 'a' :
    with nfc.ContactlessFrontend('tty:S0') as clf:    
           target = clf.sense(RemoteTarget('106A'))
           tag = nfc.tag.activate(clf, target)
           record = ndef.UriRecord(get_uri())
           tag.ndef.records=[record]
    

    ๊ฐ„๊ฒฐํ•ด์ง„ NFC ํƒœ๊ทธ ์ฝ”๋“œ

     

    ๊ธฐ์กด์—๋Š” ndef ํŒŒ์ผ์„ Flask ์„œ๋ฒ„์—์„œ ๋งŒ๋“  ๋’ค ํ•ด๋‹น ndef ํŒŒ์ผ์„ ์ „์†ก๋ฐ›์•„์„œ ndef ํŒŒ์ผ์„ ์ฝ๊ณ  ํ•ด๋‹น ํŒŒ์ผ์„ NFC ํƒœ๊ทธ์— ๊ธฐ๋กํ•˜๋Š” ๋ฐฉ์‹์ด์—ˆ๋‹ค๋ฉด, ์ƒˆ๋กœ์šด ๋ฐฉ์‹์€ Flask ์„œ๋ฒ„์—์„œ ndef ํŒŒ์ผ์ด ์•„๋‹Œ ๋ฐ”๋€Œ์–ด์ง„ ์‚ฌ์ดํŠธ์˜ URL์™€ ์•”ํ˜ธ ์ฝ”๋“œ๋งŒ ๋ฐ›์•„๋„ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ์‹์ด์—ˆ๋‹ค.

     

    NFC ๋ชจ๋“ˆ ๊ตฌ๋™ ์ฝ”๋“œ์˜ ์ˆ˜์ •๊ณผ ํ•จ๊ป˜, Flask ์„œ๋ฒ„์— ์‚ฌ์šฉ๋œ ์ฝ”๋“œ๋„ ์ƒˆ๋กœ์šด ๋ฐฉ์‹์— ๋งž์ถฐ์„œ ๋ณ€๊ฒฝํ•ด์ค˜์•ผ ํ–ˆ๋‹ค. ๊ธฐ์กด์˜ ndef ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋Š” ๋ถ€๋ถ„์„ ์ œ๊ฑฐํ•˜๊ณ , ndef ํŒŒ์ผ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ ๋Œ€์‹ ์— Resoponse๋ฅผ ํ†ตํ•ด ์‚ฌ์ดํŠธ์˜ URL๊ณผ ์•”ํ˜ธ ์ฝ”๋“œ ํ…์ŠคํŠธ๋งŒ https๋กœ ์ „์†กํ•˜๋„๋ก ๋ณ€๊ฒฝํ–ˆ๋‹ค.

     

    @app.route('/url.ndef', methods=['GET'])
    def urlndef():
        if request.args.get('passcode', "pass") == ndefpasskey :
    return Response("https://beatcart.ipdisk.co.kr/?passcode=" + str(secretword), mimetype='text/plain')
        else :
            flash('Wrong url download code')
            return redirect ('/')

    ์ƒˆ๋กœ ์ž‘์„ฑ๋œ Flask ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ฝ”๋“œ

     

    ์•ˆ์ „์„ฑ ํ–ฅ์ƒ

    50๋ฒˆ์˜ ์—ฐ์†์ ์ธ NFC ์“ฐ๊ธฐ ์‹คํ—˜์„ ํ•ด๋ดค์ง€๋งŒ, NFC ๋ชจ๋“ˆ ์‚ฌ์šฉ์— ์‹คํŒจ๋ฅผ ํ•œ ์ ์€ ์—†์—ˆ๋‹ค. ํ˜น์‹œ๋‚˜ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ๊ธฐ ์‹คํŒจ์— ๋Œ€๋น„ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์— ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ NFC ๋ชจ๋“ˆ ํƒ์ง€์— ์„ฑ๊ณตํ•  ๋•Œ๊นŒ์ง€ 1์ดˆ๋งˆ๋‹ค ๋ชจ๋“ˆ์„ ๊ฒ€์ƒ‰ํ•˜๊ฒŒ ์ˆ˜์ •ํ–ˆ๋‹ค.[๊ฐ์ฃผ:6]

     

    with nfc.ContactlessFrontend('tty:S0') as clf:
                        while True:
                            target = clf.sense(RemoteTarget('106A'))        
                            if target is None:
                                sleep(1)
                                print("NFC Module Searching..")
                                continue ##Search everytime 
                            else:
                                print("Found a NFC Module")
                                break
    

    NFC ๊ฒ€์ƒ‰์„ ์ง€์†์ ์œผ๋กœ ํ•˜๋Š” ๋ฌดํ•œ ๋ฃจํ”„ ์ฝ”๋“œ

     

    ๋ฌดํ•œ ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•œ NFC ์“ฐ๊ธฐ ์ฝ”๋“œ๋ฅผ ๊ต์ˆ˜๋‹˜๊ป˜ ๋ณด์—ฌ๋“œ๋ ธ๋Š”๋ฐ, ๊ต์ˆ˜๋‹˜๊ป˜์„œ ์ด๋Ÿฐ ์‹์˜ while๋ฌธ ๋ฌดํ•œ ๋ฃจํ”„๋Š” ์ข€ ์œ„ํ—˜ํ•œ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ๋ง์„ ํ•ด ์ฃผ์…จ๋‹ค. ๊ทธ๋ž˜์„œ ์ตœ์ข…์ ์œผ๋กœ๋Š” ์ตœ์ข… ํšŸ์ˆ˜๊ฐ€ ์ •ํ•ด์ง„ for ๋ฌธ์œผ๋กœ ๊ตฌํ˜„ํ•˜์˜€๋‹ค. ์ด๋ ‡๊ฒŒ NFC ํƒœ๊ทธ ๋ชจ๋“ˆ ์ฝ”๋“œ๋ฅผ ๋์„ ๋งบ์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

     

    for i in range(30) : ##for safe coding, retry 30 times for searching a nfc module.
                        with nfc.ContactlessFrontend('tty:S0') as clf:    
                            target = clf.sense(RemoteTarget('106A'))        
                            if target is None:
                                sleep(1)
                                print("Failed to find NFC Module, retrying..")
                                continue ##Search everytime 
                            else:
                                print("Found a NFC Module")
                                tag = nfc.tag.activate(clf, target)
                                record = ndef.UriRecord(get_uri())
                                tag.ndef.records=[record]
                                print("Wrote on a tag")
                                break
                            if i == 29 :
                                print("Couldn't find nfc tag")
                                exit()
    

    ์™„์„ฑ๋œ NFC ์“ฐ๊ธฐ ์ฝ”๋“œ ์ผ๋ถ€

     

    [๋ณธ๋ฌธ ๋™์˜์ƒ ํŒŒ์ผ]

     

    smartcart_nav.mp4
    6.12MB

     

     

    1. ๋‚ด๊ฐ€ ๊ณ ๋ฅธ NFC ๋ชจ๋“ˆ์€ ITHEAD์‚ฌ์—์„œ ๋งŒ๋“ค์—ˆ์œผ๋ฉฐ PN532 ์นฉ์…‹์„ ์‚ฌ์šฉํ•˜๋ฉฐ, UART, I2C, SPI ํ†ต์‹ ์„ ์ง€์›ํ•˜์˜€๋‹ค. [๋ณธ๋ฌธ์œผ๋กœ]
    2. ์‹ค์ œ ์‚ฌ์šฉ์„ ํ•ด ๋ณธ ๊ฒฐ๊ณผ ์ด์ƒํ•˜๊ฒŒ ๊ฐค๋Ÿญ์‹œ ํœด๋Œ€ํฐ์—์„œ๋Š” ์ธ์‹์ด ๋˜์ง€ ์•Š๊ณ  LG ํœด๋Œ€ํฐ์—์„œ๋งŒ ์ž‘๋™์„ ํ•˜์˜€์œผ๋ฉฐ, ์ธํ„ฐ๋„ท์—์„œ๋Š” ์•„์ดํฐ์—์„œ๋Š” ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๋ง์„ ์ฐพ์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค. [๋ณธ๋ฌธ์œผ๋กœ]
    3. ์ฐธ๊ณ : https://github.com/nfcpy/nfcpy/issues/111 [๋ณธ๋ฌธ์œผ๋กœ]
    4. ์ถœ์ฒ˜: https://stackoverflow.com/questions/44845043/using-nfcpy-and-spi-to-connect-pn532-to-rasperry-pi#comment76672809_44845605 [๋ณธ๋ฌธ์œผ๋กœ]
    5. ์ฐธ๊ณ : https://blog.sigsec.net/posts/2019/04/reading-and-writing-nfc-tags.html [๋ณธ๋ฌธ์œผ๋กœ]
    6. ์ฐธ๊ณ : https://blog.sigsec.net/posts/2019/04/reading-and-writing-nfc-tags.html [๋ณธ๋ฌธ์œผ๋กœ]

    ๋Œ“๊ธ€

์–ด์ œ๋Š” ์ด๊ณณ์— ๋ช…์ด ๋‹ค๋…€๊ฐ”์Šต๋‹ˆ๋‹ค.

Powered & Designed by Tistory