44 double frequencyOverlapRatio(std::uint64_t u64FrequencyHz1,
45 std::uint64_t u64BandwidthHz1,
46 std::uint64_t u64FrequencyHz2,
47 std::uint64_t u64BandwidthHz2);
57 u64ReceiverBandwidthHz_{},
59 dReceiverSensitivityMilliWatt_{}{}
62 std::uint64_t u64BandwidthHz,
63 double dReceiverSensitivityMilliWatt,
72 std::lock_guard<std::mutex> m(mutex_);
78 maxOffset_ = maxOffset;
80 maxPropagation_ = maxPropagation;
82 maxDuration_ = maxDuration;
84 bMaxClamp_ = bMaxClamp;
86 timeSyncThreshold_ = timeSyncThreshold;
88 dReceiverSensitivityMilliWatt_ = dReceiverSensitivityMilliWatt;
90 u64ReceiverBandwidthHz_ = u64BandwidthHz;
93 transmitterBandwidthCache_.clear();
95 TransmitterBandwidthCache transmitterBandwidthCache_;
97 transmitterBandwidthCache_.insert(std::make_pair(u64BandwidthHz,std::unique_ptr<Cache>(
new Cache{})));
99 noiseRecorderMap_.clear();
101 for(
const auto & frequency : foi)
103 noiseRecorderMap_.insert(std::make_pair(frequency,
108 dReceiverSensitivityMilliWatt}}));
113 std::tuple<EMANE::TimePoint,EMANE::Microseconds,EMANE::Microseconds,EMANE::FrequencySegments,bool>
118 std::uint64_t u64SegmentBandwidthHz,
119 const std::vector<double> & rxPowersMilliWatt,
121 const std::vector<NEMId> & transmitters)
123 std::lock_guard<std::mutex> m(mutex_);
125 if(segments.size() != rxPowersMilliWatt.size())
130 bool bReportAsInBand{};
135 auto validTxTime = txTime;
137 if(txTime > now + timeSyncThreshold_ || now - txTime > timeSyncThreshold_)
142 auto validPropagation = propagationDelay;
144 if(propagationDelay > maxPropagation_)
148 validPropagation = maxPropagation_;
152 throw makeException<SpectrumServiceException>(
"Message propagation %ju usec > max propagation %ju usec and max clamp is %s",
153 propagationDelay.count(),
154 maxPropagation_.count(),
155 bMaxClamp_ ?
"on" :
"off");
168 bReportAsInBand =
true;
170 for(
const auto & segment : segments)
172 if(noiseRecorderMap_.find(segment.getFrequencyHz()) != noiseRecorderMap_.end())
174 if(rxPowersMilliWatt[i] >= dReceiverSensitivityMilliWatt_)
176 auto validOffset = segment.getOffset();
178 if(validOffset > maxOffset_)
182 validOffset = maxOffset_;
186 throw makeException<SpectrumServiceException>(
"Segment offset %ju usec > max offset %ju usec and max clamp is %s",
189 bMaxClamp_ ?
"on" :
"off");
193 auto validDuration = segment.getDuration();
195 if(validDuration > maxDuration_)
199 validDuration = maxDuration_;
203 throw makeException<SpectrumServiceException>(
"Segment duration %ju usec > max duration %ju usec and max clamp is %s",
204 validDuration.count(),
205 maxDuration_.count(),
206 bMaxClamp_ ?
"on" :
"off");
211 std::max(maxEoR,validTxTime + validOffset + validDuration + validPropagation);
214 std::min(minSoR,validTxTime + validOffset + validPropagation);
216 reportableFrequencySegments.push_back({segment.getFrequencyHz(),
226 bReportAsInBand =
false;
235 const auto transmitterBandwidthCacheIter =
236 transmitterBandwidthCache_.find(u64SegmentBandwidthHz);
239 if(transmitterBandwidthCacheIter != transmitterBandwidthCache_.end())
242 pCache = transmitterBandwidthCacheIter->second.get();
247 pCache =
new Cache{};
249 transmitterBandwidthCache_.insert(std::make_pair(u64SegmentBandwidthHz,
250 std::unique_ptr<Cache>(pCache)));
255 for(
const auto & segment : segments)
257 bool bFrequencyMatch{};
258 bool bAboveSensitivity{};
263 auto iter = pCache->find(segment.getFrequencyHz());
265 auto validOffset = segment.getOffset();
267 if(validOffset > maxOffset_)
271 validOffset = maxOffset_;
275 throw makeException<SpectrumServiceException>(
"Segment offset %ju usec > max offset %ju usec and max clamp is %s",
278 bMaxClamp_ ?
"on" :
"off");
282 auto validDuration = segment.getDuration();
284 if(validDuration > maxDuration_)
288 validDuration = maxDuration_;
292 throw makeException<SpectrumServiceException>(
"Segment duration %ju usec > max duration %ju usec and max clamp is %s",
293 validDuration.count(),
294 maxDuration_.count(),
295 bMaxClamp_ ?
"on" :
"off");
299 if(iter != pCache->end())
301 for(
const auto & entry : iter->second)
304 double dOverlapRatio{};
305 std::uint64_t u64RecorderFrequencyHz{};
307 std::tie(pNoiseRecorder,
309 u64RecorderFrequencyHz) = entry;
311 if(dOverlapRatio > 0)
313 double dOverlapRxPowerMillWatt{rxPowersMilliWatt[i] * dOverlapRatio};
315 if(dOverlapRxPowerMillWatt >= dReceiverSensitivityMilliWatt_)
317 bAboveSensitivity =
true;
319 std::tie(startOfReception,endOfReception) =
320 pNoiseRecorder->
update(now,
325 dOverlapRxPowerMillWatt,
331 bFrequencyMatch = (u64RecorderFrequencyHz == segment.getFrequencyHz());
338 std::vector<std::tuple<NoiseRecorder *,double,std::uint64_t>> recorderInfo;
340 recorderInfo.reserve(noiseRecorderMap_.size());
342 for(
const auto & entry : noiseRecorderMap_)
344 double dOverlapRatio{frequencyOverlapRatio(entry.first,
345 u64ReceiverBandwidthHz_,
346 segment.getFrequencyHz(),
347 u64SegmentBandwidthHz)};
349 if(dOverlapRatio > 0)
351 double dOverlapRxPowerMillWatt{rxPowersMilliWatt[i] * dOverlapRatio};
353 if(dOverlapRxPowerMillWatt >= dReceiverSensitivityMilliWatt_)
355 bAboveSensitivity =
true;
357 std::tie(startOfReception,endOfReception) =
358 entry.second->update(now,
363 dOverlapRxPowerMillWatt,
369 bFrequencyMatch = (entry.first == segment.getFrequencyHz());
373 recorderInfo.push_back(std::make_tuple(entry.second.get(),dOverlapRatio,entry.first));
376 pCache->insert({segment.getFrequencyHz(),std::move(recorderInfo)});
383 bReportAsInBand =
true;
386 if(bAboveSensitivity)
388 maxEoR = std::max(maxEoR,endOfReception);
390 minSoR = std::min(minSoR,startOfReception);
392 reportableFrequencySegments.push_back({segment.getFrequencyHz(),
403 return std::make_tuple(validTxTime,
405 std::chrono::duration_cast<Microseconds>(maxEoR - minSoR),
406 reportableFrequencySegments,
413 std::lock_guard<std::mutex> m(mutex_);
417 std::transform(noiseRecorderMap_.begin(),
418 noiseRecorderMap_.end(),
419 std::inserter(frequencySet,frequencySet.begin()),
420 std::bind(&NoiseRecorderMap::value_type::first,
421 std::placeholders::_1));
427 std::lock_guard<std::mutex> m(mutex_);
434 std::uint64_t u64FrequencyHz,
438 std::lock_guard<std::mutex> m(mutex_);
440 auto validDuration = duration;
442 if(validDuration > maxDuration_)
446 validDuration = maxDuration_;
450 throw makeException<SpectrumServiceException>(
"Segment duration %ju usec > max duration %ju usec and max clamp is %s",
451 validDuration.count(),
452 maxDuration_.count(),
453 bMaxClamp_ ?
"on" :
"off");
457 const auto iter = noiseRecorderMap_.find(u64FrequencyHz);
459 if(iter!= noiseRecorderMap_.end())
461 auto ret = iter->second->get(now,validDuration,timepoint);
463 return std::tuple_cat(std::move(ret),std::make_tuple(binSize_,dReceiverSensitivityMilliWatt_,mode_==
NoiseMode::ALL));
476 return request_i(Clock::now(),u64FrequencyHz,duration,timepoint);
481 std::lock_guard<std::mutex> m(mutex_);
483 const auto iter = noiseRecorderMap_.find(u64FrequencyHz);
485 if(iter!= noiseRecorderMap_.end())
487 return iter->second->dump();
495 double frequencyOverlapRatio(std::uint64_t u64FrequencyHz1,
496 std::uint64_t u64BandwidthHz1,
497 std::uint64_t u64FrequencyHz2,
498 std::uint64_t u64BandwidthHz2)
500 double u64UpperFrequencyHz1{u64FrequencyHz1 + u64BandwidthHz1 / 2.0};
501 double u64LowerFrequencyHz1{u64FrequencyHz1 - u64BandwidthHz1 / 2.0};
503 double u64UpperFrequencyHz2{u64FrequencyHz2 + u64BandwidthHz2 / 2.0};
504 double u64LowerFrequencyHz2{u64FrequencyHz2 - u64BandwidthHz2 / 2.0};
510 if((u64LowerFrequencyHz2 < u64UpperFrequencyHz1) && (u64UpperFrequencyHz2 > u64LowerFrequencyHz1))
513 if(u64LowerFrequencyHz2 >= u64LowerFrequencyHz1)
516 if(u64UpperFrequencyHz2 <= u64UpperFrequencyHz1)
525 dRatio = (u64UpperFrequencyHz1 - u64LowerFrequencyHz2) / u64BandwidthHz2;
532 if( u64UpperFrequencyHz2 <= u64UpperFrequencyHz1)
535 dRatio = (u64UpperFrequencyHz2 - u64LowerFrequencyHz1) / u64BandwidthHz2;
539 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