chariotsolutions / phonegap-nfc

PhoneGap NFC Plugin
MIT License
706 stars 559 forks source link

Support for nfcV #195

Closed Giusti closed 8 years ago

Giusti commented 8 years ago

I tried to read an nfcV with your plugin, i could only read the id and tech Information, on Stackoverflow I read that your plugin can only read Ndef completely but with other nfc technologies it can only retrieve id and tech. I tried to write on the tag

nfc.addNdefFormatableListener(function (nfcEvent) {
        var tagId = nfc.bytesToHexString(nfcEvent.tag.id);
        $rootScope.$broadcast('nfcScanned', tagId);
        console.log('goodread')
        console.log(nfcEvent);
        nfc.write(
            [
                ndef.textRecord("Hello!")
            ],
            function () { console.log("============= WRITE SUCCESS ==============="); },
            function (error) { console.log("=================== WRITE FAILED =================="); console.log(error); }
        );
    }, function () {
        alert("Listening for NDEF Tags.");
    }, function (reason) {
        alert("Error adding NFC Listener " + reason);
    });

I was able to read the Tag and got the Tag Object but when i wanted to write on it nothing happens as soon as i removed the tag from the phone i got "write Failed" with reason "null". I was wondering if you are going to support nfcV soon to read the complete data. Another thing i noticed when i read the tag, i got neither ndefMessage or record in my tag Object, which I have seen others get from reading the tag, but maybe i missed something.

don commented 8 years ago

The plugin supports NDEF for MifareClassic and NFC Forum Type 1 through 4. I don't have plans to add NFCV now, since Android's NDEF doesn't support NFCV. AFAIK there's no tag type spec for ISO 15693 (NFCV tags).

There are Android APIs for NfcV so you could add support. But it looks like you might need to implement the details of writing to the tag yourself.

Can you get some different NFC tags that support NDEF? If you really need NFCV support we can talk about adding enhancements as a consulting project.

floutchito commented 8 years ago

Hello,

I've been reading and writing NfcV tags intensively (almost 1,000 tags per day and device) using Nexus 10 with this plugin for 2 years without problems. What device do you use?

Giusti commented 8 years ago

Hey Flouchito, Well my problem is that I only get the Tag Id and the Type of Tag scanned, but I Need to read the Content of the tag the Bytes written on it, further I would need to write on the Tag (nfcv ISO 15693). I tried the Plugin with a Nexus 5 and a Samsung Galaxy S5. Did you change the Code of the Plugin?

don commented 8 years ago

@Giusti try reading the tag with an NDEF listener. Use nfc.addNdefListener.

You might need the both the nfc.addNdefFormatableListener and nfc.addNdefListener. It's fine to share callbacks between listeners. Android will call the most specific listener for the tag that is scanned.

Giusti commented 8 years ago

Hey Don, I tried all 4 Eventlisteners the tag and the ndef Listener returned data, but only the TagId, and TagType as well as the Timestamp thats all.. I also called the write function It does nothing and when i remove the phone after 5 minutes connection breaks.. neither the success or error function are called only when i remove the phone the error function is called I also tried modifying your plugin so it would fit my needs see here http://stackoverflow.com/questions/31455480/creating-custom-cordova-plugin-for-nfcv-tags not really successful ..

don commented 8 years ago

If there's no NDEF message on the tag, you'll only get the TagId and TagType when you read.

If you can write an NDEF message to the tag using an app like NXP Tag Writer, then phonegap-nfc should be able to read it with nfc.addNdefListener(). If NXP Tag Writer can't write NDEF messages to the tag, you'll probably need non-NDEF solution or different tags.

Giusti commented 8 years ago

I tried the NXP Tag Writer as you suggested, I tried to write an Url to the Tag after I placed the Phone on the Tag I got the following Error Message "No NDEF detected", so I guess the Tags are the Problem.. As posted above I tryed modifying the plugin so it uses the "android.nfc.tech.NfcV"; but wasnt really successful there but thanks for your help and suggestions

