Skip to content

Commit 2ebd8d0

Browse files
committed
Added missing functions to Scheduler.
1 parent c70696d commit 2ebd8d0

File tree

4 files changed

+219
-3
lines changed

4 files changed

+219
-3
lines changed

CMakeLists.txt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,18 @@ target_link_libraries(auto_sdr
5555
)
5656

5757
add_executable(auto_sdr_test ${TEST_SOURCES} "tests/test_main.cpp")
58-
target_link_libraries(auto_sdr_test auto_sdr_libs gtest)
58+
target_link_libraries(auto_sdr_test
59+
gtest
60+
auto_sdr_libs
61+
gnuradio::gnuradio-blocks
62+
gnuradio::gnuradio-fft
63+
gnuradio::gnuradio-filter
64+
gnuradio::gnuradio-soapy
65+
nlohmann_json::nlohmann_json
66+
spdlog::spdlog
67+
PahoMqttCpp::paho-mqttpp3
68+
CLI11::CLI11
69+
)
5970

6071
install(TARGETS auto_sdr DESTINATION)
6172
install(TARGETS auto_sdr_test DESTINATION)

sources/radio/scheduler.cpp

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@
88
constexpr auto LABEL = "scheduler";
99
constexpr auto LOOP_TIMEOUT = std::chrono::milliseconds(100);
1010
constexpr auto UPDATE_INTERVAL = std::chrono::minutes(60);
11+
constexpr auto SHIFT_FREQUENCY = Frequency(100000);
1112

1213
using namespace std::placeholders;
1314

15+
ScheduledTransmission::ScheduledTransmission(
16+
const std::string& name, const std::chrono::seconds& begin, const std::chrono::seconds& end, const Frequency& frequency, const Frequency& bandwidth, const std::string& modulation)
17+
: m_name(name), m_begin(begin), m_end(end), m_frequency(frequency), m_bandwidth(bandwidth), m_modulation(modulation) {}
18+
1419
Scheduler::Scheduler(const Config& config, const Device& device, RemoteController& remoteController)
1520
: m_config(config), m_device(device), m_remoteController(remoteController), m_lastUpdateTime(0), m_isRunning(true), m_thread([this]() { worker(); }) {}
1621

@@ -19,6 +24,43 @@ Scheduler::~Scheduler() {
1924
m_thread.join();
2025
}
2126

