work on ServerBeacon began
This commit is contained in:
		
							parent
							
								
									bbd19fc2a8
								
							
						
					
					
						commit
						94f851011f
					
				
							
								
								
									
										1
									
								
								.idea/.name
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.idea/.name
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
wfr
 | 
			
		||||
							
								
								
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.idea/vcs.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<project version="4">
 | 
			
		||||
  <component name="VcsDirectoryMappings">
 | 
			
		||||
    <mapping directory="$PROJECT_DIR$" vcs="Git" />
 | 
			
		||||
  </component>
 | 
			
		||||
</project>
 | 
			
		||||
@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD 14)
 | 
			
		||||
 | 
			
		||||
add_executable(${APP_NAME} main.cpp src/ALSADevice.cpp src/ALSADevice.h src/MemoryPool.cpp src/MemoryPool.h utils/Semaphore.h utils/Semaphore.cpp src/SampleWriter.h src/Timestamp.h
 | 
			
		||||
        #src/SampleReceiver.h
 | 
			
		||||
        src/audio_types.h)
 | 
			
		||||
        src/audio_types.h src/ServerBeacon.cpp src/ServerBeacon.h)
 | 
			
		||||
 | 
			
		||||
find_package(Threads REQUIRED)
 | 
			
		||||
if (THREADS_FOUND)
 | 
			
		||||
 | 
			
		||||
@ -1,39 +1,46 @@
 | 
			
		||||
% settings
 | 
			
		||||
DATASET_DIR = 'test';
 | 
			
		||||
TS_FILE = 'ts';
 | 
			
		||||
SAMPLE_FILE_PREFIX = 'ch_';
 | 
			
		||||
FILE_EXT = 'dat';
 | 
			
		||||
CHANNELS = 2;
 | 
			
		||||
function ds = read_syncdata(DATASET_DIR)
 | 
			
		||||
  % settings
 | 
			
		||||
  %DATASET_DIR = 'test_20221';
 | 
			
		||||
  TS_FILE = 'ts';
 | 
			
		||||
  SAMPLE_FILE_PREFIX = 'ch_';
 | 
			
		||||
  FILE_EXT = 'dat';
 | 
			
		||||
  CHANNELS = 2;
 | 
			
		||||
 | 
			
		||||
% computed values
 | 
			
		||||
FN_TS = strcat(DATASET_DIR, '/', TS_FILE, '.', FILE_EXT);
 | 
			
		||||
  % computed values
 | 
			
		||||
  FN_TS = strcat(DATASET_DIR, '/', TS_FILE, '.', FILE_EXT);
 | 
			
		||||
 | 
			
		||||
for ch=0:1:(CHANNELS-1)
 | 
			
		||||
  FN_SAMPLE{ch+1} = strcat(DATASET_DIR, '/', SAMPLE_FILE_PREFIX, num2str(ch), '.', FILE_EXT);
 | 
			
		||||
end
 | 
			
		||||
  for ch=0:1:(CHANNELS-1)
 | 
			
		||||
    FN_SAMPLE{ch+1} = strcat(DATASET_DIR, '/', SAMPLE_FILE_PREFIX, num2str(ch), '.', FILE_EXT);
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
% load timestamps
 | 
			
		||||
f = fopen(FN_TS ,'r');
 | 
			
		||||
ts = fread(f,[2,Inf],'uint32');
 | 
			
		||||
fclose(f);
 | 
			
		||||
 | 
			
		||||
% take first element as t0
 | 
			
		||||
ts(1,:) = ts(1,:) - ts(1,1);
 | 
			
		||||
 | 
			
		||||
% create fractional timestamp
 | 
			
		||||
ts = ts(1,:) + ts(2,:) / 1E+09;
 | 
			
		||||
 | 
			
		||||
% get sample count
 | 
			
		||||
sample_cnt = length(ts);
 | 
			
		||||
 | 
			
		||||
% load samples
 | 
			
		||||