Giusti commented 8 years ago

Hey don, could you please leave me your Contact Information ( Tel, Email ), so I can contact you about adding this Functionality as a Consulting Project.

don commented 8 years ago

@Giusti I added my email to my github profile.

valentiniljaz commented 7 years ago

Hi, I faced the same task when trying to read/write NfcV tags. Since I couldn't find any appropriate cordova plugins to accomplish the task, I've developed my own plugin.

Check it out: https://github.com/valentiniljaz/cordova-nfc-plugin

SantoshSah commented 7 years ago

Thank you @valentiniljaz for your plugin. Could you please explain how to use this plugin in Ionic2 app. I tried it to use as other cordova plugin but nothing happens. I mean it did not work. I have configured AndroidManifest.xml and added nfc_tech_filter. I appreciate for your help.

valentiniljaz commented 7 years ago

Could you provide more context so that I can understand what you are trying to do. If you could paste in your JS (TS) code for reading/writing NfcV tags. What command have you used to install the plugin?

SantoshSah commented 7 years ago

Thank you @valentiniljaz for your quick reply.

I performed below steps:

1) I run command "ionic plugin add https://github.com/valentiniljaz/cordova-nfc-plugin" to add this plugin from git to my ionic2 app. I verified that this plugin has been added to project.

2) modified platforms/android/AndroidManifest.xml file and added below code to activity

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
    <action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" />

3) added file nfc_tech_filter.xml to platforms/android/res/xml and added below code to it.

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.NfcV</tech>
    </tech-list>
</resources>

4) In home.ts, i decalred NfcV before @Component as below

declare var NfcV: any; 

5) In constructor of home.ts, called NfcV.init to verify if plugin has been setup correctly as in below code. For sake of clarity, i have added all code of home.ts.

import { Component } from '@angular/core';
import { NavController, Platform } from 'ionic-angular';

declare var NfcV: any;

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public navCtrl: NavController, platform: Platform) {
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      NfcV.init(this.onSuccess, this.onFailure);
      NfcV.checkNfcVAvailability(this.onSuccess, this.onFailure);
    });
  }

  onSuccess() {
    alert('success');
  }

  onFailure(err: any) {
      alert('failed'); 
  }

}

6) For testing, i run command "ionic run android" to see if plugin is initialized correctly but nothing happens when home page is loaded in mobile. No alert for "success" of "failed".

Please let me know if i need to provide anything more.

valentiniljaz commented 7 years ago

There was a bug within plugin.xml, which is now fixed. You need to remove the plugin and readd it.

ionic plugin remove nfc.plugin.NfcVPlugin
ionic plugin add https://github.com/valentiniljaz/cordova-nfc-plugin

I've also added angular service which abstracts away many low level details of cordova plugin. Let me know if it'll be helpful to you.

SantoshSah commented 7 years ago

Thank you @valentiniljaz for your work. I also needed to add it through npm as you have mentioned in page https://github.com/valentiniljaz/cordova-nfc-plugin/blob/master/ionic2/readme.md.

Though it is being initialized correctly by below code

      nfcvService.init().then((success) => {
        console.log('NfcV OK', success);
      });

, this.nfcvService.onTag() is not being invoked when tag is discovered. It is being called only once in ngOnInit() with null tag.

valentiniljaz commented 7 years ago

In order to get notified whenever a new tag is discovered you need to setup two things:

1) within platform.ready() setup ndefListener:

nfcvService.addNdefListener();

This method will add new event listener for Ndef messages. Whenever a new tag is discovered it will push new event down the observable stream. You can subscribe to this stream and you'll be notified whenever a tag is discovered.

2) subscribe to obsevable:

this.nfcvService.onTag().subscribe((tag) => {
    if (tag !== null) {
        console.log('Tag', tag);
    }
});

