Arduino 和 Android Kotlin 上带有 PN532 模块的 NFC P2P

发布于 2025-01-11 02:26:12 字数 5019 浏览 5 评论 0原文

我正在尝试使用 PN532 模块从 Android 向 Arduino 发送字符串消息。当我将智能手机(打开应用程序)靠近模块时,会显示“点击发送”UI,但在我点击屏幕后,手机会告诉我再次靠近两个设备。当我再次接近它们后(屏幕上仍然显示“再次接近设备”消息),没有任何反应,arduino 打印出“失败”。

这是 Kotlin 代码:

package com.cerowski.nfcclient

import android.nfc.NdefMessage
import android.nfc.NdefRecord
import android.nfc.NfcAdapter
import android.os.Bundle
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager.widget.ViewPager
import com.cerowski.nfcclient.databinding.ActivityMainBinding
import com.cerowski.nfcclient.ui.main.SectionsPagerAdapter
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout
import java.io.File
import java.io.UnsupportedEncodingException


class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {config(); sendid();

        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager)
        val viewPager: ViewPager = binding.viewPager
        viewPager.adapter = sectionsPagerAdapter
        val tabs: TabLayout = binding.tabs
        tabs.setupWithViewPager(viewPager)
        val fab: FloatingActionButton = binding.fab



        fab.setOnClickListener { view ->
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                .setAction("Action", null).show()
        }

    }


fun config(){
    val dir = getExternalFilesDir(null);
    val file = File(dir,"config");
    var msgtext="";
    val msg = TextView (this)

    if (dir!=null) {
        if (!file.exists()) {msgtext = "config not found, attempting to create..."; file.createNewFile(); if(file.exists()) {msgtext = "config created successfully"; file.writeText(idgenerator())} else {msgtext = "problem creating file"}}
        else {msgtext = (file.readText())}
    } else {msgtext = "app directory not found"}
}

    fun idgenerator() : String {
        val allowedChars = ('a'..'z') + ('A'..'Z') + ('0'..'9')
        return (1..16)
            .map { allowedChars.random() }
            .joinToString("")
    }

    fun sendid() {
        val dir = getExternalFilesDir(null);
        val file = File(dir,"config");
        //var bytes = file.readBytes();
        //var nfcmsg = NdefMessage(bytes);
        //var msgtext="";
        var nfcAdapter = NfcAdapter.getDefaultAdapter(this);


        if (nfcAdapter != null) {

            val msg: String = file.readText().toString()
            val languageCode: ByteArray
            val msgBytes: ByteArray
            try {
                languageCode = "en".toByteArray(charset("US-ASCII"))
                msgBytes = msg.toByteArray(charset("UTF-8"))
            } catch (e: UnsupportedEncodingException) {
                return
            }

            val messagePayload = ByteArray(
                1 + languageCode.size
                        + msgBytes.size
            )
            messagePayload[0] = 0x02.toByte() // status byte: UTF-8 encoding and

            // length of language code is 2
            // length of language code is 2
            System.arraycopy(
                languageCode, 0, messagePayload, 1,
                languageCode.size
            )
            System.arraycopy(
                msgBytes, 0, messagePayload, 1 + languageCode.size,
                msgBytes.size
            )

            val message: NdefMessage
            val records = arrayOfNulls<NdefRecord>(1)
            val textRecord = NdefRecord(
                NdefRecord.TNF_WELL_KNOWN,
                NdefRecord.RTD_TEXT, byteArrayOf(), messagePayload
            )
            records[0] = textRecord
            message = NdefMessage(records)

            nfcAdapter.setNdefPushMessage(message, this);

        }
        else {Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();}

    }
}

这是我的 Arduino Uno 与 PN532 模块的代码(红色的,如果你在线搜索照片):

// Receive a NDEF message from a Peer
// Requires SPI. Tested with Seeed Studio NFC Shield v2

