NAV Navbar
Logo
objective_c swift java

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. With a focus on mobile platforms, Flomio makes it easy to integrate our readers into Apps for iOS and Android.

You can use the Flomio SDK alongside any of Flomio’s line of NFC, BLE, and UHF RFID readers.

You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.

Getting Started

Flomio helps you build apps with NFC and RFID support so you can scan a tag to get a unique ID or read data. If after reading through this you still need a help, feel free to ask the flomies.

Our Flomio SDK consists of native libraries for Android and iOS that let you collect NFC and RFID without having to deal with the stress of managing the low level interactions between the reader and tag. The Flomio SDK comes in 2 flavors, Basic and Pro. The Basic SDK checks for proper license on our cloud server so it requires connectivity to work. The Pro SDK works completely offline. More details in FAQ section below.

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 encoutner during your integration.

Install Flomio Test app

You can now register to download the Flomio Test app via TestFlight. Once registered, you’ll recieve 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:

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 madulation so the higher signal strength, the better data is captured by the reader. Also, the readers should be fully charged for best results. This is done by plugging in the readers to USB power and observing charging RED led indicator go off. At this point the device is fully charged.

Download the Libraries

Download the latest Flomio SDK and unzip it.

iOS Integration

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.

Configure Project Settings

  1. Drag+drop the “iOS” folder on project in Xcode navigator. Make sure the “Copy items if needed” option is selected and click “Create groups” and “Finish” in dialog.

  2. 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’

  3. In Targets -> YourAppTarget -> Build Options -> Enable Bitcode set to ‘No’

  4. (optional) In Target -> Build Settings -> Apple LLVM 9.0-Preprocessing -> Preprocessor Macros add ‘DEBUGLOG’

  5. In Targets -> YourAppTarget -> General -> Link Binary with Libraries, add MediaPlayer.Framework and libz.tbd

  6. For Swift Developers: Add a bridge header file: File -> New > File... > Header File and name it ViewController-Bridging-Header.h

  7. For Swift Developers: In Targets -> YourAppTarget -> Build Options -> Swift Compiler - General -> Objective-C Bridging Header, add ViewController-Bridging-Header.h

Note: Since we don’t support testing the SDK via the iOS Simulator we don’t compile the library for i386 and x86_64 target architectures.

Initialize the Flomio SDK

    ------------------------------------------
    // in YourViewController.h, add this to viewDidLoad
    #import "FmSessionManager.h"

    @interface ViewController : UIViewController <FmSessionManagerDelegate> {  
        NSString *_deviceUuid;
        FmSessionManager *flomioMW;
    }   

    @end

    ------------------------------------------
    // in YourViewController.m, add this to viewDidLoad
    - (void)viewDidLoad {
      FmConfiguration *defaultConfiguration = [[FmConfiguration alloc] init];
          defaultConfiguration.deviceType = kFloBlePlus;
          defaultConfiguration.transmitPower = kHighPower;
          defaultConfiguration.scanSound = @YES;
          defaultConfiguration.scanPeriod = @1000;
          defaultConfiguration.powerOperation = kAutoPollingControl; //, kBluetoothConnectionControl for low power usage
          defaultConfiguration.transmitPower = kHighPower;
          defaultConfiguration.allowMultiConnect = @NO;
          defaultConfiguration.specificDeviceUuid = nil; //@"RR330-000120";
          flomioMW = [[FmSessionManager flomioMW] initWithConfiguration:defaultConfiguration];
          flomioMW.delegate = self;

    }

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(inactive) name:UIApplicationDidEnterBackgroundNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(active) name:UIApplicationDidBecomeActiveNotification object:nil];


    ------------------------------------------
    // in ViewController-Bridging-Header.h, add
    #import "FmSessionManager.h"


    ------------------------------------------
    // in ViewController.swift, add

    class ViewController: UIViewController, FmSessionManagerDelegate {

      var flomioMW : FmSessionManager = FmSessionManager()
      var deviceUuid = ""

      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; //, kBluetoothConnectionControl for low power usage
          defaultConfiguration.allowMultiConnect = false;
          flomioMW = FmSessionManager.init(configuration: defaultConfiguration);
          flomioMW.delegate = self; 
      }

    }

You must first configure your settings and initialize the SDK. Add the code from your language of choice (on the right) to your app to create the readers.

Here is a description for each configuration item, some items are not relevant for some readers.

Configuration item Description
deviceType Choose your device type, you may only use one device type at a time.
scanSound Hear notifications from Flojack MSR.
scanPeriod Period of polling for Audiojack readers.
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 Control the power of the NFC polling on the FloBle Plus.
allowMulticonnect Control whether multiple FloBle devices can connect simultaneously
specificDeviceUuid 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.

Listen for Reader Events


