Firmware

Dependencies:   BMI160 ADT7410 Thermistor DS1621 max32630fthr Adafruit_FeatherOLED

ble_functions.cpp

Committer:
condato_mbed
Date:
2020-07-09
Revision:
2:b802b30cc7d2
Parent:
0:556294574340

File content as of revision 2:b802b30cc7d2:

#include "functions.h"
#include "ble_functions.h"
#include "RawSerial.h"
#include <InterruptIn.h>
#include <InterruptManager.h>
#include "bmi160.h"
#include "max32630fthr.h"
#include "max3263x.h"
#include "MAX14690.h"
#include "ADT7410.h"
#include "Adafruit_SSD1306.h"
#include <BLE.h>
#include "ble/BLE.h"
#include "ble/Gap.h"
#include "ble/services/BatteryService.h"
#include "ble/blecommon.h"
#include "UUID.h"
#include "ble/gap/AdvertisingDataTypes.h"
#include "ble/gap/Types.h"
#include "SDBlockDevice.h"
#include "FATFileSystem.h"
#include <errno.h>
#include <stdio.h>
#include <time.h>
#include <stdint.h>

extern char device_id[];
extern unsigned short int measure_id;
extern unsigned short int log_id;

extern Serial pan1326b;
extern DigitalOut bt_rst;

extern volatile int conn_state;
extern bool in_BT;

extern AnalogIn battery;

extern DigitalOut r;
extern DigitalOut g;
extern DigitalOut b;
extern DigitalOut RGBs[];

extern MAX32630FTHR pegasus;

extern ADT7410 myADT7410;
extern I2C i2cm2;
extern MAX14690 max14690;

extern InterruptIn button;

extern FATFileSystem fileSystem;
extern SDBlockDevice blockDevice;

extern I2C i2c;
extern int sensor_temp;
extern Adafruit_SSD1306_I2c featherOLED;

extern volatile int quit;
extern volatile int ble_return;
extern volatile int conn_state;
extern int counter_ble;

extern bool error_status;
extern bool BT_error;
extern bool shipping;
extern bool pause;
extern bool init_status;
extern bool after_BT;
extern bool charge;

extern Timeout after_BLE;
extern Timeout turnoff;
extern Timeout flipper;                    
extern Timeout advertise_cancel;         
extern Timeout connected_cancel;         
extern Ticker mess_timer;                 
extern Ticker ticker;
extern time_t now;
extern time_t raw;

extern float    buffer_temp;
extern struct   tm current;
extern struct   tm actual;

extern struct user_config_struct user_config_para;
extern struct tm user_config_time;

extern Timeout done_rcv;

extern int next_state;

extern int unsigned long t_diff;
extern int unsigned long unix_time;

extern int default_advertise_time;
extern int default_connected_time;

extern int alert_count;

int ble_buff_line = 0;
char ble_buff[1024][64];

char response = '0';
char messungen[7];
int messwerte[5000];
char logs_array[7];
char seconds[12];
float min_temp = 0;
float max_temp = 0;
float avr_temp = 0;
unsigned short counter_m = 0;
unsigned short counter_l = 0;
int sendLedCounter = 0;

//const static char* SERVICE_UUID = "32372fb9-5f73-4c32-a17b-25e17f52a99a";
static uint8_t service_data[16];

//const static char* CHARACTERISTIC_UUID = "1d6ba3db-d405-4034-96fc-78942ef7075f";

uint16_t customServiceUUID  = 0xA000;
uint16_t readCharUUID       = 0xA001;
uint16_t writeCharUUID      = 0xA002;
uint16_t battService        = 0x180F;

const static char DEVICE_NAME[] = "Cold Chain Logger";

static const uint16_t uuid16_list[] = {0xFFFF};
//static const uint8_t advData[26];

//UUID service_uuid =  UUID(SERVICE_UUID);
//UUID characteristic_uuid = UUID(CHARACTERISTIC_UUID);

//Gap::ConnectionParams_t fast;

// Set Up custom Charatiristics
static uint8_t readValue[360];
//ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(readCharUUID, readValue);
ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(readCharUUID, readValue, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY ,NULL,0);

static uint8_t writeValue[20];
//WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(writeCharUUID, writeValue);
WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(writeCharUUID, writeValue, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE ,NULL,0);

// Set up custom service
GattCharacteristic *characteristics[] = {&readChar, &writeChar};
GattService        customService(customServiceUUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *));

//Battery service
uint8_t batteryLevel = 50;
static BatteryService* batteryServicePtr;

void periodicCallback(void)
{
    b = !b;
}

void writeLedCallback(void)
{
    b = !b;
    ticker.detach();
}

void sendLedCallback(void)
{
    b = !b;
    if(sendLedCounter == 2){
        ticker.detach();
        sendLedCounter = 0;
    }else{
        sendLedCounter++;
    }
}

void clear_buffer(){
    if(response != 's'){
        counter_m = 0;
    }else if(response != 'l'){
        counter_l = 0;
    }
    ble_buff_line = 0;
    memset(&ble_buff[0][0], 0, sizeof(ble_buff));
    memset(&readValue[0], 0, sizeof(readValue));
    memset(&writeValue[0], 0, sizeof(writeValue));
}

void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *)
{
    printf("\nDisconnection callback\n");
    clear_buffer();
    connected_cancel.detach();
    ticker.attach(periodicCallback, 0.5);
    advertise_cancel.attach(&BT_false, user_config_para.advertise);
    char string[] = "Bluetooth disconnected";
    write_to_sd_log_single(string);
    conn_state = 0;
    counter_m = 0;
    counter_l = 0;
    BLE::Instance(BLE::DEFAULT_INSTANCE).startAdvertising();
    printf("\nAdvertising\n");
}