#include "SPI.h"
#include "PN532_SPI.h"
#include "snep.h"
#include "NdefMessage.h"

PN532_SPI pn532spi(SPI, 10);
SNEP nfc(pn532spi);
uint8_t ndefBuf[128];

void setup() {
  Serial.begin(9600);
  Serial.println("NFC Peer to Peer Example - Receive Message");
}

void loop() {
  Serial.println("Waiting for message from Peer");
  int msgSize = nfc.read(ndefBuf, sizeof(ndefBuf));
  if (msgSize > 0) {
      NdefMessage msg  = NdefMessage(ndefBuf, msgSize);
      msg.print();
      Serial.println("\nSuccess");
  } else {
      Serial.println("Failed");
  }
  delay(3000);
}

NFC 模块上的小开关位于正确的位置,并且模块连接到板应该是这样的(对于SPI),所以我不知道是什么原因导致它失败。

非常感谢任何帮助。

I am trying to send a string message from Android to Arduino with the PN532 module. When I approach the smartphone (with the app open) to the module, the "tap to beam" UI shows up, but after I tap on the screen, the phone tells me to approach the two devices again. After I approach them again (with the "approach the devices again" message still displayed on the screen), nothing happens and arduino prints out "failed".

Here is the Kotlin code:

package com.cerowski.nfcclient

import android.nfc.NdefMessage
import android.nfc.NdefRecord
import android.nfc.NfcAdapter
import android.os.Bundle
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager.widget.ViewPager
import com.cerowski.nfcclient.databinding.ActivityMainBinding
import com.cerowski.nfcclient.ui.main.SectionsPagerAdapter
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout
import java.io.File
import java.io.UnsupportedEncodingException


class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {config(); sendid();

        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager)
        val viewPager: ViewPager = binding.viewPager
        viewPager.adapter = sectionsPagerAdapter
        val tabs: TabLayout = binding.tabs
        tabs.setupWithViewPager(viewPager)
        val fab: FloatingActionButton = binding.fab



        fab.setOnClickListener { view ->
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                .setAction("Action", null).show()
        }

    }


fun config(){
    val dir = getExternalFilesDir(null);
    val file = File(dir,"config");
    var msgtext="";
    val msg = TextView (this)

    if (dir!=null) {
        if (!file.exists()) {msgtext = "config not found, attempting to create..."; file.createNewFile(); if(file.exists()) {msgtext = "config created successfully"; file.writeText(idgenerator())} else {msgtext = "problem creating file"}}
        else {msgtext = (file.readText())}
    } else {msgtext = "app directory not found"}
}

    fun idgenerator() : String {
        val allowedChars = ('a'..'z') + ('A'..'Z') + ('0'..'9')
        return (1..16)
            .map { allowedChars.random() }
            .joinToString("")
    }

    fun sendid() {
        val dir = getExternalFilesDir(null);
        val file = File(dir,"config");
        //var bytes = file.readBytes();
        //var nfcmsg = NdefMessage(bytes);
        //var msgtext="";
        var nfcAdapter = NfcAdapter.getDefaultAdapter(this);


        if (nfcAdapter != null) {

            val msg: String = file.readText().toString()
            val languageCode: ByteArray
            val msgBytes: ByteArray
            try {
                languageCode = "en".toByteArray(charset("US-ASCII"))
                msgBytes = msg.toByteArray(charset("UTF-8"))
            } catch (e: UnsupportedEncodingException) {
                return
            }

            val messagePayload = ByteArray(
                1 + languageCode.size
                        + msgBytes.size
            )
            messagePayload[0] = 0x02.toByte() // status byte: UTF-8 encoding and

            // length of language code is 2
            // length of language code is 2
            System.arraycopy(
                languageCode, 0, messagePayload, 1,
                languageCode.size
            )
            System.arraycopy(
                msgBytes, 0, messagePayload, 1 + languageCode.size,
                msgBytes.size
            )

            val message: NdefMessage
            val records = arrayOfNulls<NdefRecord>(1)
            val textRecord = NdefRecord(
                NdefRecord.TNF_WELL_KNOWN,
                NdefRecord.RTD_TEXT, byteArrayOf(), messagePayload
            )
            records[0] = textRecord
            message = NdefMessage(records)

            nfcAdapter.setNdefPushMessage(message, this);

        }
        else {Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();}

    }
}

