Ble for smart sOlutions

Dependencies:   Adafruit_WS2801

source/BleDevice.h

Committer:
kris@kris-X682X
Date:
2019-05-20
Revision:
6:ee9c86f06eae
Child:
7:9cda1b0f25ae

File content as of revision 6:ee9c86f06eae:

//
// Created by kris on 20-4-19.
//

#ifndef SSS_BLE_BLEDEVICE_H
#define SSS_BLE_BLEDEVICE_H
#include "pretty_printer.h"

#include <mbed.h>
#include "SecurityManager.h"
#include "ble/BLE.h"
#include <events/mbed_events.h>

typedef ble_error_t (Gap::*disconnect_call_t)(ble::connection_handle_t, ble::local_disconnection_reason_t);
const static disconnect_call_t disconnect_call = &Gap::disconnect;

class BleDevice : private mbed::NonCopyable<BleDevice>,
                  public SecurityManager::EventHandler,
                  public ble::Gap::EventHandler
{
public:
    inline void print_error(ble_error_t error, const char* msg)
    {
        printf("%s: ", msg);
        switch(error) {
            case BLE_ERROR_NONE:
                printf("BLE_ERROR_NONE: No error");
                break;
            case BLE_ERROR_BUFFER_OVERFLOW:
                printf("BLE_ERROR_BUFFER_OVERFLOW: The requested action would cause a buffer overflow and has been aborted");
                break;
            case BLE_ERROR_NOT_IMPLEMENTED:
                printf("BLE_ERROR_NOT_IMPLEMENTED: Requested a feature that isn't yet implement or isn't supported by the target HW");
                break;
            case BLE_ERROR_PARAM_OUT_OF_RANGE:
                printf("BLE_ERROR_PARAM_OUT_OF_RANGE: One of the supplied parameters is outside the valid range");
                break;
            case BLE_ERROR_INVALID_PARAM:
                printf("BLE_ERROR_INVALID_PARAM: One of the supplied parameters is invalid");
                break;
            case BLE_STACK_BUSY:
                printf("BLE_STACK_BUSY: The stack is busy");
                break;
            case BLE_ERROR_INVALID_STATE:
                printf("BLE_ERROR_INVALID_STATE: Invalid state");
                break;
            case BLE_ERROR_NO_MEM:
                printf("BLE_ERROR_NO_MEM: Out of Memory");
                break;
            case BLE_ERROR_OPERATION_NOT_PERMITTED:
                printf("BLE_ERROR_OPERATION_NOT_PERMITTED");
                break;
            case BLE_ERROR_INITIALIZATION_INCOMPLETE:
                printf("BLE_ERROR_INITIALIZATION_INCOMPLETE");
                break;
            case BLE_ERROR_ALREADY_INITIALIZED:
                printf("BLE_ERROR_ALREADY_INITIALIZED");
                break;
            case BLE_ERROR_UNSPECIFIED:
                printf("BLE_ERROR_UNSPECIFIED: Unknown error");
                break;
            case BLE_ERROR_INTERNAL_STACK_FAILURE:
                printf("BLE_ERROR_INTERNAL_STACK_FAILURE: internal stack faillure");
                break;
            case BLE_ERROR_NOT_FOUND:
                printf("BLE_ERROR_NOT_FOUND");
                break;
        }
        printf("\r\n");
    }

/** print device address to the terminal */
    void print_address(const uint8_t *addr)
    {
        printf("%02x:%02x:%02x:%02x:%02x:%02x\r\n",
               addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
    }

    inline void print_mac_address()
    {
        /* Print out device MAC address to the console*/
        Gap::AddressType_t addr_type;
        Gap::Address_t address;
        BLE::Instance().gap().getAddress(&addr_type, address);
        printf("DEVICE MAC ADDRESS: ");
        print_address(address);
    }

    inline const char* phy_to_string(Gap::Phy_t phy) {
        switch(phy.value()) {
            case Gap::Phy_t::LE_1M:
                return "LE 1M";
            case Gap::Phy_t::LE_2M:
                return "LE 2M";
            case Gap::Phy_t::LE_CODED:
                return "LE coded";
            default:
                return "invalid PHY";
        }
    }

    BleDevice(const BLE& ble, events::EventQueue &event_queue) :
            _led1(LED1, 0),
            _ble(const_cast<BLE &>(ble)),
            _event_queue(event_queue),
            _handle(0),
            _is_connecting(false) { };

    virtual ~BleDevice()
    {
        if (_ble.hasInitialized()) {
            _ble.shutdown();
        }
    };

    /** Start BLE interface initialisation */
    void run(int time)
    {
        ble_error_t error;

        /* to show we're running we'll blink every 500ms */
        _event_queue.call_every(500, this, &BleDevice::blink);

        if (_ble.hasInitialized()) {
            printf("Ble instance already initialised.\r\n");
            return;
        }

        /* this will inform us off all events so we can schedule their handling
         * using our event queue */
        _ble.onEventsToProcess(
                makeFunctionPointer(this, &BleDevice::schedule_ble_events)
        );

        /* handle gap events */
        _ble.gap().setEventHandler(this);

        error = _ble.init(this, &BleDevice::on_init_complete);

        if (error) {
            printf("Error returned by BLE::init.\r\n");
            return;
        }
        printf("Initialized the device! I should now wait for a bit maybe?");

        /* this will not return until shutdown */
        //BUT IT SHOULD!
//        _event_queue.dispatch_forever();
//        wait(2);
//        printf(" Waited? ");
        _event_queue.dispatch(time);
    };

private:
    /** Override to start chosen activity when initialisation completes */
    virtual void start() = 0;

    /** This is called when BLE interface is initialised and starts the demonstration */
    void on_init_complete(BLE::InitializationCompleteCallbackContext *event)
    {
//        ble_error_t error;

        if (event->error) {
            printf("Error during the initialisation\r\n");
            return;
        }

        /* gap events also handled by this class */
        _ble.gap().setEventHandler(this);

        /* print device address */
        Gap::AddressType_t addr_type;
        Gap::Address_t addr;
        _ble.gap().getAddress(&addr_type, addr);
        print_address(addr);
        printf(".... Initialized the device!");

        _event_queue.call_in(500, this, &BleDevice::start);
    };

    /** Schedule processing of events from the BLE in the event queue. */
    void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context)
    {
        _event_queue.call(mbed::callback(&context->ble, &BLE::processEvents));
    };

    /** Blink LED to show we're running */
    void blink(void)
    {
        _led1 = !_led1;
    };

private:
    /* Event handler */

    /** This is called by Gap to notify the application we disconnected,
     *  in our case it ends the demonstration. */
    virtual void onDisconnectionComplete(const ble::DisconnectionCompleteEvent &)
    {
        printf("Diconnected\r\n");
        _event_queue.break_dispatch();
    };

    virtual void onAdvertisingEnd(const ble::AdvertisingEndEvent &)
    {

        printf("Advertising timed out - aborting advertisting\r\n");
//        _event_queue.break_dispatch();
    }

    virtual void onScanTimeout(const ble::ScanTimeoutEvent &)
    {
        printf("Scan timed out - aborting\r\n");
        _event_queue.break_dispatch();
    }

private:
    DigitalOut _led1;

protected:
    BLE &_ble;
    events::EventQueue &_event_queue;
    ble::connection_handle_t _handle;
    bool _is_connecting;
};



#endif //SSS_BLE_BLEDEVICE_H