43 double frequencyOverlapRatio(std::uint64_t u64FrequencyHz1,
44 std::uint64_t u64BandwidthHz1,
45 std::uint64_t u64FrequencyHz2,
46 std::uint64_t u64BandwidthHz2);
56 u64ReceiverBandwidthHz_{},
58 dReceiverSensitivityMilliWatt_{}{}
61 std::uint64_t u64BandwidthHz,
62 double dReceiverSensitivityMilliWatt,
71 std::lock_guard<std::mutex> m(mutex_);
77 maxOffset_ = maxOffset;
79 maxPropagation_ = maxPropagation;
81 maxDuration_ = maxDuration;
83 bMaxClamp_ = bMaxClamp;
85 timeSyncThreshold_ = timeSyncThreshold;
87 dReceiverSensitivityMilliWatt_ = dReceiverSensitivityMilliWatt;
89 u64ReceiverBandwidthHz_ = u64BandwidthHz;
92 transmitterBandwidthCache_.clear();
94 TransmitterBandwidthCache transmitterBandwidthCache_;
96 transmitterBandwidthCache_.insert(std::make_pair(u64BandwidthHz,std::unique_ptr<Cache>(
new Cache{})));
98 noiseRecorderMap_.clear();
100 for(
const auto & frequency : foi)
102 noiseRecorderMap_.insert(std::make_pair(frequency,
107 dReceiverSensitivityMilliWatt}}));
112 std::tuple<EMANE::TimePoint,EMANE::Microseconds,EMANE::Microseconds,EMANE::FrequencySegments,bool>
117 std::uint64_t u64SegmentBandwidthHz,
118 const std::vector<double> & rxPowersMilliWatt,
120 const std::vector<NEMId> & transmitters)
122 std::lock_guard<std::mutex> m(mutex_);
124 if(segments.size() != rxPowersMilliWatt.size())
129 bool bReportAsInBand{};
134 auto validTxTime = txTime;
136 if(txTime > now + timeSyncThreshold_ || now - txTime > timeSyncThreshold_)
141 auto validPropagation = propagationDelay;
143 if(propagationDelay > maxPropagation_)
147 validPropagation = maxPropagation_;
151 throw makeException<SpectrumServiceException>(
"Message propagation %ju usec > max propagation %ju usec and max clamp is %s",
152 propagationDelay.count(),
153 maxPropagation_.count(),
154 bMaxClamp_ ?
"on" :
"off");
167 bReportAsInBand =
true;
169 for(
const auto & segment : segments)
171 if(noiseRecorderMap_.find(segment.getFrequencyHz()) != noiseRecorderMap_.end())
173 if(rxPowersMilliWatt[i] >= dReceiverSensitivityMilliWatt_)
175 auto validOffset = segment.getOffset();
177 if(validOffset > maxOffset_)
181 validOffset = maxOffset_;
185 throw makeException<SpectrumServiceException>(
"Segment offset %ju usec > max offset %ju usec and max clamp is %s",
188 bMaxClamp_ ?
"on" :
"off");
192 auto validDuration = segment.getDuration();
194 if(validDuration > maxDuration_)
198 validDuration = maxDuration_;
202 throw makeException<SpectrumServiceException>(
"Segment duration %ju usec > max duration %ju usec and max clamp is %s",
203 validDuration.count(),
204 maxDuration_.count(),
205 bMaxClamp_ ?
"on" :
"off");
210 std::max(maxEoR,validTxTime + validOffset + validDuration + validPropagation);
213 std::min(minSoR,validTxTime + validOffset + validPropagation);
215 reportableFrequencySegments.push_back({segment.getFrequencyHz(),
225 bReportAsInBand =
false;
234 const auto transmitterBandwidthCacheIter =
235 transmitterBandwidthCache_.find(u64SegmentBandwidthHz);
238 if(transmitterBandwidthCacheIter != transmitterBandwidthCache_.end())
241 pCache = transmitterBandwidthCacheIter->second.get();
246 pCache =
new Cache{};
248 transmitterBandwidthCache_.insert(std::make_pair(u64SegmentBandwidthHz,
249 std::unique_ptr<Cache>(pCache)));
254 for(
const auto & segment : segments)
256 bool bFrequencyMatch{};
257 bool bAboveSensitivity{};
262 auto iter = pCache->find(segment.getFrequencyHz());
264 auto validOffset = segment.getOffset();
266 if(validOffset > maxOffset_)
270 validOffset = maxOffset_;
274 throw makeException<SpectrumServiceException>(
"Segment offset %ju usec > max offset %ju usec and max clamp is %s",
277 bMaxClamp_ ?
"on" :
"off");
281 auto validDuration = segment.getDuration();
283 if(validDuration > maxDuration_)
287 validDuration = maxDuration_;
291 throw makeException<SpectrumServiceException>(
"Segment duration %ju usec > max duration %ju usec and max clamp is %s",
292 validDuration.count(),
293 maxDuration_.count(),
294 bMaxClamp_ ?
"on" :
"off");
298 if(iter != pCache->end())
300 for(
const auto & entry : iter->second)
303 double dOverlapRatio{};
304 std::uint64_t u64RecorderFrequencyHz{};
306 std::tie(pNoiseRecorder,
308 u64RecorderFrequencyHz) = entry;
310 if(dOverlapRatio > 0)
312 double dOverlapRxPowerMillWatt{rxPowersMilliWatt[i] * dOverlapRatio};
314 if(dOverlapRxPowerMillWatt >= dReceiverSensitivityMilliWatt_)
316 bAboveSensitivity =
true;
318 std::tie(startOfReception,endOfReception) =
319 pNoiseRecorder->
update(now,
324 dOverlapRxPowerMillWatt,
330 bFrequencyMatch = (u64RecorderFrequencyHz == segment.getFrequencyHz());
337 std::vector<std::tuple<NoiseRecorder *,double,std::uint64_t>> recorderInfo;
339 recorderInfo.reserve(noiseRecorderMap_.size());
341 for(
const auto & entry : noiseRecorderMap_)
343 double dOverlapRatio{frequencyOverlapRatio(entry.first,
344 u64ReceiverBandwidthHz_,
345 segment.getFrequencyHz(),
346 u64SegmentBandwidthHz)};
348 if(dOverlapRatio > 0)
350 double dOverlapRxPowerMillWatt{rxPowersMilliWatt[i] * dOverlapRatio};
352 if(dOverlapRxPowerMillWatt >= dReceiverSensitivityMilliWatt_)
354 bAboveSensitivity =
true;
356 std::tie(startOfReception,endOfReception) =
357 entry.second->update(now,
362 dOverlapRxPowerMillWatt,
368 bFrequencyMatch = (entry.first == segment.getFrequencyHz());
372 recorderInfo.push_back(std::make_tuple(entry.second.get(),dOverlapRatio,entry.first));
375 pCache->insert({segment.getFrequencyHz(),std::move(recorderInfo)});
382 bReportAsInBand =
true;
385 if(bAboveSensitivity)
387 maxEoR = std::max(maxEoR,endOfReception);
389 minSoR = std::min(minSoR,startOfReception);
391 reportableFrequencySegments.push_back({segment.getFrequencyHz(),
402 return std::make_tuple(validTxTime,
404 std::chrono::duration_cast<Microseconds>(maxEoR - minSoR),
405 reportableFrequencySegments,
412 std::lock_guard<std::mutex> m(mutex_);
416 std::transform(noiseRecorderMap_.begin(),
417 noiseRecorderMap_.end(),
418 std::inserter(frequencySet,frequencySet.begin()),
419 std::bind(&NoiseRecorderMap::value_type::first,
420 std::placeholders::_1));
426 std::lock_guard<std::mutex> m(mutex_);
433 std::uint64_t u64FrequencyHz,
437 std::lock_guard<std::mutex> m(mutex_);
439 auto validDuration = duration;
441 if(validDuration > maxDuration_)
445 validDuration = maxDuration_;
449 throw makeException<SpectrumServiceException>(
"Segment duration %ju usec > max duration %ju usec and max clamp is %s",
450 validDuration.count(),
451 maxDuration_.count(),
452 bMaxClamp_ ?
"on" :
"off");
456 const auto iter = noiseRecorderMap_.find(u64FrequencyHz);
458 if(iter!= noiseRecorderMap_.end())
460 auto ret = iter->second->get(now,validDuration,timepoint);
462 return std::tuple_cat(std::move(ret),std::make_tuple(binSize_,dReceiverSensitivityMilliWatt_,mode_==
NoiseMode::ALL));
475 return request_i(Clock::now(),u64FrequencyHz,duration,timepoint);
480 std::lock_guard<std::mutex> m(mutex_);
482 const auto iter = noiseRecorderMap_.find(u64FrequencyHz);
484 if(iter!= noiseRecorderMap_.end())
486 return iter->second->dump();
494 double frequencyOverlapRatio(std::uint64_t u64FrequencyHz1,
495 std::uint64_t u64BandwidthHz1,
496 std::uint64_t u64FrequencyHz2,
497 std::uint64_t u64BandwidthHz2)
499 double u64UpperFrequencyHz1{u64FrequencyHz1 + u64BandwidthHz1 / 2.0};
500 double u64LowerFrequencyHz1{u64FrequencyHz1 - u64BandwidthHz1 / 2.0};
502 double u64UpperFrequencyHz2{u64FrequencyHz2 + u64BandwidthHz2 / 2.0};
503 double u64LowerFrequencyHz2{u64FrequencyHz2 - u64BandwidthHz2 / 2.0};
509 if((u64LowerFrequencyHz2 < u64UpperFrequencyHz1) && (u64UpperFrequencyHz2 > u64LowerFrequencyHz1))
512 if(u64LowerFrequencyHz2 >= u64LowerFrequencyHz1)
515 if(u64UpperFrequencyHz2 <= u64UpperFrequencyHz1)
524 dRatio = (u64UpperFrequencyHz1 - u64LowerFrequencyHz2) / u64BandwidthHz2;
531 if( u64UpperFrequencyHz2 <= u64UpperFrequencyHz1)
534 dRatio = (u64UpperFrequencyHz2 - u64LowerFrequencyHz1) / u64BandwidthHz2;
538 dRatio = (u64UpperFrequencyHz1 - u64LowerFrequencyHz1) / u64BandwidthHz2;
double MILLIWATT_TO_DB(double dMillWatt)
std::tuple< std::vector< double >, TimePoint, Microseconds, double, bool > SpectrumWindow
double getReceiverSensitivitydBm() const override
std::set< std::uint64_t > FrequencySet
std::tuple< TimePoint, Microseconds, Microseconds, FrequencySegments, bool > update(const TimePoint &now, const TimePoint &txTime, const Microseconds &propagationDelay, const FrequencySegments &segments, std::uint64_t u64SegmentBandwidthHz, const std::vector< double > &rxPowersMilliWatt, bool bInBand, const std::vector< NEMId > &transmitters)
std::chrono::microseconds Microseconds
void initialize(const FrequencySet &foi, std::uint64_t u64BandwidthHz, double dReceiverSensitivityMilliWatt, NoiseMode mode, const Microseconds &binSize, const Microseconds &maxOffset, const Microseconds &maxPropagation, const Microseconds &maxDuration, const Microseconds &timeSyncThreshold, bool bMaxClamp)
std::list< FrequencySegment > FrequencySegments
std::pair< TimePoint, TimePoint > update(const TimePoint &now, const TimePoint &txTime, const Microseconds &offset, const Microseconds &propagation, const Microseconds &duration, double dRxPower, const std::vector< NEMId > &transmitters)
FrequencySet getFrequencies() const override
Clock::time_point TimePoint
SpectrumWindow request(std::uint64_t u64FrequencyHz, const Microseconds &duration=Microseconds::zero(), const TimePoint &timepoint=TimePoint::min()) const override
std::vector< double > dump(std::uint64_t u64FrequencyHz) const
SpectrumWindow request_i(const TimePoint &now, std::uint64_t u64FrequencyHz, const Microseconds &duration=Microseconds::zero(), const TimePoint &timepoint=TimePoint::min()) const