And here is the code for my Arduino Uno with the PN532 module (the red one, if you search for photos online):

// Receive a NDEF message from a Peer
// Requires SPI. Tested with Seeed Studio NFC Shield v2

#include "SPI.h"
#include "PN532_SPI.h"
#include "snep.h"
#include "NdefMessage.h"

PN532_SPI pn532spi(SPI, 10);
SNEP nfc(pn532spi);
uint8_t ndefBuf[128];

void setup() {
  Serial.begin(9600);
  Serial.println("NFC Peer to Peer Example - Receive Message");
}

void loop() {
  Serial.println("Waiting for message from Peer");
  int msgSize = nfc.read(ndefBuf, sizeof(ndefBuf));
  if (msgSize > 0) {
      NdefMessage msg  = NdefMessage(ndefBuf, msgSize);
      msg.print();
      Serial.println("\nSuccess");
  } else {
      Serial.println("Failed");
  }
  delay(3000);
}

The little switches on the NFC module are in the right positions and the module is connected to the board as it should be (for SPI), So I do not know what is the thing that causes it to fail.

Any help is much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我们只是彼此的过ke 2025-01-18 02:26:12

首先检查它是否 a) 可用、b) 启用以及 c) 注册和注册。实现回调。在 Java 中:

MainActivity extends AppCompatActivity implements
        NfcAdapter.CreateNdefMessageCallback,
        NfcAdapter.OnNdefPushCompleteCallback,
        NfcAdapter.CreateBeamUrisCallback {
        ...

if (
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && 
    Build.VERSION.SDK_INT < Build.VERSION_CODES.Q
) {
     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
     if (!nfcAdapter.isEnabled()) {
         startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));
     } else if (!nfcAdapter.isNdefPushEnabled()) {
         startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS));
     } else {
         nfcAdapter.setNdefPushMessageCallback(this);
         nfcAdapter.setOnNdefPushCompleteCallback(this);
         nfcAdapter.setNdefPushMessage(nfcMessage, this);
     }
}

Build.VERSION_CODES.Q 中已弃用意味着仍然可用;也许<=
这些回调还可能为您提供更多详细信息,甚至失败的原因。

否则,您将发送一条 NDEF 消息,并且它不知道下一步要做什么...

类似地,您也可能能够生成正确的错误消息。
另请参阅: https://developer.android.com/training/beam-files /发送文件

First check if it's even a) available, b) enabled and c) register & implement the callbacks. In Java:

MainActivity extends AppCompatActivity implements
        NfcAdapter.CreateNdefMessageCallback,
        NfcAdapter.OnNdefPushCompleteCallback,
        NfcAdapter.CreateBeamUrisCallback {
        ...

if (
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && 
    Build.VERSION.SDK_INT < Build.VERSION_CODES.Q
) {
     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
     if (!nfcAdapter.isEnabled()) {
         startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));
     } else if (!nfcAdapter.isNdefPushEnabled()) {
         startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS));
     } else {
         nfcAdapter.setNdefPushMessageCallback(this);
         nfcAdapter.setOnNdefPushCompleteCallback(this);
         nfcAdapter.setNdefPushMessage(nfcMessage, this);
     }
}

Deprecated in Build.VERSION_CODES.Q means still available; maybe <=.
These callbacks might also provide you with more detail, why it even fails.
Else you'll send a NDEF message and it will not know what to do next ...

Alike this you might also be able to produce a proper error message.
Also see: https://developer.android.com/training/beam-files/send-files

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文