예제 #1
0
 /// <summary>
 /// Stops tag publishing
 /// </summary>
 public void StopPublishing()
 {
     _isWriting = _isFormatting = _customInvalidation = false;
     _tag       = null;
     NfcSession?.InvalidateSession();
     OnTagListeningStatusChanged?.Invoke(false);
 }
예제 #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="tag"></param>
        /// <returns></returns>
        INFCNdefTag GetNdefTag(INFCTag tag)
        {
            if (tag == null || !tag.Available)
            {
                return(null);
            }

            INFCNdefTag ndef;

            if (tag.GetNFCMiFareTag() != null)
            {
                ndef = tag.GetNFCMiFareTag();
            }
            else if (tag.GetNFCIso7816Tag() != null)
            {
                ndef = tag.GetNFCIso7816Tag();
            }
            else if (tag.GetNFCFeliCaTag() != null)
            {
                ndef = tag.GetNFCFeliCaTag();
            }
            else
            {
                ndef = null;
            }

            return(ndef);
        }
예제 #3
0
        public static INFCNdefTag GetNdefTag(INFCTag tag)
        {
            if (tag == null /*|| !tag.Available*/)
            {
                return(null);
            }
            NFCTagType tp = (NFCTagType)tag.Type;

            INFCNdefTag ndef;

            if (tag.GetNFCMiFareTag() != null)
            {
                ndef = tag.GetNFCMiFareTag();
            }
            else if (tag.GetNFCIso7816Tag() != null)
            {
                ndef = tag.GetNFCIso7816Tag();
            }
            else if (tag.GetNFCFeliCaTag() != null)
            {
                ndef = tag.GetNFCFeliCaTag();
            }
            else
            {
                ndef = null;
            }

            return(ndef);
        }
예제 #4
0
        protected override async Task OnTagDetected(NFCTagReaderSession session, INFCTag tag)
        {
            var amiibo = await TryReadAmiibo(session, tag);

            if (amiibo != null)
            {
                await OnAmiibo(amiibo, false);
            }
        }
예제 #5
0
        protected override async Task OnTagDetected(NFCTagReaderSession session, INFCTag tag)
        {
            if (SelectedAmiibo == null)
            {
                session.AlertMessage = "Select an amiibo to clone.";
                return;
            }

            if (SelectedAmiibo != null)
            {
                session.AlertMessage = $"Writing {SelectedAmiibo.Metadata.Name} to this tag...";

                await WriteAmiibo(session, tag.GetNFCMiFareTag(), SelectedAmiibo);

                return;
            }
        }
예제 #6
0
        void MakeTagReadOnly(NFCTagReaderSession session, INFCTag tag, INFCNdefTag ndefTag)
        {
            session.ConnectTo(tag, (error) =>
            {
                if (error != null)
                {
                    Console.WriteLine(error.LocalizedDescription);
                    return;
                }

                ndefTag.WriteLock((error) =>
                {
                    if (error != null)
                    {
                        Console.WriteLine("Error when locking a tag on iOS: " + error.LocalizedDescription);
                    }
                    else
                    {
                        Console.WriteLine("Locking Successful!");
                    }
                });
            });
        }
예제 #7
0
        public async Task <byte[]> ReadTagData(
            NFCTagReaderSession session, INFCTag tag)
        {
            await session.ConnectToAsync(tag);

            var mifare = tag.GetNFCMiFareTag();

            if (mifare is null)
            {
                return(new byte[0]); // not a mifare tag
            }
            var tagData =
                await mifare.DoFastRead(
                    from : 0x0, to : 0x86,
                    batchSize : 0x43
                    );

            Debug.WriteLine(
                "Tag Data:\r\n" +
                Utils.HexDump(tagData, 8));

            return(tagData);
        }