Since this is BehaviorSubject the first tag will always be null. You can subscribe within ngOnInit method or basically any other as well. More info: https://github.com/valentiniljaz/cordova-nfc-plugin/blob/master/ionic2/readme.md#nfcvserviceaddndeflistener

init method is not required in most cases. Everytime you invoke any other method (addNdefListener, read, write etc.) from cordova plugin, NfcV adapater is initialized.

So you dont't need to use init method. Just use addNdefListener and onTag.

SantoshSah commented 7 years ago

Hello @valentiniljaz,

I did exactly like you have mentioned above but issue remains same. For sake of clarity, i am posting my code.

import { Component, OnInit } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { Device } from '@ionic-native/device';
import {NfcvService} from 'cordova-nfc-plugin/ionic2';

import { HomePage } from '../pages/home/home';

@Component({
  templateUrl: 'app.html'
})

export class MyApp implements OnInit {
  rootPage:any = HomePage;

  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, public nfcvService: NfcvService) {
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      statusBar.styleDefault();
      splashScreen.hide();

      this.nfcvService.addNdefListener();

    });

  }

  ngOnInit() { 
      this.nfcvService.onTag().subscribe((tag) => {

        //Avoid reading null tag on first call
        if(tag){
          //read tag
          var device = {"regexp": new RegExp('<regula-exp>', 'i')};
          this.nfcvService.
            read([
                { block: new Uint8Array([0x00]) },
                { block: new Uint8Array([0x20]) }
            ], true, device)
            .then((data) => {
                alert(JSON.stringify(data));
            });
        }

      });

  }

}

Below is code of AndroidManifest.xml

<?xml version='1.0' encoding='utf-8'?>
<manifest android:hardwareAccelerated="true" android:versionCode="1" android:versionName="0.0.1" package="com.ionicframework.nfcv346699" xmlns:android="http://schemas.android.com/apk/res/android">
    <supports-screens android:anyDensity="true" android:largeScreens="true" android:normalScreens="true" android:resizeable="true" android:smallScreens="true" android:xlargeScreens="true" />
    <uses-permission android:name="android.permission.INTERNET" />
    <application android:hardwareAccelerated="true" android:icon="@mipmap/icon" android:label="@string/app_name" android:supportsRtl="true">
        <activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale" android:label="@string/activity_name" android:launchMode="singleTask" android:name="MainActivity" android:theme="@android:style/Theme.DeviceDefault.NoActionBar" android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="text/plain" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.nfc.action.TECH_DISCOVERED" />
            </intent-filter>
            <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" />
            <intent-filter android:label="@string/launcher_name">
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="25" />
    <uses-permission android:name="android.permission.NFC" />
    <uses-feature android:name="android.hardware.nfc" android:required="false" />
</manifest>

It would be great if you could send me your working sample.

valentiniljaz commented 7 years ago

What you are trying to do it won't work exactly the way you want in to. Ndef listener is separated from read/write operations. With NdefListener you receive an event each time a tag's Ndef message is read, and that's it. If you want to read from that device, Android has to dispatch new intent.

My example:

app.component.ts

import {Component, OnInit} from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { TabsPage } from '../pages/tabs/tabs';
import {NfcvService} from 'cordova-nfc-plugin/ionic2';

@Component({
  templateUrl: 'app.html'
})
export class MyApp implements OnInit {
  rootPage:any = TabsPage;
  public tag;

  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, public nfcvService: NfcvService) {
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      statusBar.styleDefault();
      splashScreen.hide();

      nfcvService.addNdefListener();
    });
  }

  ngOnInit() {
    this.nfcvService.onTag().subscribe((tag) => {
      //Avoid reading null tag on first call
      if (tag) {
        console.log('Found tag:', tag);
        this.tag = tag;
      }
    });
  }

  read() {
    var device = {"regexp": new RegExp('^AIR\-SAVER v[0-9\.]+$', 'i')};
    this.nfcvService.
    read([
      { block: new Uint8Array([0x18]) },
      { block: new Uint8Array([0x19]) }
    ], true, device)
        .then((data) => {
          console.log(data);
        });
  }
}