27+
std::vector<ScheduledTransmission> Scheduler::getTransmissions(const std::chrono::milliseconds& now, std::list<ScheduledTransmission>& scheduledTransmissions) {
28+
while (!scheduledTransmissions.empty() && scheduledTransmissions.front().m_end < now) {
29+
scheduledTransmissions.pop_front();
30+
}
31+
std::vector<ScheduledTransmission> transmissions;
32+
for (auto it = scheduledTransmissions.begin(); it != scheduledTransmissions.end() && it->m_begin <= now; ++it) {
33+
transmissions.push_back(*it);
34+
}
35+
return transmissions;
36+
}
37+
38+
std::optional<std::pair<FrequencyRange, std::vector<Recording>>> Scheduler::getRecordings(
39+
const std::chrono::milliseconds& now, std::list<ScheduledTransmission>& scheduledTransmissions, Frequency sampleRate, Frequency shift) {
40+
const auto transmissions = getTransmissions(now, scheduledTransmissions);
41+
if (transmissions.empty()) {
42+
return std::nullopt;
43+
}
44+
const auto center = transmissions.front().m_frequency + shift;
45+
const auto left = center - sampleRate / 2;
46+
const auto right = center + sampleRate / 2;
47+
const FrequencyRange range(left, right);
48+
std::vector<Recording> recordings;
49+
for (const auto& transmission : transmissions) {
50+
const auto transmissionLeft = transmission.m_frequency - transmission.m_bandwidth / 2;
51+
const auto transmissionRight = transmission.m_frequency + transmission.m_bandwidth / 2;
52+
if (left <= transmissionLeft && transmissionRight <= right) {
53+
recordings.emplace_back(transmission.m_frequency - center, true);
54+
}
55+
}
56+
return std::pair<FrequencyRange, std::vector<Recording>>(range, recordings);
57+
}
58+
59+
std::optional<std::pair<FrequencyRange, std::vector<Recording>>> Scheduler::getRecordings(const std::chrono::milliseconds& now) {
60+
std::unique_lock lock(m_mutex);
61+
return Scheduler::getRecordings(now, m_scheduledTransmissions, m_device.m_sampleRate, SHIFT_FREQUENCY);
62+
}
63+
2264
void Scheduler::worker() {
2365
m_remoteController.satellitesCallback(m_device.getName(), std::bind(&Scheduler::satellitesCallback, this, _1));
2466
while (m_isRunning) {
@@ -47,4 +89,20 @@ void Scheduler::satellitesQuery() {
4789
m_remoteController.satellitesQuery(m_device.getName(), json.dump());
4890
}
4991

50-
void Scheduler::satellitesCallback(const nlohmann::json& json) { Logger::info(LABEL, "received satellites: {}", colored(GREEN, "{}", json.dump())); }
92+
void Scheduler::satellitesCallback(const nlohmann::json& json) {
93+
Logger::info(LABEL, "received satellites: {}", colored(GREEN, "{}", json.dump()));
94+
95+
std::list<ScheduledTransmission> scheduledTransmissions;
96+
for (const auto& item : json) {
97+
const auto name = item.at("name").get<std::string>();
98+
const auto begin = std::chrono::seconds(item.at("begin").get<uint64_t>());
99+
const auto end = std::chrono::seconds(item.at("end").get<uint64_t>());
100+
const auto frequency = item.at("frequency").get<Frequency>();
101+
const auto bandwidth = item.at("bandwidth").get<Frequency>();
102+
const auto modulation = item.at("modulation").get<std::string>();
103+
scheduledTransmissions.emplace_back(name, begin, end, frequency, bandwidth, modulation);
104+
}
105+
106+
std::unique_lock lock(m_mutex);
107+
m_scheduledTransmissions = scheduledTransmissions;
108+
}

sources/radio/scheduler.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,42 @@
44
#include <network/remote_controller.h>
55
#include <radio/sdr_device.h>
66

7+
#include <list>
8+
#include <mutex>
9+
#include <optional>
10+
11+
struct ScheduledTransmission {
12+
ScheduledTransmission(
13+
const std::string& m_name, const std::chrono::seconds& m_begin, const std::chrono::seconds& m_end, const Frequency& m_frequency, const Frequency& m_bandwidth, const std::string& m_modulation);
14+
15+
std::string m_name;
16+
std::chrono::seconds m_begin;
17+
std::chrono::seconds m_end;
18+
Frequency m_frequency;
19+
Frequency m_bandwidth;
20+
std::string m_modulation;
21+
};
22+
723
class Scheduler {
824
public:
925
Scheduler(const Config& config, const Device& device, RemoteController& remoteController);
1026
~Scheduler();
1127

12-
private:
28+
static std::vector<ScheduledTransmission> getTransmissions(const std::chrono::milliseconds& now, std::list<ScheduledTransmission>& scheduledTransmissions);
29+
static std::optional<std::pair<FrequencyRange, std::vector<Recording>>> getRecordings(
30+
const std::chrono::milliseconds& now, std::list<ScheduledTransmission>& scheduledTransmissions, Frequency sampleRate, Frequency shift);
31+
std::optional<std::pair<FrequencyRange, std::vector<Recording>>> getRecordings(const std::chrono::milliseconds& now);
32+
1333
void worker();
1434
void satellitesQuery();
1535
void satellitesCallback(const nlohmann::json& json);
1636

1737
const Config& m_config;
1838
const Device m_device;
1939
RemoteController& m_remoteController;
40+
std::list<ScheduledTransmission> m_scheduledTransmissions;
2041
std::chrono::milliseconds m_lastUpdateTime;
2142
std::atomic<bool> m_isRunning;
2243
std::thread m_thread;
44+
std::mutex m_mutex;
2345
};

tests/test_scheduler.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#include <gtest/gtest.h>
2+
#include <radio/scheduler.h>
3+
4+
#include <chrono>
5+
6+
using namespace std::chrono_literals;
7+
8+
TEST(Scheduler, Transmissions) {
9+
std::list<ScheduledTransmission> scheduledTransmissions;
10+
const Frequency f1(700);
11+
const Frequency f2(800);
12+
const Frequency f3(800);
13+
14+
scheduledTransmissions.emplace_back("", 100s, 200s, f1, 20, "");
15+
scheduledTransmissions.emplace_back("", 150s, 200s, f2, 20, "");
16+
scheduledTransmissions.emplace_back("", 250s, 300s, f3, 20, "");
17+
18+
{
19+
const auto result = Scheduler::getTransmissions(10s, scheduledTransmissions);
20+
EXPECT_EQ(result.size(), 0);
21+
EXPECT_EQ(scheduledTransmissions.size(), 3);
22+
}
23+
{
24+
const auto result = Scheduler::getTransmissions(99s, scheduledTransmissions);
25+
EXPECT_EQ(result.size(), 0);
26+
EXPECT_EQ(scheduledTransmissions.size(), 3);
27+
}
28+
{
29+
const auto result = Scheduler::getTransmissions(100s, scheduledTransmissions);
30+
EXPECT_EQ(result.size(), 1);
31+
EXPECT_EQ(result[0].m_frequency, f1);
32+
EXPECT_EQ(scheduledTransmissions.size(), 3);
33+
}
34+
{
35+
const auto result = Scheduler::getTransmissions(150s, scheduledTransmissions);
36+
EXPECT_EQ(result.size(), 2);
37+
EXPECT_EQ(result[0].m_frequency, f1);
38+
EXPECT_EQ(result[1].m_frequency, f2);
39+
EXPECT_EQ(scheduledTransmissions.size(), 3);
40+
}
41+
{
42+
const auto result = Scheduler::getTransmissions(200s, scheduledTransmissions);
43+
EXPECT_EQ(result.size(), 2);
44+
EXPECT_EQ(result[0].m_frequency, f1);
45+
EXPECT_EQ(result[1].m_frequency, f2);
46+
EXPECT_EQ(scheduledTransmissions.size(), 3);
47+
}
48+
{
49+
const auto result = Scheduler::getTransmissions(201s, scheduledTransmissions);
50+
EXPECT_EQ(result.size(), 0);
51+
EXPECT_EQ(scheduledTransmissions.size(), 1);
52+
}
53+
{
54+
const auto result = Scheduler::getTransmissions(250s, scheduledTransmissions);
55+
EXPECT_EQ(result.size(), 1);
56+
EXPECT_EQ(result[0].m_frequency, f3);
57+
EXPECT_EQ(scheduledTransmissions.size(), 1);
58+
}
59+
{
60+
const auto result = Scheduler::getTransmissions(301s, scheduledTransmissions);
61+
EXPECT_EQ(result.size(), 0);
62+
EXPECT_EQ(scheduledTransmissions.size(), 0);
63+
}
64+
}
65+
66+
TEST(Scheduler, Recordings) {
67+
std::list<ScheduledTransmission> scheduledTransmissions;
68+
const Frequency f1(7000);
69+
const Frequency f2(7500);
70+
const Frequency f3(8050);
71+
const Frequency sampleRate(2000);
72+
const Frequency shift(100);
73+
74+
scheduledTransmissions.emplace_back("", 100s, 300s, f1, 100, "");
75+
scheduledTransmissions.emplace_back("", 150s, 300s, f2, 100, "");
76+
scheduledTransmissions.emplace_back("", 200s, 300s, f3, 100, "");
77+
78+
{
79+
const auto result = Scheduler::getRecordings(125s, scheduledTransmissions, sampleRate, shift);
80+
EXPECT_EQ(result->first, FrequencyRange(6100, 8100));
81+
EXPECT_EQ(result->second.size(), 1);
82+
EXPECT_EQ(result->second[0].m_shift, -100);
83+
}
84+
{
85+
const auto result = Scheduler::getRecordings(175s, scheduledTransmissions, sampleRate, shift);
86+
EXPECT_EQ(result->first, FrequencyRange(6100, 8100));
87+
EXPECT_EQ(result->second.size(), 2);
88+
EXPECT_EQ(result->second[0].m_shift, -100);
89+
EXPECT_EQ(result->second[1].m_shift, 400);
90+
}
91+
{
92+
const auto result = Scheduler::getRecordings(225s, scheduledTransmissions, sampleRate, shift);
93+
EXPECT_EQ(result->first, FrequencyRange(6100, 8100));
94+
EXPECT_EQ(result->second.size(), 3);
95+
EXPECT_EQ(result->second[0].m_shift, -100);
96+
EXPECT_EQ(result->second[1].m_shift, 400);
97+
EXPECT_EQ(result->second[2].m_shift, 950);
98+
}
99+
}
100+
101+
TEST(Scheduler, RecordingsEdgeCase) {
102+
std::list<ScheduledTransmission> scheduledTransmissions;
103+
const Frequency f1(7000);
104+
const Frequency f2(6149);
105+
const Frequency f3(6150);
106+
const Frequency f4(8050);
107+
const Frequency f5(8051);
108+
const Frequency sampleRate(2000);
109+
const Frequency shift(100);
110+
111+
scheduledTransmissions.emplace_back("", 200s, 300s, f1, 100, "");
112+
scheduledTransmissions.emplace_back("", 200s, 300s, f2, 100, "");
113+
scheduledTransmissions.emplace_back("", 200s, 300s, f3, 100, "");
114+
scheduledTransmissions.emplace_back("", 200s, 300s, f4, 100, "");
115+
scheduledTransmissions.emplace_back("", 200s, 300s, f5, 100, "");
116+
117+
{
118+
const auto result = Scheduler::getRecordings(250s, scheduledTransmissions, sampleRate, shift);
119+
EXPECT_EQ(result->first, FrequencyRange(6100, 8100));
120+
EXPECT_EQ(result->second.size(), 3);
121+
EXPECT_EQ(result->second[0].m_shift, -100);
122+
EXPECT_EQ(result->second[1].m_shift, -950);
123+
EXPECT_EQ(result->second[2].m_shift, 950);
124+
}
125+
}

0 commit comments

Comments
 (0)