Dependencies:   AccelSensor BLE_API mbed nRF51822

Files at this revision

API Documentation at this revision

Comitter:
fjaviercifuentes
Date:
Fri Jan 19 02:38:38 2018 +0000
Commit message:

Changed in this revision

ALARMService.h Show annotated file Show diff for this revision Revisions of this file
AccelSensor.lib Show annotated file Show diff for this revision Revisions of this file
AccelSensorService.h Show annotated file Show diff for this revision Revisions of this file
BLE_API.lib Show annotated file Show diff for this revision Revisions of this file
ImobStateService.h Show annotated file Show diff for this revision Revisions of this file
InternalValuesService.h Show annotated file Show diff for this revision Revisions of this file
RELAYService.h Show annotated file Show diff for this revision Revisions of this file
crypt.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
nRF51822.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ALARMService.h	Fri Jan 19 02:38:38 2018 +0000
@@ -0,0 +1,57 @@
+#ifndef __BLE_ALARM_SERVICE_H__
+#define __BLE_ALARM_SERVICE_H__
+
+#include "mbed.h"
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "ImobStateService.h"
+
+class ALARMService {
+public:
+    const static uint16_t ALARM_SERVICE_UUID = 0xE000;
+    const static uint16_t ALARM_STATE_CHARACTERISTIC_UUID = 0xE001;
+
+    ALARMService(BLEDevice &_ble) : 
+        ble(_ble),
+        alarmState(0), 
+        AlarmCharacteristic(ALARM_STATE_CHARACTERISTIC_UUID, &alarmState, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)
+    {
+        GattCharacteristic *charTable[] = {&AlarmCharacteristic};
+        GattService alarmService(ALARM_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+
+        ble.addService(alarmService);
+
+        ble.gattServer().onDataWritten(this, &ALARMService::onDataWritten);
+    }
+
+    GattAttribute::Handle_t getValueHandle() const 
+    {
+        return AlarmCharacteristic.getValueHandle();
+    }
+    
+    void updateAlarmState(uint8_t newAlarmState) {
+        alarmState = newAlarmState;
+        ble.gattServer().write(AlarmCharacteristic.getValueHandle(), &alarmState, 1);
+    }
+    
+protected:
+    
+    virtual void onDataWritten(const GattWriteCallbackParams *params)
+    {          
+        if ((params->handle == AlarmCharacteristic.getValueHandle()) && (params->len == 1) && authenticated)
+        {
+            updateAlarmState(*(params->data));
+        }
+        else
+            updateAlarmState(0);
+    }     
+
+private:
+    
+    BLEDevice &ble;
+    uint8_t alarmState;
+    
+    ReadWriteGattCharacteristic<uint8_t> AlarmCharacteristic;
+};
+
+#endif /* #ifndef __BLE_RELAY_SERVICE_H__ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AccelSensor.lib	Fri Jan 19 02:38:38 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/fjaviercifuentes/code/AccelSensor/#620548ead4d9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AccelSensorService.h	Fri Jan 19 02:38:38 2018 +0000
@@ -0,0 +1,67 @@
+#ifndef __BLE_ACCEL_SENSOR_SERVICE_H__
+#define __BLE_ACCEL_SENSOR_SERVICE_H__
+
+#include "mbed.h"
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "AccelSensor/AccelSensor.h"
+
+#define ACCEL_DETECTION_THRESHOLD 85
+
+class AccelSensorService {
+public:
+    const static uint16_t ACCEL_SENSOR_SERVICE_UUID = 0xD000;
+    const static uint16_t ACCEL_DETECTION_UUID = 0xD001;
+
+    AccelSensorService(BLEDevice &_ble) : 
+        ble(_ble), 
+        accelerometer(P0_22, P0_20),// waveshare //accelerometer(P0_24, P0_21),// nuevo
+        accelDetection(0),
+        AccelDetectionCharacteristic(ACCEL_DETECTION_UUID, &accelDetection, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)
+    {
+        GattCharacteristic *charTable[] = {&AccelDetectionCharacteristic};
+        GattService accelSensorService(ACCEL_SENSOR_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+
+        ble.addService(accelSensorService);
+        
+        accelerometer.init();
+        updateAccel();       
+    }
+            
+    void updateAccel() {
+        int aux_accel[3];
+        accelerometer.readData(aux_accel);
+        
+        for(int i = 0; i < 3; i++)
+            accel[i] = (uint8_t)aux_accel[i];
+    }
+    
+    bool updateAccelDetection() {
+        uint8_t passAccel[3] = {accel[0], accel[1], accel[2]};      
+        updateAccel();
+        if( abs(accel[0] - passAccel[0]) > ACCEL_DETECTION_THRESHOLD || abs(accel[1] - passAccel[1]) > ACCEL_DETECTION_THRESHOLD || abs(accel[2] - passAccel[2]) > ACCEL_DETECTION_THRESHOLD )
+        {
+            accelDetection = 1;
+            ble.gattServer().write(AccelDetectionCharacteristic.getValueHandle(), &accelDetection, 1);            
+        }
+        else
+        {
+            accelDetection = 0;
+            ble.gattServer().write(AccelDetectionCharacteristic.getValueHandle(), &accelDetection, 1);        
+        }
+        
+        return ((accelDetection > 0) ? true: false);
+    }
+
+private:
+    BLEDevice &ble;
+    
+    AccelSensor accelerometer;
+    
+    uint8_t accel[3];
+    uint8_t accelDetection;
+    
+    ReadOnlyGattCharacteristic < uint8_t > AccelDetectionCharacteristic;    
+};
+
+#endif /* #ifndef __BLE_ACCEL_SENSOR_SERVICE_H__ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BLE_API.lib	Fri Jan 19 02:38:38 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/#65474dc93927
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ImobStateService.h	Fri Jan 19 02:38:38 2018 +0000
@@ -0,0 +1,225 @@
+#ifndef __BLE_IMOB_STATE_SERVICE_H__
+#define __BLE_IMOB_STATE_SERVICE_H__
+
+#include "mbed.h"
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "crypt.h"
+
+#include "softdevice_handler.h"
+
+#define PASSLEN 16
+#define KEYLEN 16
+#define MACLEN 6
+
+static bool authenticated = false;
+static bool activated = false;
+static bool userIsConnected = false;
+static bool initial_activation = false;
+
+uint8_t defaultPass[PASSLEN] = {0};
+uint8_t defaultMac[MACLEN] = {0};
+
+bool equal_arrays(uint8_t a1 [], const uint8_t a2 [], uint8_t n) 
+{
+    for (uint8_t i = 0; i < n; ++i)
+        if (a1[i] != a2[i])
+            return false;
+    return (true);
+}
+
+class ImobStateService {
+public:
+    const static uint16_t IMOB_STATE_SERVICE_UUID = 0xA000;
+    const static uint16_t IMOB_STATE_PASS_CHARACTERISTIC_UUID = 0xA001;
+    const static uint16_t IMOB_STATE_NONCE_CHARACTERISTIC_UUID = 0xA002;
+    const static uint16_t IMOB_STATE_NONCE_UPDATED_CHARACTERISTIC_UUID = 0xA003;
+    const static uint16_t IMOB_STATE_AUTHENTICATION_CHARACTERISTIC_UUID = 0xA004;
+    const static uint16_t IMOB_STATE_ACTIVATION_CHARACTERISTIC_UUID = 0xA005;
+    
+    ImobStateService(BLEDevice &_ble) : 
+        ble(_ble),
+        passUpdated(false),
+        nonceUpdated(false),
+        activation(0),
+        authentication(0),
+        passCharacteristic(IMOB_STATE_PASS_CHARACTERISTIC_UUID, defaultPass),
+        nonceCharacteristic(IMOB_STATE_NONCE_CHARACTERISTIC_UUID, defaultPass),
+        nonceUpdatedCharacteristic(IMOB_STATE_NONCE_UPDATED_CHARACTERISTIC_UUID, (uint8_t*)&nonceUpdated),
+        activationCharacteristic(IMOB_STATE_ACTIVATION_CHARACTERISTIC_UUID, &activation),
+        authenticationCharacteristic(IMOB_STATE_AUTHENTICATION_CHARACTERISTIC_UUID, &authentication)
+        
+    {              
+        GattCharacteristic *charTable[] = {&passCharacteristic, &nonceCharacteristic, &nonceUpdatedCharacteristic, &activationCharacteristic, &authenticationCharacteristic};        
+        GattService imobStateService(IMOB_STATE_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+
+        ble.addService(imobStateService);
+
+        ble.gap().onDisconnection(this, &ImobStateService::onDisconnectionFilter);
+        ble.gap().onConnection(this, &ImobStateService::onConnectionFilter);
+        ble.gattServer().onDataWritten(this, &ImobStateService::onDataWritten);
+        
+        resetAuthenticationValues();
+    
+        for(uint8_t i = 0; i < PASSLEN;i++)
+            correctPass[i] = defaultPass[i];
+    
+        for(uint8_t i = 0; i < KEYLEN;i++)
+            p_ecb_key[i] = defaultPass[i];
+            
+        for(uint8_t i = 0; i < MACLEN;i++)
+            recentMac[i] = defaultMac[i];
+    
+    }
+    
+    void resetAuthenticationValues()
+    {
+        updateAuthenticationValue(false);
+                
+        passUpdated = false;
+            
+        for(uint8_t i = 0; i < PASSLEN; i++)
+            pass[i] = defaultPass[i];
+        
+        ble.updateCharacteristicValue(passCharacteristic.getValueHandle(), pass, PASSLEN);
+    }
+    
+    void updateAuthenticationPassValues(const uint8_t newpass[PASSLEN])
+    {
+        passUpdated = true;
+        
+        for(uint8_t i = 0; i < PASSLEN;i++)
+            pass[i] = newpass[i];
+               
+        ctr_decrypt(pass);
+    }
+    
+    void updateAuthenticationNonceValues(const uint8_t newnonce[PASSLEN])
+    {
+        updateNonceUpdatedValue(true);
+        
+        for(uint8_t i = 0; i < PASSLEN;i++)
+            nonce[i] = newnonce[i];
+            
+        ble.updateCharacteristicValue(nonceCharacteristic.getValueHandle(),nonce,PASSLEN);
+        ctr_init(nonce, p_ecb_key);
+    }
+    
+    void updateNonceUpdatedValue(bool value)
+    {
+        nonceUpdated = value;
+        uint8_t aux_nonceUpdated = (nonceUpdated) ? 1: 0;
+        ble.gattServer().write(nonceUpdatedCharacteristic.getValueHandle(), &aux_nonceUpdated, 1);
+        
+    }
+        
+    void updateAuthenticationValue(bool value)
+    {
+        authenticated = value;
+        authentication = (authenticated) ? 1: 0;
+        ble.gattServer().write(authenticationCharacteristic.getValueHandle(), &authentication, 1);
+    }
+    
+    void updateActivationValue(const uint8_t value)
+    {
+        activated = (value == 1) ? true: false;
+        activation = (activated) ? 1: 0;
+        ble.gattServer().write(activationCharacteristic.getValueHandle(), &activation, 1);        
+    }
+        
+    void setCorrectPass(const uint8_t * newCorrectPass)
+    {
+        for(uint8_t i = 0; i < PASSLEN;i++)
+            correctPass[i] = newCorrectPass[i];
+    }
+    
+    void setCryptKey(const uint8_t * newCryptKey)
+    {
+        for(uint8_t i = 0; i < PASSLEN;i++)
+            p_ecb_key[i] = newCryptKey[i];
+    }
+ 
+protected:
+    virtual void onDataWritten(const GattWriteCallbackParams *params)
+    {          
+        if ((params->handle == passCharacteristic.getValueHandle()) && (params->len == PASSLEN) && (nonceUpdated))
+        {
+            updateAuthenticationPassValues((params->data));
+        }
+        else if ((params->handle == nonceCharacteristic.getValueHandle()) && (params->len == PASSLEN))
+        {
+            updateAuthenticationNonceValues((params->data));
+        }
+        else if ((params->handle == activationCharacteristic.getValueHandle()) && (params->len == 1) && authenticated)
+        {
+            updateActivationValue(*(params->data));
+        }
+        
+        if(passUpdated)
+        {           
+            if(equal_arrays(pass, correctPass, PASSLEN))
+            {                
+                updateAuthenticationValue(true);
+                initial_activation = true;
+            }
+            else
+            {
+                resetAuthenticationValues();
+            }
+        }
+    }
+    
+    void onDisconnectionFilter(const Gap::DisconnectionCallbackParams_t *params)
+    {   
+        resetAuthenticationValues();
+        userIsConnected = false;
+    }
+    
+    void onConnectionFilter(const Gap::ConnectionCallbackParams_t* params)
+    {
+        uint8_t newMac[MACLEN];
+        for(uint8_t i = 0; i < 6; i++)
+            newMac[i] = params->peerAddr[i];
+            
+        if(!equal_arrays(recentMac, newMac, MACLEN))
+        {                
+            for(uint8_t i = 0; i < 6; i++)
+                recentMac[i] = newMac[i];
+                
+            updateNonceUpdatedValue(false);
+            
+            for(uint8_t i = 0; i < PASSLEN; i++)
+                nonce[i] = defaultPass[i];  
+            
+            ble.updateCharacteristicValue(nonceCharacteristic.getValueHandle(), nonce, PASSLEN);
+        }
+        
+        userIsConnected = true;              
+    }
+
+private:
+    BLEDevice &ble;
+    bool passUpdated;
+    bool nonceUpdated;   
+    
+    uint8_t pass[PASSLEN];    
+    uint8_t nonce[PASSLEN];
+    uint8_t correctPass[PASSLEN];
+    uint8_t p_ecb_key[KEYLEN];
+    
+    uint8_t recentMac[MACLEN];
+    
+    uint8_t activation;
+    uint8_t authentication;
+    
+    WriteOnlyArrayGattCharacteristic <uint8_t, sizeof(pass)> passCharacteristic;    
+    WriteOnlyArrayGattCharacteristic <uint8_t, sizeof(pass)> nonceCharacteristic;
+    
+    ReadOnlyGattCharacteristic < uint8_t > nonceUpdatedCharacteristic;
+    ReadWriteGattCharacteristic < uint8_t > activationCharacteristic;
+    ReadOnlyGattCharacteristic < uint8_t > authenticationCharacteristic;
+    
+        
+};
+
+#endif /* #ifndef __BLE_IMOB_STATE_SERVICE_H__ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/InternalValuesService.h	Fri Jan 19 02:38:38 2018 +0000
@@ -0,0 +1,146 @@
+#ifndef __BLE_INTERNAL_VALUES_SERVICE_H__
+#define __BLE_INTERNAL_VALUES_SERVICE_H__
+
+#include "mbed.h"
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "ImobStateService.h"
+
+class InternalValuesService {
+public:
+    const static uint16_t INTERNAL_VALUES_SERVICE_UUID = 0xB000;
+    const static uint16_t LIPOCHARGER_STATE_CHARACTERISTIC_UUID = 0xB001;
+    const static uint16_t CONTACT_STATE_CHARACTERISTIC_UUID = 0xB002;
+    const static uint16_t ID1_CHARACTERISTIC_UUID = 0xB003;
+    const static uint16_t ID2_CHARACTERISTIC_UUID = 0xB004;
+    const static uint16_t CPC_CHARACTERISTIC_UUID = 0xB005;
+    const static uint16_t DPC_CHARACTERISTIC_UUID = 0xB006;
+
+    InternalValuesService(BLEDevice &_ble, ImobStateService * imobStateServicePtr) : 
+        ble(_ble),
+        lipoChargerState(2),
+        contactState(0),
+        id1(NRF_FICR->DEVICEID[0]),
+        id2(NRF_FICR->DEVICEID[1]),
+        chargeProgramCycles(0),
+        dischargeProgramCycles(0),
+        ISS(imobStateServicePtr),
+        LipoChargerCharacteristic(LIPOCHARGER_STATE_CHARACTERISTIC_UUID, &lipoChargerState, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
+        ContactCharacteristic(CONTACT_STATE_CHARACTERISTIC_UUID, &contactState, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY),
+        Id1Characteristic(ID1_CHARACTERISTIC_UUID, &id1),
+        Id2Characteristic(ID2_CHARACTERISTIC_UUID, &id2),
+        ChargeProgramCyclesCharacteristic(CPC_CHARACTERISTIC_UUID, &chargeProgramCycles),
+        DischargeProgramCyclesCharacteristic(DPC_CHARACTERISTIC_UUID, &dischargeProgramCycles)
+    {
+        GattCharacteristic *charTable[] = {&LipoChargerCharacteristic, &ContactCharacteristic, &Id1Characteristic, &Id2Characteristic, &ChargeProgramCyclesCharacteristic, &DischargeProgramCyclesCharacteristic};
+        GattService internalValuesService(INTERNAL_VALUES_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+
+        ble.addService(internalValuesService);
+               
+        uint8_t auxPass[PASSLEN];
+        uint8_t auxKey[KEYLEN];
+                        
+        id1Array[0] = id1 >> 24;
+        id1Array[1] = id1 >> 16;
+        id1Array[2] = id1 >> 8;
+        id1Array[3] = id1;
+        
+        id2Array[0] = id2 >> 24;
+        id2Array[1] = id2 >> 16;
+        id2Array[2] = id2 >> 8;
+        id2Array[3] = id2;
+        
+        
+        for(uint8_t i = 0; i < 8; i++)
+            auxPass[i] = id1Array[i%4];
+            
+        for(uint8_t i = 8; i < PASSLEN; i++)
+            auxPass[i] = id2Array[i%4];
+        
+        for(uint8_t i = 0; i < KEYLEN; i++)
+            auxKey[i] = id2Array[i%4];
+            
+        ISS->setCorrectPass(auxPass);
+        ISS->setCryptKey(auxKey);
+        
+        ble.gattServer().write(Id1Characteristic.getValueHandle(), id1Array, 4);
+        ble.gattServer().write(Id2Characteristic.getValueHandle(), id2Array, 4);
+    }
+    
+    void updateLipoChargerState(uint8_t newLipoChargerState)
+    {
+        lipoChargerState = newLipoChargerState;
+        ble.gattServer().write(LipoChargerCharacteristic.getValueHandle(), &lipoChargerState, 1);
+    }
+    
+    uint8_t getLipoChargerState()
+    {
+        return lipoChargerState;
+    }
+    
+    void updateContactState(uint8_t newContactState)
+    {
+        contactState = newContactState;
+        ble.gattServer().write(ContactCharacteristic.getValueHandle(), &contactState, 1);
+    }
+        
+    void updateDischargeProgramCyclesCharacteristic()
+    {
+        dischargeProgramCyclesArray[0] = dischargeProgramCycles >> 24;
+        dischargeProgramCyclesArray[1] = dischargeProgramCycles >> 16;
+        dischargeProgramCyclesArray[2] = dischargeProgramCycles >> 8;
+        dischargeProgramCyclesArray[3] = dischargeProgramCycles;
+        
+        ble.gattServer().write(DischargeProgramCyclesCharacteristic.getValueHandle(), dischargeProgramCyclesArray, 4);
+        dischargeProgramCycles = 0;
+    }
+    
+    void incrementDischargeProgramCycles()
+    {
+        dischargeProgramCycles++;
+    }
+    
+    void updateChargeProgramCyclesCharacteristic()
+    {
+        chargeProgramCyclesArray[0] = chargeProgramCycles >> 24;
+        chargeProgramCyclesArray[1] = chargeProgramCycles >> 16;
+        chargeProgramCyclesArray[2] = chargeProgramCycles >> 8;
+        chargeProgramCyclesArray[3] = chargeProgramCycles;
+        
+        ble.gattServer().write(ChargeProgramCyclesCharacteristic.getValueHandle(), chargeProgramCyclesArray, 4);
+        chargeProgramCycles = 0;
+    }
+    
+    void incrementChargeProgramCycles()
+    {
+        chargeProgramCycles++;
+    }        
+    
+private:
+    BLEDevice &ble;
+    uint8_t lipoChargerState;
+    uint8_t contactState;
+    
+    uint32_t id1;
+    uint32_t id2;    
+    uint32_t chargeProgramCycles;
+    uint32_t dischargeProgramCycles;    
+    
+    uint8_t id1Array[4];    
+    uint8_t id2Array[4];
+    uint8_t chargeProgramCyclesArray[4];
+    uint8_t dischargeProgramCyclesArray[4];
+            
+    ImobStateService * ISS;
+    
+    ReadOnlyGattCharacteristic < uint8_t > LipoChargerCharacteristic;
+    ReadOnlyGattCharacteristic < uint8_t > ContactCharacteristic;
+        
+    ReadOnlyGattCharacteristic < uint32_t > Id1Characteristic;
+    ReadOnlyGattCharacteristic < uint32_t > Id2Characteristic;
+    ReadOnlyGattCharacteristic < uint32_t > ChargeProgramCyclesCharacteristic;
+    ReadOnlyGattCharacteristic < uint32_t > DischargeProgramCyclesCharacteristic;    
+    
+};
+
+#endif /* #ifndef __BLE_INTERNAL_VALUES_SERVICE_H__ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RELAYService.h	Fri Jan 19 02:38:38 2018 +0000
@@ -0,0 +1,93 @@
+#ifndef __BLE_RELAY_SERVICE_H__
+#define __BLE_RELAY_SERVICE_H__
+
+#include "mbed.h"
+#include "ble/BLE.h"
+#include "ble/Gap.h"
+#include "ImobStateService.h"
+
+#define RELAY_TIME 1000000 // us
+#define CTR12V_TIME 100000 // us
+
+class RELAYService {
+public:
+    const static uint16_t RELAY_SERVICE_UUID = 0xC000;
+    const static uint16_t RELAY_STATE_CHARACTERISTIC_UUID = 0xC001;
+
+    RELAYService(BLEDevice &_ble, ImobStateService * imobStateServicePtr) : 
+        ble(_ble),
+        relayState(0),
+        actuatedRelay(P0_10,0),
+        Ctr12v(P0_3,0),        
+        ISS(imobStateServicePtr),
+        RelayCharacteristic(RELAY_STATE_CHARACTERISTIC_UUID, &relayState, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)
+    {
+        GattCharacteristic *charTable[] = {&RelayCharacteristic};
+        GattService relayService(RELAY_SERVICE_UUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
+
+        ble.addService(relayService);
+
+        ble.gap().onDisconnection(this, &RELAYService::onDisconnectionFilter);
+        ble.gattServer().onDataWritten(this, &RELAYService::onDataWritten);
+    }
+
+    GattAttribute::Handle_t getValueHandle() const 
+    {
+        return RelayCharacteristic.getValueHandle();
+    }
+    
+    void updateRelayState(uint8_t newRelayState) {
+        relayState = newRelayState;
+        actuatedRelay = newRelayState;
+        ble.gattServer().write(RelayCharacteristic.getValueHandle(), &relayState, 1);
+    }
+    
+    void activate()
+    {
+        Ctr12v = 1;
+        wait_us(CTR12V_TIME);
+        updateRelayState(1);
+        wait_us(RELAY_TIME);//depending of the time switching desired
+        updateRelayState(0);
+        wait_us(CTR12V_TIME);
+        Ctr12v = 0;   
+    }
+
+protected:
+
+    void onDisconnectionFilter(const Gap::DisconnectionCallbackParams_t *params)
+    {   
+        if(authenticated && activated)
+        {
+            activate();
+            //ISS->resetAuthenticationValues();
+        }
+    }
+    
+    virtual void onDataWritten(const GattWriteCallbackParams *params)
+    {          
+        if ((params->handle == RelayCharacteristic.getValueHandle()) && (params->len == 1) && authenticated)
+        {
+            activate();
+            ISS->resetAuthenticationValues();
+            
+            if(!activated)
+                ISS->updateActivationValue(1);
+        }
+        else
+            updateRelayState(0);
+    }     
+
+private:
+    
+    BLEDevice &ble;
+    uint8_t relayState;
+    DigitalOut actuatedRelay;
+    DigitalOut Ctr12v;
+    
+    ImobStateService * ISS;
+
+    ReadWriteGattCharacteristic<uint8_t> RelayCharacteristic;
+};
+
+#endif /* #ifndef __BLE_RELAY_SERVICE_H__ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypt.h	Fri Jan 19 02:38:38 2018 +0000
@@ -0,0 +1,150 @@
+#include "nrf_soc.h"
+#include "nrf_delay.h"
+#include "app_error.h"
+
+#define ECB_KEY_LEN            (16UL)
+#define COUNTER_BYTE_LEN       (4UL)
+#define NONCE_RAND_BYTE_LEN    (12UL)
+
+// The RNG wait values are typical and not guaranteed. See Product Specifications for more info.
+#ifdef NRF51
+#define RNG_BYTE_WAIT_US       (677UL)
+#elif defined NRF52
+#define RNG_BYTE_WAIT_US       (124UL)
+#else
+#error "Either NRF51 or NRF52 must be defined."
+#endif
+
+/**
+ * @brief Uses the RNG to write a 12-byte nonce to a buffer
+ * @details The 12 bytes will be written to the buffer starting at index 4 to leave
+ *          space for the 4-byte counter value.
+ *
+ * @param[in]    p_buf    An array of length 16
+ */
+void nonce_generate(uint8_t * p_buf)
+{
+    uint8_t i         = COUNTER_BYTE_LEN;
+    uint8_t remaining = NONCE_RAND_BYTE_LEN;
+
+    // The random number pool may not contain enough bytes at the moment so
+    // a busy wait may be necessary.
+    while(0 != remaining)
+    {
+        uint32_t err_code;
+        uint8_t  available = 0;
+
+        err_code = sd_rand_application_bytes_available_get(&available);
+        APP_ERROR_CHECK(err_code);
+
+        available = ((available > remaining) ? remaining : available);
+        if (0 != available)
+        {
+            err_code = sd_rand_application_vector_get((p_buf + i), available);
+            APP_ERROR_CHECK(err_code);
+
+            i         += available;
+            remaining -= available;
+        }
+
+        if (0 != remaining)
+        {
+            nrf_delay_us(RNG_BYTE_WAIT_US * remaining);
+        }
+    }    
+}
+
+static bool m_initialized = false;
+
+// NOTE: The ECB data must be located in RAM or a HardFault will be triggered.
+static nrf_ecb_hal_data_t m_ecb_data;
+
+/**
+ * @brief Initializes the module with the given nonce and key
+ * @details The nonce will be copied to an internal buffer so it does not need to
+ *          be retained after the function returns. Additionally, a 32-bit counter
+ *          will be initialized to zero and placed into the least-significant 4 bytes
+ *          of the internal buffer. The nonce value should be generated in a
+ *          reasonable manner (e.g. using this module's nonce_generate function).
+ *
+ * @param[in]    p_nonce    An array of length 16 containing 12 random bytes
+ *                          starting at index 4
+ * @param[in]    p_ecb_key  An array of length 16 containing the ECB key
+ */
+void ctr_init(const uint8_t * p_nonce, const uint8_t * p_ecb_key)
+{
+    m_initialized = true;
+
+    // Save the key.
+    memcpy(&m_ecb_data.key[0], p_ecb_key, ECB_KEY_LEN);
+
+    // Copy the nonce.
+    memcpy(&m_ecb_data.cleartext[COUNTER_BYTE_LEN],
+              &p_nonce[COUNTER_BYTE_LEN],
+              NONCE_RAND_BYTE_LEN);
+
+    // Zero the counter value.
+    memset(&m_ecb_data.cleartext[0], 0x00, COUNTER_BYTE_LEN);
+}
+
+static uint32_t crypt(uint8_t * buf)
+{
+    uint8_t  i;
+    uint32_t err_code;
+
+    if (!m_initialized)
+    {
+        return NRF_ERROR_INVALID_STATE;
+    }
+
+    err_code = sd_ecb_block_encrypt(&m_ecb_data);
+    if (NRF_SUCCESS != err_code)
+    {
+        return err_code;
+    }
+
+    for (i=0; i < ECB_KEY_LEN; i++)
+    {
+        buf[i] ^= m_ecb_data.ciphertext[i];
+    }
+
+    // Increment the counter.
+    (*((uint32_t*) m_ecb_data.cleartext))++;
+
+    return NRF_SUCCESS;
+}
+
+/**
+ * @brief Encrypts the given buffer in-situ
+ * @details The encryption step is done separately (using the nonce, counter, and
+ *          key) and then the result from the encryption is XOR'd with the given
+ *          buffer in-situ. The counter will be incremented only if no error occurs.
+ *
+ * @param[in]    p_clear_text    An array of length 16 containing the clear text
+ *
+ * @retval    NRF_SUCCESS                         Success
+ * @retval    NRF_ERROR_INVALID_STATE             Module has not been initialized
+ * @retval    NRF_ERROR_SOFTDEVICE_NOT_ENABLED    SoftDevice is present, but not enabled
+ */
+uint32_t ctr_encrypt(uint8_t * p_clear_text)
+{
+    return crypt(p_clear_text);
+}
+
+/**
+ * @brief Decrypts the given buffer in-situ
+ * @details The encryption step is done separately (using the nonce, counter, and
+ *          key) and then the result from the encryption is XOR'd with the given
+ *          buffer in-situ. The counter will be incremented only if no error occurs.
+ *
+ * @param[in]    p_cipher_text    An array of length 16 containing the cipher text
+ *
+ * @retval    NRF_SUCCESS                         Succeess
+ * @retval    NRF_ERROR_INVALID_STATE             Module has not been initialized
+ * @retval    NRF_ERROR_SOFTDEVICE_NOT_ENABLED    SoftDevice is present, but not enabled
+ */
+uint32_t ctr_decrypt(uint8_t * p_cipher_text)
+{
+    return crypt(p_cipher_text);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Jan 19 02:38:38 2018 +0000
@@ -0,0 +1,247 @@
+#include "mbed.h"
+#include "ble/BLE.h"
+#include "RELAYService.h"
+#include "ALARMService.h"
+#include "BatteryService.h"
+#include "InternalValuesService.h"
+#include "ImobStateService.h"
+#include "AccelSensorService.h"
+
+#define TIME_CICLE 80.0 //ms
+#define ANALOGIN 3
+#define DISCONNECTION_TIME (1000.0/TIME_CICLE)*10.0 // seg
+#define AUTHENTICATION_TIME (1000.0/TIME_CICLE)*25.0 // seg
+
+
+/* LED aliveness indicator system  */
+DigitalOut alivenessLED(P0_18, 0); // P0_25
+
+/* battery charge level, Pin P0_1 */
+AnalogIn batteryCharge(P0_1);
+/* lipo charger Status, Pin P0_2 */
+AnalogIn lcStat(P0_2);
+/* Chack contact, Pin P0_6 */
+AnalogIn contact(P0_6);
+
+
+/* Device name setting to identifying your device */
+const static char     DEVICE_NAME[] = "I-Mob";
+static const uint16_t uuid16_list[] = {ImobStateService::IMOB_STATE_SERVICE_UUID, RELAYService::RELAY_SERVICE_UUID, ALARMService::ALARM_SERVICE_UUID,  InternalValuesService::INTERNAL_VALUES_SERVICE_UUID, AccelSensorService::ACCEL_SENSOR_SERVICE_UUID, GattService::UUID_BATTERY_SERVICE};
+
+
+ImobStateService * imobStateServicePtr;
+
+InternalValuesService * internalValuesServicePtr;
+RELAYService * relayServicePtr;
+ALARMService * alarmServicePtr;
+AccelSensorService * accelSensorServicePtr;
+BatteryService * batteryServicePtr;
+
+float lipochargerState = 0;
+float contactState = -1;
+uint8_t batteryLevel = 0;
+
+uint8_t selectedAnalogIn = 0;
+
+uint32_t forceDisconnectionCounter = 0;
+uint32_t forceActivationCounter = 0;
+
+/* Calibration variables */
+bool batteryLevelCalibration = false;
+float batteryLevelConstant = 100.0f;
+float contactStateThreshold = 0.21f;
+/* ----- */
+
+Ticker ticker;
+
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
+{
+    /* Re-enable advertisements after a connection teardown */
+    BLE::Instance().gap().startAdvertising();
+}
+
+void periodicCallback(void)
+{
+    /* Do blinky on LED1 to indicate system aliveness. */
+    alivenessLED = !alivenessLED;
+}
+
+/**
+ * This function is called when the ble initialization process has failed
+ */
+void onBleInitError(BLE &ble, ble_error_t error)
+{
+    /* Initialization error handling should go here */
+}
+
+/**
+ * Callback triggered when the ble initialization process has finished
+ */
+void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
+{
+    BLE& ble = params->ble;
+    ble_error_t error = params->error;
+
+    if (error != BLE_ERROR_NONE) 
+    {
+        /* In case of error, forward the error handling to onBleInitError */
+        onBleInitError(ble, error);
+        return;
+    }
+
+    /* Ensure that it is the default instance of BLE */
+    if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE)
+    {
+        return;
+    }
+ 
+    ble.gap().onDisconnection(disconnectionCallback);
+        
+    imobStateServicePtr = new ImobStateService(ble);
+    
+    internalValuesServicePtr = new InternalValuesService(ble, imobStateServicePtr);
+    relayServicePtr = new RELAYService(ble, imobStateServicePtr);
+    alarmServicePtr = new ALARMService(ble);
+    accelSensorServicePtr = new AccelSensorService(ble);
+    batteryServicePtr = new BatteryService(ble, batteryLevel);
+    
+    /* setup advertising */
+    
+    /* BREDR_NOT_SUPPORTED means classic bluetooth not supported;
+    * LE_GENERAL_DISCOVERABLE means that this peripheral can be discovered by any BLE scanner--i.e. any phone. 
+    */
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
+    /* Adding the RELAY service UUID to the advertising payload*/
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
+    /* This is where we're collecting the device name into the advertisement payload. */
+    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
+    /* We'd like for this BLE peripheral to be connectable. */
+    ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
+    /* set the interval at which advertisements are sent out, 1000ms. */
+    ble.gap().setAdvertisingInterval(TIME_CICLE);
+    /* we're finally good to go with advertisements. */
+    ble.gap().startAdvertising();
+}
+
+int main(void)
+{    
+    /* Setting up a callback to go at an interval of 1s. */
+    ticker.attach(periodicCallback, TIME_CICLE/1000.0);
+
+    /*  initialize the BLE stack and controller. */
+    BLE &ble = BLE::Instance();
+    ble.init(bleInitComplete);
+    
+    /* Accelerometer functions
+    accelerometer.init();
+    accelerometer.standby();
+    accelerometer.active();
+    int accel[3];
+    accelerometer.readData(accel);
+    accelerometer.standby();
+    */
+    
+    /* SpinWait for initialization to complete. This is necessary because the
+     * BLE object is used in the main loop below. */
+    while (ble.hasInitialized()  == false) { /* spin loop */ }       
+
+    while (true)
+    {
+        /* this will return upon any system event (such as an interrupt or a ticker wakeup) */
+        ble.waitForEvent();
+        bool accel = accelSensorServicePtr->updateAccelDetection();
+                      
+        /* Update battery charge level */        
+        if (selectedAnalogIn == 0)
+        {
+            batteryLevel = (uint8_t)(batteryCharge.read()*batteryLevelConstant);
+            batteryServicePtr->updateBatteryLevel(batteryLevel);           
+        }
+        /* Update lipo charger state */
+        if (selectedAnalogIn == 1)
+        {
+            lipochargerState = lcStat.read();
+            uint8_t aux_lipochargerState;
+                        
+            uint8_t pass_lipochargerState = internalValuesServicePtr->getLipoChargerState();
+            
+            if (lipochargerState > 0.4)
+            {                   
+                if (lipochargerState > 0.9)
+                {                       
+                    aux_lipochargerState = 1;                    
+                    if (pass_lipochargerState == 0) internalValuesServicePtr->updateChargeProgramCyclesCharacteristic();
+                }
+                else
+                {
+                    aux_lipochargerState = 2;
+                    if (activated && accel) alarmServicePtr->updateAlarmState(1);
+                }
+            }
+            else
+            {
+                aux_lipochargerState = 0;
+                if (pass_lipochargerState == 1) internalValuesServicePtr->updateDischargeProgramCyclesCharacteristic();
+            }
+                
+            if(!batteryLevelCalibration && aux_lipochargerState == 1)
+            {
+                batteryLevelConstant *= 100.0f/batteryLevel;
+                batteryLevelCalibration = true;
+            }
+                
+            internalValuesServicePtr->updateLipoChargerState(aux_lipochargerState);
+        }
+        
+        if (internalValuesServicePtr->getLipoChargerState() == 0) internalValuesServicePtr->incrementChargeProgramCycles();
+        else if (internalValuesServicePtr->getLipoChargerState() == 1) internalValuesServicePtr->incrementDischargeProgramCycles();
+        
+        /* Update contact state */
+        if (selectedAnalogIn == 2)
+        {
+            contactState = contact.read();
+            uint8_t aux_contactState;                                   
+            
+            if (contactState > contactStateThreshold)
+            {
+                aux_contactState = 1;
+                
+                if (!authenticated && activated)
+                    relayServicePtr->activate();                
+            }
+            else
+                aux_contactState = 0;
+                                
+            internalValuesServicePtr->updateContactState(aux_contactState);
+        }       
+        
+        selectedAnalogIn++;
+            
+        if (selectedAnalogIn == ANALOGIN) selectedAnalogIn = 0;
+        
+        if (!authenticated && userIsConnected)
+        {
+            if (forceDisconnectionCounter > DISCONNECTION_TIME)
+            {
+                forceDisconnectionCounter = 0;
+                Gap::DisconnectionReason_t res=Gap::LOCAL_HOST_TERMINATED_CONNECTION;
+                ble.disconnect(res);
+            }
+            else
+                forceDisconnectionCounter++;
+        }
+        else
+            forceDisconnectionCounter = 0;
+        
+        if ( !initial_activation  && !userIsConnected)
+            if (forceActivationCounter > AUTHENTICATION_TIME)
+            {
+                imobStateServicePtr->updateActivationValue(1);
+                initial_activation = true;
+            }
+            else
+                forceActivationCounter++;
+            
+        
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Jan 19 02:38:38 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/7130f322cb7e
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nRF51822.lib	Fri Jan 19 02:38:38 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/teams/Nordic-Semiconductor/code/nRF51822/#c90ae1400bf2