@iotize/device-com-nfc.cordova 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/LICENSE +31 -0
  2. package/README.md +673 -0
  3. package/bundles/iotize-device-com-nfc.cordova.umd.js +469 -0
  4. package/bundles/iotize-device-com-nfc.cordova.umd.js.map +1 -0
  5. package/esm2015/iotize-device-com-nfc.cordova.js +5 -0
  6. package/esm2015/iotize-device-com-nfc.cordova.js.map +1 -0
  7. package/esm2015/iotize-device-com-nfc.cordova.metadata.json +1 -0
  8. package/esm2015/iotize-device-com-nfc.cordova.ngsummary.json +1 -0
  9. package/esm2015/public_api.js +2 -0
  10. package/esm2015/public_api.js.map +1 -0
  11. package/esm2015/public_api.metadata.json +1 -0
  12. package/esm2015/public_api.ngsummary.json +1 -0
  13. package/esm2015/www/cordova-interface.js +2 -0
  14. package/esm2015/www/cordova-interface.js.map +1 -0
  15. package/esm2015/www/cordova-interface.metadata.json +1 -0
  16. package/esm2015/www/cordova-interface.ngsummary.json +1 -0
  17. package/esm2015/www/errors.js +28 -0
  18. package/esm2015/www/errors.js.map +1 -0
  19. package/esm2015/www/errors.metadata.json +1 -0
  20. package/esm2015/www/errors.ngsummary.json +1 -0
  21. package/esm2015/www/index.js +5 -0
  22. package/esm2015/www/index.js.map +1 -0
  23. package/esm2015/www/index.metadata.json +1 -0
  24. package/esm2015/www/index.ngsummary.json +1 -0
  25. package/esm2015/www/logger.js +3 -0
  26. package/esm2015/www/logger.js.map +1 -0
  27. package/esm2015/www/logger.metadata.json +1 -0
  28. package/esm2015/www/logger.ngsummary.json +1 -0
  29. package/esm2015/www/nfc-com-protocol.js +109 -0
  30. package/esm2015/www/nfc-com-protocol.js.map +1 -0
  31. package/esm2015/www/nfc-com-protocol.metadata.json +1 -0
  32. package/esm2015/www/nfc-com-protocol.ngsummary.json +1 -0
  33. package/esm2015/www/tap-ndef/definitions.js +2 -0
  34. package/esm2015/www/tap-ndef/definitions.js.map +1 -0
  35. package/esm2015/www/tap-ndef/definitions.metadata.json +1 -0
  36. package/esm2015/www/tap-ndef/definitions.ngsummary.json +1 -0
  37. package/esm2015/www/tap-ndef/index.js +3 -0
  38. package/esm2015/www/tap-ndef/index.js.map +1 -0
  39. package/esm2015/www/tap-ndef/index.metadata.json +1 -0
  40. package/esm2015/www/tap-ndef/index.ngsummary.json +1 -0
  41. package/esm2015/www/tap-ndef/parse-ndef-message.js +57 -0
  42. package/esm2015/www/tap-ndef/parse-ndef-message.js.map +1 -0
  43. package/esm2015/www/tap-ndef/parse-ndef-message.metadata.json +1 -0
  44. package/esm2015/www/tap-ndef/parse-ndef-message.ngsummary.json +1 -0
  45. package/fesm2015/iotize-device-com-nfc.cordova.js +196 -0
  46. package/fesm2015/iotize-device-com-nfc.cordova.js.map +1 -0
  47. package/iotize-device-com-nfc.cordova.d.ts +4 -0
  48. package/iotize-device-com-nfc.cordova.metadata.json +1 -0
  49. package/package.json +54 -0
  50. package/plugin.xml +97 -0
  51. package/public_api.d.ts +1 -0
  52. package/src/android/build.gradle +38 -0
  53. package/src/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  54. package/src/android/gradle/wrapper/gradle-wrapper.properties +6 -0
  55. package/src/android/gradlew +172 -0
  56. package/src/android/gradlew.bat +84 -0
  57. package/src/android/local.properties +8 -0
  58. package/src/android/src/com/chariotsolutions/nfc/plugin/JSONBuilder.java +60 -0
  59. package/src/android/src/com/chariotsolutions/nfc/plugin/NfcPlugin.java +1192 -0
  60. package/src/android/src/com/chariotsolutions/nfc/plugin/NfcPluginError.java +15 -0
  61. package/src/android/src/com/chariotsolutions/nfc/plugin/PluginResponse.java +85 -0
  62. package/src/android/src/com/chariotsolutions/nfc/plugin/Util.java +140 -0
  63. package/src/ios/AppDelegate+NFC.swift +51 -0
  64. package/src/ios/ISO15Reader.swift +376 -0
  65. package/src/ios/NFCNDEFDelegate.swift +78 -0
  66. package/src/ios/NFCPlugin-Bridging-Header.h +7 -0
  67. package/src/ios/NFCTapPlugin.swift +251 -0
  68. package/www/cordova-interface.d.ts +18 -0
  69. package/www/errors.d.ts +16 -0
  70. package/www/index.d.ts +4 -0
  71. package/www/logger.d.ts +2 -0
  72. package/www/nfc-com-protocol.d.ts +14 -0
  73. package/www/phonegap-nfc.js +885 -0
  74. package/www/tap-ndef/definitions.d.ts +25 -0
  75. package/www/tap-ndef/index.d.ts +2 -0
  76. package/www/tap-ndef/parse-ndef-message.d.ts +6 -0
