function createDb_2023_Aranda_IEEE_COINS(dbInfo)
%{    
    This function takes the raw logs files generated for the project "IEE
    COINS 2023" and create the correspoing database in Matlab format.
    Therea re three types of log files: "_DeviceInfo_", "_BLE_", and
    "_WIFI_". Ideally, there should be one of each type for each smartphone
    and collection campaing, but some time, when no BLE or Wi-Fi signals
    were available, or measurements were to short, these files were not
    created.
    Initially, we navigate through all files marked with the "meta" tag to 
    collect the relevant metadata. Then each transmitter-receiver pair is
    considered separatly, distinguishing between BLE or WiFi data.
    Log files contains measurements from different transmitter (each log
    file is associated unambiguously with a receiver). To separate all data
    into trasnmitter-receiver pairs we used the MAC address. On top of
    that, data for each transmitter is further separated into frequencies
    for Wi-Fi and power/transmission slots for BLE.     
    Wi-Fi data from the same transmitter is separated according to the
    frequency band (2.4 GHz or 5 GHz). This separation is done using the
    field frequency. 
 
    BLE RSS measurements from the same beacon (transmitter) are separated 
    using the transmission power. This  is possible because some beacons were
    placed ad-hox by us in the environment. These beacons, the iBKS Plus from
    Accent System, can broadcast 6 transmission slots simultaneusly, each with
    a different transmission power and advertising period. Each ibks beacon 
    and slot has a different name that we use to know the associated transmission
    power. 
    
    References:
    Android documentation
    Bluetooth Low Energy data
    android.bluetooth.le.ScanResult ->   https://developer.android.com/reference/android/bluetooth/le/ScanResult
    android.bluetooth.BluetoothDevice -> https://developer.android.com/reference/android/bluetooth/BluetoothDevice
    Wi-Fi log data
	android.net.wifi.ScanResult -> https://developer.android.com/reference/android/net/wifi/ScanResult
    Fernando J. Aranda
    Grupo de Investigación en Sistemas Sensoriales
    Universidad de Extremadura
    Last check: 09/01/2025
%}

    flags.repeat = [true true];
    wifiTranasmitterNamesList = [];

    if (flags.repeat(1))

        db = struct;
        receiversList = ["21091116UG", "Aquaris X", "begonia" ,"bardock", "ELE-L29","MI 8","Mi A3","Redmi Note 8 Pro","SM-T720","SM-T860"];
        %% List of all "_DeviceInfo_" files (metadata files)
        folderName    = strcat(dbInfo.dbPath,"rawLogs");
        files         = dir(folderName);
        metadataFiles = [];
        bleFiles      = [];
        wifiFiles     = [];
        for i = 1:1:numel(files)
            if (contains(files(i).name,"_DeviceInfo_"))
                metadataFiles = [metadataFiles; string(files(i).name)];
            elseif (contains(files(i).name,"BLE"))
                bleFiles = [bleFiles; string(files(i).name)];
            elseif (contains(files(i).name,"WIFI"))
                wifiFiles = [wifiFiles; string(files(i).name)];
            end
        end
        %% Campaings
        aux = split(metadataFiles,"DeviceInfo_");
        aux = split(aux(:,2),'--');
        campaingsList = unique(aux(:,1));
        expId         = 1;
        measurementId = 1;
        bleStructureCounter  = 0;
        wifiStructureCounter = 0;
    
        %% Loop over all meta data log files
        for i = 1:1:numel(metadataFiles)
    
            disp(strcat("   File: ",num2str(i),"/",num2str(numel(metadataFiles))))
            auxStruct = getEmptyStructure();
    
            % Common metadata
            metadataLogFilePath = strcat(folderName,"/",metadataFiles(i));
            [transmitters, receiver,experimentTimestamp, fileAuxName] = getDeviceInfoData(metadataLogFilePath);
            receiverId = find(strcmp(receiver.model, receiversList));
            db.metadata.receiver(receiverId).info = receiver;
            % If there is at least one transmitter
            if (size(transmitters,2) < 1)
                break
            end
            % Read Bluetooth Low Energy data log
            bleFileIdx = find(contains(bleFiles,experimentTimestamp).*contains(bleFiles,fileAuxName)==1, 1); 
            if (~isempty(bleFileIdx))
                rawTable = readtable(strcat(folderName,"/",bleFiles(bleFileIdx)),'ReadRowNames',false,'Delimiter', ';'); 
                bleDat   = readBleRawLogFile(rawTable);
            end
            % Read Wi-Fi data log
            wifiFileIdx = find(contains(wifiFiles,experimentTimestamp).*contains(wifiFiles,fileAuxName)==1); 
            if (~isempty(wifiFileIdx))
                rawTable = readtable(strcat(folderName,"/",wifiFiles(wifiFileIdx)),'ReadRowNames',false,'Delimiter', ';');
                wifiDat  = readWifiRawLogFile(rawTable);
            end
            % Loop over all transmitters
            for j = 1:1:size(transmitters,2)
                disp(strcat("       Transmitter: ",num2str(j),"/",num2str(size(transmitters,2))));
                % If the field is unspecified
                if ~isfield(transmitters(j),'type')
                    break
                end
                disp(transmitters(j).deviceAndSlotName)
                %% BLE
                if (strcmp(transmitters(j).type,"BLE") && contains( transmitters(j).deviceAndSlotName,"GISS"))
                    % We separate the data by MAC addresses and the slots associated with each one
                    filterMac          = strcmp(bleDat.macAddress ,transmitters(j).mac);
                    availableSlotsList = unique(bleDat.beaconName(filterMac));
                
                    % Loop over all slots available for the current MAC (transmitter)
                    for s = 1:1:size(availableSlotsList,1) 
                        % Filter for MAC address and slotId 
                        filterMac  = strcmp(bleDat.macAddress, transmitters(j).mac);
                        filterslot = strcmp(bleDat.beaconName, availableSlotsList(s));
                        filter     = boolean(filterMac .* filterslot);
          
                        auxStruct.ble_rss_dBm                     = [auxStruct.ble_rss_dBm;                     bleDat.rssdBm(filter)];
                        auxStruct.ble_timestamp_ms                = [auxStruct.ble_timestamp_ms;                bleDat.systemTimestampMillis(filter)];
                        auxStruct.ble_detectionTimestamp_ns       = [auxStruct.ble_detectionTimestamp_ns;       bleDat.detectionTimestampNanos(filter)];
                        auxStruct.ble_macAddress                  = [auxStruct.ble_macAddress;                  bleDat.macAddress(filter)];
                        auxStruct.ble_transmitPower               = [auxStruct.ble_transmitPower;               bleDat.transmitPower(filter)];
                        auxStruct.ble_primaryPhy                  = [auxStruct.ble_primaryPhy;                  bleDat.primaryPhy(filter)];
                        auxStruct.ble_secondaryPhy                = [auxStruct.ble_secondaryPhy;                bleDat.secondaryPhy(filter)];
                        auxStruct.ble_periodicAdvertisingInterval = [auxStruct.ble_periodicAdvertisingInterval; bleDat.periodicAdvertisingInterval(filter)];
                        auxStruct.ble_advertisingSid              = [auxStruct.ble_advertisingSid;              bleDat.advertisingSid(filter)];
                        auxStruct.ble_isLos                       = [auxStruct.ble_isLos;                       ones(size(bleDat.rssdBm(filter),1),1)*strcmp(transmitters(j).state,"LOS")];
                        auxStruct.ble_distance_m                  = [auxStruct.ble_distance_m;                  ones(size(bleDat.rssdBm(filter),1),1)*str2num(transmitters(j).distance)];
                        auxStruct.ble_beaconName                  = [auxStruct.ble_beaconName;                  bleDat.beaconName(filter)];
                        for auxIdx = 1:1:size(bleDat.beaconName(filter),1)
                            auxStruct.ble_TxPower_dBm                 = [auxStruct.ble_TxPower_dBm;                 getSlotPower(bleDat.beaconName(auxIdx))];
                            [deviceId, slotId] = getSlotId(bleDat.beaconName(auxIdx));
                            auxStruct.ble_transmitterId               = [auxStruct.ble_transmitterId;                deviceId slotId];
                        end
                        auxStruct.ble_receiverId               = [auxStruct.ble_receiverId;           ones(size(bleDat.rssdBm(filter),1),1)*receiverId];
                        % Identifiers
                        auxStruct.ble_experimentId                = [auxStruct.ble_experimentId;         ones(size(bleDat.rssdBm(filter),1),1)*expId];
                        auxStruct.ble_dbId                        = [auxStruct.ble_dbId;                 ones(size(bleDat.rssdBm(filter),1),1)*dbInfo.dbId];
                        auxStruct.ble_measurementId               = [auxStruct.ble_measurementId;        ones(size(bleDat.rssdBm(filter),1),1)*measurementId];
                        auxStruct.ble_campaingId                  = [auxStruct.ble_campaingId;           ones(size(bleDat.rssdBm(filter),1),1)*getCampaingId(campaingsList,metadataFiles(i))];
                        auxStruct.ble_collection                  = [auxStruct.ble_collection;           ones(size(bleDat.rssdBm(filter),1),1)*j];
                        auxStruct.ble_experiment_timestamp        = [auxStruct.ble_experiment_timestamp; repmat(experimentTimestamp,      size(bleDat.rssdBm(filter),1), 1)];
                        measurementId = measurementId+1;
                        bleStructureCounter = bleStructureCounter + size(bleDat.rssdBm(filter),1);
                    end
                end
                %% WIFI
                if (strcmp(transmitters(j).type,"Wi-Fi"))
                    
                    % We separete for different frequency bands
                    bandsFloorFrequencyGHz = [2, 5];
                    % Bucle sobre las frecuencias
                    frequencyBands = floor(wifiDat.frequencyMHz/1000);
                    % Loop over Wifi bands (2.4 and 5 GHz)
                    for bandIdx = 1:size(bandsFloorFrequencyGHz,2)
                        % Filter for MAC address and frequency band  
                        filterMac  = strcmp(wifiDat.macAddress, transmitters(j).mac);
                        filterFreq = (frequencyBands == bandsFloorFrequencyGHz(bandIdx));
                        filter     = boolean(filterMac .* filterFreq);
                    
                        auxStruct.wifi_timestamp_ms         = [auxStruct.wifi_timestamp_ms;         wifiDat.systemTimestampMillis(filter)];
                        auxStruct.wifi_macAddress           = [auxStruct.wifi_macAddress;           repmat(transmitters(j).mac, size(wifiDat.rssdBm(filter),1), 1) ];
                        auxStruct.wifi_rss_dBm              = [auxStruct.wifi_rss_dBm;              wifiDat.rssdBm(filter)];
                        auxStruct.wifi_wifiStandard         = [auxStruct.wifi_wifiStandard;         wifiDat.wifiStandard(filter)];
                        auxStruct.wifi_frequencyMHz         = [auxStruct.wifi_frequencyMHz;         wifiDat.frequencyMHz(filter)];
                        auxStruct.wifi_centralFrequencyMHz0 = [auxStruct.wifi_centralFrequencyMHz0; wifiDat.centralFrequencyMHz0(filter)];
                        auxStruct.wifi_centralFrequencyMHz1 = [auxStruct.wifi_centralFrequencyMHz1; wifiDat.centralFrequencyMHz1(filter)];
                        auxStruct.wifi_channelWidthsMHz     = [auxStruct.wifi_channelWidthsMHz;     wifiDat.channelWidthsMHz(filter)];
                        auxStruct.wifi_transmitterId        = [auxStruct.wifi_transmitterId;     getWiFiTrasnmitterId(transmitters(j).deviceName,wifiTranasmitterNamesList)];
                        auxStruct.wifi_experimentId         = [auxStruct.wifi_experimentId;          ones(size(wifiDat.rssdBm(filter),1),1)*expId];
                        auxStruct.wifi_dbId                 = [auxStruct.wifi_dbId;                  ones(size(wifiDat.rssdBm(filter),1),1)*dbInfo.dbId];
                        auxStruct.wifi_measurementId        = [auxStruct.wifi_measurementId;         ones(size(wifiDat.rssdBm(filter),1),1)*measurementId];
                        auxStruct.wifi_campaingId           = [auxStruct.wifi_campaingId;            ones(size(wifiDat.rssdBm(filter),1),1)*getCampaingId(campaingsList,metadataFiles(i))];
                        auxStruct.wifi_collection           = [auxStruct.wifi_collection;            ones(size(wifiDat.rssdBm(filter),1),1)*getCampaingId(campaingsList,metadataFiles(i))];
                        auxStruct.wifi_experiment_timestamp = [auxStruct.wifi_experiment_timestamp;  repmat(experimentTimestamp, size(wifiDat.rssdBm(filter),1), 1)];
                        auxStruct.wifi_transmitterId        = [auxStruct.wifi_transmitterId];
                        auxStruct.wifi_isLos                = [auxStruct.wifi_isLos;       ones(size(wifiDat.rssdBm(filter),1),1)*strcmp(transmitters(j).state,"LOS")];
                        auxStruct.wifi_distance_m           = [auxStruct.wifi_distance_m;  ones(size(wifiDat.rssdBm(filter),1),1)*str2num(transmitters(j).distance)];
                        auxStruct.wifi_deviceName           = [auxStruct.wifi_deviceName;  repmat(receiver.deviceName,   size(wifiDat.rssdBm(filter),1), 1)];
                    
                        auxStruct.wifi_receiverId               = [auxStruct.wifi_receiverId;           ones(size(wifiDat.rssdBm(filter),1),1)*receiverId];
                        measurementId                            = measurementId+1;
                        wifiStructureCounter = wifiStructureCounter + size(wifiDat.rssdBm(filter),1);
                    end
                end
            end
            expId = expId + 1;
            auxPath = strrep(metadataLogFilePath,".txt",".mat");
            auxPath = strrep(auxPath,"_DeviceInfo_","_");
            auxPath = strrep(auxPath,"/","\");
            save(auxPath,'auxStruct','-v7.3');
        end 

    elseif (flags.repeat(2))

    files = dir(strcat(dbInfo.dbPath,"rawLogs"));
    finalStruct = getEmptyStructure();

    for fileIdx = 1:1:size(files,1)
        if (contains(files(fileIdx).name,".mat"))
            disp(strcat("   ",files(fileIdx).name))
            load(strcat(dbInfo.dbPath,"rawLogs\",files(fileIdx).name));

          finalStruct.ble_rss_dBm                     = [finalStruct.ble_rss_dBm;                     auxStruct.ble_rss_dBm];
          finalStruct.ble_detectionTimestamp_ns       = [finalStruct.ble_detectionTimestamp_ns;       auxStruct.ble_detectionTimestamp_ns];
          finalStruct.ble_macAddress                  = [finalStruct.ble_macAddress;                  auxStruct.ble_macAddress];
          finalStruct.ble_transmitPower               = [finalStruct.ble_transmitPower;               auxStruct.ble_transmitPower];
          finalStruct.ble_primaryPhy                  = [finalStruct.ble_primaryPhy;                  auxStruct.ble_primaryPhy];
          finalStruct.ble_beaconName                  = [finalStruct.ble_beaconName;                  auxStruct.ble_beaconName];
          finalStruct.ble_secondaryPhy                = [finalStruct.ble_secondaryPhy;                auxStruct.ble_secondaryPhy];
          finalStruct.ble_periodicAdvertisingInterval = [finalStruct.ble_periodicAdvertisingInterval; auxStruct.ble_periodicAdvertisingInterval];
          finalStruct.ble_advertisingSid              = [finalStruct.ble_advertisingSid;              auxStruct.ble_advertisingSid];
          finalStruct.ble_timestamp_ms                = [finalStruct.ble_timestamp_ms;                auxStruct.ble_timestamp_ms];
          finalStruct.ble_isLos                       = [finalStruct.ble_isLos;                       auxStruct.ble_isLos];
          finalStruct.ble_TxPower_dBm                 = [finalStruct.ble_TxPower_dBm;                 auxStruct.ble_TxPower_dBm];
          finalStruct.ble_distance_m                  = [finalStruct.ble_distance_m;                  auxStruct.ble_distance_m];
          finalStruct.ble_experimentId                = [finalStruct.ble_experimentId;                auxStruct.ble_experimentId];
          finalStruct.ble_dbId                        = [finalStruct.ble_dbId;                        auxStruct.ble_dbId];
          finalStruct.ble_measurementId               = [finalStruct.ble_measurementId;              auxStruct.ble_measurementId];
          finalStruct.ble_campaingId                  = [finalStruct.ble_campaingId;                  auxStruct.ble_campaingId];
          finalStruct.ble_collection                  = [finalStruct.ble_collection;                  auxStruct.ble_collection];
          finalStruct.ble_experiment_timestamp        = [finalStruct.ble_experiment_timestamp;       auxStruct.ble_experiment_timestamp];
          finalStruct.ble_receiverId                  = [finalStruct.ble_receiverId;                  auxStruct.ble_receiverId];
          finalStruct.ble_transmitterId               = [finalStruct.ble_transmitterId;               auxStruct.ble_transmitterId];

          finalStruct.wifi_timestamp_ms         = [finalStruct.wifi_timestamp_ms;               auxStruct.wifi_timestamp_ms];
          finalStruct.wifi_macAddress           = [finalStruct.wifi_macAddress;                 auxStruct.wifi_macAddress];
          finalStruct.wifi_rss_dBm              = [finalStruct.wifi_rss_dBm;                    auxStruct.wifi_rss_dBm];
          finalStruct.wifi_wifiStandard         = [finalStruct.wifi_wifiStandard;               auxStruct.wifi_wifiStandard];
          finalStruct.wifi_frequencyMHz         = [finalStruct.wifi_frequencyMHz;               auxStruct.wifi_frequencyMHz];
          finalStruct.wifi_centralFrequencyMHz0 = [finalStruct.wifi_centralFrequencyMHz0;       auxStruct.wifi_centralFrequencyMHz0];
          finalStruct.wifi_centralFrequencyMHz1 = [finalStruct.wifi_centralFrequencyMHz1;       auxStruct.wifi_centralFrequencyMHz1];
          finalStruct.wifi_channelWidthsMHz     = [finalStruct.wifi_channelWidthsMHz;           auxStruct.wifi_channelWidthsMHz];
          finalStruct.wifi_experimentId         = [finalStruct.wifi_experimentId;               auxStruct.wifi_experimentId];
          finalStruct.wifi_dbId                 = [finalStruct.wifi_dbId;                       auxStruct.wifi_dbId];
          finalStruct.wifi_measurementId        = [finalStruct.wifi_measurementId;              auxStruct.wifi_measurementId];
          finalStruct.wifi_campaingId           = [finalStruct.wifi_campaingId;                 auxStruct.wifi_campaingId];
          finalStruct.wifi_collection           = [finalStruct.wifi_collection;                 auxStruct.wifi_collection];
          finalStruct.wifi_experiment_timestamp = [finalStruct.wifi_experiment_timestamp;       auxStruct.wifi_experiment_timestamp];
          finalStruct.wifi_isLos                = [finalStruct.wifi_isLos;                      auxStruct.wifi_isLos];
          finalStruct.wifi_distance_m           = [finalStruct.wifi_distance_m;                 auxStruct.wifi_distance_m];
          finalStruct.wifi_deviceName           = [finalStruct.wifi_deviceName;                 auxStruct.wifi_deviceName];
          finalStruct.wifi_mac                  = [finalStruct.wifi_mac;                        auxStruct.wifi_mac];
          finalStruct.wifi_receiverId           = [finalStruct.wifi_receiverId;                 auxStruct.wifi_receiverId]; 
          finalStruct.wifi_transmitterId           = [finalStruct.wifi_transmitterId;                 auxStruct.wifi_transmitterId]; 
        end
    end


    timestamp_ms         = finalStruct.wifi_timestamp_ms;               
    macAddress           = finalStruct.wifi_macAddress;                 
    rss_dBm              = finalStruct.wifi_rss_dBm;                    
    wifiStandard         = finalStruct.wifi_wifiStandard;               
    frequency_MHz         = finalStruct.wifi_frequencyMHz;     
    frequencyBand_GHz     = frequency_MHz;
    frequencyBand_GHz(frequency_MHz<3000) = 2.4;
    frequencyBand_GHz(frequency_MHz>3000) = 5;
    centralFrequency_MHz0 = finalStruct.wifi_centralFrequencyMHz0;       
    centralFrequency_MHz1 = finalStruct.wifi_centralFrequencyMHz1;       
    channelWidths_MHz     = finalStruct.wifi_channelWidthsMHz;           
    experimentId         = finalStruct.wifi_experimentId;               
    dbId                 = finalStruct.wifi_dbId;                      
    measurementId        = finalStruct.wifi_measurementId;              
    campaingId           = finalStruct.wifi_campaingId;                 
    collectionId           = finalStruct.wifi_collection;                 
    experiment_timestamp = finalStruct.wifi_experiment_timestamp;       
    isLos                = finalStruct.wifi_isLos;                      
    distance_m           = finalStruct.wifi_distance_m;                 
    deviceName           = finalStruct.wifi_deviceName;                                    
    receiverId           = finalStruct.wifi_receiverId;
    transmitterId           = finalStruct.wifi_transmitterId;

    db = struct;

    db.wifiData = table(rss_dBm,timestamp_ms,macAddress,wifiStandard,frequency_MHz,centralFrequency_MHz0,centralFrequency_MHz1,channelWidths_MHz,...
        experimentId,dbId,measurementId,campaingId,collectionId,experiment_timestamp,isLos,distance_m,deviceName,receiverId,frequencyBand_GHz,transmitterId);
    
      rss_dBm                     = finalStruct.ble_rss_dBm;                     
      detectionTimestamp_ns       = finalStruct.ble_detectionTimestamp_ns;       
      macAddress                  = finalStruct.ble_macAddress;                  
      transmitPower               = finalStruct.ble_transmitPower;               
      primaryPhy                  = finalStruct.ble_primaryPhy;                  
      beaconName                  = finalStruct.ble_beaconName;                  
      secondaryPhy                = finalStruct.ble_secondaryPhy;                
      periodicAdvertisingInterval = finalStruct.ble_periodicAdvertisingInterval; 
      advertisingSid              = finalStruct.ble_advertisingSid;              
      timestamp_ms                = finalStruct.ble_timestamp_ms;                
      isLos                       = finalStruct.ble_isLos;                       
      TxPower_dBm                 = finalStruct.ble_TxPower_dBm;                 
      distance_m                  = finalStruct.ble_distance_m;                  
      experimentId                = finalStruct.ble_experimentId;                
      dbId                        = finalStruct.ble_dbId;                        
      measurementId               = finalStruct.ble_measurementId;              
      campaingId                  = finalStruct.ble_campaingId;                  
      collectionId                = finalStruct.ble_collection;                  
      experiment_timestamp        = finalStruct.ble_experiment_timestamp;       
      receiverId                  = finalStruct.ble_receiverId;                 
      transmitterId               = finalStruct.ble_transmitterId;              
    
      db.bleData  = table(rss_dBm,detectionTimestamp_ns,macAddress,transmitPower,primaryPhy,beaconName,secondaryPhy,periodicAdvertisingInterval,advertisingSid, ...
        timestamp_ms,isLos,TxPower_dBm,distance_m,experimentId,dbId,measurementId,campaingId,collectionId,experiment_timestamp,receiverId,transmitterId);

      % Filtramos y solo quedo los BLE asociados a nuestras balizas
      db.bleData = db.bleData(~isnan(db.bleData.transmitterId(:,1)));

    % Meta
    db.metadata.dbId   = dbInfo.dbId;
    db.metadata.dbName = dbInfo.dbName;
    db.metadata.dbShortDescription = dbInfo.dbShortDescription;
    save(strcat(dbInfo.dbPath,"matlabData\",db.metadata.dbName,".mat"),'db','-v7.3');

    % Save data in csv format for zenodo
    writetable(db.wifiData, strcat(dbInfo.dbPath,"csvData\",db.metadata.dbName,"_wifiData.csv"));
    writetable(db.bleData, strcat(dbInfo.dbPath,"csvData\",db.metadata.dbName,"_bleData.csv"));

    end
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    %% Auxiliar functions of this script
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % Takes BLE raw imported as a MATLAB table and transforms it into the final format.
    function bleDat = readBleRawLogFile(data)
        bleDat = struct;
        bleDat.systemTimestampMillis          = [table2array(data(:,2))        ];
        bleDat.detectionTimestampNanos        = [table2array(data(:,3))        ];
        bleDat.macAddress                     = [string(table2array(data(:,4)))];
        bleDat.beaconName                     = [string(table2array(data(:,5)))];
        bleDat.rssdBm                         = [table2array(data(:,6))        ];   
        bleDat.transmitPower                  = [table2array(data(:,7))        ]; 
        bleDat.primaryPhy                     = [table2array(data(:,8))        ];
        bleDat.secondaryPhy                   = [table2array(data(:,9))        ];
        bleDat.periodicAdvertisingInterval    = [table2array(data(:,10))       ];
        bleDat.advertisingSid                 = [table2array(data(:,11))       ];
        return
    end  
    
    % Takes Wi-Fi raw data imported as a MATLAB table and transforms it into the final format.
    function wifiDat = readWifiRawLogFile(data)
        wifiDat = struct;
        % Strings
        wifiDat.systemTimestampMillis   = [table2array(data(:,2))];
        wifiDat.macAddress         = [string(table2array(data(:,3)))];
        wifiDat.rssdBm             = [table2array(data(:,4))];
        wifiDat.wifiStandard       = [string(table2array(data(:,9)))];
        % Numbers
        wifiDat.frequencyMHz         = zeros(size(data,1),1);
        wifiDat.centralFrequencyMHz0 = zeros(size(data,1),1);
        wifiDat.centralFrequencyMHz1 = zeros(size(data,1),1);
        wifiDat.channelWidthsMHz     = zeros(size(data,1),1);
        for ii = 1:size(data,1)
            wifiDat.centralFrequencyMHz0(ii) = table2array(data(ii,5));
            wifiDat.centralFrequencyMHz1(ii) = table2array(data(ii,6));
            wifiDat.channelWidthsMHz(ii)     = str2double(strrep(string(table2array(data(ii,7))),"MHZ",''));
            wifiDat.frequencyMHz(ii)         = table2array(data(ii,8));
        end
        return
    end  
    % Takes the names of all transmitters consider by an smartphone in a
    % mesaurement campaing
    function [transmitters, receiver,experimentTimestamp, fileAuxName] = getDeviceInfoData(filePath)
        % Experiment name and experiment timestamp
        nameSlices          = split(filePath,"/");
        nameSlices          = split(nameSlices(end),"_DeviceInfo_");
        fileAuxName         = nameSlices(1);
        experimentTimestamp = strrep(nameSlices(end),"_.txt",'');
   
        % Read the transmitters names and receiver name 
        rawText     = fileread(filePath);
        textLines   = splitlines(rawText);
        transmitters = struct;
        receiver    = struct;
        n = 1;
        for k=1:1:size(textLines,1)
            trozos = split(textLines(k),";");
            if (strcmp(trozos(1),'Transmitter'))
                transmitters(n).type           = strtrim(string(cell2mat(trozos(2))));
                transmitters(n).mac            = string(cell2mat(trozos(3)));
                transmitters(n).deviceName     = string(cell2mat(trozos(4)));
                transmitters(n).deviceAndSlotName = string(cell2mat(trozos(4)));
                transmitters(n).state          = string(cell2mat(trozos(5)));
                transmitters(n).distance       = string(cell2mat(trozos(6)));
                if (strcmp(transmitters(n).deviceName,"--"))
                    transmitters(n).deviceName = "unknow";
                end
                if (strcmp(transmitters(n).deviceName,""))
                    transmitters(n).deviceName = strcat("empty_name_",transmitters(n).type);
                end
                n = n + 1;
            end
            if (strcmp(trozos(1),'Receiver'))
                receiver.type         = "Smartphone";
                receiver.model        = string(cell2mat(trozos(2)));
                receiver.deviceName       = string(cell2mat(trozos(3)));
                receiver.manufacturer = string(cell2mat(trozos(4)));
                receiver.brand        = string(cell2mat(trozos(5)));
                receiver.product      = string(cell2mat(trozos(6)));
                receiver.display      = string(cell2mat(trozos(7)));
                receiver.sdk_int      = string(cell2mat(trozos(8)));
                receiver.name         = strcat(string(cell2mat(trozos(4))),"_", ...
                                      string(cell2mat(trozos(3))));      
            end
        end
    end
    
    % Associates each slot/Tx. power with its real transmission power.
    function power = getSlotPower(slot)
    
    try
        if (strcmp(slot,"29EDD4603"))
            % There was a typo in the device UID.
            slot = "29EDD4";
        end
        if (strcmp(slot,"27EDD293B"))
            % There was a typo in the device UID.
            slot = "27EDD2";
        end
        if (strcmp(slot,"10BEAC2C8"))
            % There was a typo in the device UID.
            slot = "10BEAC2";
        end
    
        %{
        Los números de beaconIdList se corresponden con las filas en slotPowerList
        %}
        beaconsIdList = [28 38 27 10 41 23 16 29 4 50 45 5 58 59 9 37 40 46 48 25];
        slotPowerList = [...
            4 0 -4 -8 -12 -16;       ... % 28
            4 0 -4 -8 -12 -16;       ... % 38
            4 0 -4 -8 -12 -16;       ... % 27
            4 0 -8 -12 -20 -30;      ... % 10
            4 0 -4 -8 -12 -16;       ... % 41
            4 0 -4 -8 -12 -16;       ... % 23
            4 0 -4 -8 -12 -16;       ... % 16
            4 0 -4 -8 -12 -16;       ... % 29
            -30 -20 -16 -12 -4 -16;  ... % 4
            -30 -20 -16 -12 0 -8;    ... % 50
            -30 -20 -16 -12 -20 -30; ... % 45
            4 0 -4 -8 -12 -16;       ... % 5
            -30 -20 -16 -12 -8 -4;   ... % 58
            -30 -20 -16 -12 -8 -4;   ... % 59
            -30 -20 -16 -12 -8 -4;   ... % 9
            -30 -20 -16 -12 -8 -4;   ... % 37
            -30 -20 -16 -12 -8 -4;   ... % 40
            -30 -20 -16 -12 -8 -4;   ... % 46
            -30 -20 -16 -12 -8 -4;   ... % 48
            -30 -20 -16 -12 -8 -4;   ... % 25
        
            ];
        
        if (contains(slot,"BEAC"))  
            aux      = split(slot,"BEAC");
            beaconId = str2double(aux(1));
            slotId   = str2double(aux(2))+4;
        elseif (contains(slot,"EDD"))
            aux      = split(slot,"EDD");
            beaconId = str2double(aux(1));
            slotId   = str2double(aux(2));
        else
            beaconId = 10000;
            slotId = 7;
        end
        
        id = find(beaconId == beaconsIdList);
        
        if (~isempty(id))
            power =  slotPowerList(id,slotId);
        else
            power = nan;
        end
    
    catch
        disp("Problema -> getSlotPower")
    end
    end
    function [deviceId, slotId] = getSlotId(slot)
        if (contains(slot,"BEAC"))  
            aux      = split(slot,"BEAC");
            deviceId = str2double(aux(1));
            slotId   = str2double(aux(2))+4;
        elseif (contains(slot,"EDD"))
            aux      = split(slot,"EDD");
            deviceId = str2double(aux(1));
            slotId   = str2double(aux(2));
        else
            deviceId = nan;
            slotId = nan;
        end
    end
    % Prepares the experiment name to good format
    function outputName = prepareName(outputName)
        outputName = strrep(outputName,'.','');
        outputName = strrep(outputName,':','');
    end
    % Decode timestamp into date and time
    function  [date, time] = decodeTimeStamp(timestamp)
        pieces = split(timestamp,'--');
        date = pieces(1);
        time = pieces(2);
    end
    function [campaingId] = getCampaingId(campaingsList,currentDate)
        %% Campaings
        aux = split(currentDate,"DeviceInfo_");
        aux = split(aux(2,1),'--');
        campaingId = find(strcmp(campaingsList,unique(aux(1,:)))==1);
        
    end
end

function auxStruct = getEmptyStructure()
    
    auxStruct = struct;
    auxStruct.ble_rss_dBm                     = [];
    auxStruct.ble_detectionTimestamp_ns       = [];
    auxStruct.ble_macAddress                  = [];
    auxStruct.ble_transmitPower               = [];
    auxStruct.ble_primaryPhy                  = [];
    auxStruct.ble_beaconName                  = [];
    auxStruct.ble_secondaryPhy                = [];
    auxStruct.ble_periodicAdvertisingInterval = [];
    auxStruct.ble_advertisingSid              = [];
    auxStruct.ble_timestamp_ms                = [];
    auxStruct.ble_isLos                       = [];
    auxStruct.ble_TxPower_dBm                 = [];
    auxStruct.ble_distance_m                  = [];
    auxStruct.ble_experimentId                = [];
    auxStruct.ble_dbId                        = [];
    auxStruct.ble_measurementId               = [];
    auxStruct.ble_campaingId                  = [];
    auxStruct.ble_collection                  = [];
    auxStruct.ble_experiment_timestamp        = [];
    auxStruct.ble_receiverId                  = [];
    auxStruct.ble_transmitterId               = [];
    auxStruct.bleStructureCounter  = 0;

    % Wi-Fi data
    auxStruct.wifi_timestamp_ms         = [];
    auxStruct.wifi_macAddress           = [];
    auxStruct.wifi_rss_dBm              = [];
    auxStruct.wifi_wifiStandard         = [];
    auxStruct.wifi_frequencyMHz         = [];
    auxStruct.wifi_centralFrequencyMHz0 = [];
    auxStruct.wifi_centralFrequencyMHz1 = [];
    auxStruct.wifi_channelWidthsMHz     = [];
    auxStruct.wifi_experimentId         = [];
    auxStruct.wifi_dbId                 = [];
    auxStruct.wifi_measurementId        = [];
    auxStruct.wifi_campaingId           = [];
    auxStruct.wifi_collection           = [];
    auxStruct.wifi_experiment_timestamp = [];
    auxStruct.wifi_isLos                = [];
    auxStruct.wifi_distance_m           = [];
    auxStruct.wifi_deviceName           = [];
    auxStruct.wifi_mac                  = [];
    auxStruct.wifi_receiverId           = [];
    auxStruct.wifi_transmitterId        = [];
    auxStruct.wifiStructureCounter  = 0;

end

function idx = getWiFiTrasnmitterId(newdeviceName,wifiTranasmitterNamesList)

    match = strcmp(wifiTranasmitterNamesList, newdeviceName);
    idx = find(match);

    if isempty(idx)
        wifiTranasmitterNamesList = [wifiTranasmitterNamesList; newdeviceName];
        match = strcmp(wifiTranasmitterNamesList, newdeviceName);
        idx = find(match);
    end
end