public void StopListening(bool Dummy) { WriteMode = false; Enabled = false; NfcSession?.InvalidateSession(); NfcSession = null; }
/// <summary> /// NFC読取セッションがタグを検知されたら呼び出される。 /// </summary> /// <param name="session">NFC読取セッション</param> /// <param name="tags">検知タグ</param> public override void DidDetectTags(NFCTagReaderSession session, INFCTag[] tags) { Debug.WriteLine($"DidDetectTags"); // タグに接続する。 if (tags.Length <= 0) { return; } session.ConnectTo(tags[0], connectErr => { // 接続エラー時はメッセージを表示してNFC読取セッションを終了する、 if (connectErr != null) { Debug.WriteLine($"Connect Error = [{connectErr}]"); session.InvalidateSession("タグ接続失敗。"); return; } // FeliCa準拠のタグプロトコルを取得する。 _felicaTag = tags[0].GetNFCFeliCaTag(); if (_felicaTag == null) { return; } // FeliCaのRequest Serviceコマンドを実行し、 // サービスコード0x090Fを指定し、カード種別およびカード残額情報サービスに接続する。 // (サービスコードはリトルエンディアンで) _felicaTag.RequestService(ServiceCodes, OnCompletedRequestService); }); }
protected override async Task OnTagDetected(NFCTagReaderSession session, INFCTag tag) { var amiibo = await TryReadAmiibo(session, tag); if (amiibo != null) { await OnAmiibo(amiibo, false); } }
/// <summary> /// Suica読取開始。 /// </summary> /// <param name="onScanAction">Suica検知デリゲート。引数はSuicaから読み取った残高と日付。</param> public void StartScanningSuica(Action <int, DateTime> onScanAction) { // Suica検知デリゲートを保存。 _onScanAction = onScanAction; // NFC読取セッションを開始する。 _session = new NFCTagReaderSession(NFCPollingOption.Iso18092, this, DispatchQueue.CurrentQueue); _session.AlertMessage = "Suica/Kitacaをかざして"; _session.BeginSession(); }
public void BeginSession() { TryInvalidateSession(); Session = new NFCTagReaderSession( NFCPollingOption.Iso14443, GetSessionDelegate(), DispatchQueue.MainQueue); Session.BeginSession(); }
/// <summary> /// Invalidate the session /// </summary> /// <param name="session"><see cref="NFCTagReaderSession"/></param> /// <param name="message">Message to show</param> void Invalidate(NFCTagReaderSession session, string message = null) { _customInvalidation = true; if (string.IsNullOrWhiteSpace(message)) { session.InvalidateSession(); } else { session.InvalidateSession(message); } }
/// <summary> /// Starts tags detection /// </summary> public void StartListening() { _customInvalidation = false; _isWriting = false; _isFormatting = false; NfcSession = new NFCTagReaderSession(NFCPollingOption.Iso14443 | NFCPollingOption.Iso15693, this, DispatchQueue.CurrentQueue) { AlertMessage = UIMessages.NFCDialogAlertMessage }; NfcSession?.BeginSession(); }
/// <summary> /// Invalidate the session /// </summary> /// <param name="session"><see cref="NFCTagReaderSession"/></param> /// <param name="message">Message to show</param> void Invalidate(NFCTagReaderSession session, string message = null) { _customInvalidation = true; if (string.IsNullOrWhiteSpace(message)) { session.InvalidateSession(); } else { session.InvalidateSession(message); } OnTagListeningStatusChanged?.Invoke(false); }
public bool IsAvailable() { NfcSession = new NFCTagReaderSession(NFCPollingOption.Iso14443, this, null) { AlertMessage = "NFC not available." }; if (NfcSession != null) { NfcSession.InvalidateSession(); return(true); } return(false); }
/// <summary> /// Starts tag publishing (writing or formatting) /// </summary> /// <param name="clearMessage">Format tag</param> public void StartPublishing(bool clearMessage = false) { if (!IsAvailable) { throw new InvalidOperationException(UIMessages.NFCWritingNotSupported); } _customInvalidation = false; _isWriting = true; _isFormatting = clearMessage; NfcSession = new NFCTagReaderSession(NFCPollingOption.Iso14443 | NFCPollingOption.Iso15693, this, DispatchQueue.CurrentQueue) { AlertMessage = UIMessages.NFCDialogAlertMessage }; NfcSession?.BeginSession(); }
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; } }
/// <summary> /// Event raised when an error happened during detection /// </summary> /// <param name="session">iOS <see cref="NFCTagReaderSession"/></param> /// <param name="error">iOS <see cref="NSError"/></param> public override void DidInvalidate(NFCTagReaderSession session, NSError error) { var readerError = (NFCReaderError)(long)error.Code; if (readerError != NFCReaderError.ReaderSessionInvalidationErrorFirstNDEFTagRead && readerError != NFCReaderError.ReaderSessionInvalidationErrorUserCanceled) { var alertController = UIAlertController.Create("Session Invalidated", error.LocalizedDescription, UIAlertControllerStyle.Alert); alertController.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, null)); DispatchQueue.MainQueue.DispatchAsync(() => { GetCurrentController().PresentViewController(alertController, true, null); }); } else if (readerError == NFCReaderError.ReaderSessionInvalidationErrorUserCanceled && !_customInvalidation) { OniOSReadingSessionCancelled?.Invoke(null, EventArgs.Empty); } }
/// <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) { var _tag = tags.First(); var connectionError = string.Empty; session.ConnectTo(_tag, (error) => { if (error != null) { connectionError = error.LocalizedDescription; return; } }); var nMifareTag = _tag.GetNFCMiFareTag(); //nMifareTag.SendMiFareCommand(); }
/// <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) { var _tag = tags.First(); var connectionError = string.Empty; session.ConnectTo(_tag, (error) => { if (error != null) { connectionError = error.LocalizedDescription; return; } }); var nMifareTag = _tag.GetNFCMiFareTag(); var t = WriteMode ? Task.Run(() => HandleWiteTag(nMifareTag)): Task.Run(() => HandleReadTag(nMifareTag)); }
public void StartListening(bool Write) { if (!IsAvailable()) { throw new InvalidOperationException("NFC not available"); } if (!IsEnabled()) // todo: offer possibility to open dialog { throw new InvalidOperationException("NFC is not enabled"); } WriteMode = Write; NfcSession = new NFCTagReaderSession(NFCPollingOption.Iso14443, this, null) { AlertMessage = "Present your NFC tag" }; NfcSession?.BeginSession(); Enabled = true; }
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); }
public async Task WriteAmiibo(NFCTagReaderSession session, INFCMiFareTag tag, DetectedAmiibo amiibo) { var dynamicLockBytes = new byte[] { 0x01, 0x00, 0x0F, 0xBD }; var staticLockBytes = new byte[] { 0x0F, 0xE0, 0x0F, 0xE0 }; var dump = amiibo.TagData; // this is ille🚨al so i took it out, but the flow is: // 1. make a copy of the tag dump // 2. decrypt the encrypted part of the tag dump using the original tag uid and secret nintendo key material // 3. reencrypt the now decrypted parts of the tag dump using the uid of the target tag and secret nintendo key material // 4. write the tag dump (not the lock bits) to the tag // 5. write the dynamic lock bits to 0x82 // 6. write the static lock bits to 0x2 // 7. draw the amiibo on the card for good luck // check https://www.3dbrew.org/wiki/Amiibo for amiibo data structure // check https://github.com/AcK77/AmiiBomb-uino for a good cloning reference await Task.Yield(); session.AlertMessage = "Various implementation details removed and left to the reader (check the source)."; }
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!"); } }); }); }
public override void DidInvalidate(NFCTagReaderSession session, NSError error) => _DidInvalidate?.Invoke(session, error);
public override void DidDetectTags(NFCTagReaderSession session, INFCTag[] tags) => _DidDetectTags?.Invoke(session, tags);
public override void DidBecomeActive(NFCTagReaderSession session) => _DidBecomeActive?.Invoke(session);
public override void DidInvalidate(NFCTagReaderSession session, NSError error) { MainTabViewModel.Current.cbNFCRead = false; MainTabViewModel.Current.cbNFCWrite = false; }
/// <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); }); } }); }); }
/// <summary> /// Writes or clears a TAG /// </summary> /// <param name="session"><see cref="NFCTagReaderSession"/></param> /// <param name="tag"><see cref="INFCNdefTag"/></param> /// <param name="tagInfo"><see cref="ITagInfo"/></param> /// <param name="clearMessage">Clear message</param> void ExecuteWriteOrClear(NFCTagReaderSession session, INFCNdefTag tag, ITagInfo tagInfo, bool clearMessage = false) { tag.QueryNdefStatus((status, capacity, error) => { if (error != null) { Invalidate(session, error.LocalizedDescription); return; } if (status == NFCNdefStatus.ReadOnly) { Invalidate(session, UIMessages.NFCErrorReadOnlyTag); return; } if (Convert.ToInt32(capacity) < NFCUtils.GetSize(tagInfo.Records)) { Invalidate(session, UIMessages.NFCErrorCapacityTag); return; } NFCNdefMessage message = null; if (!clearMessage) { session.AlertMessage = UIMessages.NFCSuccessWrite; var records = new List <NFCNdefPayload>(); for (var i = 0; i < tagInfo.Records.Length; i++) { var record = tagInfo.Records[i]; if (GetiOSPayload(record) is NFCNdefPayload ndefPayload) { records.Add(ndefPayload); } } if (records.Any()) { message = new NFCNdefMessage(records.ToArray()); } } else { session.AlertMessage = UIMessages.NFCSuccessClear; message = GetEmptyNdefMessage(); } if (message != null) { tag.WriteNdef(message, (error) => { if (error != null) { Invalidate(session, error.LocalizedDescription); return; } tagInfo.Records = GetRecords(message.Records); OnMessagePublished?.Invoke(tagInfo); Invalidate(NfcSession); }); } else { Invalidate(session, UIMessages.NFCErrorWrite); } }); }
/// <summary> /// NFC読取セッションが無効になった際に呼び出される。 /// </summary> /// <param name="session">無効になったセッション</param> /// <param name="error">無効になった理由</param> public override void DidInvalidate(NFCTagReaderSession session, NSError error) { Debug.WriteLine($"DidInvalidate. error=[{error}]"); _session.Dispose(); _session = null; }
protected async virtual Task OnTagDetected(NFCTagReaderSession session, INFCTag tag) { await ReadTagData(session, tag); }
public override void DidInvalidate(NFCTagReaderSession session, NSError error) { // throw new NotImplementedException(); }
/// <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); }); } }); }); }
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, }); }