Skip to content

Commit

Permalink
Add support for ISO 15693 transceiving on iOS
Browse files Browse the repository at this point in the history
Signed-off-by: Harry Chen <harry-chen@outlook.com>
  • Loading branch information
Harry-Chen committed Oct 31, 2023
1 parent 232cc1f commit 1388333
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 20 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,9 @@
* Add support for reading / write ISO 15693 tags on iOS (merged #117, partially fixes #68)
* Fix compiling issues (#123)
* Other minor fixes (#114, #115)

## 3.4.1

* Fix & split examples to example/ dir
* Publish examples to pub.dev
* Support transceiving of raw ISO15693 commands on iOS
37 changes: 27 additions & 10 deletions ios/Classes/SwiftFlutterNfcKitPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,29 @@ public class SwiftFlutterNfcKitPlugin: NSObject, FlutterPlugin, NFCTagReaderSess
} else {
result(FlutterError(code: "400", message: "No mifare command specified", details: nil))
}
case let .iso15693(tag):
if data != nil {
// format: flag, command, [parameter, data]
tag.sendRequest(requestFlags: data![0], commandCode: data![1], data: data!.advanced(by: 2)) { (result: Result<(NFCISO15693ResponseFlag, Data?), Error>) in
switch (result):
case .failure(error):
result(FlutterError(code: "500", message: "Communication error", details: error.localizedDescription))
case .success((flags, data)):
var response = Data()
response.append(flags.rawValue)
if data != nil {
response.append(data!)
}
if req is String {
result(response.hexEncodedString())
} else {
result(response)
}
}
}
} else {
result(FlutterError(code: "400", message: "No iso15693 command specified", details: nil))
}
default:
result(FlutterError(code: "405", message: "Transceive not supported on this type of card", details: nil))
}
Expand All @@ -163,11 +186,11 @@ public class SwiftFlutterNfcKitPlugin: NSObject, FlutterPlugin, NFCTagReaderSess
let arguments = call.arguments as! [String : Any?]

if case let .iso15693(tag) = tag {
let rawFlags = (arguments["iso15693Flag"] as? UInt8) ?? 0
let rawFlags = (arguments["iso15693Flags"] as? UInt8) ?? 0
let extendedMode = (arguments["iso15693ExtendedMode"] as? Bool) ?? false
let handler = { (dataBlock: Data, error: Error?) in
if let error = error {
result(self.wrapFlutterError(error))
result(FlutterError(code: "500", message: "Communication error", details: error.localizedDescription))
} else {
result(dataBlock)
}
Expand All @@ -187,11 +210,11 @@ public class SwiftFlutterNfcKitPlugin: NSObject, FlutterPlugin, NFCTagReaderSess
let data = (arguments["data"] as! FlutterStandardTypedData).data

if case let .iso15693(tag) = tag {
let rawFlags = (arguments["iso15693Flag"] as? UInt8) ?? 0
let rawFlags = (arguments["iso15693Flags"] as? UInt8) ?? 0
let extendedMode = (arguments["iso15693ExtendedMode"] as? Bool) ?? false
let handler = { (error: Error?) in
if let error = error {
result(self.wrapFlutterError(error))
result(FlutterError(code: "500", message: "Communication error", details: error.localizedDescription))
} else {
result(nil)
}
Expand Down Expand Up @@ -426,12 +449,6 @@ public class SwiftFlutterNfcKitPlugin: NSObject, FlutterPlugin, NFCTagReaderSess
tag = nil
}

func wrapFlutterError(_ arg: Error) -> FlutterError {
return FlutterError(code: "\((arg as NSError).code)",
message: arg.localizedDescription,
details: nil)
}

// from NFCTagReaderSessionDelegate
public func tagReaderSession(_ session: NFCTagReaderSession, didDetect tags: [NFCTag]) {
if tags.count > 1 {
Expand Down
20 changes: 10 additions & 10 deletions lib/flutter_nfc_kit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ extension NDEFRecordConvert on ndef.NDEFRecord {
}

/// Request flag for ISO 15693 Tags
class Iso15693RequestFlag {
class Iso15693RequestFlags {
/// bit 1
bool dualSubCarriers;

Expand Down Expand Up @@ -243,7 +243,7 @@ class Iso15693RequestFlag {
return result as Uint8;
}

Iso15693RequestFlag(
Iso15693RequestFlags(
{this.dualSubCarriers = false,
this.highDataRate = false,
this.inventory = false,
Expand All @@ -254,9 +254,9 @@ class Iso15693RequestFlag {
this.commandSpecificBit8 = false});

/// decode bits from one byte as specified in ISO15693-3
factory Iso15693RequestFlag.fromRaw(Uint8 raw) {
factory Iso15693RequestFlags.fromRaw(Uint8 raw) {
var r = raw as int;
var f = Iso15693RequestFlag(
var f = Iso15693RequestFlags(
dualSubCarriers: (r & 0x01) != 0,
highDataRate: (r & 0x02) != 0,
inventory: (r & 0x04) != 0,
Expand Down Expand Up @@ -465,12 +465,12 @@ class FlutterNfcKit {
/// For MIFARE Ultralight tags, four consecutive pages will be read.
/// Returns data in [Uint8List].
static Future<Uint8List> readBlock(int index,
{Iso15693RequestFlag? iso15693Flag,
{Iso15693RequestFlags? iso15693Flags,
bool iso15693ExtendedMode = false}) async {
var flag = iso15693Flag ?? Iso15693RequestFlag();
var flags = iso15693Flags ?? Iso15693RequestFlags();
return await _channel.invokeMethod('readBlock', {
'index': index,
'iso15693Flag': flag.encode(),
'iso15693Flags': flags.encode(),
'iso15693ExtendedMode': iso15693ExtendedMode,
});
}
Expand All @@ -484,14 +484,14 @@ class FlutterNfcKit {
/// [index] refers to the block / page index.
/// For MIFARE Classic tags, you must first authenticate against the corresponding sector.
static Future<void> writeBlock<T>(int index, T data,
{Iso15693RequestFlag? iso15693Flag,
{Iso15693RequestFlags? iso15693Flags,
bool iso15693ExtendedMode = false}) async {
assert(T is String || T is Uint8List);
var flag = iso15693Flag ?? Iso15693RequestFlag();
var flags = iso15693Flags ?? Iso15693RequestFlags();
await _channel.invokeMethod('writeBlock', {
'index': index,
'data': data,
'iso15693Flag': flag.encode(),
'iso15693Flags': flags.encode(),
'iso15693ExtendedMode': iso15693ExtendedMode,
});
}
Expand Down

0 comments on commit 1388333

Please sign in to comment.