void updateSensorValue() {
    float batteryProcent = (100 / 0.271) * (battery.read() - 0.704);
    if(batteryProcent > 97){
        batteryProcent = 100;
    }
    batteryLevel = batteryProcent;
    batteryServicePtr->updateBatteryLevel(batteryProcent);
}

void printMacAddress()
{
    Gap::AddressType_t addr_type;
    Gap::Address_t address;
    BLE::Instance().gap().getAddress(&addr_type, address);
    printf("Device MAC address: ");
    for (int i = 5; i >= 1; i--){
        printf("%02x:", address[i]);
    }
    printf("%02x\r\n", address[0]);
}

void writeCharCallback(const GattWriteCallbackParams *params)
{
    printf("\nData received\n");
    //b = 1;
    //ticker.attach(writeLedCallback, 0.5);
    memset(&readValue[0], 0, sizeof(readValue));
    memset(&writeValue[0], 0, sizeof(writeValue));
    BLE::Instance(BLE::DEFAULT_INSTANCE).gattServer().write(readChar.getValueHandle(), params->data, params->len);
    for(int i = 0; i < 15; i++){
        ble_buff[0][i + ble_buff_line] = readValue[i];
    }
    printf("\n%s received (ble_buff)", ble_buff[0]);
    ble_buff_line = ble_buff_line + 15;
    if(readValue[0] > 0x60 && readValue[0] < 0x7a){
        response = readValue[0];
    }else if(response != 's' && response != 'l' && response != 'e' && response != 't'){
        clear_buffer();
    }
    printf("\nresponse: %c\n", response);
}

void disconnect(){
    Gap::DisconnectionReason_t res=Gap::LOCAL_HOST_TERMINATED_CONNECTION;
    BLE::Instance(BLE::DEFAULT_INSTANCE).gap().disconnect(res);
}

void whenConnected(const Gap::ConnectionCallbackParams_t *)
{
    printf("\nConnected\n");
    advertise_cancel.detach();
    ticker.detach();
    connected_cancel.attach(&disconnect, user_config_para.connected);
    conn_state = 1;
    if(error_status == true){
        r = 1;
    }
    b = 0;
    response = '0';
    char string[] = "Bluetooth connected";
    write_to_sd_log_single(string);
}

void onDataSent(unsigned count)
{
    printf("%c", ble_buff[ble_buff_line][count]);
    readValue[count] = ble_buff[ble_buff_line][count];
}

void after_BL(){
    after_BT = false;
    after_BLE.detach();
}

void BT_false()
{
    BLE &ble = BLE::Instance();
    in_BT = false;
    b = 1;
    conn_state = 0;
    quit = 0;
    clear_buffer();
    ticker.detach();
    advertise_cancel.detach();
    connected_cancel.detach();
    disconnect();
    wait(0.5);
    if(error_status == true){
        r = 0;
    }
    if(shipping == true && pause == false){
        mess_timer.attach(&mess_handler, (float)user_config_para.interval);
    }
    after_BT = true;
    after_BLE.attach(after_BL, 1);
    response = '0';
}

void BT_true() 
{
    in_BT = true;
    next_state = 2;
}

void log_count(){
    fileSystem.unmount();
    fflush(stdout);
    
    fileSystem.mount(&blockDevice);
    FILE * log = fopen ("/fs/log.csv", "rb");
    
    int ch = 0;
    int lines = 0;
    
    while(!feof(log)){
        ch = fgetc(log);
        if(ch == '\n')
        {
            lines++;
        }
    }
    
    log_id = lines;
    
    fclose(log);
    fileSystem.unmount();
    
    sprintf(logs_array,"%d", lines);
}

void messdaten_count(){
    fileSystem.unmount();
    fflush(stdout);
    
    fileSystem.mount(&blockDevice);
    FILE * messdaten = fopen ("/fs/messdaten.csv", "rb");
    
    int ch = 0;
    int lines = 0;
    
    while(!feof(messdaten)){
        ch = fgetc(messdaten);
        if(ch == '\n')
        {
            lines++;
        }
    }
    
    fclose(messdaten);
    fileSystem.unmount();
    
    measure_id = lines;
    
    sprintf(messungen,"%d", lines);
}

void unixtime_to_char_array(){
    tm *current;
    time(&now);
    current = localtime (&now);
    printf ("\nDate: 20%02d-%02d-%02d %02d:%02d:%02d\r\n", current->tm_year - 100, current->tm_mon + 1, current->tm_mday, current->tm_hour, current->tm_min, current->tm_sec);
    
    printf("\nSekunden als Dezimal: %d\n", time(&now));
    
    sprintf(seconds,"%d", time(&now));
    
    printf("\nSekunden als String: %s\n", seconds);
}

int array_to_int(int z){
    int zahl[z];
                            
    for(int i = 0; i < z; i++){
        zahl[i] = readValue[i];
        zahl[i] = zahl[i] - 48;
    }
               
    unsigned long ganzes = 0;
    unsigned long log = 1;
    int j = z;
    do{
        j--;
        ganzes = ganzes + log * zahl[j];
        log = log * 10;
    }while(j > 0);
    
    if((int)ganzes < 0){
        ganzes = 0;
    }
    return ganzes;
}

void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
{
    BLE &ble          = params->ble;
    ble_error_t error = params->error;

    if (error != BLE_ERROR_NONE) {
        return;
    }
    
    read_id();
    
    /* 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::SHORTENED_LOCAL_NAME, (const uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // add name
    ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::DEVICE_ID, (uint8_t *)device_id, 5); // 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.
    
    /* Add custom service */
    ble.gattServer().addService(customService);
    
    /* Add battery service */
    batteryServicePtr = new BatteryService(ble, batteryLevel);
    
    ble.gap().onDisconnection(disconnectionCallback);
    ble.gap().onConnection(whenConnected);
    ble.gattServer().onDataWritten(writeCharCallback);
    ble.gattServer().onDataSent(onDataSent);
    
    /* Start advertising */
    ble.gap().startAdvertising();
}

