Access VBAでNFCを使った社内アプリを作ってみる

以前、Accessで社内向けの書籍貸し出し管理用アプリを作ろうとした時、社内のOfficeが64bit版であったが為に、SheepSmartCard.dllが32bit版のみであったので、作成を断念しElectronでアプリを作成しました。

しかし、つい先日DLL作者様のページを見た所、64bit版がリリースされていました!!

Electronは開発環境の整備やNode.jsを使う為、少々敷居が高い。そこで今回手軽なVBA環境でNFCカードを使った書籍管理アプリを改めて作成してみました。NFCが使えると出退勤のタイムレコーダの作成や認証処理にも使えるので社内向けアプリでは活躍の場が広がります。

※64bit版Officeを使っているので、32bit版の場合はDLLの呼び出しと利用するDLLが異なるので注意です。

今回使用するものとライブラリ

カードリーダーとドライバー

DLLについては作者様のサイトよりダウンロードし、今回使用するAccessファイルと同じ場所に入れてください。書籍検索機能も装備しているため、利用する場合には事前準備が必要です。また、バーコードリーダですが適当なものでもISBNコード(13桁)はだいたい読めるはずなので、安いものを用意してもらえればと思います。

また、NFCのカードではなく、スマフォ搭載のNFCでも行けるかもしれません。運転免許証やマイナンバーカード等のType-Bカードは使えないので注意が必要です。SuicaやPasmoは利用可能です。会社側でカードを用意せずとも、手持ちのNFCのidm番号を登録しておいて、利用することでカードのコストをゼロに出来ますね。

※Electronとは違い、カードをかざしただけではNFC読み取りはなされません。

使用する外部サービス

事前準備と仕様

楽天ブックスAPIの準備

今回、国会図書館APIおよび楽天ブックスAPIを使っての書籍検索を装備しています。書籍登録時に国会図書館APIでまず検索し、見つからない場合には、楽天ブックスAPIで続けて検索をする仕様になっています(ただ、国会図書館APIは反応が鈍いので、検索する順番は逆の方が良いかもしれません)。

楽天ブックス書籍検索APIは、事前にアプリケーションIDの取得が必要です。ISBN検索で引っ張るようにしました。試しに使用したクエリはこちら