예제 #8
0
        /// <summary>
        /// Write or Clear a NDEF message
        /// </summary>
        /// <param name="tag"><see cref="INFCTag"/></param>
        /// <param name="tagInfo"><see cref="ITagInfo"/></param>
        /// <param name="clearMessage">Clear Message</param>
        /// <param name="makeReadOnly">Make a tag read-only</param>
        internal void WriteOrClearMessage(INFCTag tag, ITagInfo tagInfo, bool clearMessage = false, bool makeReadOnly = false)
        {
            if (NfcSession == null)
            {
                return;
            }

            if (tag == null)
            {
                Invalidate(NfcSession, UIMessages.NFCErrorMissingTag);
                return;
            }

            if (tagInfo == null)
            {
                Invalidate(NfcSession, UIMessages.NFCErrorMissingTagInfo);
                return;
            }

            var ndefTag = GetNdefTag(tag);

            if (ndefTag == null)
            {
                Invalidate(NfcSession, UIMessages.NFCErrorNotCompliantTag);
                return;
            }

            try
            {
                if (!ndefTag.Available)
                {
                    NfcSession.ConnectTo(tag, (error) =>
                    {
                        if (error != null)
                        {
                            Invalidate(NfcSession, error.LocalizedDescription);
                            return;
                        }

                        ExecuteWriteOrClear(NfcSession, ndefTag, tagInfo, clearMessage);
                    });
                }
                else
                {
                    ExecuteWriteOrClear(NfcSession, ndefTag, tagInfo, clearMessage);
                }

                if (!clearMessage && makeReadOnly)
                {
                    MakeTagReadOnly(NfcSession, tag, ndefTag);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
            }
            finally
            {
                OnTagDisconnected?.Invoke(null, EventArgs.Empty);
            }
        }
예제 #9
0
        /// <summary>
        /// Event raised when NFC tags are detected
        /// </summary>
        /// <param name="session">iOS <see cref="NFCTagReaderSession"/></param>
        /// <param name="tags">Array of iOS <see cref="INFCTag"/></param>
        public override void DidDetectTags(NFCTagReaderSession session, INFCTag[] tags)
        {
            _customInvalidation = false;
            _tag = tags.First();

            var connectionError = string.Empty;

            session.ConnectTo(_tag, (error) =>
            {
                if (error != null)
                {
                    connectionError = error.LocalizedDescription;
                    Invalidate(session, connectionError);
                    return;
                }

                var ndefTag = GetNdefTag(_tag);

                if (ndefTag == null)
                {
                    Invalidate(session, UIMessages.NFCErrorNotCompliantTag);
                    return;
                }

                ndefTag.QueryNdefStatus((status, capacity, error) =>
                {
                    if (error != null)
                    {
                        Invalidate(session, error.LocalizedDescription);
                        return;
                    }

                    if (status == NFCNdefStatus.NotSupported)
                    {
                        Invalidate(session, UIMessages.NFCErrorNotSupportedTag);
                        return;
                    }

                    var identifier = GetTagIdentifier(ndefTag);
                    var nTag       = new TagInfo(identifier)
                    {
                        IsWritable = status == NFCNdefStatus.ReadWrite
                    };

                    if (_isWriting)
                    {
                        // Write mode
                        OnTagDiscovered?.Invoke(nTag, _isFormatting);
                    }
                    else
                    {
                        // Read mode
                        ndefTag.ReadNdef((message, error) =>
                        {
                            if (error != null)
                            {
                                Invalidate(session, UIMessages.NFCErrorRead);
                                return;
                            }

                            if (message == null)
                            {
                                Invalidate(session, UIMessages.NFCErrorEmptyTag);
                                return;
                            }

                            session.AlertMessage = UIMessages.NFCSuccessRead;

                            nTag.Records = GetRecords(message.Records);
                            OnMessageReceived?.Invoke(nTag);
                            Invalidate(session);
                        });
                    }
                });
            });
        }
예제 #10
0
 /// <summary>
 /// Stops tag publishing
 /// </summary>
 public void StopPublishing()
 {
     _isWriting = _isFormatting = _customInvalidation = false;
     _tag       = null;
     NfcSession?.InvalidateSession();
 }
예제 #11
0
 protected async virtual Task OnTagDetected(NFCTagReaderSession session, INFCTag tag)
 {
     await ReadTagData(session, tag);
 }
예제 #12
0
        /// <summary>
        /// Event raised when NFC tags are detected
        /// </summary>
        /// <param name="session">iOS <see cref="NFCTagReaderSession"/></param>
        /// <param name="tags">Array of iOS <see cref="INFCTag"/></param>
        public override void DidDetectTags(NFCTagReaderSession session, INFCTag[] tags)
        {
            _customInvalidation = false;
            _tag = tags.First();

            var connectionError = string.Empty;

            session.ConnectTo(_tag, (error) =>
            {
                if (error != null)
                {
                    connectionError = error.LocalizedDescription;
                    Invalidate(session, connectionError);
                    return;
                }

                var ndefTag = GetNdefTag(_tag);

                if (ndefTag == null)
                {
                    Invalidate(session, Configuration.Messages.NFCErrorNotCompliantTag);
                    return;
                }

                ndefTag.QueryNdefStatus((status, capacity, error) =>
                {
                    if (error != null)
                    {
                        Invalidate(session, error.LocalizedDescription);
                        return;
                    }

                    var isNdefSupported = status != NFCNdefStatus.NotSupported;

                    var identifier = GetTagIdentifier(ndefTag);
                    var nTag       = new TagInfo(identifier, isNdefSupported)
                    {
                        IsWritable = status == NFCNdefStatus.ReadWrite,
                        Capacity   = Convert.ToInt32(capacity)
                    };

                    if (!isNdefSupported)
                    {
                        session.AlertMessage = Configuration.Messages.NFCErrorNotSupportedTag;

                        OnMessageReceived?.Invoke(nTag);
                        Invalidate(session);
                        return;
                    }

                    if (_isWriting)
                    {
                        // Write mode
                        OnTagDiscovered?.Invoke(nTag, _isFormatting);
                    }
                    else
                    {
                        // Read mode
                        ndefTag.ReadNdef((message, error) =>
                        {
                            // iOS Error: NFCReaderError.NdefReaderSessionErrorZeroLengthMessage (NDEF tag does not contain any NDEF message)
                            // NFCReaderError.NdefReaderSessionErrorZeroLengthMessage constant should be equals to 403 instead of 304
                            // see https://developer.apple.com/documentation/corenfc/nfcreadererror/code/ndefreadersessionerrorzerolengthmessage
                            if (error != null && error.Code != 403)
                            {
                                Invalidate(session, Configuration.Messages.NFCErrorRead);
                                return;
                            }

                            session.AlertMessage = Configuration.Messages.NFCSuccessRead;

                            nTag.Records = GetRecords(message?.Records);
                            OnMessageReceived?.Invoke(nTag);
                            Invalidate(session);
                        });
                    }
                });
            });
        }
예제 #13
0
        public async Task <DetectedAmiibo> TryReadAmiibo(NFCTagReaderSession session, INFCTag tag)
        {
            // dump tag data
            Debug.WriteLine($"Found a tag: {tag}");

            // get mifare representation
            var mifareTag  = tag.GetNFCMiFareTag();
            var identifier = mifareTag.Identifier.ToArray();

            // connect w h y
            await session.ConnectToAsync(tag);

            // read entire tag contents
            var tagData =
                await mifareTag.DoFastRead(
                    from : 0x0, to : 0x86,
                    batchSize : 0x20
                    );

            // dump tag data
            Debug.WriteLine($"== Raw tag data ==\r\n" +
                            $"{Utils.HexDump(tagData, 16)}");

            // extract character identifiers
            var identificationHeader = tagData.Slice(0x15 * 4, 0x2 * 4);

            var uid       = identifier.String();
            var game      = identificationHeader.SliceStr(0, 4);
            var character = identificationHeader.SliceStr(4, 4);

            // print identifiers
            Debug.WriteLine(
                $"== Identifiers ==\r\n" +
                $"Nfc Uid: {uid}\r\n" +
                $"Game Id: {game}\r\n" +
                $"Char Id: {character}\r\n");

            // get metadata from amiibo api
            session.AlertMessage = $"Looking up Amiibo...";

            var lookup = await AmiiboApi.GetAmiibo(game, character);

            var metadata = lookup.Amiibo.FirstOrDefault();

            // dump metadata
            Debug.WriteLine(
                $"== Metadata : https://www.amiiboapi.com/api/ ==\r\n" +
                metadata.ToJson());

            // we did it!
            session.AlertMessage = $"It's {metadata.Name}!";

            var imageData = await new HttpClient().GetByteArrayAsync(metadata.Image);

            return(new DetectedAmiibo
            {
                UID = uid,
                CharacterId = $"{game}-{character}",
                Metadata = metadata,
                TagData = tagData,
                ImageData = imageData,
            });
        }