This tutorial shows you, how you can add support for the Fleigl Counter HD Beacons to your own iOS Application with only a few steps.

Since the beacons depend on a bluetooth LE connection, Hardware is limited to the following (and newer generations) Hardware devices:

iPod iphone iPad iPad (mini)
iPod touch 5th gen iPhone 4s iPad 3rd gen iPad mini 1st gen

Open the file browser of your xcode project and highlight the project file. Activate the tab "Build Phases" and add a framework using the "+" button. In the prompting modal dialogue, select the "CoreBluetooth.framework" and hit the "Add" button.

Framework hinzufügen

To discover bluetooth peripherals and connecting them, we'll need only four classes from the framework:

  • CBCentralManager
  • CBPeripheral
    • CBService
    • CBCharacteristic

The CBCentralManager instance gives us access to the bluetooth interfaces state and makes it possible to discover peripherals, connect and disconnect them.

Instances of the CBPeripheral are utilized to communicate to the peripheral device, the Fliegl Counter HD Beacon. It provides methods to discover and access the peripherals services and characteristics values and attributes.

In the following example you see an UIViewController wich acts as CBCentralManager- and CBPeripheral delegate.

Make sure, that you already have added the CoreBluetooth.framework to the project and added (@import CoreBluetooth) to the top of the header file.

Since this example picks only one random Fliegl HD Counter beacon, this approach is not suitable for production environments. The following source code only demonstrates how one could optain values from the beacons characteristics in a very simplified way.

//
//  ViewController.h
//  Fliegl Counter Example
//
//  Created by Johannes Duerr on 15.12.16.
//  Copyright © 2016 Fliegl Agrartechnik. All rights reserved.
//

@import CoreBluetooth;

#import <UIKit/UIKit.h>

/ Define UUID-Strings for services and characteristics
#define FLIEGL_BEACON_SERVICE_UUID @"C13AAAA0-C497-4C95-8699-01B142AF0C24"

@interface ViewController : UIViewController <CBCentralManagerDelegate, CBPeripheralDelegate>
{
    // CBCentral
    CBCentralManager* manager;

    // CBPeripheral (This solution is not suited for production!)
    CBPeripheral* discoveredPeripheral;
}

@end
//
//  ViewController.m
//  Fliegl Counter Example
//
//  Created by Johannes Duerr on 15.12.16.
//  Copyright © 2016 Fliegl Agrartechnik. All rights reserved.
//

#import "ViewController.h"

#define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // create manager and peripheral
    manager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - CBCentral delegate methods

- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    // catch and handle ***all*** managers states
    switch ([manager state]) {
        case CBManagerStatePoweredOff:
            NSLog(@"CBCentralManagerStatePoweredOff");
            break;
        case CBManagerStateResetting:
            NSLog(@"CBCentralManagerStateResetting");
            break;
        case CBManagerStateUnauthorized:
            NSLog(@"CBCentralManagerStateUnauthorized");
            break;
        case CBManagerStateUnknown:
            NSLog(@"CBCentralManagerStateUnknown");
            break;
        case CBManagerStateUnsupported:
            NSLog(@"CBCentralManagerStateUnsupported");
            break;
        case CBManagerStatePoweredOn:
            NSLog(@"CBManagerStatePoweredOn");
            NSLog(@"Start Scanning for Fliegl Counter HD Beacons...");
            CBUUID* beaconServiceUUID = [CBUUID UUIDWithString:FLIEGL_BEACON_SERVICE_UUID];
            NSArray* serviceArray = [NSArray arrayWithObjects:beaconServiceUUID,nil];
            [manager scanForPeripheralsWithServices:serviceArray options:nil];
            break;
    }
}

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI
{

    NSLog(@"CentralManager found new peripheral");
    NSLog(@"%@", [peripheral description]);

    // catch pointer to discovered peripheral
    discoveredPeripheral = peripheral;

    // stop scanning
    [manager stopScan];

    // set ourselves as delegate for the discovered peripheral
    [discoveredPeripheral setDelegate:self];

    // connect to peripheral
    [manager connectPeripheral:discoveredPeripheral options:nil];
}

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    NSLog(@"CentralManager did connect to peripheral:");
    NSLog(@"%@", [peripheral description]);

    // Start discovering Services
    [peripheral discoverServices:nil];
}

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
    NSLog(@"CentralManager did disconnect from peripheral:");
    NSLog(@"%@", [peripheral description]);
}

#pragma mark - CBPeripheral delegate methods

- (void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
    NSLog(@"\nDid discover Services...");
    for (CBService* s  in peripheral.services) {
        NSLog(@"%@", [NSString stringWithFormat:@"%@", s.UUID.UUIDString]);
        [peripheral discoverCharacteristics:nil forService:s];
    }
}

- (void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
    for (CBCharacteristic *c in service.characteristics) {
        NSLog(@"Did discover Characteristic: %@", [NSString stringWithFormat:@"%@", c.UUID.UUIDString]);

        // Now you can read / write the value of the characteristic depending on its attributes.
        // Call:
        //      - readValueForCharacteristic: to read its current value
        //      - writeValueForCharacteristic: to write a new value to the characteristic
        //      - setNotifyValue:YES|NO to get notifications from the peripheral if its characteristic value did change.

        // iBeacon minor characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBB1-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // iBeacon major characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBB2-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // iBeacon uuid characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBB3-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // iBeacon Bluetooth local name characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBB4-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // iBeacon txpower characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBB5-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // Chip temperature characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBB6-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // Beacon button-state changed characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBB7-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // Accelerometer / Inclination characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBB8-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // Active time (seconds) characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBB9-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // Activity count characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBBC-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // Current time (seconds since 1st jan 1970) characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBBB-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // Tank event count characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBBE-C497-4C95-8699-01B142AF0C24"]) {
            //[peripheral readValueForCharacteristic:c];
            [peripheral setNotifyValue:YES forCharacteristic:c];
        }

        // Tank (full tanks) count characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBBF-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }

        // Battery information characteristic
        if ([c.UUID.UUIDString isEqualToString:@"C13ABBC0-C497-4C95-8699-01B142AF0C24"]) {
            [peripheral readValueForCharacteristic:c];
        }
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
    NSLog(@"\nPeripheral did update the value of characteristic:\n%@\n\nValue: %@\n",characteristic.UUID.UUIDString, [characteristic.value description] );
}

@end

Of course, you can download the whole project archive for XCode 10.

ProjektArchiv.zip

Next Post