Como Utilizar o Leitor NFC ACR122U/ACR122 no Tauri com Rust

Introdução Neste post, apresento uma solução para integrar o leitor NFC ACR122U em uma aplicação Tauri, utilizando Rust no backend para comunicação com o dispositivo. O objetivo é demonstrar como obter o UID de um cartão NFC e utilizar essa informação no React (ou qualquer framework suportado pelo Tauri). Ambiente de desenvolvimento: [windows]. Requisitos Teste realizado com as seguintes condições: Leitor NFC ACR122U Rust e Cargo Tauri CLI Configurando o Backend (Rust) Vamos criar um comando no Tauri para interagir com o leitor NFC. Dependências Adicione a dependência pcsc ao seu Cargo.toml: [dependencies] pcsc = "2.9.0" tauri = { version = "2.0", features = [] } Implementação em Rust A seguir, o código que configura a leitura do UID do cartão NFC no main.rs: // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] use pcsc::*; #[tauri::command] fn read_nfc() -> Result { // Sets the context let ctx = match Context::establish(Scope::User) { Ok(ctx) => ctx, Err(err) => return Err(format!("Error establishing context: {:?}", err)), }; // Buffer for listing readers let mut buffer = [0u8; 1024]; let readers = match ctx.list_readers(&mut buffer) { Ok(readers) => readers, Err(err) => return Err(format!("Error listing readers: {:?}", err)), }; // Converts readers into a collection for verification let reader_iter = readers.into_iter(); let reader_vec: Vec = reader_iter.collect(); // Checks for connected readers if reader_vec.is_empty() { return Err("No reader connected".to_string()); } // Search for ACR122 let reader_name = match reader_vec .iter() .find(|&&r| r.to_str().map(|s| s.contains("ACR122")).unwrap_or(false)) { Some(&reader) => reader, None => { // List available readers on error let available_readers: String = reader_vec .iter() .map(|r| r.to_str().unwrap_or("Invalid name").to_string()) .collect::() .join(", "); return Err(format!( "ACR122 reader not found. Available readers: {}", available_readers )); } }; // Connects to the reader let card = match ctx.connect(reader_name, ShareMode::Shared, Protocols::ANY) { Ok(card) => card, Err(err) => return Err(format!("Error connecting to reader: {:?}", err)), }; // Send APDU command to read UID let apdu = [0xFF, 0xCA, 0x00, 0x00, 0x00]; let mut buffer = [0u8; 256]; let response = match card.transmit(&apdu, &mut buffer) { Ok(response) => response, Err(err) => return Err(format!("Error reading tag: {:?}", err)), }; // Format UUID as hexadecimal string let uid = response[..response.len() - 2] .iter() .map(|b| format!("{:02X}", b)) .collect::(); Ok(uid) } fn main() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) .invoke_handler(tauri::generate_handler![read_nfc]) .run(tauri::generate_context!()) .expect("Erro ao executar aplicação Tauri"); } No seu Frontend (React/TypeScript) Implementação do App.tsx Crie um componente React para chamar a função do backend: import { invoke } from "@tauri-apps/api/core"; import "./App.css"; function App() { async function readNFC() { try { const uid = await invoke('read_nfc'); console.log('Card UID =>', uid); } catch (error) { console.error('Error reading NFC:', error); } } return ( Read NFC! read NFC ); } export default App; Executando a Aplicação Inicie seu ambiente: yarn tauri dev Agora, ao pressionar o botão "Ler NFC", o UID do cartão será capturado e exibido no console. Cartão Adicionado Com sucesso Caso cartão não conectado ao leitor Caso leitor não conectado Conclusão Com essa solução, conseguimos integrar um leitor NFC ACR122U em um aplicativo Tauri com Rust no backend. Essa abordagem permite que criem aplicações desktop sem executáveis externos que use outras formas dependências de comunicação entre o sistemas e o leitor. Detalhe Em meus testes meu leitor ACR122U foi reconhecido no meu Windows como ACR122 com os drivers devidos instalados por conta disso o código foi preparado para listar os leitores disponíveis, caso ainda sim não funcione como o esperado tente verificar qual nome o Windows atribuiu ao seu leitor. Se tiver alguma dúvida ou sugestão, deixe seu comentário! ✌️

Mar 28, 2025 - 18:14
 0
Como Utilizar o Leitor NFC ACR122U/ACR122 no Tauri com Rust

Introdução

Neste post, apresento uma solução para integrar o leitor NFC ACR122U em uma aplicação Tauri, utilizando Rust no backend para comunicação com o dispositivo.