app.html

<ion-nav [root]="rootPage"></ion-nav>
<div *ngIf="tag">
    Tag: {{tag}}
    <button ion-button (tap)="read()">READ</button>
</div>

1) In constructor I setup NdefListener and within ngOnInit I subscribe to Ndef messages. 2) Once a Nfc intent is received (phone will beep) its Ndef message is sent over to onTag. 3) In onTag I set the property tag to the current read tag which is displayed in view. 3) View has a button which calls read method when tapped. 4) NfcvService.read method waits for another Nfc intent (phone will beep again). Once an intent is received it reads data from specified addresses and returns read data. You will notice that when this intent is received onTag will also receive new event (but the same tag).

The idea for NdefListener is to just handle Ndef messages and nothing else. Once a tag is received within onTag you display specific options for the received tag. Then the user chooses an option which will be executed against that tag.

In your example you need to move the tag to the phone twice. First time to read Ndef message in order to discover which tag you are communicating with. Second time to actually read data from the current tag.

If you wanted to do both steps at once, you can just skip the first step. You don't listen for Ndef messages. You just start reading from the device. Once the Nfc intent is received the data will be read. You can use device object to filter out specific tag.

In future I plan to support your example.

SantoshSah commented 7 years ago

Hello @valentiniljaz ,

I have a NfcV tag. I want to read it when i move mobile to it. I found addNdefFormatableListener from phonegap-nfc is reading tag id and techs but not its data when i move mobile to NfcV tag. Could you please add similar EventListener to this plugin? If not, is there any way i can use this plugin to achieve what i am expecting?

valentiniljaz commented 7 years ago

Of course. You can do it like this:

import {Component, OnInit} from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { TabsPage } from '../pages/tabs/tabs';
import { NfcvService } from 'cordova-nfc-plugin/ionic2';

@Component({
  templateUrl: 'app.html'
})
export class MyApp implements OnInit {
  rootPage:any = TabsPage;

  constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, public nfcvService: NfcvService) {
    platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      statusBar.styleDefault();
      splashScreen.hide();
    });
  }

  ngOnInit() {
    var device = {"regexp": new RegExp('^AIR\-SAVER v[0-9\.]+$', 'i')};
    this.nfcvService.
    read([
      { block: new Uint8Array([0x18]) },
      { block: new Uint8Array([0x19]) }
    ], true, device)
        .then((data) => {
          console.log(data);
        });
  }

}

This will work like this:

Hope it helps.

SantoshSah commented 7 years ago

Hello @valentiniljaz ,

I tried the same in new project but no luck. When i move mobile to tag, beep sounds come but it is not read.

valentiniljaz commented 7 years ago

Well, the above sample works for me on a new Ionic2 project. I suggest you open Chrome DevTools (over USB) for your app and see where the problem is.

One possible issue could be this line in AndroidManifest.xml:

<data android:mimeType="text/plain" />

Your tag could be emitting different mimeType. You need to check with your hardware specification. Try changing to:

<data android:mimeType="*/*" />

If you could send me a link to your tag's specification I can have a look.

Let me know if you figure it out.

SantoshSah commented 7 years ago

Hello @valentiniljaz ,

I tried with

<data android:mimeType="*/*" />

but no luck. I am getting beep sound but tag is not being read.

I also tried to debug over USB and could not really understand the cause. I have attached screenshots. Do you think, cause of not working same code on my machine is node, ionic2 versions? I have tried with all of latest node and ionic2. You can see detail about version on screenshots.

1) Screenshot when app is loaded:

app_start

2) Screenshot when mobile device is moved near tag. Please see error in this screenshot.

error_when_app_moved_to_tag

