Members
(async) driverName
The name of this driver
Methods
(async) cancel() → {Promise.<undefined>}
Cancel any in progress read or write task
(async) deviceInfo() → {Promise.<module:RFID~RFIDDeviceInfo>}
Retrieve the device information about the attached RFID reader/writer peripheral.
Throws:
-
-
-
AgentTimedOutException
-
-
Example
// Query Device Information
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => agent.RFID.deviceInfo())
.then(deviceInfo => console.log(deviceInfo))
.catch(ex => {
console.error('Failed to query card state');
console.error(ex);
});
// This should print something similair to this:
{
"manufacturer": "Syncotek",
"model": "SK288-K001",
"vendorId": 9176,
"productId": 645,
"serial": "ABC1234K001",
"capabilities": [
"LOCK",
"UNLOCK",
"LED-RED",
"LED-BLUE",
"SENSE",
"MIFARE-CLASSIC",
"MIFARE-PLUS",
"MIFARE-DESFIRE"
]
}
(async) getDeviceInfo()
Retrieve information about the device, driver and its state.
(async) isAttached() → {Promise.<Boolean>}
Is the device physically connected
(async) isCardPresent() → {Promise.<Boolean>}
Is a card present in the device
Throws:
-
-
-
AgentTimedOutException
-
-
Example
// Query Card Present
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => agent.RFID.isCardPresent())
.then(isCardPresent => console.log(
isCardPresent
? 'The card is present'
: 'The card is not present'))
.catch(ex => {
console.error('Failed to query card state');
console.error(ex);
});
(async) isConnected() → {Promise.<Boolean>}
Is the device communication open and connected
(async) isEnabled() → {Promise.<Boolean>}
Is the device enabled
(async) isLocked() → {Promise.<Boolean>}
Is the latch locked
Throws:
-
-
-
AgentTimedOutException
-
-
Example
// Query lock state
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => agent.RFID.isLocked())
.then(isLocked => console.log(
isLocked
? 'The latch is locked'
: 'The latch is not locked'))
.catch(ex => {
console.error('Failed to query lock state');
console.error(ex);
});
(async) ledOff(coloropt) → {Promise.<undefined>}
Toggle the attached peripheral LED to turn off.
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
color |
LEDColor |
<optional> |
0 |
The color of the LED to illuminate. |
Throws:
-
-
-
AgentTimedOutException
-
-
-
Example
// Query Device Information
const RED_LED = 0;
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => agent.RFID.deviceInfo()) // Check if the attached peripheral has a RED LED
.then(deviceInfo => {
if (deviceInfo && deviceInfo.capabilities.includes('LED-RED')) return window.Agent;
throw new Error('RED LED Not Available'); // Will throw an error an exit as we don't have an LED to control
})
.then(agent => agent.RFID.ledOff(RED_LED)) // Turn off the RED LED
.then(() => console.log('RED LED is now off'))
.catch(ex => {
console.error('Failed to set LED state');
console.error(ex);
});
(async) ledOn(coloropt, flashingopt) → {Promise.<undefined>}
Toggle the attached peripheral LED to turn on and optionally flash.
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
color |
LEDColor |
<optional> |
0 |
The color of the LED to illuminate. |
flashing |
Boolean |
<optional> |
false |
If the LED should flash |
Throws:
-
-
-
AgentTimedOutException
-
-
-
Example
// Query Device Information
const RED_LED = 0;
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => agent.RFID.deviceInfo()) // Check if the attached peripheral has a RED LED
.then(deviceInfo => {
if (deviceInfo && deviceInfo.capabilities.includes('LED-RED')) return window.Agent;
throw new Error('RED LED Not Available'); // Will throw an error an exit as we don't have an LED to control
})
.then(agent => agent.RFID.ledOn(RED_LED, true)) // Turn on the RED LED and flash the LED
.then(() => console.log('RED LED is now on and flashing'))
.catch(ex => {
console.error('Failed to set LED state');
console.error(ex);
});
(async) lock() → {Promise.<undefined>}
Lock the latch
Throws:
-
-
-
-
AgentTimedOutException
-
-
-
Example
// Lock the latch
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => agent.RFID.lock())
.then(() => console.log('Locked'))
.catch(ex => {
console.error('Failed to Lock');
console.error(ex);
});
(async) queryCard() → {Promise.<module:RFID~CardQueryResult>}
Query for details about the card, will return card type, uid and capacity
Example
// Example for Querying card
const queryCard = async() => {
console.log("QUERY CARD: Insert");
const result = await agent.RFID.queryCard();
console.log(result);
}
// Console Output: {
type: 'Mifare S50 1K Card',
uid: '02b921de',
capacity: 1024
}
(async) read(configopt, keysopt, outEncodingopt, optionsopt) → {Promise.<module:RFID~ReadResult>}
Read data from the RFID Card
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
config |
ReadConfiguration |
<optional> |
defaultReadConfig |
The configuration of the read task defines which sectors and blocks to read |
keys |
Keys |
<optional> |
{a: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], b: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]} |
The RFID a and b keys. Required only for Mifare Classic cards. |
outEncoding |
OutputEncoding |
<optional> |
'DEFAULT' |
Output encoding defaults to MeldCX Format |
options |
ReadOptions |
<optional> |
{skipInsert: false, skipRemove: false} |
Optional configuration params, skipInsert to skip waiting for a card to be inserted and skipRemove to skip waiting for a card to be removed. |
Throws:
-
-
-
-
-
-
AgentTimedOutException
-
-
-
-
-
CancelledException
-
Examples
//Read Data from Ultralight cards
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => agent.RFID.read(
[
{
index: 5,
blocks: [{index: 0}]
},
{
index: 6
blocks: [{index: 0}]
}
],
undefined,
undefined,
{ skipRemove: true, skipRelease: true }
))
.then(result => {
console.log(result);
})
.catch(ex => {
console.error('Failed to read card data');
console.error(ex);
});
Console Output: {
sectors: [
{
index: 5,
blocks: [{index: 0, data: [1, 2, 3, 4]}]
},
{
index: 6,
blocks: [{index: 0, data: [5, 6, 7, 8]}]
}
],
uid: '0a0b0304050607',
capacity: 48,
type: 'Mifare Ultralight MF0UL11',
};
//Read Data from Mifare Classic cards
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => agent.RFID.read([
{
index: 0,
keys: { a: [0, 0, 0, 0, 0, 0] }
}
]))
.then(result => {
console.log('NUID', result.nuid);
console.log('UID', result.uid);
console.log('Capacity', result.capacity);
console.log('Sectors');
for (const sector of result.payload.sectors) {
console.log('\tSector', sector.index);
console.log('\t\tBlocks:');
for (const block of sector.blocks) {
console.log(
'\t\t\tBlock',
block.index,
block.type,
JSON.stringify(block.data),
JSON.stringify(block.access));
}
}
})
.catch(ex => {
console.error('Failed to read card data');
console.error(ex);
});
// Example for reading with skipReadData = true
const read = async() => {
const result = await agent.RFID.read(undefined, undefined, undefined, {
skipInsert: true,
skipRemove: true,
skipRelease: true,
skipReadData: true
});
console.log(result)
}
read()
Console Output: {
sectors: [],
type: 'Mifare S50 1K Card',
capacity: 1024
});
(async) setTimeout(timeout) → {Promise.<undefined>}
Set the default timeout value in milliseconds, this may be set to a number up to 120 seconds (2 minutes)
Parameters:
Name | Type | Description |
---|---|---|
timeout |
Number |
The length of time to wait before timing out in Milliseconds |
(async) unlock() → {Promise.<undefined>}
Unlock the latch
Throws:
-
-
-
-
AgentTimedOutException
-
-
Example
// Unlock the latch
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => agent.RFID.unlock())
.then(() => console.log('Unlocked'))
.catch(ex => {
console.error('Failed to Unlock');
console.error(ex);
});
(async) write(configopt, keysopt, inEncodingopt, optionsopt) → {Promise.<undefined>}
Write data to the RFID Card
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
config |
WriteConfiguration | Buffer | String | ArrayBuffer | UInt8Array |
<optional> |
defaultWriteConfig |
The configuration of the write task defines which sectors and blocks to write, this may also be a buffer of data |
keys |
Keys |
<optional> |
{a: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], b: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]} |
The RFID a and b keys. Required only for Mifare Classic cards. |
inEncoding |
OutputEncoding |
<optional> |
'DEFAULT' |
Input encoding |
options |
WriteOptions |
<optional> |
{skipSectorZeroBlockZero: true, skipInsert: false, skipRemove: false} |
Optional configuration for the write command, skipSectorZeroBlockZero, will skip the first 16 bytes of the provided binary payload, skipInsert will skip waiting for the card to be inserted, skipRemove will skip waiting for the card to be removed. |
Throws:
-
-
-
-
-
-
-
AgentTimedOutException
-
-
-
-
-
CancelledException
-
Examples
// For Mifare Ultralight cards.
// Below example writes 8 bytes of data to sector 5 and 6 of the card.
// Ultralight card MF0UL11 contains 12 user sectors(sector index 4 to 15). Each sector has 1 block only.
// Each block contains 4 bytes of data.
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => {
const writeConfig = [
{
index: 5,
blocks: [{index: 0, data: [0x01,0x02,0x03,0x04]}]
},
{
index: 6,
blocks: [{index: 0, data: [0x05,0x06,0x07,0x08]}]
},
];
const keys = undefined;
const inEncoding = undefined;
const writeOptions = {
skipInsert: true,
skipRemove: true,
skipRelease: true,
};
return agent.RFID.write(writeConfig, keys, inEncoding, writeOptions)
})
.then(() => console.log('Wrote to UL card successfully'))
.catch(ex => {
if (ex instanceof AgentCancelledException) {
console.error('It was cancelled, all is well :)');
return;
}
console.error('Failed to write card data');
console.error(ex);
});
// Write Data to Mifare Classic card Using the MeldCX Schema
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => agent.RFID.write([
{
index: 1,
keys: { a: [0, 0, 0, 0, 0, 0] }, // Key required to read or write.
blocks: [
{ index: 0, data: [4,3,2,1] }
],
updateKeys: { a: [1, 2, 3, 4, 5, 6] }, // Optional update the key.
access: {read: true, write: true, increment: true, decrement: true} // Optional update the access.
}
]))
.then(() => console.log('Wrote to card successfully'))
.catch(ex => {
if (ex instanceof AgentCancelledException) {
console.error('It was cancelled, all is well :)');
return;
}
console.error('Failed to write card data');
console.error(ex);
});
// Write Data to Mifare Classic card Using a Base64 string of data
const base64 = 'AAECAwQFBgcIAAECAwQFBgcIAAECAwQFBgcIAAECAwQFBgcIAAECAwQFBgcIAAECAwQFBgcIAAECAwQFBgcIAAECAwQFB.....';
const keys = {a: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF], b: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]};
window.Agent.onReadyAsync()
.then(() => window.Agent)
.then(agent => agent.RFID.write(base64, keys, 'base64'))
.then(() => console.log('Wrote to card successfully'))
.catch(ex => {
console.error('Failed to write card data');
console.error(ex);
});
For Mifare Classic card
// C3[4] C2[2] C1[1] Total Access
// 1 1 0 6 Can read with Key A/B but can only write with Key B
// 1 0 0 4 Can only read and write with Key A.
// 1 1 1 7 Access can only be read by Key A/B locked to changes *permanently*
// See here for a comprehensive guide: https://www.nxp.com/docs/en/data-sheet/MF1S50YYX_V1.pdf#page=12
await agent.RFID.write([{
index: 1,
access: [0, 0, 0, 6]
}], {a: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]}
* @example
// Example for writing to key B to Mifare Classic card
const writeKeyB = async() => {
const sector = 7;
const newKeyB = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
const result = await agent.RFID.write([
{
index: sector,
updateKeys: {b: newKeyB}
}
], undefined, undefined, {skipInsert: true, skipRemove: true, skipRelease: true});
console.log(result);
};
writeKeyB();
// Console Output: Undefined (no error thrown, shows that key write was successful)
// For Mifare Classic card
// Example of writing to change the access bits of a particular sector
const writeAccessBits = async() => {
const sector = 7;
const newAccess = [ 0, 0, 0, 6 ];
const newPermission = [127, 7, 136];
await agent.RFID.write([{
index: sector,
access: newAccess
}], {a: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]}, undefined, {skipInsert: true, skipRemove: true, skipRelease: true});
const readResult = await agent.RFID.read([{
index: sector,
blocks: [{index: 3}]
}], {a: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]}, undefined, {skipInsert: true, skipRemove: true, skipRelease: true});
const originalAccess = readResult.sectors[0].blocks[0].data.slice(6, 9);
console.log(originalAccess)
};
writeAccessBits();
Console Output: [127, 7, 136];
// For Mifare Classic card
// Example of reseting the access to default
const resetAccess = async() => {
const sector = 7;
const oldAccess = [ 0, 0, 0, 4 ];
const oldPermission = [255, 7, 128];
await agent.RFID.write([{
index: sector,
access: oldAccess
}], {b: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]}, undefined, {skipInsert: true, skipRemove: true, skipRelease: true});
const readResult = await agent.RFID.read([{
index: sector,
blocks: [{index: 3}]
}], {a: [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]}, undefined, {skipInsert: true, skipRemove: true, skipRelease: true});
const originalAccess = readResult.sectors[0].blocks[0].data.slice(6, 9);
}
resetAccess();
Console Output: [255, 7, 128];