s = zeros(CHANNELS, sample_cnt);
 | 
			
		||||
for ch=1:CHANNELS
 | 
			
		||||
  f = fopen(FN_SAMPLE{ch},'r');
 | 
			
		||||
  d = fread(f, [1,Inf],'int16');
 | 
			
		||||
  s(ch,:) = d;
 | 
			
		||||
  % load timestamps
 | 
			
		||||
  f = fopen(FN_TS ,'r');
 | 
			
		||||
  ts = fread(f,[2,Inf],'uint32');
 | 
			
		||||
  fclose(f);
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
plot(ts(1,1:100), s(1,1:100))
 | 
			
		||||
  % take first element as t0
 | 
			
		||||
  %ts(1,:) = ts(1,:) - 1636036145;
 | 
			
		||||
 | 
			
		||||
  % create fractional timestamp
 | 
			
		||||
  ts = ts(1,:) + ts(2,:) / 1E+09;
 | 
			
		||||
 | 
			
		||||
  % get sample count
 | 
			
		||||
  sample_cnt = length(ts);
 | 
			
		||||
 | 
			
		||||
  % load samples
 | 
			
		||||
  s = zeros(CHANNELS, sample_cnt);
 | 
			
		||||
  for ch=1:CHANNELS
 | 
			
		||||
    f = fopen(FN_SAMPLE{ch},'r');
 | 
			
		||||
    d = fread(f, [1,Inf],'int16');
 | 
			
		||||
    s(ch,:) = d;
 | 
			
		||||
    fclose(f);
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  %figure(1)
 | 
			
		||||
  %plot(ts(1,1:100), s(1,1:100), 'x')
 | 
			
		||||
  %xlim([ts(1) ts(100)])
 | 
			
		||||
  %hold on
 | 
			
		||||
  
 | 
			
		||||
  ds = [ts' s'];
 | 
			
		||||
end
 | 
			
		||||
							
								
								
									
										72
									
								
								MATLAB/sync_datasets.m
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								MATLAB/sync_datasets.m
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
			
		||||
function sds = sync_datasets(dss)
 | 
			
		||||
  % load datasets
 | 
			
		||||
  len = length(dss);
 | 
			
		||||
  sds = {};
 | 
			
		||||
  first_ts = [];
 | 
			
		||||
  last_ts = [];
 | 
			
		||||
  for i=1:len
 | 
			
		||||
    ds = read_syncdata(dss{i});
 | 
			
		||||
    first_ts(i) = ds(1:1);
 | 
			
		||||
    last_ts(i) = ds(end,1);   
 | 
			
		||||
    sds{i} = ds;
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  % get first and last common timestamp
 | 
			
		||||
  ts0 = max(first_ts);
 | 
			
		||||
  tsend = min(last_ts);
 | 
			
		||||
  
 | 
			
		||||
  for i=1:len
 | 
			
		||||
    ds = sds{i}; 
 | 
			
		||||
    ds = ds(ds(:,1) > ts0 + (ds(2,1) - ds(1,1)) / 2 & ds(:,1) < tsend, :); % drop non-common sections
 | 
			
		||||
    ds(:,1) = ds(:,1) - ts0; % substract ts0 from each dataset's timestamp array
 | 
			
		||||
    sds{i} = ds;
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  % create plot
 | 
			
		||||
  figure(1)
 | 
			
		||||
  
 | 
			
		||||
  % plot samples
 | 
			
		||||
  subplot(2,1,1);
 | 
			
		||||
  
 | 
			
		||||
  marks = ['-', '-o'];
 | 
			
		||||
  
 | 
			
		||||
  PLOTRANGE = 1:100;
 | 
			
		||||
  
 | 
			
		||||
  % get beginning indices
 | 
			
		||||
  for i=1:len
 | 
			
		||||
    ds = sds{i};
 | 
			
		||||
    ts = ds(:,1);
 | 
			
		||||
    
 | 
			
		||||
    s = size(ds);
 | 
			
		||||
    
 | 
			
		||||
    %for k = 2:s(2);
 | 
			
		||||
    for k = 2:2
 | 
			
		||||
      %plot(ts(1:100),ds(1:100,k), marks(k-1));
 | 
			
		||||
      plot(ts(PLOTRANGE),ds(PLOTRANGE,k), 'x');
 | 
			
		||||
      hold on
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  grid on
 | 
			
		||||
  xlabel("Time [s]");
 | 
			
		||||
  ylabel("Sample");
 | 
			
		||||
  xlim([ts(PLOTRANGE(1)) ts(PLOTRANGE(end))]);
 | 
			
		||||
  
 | 
			
		||||
  % plot timestamp errors
 | 
			
		||||
  subplot(2,1,2);
 | 
			
		||||
 | 
			
		||||
  ds_ref = sds{1};
 | 
			
		||||
  ts_ref = ds_ref(:,1);
 | 
			
		||||
  
 | 
			
		||||
  for i = 2:len
 | 
			
		||||
    ts_err = ts(PLOTRANGE) - ts_ref(PLOTRANGE);
 | 
			
		||||
    plot(ts_ref(PLOTRANGE), ts_err * 1E+09);
 | 
			
		||||
    hold on
 | 
			
		||||
  end
 | 
			
		||||
  
 | 
			
		||||
  grid on
 | 
			
		||||
  xlabel("Time [s]");
 | 
			
		||||
  ylabel("Time error [ns]");
 | 
			
		||||
  xlim([ts(PLOTRANGE(1)) ts(PLOTRANGE(end))]);
 | 
			
		||||
  
 | 
			
		||||