I only have tag and do not have any specific document. It is freestyle Libre Sensor. I googled for it and found that Sensor is using ISO 15693 tag but not sure about. I am still verifying about its tag specification. I will inform you as soon as i get it.

Thank you.

valentiniljaz commented 7 years ago

Hi @SantoshSah,

The error seems to be originating from within Java plugin. Libre tag appears to be working somewhat differently then the tag that I used. If you can contact the manufacturer and ask then which NFC chip they are using, then I can see what the problem is within the Java plugin.

The other option is to debug the Java plugin. You can open NfcVHandler.java and insert some System.printlns in order to see where the things goes wrong. lenght=36; index=36 points to data formating of you NFC tag, which is different then what is expected by Java plugin.

SantoshSah commented 7 years ago

Hi @valentiniljaz ,

I am waiting for specification document. I will inform as soon as i get. I will debug handler now and inform you cause for this error.

Thank you.

SantoshSah commented 7 years ago

Hello @valentiniljaz ,

In file NfcVHnadler.java, FOR loop is running for i=8 and j=4 then breaks in below method

    private static byte[] getNdefPayloadFromNfcv(Intent intent) throws Exception {
        int payloadLen = NUM_BLOCK_NDEF * NUM_BYTES_BLOCK;
        byte[] payload = new byte[payloadLen];
        for (int i = 0; i < NUM_BLOCK_NDEF; i++) {
            byte[] block = NfcVHandler.readNfcVBlock(intent, new byte[]{ (byte)i });
            for (int j = 1; j < block.length; j++) {
                payload[(i * NUM_BYTES_BLOCK) + (j -1)] = (byte)block[j];
            }
        }
        return payload;
    }
valentiniljaz commented 7 years ago

Hi @SantoshSah,

My tag (referenced in datasheet) uses 36 bytes (9*4) for NDEF message. I guess your tag has different length of NDEF message. Never the less, the length of NDEF message is not the issue here. Just by looking at the code and the error (length=36; index=36) I would say that the last read block (9th) has more than 5 bytes. Array payload has 36 items (length=36) and the plugin is trying to write 37th byte (index=36) and then it fails.

Can you verify my hypothesis like this:

private static byte[] getNdefPayloadFromNfcv(Intent intent) throws Exception {
        int payloadLen = NUM_BLOCK_NDEF * NUM_BYTES_BLOCK;
        byte[] payload = new byte[payloadLen];
        for (int i = 0; i < NUM_BLOCK_NDEF; i++) {
            byte[] block = NfcVHandler.readNfcVBlock(intent, new byte[]{ (byte)i });
            System.out.println(i + 'th block length: ' + block.length);
            for (int j = 1; j < block.length; j++) {
                payload[(i * NUM_BYTES_BLOCK) + (j -1)] = (byte)block[j];
            }
        }
        return payload;
    }

If this is the case then you can limit the inner FOR loop like this:

            for (int j = 1; j < (NUM_BYTES_BLOCK + 1); j++) {
                payload[(i * NUM_BYTES_BLOCK) + (j - 1)] = (byte)block[j];
            }

It would be very helpful if I could take a look at datasheet of the NFC chip to see the length of NDEF message and its addresses. While you wait for datasheet you can try different lengths until you get a meaningfull NDEF.

More generic solution would be to use more fault-tolerant method of reading NDEF message (something from Android). I was experimenting with some options but wasn't able to make it work. I'll try again and will let you know if I find anything.

valentiniljaz commented 7 years ago

The following properties of NfcVHandler class could all be differrent for your tag:

    private static final byte CMD_READ = (byte)0x20;
    private static final byte CMD_WRITE = (byte)0x21;
    private static final byte FLAGS_DATA_RATE = (byte)0x02;
    private static final byte FLAGS_DATA_RATE_AND_PROTOCOL_EXT = (byte)0x0A;
    private static final byte NUM_BLOCK_NDEF = 9;
    private static final byte NUM_BYTES_BLOCK = 4;

