![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Dependencies: AccelSensor BLE_API mbed nRF51822
Revision 0:027b7829b46a, committed 2018-01-19
- Comitter:
- fjaviercifuentes
- Date:
- Fri Jan 19 02:38:38 2018 +0000
- Commit message:
Changed in this revision
--- /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