endfunction
 | 
			
		||||
							
								
								
									
										2
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								main.cpp
									
									
									
									
									
								
							@ -144,7 +144,7 @@ uint8_t pRecvBuf[8096] __attribute__ ((aligned (32)));
 | 
			
		||||
int main(int argc, char * argv[]) {
 | 
			
		||||
    ALSADevice dev(PERIOD_LEN, SAMPLE_RATE);
 | 
			
		||||
    MemoryPool<int16_t> pool(STEREO_BUF_LEN, 1000);
 | 
			
		||||
    //SampleWriter<AudioSampleType> sw("test", 2, STEREO_BUF_LEN / 2);
 | 
			
		||||
    //SampleWriter<AudioSampleType> sw(std::string("test_") + argv[1], 2, STEREO_BUF_LEN / 2);
 | 
			
		||||
 | 
			
		||||
    //std::this_thread::sleep_for(std::chrono::seconds(1));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										133
									
								
								src/ServerBeacon.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								src/ServerBeacon.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,133 @@
 | 
			
		||||
//
 | 
			
		||||
// Created by epagris on 2021. 11. 11..
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include "ServerBeacon.h"
 | 
			
		||||
 | 
			
		||||
const in_addr ServerBeacon::DEFAULT_MULTICAST_ADDR = {inet_addr("224.0.2.21")};
 | 
			
		||||
 | 
			
		||||
ServerBeacon::ServerBeacon() : mRunning(false) {
 | 
			
		||||
    setMulticastAddr(DEFAULT_MULTICAST_ADDR);
 | 
			
		||||
    setPort(DEFAULT_PORT);
 | 
			
		||||
    setAnnouncePeriod(DEFAULT_ANNOUNCE_PERIOD_MS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ServerBeacon::ServerBeacon(const in_addr &addr, unsigned short port, size_t announcePeriod_ms) : mRunning(false) {
 | 
			
		||||
    setMulticastAddr(addr);
 | 
			
		||||
    setPort(port);
 | 
			
		||||
    setAnnouncePeriod(announcePeriod_ms);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ServerBeacon::setMulticastAddr(const in_addr &addr) {
 | 
			
		||||
    mAddr = addr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
in_addr ServerBeacon::getMulticastAddr() const {
 | 
			
		||||
    return mAddr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void ServerBeacon::setPort(unsigned short port) {
 | 
			
		||||
    mBeaconPort = port;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned short ServerBeacon::getPort() const {
 | 
			
		||||
    return mBeaconPort;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ServerBeacon::setAnnouncePeriod(size_t period_ms) {
 | 
			
		||||
    mAnnPeriod_ms = period_ms;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t ServerBeacon::getAnnouncePeriod() const {
 | 
			
		||||
    return mAnnPeriod_ms;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ServerBeacon::startBeacon() {
 | 
			
		||||
    if (mRunning) {
 | 
			
		||||
        std::cerr << "Could not start beacon: already running!" << std::endl;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mBeaconSoc = socket(AF_INET, SOCK_DGRAM, 0); // create socket
 | 
			
		||||
    if (mBeaconSoc == -1) {
 | 
			
		||||
        std::cerr << "Could not open socket in " << __FUNCTION__ << "!" << std::endl;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // set socket options
 | 
			
		||||
    int opt = 1;
 | 
			
		||||
    setsockopt(mBeaconSoc, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
 | 
			
		||||
 | 
			
		||||
    // bind to ip-address and port
 | 
			
		||||
    sockaddr_in addr;
 | 
			
		||||
    addr.sin_family = AF_INET;
 | 
			
		||||
    addr.sin_addr = mAddr;
 | 
			
		||||
    addr.sin_port = htons(mBeaconPort);
 | 
			
		||||
 | 
			
		||||
    if (bind(mBeaconSoc, (const sockaddr *) &addr, sizeof(addr)) == -1) {
 | 
			
		||||
        std::cerr << "Could not bind to IP address and/or port in " << __FUNCTION__ << "!" << std::endl;
 | 
			
		||||
        close(mBeaconSoc);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // the beacon is running now!
 | 
			
		||||
    mRunning = true;
 | 
			
		||||
 | 
			
		||||
    // start beacon thread
 | 
			
		||||
    mpBeaconThread = std::make_shared<std::thread>(fn_BeaconThread, this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ServerBeacon::stopBeacon() {
 | 
			
		||||
    mRunning = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::list<in_addr> ServerBeacon::getNodesOnNetwork() {
 | 
			
		||||
    return std::list<in_addr>();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// -------------------------------------------
 | 
			
		||||
 | 
			
		||||
void ServerBeacon::fn_BeaconThread(ServerBeacon *pSB) {
 | 
			
		||||
    // beacon message used to send and receive information
 | 
			
		||||
    BeaconMsg msg;
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
 | 
			
		||||
    // select-related structures
 | 
			
		||||
    fd_set read_fds;
 | 
			
		||||
    timeval tv;
 | 
			
		||||
 | 
			
		||||
    // fill-in select parameters
 | 
			
		||||
    FD_ZERO(&read_fds);
 | 
			
		||||
    FD_SET(pSB->mBeaconSoc, &read_fds);
 | 
			
		||||
 | 
			
		||||
    // fill-in timeout value
 | 
			
		||||
    tv.tv_sec = pSB->mAnnPeriod_ms / 1000;
 | 
			
		||||
    tv.tv_usec = (pSB->mAnnPeriod_ms  % 1000) * 1000;
 | 
			
		||||
 | 
			
		||||
    while (pSB->mRunning) {
 | 
			
		||||
        msg.server_nClient = 1; // we are the server
 | 
			
		||||
        msg.terminalPort = 0; // we have no inbound terminal port
 | 
			
		||||
 | 
			
		||||
        send(pSB->mBeaconSoc, &msg, sizeof(BeaconMsg), 0); // send the announce message
 | 
			
		||||
 | 
			
		||||
        // ------------------
 | 
			
		||||
 | 
			
		||||
        // copy parameters
 | 
			
		||||
        fd_set cur_rfds = read_fds;
 | 
			
		||||
        timeval cur_tv = tv;
 | 
			
		||||
 | 
			
		||||
        while (select(1, &cur_rfds, nullptr, nullptr, &cur_tv) != 0) {
 | 
			
		||||
            // receive response
 | 
			
		||||
            recv(pSB->mBeaconSoc, &msg, sizeof(BeaconMsg), 0);
 | 
			
		||||
 | 
			
		||||
            // store response
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										56
									
								
								src/ServerBeacon.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/ServerBeacon.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
			
		||||
//
 | 
			
		||||
// Created by epagris on 2021. 11. 11..
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#ifndef WFR_SERVERBEACON_H
 | 
			
		||||
#define WFR_SERVERBEACON_H
 | 
			
		||||
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <netinet/in.h>
 | 
			
		||||
#include <arpa/inet.h>
 | 
			
		||||
#include <thread>
 | 
			
		||||
 | 
			
		||||
class ServerBeacon {
 | 
			
		||||
public:
 | 
			
		||||
    static constexpr unsigned short DEFAULT_PORT = 8021; // default port for multicast messages
 | 
			
		||||
    static const in_addr DEFAULT_MULTICAST_ADDR; // default multicast address
 | 
			
		||||
    static constexpr size_t DEFAULT_ANNOUNCE_PERIOD_MS = 1000; // default announce period
 | 
			
		||||
private:
 | 
			
		||||
    // structure for storing nodes
 | 
			
		||||
    struct ClientNodeInfo {
 | 
			
		||||
        in_addr addr; // address of client
 | 
			
		||||
        uint16_t terminalPort;
 | 
			
		||||
    };
 | 
			
		||||
private:
 | 
			
		||||
    int mBeaconSoc; // beacon socket
 | 
			
		||||
    in_addr mAddr; // address
 | 
			
		||||
    unsigned short mBeaconPort; // port
 | 
			
		||||
    size_t mAnnPeriod_ms; // announce period
 | 
			
		||||
    std::list<ClientNodeInfo> mNodes; // nodes
 | 
			
		||||
    bool mRunning; // does the beacon operate?
 | 
			
		||||
private:
 | 
			
		||||
    std::shared_ptr<std::thread> mpBeaconThread; // thread running the beacon
 | 
			
		||||
    static void fn_BeaconThread(ServerBeacon * pSB); // function running in beacon thread
 | 
			
		||||
private:
 | 
			
		||||
    // structure for beacon MSG
 | 
			
		||||
    struct BeaconMsg {
 | 
			
		||||
        uint8_t server_nClient; // server or client
 | 
			
		||||
        uint16_t terminalPort; // port of terminal
 | 
			
		||||
    };
 | 
			
		||||
public:
 | 
			
		||||
    ServerBeacon(); // constr.
 | 
			
		||||
    explicit ServerBeacon(const in_addr& addr, unsigned short port, size_t announcePeriod_ms); // constr. with beacon port and announce period
 | 
			
		||||
    void setMulticastAddr(const in_addr& addr); // set multicasting address
 | 
			
		||||
    in_addr getMulticastAddr() const; // set multicasting address
 | 
			
		||||
    void setPort(unsigned short port); // set port BEFORE starting beacon
 | 
			
		||||
    unsigned short getPort() const; // get beacon port
 | 
			
		||||
    void setAnnouncePeriod(size_t period_ms); // set announce period
 | 
			
		||||
    size_t getAnnouncePeriod() const; // get announce period
 | 
			
		||||
    void startBeacon(); // start the beacon
 | 
			
		||||
    void stopBeacon(); // stop the beacon
 | 
			
		||||
    std::list<in_addr> getNodesOnNetwork(); // get nodes connected to the same network
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif //WFR_SERVERBEACON_H
 | 
			
		||||
@ -7,7 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
 | 
			
		||||
#define STEREO_BUF_LEN (648)
 | 
			
		||||
#define STEREO_BUF_LEN (2 * 192)
 | 
			
		||||
#define PERIOD_LEN (STEREO_BUF_LEN / 2)
 | 
			
		||||
#define SAMPLE_RATE (48000)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user