I think that without datasheet it's just guessing and hoping it'll work. Event the size of the read block (returned by readNfcVBlock) could be different. It'll be much easier to debug once you get the documentation.

valentiniljaz commented 7 years ago

According to this: https://github.com/vicktor/FreeStyleLibre-NFC-Reader/blob/master/app/FreeStyleLibre/app/src/main/java/com/socialdiabetes/freestylelibre/Abbott.java

the above mentioned properties could be set like this:

FLAGS_DATA_RATE = (byte)0x00; // 0x00 = Low data rate. 0x02 = High data rate.
NUM_BYTES_BLOCK = 8;
NUM_BLOCK_NDEF = 3; // Just a guess, since they are skipping the first 3 blocks.

The blocks containing data seem to be located from addresses 3 - 40.

valentiniljaz commented 7 years ago

You should also have the following line in AndroidManifest.xml:

<data android:mimeType="text/plain" />

It could the case that your tag does not support NDEF messages, in this case you just set NUM_BLOCK_NDEF to 0 and your device object should be undefined. You will still receive an event when the tag is discovered but you wont know which one.

To target only specific tags (Libre) you can issue Get System Info command and use its UID and AFI values (refer to datasheet, chapter 26.12). Add the following code to Ionic NfcvService:

    getSystemInfo(startListen?) {
        console.log('** SYSTEM INFO START **');
        return new Promise((mainResolve, mainReject) => {
            this.startListening(startListen)
                .then(() => {
                    NfcV.transceive(new Uint8Array([0x00, 0x2B]), // 0x2B = Get System Info command
                    (systemInfoData) => {
                        let systemInfoBytes = new Uint8Array(systemInfoData);
                        console.log('** SYSTEM INFO END **', systemInfoBytes);
                        if (systemInfoBytes[0] !== 0) {
                            mainReject('E_SYSTEM_INFO_FAILED | CODE: ' + systemInfoBytes[1]);
                        } else {
                            mainResolve(this.Uint8ArraySplice(systemInfoBytes, 0, 1));
                        }
                    }, 
                    (error) => {
                        mainReject(error);
                    });
                })
                .catch((error) => {
                    mainReject(error);
                });
        });
    }

Full example using GetSystemInfo command and then reading some data:

  ngOnInit() {
    this.nfcvService.
    getSystemInfo(true)
        .then((systemInfo) => {
            console.log('SystemInfo:', systemInfo); // Check the tag's UID and AFI (optionally)
            this.nfcvService.
            read([
              { block: new Uint8Array([0x03]) },
              { block: new Uint8Array([0x04]) }
            ], false)
                .then((data) => {
                  console.log('Read:', data);
                });
        });
  }

WARNING: getSystemInfo and ngOnInit functions weren't tested (my phone broke down), so beware of bugs :-)

SantoshSah commented 7 years ago

Hello @valentiniljaz ,

