first release Intelligent Lumen iBeacon

Dependencies:   BLE_API mbed nRF51822

main.cpp

Committer:
javiervelasco
Date:
2016-10-17
Branch:
INTELLIGENT_LUMEN_BEACON
Revision:
1:2e474d4e7092
Parent:
0:720b1ee20d33

File content as of revision 1:2e474d4e7092:

/* mbed Microcontroller Library
 * Copyright (c) 2006-2015 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mbed.h"
#include <string.h>
#include <stddef.h>
#include <Serial.h>
#include "ble/services/iBeacon.h"
#include "ble/services/UARTService.h"
#include "ble/services/DFUService.h"
#include "nrf.h"
#include "nrf_sdm.h"


extern "C" {
    #include "pstorage.h"
}
#include "nrf_error.h"

#define _DEBUG 

BLE ble;
UARTService *uarts;
DFUService *dfus;
iBeacon *ibeacon;
pstorage_handle_t pstorageHandle;
#ifdef _DEBUG
Serial pc(USBTX, USBRX);
#endif
Ticker ticker;

// Struct to hold persistent data across power cycles
typedef struct PersistentData_t {
    char name[32];
    uint16_t majorNumber;
    uint16_t minorNumber;
    uint16_t txPower;
} __attribute__ ((aligned (4)));
PersistentData_t  persistentData;
static const int PERSISTENT_DATA_ALIGNED_SIZE = sizeof(PersistentData_t); 

/* Dummy callback handler needed by Nordic's pstorage module. */
void pstorageNotificationCallback(
            pstorage_handle_t *p_handle,
            uint8_t            op_code,
            uint32_t           result,
            uint8_t *          p_data,
            uint32_t           data_len){
            /* APP_ERROR_CHECK(result); */
}
 
void pstorageLoad(){
    if (pstorage_init()!=NRF_SUCCESS) {
    }
    
    pstorage_module_param_t pstorageParams = {
        .cb          = pstorageNotificationCallback,
        .block_size  = PERSISTENT_DATA_ALIGNED_SIZE,
        .block_count = 1
    };
    pstorage_register(&pstorageParams, &pstorageHandle);
    if (pstorage_load(
            reinterpret_cast<uint8_t *>(&persistentData),
            &pstorageHandle, PERSISTENT_DATA_ALIGNED_SIZE, 0
    ) != NRF_SUCCESS) {
        // On failure zero out and let the service reset to defaults
        sprintf(persistentData.name,"INTELLIGENTLUMEN");
        persistentData.majorNumber=1234;
        persistentData.minorNumber=5678;
        persistentData.txPower=54;       
    }
}



void pstorageSave() {
    pstorage_store(
            &pstorageHandle,
            reinterpret_cast<uint8_t *>(&persistentData),
            sizeof(PersistentData_t),
            0 /* offset */
    );
    wait(2);
}



/* BLE UART data received callback */
void onDataWritten(const GattWriteCallbackParams *params)
{
    char *bp = (char*)params->data;
    bp[params->len]=0; //Fix string end with zero.
    #ifdef _DEBUG
    pc.printf("%s\r\n",bp);
    #endif
    char *token;
    token = strtok(bp," ,");
    if (token!=NULL) {
        #ifdef _DEBUG
        pc.printf("Recv: %s\r\n",token);
        #endif
        if (strcmp(token,"name")==0) {
            token = strtok(NULL," ,");
            if (token==NULL) {
                #ifdef _DEBUG
                pc.printf("Cfg error: invalid name \r\n");
                #endif
                return;
            }
            sprintf((char *)persistentData.name,"%s",token);
        } else if (strcmp(token,"major")==0) {
            token = strtok(NULL," ,");
            if (token==NULL) {
                #ifdef _DEBUG
                pc.printf("Cfg error: invalid majorNumber \r\n");
                #endif
                return;
            }
            persistentData.majorNumber=atoi(token);
        } else if (strcmp(token,"minor")==0) {
            token = strtok(NULL," ,");
            if (token==NULL) {
                #ifdef _DEBUG
                pc.printf("Cfg error: invalid minorNumber \r\n");
                #endif
                return;
            }
            persistentData.minorNumber=atoi(token);
        } else if (strcmp(token,"rssi")==0) {
            token = strtok(NULL," ,");
            if (token==NULL) {
                #ifdef _DEBUG
                pc.printf("Cfg error: invalid txPower \r\n");
                #endif
                return;
            }
            persistentData.txPower=atoi(token);
            #ifdef _DEBUG
            pc.printf("Cfg txPower:%i\r\n",persistentData.txPower);
            #endif
        } else if (strcmp(token,"save")==0) {
            pstorageSave();
            #ifdef _DEBUG
            pc.printf("Config name:%s major:%i minor:%i tx:%i\r\n",persistentData.name,persistentData.majorNumber,persistentData.minorNumber,persistentData.txPower);
            #endif
            NVIC_SystemReset();
        } else if (strcmp(token,"dfu")==0) {
            sd_power_gpregret_set(BOOTLOADER_DFU_START);
            sd_softdevice_disable();
            sd_softdevice_vector_table_base_set(NRF_UICR->BOOTLOADERADDR);
            NVIC_SystemReset();
        }
    }
}
 
 
void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
{
    #ifdef _DEBUG
    pc.printf("Connected!\n");
    #endif
}
 
void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *cbParams)
{
    #ifdef _DEBUG
    pc.printf("Disconnected!\n");
    pc.printf("Restarting the advertising process\n");
    #endif
    ble.startAdvertising();
}

 

int main(void)
{
    const uint8_t uuid[] = {0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4,
                            0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61};
    #ifdef _DEBUG
    pc.baud(9600);
    pc.printf("INTELLIGENT LUMEN BEACON DFU v1.1\r\n");
    #endif
    
    /* Load mayor minor and txpower from storage */
    pstorageLoad();
    #ifdef _DEBUG
    pc.printf("Storage size:%i\r\n",PERSISTENT_DATA_ALIGNED_SIZE);
    pc.printf("Config name:%s mayor:%i minor:%i tx:%i\r\n",persistentData.name,persistentData.majorNumber,persistentData.minorNumber,persistentData.txPower);
    #endif
    
    ble.init();
    while (!ble.hasInitialized()) { wait(0.5);/* wait for BLE initialization */ }
    
    ble.gap().onDisconnection(disconnectionCallback);
    ble.gap().onConnection(connectionCallback);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME,
                                     (const uint8_t*)persistentData.name, strlen((const char*)persistentData.name));

    UARTService uartService(ble);
    uarts = &uartService;
    DFUService dfu(ble);
    dfus = &dfu;
    ibeacon = new iBeacon(ble, uuid, persistentData.majorNumber, persistentData.minorNumber, persistentData.txPower);  

    ble.onDataWritten(onDataWritten);

    /* setup advertising */
    ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
    ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
    ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
                                     (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed));
    ble.setAdvertisingInterval(100); /* 100ms; in multiples of 0.625ms. */
    ble.gap().startAdvertising();
        
    
    while (true) {
        ble.waitForEvent(); // allows or low power operation
    }
}