Introduction¶
This document is meant to be an overview of all the capabilities of the Spacecode SDK
(
Software Development Kit) and the best practices to leverage those capabilities. It is organized
around the four major features the SDK delivers:
- Operating Spacecode Devices
- Managing Users and Accesses
- Monitoring Temperature
- Defining and Following Alerts
The SDK is currently available for Java (local and remote devices) and Javascript (remote devices). A
Python and a C++ versions will be available in a near future.
Getting Started¶
Requirements¶
Operating Systems
- Windows XP, Vista, 7, 8, Server 2008, Server 2012
- GNU/Linux: Any distribution compatible with Java 7
- Mac OS X 10.7.3 (Lion) or later
Others
Consider downloading and installing the following (optional) dependencies:
*Most of the modern GNU/Linux distributions have the CONFIG_USB_SERIAL_FTDI_SIO
module enabled by default.
Download¶
Device¶
Communication¶
Spacecode Devices can be operated in two ways:
- Locally (USB), through a virtual serial port.
- Remotely (Ethernet or Wi-Fi), through the network.
Some products are designed to use only one. Devices capable of using both are, in most cases, always
using the same. Connecting with a local device is slightly different from connecting with a remote device.
Connection¶
Local Devices
A local device can be connected using its serial number and/or a serial port name. Serial port names are
formatted differently according to the operating system:
Operating System |
Serial Port Name |
Windows |
COM1 (COM2, COM3...) |
GNU/Linux |
/dev/ttyUSB0 (/dev/ttyUSB1, /dev/ttyUSB2...) |
Mac OS X |
/dev/tty.usbX ("X": serial number or location depending of the
USB port) |
If no serial port name is given, all serial ports available are tested.
The connection can require more time.
Device localDevice;
try {
// look on all serial ports for the device "AA7708950"
localDevice = new Device("AA7708950");
} catch (DeviceCreationException dce) {
// connection failed, handle exception
}
Device localDevice;
try {
// connect any device using ttyUSB0
localDevice = new Device(null, "/dev/ttyUSB0");
} catch (DeviceCreationException dce) {
// connection failed, handle exception
}
Device localDevice;
try {
// connect the device "AA7708950" using ttyUSB0
localDevice = new Device("AA7708950", "/dev/ttyUSB0");
} catch (DeviceCreationException dce) {
// connection failed, handle exception
}
Find Local Devices
The static method
getPluggedDevices
allows getting details about each local device plugged to the current computer. This method is useful when
the device
(s) to be used is
(are) not identified.
Map<String, PluggedDevice> serialNbrToDev = Device.getPluggedDevices();
for(PluggedDevice pd : serialNbrToDev.values())
{
System.out.println(String.format("%s on port %s", pd.getSerialNumber(), pd.getSerialPort()));
}
Remote Devices
Java
Javascript
Connections to remote devices are established with their IP address. If the TCP port used by
SmartServer
has been changed, it must be defined as a second parameter of the
TcpDevice
constructor call.
Device remoteDevice;
try {
// connect the device which IP address is "192.168.1.20"
remoteDevice = new TcpDevice("192.168.1.20");
} catch (DeviceCreationException dce) {
// connection failed, handle exception
}
As the JavaScript API is only available for the remote devices, there is only one class
Device,
which is instantiated with the IP address of the device. The TCP port used for the network
communication cannot be changed.
/** @type {Device} */
var device = new Device("192.168.1.20");
// [...]: Subscribe to events (see Events section below)
device.connect();
The result of the method
connect
is only known later, by listening to
Events.
Disconnection
Java
Javascript
Releasing a local device or disconnecting from a remote device is done by calling the method
release.
device.release();
Disconnecting a client is done by calling the method
release.
// close the connection to the remote device
device.release();
Scans ¶
Java
Javascript
As
TcpDevice class extends
Device, most of the
features available in
Device
can be executed transparently with an instance of
TcpDevice.
Starting a scan can be done as follows:
device.requestScan();
The scan process is asynchronous: the method
requestScan
does not block the calling thread.
To get the inventory resulting of a scan, an
event listener has to be defined.
The method
stopScan
allows interrupting a scan operation before it ends.
The class
Device proposes a method
requestScan
to send a scan order to the remote device.
device.requestScan();
The result of the operation is known by subscribing to some
events, described
in the next section.
The method
stopScan allows
interrupting a scan operation before it ends.
Events ¶
Java
Javascript
There are eight types of events which can be implemented with a dedicated interface:
Interface |
Events |
BasicEventHandler
|
Device‘s basic events, common to all types of devices. |
ScanEventHandler
|
Scan started, completed, tag detected, ... |
DoorEventHandler
|
Door opened, closed, ... |
AccessControlEventHandler
|
Authentication successful, authentication failure, ... |
AccessModuleEventHandler
|
Badge reader connected, fingerprint reader touched, ... |
LedEventHandler
|
Tags LED lighting started, stopped |
TemperatureEventHandler
|
New temperature measurement |
AlertEventHandler
|
New alert sent by the remote device |
Each interface provide as few events as possible. In most cases, an
event listener implements only a couple of events, keeping the code clear and modular.
Device and
TcpDevice accept
event listeners as follows:
device.addListener(new DemoEventHandler());
Two of the eight interfaces implemented as an example:
public class DemoEventHandler implements BasicEventHandler, DoorEventHandler
{
@Override
public void deviceDisconnected()
{
// BasicEventHandler
System.out.println("Device disconnected.");
}
@Override
public void deviceStatusChanged(DeviceStatus status)
{
// BasicEventHandler
System.out.println("Device status: "+status);
}
@Override
public void doorOpened()
{
// DoorEventHandler
System.out.println("Door opened.");
}
@Override
public void doorClosed()
{
// DoorEventHandler
System.out.println("Door closed.");
}
@Override
public void doorOpenDelay()
{
// DoorEventHandler
System.out.println("Door open for too long.");
}
@Override
public void scanCancelledByDoor()
{
// DoorEventHandler
System.out.println("Scan cancelled by door.");
}
}
Doing time-consuming tasks in an implementation of event listeners is
highly discouraged. Events are executed by an internal thread pool with a limited
number of threads (for performance reasons) which should not be blocked.
In order to handle the scan result (see
Scans), we can either:
// [...] other events from ScanEventHandler have been hidden
@Override
public void scanStarted()
{
System.out.println("Scan started!");
}
@Override
public void scanCompleted()
{
// the inventory (resulting from the scan) is ready
System.out.println("Scan completed!");
}
@Override
public void tagAdded(String tagUid)
{
// a tag has been detected during the scan
System.out.println(String.format("Tag scanned: %s", tagUid));
}
AbstractEventHandler
allows shortening these implementations by implementing only the desired events in an anonymous
class:
device.addListener(new AbstractEventHandler()
{
// from ScanEventHandler
@Override
public void scanCompleted()
{
// ask to light all the tags detected during the last scan
device.startLightingTagsLed(_currentDevice.getLastInventory().getTagsAll());
}
// from LedEventHandler
@Override
public void lightingStarted(List missingTags)
{
System.out.println("Lighting started!");
}
});
An event listener can be removed (and thus, disabled) by calling the method
removeListener
The class
Device emits some
Events
to which callbacks can be attached, with the method
on.
device.on('connected', function ()
{
if(device.isInitialized())
{
// Connection with the remote device established
console.log('Connected to Device: '+ device.getDeviceType() + ' ('+device.getSerialNumber()+')');
}
});
device.on('disconnected', function ()
{
if(device.isInitialized())
{
// The connection to the remote device has been lost
console.log(device.getSerialNumber() + ' - Disconnected');
return;
}
});
device.on('scanstarted', function ()
{
console.log("Scan started.");
});
device.on('scancompleted', function ()
{
// the inventory (resulting from the scan) is ready
console.log("Scan completed.");
});
device.on('tagadded', function (tagUid)
{
// a tag has been detected during the scan
console.log("Tag scanned: "+ tagUid);
});
// [...]
The method
isInitialized
guarantees that the device data (serial number, device type...) has been initialized.
Any callback (
function) attached to an event can be removed with the method
off.
In the following example, we use
off
to make sure that our callback is executed only once.
// add the named function expression 'f' to the event 'connected' listeners.
device.on('connected', function f()
{
// call the function 'doSomething' once the device is connected
doSomething();
// and remove the event listener
device.off('connected', f);
});
The above code can be simplified using the method
one.
The given callback is automatically removed from the listeners once it has been executed.
device.one('connected', function()
{
// call the function 'doSomething' once the device is connected
doSomething();
});
Inventories ¶
Items ¶
Java
Javascript
Once a scan is completed (see event
scanCompleted),
the inventory resulting from the operation can be consulted with the method
getLastInventory.
// Note: with remote devices, getLastInventory can return 'null' in case of communication errors
Inventory inventory = device.getLastInventory();
System.out.println(String.format("%d tags have been scanned.", inventory.getNumberTotal());
// prints: "X tags have been scanned." (with X the result of getNumberTotal)
Once a scan is completed (see event
scancompleted),
the inventory resulting from the operation can be consulted with the method
getLastInventory.
device.getLastInventory(function(inventory)
{
// Note: with remote devices, getLastInventory can return 'null' in case of communication errors
console.log(inventory.getNumberTotal() +" tags have been scanned.");
// prints: "X tags have been scanned." (with X the result of getNumberTotal)
});
In an inventory, each tag (identified by its
UID) has a state. This
state can take the following values:
State |
Definition |
Present |
The tag has already been scanned during the previous scan
(if any previous scan exists) |
Added |
The tag has not been scanned before: it is considered as new |
Removed |
The tag has been scanned in the previous scan, but not this time: it has been removed |
The following process describes the evolution of tags states in two scans. The first inventory results in
a list of
Added tags: all tags are "new" as there
was no previous scan. Before the second scan, TAG0003 is removed from the device, and TAG0004 is added. In
the second inventory, TAG0001 and TAG0002 are still
Present. TAG0003 is
Removed and TAG0004 is
Added.
1st Scan
Device |
TAG0001 |
TAG0002 |
TAG0003 |
|
→
Result
Inventory |
TAG0001 |
TAG0002 |
TAG0003 |
|
→
2nd Scan
Device |
TAG0001 |
TAG0002 |
|
TAG0004 |
→
Result
Inventory |
TAG0001 |
TAG0002 |
TAG0003 |
TAG0004 |
To get the list of tags scanned or removed, the
Inventory
class provides the following methods:
Method |
Description |
getTagsAll |
Provide the list of Added and
Present tags (TAG0001, TAG0002, TAG0004) |
getTagsAdded |
Provide the list of Added tags
(TAG0004) |
getTagsPresent |
Provide the list of Present tags
(TAG0001, TAG0002) |
getTagsRemoved |
Provide the list of Removed tags
(TAG0003) |
Automatic Scans ¶
Scan operations can be started either manually (through a software), or automatically when the door(s)
(if any) of the device get closed. If a user authenticated himself to open the device, the inventory
resulting from the automatic scan contains additional details:
Information |
Description |
Type |
Username |
Who opened the device and is responsible for this new inventory? |
String |
Access Type |
How did the user open the device? (Badge, Fingerprint) |
AccessType |
Door Number |
Which door has been closed? (0: master door, 1: slave) |
int |
AccessType enumeration contains three values:
Value |
Description |
Scan Type |
Username |
UNDEFINED |
Default value used by the Inventory class |
Manual |
(Empty) |
BADGE |
Access with a Badge Reader |
Automatic |
Yes |
FINGERPRINT |
Access with a Fingerprint Reader |
Automatic |
Yes |
The following example demonstrates how to use these values:
Java
Javascript
@Override
public void scanCompleted()
{
// Note: with remote devices, getLastInventory can return 'null' in case of errors
Inventory lastInventory = device.getLastInventory();
// any other value than UNDEFINED: automatic scan (BADGE or FINGERPRINT)
if(lastInventory.getAccessType() != AccessType.UNDEFINED)
{
// splitted for more readability
String display = String.format("New Inventory available. User: %s, Access: %s.",
lastInventory.getUsername(),
lastInventory.getAccessType().name());
// prints "New Inventory available. User: John, Access: BADGE."
System.out.println(display);
}
// Manual scan, no username (empty)
else
{
System.out.println("Manual scan completed.");
}
}
device.on('scancompleted', function()
{
// Note: with remote devices, getLastInventory can return 'null' in case of (communication) errors
device.getLastInventory(function(lastInventory)
{
if(lastInventory.getAccessType() != AccessType.UNDEFINED)
{
// splitted for more readability
var display = "New Inventory available. User: "+lastInventory.getUsername();
display += ", Access: "+inventory.getAccessType()+".";
// prints "New Inventory available. User: John, Access: Badge."
console.log(display);
}
else
{
console.log("Manual scan completed.");
}
});
});
Inventories History ¶
This section concerns the remote devices.
A remote device saves all the inventories it created in its dedicated database, providing the possibility to
get an inventories history over a given period.
Java
Javascript
The class
TcpDevice
provides a method
getInventories
(not available in
Device),
which accepts two Date (java.util) objects as start and end dates.
// remoteDevice is an instance of TcpDevice
// get a list of inventories, ordered by ascending creation date
List<Inventory> inventories = remoteDevice.getInventories(dateFrom, dateTo);
The class
Device provides a method
getInventories
which accepts two Date (JavaScript) objects as start and end dates.
// results: Array of Inventories, ordered by ascending creation date
device.getInventories(function(results) { }, startDate, endDate);
For efficiency reasons, using a read-only user account to directly query these inventories from the
database is recommended.
This section concerns the tags from the E2 generation and above, which provide
the Lighting and the Writing features.
LED Lighting ¶
Spacecode RFID tags from the "E2" generation can power an embedded LED on request. The SDK provides methods
to start and stop the lighting operation. The time management is depending of the user‘s code.
A minimalist example of lighting operation could be:
Java
Javascript
// get all the tags scanned in the last inventory
List<String> tagsList = device.getLastInventory().getTagsAll();
// send an order to light this list
if(device.startLightingTagsLed(tagsList))
{
// at this stage, the device confirmed the order, but we assume that it started lighting
// let the LED's blink during 4500 milliseconds
Thread.sleep(4500);
}
else
{
System.out.println("Could not start the lighting operation.");
}
if(!device.stopLightingTagsLed())
{
System.out.println("Could not stop the lighting operation.");
}
// get all the tags scanned in the last inventory
var uids = lastInventory.getTagsAll();
// send an order to light this list
device.startLightingTagsLed(function(result)
{
if(!result)
{
console.debug("Could not start the lighting operation.");
}
// let the LED's blink during 4500 milliseconds
setTimeout(function() {
device.stopLightingTagsLed(function(result)
{
if(!result)
{
console.debug("Could not stop the lighting operation.");
}
});
}, 4500);
}, uids);
The method startLightingTagsLed returns true when the device confirmed the order. At this
step, the operation can still fail starting or lighting some tags: thus, scheduling the
execution of the method stopLightingTagsLed, regardless of the result of startLightingTagsLed, is highly
recommended.
Java
Javascript
The lighting operation is not blocking unless the code commands it (
with, for instance, a
sleep): LED's keep blinking until the method
stopLightingTagsLed
is executed.
The interface
LedEventHandler
comes with the event
lightingStarted,
which contains, as a parameter, the UID's of the tags that could not be lighted (
tags missing,
or functioning abnormally). If all the tags provided to
startLightingTagsLed
could be lighted, this list is empty.
An additional event
lightingStopped
allows notifying all users that the current lighting process has been stopped.
public class DemoEventHandler implements LedEventHandler
{
@Override
public void lightingStarted(List<String> tagsNotLighted)
{
// LedEventHandler
System.out.println("Lighting started.");
if(!tagsNotLighted.isEmpty())
{
System.out.println("Tags not lighted:");
for(String uid : tagsNotLighted)
{
System.out.println(String.format("- %s", uid));
}
}
// from here, a separate timer (or thread) could
// wait for an event or a given delay to stop the lighting process.
}
@Override
public void lightingStopped(List<String> tagsNotLighted)
{
// LedEventHandler
System.out.println("Lighting stopped.");
}
}
Doing time-consuming tasks in an implementation of event listeners is
highly discouraged. Events are executed by an internal thread pool with a
limited number of threads (for performance reasons) which should not be blocked.
The class
Device emits an event
lightingstarted when
a lighting operation successfully started. The callback attached to the event is called with an
array of string as parameter, containing the UID's of the tags which could not be lighted (
tags
missing, or functioning abnormally). This array is empty if all the tags have been lighted.
An additional event
lightingstopped
allows notifying all users that the current lighting process has been stopped.
device.on('lightingstarted', function(tagsNotLighted)
{
console.log('Lighting started.');
if(tagsNotLighted.length > 0)
{
console.log('Tags not lighted:');
for(var i = 0; i < tagsNotLighted.length; ++i)
{
console.log('- '+ tagsNotLighted[i]);
}
}
});
device.on('lightingstopped', function()
{
console.log('Lighting stopped.');
});
UID Writing ¶
Embedded memory of the E2 tags can be written, resulting in a new UID which can be up to 17 characters
long. The characters allowed are:
capital letters ([A-Z]),
digits ([0-9]),
space,
dash,
slash,
dot.
Valid |
Invalid (not allowed) |
ITEM000002 |
Item000002 ("tem") |
LOT-1234-5678 |
LOT+1234+5678 ("+") |
TAG/REVIEW 035 |
TAG_REVIEW_035 ("_") |
To be
rewritten, the tag must be readable by the device, and from the E2 generation (or above).
Java
Javascript
String currentUid = "3006789456";
String newUid = "ITEM000001";
// if the operation is successful, tag 3006789456 will become tag ITEM000001
RewriteUidResult result = device.rewriteUid(currentUid, newUid);
switch(result)
{
case WRITING_CONFIRMATION_FAILED:
System.out.println("(Tag could not be confirmed with its new UID)");
// yet, the writing operation completed, continue to the successful case:
case WRITING_SUCCESS:
System.out.println("Writing operation successful!");
break;
default:
System.out.println("Operation failed.");
break;
}
UID writing (see the method
rewriteUid)
is a blocking operation. It waits until the device answered with a value from the enumeration
RewriteUidResult.
result contains a value from the enumeration
RewriteUidResult.
In most cases, all results except
WRITING CONFIRMATION FAILED
and
WRITING SUCCESS
should be considered as a failure.
var currentUid = "3006789456";
var newUid = "ITEM000001";
device.rewriteUid(function(result)
{
switch(result)
{
case RewriteUidResult.WRITING_CONFIRMATION_FAILED:
console.log("(Tag could not be confirmed with its new UID)");
// yet, the writing operation completed, continue to the successful case:
case RewriteUidResult.WRITING_SUCCESS:
console.log("Writing operation successful!");
break;
default:
console.log("Operation failed.");
break;
}
}, currentUid, newUid);
result contains a value from the enumeration
RewriteUidResult.
In most cases, all results except
WRITING CONFIRMATION FAILED and
WRITING SUCCESS
should be considered as a failure.
Access Control ¶
Permissions ¶
Four types of permission exist to control the access to the devices equipped with one (or two) door(s).
Devices coming with two has a
main door and a
second door. When
the device is equipped with one door, this last is considered as a
main door.
Type of Permission |
Description |
All |
Open all doors |
Master |
Open only the main door (equivalent to "All" on one-door devices) |
Slave |
Open only the second door |
Undefined |
No permission is given (no door can be unlocked) |
One-door devices only need
All and
Undefined.
Reminder: After a door is open and then closed, a scan operation is automatically
started.
Users ¶
A user is basically defined by a Username and a Permission (see
Permissions).
Additionally, a Badge Number and Fingerprints can be provided. Users are identified by their username,
supposed unique.
Users are separated in two categories:
Authorized and
Unregistered.
Authorized users are those considered by the device when a badge or a fingerprint is scanned: they may
have the permission to open the door. Unregistered users are kept in memory but are not considered: they
are not allowed to open the device, regardless their permission type.
Java
Javascript
// get all "active" (authorized) users, including those with a permission "Undefined"
List<User> activeUsers = device.getUsersService().getUsers();
// get the name of each unregistered user
List<String> unregisteredUsers = device.getUsersService().getUnregisteredUsers();
// get all "active" (authorized) users, including those with a permission "Undefined"
device.getUsers(function(users) { /* ... */ });
// get the name of each unregistered user
device.getUnregisteredUsers(function(users) { /* ... */ });
Register a new User ¶
Java
Javascript
The class
User
has three constructors. The simplest takes two parameters: a Username, and a type of
Permission (see
GrantType).
Fingerprints and badge number can be given as parameters, or updated later.
The operations of users management are made using the
UsersService
instance provided by the method
getUsersService.
// create the user "John" with the permission to open all doors
User userJohn = new User("John", GrantType.ALL);
// register him
device.getUsersService().addUser(userJohn);
The method
addUser
returns
false if a user with the same name is already known (of if any
error occurred during the operation).
As
TcpDevice
also uses a UsersService, using a local or a remote device for the management of Users is
programmatically transparent.
The constructor of the class
User takes up to
four parameters, but only the first two are mandatory (Username and Permission). The badge
number and the fingerprints can be given as parameters, or updated later.
// create the user "John" with the permission to open all doors
User userJohn = new User("John", GrantType.ALL);
// register him
device.addUser(function(result) {}, userJohn);
The value of
result (passed to the callback) is
false
if a user with the same name is already registered (of if any error occurred during the
operation).
Badge Number and Permission ¶
A user's badge number, or permission, can be changed as follows.
Java
Javascript
The class
UsersService
provides the methods
updateBadgeNumber
and
updatePermission,
using a username to update Badge Number and Permission.
// both methods return a boolean (true: success, false: failure)
device.getUsersService().updateBadgeNumber("John", "FOOBAR42");
device.getUsersService().updatePermission("John", GrantType.SLAVE);
The methods
updateBadgeNumber
and
updatePermission take
a username and the new value as parameters.
// "result" is a boolean (true: success, false: failure)
device.updateBadgeNumber(function(result) {}, "John", "FOOBAR42");
device.updatePermission(function(result) {}, "John", GrantType.SLAVE);
Remove a Permission, a User ¶
Removing a permission can be achieved by two ways:
- Setting the permission set to UNDEFINED
- Removing the user from the list of Active Users
In the first case, the user is still considered as active and is available in the list of authorized users.
In the former case, the user account is
disabled, regardless his/her type of permission, and put in the
list of unregistered users. In both case, the user is not able to open the device anymore.
Java
Javascript
// Remove the user's permission but keep him/her active
device.getUsersService().updatePermission("John", GrantType.UNDEFINED);
// Disable the user, who is put in the list of unregistered users
device.getUsersService().removeUser("Mike");
// Remove the user's permission but keep him/her active
device.updatePermission(function(result) { /* ... */ }, "John", GrantType.UNDEFINED);
// Disable the user account, which is transferred in the list of unregistered users
device.removeUser(function(result) { /* ... */ }, "Mike");
An unregistered user can be registered again by updating his/her permission. Thus, the user
account is transferred back in the list of authorized users (even with a permission UNDEFINED).
On Local Devices, the lists of users (authorized and unregistered) are lost when the instance of
Device is released.
However, Remote Devices keep in memory which users are authorized and which are unregistered.
Fingerprints ¶
Devices equipped with a Fingerprint Reader can take advantage of the biometric authentication.
Fingerprints are enrolled as Templates, which are made of four Samples. The ten fingers of a user
can be enrolled and each finger is differentiated with a unique index.
When using a local device equipped with fingerprint readers, the fingerprint readers have to be
initialized (or "
connected") before they can be exploited. Please refer to
connectFingerprintReaders.
The DigitalPersona UareU driver must be installed on the system.
Enroll a Finger
Java
Javascript
To start an enrollment process, the method
enrollFinger
takes two parameters: a username and a value from the enumeration
FingerIndex.
try {
boolean result = device.getUsersService().enrollFinger("John", FingerIndex.RIGHT_MIDDLE);
System.out.println(result ? "Enrollment completed!" : "Operation failed.");
} catch(TimeoutException te) {
// Delay of five minutes exceeded
}
A TimeoutException is thrown if the enrollment is not completed before five minutes.
The enrollment is a blocking process, as a fingerprint enrollment requires four samples to
create a template. The progress of the operation is indicated by an event from the interface
AccessModuleEventHandler:
fingerprintEnrollmentSample.
Once four samples have been captured, a template is created and the method enrollFinger returns
a boolean result.
To start an enrollment process, the method
enrollFinger
takes three parameters: a callback, a username and a value from the enumeration
FingerIndex.
device.enrollFinger(function(result)
{
console.log(result ? "Enrollment completed!" : "Operation failed.");
}, "John", FingerIndex.RIGHT_MIDDLE);
After a delay of five minutes, if the operation is not completed, the callback is executed with
a
result false. The progress of the
enrollment is reported by the event
enrollmentsample.
device.on('enrollmentsample', function(sampleNumber)
{
console.log('Enrollment progress: sample '+sampleNumber+'/4.');
});
In most cases, if the operation fails, it does as soon as it is executed (communication error, unknown
user...). It can exceptionally fail if the quality of the samples acquired during the enrollment
process is bad.
Set and Update Fingerprints
Setting a user's fingerprints can be done in the constructor call. This feature is particularly useful when
using a local device and loading users from a database to
register them.
Java
Javascript
Map<FingerIndex, String> templates = new EnumMap<>(FingerIndex.class);
templates.put(FingerIndex.LEFT_RING, template1);
templates.put(FingerIndex.LEFT_INDEX, template2);
User userMark = new User("Mark", GrantType.ALL, "", templates);
device.getUsersService().addUser(userMark);
Remote devices automatically save the users, including their fingerprints. But it is still
possible to create a user with preloaded fingerprints using the JS API.
var templates = new Map();
templates.set(FingerIndex.LEFT_RING, template1);
templates.set(FingerIndex.LEFT_INDEX, template2);
var userMark = new User("Mark", GrantType.ALL, "", templates);
device.addUser(function(result) {}, userMark);
Updating fingerprints is only possible by enrolling the finger again. The old template will be replaced
by the new enrolled one.
Remove Fingerprints
Java
Javascript
The method
removeFingerprint
allows removing a fingerprint, for a given Username and FingerIndex. It returns false in case
of failure (unknown user, communication error...).
device.getUsersService().removeFingerprint("Sam", FingerIndex.LEFT_RING);
The method
removeFingerprint
allows removing a fingerprint, for a given Username and FingerIndex. It returns false in case
of failure (unknown user, communication error...).
device.removeFingerprint(function(result) {}, "Sam", FingerIndex.LEFT_RING);
Authentications ¶
This section concerns the remote devices.
Remote devices save all the authentications in an internal* database. Thus, any user is able to get the
authentications history over a given period.
Java
Javascript
The class
TcpDevice
provides a method
getAuthentications
(not available in
Device),
which accepts two Date (java.util) objects as start and end dates and returns a list of
Authentications.
// remoteDevice is an instance of TcpDevice
// get a list of authentications, ordered by ascending creation date
List<Authentication> authentications = remoteDevice.getAuthentications(dateFrom, dateTo);
The class
Device provides a method
getAuthentications
which accepts two Date (JavaScript) objects as start and end dates.
// results: Array of Authentications, ordered by ascending creation date
device.getAuthentications(function(results) { }, startDate, endDate);
results is an array of
Authentications,
empty in case of error, or if there is no result for the given period.
For efficiency reasons, directly querying these authentications from the database is recommended.
Temperature ¶
This section concerns the devices equipped with a temperature probe.
Devices equipped with a temperature probe provide the current measure to allow a real-time monitoring. The
two ways to obtain this measure are:
- Reading it directly (synchronous)
- Listening to the "new measure" event (asynchronous)
For local devices, the temperature probe must be loaded by the software, using the method
addTemperatureProbe.
Remote devices automatically load it.
Current Value ¶
Instant Measure ¶
The first way to get the current temperature is to "manually" read it.
Java
Javascript
The class
Device
provides a method
getCurrentTemperature
which returns either the current temperature or
ERROR_VALUE.
double currentMeasure = device.getCurrentTemperature();
System.out.println(currentMeasure + "°C");
The class
Device
provides a method
getCurrentTemperature
which returns either the current temperature or
Device.TEMPERATURE_ERROR.
device.getCurrentTemperature(function(measure)
{
console.log(measure + "°C");
});
Events ¶
The second way to get the current temperature is to catch the notifications sent by the device. The method
addTemperatureProbe
accepts two double values: a delay (time spent between two measurement) and a delta (minimum difference
required between the last measure and the next to be considered).
On remote devices, default values are 60 seconds and 0.3°C. The listener can expect up to
one measure per minute. However, the ambient temperature is usually not subject to such changes (0.3°C
per minute).
Java
Javascript
The interface
TemperatureEventHandler
provides an event
temperatureMeasure,
called with a
double parameter, which is the current measure.
// [...] other events
@Override
public void temperatureMeasure(double value)
{
System.out.println("New temperature: "+value+"°C.");
}
The class
Device
provides an event
temperaturemeasure,
emitted with the current measure as a parameter.
device.on('temperaturemeasure', function (measure)
{
console.log("New temperature: "+value+"°C.");
});
Measures ¶
This section concerns the remote devices.
A remote device saves all the temperature measures in its dedicated database, providing the possibility to
get a measurements history over a given period.
Java
Javascript
The class
TcpDevice
provides a method
getTemperatureMeasures
(not available in
Device),
which accepts two Date (java.util) objects as start and end dates.
// remoteDevice is an instance of TcpDevice
// get a map of Date and Double (value), ordered by ascending creation date
Map<Date, Double> measures = remoteDevice.getTemperatureMeasures(dateFrom, dateTo);
The class
Device provides a method
getTemperatureMeasures
which accepts two Date (JavaScript) objects as start and end dates.
// results: Map of Date and Number (value), ordered by ascending creation date
device.getTemperatureMeasures(function(results) { }, startDate, endDate);
For efficiency reasons, directly querying these measures from the database is recommended.
Alert System ¶
Alerts ¶
SMTP Server ¶
Data Serialization ¶
Serialize ¶
Deserialize ¶