void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
    BLE &ble = BLE::Instance();
    updateSensorValue();
}

void dataSentSend(){
    response = '0';
    connected_cancel.attach(&disconnect, user_config_para.connected);
}

void dataSent(){
    //wait(1);
    //b = 1;
    //ticker.attach(sendLedCallback, 0.5);
    response = '0';
    connected_cancel.attach(&disconnect, user_config_para.connected);
}

void swap(int num1, int num2){
    int temp = messwerte[num1];
    messwerte[num1] = messwerte[num2];
    messwerte[num2] = temp;
}

int partition(int left, int right, int pivot){
    int leftPointer = left - 1;
    int rightPointer = right;
    
    while(true){
        while(messwerte[++leftPointer] < pivot){
            //do nothing
        }
        
        while(rightPointer > 0 && messwerte[--rightPointer] > pivot){
            //do nothing
        }
        
        if(leftPointer >= rightPointer){
            break;
        }else{
            swap(leftPointer, rightPointer);
        }
    }
    swap(leftPointer, right);
    
    return leftPointer;
}

void quickSort(int left, int right){
    if(right - left <= 0){
        return;
    }else{
        int pivot = messwerte[right];
        int partionPoint = partition(left, right, pivot);
        quickSort(left, partionPoint - 1);
        quickSort(partionPoint + 1, right);
    }
}

