Welcome
Welcome to Flomio! Get familiar with the Flomio products and explore their features in the Flomio Shop
Flomio builds hardware and software solutions in the proximity ID space. Flomio makes it easy to integrate our readers into your applications.
As we migrate from native mobile SDKs, please refer to the Javascript SDK for the most up to date documentation.
Getting Started
Flomio helps you build apps with NFC support so you can scan a tag to get a unique ID or read data. If after reading through this you still need help, feel free to ask on the forums.
The Flomio SDK consists of a Javascript SDK that enables reading NFC tags connected via USB without having to deal with the stress of managing the low-level interactions between the reader and tag. The Flomio SDK checks for proper a reader license on our cloud server so it requires connectivity to work.
Javascript Integration
Visit the flomio-js-sdk Github repoistory for instructions to get started using the Javascript SDK within your project.
// Visit https://github.com/flomio/flomio-js-sdk-example for documentation of the Javascript SDK
iOS Integration (Deprecated)
Our iOS libraries let you easily collect your customers/items tag information in your iOS app. Follow the instructions below to add the SDK to your project.
To be sure your reader hardware is fully operational you should install the Flomio Test app via TestFlight. This will help resolve most issues you may encounter during your integration. Our native libraries for Android and iOS and a cross-platform Javascript library are deprecated and not currently supported as we move to focus our efforts on the Javascript SDK.
Install Flomio Test app
You can now register to download the Flomio Test app via TestFlight. Once registered, you’ll receive an email from the Apple TestFlight system directing you to install the TestFlight app and subsequently the Flomio Test app from within TestFlight. Once installed, the Flomio Test app will launch with a menu of our supported readers including:
- FloJack BZR
- FloJack MSR
- FloJack Gen2
- FloBLE Noir
- FloBLE Plus
You will need to plug in the FloJack readers into the audio jack port of your iOS device or power on the FloBLE readers before selecting the appropriate reader from the menu. In order for the FloJack readers to operate well, make sure the volume of your iOS device is raised to the max. This is because the data is exchanged via audio modulation so the higher signal strength, the better data is captured by the reader. Also, the readers should be fully charged for the best results. This is done by plugging in the readers to USB power and observing charging RED led indicator goes off. At this point, the device is fully charged.
Download the Framework
Download the latest Flomio SDK and unzip it.
Build the Example App
Example iOS projects can be seen on the flomio-sdk-ios repo.
Cocoapods and Carthage
To use the FlomioSDK with Cocoapods, follow the instructions from the flomio-sdk-ios repo.
You can also manage your project’s FlomioSDK dependency using Carthage.
Follow these instructions to get setup.
Add github "https://github.com/flomio/flomio-sdk-ios"
to your Cartfile before running carthage update
.
You will still need to configure your project settings by following the steps in the Configure Project Settings section.
Configure Project Settings
Drag+drop the FlomioSDK.framework file into your Xcode Project. Make sure the “Copy items if needed” option is selected and click “Create groups” and “Finish” in dialog. It will be added to “Linked Frameworks and Libraries” section in project settings.
In Targets -> YourAppTarget -> General -> Embedded Binaries, add the FlomioSDK
You must configure your application with the following settings.
Click the Project Navigator (on the left), then click the application name under TARGET.In Targets -> YourAppTarget -> Build Settings -> Linking -> Other Linker Flags add ‘-lc++’ and ’-ObjC’
In Targets -> YourAppTarget -> Build Options -> Enable Bitcode set to ‘No’
In Targets -> YourAppTarget -> Build Phases -> Link Binary with Libraries, add MediaPlayer.Framework and libz.tbd
(optional)
In Target -> Build Settings -> Apple LLVM 9.0-Preprocessing -> Preprocessor Macros add ‘DEBUGLOG’
Initialize the Flomio SDK
You should only initialize the SDK once per session. This should be called when you want to use your reader,
after that you should use the startReaders
and stopReaders
methods on FmSessionManager to
control the readers.
See FmConfiguration for more information on the configuration.
------------------------------------------
// in YourViewController.h, add this to viewDidLoad
#import <FlomioSDK/FlomioSDK.h>
// For Pro Users
// #import <FlomioSDKPro/FlomioSDKPro.h>
@interface ViewController : UIViewController <FmSessionManagerDelegate> {
NSString *_deviceUid;
FmSessionManager *flomioSDK;
}
@end
------------------------------------------
// in YourViewController.m, add this to viewDidLoad
- (void)viewDidLoad {
FmConfiguration *defaultConfiguration = [[FmConfiguration alloc] init];
defaultConfiguration.deviceType = kFloBlePlus;
defaultConfiguration.scanSound = @YES;
defaultConfiguration.scanPeriod = @1000;
defaultConfiguration.powerOperation = kAutoPollingControl;
defaultConfiguration.transmitPower = kHighPower;
defaultConfiguration.allowMultiConnect = @NO;
defaultConfiguration.specificDeviceUid = nil;
flomioSDK = [[FmSessionManager flomioMW] initWithConfiguration:defaultConfiguration];
flomioSDK.delegate = self;
}
import FlomioSDK
// For Pro Users
// import FlomioSDKPro
class ViewController: UIViewController, FmSessionManagerDelegate {
var flomioSDK : FmSessionManager = FmSessionManager()
var deviceUid = ""
override func viewDidLoad() {
super.viewDidLoad()
let defaultConfiguration: FmConfiguration = FmConfiguration();
defaultConfiguration.deviceType = DeviceType.kFloBlePlus;
defaultConfiguration.transmitPower = TransmitPower.highPower;
defaultConfiguration.scanSound = true;
defaultConfiguration.scanPeriod = 1000;
defaultConfiguration.powerOperation = PowerOperation.autoPollingControl;
defaultConfiguration.allowMultiConnect = false;
flomioSDK = FmSessionManager.init(configuration: defaultConfiguration);
flomioSDK.delegate = self;
}
}
Listen for Reader Events
See FmSessionManagerDelegate Methods for more information on the delegate methods.
- (void)didFindTag:(FmTag *)tag fromDevice:(NSString *)deviceUid{
}
- (void)didReceiveReaderError:(NSError *)error {
}
- (void)didChangeCardStatus:(CardStatus)status fromDevice:(NSString *)deviceUid{
}
- (void)didChangeStatus:(NSString *)deviceUid withConfiguration:(FmConfiguration *)configuration andBatteryLevel:(NSNumber *)batteryLevel andCommunicationStatus:(CommunicationStatus)communicationStatus withFirmwareRevision:(NSString *)firmwareRev withHardwareRevision:(NSString *)hardwareRev{
}
- (void)didGetLicenseInfo:(NSString *)deviceUid withStatus:(BOOL)isRegistered{
}
func didFind(_ tag: FmTag!, fromDevice deviceId: String!) {
}
func didChangeStatus(_ deviceUid: String!, with configuration: FmConfiguration!, andBatteryLevel batteryLevel: NSNumber!, andCommunicationStatus communicationStatus: CommunicationStatus, withFirmwareRevision firmwareRev: String!, withHardwareRevision hardwareRev: String!) {
}
func didGetLicenseInfo(_ deviceUid: String!, withStatus isRegistered: Bool) {
}
func didChange(_ status: CardStatus, fromDevice device: String!) {
}
func didReceiveReaderError(_ error: Error!) {
}
Reading Tags
In the didFindTagFromDevice
callback, call the readNdef
method on the FmTag object
to read NDEF formatted data from your tag. Within the completion handler, iterate through the FmNdefRecords
in the FmNdefMessage to see the payload present in your tag. If there is
a URL, our SDK provides a convenience parameter with the URL as a string.
- (void)didFindTag:(FmTag *)tag fromDevice:(NSString *)deviceUid{
[tag readNdef:^(FmNdefMessage *ndef) {
if (ndef.ndefRecords) {
for (FmNdefRecord *record in ndef.ndefRecords) {
if (record.url.absoluteString.length > 0){
// if there is a URL present in your tag, it will be here
}
}
}
}];
}
func didFind(_ tag: FmTag!, fromDevice deviceId: String!) {
tag.readNdef { (ndefMessage) in
guard let ndefRecords = ndefMessage?.ndefRecords else { return }
for case let record as FmNdefRecord in ndefRecords {
for case let record as FmNdefRecord in ndefRecords {
guard let url = record.url else { return }
// if there is a URL present in your tag, it will be here
}
}
}
}
Writing to Tags
Writing a Web Address to Tags
In the didFindTagFromDevice
callback, initialize a FmNdefMessage with the createURIWithString
method and use it as a parameter on writeNdef
method
on the FmTag object to begin writing. The completion handler will indicate whether
your operation was successful.
- (void)didFindTag:(FmTag *)tag fromDevice:(NSString *)deviceUid{
FmNdefMessage *message = [FmNdefMessage createURIWithString:@"https://flomio.com"];
[tag writeNdef:message success:^(BOOL success) {
if (success) {
NSLog(@"Tag written successfully");
}
}];
}
func didFind(_ tag: FmTag!, fromDevice deviceId: String!) {
let ndefMessage = FmNdefMessage.createURI(with: "https://flomio.com")
tag.writeNdef(ndefMessage) { (success) in
if (success) {
print("Tag written successfully")
}
}
}
Writing Text Data to Tags
In the didFindTagFromDevice
callback, create one or more FmNdefRecords
and initialize a FmNdefMessage with them. Call the writeNdef
method
on the FmTag object to begin writing. The completion handler will indicate whether
your operation was successful.
- (void)didFindTag:(FmTag *)tag fromDevice:(NSString *)deviceUid{
NSData *type = [@"text/plain" dataUsingEncoding:NSASCIIStringEncoding];
NSData *payload = [@"Hello World!" dataUsingEncoding:NSASCIIStringEncoding];
FmNdefRecord *record = [[FmNdefRecord alloc] initWithTnf:kTNFMimeMedia andType:type andId:nil andPayload: payload];
FmNdefMessage *message = [[FmNdefMessage alloc] initWithNdefRecords:@[record]];
[tag writeNdef:message success:^(BOOL success) {
if (success) {
NSLog(@"Tag written successfully");
}
}];
}
func didFind(_ tag: FmTag!, fromDevice deviceId: String!) {
let type = "text/plain".data(using: .ascii)
let record = FmNdefRecord.init(tnf: Int16(kTNFMimeMedia), andType: type, andId: nil, andPayload: "Hello World!".data(using: .ascii))
let message = FmNdefMessage.init(ndefRecords: [record!])
tag.writeNdef(message) { (success) in
if (success) {
print("Tag written successfully")
}
}
}
Find UHF RFID tags
For FloJack Gen 2 device only.
Use the rfidTagsToFind
parameter on the FmConfiguration object to only target specific tags.
You must initialize a new FmConfiguration and call the setConfiguration
method on the
FmSessionManager object.
FmConfiguration *config = [[FmConfiguration alloc] init];
config.rfidTagsToFind = [[NSArray alloc] initWithObjects:@"1ABE1C0DE00000000000001B", nil];
[self.flomioSDK setConfiguration:config];
let config = FmConfiguration.init()
config.rfidTagsToFind = ["1ABE1C0DE00000000000001B"]
self.flomioSDK.configuration = config
Classes and Methods (Deprecated)
FmSessionManagerDelegate
Add FmSessionManagerDelegate to receive scan events and reader status changes.
Here is a quick summary of the notifications your app will receive from the Flomio SDK.
Delegate Method | Description |
---|---|
didFindTag | Returns a FmTag object when a tag has been detected from the reader |
didChangeStatus | Returns readers CommunicationStatus along with other reader info |
didGetLicenseInfo | When using the basic SDK, this connected displays whether the reader is licensed |
didChangeCardStatus | Returns a CardStatus object when a tag has entered/left the readers range |
didReceiveReaderError | Returns an error if there is a problem with the device |
FmSessionManager
Method | Parameters | Description |
---|---|---|
startReaders | Enable paired or connected readers to begin polling for tags. This can mean different things depending on PowerOperation setting. | |
stopReaders | Disable paired or connected readers from polling for tags. This can mean different things depending on PowerOperation setting. | |
sleepReaders | Put FloBLE Plus reader to sleep. This will also configure the reader to sleep after 60 seconds. | |
sendApdu toDevice success | APDU String, deviceId: String, completionBlock | Send an APDU using your connected device. |
updateCeNdef withDeviceUid | ndef: FmNdefMessage, deviceId: String | Configure your FloBLE Plus to emulate a tag with new NDEF data. Use when FmConfiguration’s isCeMode is true. |
FmConfiguration
You must first configure your settings and initialize the SDK.
Here is a description for each configuration item, some items are not relevant for some readers.
FmConfiguration | Type | Description |
---|---|---|
deviceType | DeviceType | Choose your device type, you may only use one device type at a time. |
scanSound | Boolean | Hear notifications from Flojack MSR. |
scanPeriod | Number | Period of polling for Audiojack readers (ms). |
powerOperation | PowerOperation | Determine power operation for FloBle Plus. The affects how startReader and stopReader control your FloBle Plus, either control bluetooth for low power operation or nfc polling for standard use. |
transmitPower | TransmitPower | Control the power of the NFC polling on the FloBle Plus. |
allowMulticonnect | Boolean | Control whether multiple FloBLE devices can connect simultaneously. |
specificDeviceUid | String | Use the device id from back of device (or deviceId property) to only connect to a certain bluetooth reader. This is only for use when ‘Allow Multiconnect’ = @0. |
isCeMode | Boolean | Activates Card Emulation mode on FloBLE Plus |
rfidTagsToFind | Array | Array of strings to indicate the identifiers of the RFID tags you want to target with your uGrokit UHF RFID reader. |
Note: Booleans listed are NSNumber initialized with Booleans. Use @YES/@No in Objective-C and true/false in Swift
FmTag
This is returned when a tag is tapped from the didFindTag:tag fromDevice:deviceId delegate method on FmSessionManagerDelegate
Properties
FmTag | Type | Description |
---|---|---|
atr | String | The ATR can be used to determine the type of tag. |
uid | String | The Unique Identifier of the tag. |
Methods
Method | Parameters | Description |
---|---|---|
readNdef | completionBlock | Returns the FmNdefMessage read from the tag in a completion block |
writeNdef | FmNdefMessage, completionBlock | Pass a NDEF message to write, returns boolean to indicate whether tag was written successfully |
FmNdefMessage
Object
Represents an NDEF (NFC Data Exchange Format) data message that contains one or more FmNdefRecords.
Name | Type | Description |
---|---|---|
ndefRecords | Array of FmNdefRecords | An array of FmNdefRecords. |
error | Error | Will explain the reason if there was a problem reading/parsing the data on the tag. |
FmNdefRecord
Object
Represents a NDEF (NFC Data Exchange Format) record as defined by the NDEF specification.
Name | Type | Description |
---|---|---|
tnf | Number | The Type Name Format field of the payload. |
type | Data | The type of the payload. |
id | Data | The identifier of the payload |
payload | Data | The data of the payload |
url | URL? | An optional convenience parameter which will return the payload as a URI for URI records. |
DeviceType
enum
Name | Type | Default | Description |
---|---|---|---|
kFlojackBzr | Number | 1 |
FloJack BZR |
kFlojackMsr | Number | 2 |
FloJack MSR |
kFloBleEmv | Number | 3 |
FloBLE EMV |
kFloBlePlus | Number | 4 |
FloBLE Plus |
uGrokit | Number | 5 |
uGrokit / Flojack Gen 2 |
PowerOperation
enum
Parameter of FmConfiguration for configuring the power of FloBLE Plus.
Name | Type | Default | Description |
---|---|---|---|
AutoPollingControl | Number | 0 |
startReaders and stopReaders turns on/off the reader from polling. |
BluetoothConnectionControl | Number | 1 |
startReaders and stopReaders turns on/off bluetooth, this can be used when exiting from/returning to your app. |
CommunicationStatus
enum
This is returned when there is a status update from the didChangeStatus delegate method on FmSessionManagerDelegate
Name | Type | Default | Description |
---|---|---|---|
Scanning | Number | 0 |
The device is connected and scanning for tags. |
Connected | Number | 1 |
The device is connected to bluetooth but not scanning for tags. |
Disconnected | Number | 2 |
The device is disconnected from bluetooth and not scanning for tags. |
CardStatus
enum
This is returned when when a tag has entered/left the readers range from the didChangeCardStatus delegate method on FmSessionManagerDelegate
Name | Type | Default | Description |
---|---|---|---|
NotPresent | Number | 0 |
A tag is not in range of the reader |
Present | Number | 1 |
A tag is in range of the reader. |
TransmitPower
enum
Parameter of FmConfiguration Used to determine the strength of the FloBLE Plus’s transmit power.
Name | Type | Default | Description |
---|---|---|---|
VeryLowPower | Number | 0 |
Lowest power setting |
LowPower | Number | 1 |
|
MediumPower | Number | 2 |
|
HighPower | Number | 3 |
Highest power setting |
Troubleshooting
Please visit the forums for help and to see previous questions.
Unsupported Architecture
When submitting to the App Store, if you get the Error ERROR ITMS-90087: Unsupported Architecture. Your executable contains unsupported architecture '[x86_64, i386]'."
Add a Run Script step to your build steps, put it after your step to embed frameworks, set it to use /bin/sh
and enter the following script:
APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"
EXTRACTED_ARCHS=()
for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done
echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"
echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
done
credit: Daniel Kennett
Android Integration (Deprecated)
NFC Actions & IFTTT (Deprecated)
The recently revamped NFC Actions app is now available in the App Store. 🎉🍾🥂
Use your FloBle Plus to write and read NFC tags (specifically Mifare Ultralight tags).
It also works with IFTTT so you can use NFC to automate your daily routine or prototype your NFC start-up without needing a front end app!
For example, with IFTTT combined with NFC Actions, you can log employees time and attendance, you can monitor inventory or control smart devices with a tap!
Set up your IFTTT
Create IFTTT Account
First, you obviously need a IFTTT account.
Get Maker Webhook URL
Then you’ll need to go to get your Maker Webhook URL from the Maker Webhook settings. First connect Maker Webhooks and then copy your Maker URL which should look like this:
https://maker.ifttt.com/use/ciaOj1jhrldDVFHVn3XwwG-QTh18JHbQoiB3b-Cd02h
Side note (optional): Navigate to your Maker URL to see details about how to make HTTP POST requests to trigger events.
Create your IFTTT Applet
You want to create your IFTTT Applet using Maker Webhooks to trigger your event… Sounds a lot more complicated than it is.
Go to IFTTT Create. Click “+this”, search 'Maker Webhooks’ and select it. Select 'Receive a web request’ and name your event to, for example, 'tag_scanned’.
Side note (optional): For more precise control, with a FloBLE Plus or FloBLE Noir, you can use the each tag Uid to trigger different events by setting the Event name to the Uid. This feature is not available when using native NFC on iOS as Apple do not allow access to Tag Uids.
Now click ’+that’, we will use iOS Calendar as an example here but you can use what you want. Click 'create a calendar event’. Now configure your event to show the details of the tag scan. Type 'Now’ into start time, click 'create’ and 'finish’.
Below are details of the values/'ingredients’ sent with the trigger.
IFTTT Ingredients
Ingredient | Description |
---|---|
Value1 | Tag Uid |
Value2 | Tag Location in Google Maps |
Value3 | Tag Payload (write to tag in NFC Actions to use this) |
Paste the URL in NFC Actions
Now that you have your Maker URL and Maker Event Name, go to the NFC Actions app and navigate to settings and paste them into the IFTTT settings fields.
Frequently Asked Questions
Q | A |
---|---|
Can the SDK run in the background? | We don’t expect Apps to ever be able operate FloJacks in the background. The FloJack requires a heartbeat handshake in order to prevent it from going into sleep mode and it’s not possible to handle from background. The active/inactive methods in the ViewController are meant to wake/sleep the reader during foregrounding/backgrounding. The FloBLE products are able to operate from a backgrounded app state. Also several of the same FloBLE products can connect to the iOS device at once (max 7 connected FloBLEs at a time). |
What’s the difference between the Basic SDK and the Pro SDK? | The Flomio SDK is currently sold on the per device license. That means that if you build an app with the Flomio SDK it will only work with readers that have valid licenses. Every FloJack and FloBLE reader we sell includes the Basic SDK license. This license is checked against reader device ID every time your app runs by checking our online database. That means that you need have web connectivity for the Basic SDK to work. For customers that need more flexibility, the Pro SDK is able to operate completely offline. The license is checked inside the Pro SDK bundle itself so you’re always guaranteed a good result. |
Can I read and write NDEF data to tags with my reader? | We recommend using the FloBLE Plus or FloBLE Noir to read and write data as the audio-jack data throughput is slow and unreliable. See FmTag for methods to read and write NDEF data. |
Please visit the forums for help and to see previous questions.