O objetivo é demonstrar como obter o UID de um cartão NFC e utilizar essa informação no React (ou qualquer framework suportado pelo Tauri).

Ambiente de desenvolvimento: [windows].

Requisitos

Teste realizado com as seguintes condições:

  • Leitor NFC ACR122U
  • Rust e Cargo
  • Tauri CLI

Configurando o Backend (Rust)

Vamos criar um comando no Tauri para interagir com o leitor NFC.

Dependências

Adicione a dependência pcsc ao seu Cargo.toml:

[dependencies]
pcsc = "2.9.0"
tauri = { version = "2.0", features = [] }

Implementação em Rust

A seguir, o código que configura a leitura do UID do cartão NFC no main.rs:

// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use pcsc::*;

#[tauri::command]
fn read_nfc() -> Result {
    // Sets the context
    let ctx = match Context::establish(Scope::User) {
        Ok(ctx) => ctx,
        Err(err) => return Err(format!("Error establishing context: {:?}", err)),
    };

    // Buffer for listing readers
    let mut buffer = [0u8; 1024];
    let readers = match ctx.list_readers(&mut buffer) {
        Ok(readers) => readers,
        Err(err) => return Err(format!("Error listing readers: {:?}", err)),
    };

    // Converts readers into a collection for verification
    let reader_iter = readers.into_iter();
    let reader_vec: Vec<_> = reader_iter.collect();

    // Checks for connected readers
    if reader_vec.is_empty() {
        return Err("No reader connected".to_string());
    }

    // Search for ACR122
    let reader_name = match reader_vec
        .iter()
        .find(|&&r| r.to_str().map(|s| s.contains("ACR122")).unwrap_or(false))
    {
        Some(&reader) => reader,
        None => {
            // List available readers on error
            let available_readers: String = reader_vec
                .iter()
                .map(|r| r.to_str().unwrap_or("Invalid name").to_string())
                .collect::>()
                .join(", ");
            return Err(format!(
                "ACR122 reader not found. Available readers: {}",
                available_readers
            ));
        }
    };

    // Connects to the reader
    let card = match ctx.connect(reader_name, ShareMode::Shared, Protocols::ANY) {
        Ok(card) => card,
        Err(err) => return Err(format!("Error connecting to reader: {:?}", err)),
    };

    // Send APDU command to read UID
    let apdu = [0xFF, 0xCA, 0x00, 0x00, 0x00];
    let mut buffer = [0u8; 256];
    let response = match card.transmit(&apdu, &mut buffer) {
        Ok(response) => response,
        Err(err) => return Err(format!("Error reading tag: {:?}", err)),
    };

    // Format UUID as hexadecimal string
    let uid = response[..response.len() - 2]
        .iter()
        .map(|b| format!("{:02X}", b))
        .collect::();

    Ok(uid)
}

fn main() {
    tauri::Builder::default()
        .plugin(tauri_plugin_opener::init())
        .invoke_handler(tauri::generate_handler![read_nfc])
        .run(tauri::generate_context!())
        .expect("Erro ao executar aplicação Tauri");
}

No seu Frontend (React/TypeScript)

Implementação do App.tsx

Crie um componente React para chamar a função do backend:

import { invoke } from "@tauri-apps/api/core";
import "./App.css";

function App() {

  async function readNFC() {
    try {
      const uid = await invoke('read_nfc');
      console.log('Card UID =>', uid);
    } catch (error) {
      console.error('Error reading NFC:', error);
    }
  }

  return (
    

Read NFC!

); } export default App;

Executando a Aplicação

Inicie seu ambiente:

yarn tauri dev

Agora, ao pressionar o botão "Ler NFC", o UID do cartão será capturado e exibido no console.

Cartão Adicionado

Image description

Com sucesso

Image description

Caso cartão não conectado ao leitor

Image description

Caso leitor não conectado

Image description

Conclusão

Com essa solução, conseguimos integrar um leitor NFC ACR122U em um aplicativo Tauri com Rust no backend. Essa abordagem permite que criem aplicações desktop sem executáveis externos que use outras formas dependências de comunicação entre o sistemas e o leitor.

Detalhe

Em meus testes meu leitor ACR122U foi reconhecido no meu Windows como ACR122 com os drivers devidos instalados por conta disso o código foi preparado para listar os leitores disponíveis, caso ainda sim não funcione como o esperado tente verificar qual nome o Windows atribuiu ao seu leitor.

Se tiver alguma dúvida ou sugestão, deixe seu comentário! ✌️