void BLE_handler()
{
    BLE &ble = BLE::Instance();
    b = 0;
    ticker.attach(periodicCallback, 0.5);
    advertise_cancel.attach(&BT_false, user_config_para.advertise);
    clear_buffer();
    next_state = 0;
    printf("\nBLE - ON\n");
    printf("\nAdvertising\n");
    
    while( quit )
    {
        ble.waitForEvent();
        ble.onEventsToProcess(scheduleBleEventsProcessing);
        
        while ( conn_state ) //Abfrage zum Verbindungsstatus
        {
            ble.waitForEvent();
            ble.onEventsToProcess(scheduleBleEventsProcessing);
            
            /*
            if(readValue[0] == NULL){
                ble.onEventsToProcess(scheduleBleEventsProcessing);
            }
            */
            
            switch ( response )
            {
                /*
                case 's':   // Messwerte übertragen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    unsigned int length = 0;
                    
                    connected_cancel.attach(&disconnect, user_config_para.connected);
                    while(readValue[0] == NULL || readValue[0] < 0x31|| readValue[0] > 0x39){
                        clear_buffer();
                        ble.waitForEvent();
                        if(conn_state == 0){
                            break;
                        }
                    }
                    connected_cancel.detach();
                    if(conn_state == 1){
                    int a = 0;
                    while(readValue[a] != NULL){
                        a++;
                    }
                    int id = array_to_int(a);
                    clear_buffer();
                    
                    fileSystem.mount(&blockDevice);
                    FILE * messdaten = fopen ("/fs/messdaten.csv", "rb");
                    
                    fseek (messdaten, 0, SEEK_END);
                    length = ftell (messdaten);
                    fseek (messdaten, 0, SEEK_SET);
                    
                    if(id > measure_id){
                        printf("\nMeasuremnt ID %d doesn't exist!\n", id);
                        char string[] = "Call of an inexistent measurement ID";
                        write_to_sd_log_single(string);
                        
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                    }else{
                        unsigned long ch = 0;
                        unsigned long lines = 0;
                        unsigned long i = 0;
                        unsigned long j = 1;
                        unsigned long c = 0;
                    
                        if(id == 1){
                            fseek(messdaten, 0, SEEK_SET);
                        }else{
                            while((id - 1) != lines){
                                ch = fgetc(messdaten);
                                if(ch == '\n'){
                                    lines++;
                                }
                                i++;
                            }
                            fseek(messdaten, i, SEEK_SET);
                            c = i;
                        }
                        if(id == measure_id){
                            while(fgetc(messdaten) != EOF){
                                i++;
                                j++;
                            }
                        }else{
                            while(fgetc(messdaten) != '\n'){
                                i++;
                                j++;
                            }
                        }
                        fseek(messdaten, c, SEEK_SET);
                        fread (ble_buff[ble_buff_line], 1, j, messdaten);
    
                        for(int l = 0; l < j; l++){
                            onDataSent(l);
                        }
                    }
                    
                    fclose(messdaten);
                    fileSystem.unmount();
                    fflush(stdout);
                    
                    dataSentSend();
                }
                    break;
                }
                */
                
                case 's':   // Messwerte übertragen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    if(counter_m == 0){
                        char string[] = "Command 's' (send measuremnts) received";
                        write_to_sd_log_single(string);
                    }
                    
                    connected_cancel.attach(&disconnect, user_config_para.connected);
                    while(readValue[0] == NULL || readValue[0] < 0x31|| readValue[0] > 0x39){
                        clear_buffer();
                        ble.waitForEvent();
                        if(conn_state == 0){
                            break;
                        }
                    }
                    connected_cancel.detach();
                    if(conn_state == 1){
                        
                        if(counter_m == 0){
                            char string1[] = "Sending measuremnts...";
                            write_to_sd_log_single(string1);
                        }
                        
                        int a = 0;
                        while(readValue[a] != NULL){
                            a++;
                        }
                        int id = array_to_int(a);
                        clear_buffer();
                        
                        fileSystem.mount(&blockDevice);
                        FILE * messdaten = fopen ("/fs/messdaten.csv", "rb");
                        
                        /* Daten senden */
                        
                        if(id > measure_id){
                            printf("\nMeasuremnt ID %d doesn't exist!\n", id);
                            char string[] = "Call of an inexistent measurement ID";
                            write_to_sd_log_single(string);
                        
                            ble_buff[0][0] = '0';
                            onDataSent(0);
                        }else{
                            unsigned long ch = 0;
                            unsigned long lines = 0;
                            unsigned long i = 0;
                            unsigned long j = 1;
                            unsigned long c = 0;
                            
                            if(id == 1){
                                fseek(messdaten, 0, SEEK_SET);
                            }else{
                                while((id - 1) != lines){
                                    ch = fgetc(messdaten);
                                    if(ch == '\n'){
                                        lines++;
                                    }
                                    i++;
                                }
                                fseek(messdaten, i, SEEK_SET);
                                c = i;
                            }
                            if(id == measure_id){
                                while(fgetc(messdaten) != EOF){
                                    i++;
                                    j++;
                                }
                            }else{
                                int y = 0;
                                while(y < 10){
                                    i++;
                                    j++;
                                    ch = fgetc(messdaten);
                                    if(ch == '\n'){
                                        y++;
                                    }
                                    if(ch == EOF){
                                        break;
                                    }
                                }
                                i--;
                                j--;
                            }
                            fseek(messdaten, c, SEEK_SET);
                            fread (ble_buff[ble_buff_line], 1, j, messdaten);
                            
                            for(int l = 0; l < j; l++){
                                onDataSent(l);
                            }
                        }
                        
                        fclose(messdaten);
                        fileSystem.unmount();
                        fflush(stdout);
                        
                        counter_m += 10;
                        if(counter_m >= measure_id){
                            char string2[] = "Sending measuremnts complete";
                            write_to_sd_log_single(string2);
                            counter_m = 0;
                            dataSent();
                        }else{
                            dataSentSend();
                        }
                    }
                    break;
                }
                
                case 'g':  //Config senden
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'g' (send config settings) received";
                    write_to_sd_log_single(string);
            
                    unsigned int length = 0;
                    
                    char string_1[] = "Sending config..";
                    write_to_sd_log_single(string_1);
                    
                    fileSystem.mount(&blockDevice);
                    FILE * user_config = fopen ("/fs/user_config.csv", "rb");
                    
                    fseek (user_config, 0, SEEK_END);
                    length = ftell (user_config);
                    fseek (user_config, 0, SEEK_SET);
                     
                    fread (ble_buff, 1, length, user_config);
                    
                    fclose(user_config);
                    fileSystem.unmount();
                    
                    fflush(stdout);
                    
                    for(int i = 0; i < length; i++){
                         onDataSent(i);
                    }
                    
                    char string_2[] = "Sending config complete";
                    write_to_sd_log_single(string_2);
                    
                    dataSent();
                    
                    break;
                }
                
                case 'c':   // Config auf Werkeinstellungen zurücksetzen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'c' (reset config to standard) received";
                    write_to_sd_log_single(string);
                    
                    if(load_standard_config() == 1){
                        char string[] = "Config reseted to factory settings";
                        write_to_sd_log_single(string);
                        
                        ble_buff[0][0] = '1';
                        onDataSent(0);
                    }else{
                        char string[] = "Failed to reset Config to factory settings";
                        write_to_sd_log_single(string);
                        
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                    }
                    
                    dataSent();
                    
                    break;
                }
                
                case 'd':   // Messwerte löschen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'd' (delete measurement data) received";
                    write_to_sd_log_single(string);
                    
                    if(delete_file_messdaten() == 1){
                        char string_1[] = "Measuerements deleted succesfully";
                        write_to_sd_log_single(string_1);
                        
                        ble_buff[0][0] = '1';
                        onDataSent(0);
                    }else{
                        char string_1[] = "Measuerements data delete failed";
                        write_to_sd_log_single(string_1);
                        
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                    }
                    
                    dataSent();
                    
                    break;
                }
                /*
                case 'l':    //Log-Datei übertragen
                {
                    
                    connected_cancel.detach();
                    clear_buffer();
                    
                    unsigned int length = 0;
                    
                    connected_cancel.attach(&disconnect, user_config_para.connected);
                    while(readValue[0] == NULL || readValue[0] < 0x31|| readValue[0] > 0x39){
                        clear_buffer();
                        ble.waitForEvent();
                        if(conn_state == 0){
                            break;
                        }
                    }
                    connected_cancel.detach();
                    if(conn_state == 1){
                    int a = 0;
                    while(readValue[a] != NULL){
                        a++;
                    }
                    int id = array_to_int(a);
                    clear_buffer();
                        
                    fileSystem.mount(&blockDevice);
                    FILE * log = fopen ("/fs/log.csv", "rb");
                    
                    fseek (log, 0, SEEK_END);
                    length = ftell (log);
                    fseek (log, 0, SEEK_SET);
                        
                    
                    
                    if(id > log_id){
                        printf("\nLog ID %d doesn't exist!\n", id);
                        char string[] = "Call of an inexistent log ID";
                        write_to_sd_log_single(string);
                        
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                    }else{
                        unsigned long ch = 0;
                        unsigned long lines = 0;
                        unsigned long i = 0;
                        unsigned long j = 1;
                        unsigned long c = 0;
                    
                        if(id == 1){
                            fseek(log, 0, SEEK_SET);
                        }else{
                            while((id - 1) != lines){
                                ch = fgetc(log);
                                if(ch == '\n'){
                                    lines++;
                                }
                                i++;
                            }
                            fseek(log, i, SEEK_SET);
                            c = i;
                        }
                        if(id == log_id){
                            while(fgetc(log) != EOF){
                                i++;
                                j++;
                            }
                        }else{
                            while(fgetc(log) != '\n'){
                                i++;
                                j++;
                            }
                        }
                        fseek(log, c, SEEK_SET);
                        fread (ble_buff[ble_buff_line], 1, j, log);
    
                        for(int l = 0; l < j; l++){
                            onDataSent(l);
                        }
                    }
                    
                    fclose(log);
                    fileSystem.unmount();
                    fflush(stdout);
                        
                    dataSentSend();
                }
                    break;
                }
                */
                
                case 'l':   //Log-Datei übertragen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    if(counter_l == 0){
                        char string[] = "Command 'l' (send logs) received";
                        write_to_sd_log_single(string);
                    }
                    
                    connected_cancel.attach(&disconnect, user_config_para.connected);
                    while(readValue[0] == NULL || readValue[0] < 0x31|| readValue[0] > 0x39){
                        clear_buffer();
                        ble.waitForEvent();
                        if(conn_state == 0){
                            break;
                        }
                    }
                    connected_cancel.detach();
                    if(conn_state == 1){
                        
                        if(counter_l == 0){
                            char string1[] = "Sending logs...";
                            write_to_sd_log_single(string1);
                        }
                        
                        int a = 0;
                        while(readValue[a] != NULL){
                            a++;
                        }
                        int id = array_to_int(a);
                        clear_buffer();
                    
                        fileSystem.mount(&blockDevice);
                        FILE * log = fopen ("/fs/log.csv", "rb");
                    
                        /* Daten senden */
                    
                        if(id > log_id){
                            printf("\nLog ID %d doesn't exist!\n", id);
                            char string[] = "Call of an inexistent log ID";
                            write_to_sd_log_single(string);
                        
                            ble_buff[0][0] = '0';
                            onDataSent(0);
                        }else{
                            unsigned long ch = 0;
                            unsigned long lines = 0;
                            unsigned long i = 0;
                            unsigned long j = 1;
                            unsigned long c = 0;
                    
                            if(id == 1){
                                fseek(log, 0, SEEK_SET);
                            }else{
                                while((id - 1) != lines){
                                    ch = fgetc(log);
                                    if(ch == '\n'){
                                        lines++;
                                    }
                                    i++;
                                }
                                fseek(log, i, SEEK_SET);
                                c = i;
                            }
                            if(id == log_id){
                                while(fgetc(log) != EOF){
                                    i++;
                                    j++;
                                }
                            }else{
                                int y = 0;
                                while(y < 5){
                                    i++;
                                    j++;
                                    ch = fgetc(log);
                                    if(ch == '\n'){
                                        y++;
                                    }
                                    if(ch == EOF){
                                        break;
                                    }
                                }
                                i--;
                                j--;
                            }
                            fseek(log, c, SEEK_SET);
                            fread (ble_buff[ble_buff_line], 1, j, log);
    
                            for(int l = 0; l < j; l++){
                                onDataSent(l);
                            }
                        }
                    
                        fclose(log);
                        fileSystem.unmount();
                        fflush(stdout);
                    
                        counter_l += 5;
                        if(counter_l >= measure_id){
                            char string2[] = "Sending logs complete";
                            write_to_sd_log_single(string2);
                            counter_l = 0;
                            dataSent();
                        }else{
                            dataSentSend();
                        }
                    }
                    break;
                }
                
                case 'r':   // Log Datei löschen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'r' (delete log file) received";
                    write_to_sd_log_single(string);
                    
                    if(delete_file_log() == 1){
                        char string_1[] = "Log file deleted";
                        write_to_sd_log_single(string_1);
                        
                        ble_buff[0][0] = '1';
                        onDataSent(0);
                    }else{
                        char string_1[] = "Log file delete failed";
                        write_to_sd_log_single(string_1);
                        
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                    }
                    
                    dataSent();
                    
                    break;
                }
                
                case 'n': //Reset
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'n' (reboot) received";
                    write_to_sd_log_single(string);
                    BT_false();
                    wait(0.5);
                    reboot();
                    break;
                }
                
                case 'w':   // Werkeinstellungen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'w' (reset to factory settings) received";
                    write_to_sd_log_single(string);
                    
                    if(delete_file_messdaten() && load_standard_config() && delete_file_log() == 1){
                        char string_1[] = "System reseted to factory settings";
                        write_to_sd_log_single(string_1);
                        
                        ble_buff[0][0] = '1';
                        onDataSent(0);
                        
                        printf("\n__________________________\n\nColdchainlogger reseted \nto factory settings\n__________________________\n\n");
                    }else{
                        char string_1[] = "System reset to factory settings failed";
                        write_to_sd_log_single(string_1);
                        
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                    }
                    
                    dataSent();
                    
                    break;
                }
                
                case 'a':   // Datenaufnahme pausieren / stoppen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'a' (pause / stop measurement) received";
                    write_to_sd_log_single(string);
                    
                    mess_timer.detach();
                    next_state = 0;
                    
                    if(pause == true){
                        char string_1[] = "Measurement stopped";
                        write_to_sd_log_single(string_1);
                        printf("\nMeasurement stopped\n");
                        shipping = false;
                        
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                    }else{
                        pause = true;
                        char string_1[] = "Measurement paused";
                        write_to_sd_log_single(string_1);
                        printf("\nMeasurement puased\n");
                        
                        ble_buff[0][0] = '1';
                        onDataSent(0);
                    }
                    
                    mess_timer.detach();
                    
                    dataSent();
                    
                    break;
                }
                
                case 'f':   // Datenaufnahme starten / fortsetzen  
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'f' (start / continue measurement) received";
                    write_to_sd_log_single(string);
                    
                    if(shipping == false){
                        char string_1[] = "Measurement started";
                        write_to_sd_log_single(string_1);
                        shipping = true;
                        pause = false;
                        
                        if(user_config_para.wait_mode == 1){
                            next_state = 3;
                        }else{
                            next_state = 1;
                        }
                        printf("\nMeasurement started\n");
                        
                        ble_buff[0][0] = '1';
                        onDataSent(0);
                    }else{
                        next_state = 1;
                        char string_1[] = "Measurement continued";
                        write_to_sd_log_single(string_1);
                        printf("\nMeasurement continued\n");
                        pause = false;
                        
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                    }
                    
                    dataSent();
                    
                    break;
                }
                
                case 'e': //Config erhalten
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'e' (receive and overwrite config) received";
                    write_to_sd_log_single(string);
                    
                    connected_cancel.attach(&disconnect, user_config_para.connected);
                    printf("\nReady to receive new config settings\n");
                    
                    while(readValue[0] == NULL){
                        ble.waitForEvent();
                        if(conn_state == 0){
                            break;
                        }
                    }
                    memset(&readValue[0], 0, sizeof(readValue));
                    memset(&writeValue[0], 0, sizeof(writeValue));
                    while(readValue[0] == NULL){
                        ble.waitForEvent();
                        if(conn_state == 0){
                            break;
                        }
                    }
                    connected_cancel.detach();
                    if(conn_state == 1){
                    char params[50];
                    printf("\n%s\n", ble_buff[0]);
                    strcpy(params, ble_buff[0]);
                    
                    if(create_user_config(params) == 1){
                        clear_buffer();
                        
                        char string_1[] = "User config changed";
                        write_to_sd_log_single(string_1);
                        printf("\n__________________________\n\nUser config changed\n__________________________\n\n");
                        
                        ble_buff[0][0] = '1';
                        onDataSent(0);
                    }else{
                        clear_buffer();
                        
                        char string_1[] = "Changing user config failed";
                        write_to_sd_log_single(string_1);
                        printf("\n__________________________\n\n!!! Error, can't changing user config !!!\n__________________________\n\n");
                        
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                    }
                    
                    dataSent();
                }
                    break;
                }
                
                case 'x':   // Verbindung beenden
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'x' (shut down bluetooth) received";
                    write_to_sd_log_single(string);
                    
                    BT_false();
                    char string_1[] = "Bluetooth shuted down";
                    write_to_sd_log_single(string_1);
                    printf("\n\nBluetooth shuted down\n\n");
                    
                    dataSentSend();
                    clear_buffer();
                    
                    break;
                }
                
                case 'b': //Akku-Zustand
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'b' (send battery info) received";
                    write_to_sd_log_single(string);
                    
                    updateSensorValue();
                    int battery = (int)batteryLevel;
                    char bat[3];
                    sprintf(bat,"%d", battery);
                    int i = 0;
                    while(bat[i] != NULL){
                        ble_buff[0][i] = bat[i];
                        onDataSent(i);
                        i++;
                    }
                    printf("\nBattery level: %d %%\n", battery);
                    
                    dataSent();
                    
                    break;
                }
                
                case 'm': //Speicher-Belegung
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'm' (send memmory info) received";
                    write_to_sd_log_single(string);
                    
                    printf("\nTotal SD memory: %llu Bytes\n", blockDevice.size());
                    
                    unsigned long long length = 0;
                    
                    //ID Größe
                    fileSystem.mount(&blockDevice);
                    FILE * id = fopen ("/fs/id.csv", "rb");
                    
                    fseek (id, 0, SEEK_END);
                    length = ftell (id);
                    fseek (id, 0, SEEK_SET);
                    
                    fclose(id);
                    fileSystem.unmount();
                    fflush(stdout);
                    
                    unsigned long long idn = length;
                    length = 0;
                    
                    //Log Größe
                    fileSystem.mount(&blockDevice);
                    FILE * log = fopen ("/fs/log.csv", "rb");
                    
                    fseek (log, 0, SEEK_END);
                    length = ftell (log);
                    fseek (log, 0, SEEK_SET);
                    
                    fclose(log);
                    fileSystem.unmount();
                    fflush(stdout);
                    
                    unsigned long long logs = length;
                    length = 0;
                    
                    //Messdaten Größe
                    fileSystem.mount(&blockDevice);
                    FILE * messdaten = fopen ("/fs/messdaten.csv", "rb");
                    
                    fseek (messdaten, 0, SEEK_END);
                    length = ftell (messdaten);
                    fseek (messdaten, 0, SEEK_SET);
                    
                    fclose(messdaten);
                    fileSystem.unmount();
                    fflush(stdout);
                    
                    unsigned long long mes = length;
                    length = 0;
                    
                    //Standard Config Größe
                    fileSystem.mount(&blockDevice);
                    FILE * stcf = fopen ("/fs/standard_config.csv", "rb");
                    
                    fseek (stcf, 0, SEEK_END);
                    length = ftell (stcf);
                    fseek (stcf, 0, SEEK_SET);
                    
                    fclose(stcf);
                    fileSystem.unmount();
                    fflush(stdout);
                    
                    unsigned long long stcfg = length;
                    length = 0;
                    
                    //User Config Größe
                    fileSystem.mount(&blockDevice);
                    FILE * uscf = fopen ("/fs/user_config.csv", "rb");
                    
                    fseek (uscf, 0, SEEK_END);
                    length = ftell (uscf);
                    fseek (uscf, 0, SEEK_SET);
                    
                    fclose(uscf);
                    fileSystem.unmount();
                    fflush(stdout);
                    
                    unsigned long long uscfg = length;
                    length = 0;
                    
                    printf("\nID size: %llu Bytes\n", idn);
                    printf("Logs size: %llu Bytes\n", logs);
                    printf("Standard config size: %llu Bytes\n", stcfg);
                    printf("User config size: %llu Bytes\n\n", uscfg);
                    
                    unsigned long long not_measuremnts = idn + logs + stcfg + uscfg;
                    unsigned long long actual_size = blockDevice.size() - not_measuremnts;
                    printf("Available SD memory (100 %%) = total SD memory - configs & id (%llu Bytes) - logs\n", not_measuremnts);
                    printf("Available SD memory (100 %%): %llu Bytes\n\n", actual_size);
                    
                    messdaten_count();
                    printf("Measuremnts count: %s\n", messungen);
                    printf("Measurements size: %llu Bytes\n\n", mes);
                    
                    double hundert = 100;
                    double occupied = hundert / actual_size * mes;
                    printf("Occupied memory: %f %%\n", occupied);
                    
                    double free_mem = 100 - occupied;
                    printf("Available memory: %f %%\n", free_mem);
                    
                    char occ[3];
                    char free[3];
                    
                    if((int)occupied != 0){
                        occupied = ceil( occupied * 100.0 ) / 100.0;
                    }
                    if((int)free_mem != 0){
                        free_mem  = ceil( free_mem  * 100.0 ) / 100.0;
                    }
                    
                    sprintf(occ,"%d", (int)occupied);
                    sprintf(free,"%d", (int)free_mem);
                    
                    printf("OCC: %s\n", occ);
                    printf("FREE: %s\n", free);
                    
                    messdaten_count();
                    
                    int i = 0;
                    while(i < messungen[i] != NULL){
                        ble_buff[0][i] = messungen[i];
                        onDataSent(i);
                        i++;
                    }
                    ble_buff[0][i] = 0x3B;
                    onDataSent(i);
                    i++;
                    int j = 0;
                    while(j < occ[j] != NULL){
                        ble_buff[0][i] = occ[j];
                        onDataSent(i);
                        i++;
                        j++;
                    }
                    ble_buff[0][i] = 0x3B;
                    onDataSent(i);
                    i++;
                    int c = 0;
                    while(c < free[c] != NULL){
                        ble_buff[0][i] = free[c];
                        onDataSent(i);
                        i++;
                        c++;
                    }
                    ble_buff[0][i] = 0x3B;
                    onDataSent(i);
                    i++;
                    dataSent();
                    
                    break;
                }
                
                case 'i': //ID auslesen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'i' (send ID) received";
                    write_to_sd_log_single(string);
                    
                    char string_1[] = "Sending device ID...";
                    write_to_sd_log_single(string_1);
                    
                    printf("\nDevice ID: %s\n", device_id);
                    
                    int i = 0;
                    while(device_id[i] != NULL){
                        ble_buff[0][i] = device_id[i];
                        onDataSent(i);
                        i++;
                    }
                    
                    char string_2[] = "Sending device ID complete";
                    write_to_sd_log_single(string_2);
                    
                    dataSent();
                    
                    break;
                }
                
                case 'z': //Hardware Module abfragen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'z' (send connected devices) received";
                    write_to_sd_log_single(string);
                    
                    char string_1[] = "Sending connected devices...";
                    write_to_sd_log_single(string_1);
                    
                    printf("\nConnected devices: Temperature sensor\n");
                    
                    char sensor[4] = {'0', '0', '1'};
                    int i = 0;
                    while(sensor[i] != NULL){
                        ble_buff[0][i] = sensor[i];
                        onDataSent(i);
                        i++;
                    }
                    
                    char string_2[] = "Sending connected devices complete";
                    write_to_sd_log_single(string_2);
                    
                    dataSent();
                    
                    break;
                }
                
                case 'v': // Zeit in Unixformat von Datenlogger abfragen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'v' (send device time) received";
                    write_to_sd_log_single(string);
                    
                    unixtime_to_char_array();
                    for(int i = 0; i < sizeof(seconds); i++){
                        ble_buff[0][i] = seconds[i];
                        onDataSent(i);
                    }
                    
                    dataSent();
                    
                    break;
                }
                
                case 't': //Zeit in Unixformat an Datenlogger schicken
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 't' (receive and set device time) received";
                    write_to_sd_log_single(string);
                    
                    connected_cancel.attach(&disconnect, user_config_para.connected);
                    printf("\nReady to receive new time settings\n");
                    while(readValue[0] == NULL || readValue[0] < 0x31|| readValue[0] > 0x39){
                        clear_buffer();
                        ble.waitForEvent();
                        if(conn_state == 0){
                            break;
                        }
                    }
                    connected_cancel.detach();
                    if(conn_state == 1){
                    int a = 0;
                    while(readValue[a] != NULL){
                        a++;
                    }
                    int new_time = array_to_int(a);
                    clear_buffer();
                    
                    if(set_app_time(new_time) == 1){
                        ble_buff[0][0] = '1';
                        onDataSent(0);
                    }else{
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                    }
                    
                    dataSent();
                }
                    break;
                }
                
                case 'q': //Min- / Max- / Mittelwert schicken
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'q' (send min/max/average) received";
                    write_to_sd_log_single(string);
                    
                    connected_cancel.detach();
                    clear_buffer();
                    
                    unsigned int length = 0;
                    int a = 0;
                    
                    char string_1[] = "Sending min/max/average..";
                    write_to_sd_log_single(string_1);
                    
                    fileSystem.unmount();
                    fflush(stdout);
                    
                    fileSystem.mount(&blockDevice);
                    FILE * messdaten = fopen ("/fs/messdaten.csv", "rb");
                    
                    fseek (messdaten, 0, SEEK_END);
                    length = ftell (messdaten);
                    fseek (messdaten, 0, SEEK_SET);
                    
                    /* Daten senden */
                    
                    unsigned long ch = 0;
                    unsigned short lines = 0;
                    unsigned long i = 0;
                    unsigned long j = 1;
                    unsigned long c = 0;
                    unsigned long e = 0;
                    
                    while(!feof(messdaten)){
                        ch = fgetc(messdaten);
                        if(ch == '\n')
                        {
                            lines++;
                        }
                    }
                    
                    printf("\n%d Eintraege\n", lines);
                    
                    for(int a = 0; a < lines; a++)
                    {
                        messwerte[a] = *new int[8];
                    }
                    
                    char temp[8];
                    
                    fseek(messdaten, 0, SEEK_SET);
                    while(!feof(messdaten)){
                        ch = fgetc(messdaten);
                        if(ch == '\n'){
                            fseek(messdaten, i - 7, SEEK_SET);
                            fread (temp, 1, 7, messdaten);
                            messwerte[e] = atoi(temp);
                            memset(&temp[0], 0, sizeof(temp));
                            e++;
                        }else if(ch == EOF){
                            fseek(messdaten, i - 8, SEEK_SET);
                            fread (temp, 1, 8, messdaten);
                            messwerte[e] = atoi(temp);
                            memset(&temp[0], 0, sizeof(temp));
                        }
                        i++;
                    }
                    
                    unsigned long summe = 0;
                    
                    for(int q = 1; q < e; q++){
                        summe += messwerte[q];
                    }
                    printf("\nSumme: %lu\n", summe);
                    
                    double avr = summe / lines;
                    
                    fclose(messdaten);
                    fileSystem.unmount();
                    fflush(stdout);
                    
                    char string_2[] = "Sending min/max/average complete";
                    write_to_sd_log_single(string_2);
                    
                    quickSort(1, lines);
                    
                    if((int)avr != 0){
                        avr = ceil( avr * 100.0 ) / 100.0;
                    }
                    
                    char min[5];
                    char max[5];
                    char durch[5];
                    
                    sprintf(min,"%d", messwerte[1]);
                    sprintf(max,"%d", messwerte[lines]);
                    sprintf(durch,"%d", (int)avr);
                    
                    printf("\n%s, %s, %s\n", min, max, durch);
                    
                    int k = 0;
                    while(k < min[k] != NULL){
                        ble_buff[0][k] = min[k];
                        onDataSent(k);
                        k++;
                    }
                    ble_buff[0][k] = 0x3B;
                    onDataSent(k);
                    k++;
                    int p = 0;
                    while(p < max[p] != NULL){
                        ble_buff[0][k] = max[p];
                        onDataSent(k);
                        k++;
                        p++;
                    }
                    ble_buff[0][k] = 0x3B;
                    onDataSent(k);
                    k++;
                    int z = 0;
                    while(z < durch[z] != NULL){
                        ble_buff[0][k] = durch[z];
                        onDataSent(k);
                        k++;
                        z++;
                    }
                    ble_buff[0][k] = 0x3B;
                    onDataSent(k);
                    k++;
                    
                    dataSent();
                    
                    break;
                }
                
                case 'j': //Anzahl der Messungen schicken
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'j' (send measurements count) received";
                    write_to_sd_log_single(string);
                    
                    //Anzahl der Messdaten
                    messdaten_count();
                    int i = 0;
                    while(messungen[i] != NULL){
                        ble_buff[0][i] = messungen[i];
                        onDataSent(i);
                        i++;
                    }
                    printf("\nMeasurements count: %s\n", messungen);
                    
                    dataSent();
                    
                    break;
                }
                
                case 'h': //Anzahl der Logs schicken
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'h' (send log count) received";
                    write_to_sd_log_single(string);
                    
                    //Anzahl der Logs
                    log_count();
                    int i = 0;
                    while(logs_array[i] != NULL){
                        ble_buff[0][i] = logs_array[i];
                        onDataSent(i);
                        i++;
                    }
                    printf("\nLogs count: %s\n", logs_array);
                    
                    dataSent();
                    
                    break;
                }
                
                case 'y': //Alarn AN / AUS - Anzahl der Meldungen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'y' (Alert function and count) received";
                    write_to_sd_log_single(string);
                    
                    if(user_config_para.alert == 1){
                        printf("\nAlert function - ON\n");
                        
                        printf("\nNumber of alerts: %d\n", alert_count);
                        char alerts[4];
                        sprintf(alerts, "%d", alert_count);
                        int i = 0;
                        while(alerts[i] != NULL){
                            ble_buff[0][i] = alerts[i];
                            onDataSent(i);
                            i++;
                        }
                    }else{
                        printf("\nAlert function - OFF\n");
                        
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                    }
                    
                    dataSent();
                    
                    break;
                }
                
                case 'k': //Initialisierungsstatus auslesen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'b' (send initialize status) received";
                    write_to_sd_log_single(string);
                    
                    if(init_status == true){
                        ble_buff[0][0] = '1';
                        onDataSent(0);
                        
                        printf("\nInitialaze status: OK\n");
                    }else{
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                        
                        printf("\nInitialaze status: FAILED\n");
                    }
                    
                    dataSent();
                    
                    break;
                }
                
                case 'p': //Mess-Status auslesen
                {
                    connected_cancel.detach();
                    clear_buffer();
                    
                    char string[] = "Command 'p' (send measurement status) received";
                    write_to_sd_log_single(string);
                    
                    if(shipping == true){
                        ble_buff[0][0] = 1;
                        onDataSent(0);
                        
                        wait(1);
                        clear_buffer();
                        
                            if(pause == false){
                            ble_buff[0][0] = '1';
                            onDataSent(0);
                            
                            printf("\nMeasuremt status = Launched\n");
                        }else{
                            ble_buff[0][0] = '0';
                            onDataSent(0);
                            
                            printf("\nMeasuremt status = Paused\n");
                        }
                        
                    }else{
                        ble_buff[0][0] = '0';
                        onDataSent(0);
                        
                        printf("\nMeasuremt status = Sttopped\n");
                    }
                    
                    dataSent();
                    
                    break;
                }
                
                default: {
                    //clear_buffer();
                    response = '0';
                    break;
                }
            }
        }
    }  
}