APIの取得手順は以下の通り。楽天IDが必要です。今回はいつものようなOAuth2認証を使わないので、APIキーのみでオッケーです。

  1. 新規アプリ登録画面へ行く
  2. アプリ名、アプリのURL(http://127.0.0.1でOK)を入力して、規約に同意して新規アプリを作成をクリック
  3. アプリのデベロッパーID等が表示されますので、この値を控えておきます。プログラムの中で使用します。
  4. コードの中の変数にアプリのデベロッパーIDを記入する(今回はこのIDのみで作成可能です)

図:アプリIDがそれになります。

参照設定

今回のAccessアプリで追加してる参照設定は以下の通り。新規で作成する場合には参照設定に追加しておきましょう。遅延バインディングで良いのであれば、1x.0 Object Library以外を参照させない方法も可能です。

  • Microsoft Office 1x.0 Object Library - 独自のリボンを使う場合に必要
  • Microsoft Scripting Runtime - FSOなどのサービスを利用するのに必要
  • Microsoft XML v6.0 - 国会図書館APIの返り値であるXMLファイルの解析に必要

図:今回は3個の設定を追加しています。

仕様

登録窓口フォームについて

貸出フォームである登録窓口フォームは、今回隠しオブジェクトになっています。また、以下のコードにより起動時に最大化されてフレームレスになっているので、画面いっぱいまでフルスクリーンになります。

'最大化表示
DoCmd.Maximize
DoCmd.RunCommand acCmdAppMinimize

隠しオブジェクトを表示する方法は以下の通りです。

  1. Accessのサイドバー上の▼の部分を右クリック
  2. ナビゲーションオプションをクリック
  3. 表示オプションの「隠しオブジェクトの表示」をチェックを入れて、OKにする
  4. 登録窓口フォームがサイドバーに表示されます

図:隠しオブジェクトは普段は非表示にしています

database.accdbについて

データを保存してるdatabase.accdbには、本体のアプリであるooteboook.accdbより起動時にリンクテーブルにて接続させています。また、このdatabase.accdbは暗号化を施しています(パスワードはhogehoge2020)。以下のコードでリンクテーブルを起動時にクリアして接続し直しています。また、このファイルは本体アプリ起動時に自動的に日付時間でバックアップファイルが5世代で作成されます。

'リンクテーブルを削除する
Function deleteLink() As Boolean
On Error Resume Next
    Dim mdb As DAO.Database
    Dim tdf As DAO.TableDef

    Set mdb = CurrentDb
    
    DoCmd.DeleteObject acTable, "ユーザマスタ"
    DoCmd.DeleteObject acTable, "貸出マスタ"
    DoCmd.DeleteObject acTable, "bookマスタ"
    DoCmd.DeleteObject acTable, "廃棄bookマスタ"
    
    deleteLink = True
    Set mdb = Nothing
    
End Function

'外部のデータベースにリンクテーブルを貼る
Public Function makelink()
    On Error GoTo Err_makelink
    
    'リンクテーブルを設定する
    Dim db As DAO.Database
    Dim tb As DAO.TableDef
    Dim basemdbpath As Variant
    Set db = CurrentDb()
    
    '接続パスワード
    Dim passcode As String
    passcode = "hogehoge2020"
    
    'データ保存ファイルへリンクテーブルを貼る
    basemdbpath = CurrentProject.Path & "\database.accdb"

    Set tb = db.CreateTableDef("ユーザマスタ")
    tb.Connect = "MS Access;PWD=" & passcode & ";DATABASE=" & basemdbpath
    tb.SourceTableName = "ユーザマスタ"
    db.TableDefs.Append tb
    
    Set tb = db.CreateTableDef("貸出マスタ")
    tb.Connect = "MS Access;PWD=" & passcode & ";DATABASE=" & basemdbpath
    tb.SourceTableName = "貸出マスタ"
    db.TableDefs.Append tb

    Set tb = db.CreateTableDef("bookマスタ")
    tb.Connect = "MS Access;PWD=" & passcode & ";DATABASE=" & basemdbpath
    tb.SourceTableName = "bookマスタ"
    db.TableDefs.Append tb

    Set tb = db.CreateTableDef("廃棄bookマスタ")
    tb.Connect = "MS Access;PWD=" & passcode & ";DATABASE=" & basemdbpath
    tb.SourceTableName = "廃棄bookマスタ"
    db.TableDefs.Append tb

Exit_makelink:
    Exit Function
Err_makelink:
    MsgBox Err.Description
    Resume Exit_makelink
End Function

database.accdbの接続パスワードを変更するにはコード内のpasscodeを変更するだけでなく、database.accdb側のパスコードを変更する必要があります。以下の手順で行います。

  1. Accessを起動する
  2. ファイル⇒開く⇒参照⇒対象のdatabase.accdbを指定する
  3. ここで開くボタンの横にある▼をクリックし、排他モードで開くにする
  4. パスワードを入力
  5. ファイル⇒情報⇒データベースの解読をクリック
  6. 改めて現在のパスワードを入力
  7. ファイル⇒情報⇒パスワードを使用して暗号化をクリック
  8. 新しいパスワードを設定し、コード側のpasscodeも書き換える
  9. 閉じる

passcodeはコード内に書くのではなく起動時に入力するようなダイアログを用意してメモリ上で保存しておくほうが望ましいでしょう。

図:暗号化は排他モードで開く必要性があります

使い方

データの整備

ユーザの登録

事前にユーザの登録が必要です。

  1. リボンの各種設定とアプリ⇒ユーザ登録を開く
  2. ユーザID(例えば社員番号などの重複しないコード)、Felicaコード(NFCのidm番号)の2つは最低限登録しておきます

登録がないと貸出処理が出来ません。

書籍の登録

事前に書籍の登録情報がないと貸出が行なえません。

  1. リボンの各種設定とアプリ⇒書籍データのスキャン取り込みを開く
  2. ISBNコードをバーコードリーダなどで読み取る
  3. 読み取れたらEnterキーを押すと、国会図書館APIおよび楽天ブックスAPIが実行されて書籍情報がロードされる
  4. ロードされたら、登録ボタンを押すとマスタに登録されます。重複登録は出来ません。

図:書籍情報は手入力は不要です

書籍の廃棄登録

書籍が破損したり不要になって登録抹消する場合は以下の手順で行います。

  1. リボンの各種設定とアプリ⇒書籍データのスキャン取り込みを開く
  2. 書籍廃棄のタブをクリック
  3. ISBNコードをバーコードリーダなどで読み取る
  4. 廃棄ボタンをクリックするとマスタから削除され、廃棄Bookマスタに登録されます。

図:廃棄登録も必要なメンテナンスです

実際の貸出・返却処理

実際の貸出処理は前述のデータ整備がなされていれば簡単です。ユーザは以下の手順で貸し出し・返却を行います。管理者はリボンの各種共通台帳にある「各種設定とアプリ」⇒貸出フォーム表示をクリックすれば、Accessフォームがフルスクリーン表示で開かれますので、この状態で運用を行います(左下のボタンを押せば閉じられます)

  1. 貸出処理はISBNコードは書籍からバーコードリーダを使って読み込ませましょう
  2. セキュリティカードNo.はPasoriからNFCをかざして、貸出・返却のボタンを押す事で読み込まれます。
  3. 貸出・返却のボタンを押すと書籍登録とユーザ登録チェックの後に、データベースへと登録がなされます。

図:フルスクリーン表示で専用端末化

ソースコード

書籍検索用コード

Option Compare Database

'プロキシアドレス
Const proxyuri As String = "ここにプロキシのアドレスを入れる"

'XMLデータ保存用
Public xmldata As Variant

'楽天Booksパラメータ
Const appid As Variant = "ここにAPPIDを入れる"
'Const appsecret As Variant = "ここにAPP Secretを入れる"
'Const afiid As Variant = "ここに楽天アフィリエイトIDを入れる" '
'Const Callback As String = "ここにコールバックURLを入れる"
Const rakutenurl As String = "https://app.rakuten.co.jp/services/api/BooksBook/Search/20170404?applicationId="

'XMLデータ
Private xmlDocument As MSXML2.DOMDocument60

'国会図書館API検索
Public Function kokkaibook(isbncode As Variant) As Boolean
    On Error Resume Next
    '変数を宣言
    Dim URL As String
    Dim statusflg As Variant
    URL = "http://iss.ndl.go.jp/api/opensearch?isbn=" & isbncode

    'POST通信でAPIを叩いてデータを取得
    With CreateObject("WinHttp.WinHttpRequest.5.1")
      .Open "GET", URL, False
      .setProxy 2, proxyuri  'プロキシサーバのURLとポート番号
      .send
      
      '返ってきた値をもとにデータを処理
      Select Case .Status
        Case 200
            'JSONデータを取得する
            xmldata = .responseText
            
        Case Else
            'フラグを返す
            kokkaibook = False
      End Select
    End With
    
    '取得データの中身を取得
    'Microsoft XML v6.0 を参照設定
    Set xmlDocument = Nothing
    Set xmlDocument = New MSXML2.DOMDocument60
    xmlDocument.async = False
    xmlDocument.LoadXML (xmldata)

    If (xmlDocument.parseError.ErrorCode <> 0) Then 'ロード失敗
        Dim strMsg As String
        strMsg = xmlDocument.parseError.reason      'エラー内容を出力
        MsgBox "ロードに失敗しました・・・" & vbCrLf & vbCrLf & strMsg, vbCritical
        Exit Function
    End If
    
    'XMLノード取得用
    Dim rssNode As IXMLDOMNode
    Dim chkNode As IXMLDOMNode
    Dim chanNode As IXMLDOMNode
    Dim tempdate As Variant
    Dim tempprice As Variant
    Dim i As Integer
    
    '検索結果をチェックする
    Set chkNode = xmlDocument.SelectSingleNode("//rss/channel")
    For Each chanNode In chkNode.ChildNodes
        DoEvents
        DoCmd.Hourglass True
        'タイトルを取得する
        If chanNode.nodeName = "openSearch:totalResults" Then
            If chanNode.Text = "0" Then
                '終了処理
                'オブジェクトの開放
                Set chkNode = Nothing
                Set chanNode = Nothing
                Set xmlDocument = Nothing
                DoCmd.Hourglass False
                kokkaibook = False
                Exit Function
            End If
        End If
    Next chanNode
    
    DoCmd.Hourglass False
    
    'itemノードを取得する
    Set rssNode = xmlDocument.SelectSingleNode("//rss/channel/item")
    
    'ノードを精査する
    For Each chanNode In rssNode.ChildNodes
        DoEvents

        'タイトルを取得する
        If chanNode.nodeName = "title" Then
            Forms!書籍情報登録!booktitle.Value = chanNode.Text
        End If
        
        'リンク先を取得する
        If chanNode.nodeName = "link" Then
            Forms!書籍情報登録!booklink.Value = chanNode.Text
        End If
        
        '著者名を取得する
        If chanNode.nodeName = "author" Then
            Forms!書籍情報登録!authorname.Value = chanNode.Text
        End If
        
        '出版社名を取得する
        If chanNode.nodeName = "dc:publisher" Then
            Forms!書籍情報登録!pubname.Value = chanNode.Text
        End If
    
        '発売日
        If chanNode.nodeName = "pubDate" Then
            tempdate = CDate(Mid(chanNode.Text, 5, 12))
            Forms!書籍情報登録!pubdate.Value = tempdate
        End If
    
        '価格
        If chanNode.nodeName = "dcndl:price" Then
            tempprice = Replace(chanNode.Text, "円", "")
            Forms!書籍情報登録!pubprice.Value = tempprice
        End If   
    Next chanNode
    
    'オブジェクトの開放
    Set rssNode = Nothing
    Set chanNode = Nothing
    Set xmlDocument = Nothing
    
    '値を返す
    kokkaibook = True
    
End Function

'楽天Books API検索モジュール
Public Function rakutenbook(isbncode As Variant) As Boolean
    '変数を宣言
    Dim URL As String
    URL = rakutenurl & appid & "&isbn=" & isbncode
    Debug.Print URL
    
    'JSONをパースする用の変数
    Dim doc, jsn, Json
    
    'JSON受信用
    'HTMLDocumentを取得
    Set doc = CreateObject("HtmlFile")
    'scriptタグを追加
    doc.Write "<script>document.JsonParse=function (s) {return eval('(' + s + ')');}</script>"
 
    'POST通信でAPIを叩いてデータを取得
    With CreateObject("WinHttp.WinHttpRequest.5.1")
      .Open "GET", URL, False
      .setProxy 2, proxyuri  'プロキシサーバのURLとポート番号
      .setRequestHeader "Content-Type", "application/json; charset=UTF-8"
      .send
      
      '返ってきた値をもとにデータを処理
      Debug.Print .Status
      Select Case .Status
        Case 200
            'JSONデータを取得する
            Json = .responseText
            
            If Len(Trim(Json)) > 0 Then
                'パース関数でJSONオブジェクトを取得
                Set jsn = doc.JsonParse(Json)
                tempArray = Split(jsn.Items, ",")
                blength = UBound(tempArray) - LBound(tempArray)
                Set o = CallByName(jsn.Items, 0, VbGet)
                Set o2 = CallByName(o, "Item", VbGet)
                
                '各種返り値をフォームに格納する
                Forms!書籍情報登録!booktitle.Value = CallByName(o2, "title", VbGet)
                Forms!書籍情報登録!booklink.Value = CallByName(o2, "itemUrl", VbGet)
                Forms!書籍情報登録!authorname.Value = CallByName(o2, "author", VbGet)
                Forms!書籍情報登録!pubname.Value = CallByName(o2, "publisherName", VbGet)
                tempdate = CDate(CallByName(o2, "salesDate", VbGet))
                Forms!書籍情報登録!pubdate.Value = tempdate
                Forms!書籍情報登録!pubprice.Value = CallByName(o2, "itemPrice", VbGet)
                
                '値を返す
                rakutenbook = True
            Else
                rakutenbook = False
            End If
        Case Else
            'フラグを返す
            rakutenbook = False
      End Select
    End With
End Function
  • 今回は社内向けアプリなので、プロキシーを超える為に設定を追加しています。利用しない場合は、WinHTTPの.setProxy 2, proxyuriをコメントアウトすると良いでしょう。
  • 今回のケースでは楽天ブックスAPIのAPIIDのみで構築可能です
  • コード冒頭のGeneralセクションに、楽天ブックスAPIで使用するAPPIDなどをセットしておく必要があります。
  • 国会図書館APIは叩いた結果がXMLで返ってくるので、解析を行いフォームに追加する仕組みです。API実行に特にAPPIDなどは不要ですが、レスポンスが非常に悪いです(とにかく遅い)
  • 楽天ブックスAPIは叩いた結果がJSONで返ってくるので、CallByName関数で解析を行います。64bit環境なのでScriptControlを使った手法は利用できません。

書籍の貸出・返却用コード

'貸出ボタンのルーチン
Private Sub コマンド11_Click()
    'エラーハンドリング開始
    On Error GoTo err_handle
    
    '入力内容のvalidation
    If IsNull(Me.isbncode.Value) Or Me.isbncode.Value = "" Then
        MsgBox "ISBNコードが空っぽですよ"
        Me.isbncode.SetFocus
        Exit Sub
    End If

    'ISBNコードが登録済みのデータ内にあるかチェック
    Dim isbnman As Variant
    Dim result As Variant
    isbnman = Me.isbncode.Value
    
    result = DCount("*", "bookマスタ", "ISBNコード=" & isbnman)

    If result = 0 Then
        MsgBox "入力されたISBNコードはシステムに未登録です。"
        Me.isbncode.SetFocus
        Exit Sub
    End If

    'セキュリティカード番号が登録済みのデータ内にあるかチェック
    Dim secman As Variant

    'カードを読み取り
    secman = readcard()
    
    'retの値が空の場合
    If secman = "" Then
        Exit Sub
    Else
        Me.seccard.Value = secman
    End If
    
    'セキュリティカードナンバーのデータの件数チェック
    result = DCount("*", "ユーザマスタ", "Felicaコード='" & secman & "'")

    If result = 0 Then
        MsgBox "入力されたセキュリティカード番号はシステムに未登録です。"
        Me.seccard.SetFocus
        Exit Sub
    End If
    
    '貸出マスタにデータを登録
    'データベース接続用変数
    Dim db As Database
    Dim rst As DAO.Recordset
    Set db = CurrentDb
    Set rst = db.OpenRecordset("貸出マスタ")
    
    With rst
        .AddNew
        !Felicaコード = secman
        !ISBNコード = isbnman
        !貸出日 = Now()
        .Update
    End With
    
    '終了処理
    Set db = Nothing
    Set rst = Nothing
    
    'メッセージとフォーカス
    MsgBox "貸出処理完了!!"
    Me.isbncode.SetFocus
    
    '終了処理
    Me.isbncode.Value = ""
    Me.seccard.Value = ""
    
end_handle:
    Exit Sub

err_handle:
    MsgBox Err.Number & " : " & Err.Description, vbExclamation
    Resume end_handle

End Sub
'返却ボタンのルーチン
Private Sub コマンド12_Click()
    'エラーハンドリング開始
    On Error GoTo err_handle
    
    '入力内容のvalidation
    If IsNull(Me.isbncode.Value) Or Me.isbncode.Value = "" Then
        MsgBox "ISBNコードが空っぽですよ"
        Me.isbncode.SetFocus
        Exit Sub
    End If
    
    'ISBNコードが登録済みのデータ内にあるかチェック
    Dim isbnman As Variant
    Dim result As Variant
    isbnman = Me.isbncode.Value
    
    result = DCount("*", "bookマスタ", "ISBNコード=" & isbnman)

    If result = 0 Then
        MsgBox "入力されたISBNコードはシステムに未登録です。"
        Me.isbncode.SetFocus
        Exit Sub
    End If

    'セキュリティカード番号が登録済みのデータ内にあるかチェック
    Dim secman As Variant
    'カードを読み取り
    secman = readcard()
    
    'retの値が空の場合
    If secman = "" Then
        Exit Sub
    Else
        Me.seccard.Value = secman
    End If
    
    result = DCount("*", "ユーザマスタ", "Felicaコード='" & secman & "'")

    If result = 0 Then
        MsgBox "入力されたセキュリティカード番号はシステムに未登録です。"
        Me.seccard.SetFocus
        Exit Sub
    End If
    
    '貸出マスタにデータを登録
    'データベース接続用変数
    Dim db As Database
    Dim rst As DAO.Recordset
    Set db = CurrentDb
    Dim strSQL As String
    Dim henday As Variant
    Dim henflg As Boolean
    
    'フラグ初期化
    henflg = False
    
    '指定のレコードがあるかどうかチェック
    result = DCount("*", "貸出マスタ", "Felicaコード='" & secman & "' AND ISBNコード=" & isbnman)
    
    If result = 0 Then
        MsgBox "指定の書籍の貸出履歴が見つかりませんでした。"
        
        '終了処理
        Set db = Nothing
        Exit Sub
    End If
    
    '特定のレコードを抽出する
    strSQL = "SELECT * FROM 貸出マスタ WHERE Felicaコード='" & secman & "' AND ISBNコード=" & isbnman
    Set rst = db.OpenRecordset(strSQL)
    
    Do Until rst.EOF
        '返却日の値を取得する
        henday = rst!返却日
        
        '返却日が空かどうかをチェックする
        If IsNull(henday) Or henday = "" Then
            '返却日を追加記入
            With rst
                .Edit
                !返却日 = Now()
                .Update
            End With
            
            'フラグを立てる
            henflg = True
            
        Else
            '既に返却データが入ってるので何もしない
        End If

        '次のレコードへ移動
        rst.MoveNext
    Loop

    '終了処理
    Set db = Nothing
    Set rst = Nothing
    
    If henflg = True Then
        MsgBox "返却処理が完了しました。"
    Else
        MsgBox "返却処理すべきデータが見つかりませんでした。"
    End If
    
    '元に位置にフォーカスを移動する
    Me.isbncode.SetFocus
    
    'データをクリアする
    Me.isbncode.Value = ""
    Me.seccard.Value = ""

end_handle:
    Exit Sub

err_handle:
    MsgBox Err.Number & " : " & Err.Description, vbExclamation
    Resume end_handle
End Sub
  • 書籍のISBNコードおよびNFCのidm番号がフォーム上に入ってる状態で貸出および返却を実行した場合の処理です。
  • 貸出の場合idmからユーザ登録の有無、isbnから書籍登録の有無をチェックしてから登録になります。
  • 今回のアプリでは同じ書籍が複数ある場合のカウントチェックなどは行っていません。
  • 返却の場合idmからユーザ登録の有無、isbnから貸出マスタを参照し返却済みかどうかを探しだしチェックしてから登録になります。
  • 複数書籍があり貸出を行っていてもidmで区別をしているので、他人の貸出に返却処理が追加される事はありません。

カードリーダ読み取り用コード

Option Compare Database
'SheepSmartCard64.dllを読み込ませる(カレントディレクトリより)
Public Declare PtrSafe Function GetSmartCardUID Lib "SheepSmartCard64.dll" (ByVal SCardUID As String) As Integer

'カードリーダー読み取り
Public Function readcard() As Variant
    '変数の宣言
    Dim ret As Integer
    Dim strCardUID As String

    'DLL読み込みカレントディレクトリの変更等用
    ChDrive Application.CurrentProject.Path
    ChDir Application.CurrentProject.Path
    ChDriver = Application.CurrentProject.Path
    
    '空文字のままで関数に渡すとエラーとなるので、Null文字で埋めておきます
    strCardUID = String$(128, vbNullChar)
    
    '文字列からNull文字を除去
    ret = GetSmartCardUID(strCardUID)
    strCardUID = Replace(strCardUID, vbNullChar, "")
    
    '読み取り結果
    Select Case ret
        Case 0
            '読み取り成功
            readcard = strCardUID
        Case 100
            'セットされていない?
            MsgBox "カードがセットされていないか、または読み取りできないカードがセットされています。"
            readcard = ""
        Case 200
            'カードリーダー接続不良
            MsgBox "カードリーダーを認識できません。接続されているかご確認下さい。"
            readcard = ""
        Case 300
            'SmartCardサービスが起動していない
            MsgBox "スマートカードサービスが起動していないか、またはインストールされていません。"
            readcard = ""
        Case 400
            '読み取り失敗
            MsgBox "カードIDの取得に失敗しました。"
            readcard = ""
        Case Else
            'その他のエラー
            MsgBox "予期しないエラーが発生しました。"
            readcard = ""
    End Select
    
End Function
  • SheepSmartCard作者さんのコードそのものですが、通常このDLLはC:\Windows\System32に配置するのですが、社内PCだと制限で入れられない事が多いので、DLL読み込みカレントディレクトリの変更等用のコードを追加して、カレントディレクトリ内にあるDLLを読み込ませています(DLLのフルパス指定は必要ありません)
  • Pasoriがきちんと接続されていれば、NFCをかざしてデータ取得処理を行えば、NFCのidm番号がきちんと読み取れます。

図:64bit環境でもNFCが使えるととても利用の幅が広がります

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)