Coder Social home page Coder Social logo

nfcpairingdemo's Introduction

If you clone this repository, just run

npm install
ionic cordova run android

Creating an IoTize NFC Pairing App with Ionic4 03/04/19

Get latest versions of node and npm

(Node Download Page)[https://nodejs.org/en/download/]

Create the Ionic App

Install / Update ionic

npm i -g ionic@latest

Create an Ionic project from blank template

ionic start nfcPairing blank

You don't have to connect to AppFlow when prompted.

Run a serve to check the proper creation of the Ionic App

ionic serve

Add IoTize dependencies

Add device client library

npm install @iotize/device-client.js --save

Add cordova BLE and NFC IoTize plugins

ionic cordova plugin add @iotize/cordova-plugin-iotize-ble
ionic cordova plugin add @iotize/device-com-nfc.cordova

Add ionic-native NFC service

npm i @ionic-native/nfc

And register it as a provider in app.module.ts

Create services

ionic generate service nfc
ionic generate service device

modify nfc.service.ts

import { Injectable } from '@angular/core';
import { NFC, NdefEvent } from '@ionic-native/nfc/ngx'

@Injectable({
  providedIn: 'root'
})
export class NfcService {

  public lastTagRead = {
    appName: "",
    macAddress: ""
  };

  constructor(public nfc: NFC) { }

  listenNFC() {
    this.nfc.addNdefListener(() => {
      console.log('NFC listener ON')
    },
      (error) => {
        console.error('NFC listener didn\'t start: ', error)
      }).subscribe(event => {
        console.log('NDEF Event')
        this.onDiscoveredTap(event);
      });
  }

  onDiscoveredTap(event: NdefEvent) {
    let message = event.tag.ndefMessage;
    this.lastTagRead.appName = String.fromCharCode(...message[3].payload);
    this.lastTagRead.macAddress = this.convertBytesToBLEAddress(message[2].payload);
  }

  convertBytesToBLEAddress(bytes: number[]): string {
    return bytes.slice(1)
                .map(byte => {
                  if (byte < 0) {
                    byte += 256;
                  }
                  return byte.toString(16).toUpperCase();
                })
                .reverse()
                .join(':')
  }
}

Update home page

home.page.ts

import { Component, OnInit } from '@angular/core';
import { NfcService } from '../nfc.service';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {

  constructor(public nfcService: NfcService) {}

  ngOnInit() {
    this.nfcService.listenNFC();
  }
}

home.page.html

<ion-header>
  <ion-toolbar>
    <ion-title>
      NFC Pairing Demo
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <div class="ion-padding">
    <p>Tag's AppName: {{nfcService.lastTagRead.appName}}</p>
    <p>Tag's mac Address: {{nfcService.lastTagRead.macAddress}}</p>
  </div>
</ion-content>

Test NFC Reading

Launch app

ionic cordova run android

And tap and IoTize Tag. It should display its appName and BLE mac Address

Add NFC to BLE Pairing

device.service.ts

import { Injectable } from '@angular/core';
import { ComProtocol } from '@iotize/device-client.js/protocol/api';
import { BLEComProtocol } from 'plugins/cordova-plugin-iotize-ble/src/www';
import { NFCComProtocol } from 'plugins/cordova-plugin-iotize-device-com-nfc/src/www';
import { Tap, SessionState } from '@iotize/device-client.js/device';

@Injectable({
  providedIn: 'root'
})
export class DeviceService {

  isReady = false;
  device: Tap;
  connectionPromise = null;
  nfcSessionStateString = "";
  bleSessionStateString = "";

  constructor() { }

  async init(protocol: ComProtocol) {
    this.isReady = false;
    try {
      this.device = Tap.create();
      console.log('device created');
      this.connectionPromise = this.connect(protocol);
      console.log('waiting for connection promise');
      await this.connectionPromise;
      console.log(await this.getSerialNumber());
      this.isReady = true;
    } catch (error) {
      console.error('init failed');
      console.error(error);
      throw new Error('Connection Failed: ' + (error.message? error.message : error));
    }
  }

  async NFCLoginAndBLEPairing(deviceAddress: string){

    try {
      //start a communication session in NFC
      await this.init(new NFCComProtocol());
      
      //enable NFC auto login
      await this.device.encryption(true);
      
      //check the user login
      let sessionState: SessionState = await this.device.refreshSessionState()
      this.nfcSessionStateString =  JSON.stringify(sessionState);
      console.log(`NFCLoginAndBLEPairing in NFC:  ` + this.nfcSessionStateString);
      
      //connect to the device in BLE
      let bleCom : ComProtocol= new BLEComProtocol(deviceAddress);

      //start the BLE communication with the device
      await this.device.useComProtocol(bleCom);
      await this.device.connect();
      
      //check the connection
      sessionState = await this.device.refreshSessionState();
      this.bleSessionStateString = JSON.stringify(sessionState);
      console.log(`NFCLoginAndBLEPairing in BLE:  `+ this.bleSessionStateString);
    } catch (err) {
    console.error("Can't connect to TAP, try again" + JSON.stringify(err));
    console.error(err);
    }
   
  }

  connect(protocol: ComProtocol): Promise<void> {
    return this.device.connect(protocol);
  }

  async getSerialNumber() {
    return (await this.device.service.device.getSerialNumber()).body();
  }
}

update nfc.service.ts

constructor(public nfc: NFC,
            public deviceService: DeviceService) { }

onDiscoveredTap(event: NdefEvent) {
let message = event.tag.ndefMessage;
this.lastTagRead.appName = String.fromCharCode(...message[3].payload);
this.lastTagRead.macAddress = this.convertBytesToBLEAddress(message[2].payload);

this.deviceService.NFCLoginAndBLEPairing(this.lastTagRead.macAddress);
}

whole nfc.service.ts file:

import { Injectable } from '@angular/core';
import { NFC, NdefEvent } from '@ionic-native/nfc/ngx'
import { DeviceService } from './device.service';

@Injectable({
  providedIn: 'root'
})
export class NfcService {

  public lastTagRead = {
    appName: "",
    macAddress: ""
  };

  constructor(public nfc: NFC,
              public deviceService: DeviceService) { }

  listenNFC() {
    this.nfc.addNdefListener(() => {
      console.log('NFC listener ON')
    },
      (error) => {
        console.error('NFC listener didn\'t start: ', error)
      }).subscribe(event => {
        console.log('NDEF Event')
        this.onDiscoveredTap(event);
      });
  }

  onDiscoveredTap(event: NdefEvent) {
    let message = event.tag.ndefMessage;
    this.lastTagRead.appName = String.fromCharCode(...message[3].payload);
    this.lastTagRead.macAddress = this.convertBytesToBLEAddress(message[2].payload);

    this.deviceService.NFCLoginAndBLEPairing(this.lastTagRead.macAddress);
  }

  convertBytesToBLEAddress(bytes: number[]): string {
    return bytes.slice(1)
                .map(byte => {
                  if (byte < 0) {
                    byte += 256;
                  }
                  let byteString = '0' + byte.toString(16).toUpperCase();
                  byteString = byteString.slice(-2);
                  return byteString;
                })
                .reverse()
                .join(':')
  }
}

Update view to add session states:

home.page.ts

import { Component, OnInit } from '@angular/core';
import { NfcService } from '../nfc.service';
import { DeviceService } from '../device.service';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {

  constructor(public nfcService: NfcService,
              public deviceService: DeviceService) {}

  ngOnInit() {
    this.nfcService.listenNFC();
  }

}

and html view home.page.html

<ion-header>
  <ion-toolbar>
    <ion-title>
      NFC Pairing Demo
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <div class="ion-padding">
    <p>Tag's AppName: {{nfcService.lastTagRead.appName}}</p>
    <p>Tag's mac Address: {{nfcService.lastTagRead.macAddress}}</p>
    <p>NFC Session State: {{deviceService.nfcSessionStateString}}</p>
    <p>BLE Session State: {{deviceService.bleSessionStateString}}</p>
    <p *ngIf="deviceService.bleSessionStateString != '' ">Tap is ready to use</p>
  </div>
</ion-content>

Test NFC Login and BLE Pairing

Run the app again:

ionic cordova run android

And try to tap to your device. If the connection and login succeed, you should see the message 'Tap is ready to use', and see the logged profile under NFC Session State and BLE Session State.

nfcpairingdemo's People

Watchers

James Cloos avatar Stephane Léonard avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.