I experimented with combinations of all of Static values but could not help much. When i tried with device to undefined, its reads some garbage values. I tried to read block from 0x03 to 0x40 and i can see some special characters from tag. I have converted bytes to string using method "nfcvService.bytesToString" as shown in below code.

      this.nfcvService.
      read([
        { block: new Uint8Array([0x03]) },
        { block: new Uint8Array([0x04]) },
        { block: new Uint8Array([0x05]) },
        { block: new Uint8Array([0x06]) },
        { block: new Uint8Array([0x07]) },
        { block: new Uint8Array([0x08]) },
        { block: new Uint8Array([0x09]) },
        { block: new Uint8Array([0x10]) },
        { block: new Uint8Array([0x11]) },
        { block: new Uint8Array([0x12]) },
        { block: new Uint8Array([0x13]) },
        { block: new Uint8Array([0x14]) },
        { block: new Uint8Array([0x15]) },
        { block: new Uint8Array([0x16]) },
        { block: new Uint8Array([0x17]) },
        { block: new Uint8Array([0x18]) },
        { block: new Uint8Array([0x19]) },
        { block: new Uint8Array([0x20]) },
        { block: new Uint8Array([0x21]) },
        { block: new Uint8Array([0x22]) },
        { block: new Uint8Array([0x23]) },
        { block: new Uint8Array([0x24]) },
        { block: new Uint8Array([0x25]) },
        { block: new Uint8Array([0x26]) },
        { block: new Uint8Array([0x27]) },
        { block: new Uint8Array([0x28]) },
        { block: new Uint8Array([0x29]) },
        { block: new Uint8Array([0x30]) },
        { block: new Uint8Array([0x31]) },
        { block: new Uint8Array([0x32]) },
        { block: new Uint8Array([0x33]) },
        { block: new Uint8Array([0x34]) },
        { block: new Uint8Array([0x35]) },
        { block: new Uint8Array([0x36]) },
        { block: new Uint8Array([0x37]) },
        { block: new Uint8Array([0x38]) },
        { block: new Uint8Array([0x39]) },
        { block: new Uint8Array([0x40]) }

      ], true, undefined)
          .then((data:any[]) => {
            console.log('datas:',data);
            data.forEach((item:any,index:number)=>{
              console.log(this.nfcvService.bytesToString(item.data));
            })
          });

I can see converted string as special character as in below image.

nfcv_garbase_values

Is there any method to read all blocks of tag?

valentiniljaz commented 7 years ago

Hi @SantoshSah,

I've manged to resolve NDEF issues. New version of plugin is already on Github. I've added a configuration to NfcVHandler class so that you can control whether you wish to read NDEF messages or not. Set READ_NDEF flag to false to prevent reading NDEF message, since your tag does not support NDEF messages.

I've also added a new method to NfcvService (for Ionic) so that you can read data within some range:

readRange(startBlock, endBlock, startListen?, device?)

Method will return one array with all read data from block in specified range.

Everything else remains the same, as discussed:

You should readd Cordova plugin as well as NPM dependency.

Now you can read all the data like this:

this.nfcvService.readRange(0x03, 0x40, true)
    .then((data) => {
        console.log('Read:', data);
     });

The result will be an array with all the bytes from blocks 0x03 to 0x40 (including). What those bytes mean is up to you to determine. The link in two post back can help you.

valentiniljaz commented 7 years ago

I have renamed the repository to reflect what it actually does. The repo was moved to new location:

https://github.com/valentiniljaz/cordova-nfcv-plugin

I will maintain this new repository. So, you should readd cordova plugin by using this plugin. It applies to NPM package as well.

SantoshSah commented 7 years ago

Thank you @valentiniljaz for new plugin. I remove old one and setup new one but it is not applying to NPM packages. I added it to NPM package with "npm install". nfcvService .readRange is reading blocks of data but only once. I mean when i move my mobile to tag, it reads blocks for first time only. Then after it is not reading. Only beep sound comes and nothing happens. I debugged in chrome also. There is no error in second time. Just nothing happens. I will debug NfcvHandler in android studio and post you result.

valentiniljaz commented 7 years ago

Hi @SantoshSah,

after readRange is finished you need to dispatch new readRange in order to start reading whenever new tag is discovered.

To simplify the process I've create a helper methods to do just that.

this.nfcvService.waitForTag();
this.nfcvService.onTag(
    (tag) => {
        console.log('Found tag', tag);
        this.nfcvService.readRange(0x03, 0x40, false)
            .then((data) => {
                console.log('Read data:', data);
                this.nfcvService.waitForTag();
            })
            .catch((error) => {
                console.log('Error reading:', error);
                this.nfcvService.waitForTag();
            });
    },
    (error) => {
        console.log('Error on tag', error);
        this.nfcvService.waitForTag();
    });

You need to reinstall NPM package to use the above method.

