Javier Vargas
/
ControllerBLE
Test
source/main.cpp
- Committer:
- HelGast95
- Date:
- 2019-02-04
- Revision:
- 81:dded8c042cca
- Parent:
- 80:5e52c5847273
File content as of revision 81:dded8c042cca:
#define END_OF_JSON 0xFE #define VERBOSE_MODE 1 // Habilita la generacion de logs por el puerto USB #include "mbed.h" #include "picojson.h" #include "stats_report.h" /* Librerías para BLE - Servicio GATT */ #include "ble/BLE.h" #include "ble/Gap.h" #include "TOFService.h" #include "ble/DiscoveredCharacteristic.h" #include "ble/DiscoveredService.h" const static char DEVICE_NAME[] = "BLE_CONTROLLER"; static const uint16_t uuid16_list[] = {TOFService::CUSTOM_TOF_SERVICE_UUID}; bool serviceDiscovered = false; char finalCharacterJSON = END_OF_JSON; typedef struct { string MAC1; /* Dirección MAC1*/ string MAC2; /* Dirección MAC2*/ double ToF; /* Tiempo de vuelo*/ } BLEdata_t; typedef struct { string hazardousDevice; /* MAC dispositvo peligroso */ string affectedDevice; /* MAC dispositivo afectado */ uint8_t type; /* Tipo de evento */ } JSONdata_t; DigitalOut led3Test(LED3); DigitalOut led4BLE(LED4); Serial pcSerial(USBTX, USBRX); // Abrimos conexión serial con el puerto USB TOFService* tofService; EventQueue eventQueue; Queue<JSONdata_t, 32> JSONqueue; Queue<BLEdata_t, 32> BLEqueue; Mail<BLEdata_t, 16> BLEMail; Thread threadLED(osPriorityAboveNormal1, 400); Thread threadSerial(osPriorityAboveNormal2, 2500); Thread threadBLE(osPriorityRealtime3, 2500); Thread threadCalculateEvent(osPriorityRealtime2, 1500); template<typename arg> void printLog(const char * log, arg data) { if(VERBOSE_MODE) printf(log, data); } void printLog(const char * log) { if(VERBOSE_MODE) printf(log); } /** * Thread encargado de parpadear un LED continuamente */ void blinkLED3() { while(true) { led3Test = !led3Test; wait(0.8); } } /** * Método encargado de enviar un string por el puerto serie char a char */ void sendCharArrayToSerial(char const *array, Serial *serial) { uint32_t i = 0; while(array[i] != '\0') { serial->putc(array[i]); i++; } serial->putc('\0'); } /** * Thread encargado de calcular el tipo de evento a enviar */ void calculateEvent() { while(true) { printLog("Leo evento de BLEMail\r\n"); osEvent evt = BLEMail.get(); printLog("Evento leido de BLEMail\r\n"); if (evt.status == osEventMail) { BLEdata_t *dataIn = (BLEdata_t*) evt.value.p; printLog("ToF: %s\r\n", dataIn->ToF); printLog("Se obtiene puntero de BLEdata\r\n"); JSONdata_t event; printLog("Se declara objeto JSONdata_t\r\n"); if(dataIn->ToF > 1.0) { printLog("Evento de tipo 1\r\n"); event.hazardousDevice = dataIn->MAC1; event.affectedDevice = dataIn->MAC2; event.type = 1; } else { // Keep Alive event.type = 0; event.hazardousDevice = dataIn->MAC1; } BLEMail.free(dataIn); printLog("Se va a escribir en la cola de JSON\r\n"); JSONqueue.put(&event); printLog("Evento enviado a JSON\r\n"); } } } /** * Thread encargado de enviar JSONs por el puerto serie */ void sendJsonOverSerial() { char tmp[512]; // Vble auxiliar para el tratamiento de cadenas de char. string str; while(true) { // Esperamos a un mensaje en la cola picojson::object json; picojson::object event; picojson::object extraInfo; osEvent evt = JSONqueue.get(); if (evt.status == osEventMessage) { JSONdata_t *data = (JSONdata_t*) evt.value.p; int id = rand() % 1000; event["idEvent"] = picojson::value((double) id); event["type"] = picojson::value((double) data->type); //str = "E9:ED:F4:AC:BF:8E"; extraInfo["hazardousDevice"] = picojson::value(data->hazardousDevice); //str = "D5:62:12:BF:B8:45"; if(data->type != 0) extraInfo["affectedDevice"] = picojson::value(data->affectedDevice); event["extraInfo"] = picojson::value(extraInfo); json["Event"] = picojson::value(event); str = picojson::value(json).serialize(); // Convertimos el string a char * strncpy(tmp, str.c_str(), sizeof(tmp)); strncat(tmp, &finalCharacterJSON, sizeof(finalCharacterJSON)); // Añadimos el caracter al final tmp[sizeof(tmp) - 1] = 0; sendCharArrayToSerial(tmp, &pcSerial); } } } void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { printLog("Desconectado. Se comienza la fase de Advertising de nuevo\r\n"); BLE::Instance(BLE::DEFAULT_INSTANCE).gap().startAdvertising(); } void connectionCallback(const Gap::ConnectionCallbackParams_t *params) { printLog("Conectado al servidor\r\n"); } void parseRawJSONToQueue(string JSONsource) { picojson::value v; string err, MAC1, MAC2; BLEdata_t *data = BLEMail.alloc();; picojson::parse(v, JSONsource.c_str(), JSONsource.c_str() + strlen(JSONsource.c_str()), &err); printLog("res error? %s\r\n", err); printLog("ToF %f\r\n", v.get("TOF").get<double>()); MAC1 = v.get("MAC1").get<string>(); MAC2 = v.get("MAC2").get<string>(); printLog("MAC1 en string: %s", MAC1); printLog("MAC2 en string: %s", MAC2); data->ToF = v.get("TOF").get<double>(); printLog("Se leen los datos del JSON\r\n"); printLog("ToF = %f", data->ToF); printLog(" MAC1 = %s", data->MAC1); printLog(" MAC2 = %s\r\n", data->MAC2); BLEMail.put(data); printLog("Se introduce dato en BLEqueue\r\n"); } void writeCharCallback(const GattWriteCallbackParams *params) { if(params->handle == tofService->getValueHandle()) { char toChar [TOFService::TOF_CHAR_ARRAY_SIZE]; printLog("Data received: length = %d, data = 0x", params->len); for(int x=0; x < params->len; x++) { toChar[x] = (char) params->data[x]; printLog("%x", params->data[x]); } //toChar[params->len] = '\0'; printLog("\n\r"); printLog("Cadena: %s\n\r", toChar); string str(toChar); eventQueue.call(parseRawJSONToQueue, str); } } /** * Esta función se llama si ha habido algún error en el proceso de inicialización del BLE */ void onBleInitError(BLE &ble, ble_error_t error) { printLog("Ha ocurrido un error al inicializar la configuracion del BLE\n"); } /** * 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) { return; } ble.gap().onDisconnection(disconnectionCallback); ble.gap().onConnection(connectionCallback); ble.gattServer().onDataWritten(writeCharCallback); tofService = new TOFService(ble); /* Setup advertising */ ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // BLE only, no classic BT ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); // advertising type ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // add name ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); // UUID's broadcast in advertising packet ble.gap().setAdvertisingInterval(100); // 100ms. /* Start advertising */ ble.gap().startAdvertising(); } void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) { BLE &ble = BLE::Instance(); eventQueue.call(Callback<void()>(&ble, &BLE::processEvents)); } void BLEServiceManagment() { BLE &ble = BLE::Instance(); ble.onEventsToProcess(scheduleBleEventsProcessing); ble.init(bleInitComplete); eventQueue.dispatch_forever(); } int main() { srand(time(NULL)); threadLED.start(callback(blinkLED3)); threadBLE.start(callback(BLEServiceManagment)); threadSerial.start(callback(sendJsonOverSerial)); threadCalculateEvent.start(callback(calculateEvent)); threadLED.join(); threadBLE.join(); threadSerial.join(); threadCalculateEvent.join(); }