- (void)didFindTag:(FmTag *)tag fromDevice:(NSString *)deviceUuid{
    dispatch_async(dispatch_get_main_queue(), ^{
        //Use the main queue if the UI must be updated with the tag UUID or the deviceId
        NSLog(@"Found tag UUID: %@ with ATR: %@ from device:%@",tag.uuid, tag.atr, deviceUuid);
        [self readData];
    });
  }

- (void)readData {
    int currentPage = 0;
    for (currentPage = 4; currentPage < 16 ; currentPage+=4){
        NSString *apdu = [NSString stringWithFormat: @"FF B0 00 %02X 10",currentPage];
        [flomioMW sendApdu:apdu  toDevice:_deviceUuid success:^(NSString *response) {
            response = [response stringByReplacingOccurrencesOfString:@"90 00" withString:@""];
            NSLog(@"command: %@, response: %@", apdu, response);
        }];
    }
}

- (void)didReceiveReaderError:(NSError *)error {
    dispatch_async(dispatch_get_main_queue(), ^{ 
        NSLog(@"%@",error); //Reader error
    });
}

- (void)didChangeCardStatus:(CardStatus)status fromDevice:(NSString *)deviceUuid{
    // 0:kNotPresent
    // 1:kPresent
}

- (void)didChangeStatus:(NSString *)deviceUuid withConfiguration:(FmConfiguration *)configuration andBatteryLevel:(NSNumber *)batteryLevel andCommunicationStatus:(CommunicationStatus)communicationStatus withFirmwareRevision:(NSString *)firmwareRev withHardwareRevision:(NSString *)hardwareRev{
    _deviceId = deviceUuid;
}

- (void)didGetLicenseInfo:(NSString *)deviceUuid withStatus:(BOOL)isRegistered{
    if (!status){
        NSLog(@"%@",[NSString stringWithFormat:@"Device: %@ is not registered", deviceUuidString];);
    }
}


    func didFind(_ tag: FmTag!, fromDevice deviceId: String!) {
        DispatchQueue.main.async {
            if let thisUuid = tag.uuid, let thisDeviceId = deviceId {
                print("Did find UUID: \(thisUuid) from Device: \(thisDeviceId)")
                self.readData()
            }
        }
    }

    func readData() {
        for currentPage in stride(from: 4, to: 16, by: 4) {
            let st = String(format:"%02X", currentPage)
            let apdu: String = "FF B0 00 \(st) 10"
            flomioMW.sendApdu(apdu, toDevice: self.deviceUuid) { (response) in
                DispatchQueue.main.async {
                    if let thisResponse = response {
                        print("Response: \(thisResponse)")
                    }
                }
            }
        }
    }

    func didChangeStatus(_ deviceUuid: String!, with configuration: FmConfiguration!, andBatteryLevel batteryLevel: NSNumber!, andCommunicationStatus communicationStatus: CommunicationStatus, withFirmwareRevision firmwareRev: String!, withHardwareRevision hardwareRev: String!) {
        DispatchQueue.main.async {
            if let thisDeviceUuid = deviceUuid {
                self.deviceUuid = deviceUuid;
                print("Device: \(thisDeviceUuid)")
            }
        }
    }

    func didGetLicenseInfo(_ deviceUuid: String!, withStatus isRegistered: Bool) {
        DispatchQueue.main.async {
            if let thisDeviceUuid = deviceUuid {
                print("Device: \(thisDeviceUuid) Registered: \(isRegistered.description)")
            }
        }
    }

    func didChange(_ status: CardStatus, fromDevice device: String!) {
    //  DispatchQueue.main.async {
        //The card status has entered or left the scan range of the reader
        // Cardstatus:
        // 0:CardStatus.notPresent
        // 1:CardStatus.present
    //   }
    }

    func didReceiveReaderError(_ error: Error!) {
        DispatchQueue.main.async {
            print("Error: \(error)")
        }
    }

Add the FlomioSessionManager delegates to receive scan events and reader status changes. First you need to indicate that you will conform to the FmSessionManagerDelegate and then add the delegate methods.

Delegates

Here is a quick summary of the notifications your app will receive from the Flomio SDK.

Delegate Description
didFindTag Tag has been detected by the reader
didChangeStatus Returns readers current status along with other reader info
didGetLicenseInfo When using basic SDK, this connected displays whether the reader is licensed
didChangeCardStatus Displays when a tag has entered/left the readers range

Start/Stop Readers

The Flomio SDK provides an interface to start and stop the reader activity. These can be used when your app goes into the background or the user navigates to a screen when scanning should not be enabled.

Methods

Method Description
startReaders Enable paired or connected readers to begin polling for tags. This method will reinitialize reader if needed.
stopReaders Disable paired or connected readers from polling for tags.
sleepReaders Place paired or connected readers in low power mode. This can mean different things depending on “Power Operation” setting.

Android Integration

NFC Actions & IFTTT

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, you can use the each tag UUID to trigger different events by setting the Event name to the UUID.

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 UUID
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 foregounding/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.

Get Help

Please visit the forums for help and to see previous questions.