More info: https://github.com/valentiniljaz/cordova-nfcv-plugin/tree/master/ionic2#nfcvservicewaitfortag

I wasn't able to test these methods properly, so they might not work out of the box. If you'll find some bugs, let me know and I'll fix them.

SantoshSah commented 7 years ago

Thank you @valentiniljaz . It is working now. I am trying to parsing tag data. I will post if i could parse it properly.

SantoshSah commented 7 years ago

Hello @valentiniljaz , i tried to get system info with getSystemInfo() but could not. When i move mobile to sensor, i am getting message ' SYSTEM INFO START ' in console and nothing happens. When i again move mobile to sensor, i am getting message E_SYSTEM_INFO_FAILED | CODE:undefined.

I am calling getSystemInfo() like below:

      this.nfcvService.waitForTag();
      this.nfcvService.onTag(
          (tag) => {
              console.log('Found tag', tag);
                this.nfcvService
                .getSystemInfo(true)
                .then((systemInfo) => {
                    console.log('SystemInfo:', systemInfo); // Check the tag's UID and AFI (optionally)
                     this.nfcvService.waitForTag();   
                })
                .catch((error) => {
                    console.log('Error reading:', error);
                    this.nfcvService.waitForTag();
                });;
          },
          (error) => {
              console.log('Error on tag', error);
              this.nfcvService.waitForTag();
          });

am i doing any mistake while calling getSystemInfo()?

valentiniljaz commented 7 years ago

Hi @SantoshSah,

you have an error in:

this.nfcvService.getSystemInfo(true)

The parameter in call to getSystemInfo should be false in the context of onTag callback.

If you check out NfcvService.ts you will notice, that many methods accept parameter startListen. The parameter tells the methods whether to wait and listen for NfcV Intent or to use already dispatched intent. In order to execute many requests against a tag in just one go, you need to use one Nfcv intent. To use only one intent you must manipulate startListen parameter, which must be true only the first time and false for all subsequent requests.

Your code should be like this:

      this.nfcvService.waitForTag();
      this.nfcvService.onTag(
          (tag) => {
              console.log('Found tag', tag);
                this.nfcvService
                .getSystemInfo(false)
                .then((systemInfo) => {
                    console.log('SystemInfo:', systemInfo); // Check the tag's UID and AFI (optionally)
                     this.nfcvService.waitForTag();   
                })
                .catch((error) => {
                    console.log('Error reading:', error);
                    this.nfcvService.waitForTag();
                });;
          },
          (error) => {
              console.log('Error on tag', error);
              this.nfcvService.waitForTag();
          });

Can I ask you to please submit all future issues in my repo: https://github.com/valentiniljaz/cordova-nfcv-plugin/issues

valentiniljaz commented 7 years ago

If you wanted to read data from device after reading System Info you would do it like this:

this.nfcvService.waitForTag(); // Start listening for new NfcV intent
this.nfcvService.onTag(
    (tag) => {
        console.log('Found tag', tag);
        this.nfcvService.getSystemInfo(false) // Use the same NfcV intent
            .then((systemInfo) => {
                console.log('SystemInfo:', systemInfo); 
                // Check the tag's UID and AFI (optionally)
                // If the tag is the one, then:
                this.nfcvService.readRange(0x03, 0x40, false) // Use the same NfcV intent
                    .then((data) => {
                        console.log('Read data:', data);
                        this.nfcvService.waitForTag(); // Start listening for new NfcV intent
                    })
                    .catch((error) => {
                        console.log('Error reading:', error);
                        this.nfcvService.waitForTag(); // Start listening for new NfcV intent
                    });
            })
            .catch((error) => {
                console.log('Error reading:', error);
                this.nfcvService.waitForTag(); // Start listening for new NfcV intent
            });
    },
    (error) => {
        console.log('Error on tag', error);
        this.nfcvService.waitForTag(); // Start listening for new NfcV intent
    });