@@ -0,0 +1,15 @@
1
+ package com.chariotsolutions.nfc.plugin;
2
+
3
+ class NfcPluginError extends Exception {
4
+
5
+ String code;
6
+
7
+ public String getCode() {
8
+ return code;
9
+ }
10
+
11
+ public NfcPluginError(String code, String message, Throwable cause) {
12
+ super(message, cause);
13
+ this.code = code;
14
+ }
15
+ }
@@ -0,0 +1,85 @@
1
+ //
2
+ // Copyright 2018 IoTize SAS Inc. Licensed under the MIT license.
3
+ //
4
+ // PluginResponse.java
5
+ // device-com-ble.cordova BLE Cordova Plugin
6
+ //
7
+ package com.chariotsolutions.nfc.plugin;
8
+
9
+ import com.iotize.android.core.util.Helper;
10
+
11
+ import org.apache.cordova.CallbackContext;
12
+ import org.apache.cordova.PluginResult;
13
+ import org.json.JSONArray;
14
+ import org.json.JSONObject;
15
+
16
+ public class PluginResponse {
17
+
18
+ private static final String TAG = "PluginResponse";
19
+ private final CallbackContext callbackContext;
20
+ private final String action;
21
+
22
+ public PluginResponse(String action, JSONArray args, CallbackContext callbackContext) {
23
+ this.callbackContext = callbackContext;
24
+ this.action = action;
25
+
26
+ }
27
+
28
+ public void newResult(String data) {
29
+ PluginResult result = new PluginResult(
30
+ PluginResult.Status.OK,
31
+ data
32
+ );
33
+ result.setKeepCallback(true);
34
+ this.callbackContext.sendPluginResult(result);
35
+ }
36
+
37
+ public void newResult(JSONObject data) {
38
+ PluginResult result = new PluginResult(
39
+ PluginResult.Status.OK,
40
+ data
41
+ );
42
+ result.setKeepCallback(true);
43
+ this.callbackContext.sendPluginResult(result);
44
+ }
45
+
46
+ public void newResult(NfcPluginError error) {
47
+ this.callbackContext.sendPluginResult(new PluginResult(
48
+ PluginResult.Status.ERROR,
49
+ JSONBuilder.toJSONObject(error)
50
+ ));
51
+ }
52
+
53
+ public void success(JSONObject object) {
54
+ this.callbackContext.success(object);
55
+ }
56
+
57
+ public void success(byte[] response) {
58
+ this.callbackContext.success(Helper.ByteArrayToHexString(response));
59
+ }
60
+
61
+ public void error(NfcPluginError err) {
62
+ JSONObject object = JSONBuilder.toJSONObject(err);
63
+ this.callbackContext.error(object);
64
+ }
65
+
66
+ public void success(boolean isConnected) {
67
+ this.callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, isConnected)); }
68
+
69
+ public void success() {
70
+ this.callbackContext.success();
71
+ }
72
+
73
+ public void error(String message) {
74
+ this.callbackContext.success(message);
75
+ }
76
+
77
+ public void success(String msg) {
78
+ this.callbackContext.success(msg);
79
+ }
80
+
81
+ public CallbackContext getCallbackContext() {
82
+ return callbackContext;
83
+ }
84
+
85
+ }
@@ -0,0 +1,140 @@
1
+ package com.chariotsolutions.nfc.plugin;
2
+
3
+ import android.nfc.NdefMessage;
4
+ import android.nfc.NdefRecord;
5
+ import android.nfc.Tag;
6
+ import android.nfc.tech.Ndef;
7
+ import android.util.Log;
8
+ import org.json.JSONArray;
9
+ import org.json.JSONException;
10
+ import org.json.JSONObject;
11
+
12
+ import java.util.ArrayList;
13
+ import java.util.Arrays;
14
+ import java.util.List;
15
+
16
+ public class Util {
17
+
18
+ static final String TAG = "NfcPlugin";
19
+
20
+ static JSONObject ndefToJSON(Ndef ndef) {
21
+ JSONObject json = new JSONObject();
22
+
23
+ if (ndef != null) {
24
+ try {
25
+
26
+ Tag tag = ndef.getTag();
27
+ // tag is going to be null for NDEF_FORMATABLE until NfcUtil.parseMessage is refactored
28
+ if (tag != null) {
29
+ json.put("id", byteArrayToJSON(tag.getId()));
30
+ json.put("techTypes", new JSONArray(Arrays.asList(tag.getTechList())));
31
+ }
32
+
33
+ json.put("type", translateType(ndef.getType()));
34
+ json.put("maxSize", ndef.getMaxSize());
35
+ json.put("isWritable", ndef.isWritable());
36
+ json.put("ndefMessage", messageToJSON(ndef.getCachedNdefMessage()));
37
+ // Workaround for bug in ICS (Android 4.0 and 4.0.1) where
38
+ // mTag.getTagService(); of the Ndef object sometimes returns null
39
+ // see http://issues.mroland.at/index.php?do=details&task_id=47
40
+ try {
41
+ json.put("canMakeReadOnly", ndef.canMakeReadOnly());
42
+ } catch (NullPointerException e) {
43
+ json.put("canMakeReadOnly", JSONObject.NULL);
44
+ }
45
+ } catch (JSONException e) {
46
+ Log.e(TAG, "Failed to convert ndef into json: " + ndef.toString(), e);
47
+ }
48
+ }
49
+ return json;
50
+ }
51
+
52
+ static JSONObject tagToJSON(Tag tag) {
53
+ JSONObject json = new JSONObject();
54
+
55
+ if (tag != null) {
56
+ try {
57
+ json.put("id", byteArrayToJSON(tag.getId()));
58
+ json.put("techTypes", new JSONArray(Arrays.asList(tag.getTechList())));
59
+ } catch (JSONException e) {
60
+ Log.e(TAG, "Failed to convert tag into json: " + tag.toString(), e);
61
+ }
62
+ }
63
+ return json;
64
+ }
65
+
66
+ static String translateType(String type) {
67
+ String translation;
68
+ if (type.equals(Ndef.NFC_FORUM_TYPE_1)) {
69
+ translation = "NFC Forum Type 1";
70
+ } else if (type.equals(Ndef.NFC_FORUM_TYPE_2)) {
71
+ translation = "NFC Forum Type 2";
72
+ } else if (type.equals(Ndef.NFC_FORUM_TYPE_3)) {
73
+ translation = "NFC Forum Type 3";
74
+ } else if (type.equals(Ndef.NFC_FORUM_TYPE_4)) {
75
+ translation = "NFC Forum Type 4";
76
+ } else {
77
+ translation = type;
78
+ }
79
+ return translation;
80
+ }
81
+
82
+ static NdefRecord[] jsonToNdefRecords(String ndefMessageAsJSON) throws JSONException {
83
+ JSONArray jsonRecords = new JSONArray(ndefMessageAsJSON);
84
+ NdefRecord[] records = new NdefRecord[jsonRecords.length()];
85
+ for (int i = 0; i < jsonRecords.length(); i++) {
86
+ JSONObject record = jsonRecords.getJSONObject(i);
87
+ byte tnf = (byte) record.getInt("tnf");
88
+ byte[] type = jsonToByteArray(record.getJSONArray("type"));
89
+ byte[] id = jsonToByteArray(record.getJSONArray("id"));
90
+ byte[] payload = jsonToByteArray(record.getJSONArray("payload"));
91
+ records[i] = new NdefRecord(tnf, type, id, payload);
92
+ }
93
+ return records;
94
+ }
95
+
96
+ static JSONArray byteArrayToJSON(byte[] bytes) {
97
+ JSONArray json = new JSONArray();
98
+ for (byte aByte : bytes) {
99
+ json.put(aByte);
100
+ }
101
+ return json;
102
+ }
103
+
104
+ static byte[] jsonToByteArray(JSONArray json) throws JSONException {
105
+ byte[] b = new byte[json.length()];
106
+ for (int i = 0; i < json.length(); i++) {
107
+ b[i] = (byte) json.getInt(i);
108
+ }
109
+ return b;
110
+ }
111
+
112
+ static JSONArray messageToJSON(NdefMessage message) {
113
+ if (message == null) {
114
+ return null;
115
+ }
116
+
117
+ List<JSONObject> list = new ArrayList<JSONObject>();
118
+
119
+ for (NdefRecord ndefRecord : message.getRecords()) {
120
+ list.add(recordToJSON(ndefRecord));
121
+ }
122
+
123
+ return new JSONArray(list);
124
+ }
125
+
126
+ static JSONObject recordToJSON(NdefRecord record) {
127
+ JSONObject json = new JSONObject();
128
+ try {
129
+ json.put("tnf", record.getTnf());
130
+ json.put("type", byteArrayToJSON(record.getType()));
131
+ json.put("id", byteArrayToJSON(record.getId()));
132
+ json.put("payload", byteArrayToJSON(record.getPayload()));
133
+ } catch (JSONException e) {
134
+ //Not sure why this would happen, documentation is unclear.
135
+ Log.e(TAG, "Failed to convert ndef record into json: " + record.toString(), e);
136
+ }
137
+ return json;
138
+ }
139
+
140
+ }
@@ -0,0 +1,51 @@
1
+ //
2
+ // AppDelegate+NFC.swift
3
+ // PhoneGap NFC - Cordova Plugin
4
+ //
5
+ // Copyright © 2019 dev@iotize.com. All rights reserved.
6
+
7
+ import CoreNFC
8
+
9
+ extension AppDelegate {
10
+
11
+ override open func application(_ application: UIApplication,
12
+ continue userActivity: NSUserActivity,
13
+ restorationHandler: @escaping ([Any]?) -> Void) -> Bool {
14
+
15
+ NSLog("Extending UIApplicationDelegate")
16
+
17
+ guard userActivity.activityType == NSUserActivityTypeBrowsingWeb else {
18
+ return false
19
+ }
20
+
21
+ // Confirm that the NSUserActivity object contains a valid NDEF message.
22
+ if #available(iOS 12.0, *) {
23
+ let ndefMessage = userActivity.ndefMessagePayload
24
+ guard ndefMessage.records.count > 0,
25
+ ndefMessage.records[0].typeNameFormat != .empty else {
26
+ return false
27
+ }
28
+ let nfcPluginInstance: NfcPlugin = self.viewController.getCommandInstance("NfcPlugin") as! NfcPlugin
29
+ var resolved: Bool = false;
30
+ NSLog(nfcPluginInstance.debugDescription);
31
+
32
+ DispatchQueue.global().async {
33
+ let waitingTimeInterval: Double = 0.1;
34
+ print("<NFC> Did start timeout")
35
+ for _ in 1...2000 { // 5?s timeout
36
+ if ( !nfcPluginInstance.isListeningNDEF ) {
37
+ Thread.sleep(forTimeInterval: waitingTimeInterval)
38
+ } else {
39
+ let jsonDictionary = ndefMessage.ndefMessageToJSON()
40
+ nfcPluginInstance.sendThroughChannel(jsonDictionary: jsonDictionary)
41
+ resolved = true
42
+ return
43
+ }
44
+ }
45
+ }
46
+ return resolved
47
+ } else {
48
+ return false
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,376 @@
1
+ //
2
+ // IOS15Reader.swift
3
+ // NFC
4
+ //
5
+ // Created by dev@iotize.com on 23/07/2019.
6
+ // Copyright © 2019 dev@iotize.com. All rights reserved.
7
+ //
8
+
9
+ import UIKit
10
+ import CoreNFC
11
+
12
+
13
+ public extension String {
14
+
15
+ func dataFromHexString() -> Data {
16
+ var bytes = [UInt8]()
17
+ for i in 0..<(count/2) {
18
+ let range = index(self.startIndex, offsetBy: 2*i)..<index(self.startIndex, offsetBy: 2*i+2)
19
+ let stringBytes = self[range]
20
+ let byte = strtol((stringBytes as NSString).utf8String, nil, 16)
21
+ bytes.append(UInt8(byte))
22
+ }
23
+ return Data(bytes: UnsafePointer<UInt8>(bytes), count:bytes.count)
24
+ }
25
+
26
+ }
27
+
28
+ extension Data {
29
+
30
+ func hexEncodedString() -> String {
31
+ let format = "%02hhX"
32
+ return map { String(format: format, $0) }.joined()
33
+ }
34
+ }
35
+
36
+ @available(iOS 13.0, *)
37
+ class ST25DVReader : NSObject {
38
+
39
+ typealias Completion = (Error?) -> ()
40
+
41
+ private var comSession: NFCTagReaderSession?
42
+ private var tag: NFCISO15693Tag?
43
+
44
+ static var MB_CTRL_DYN : UInt8 = 0x0D
45
+
46
+ private var connectionCompleted : Completion?
47
+
48
+ /*ST25 commands*/
49
+ static var ISO15693_CUSTOM_ST25DV_CMD_WRITE_MB_MSG : UInt8 = 0xAA;
50
+ static var ISO15693_CUSTOM_ST25DV_CMD_READ_MB_MSG_LENGTH : Int = 0xAB;
51
+ static var ISO15693_CUSTOM_ST25DV_CMD_READ_MB_MSG = 0xAC;
52
+
53
+ static var ISO15693_CUSTOM_ST_CMD_READ_DYN_CONFIG : Int = 0xAD;
54
+ static var ISO15693_CUSTOM_ST_CMD_WRITE_DYN_CONFIG : Int = 0xAE;
55
+
56
+ static var DELAY : UInt32 = 1000; // timeout resolution in millionths of second
57
+ static var NB_MAX_RETRY : Int = 50;
58
+
59
+ override init() {
60
+ super.init()
61
+ }
62
+
63
+ func initSession( alertMessage: String, completed: @escaping (Error?)->() ) {
64
+
65
+ guard NFCNDEFReaderSession.readingAvailable else {
66
+ completed( NFCReaderError( NFCReaderError.readerErrorUnsupportedFeature ))
67
+ return
68
+ }
69
+
70
+ connectionCompleted = completed
71
+
72
+ if NFCNDEFReaderSession.readingAvailable {
73
+ comSession = NFCTagReaderSession(pollingOption: [.iso15693], delegate: self, queue: nil)
74
+ comSession?.alertMessage = alertMessage
75
+ comSession?.begin()
76
+ }
77
+ }
78
+
79
+ func invalidateSession( message :String) {
80
+ comSession?.alertMessage = message
81
+ comSession?.invalidate()
82
+ }
83
+
84
+ func send( request: String, completed: @escaping (Data?,Error?)->() ) {
85
+
86
+ guard NFCNDEFReaderSession.readingAvailable else {
87
+ let error = NFCReaderError( NFCReaderError.readerErrorUnsupportedFeature )
88
+ invalidateSession( message: error.localizedDescription )
89
+ completed( nil, error )
90
+ return
91
+ }
92
+
93
+ guard comSession != nil && comSession!.isReady else {
94
+ let error = NFCReaderError( NFCReaderError.readerTransceiveErrorTagNotConnected )
95
+ invalidateSession( message: error.localizedDescription )
96
+ completed( nil, error )
97
+ return
98
+ }
99
+
100
+ let requestData : Data = request.dataFromHexString()
101
+ print( "Transceive - \(requestData.hexEncodedString())" )
102
+ transceive(request: requestData,
103
+ completed: { ( response: Data?, error: Error?) in
104
+ if nil != error {
105
+ self.invalidateSession( message: error?.localizedDescription ?? "Error" )
106
+ completed( nil, error )
107
+ return
108
+ }
109
+ else {
110
+ completed( response, nil)
111
+ return
112
+ }
113
+ })
114
+ }
115
+
116
+
117
+ }
118
+
119
+ @available(iOS 13.0, *)
120
+ extension ST25DVReader : NFCTagReaderSessionDelegate {
121
+ // MARK: - NFCTagReaderSessionDelegate
122
+ func tagReaderSessionDidBecomeActive(_ session: NFCTagReaderSession) {
123
+ // If necessary, you may perform additional operations on session start.
124
+ // At this point RF polling is enabled.
125
+ print( "tagReaderSessionDidBecomeActive" )
126
+ }
127
+
128
+ func tagReaderSession(_ session: NFCTagReaderSession, didInvalidateWithError error: Error) {
129
+ // If necessary, you may handle the error. Note session is no longer valid.
130
+ // You must create a new session to restart RF polling.
131
+ print( "tagReaderSession:didInvalidateWithError - \(error)" )
132
+ connectionCompleted?(error)
133
+ self.comSession = nil
134
+ }
135
+
136
+ func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
137
+ print( "tagReaderSession:didDectectTag" )
138
+ guard let session = self.comSession else {
139
+ return;
140
+ }
141
+ if tags.count > 1 {
142
+ // Restart polling in 500 milliseconds.
143
+ let retryInterval = DispatchTimeInterval.milliseconds(500)
144
+ session.alertMessage = "More than 1 Tap is detected. Please remove all tags and try again."
145
+ DispatchQueue.global().asyncAfter(deadline: .now() + retryInterval, execute: {
146
+ session.restartPolling()
147
+ })
148
+ return
149
+ }
150
+
151
+ guard let tag = tags.first else {
152
+ return;
153
+ }
154
+
155
+ switch tag {
156
+ case .iso15693(let iso15tag):
157
+ self.tag = iso15tag
158
+ default:
159
+ let error = NFCReaderError( NFCReaderError.ndefReaderSessionErrorTagNotWritable )
160
+ invalidateSession( message: error.localizedDescription )
161
+ connectionCompleted?(error)
162
+ return;
163
+ }
164
+
165
+ // Connect to tag
166
+ session.connect(to: tag) { [weak self] (error: Error?) in
167
+ guard let strongSelf = self else {
168
+ return;
169
+ }
170
+
171
+ if error != nil {
172
+ let error = NFCReaderError( NFCReaderError.readerTransceiveErrorTagNotConnected )
173
+ strongSelf.invalidateSession( message: error.localizedDescription )
174
+ strongSelf.connectionCompleted?(error)
175
+ return
176
+ }
177
+ print( "connected to tag" )
178
+ strongSelf.connectionCompleted?(nil)
179
+ }
180
+ }
181
+ }
182
+
183
+ @available(iOS 13.0, *)
184
+ extension ST25DVReader {
185
+
186
+
187
+
188
+ func transceive(request: Data, completed: @escaping (Data?, Error?)->()){
189
+
190
+
191
+ checkMBEnabled( completed: { ( error: Error?) in
192
+ if nil != error {
193
+ self.invalidateSession( message: error?.localizedDescription ?? "Error" )
194
+ completed( nil, error )
195
+ return
196
+ }
197
+ print( "Com enabled" )
198
+ self.sendRequest( request: request,
199
+ nbTry: ST25DVReader.NB_MAX_RETRY,
200
+ completed: { ( response: Data?, error: Error?) in
201
+ if nil != error {
202
+ self.invalidateSession( message: error?.localizedDescription ?? "Error" )
203
+ completed( nil, error )
204
+ return
205
+ }
206
+ completed(response, nil)
207
+ })
208
+ })
209
+
210
+ }
211
+
212
+ func sendRequest(request: Data, nbTry: Int, completed: @escaping (Data?, Error?)->() ) {
213
+ guard let tag = self.tag else {
214
+ let error = NFCReaderError( NFCReaderError.readerTransceiveErrorTagNotConnected )
215
+ invalidateSession( message: error.localizedDescription )
216
+ completed(nil, error )
217
+ return;
218
+ }
219
+
220
+ if (nbTry <= 0){
221
+ let error = NFCReaderError( NFCReaderError.readerTransceiveErrorRetryExceeded )
222
+ invalidateSession( message: error.localizedDescription )
223
+ completed(nil, error )
224
+ return
225
+ }
226
+
227
+ var parameters = Data( bytes:[request.count - 1], count: 1 )
228
+ parameters.append(request)
229
+ print( "Send - \(parameters.hexEncodedString())" )
230
+ tag.customCommand(requestFlags: [.highDataRate],
231
+ customCommandCode: 0xAA,
232
+ customRequestParameters: parameters,
233
+ completionHandler: { (response: Data?, error: Error?) in
234
+ if nil != error {
235
+ usleep(ST25DVReader.DELAY)
236
+ self.sendRequest( request: request, nbTry: nbTry - 1, completed: completed )
237
+ return
238
+ }
239
+ usleep(ST25DVReader.DELAY * 10) // free ST25DV for SPI
240
+ self.readResponse( nbTry: nbTry , completed: completed)
241
+ })
242
+
243
+ }
244
+
245
+ func readResponse( nbTry: Int, completed: @escaping (Data?, Error?)->() ) {
246
+
247
+ guard let tag = self.tag else {
248
+ let error = NFCReaderError( NFCReaderError.readerTransceiveErrorTagNotConnected )
249
+ invalidateSession( message: error.localizedDescription )
250
+ completed( nil, error )
251
+ return;
252
+ }
253
+
254
+ //We have tried enough timeout and return
255
+ if (nbTry <= 0){
256
+ print( "Read Abandonned" )
257
+ let error = NFCReaderError( NFCReaderError.readerTransceiveErrorRetryExceeded )
258
+ invalidateSession( message: error.localizedDescription )
259
+ completed( nil, error )
260
+ return;
261
+ }
262
+
263
+ print( "Read \(nbTry)" )
264
+
265
+ //check Mailbox
266
+ tag.customCommand(requestFlags: [.highDataRate],
267
+ customCommandCode: 0xAD,
268
+ customRequestParameters: Data(bytes: [UInt8(0x0D)], count: 1),
269
+ completionHandler: { (response: Data, error: Error?) in
270
+ if nil != error {
271
+ usleep(ST25DVReader.DELAY)
272
+ self.readResponse( nbTry: nbTry - 1, completed: completed )
273
+ return
274
+ }
275
+
276
+ print( "Read resonse" )
277
+
278
+ if ( (response.count >= 1) && ( (response[0]&0x1) != 0 ) && ( (response[0]&0x2) != 0 )){
279
+
280
+ print( "Read Value - \(Data(response).hexEncodedString())" )
281
+ tag.customCommand(requestFlags: [.highDataRate],
282
+ customCommandCode: 0xAC,
283
+ customRequestParameters: Data(bytes: [UInt8(0), UInt8(0)], count: 2),
284
+ completionHandler: { (response: Data, error: Error?) in
285
+ if nil != error {
286
+ self.invalidateSession( message: error?.localizedDescription ?? "Error" )
287
+ completed( nil, error )
288
+ return
289
+ }
290
+ print( "got Value - \(Data(response).hexEncodedString())" )
291
+ completed(response,nil)
292
+ return
293
+ })
294
+
295
+ }
296
+ else {
297
+ usleep(ST25DVReader.DELAY)
298
+ self.readResponse( nbTry: nbTry - 1, completed: completed )
299
+ }
300
+
301
+ })
302
+
303
+
304
+ }
305
+
306
+ func checkMBEnabled(completed: @escaping (Error?)->()) {
307
+ guard let tag = self.tag else {
308
+ let error = NFCReaderError( NFCReaderError.readerTransceiveErrorTagNotConnected )
309
+ invalidateSession( message: error.localizedDescription )
310
+ completed( error )
311
+ return;
312
+ }
313
+
314
+ //Read Config
315
+ tag.customCommand(requestFlags: [.highDataRate],
316
+ customCommandCode: 0xAD,
317
+ customRequestParameters: Data(bytes: [UInt8(0x0D)], count: 1),
318
+ completionHandler: { (response: Data, error: Error?) in
319
+ if nil != error {
320
+ self.invalidateSession( message: error?.localizedDescription ?? "Error" )
321
+ completed(error)
322
+ return
323
+ }
324
+
325
+ if ( response.count == 0) {
326
+ let error = NFCReaderError( NFCReaderError.readerTransceiveErrorTagResponseError )
327
+ self.invalidateSession( message: error.localizedDescription )
328
+ completed( error )
329
+ return
330
+ }
331
+
332
+
333
+ let current = response[0];
334
+
335
+ //We should reset mailbox
336
+ if ( (current != 0x41) && (current != 0x81) ) {
337
+
338
+ //disable
339
+ tag.customCommand(requestFlags: [.highDataRate],
340
+ customCommandCode: 0xAE,
341
+ customRequestParameters: Data(bytes: [UInt8(0x0D), UInt8(0x00)], count: 2),
342
+ completionHandler: { (response: Data, error: Error?) in
343
+ if nil != error {
344
+ self.invalidateSession( message: error?.localizedDescription ?? "Error" )
345
+ completed( error )
346
+ return
347
+ }
348
+
349
+ //enable
350
+ tag.customCommand(requestFlags: [.highDataRate],
351
+ customCommandCode: 0xAE,
352
+ customRequestParameters: Data(bytes: [UInt8(0x0D), UInt8(0x01)], count: 2),
353
+ completionHandler: { (response: Data, error: Error?) in
354
+ if nil != error {
355
+ self.invalidateSession( message: error?.localizedDescription ?? "Error" )
356
+ completed( error )
357
+ return
358
+ }
359
+
360
+ completed(nil)
361
+ return
362
+
363
+ })
364
+ })
365
+ }
366
+ //We are ok to go
367
+ else
368
+ {
369
+ completed(nil)
370
+ return
371
+ }
372
+
373
+ })
374
+ }
375
+ }
376
+