OLD | NEW |
(Empty) | |
| 1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ |
| 2 /* |
| 3 * Copyright (c) 2017 University of Padova |
| 4 * |
| 5 * This program is free software; you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 2 as |
| 7 * published by the Free Software Foundation; |
| 8 * |
| 9 * This program is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. |
| 13 * |
| 14 * You should have received a copy of the GNU General Public License |
| 15 * along with this program; if not, write to the Free Software |
| 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 17 * |
| 18 * Author: Davide Magrin <magrinda@dei.unipd.it> |
| 19 */ |
| 20 |
| 21 #include "ns3/lora-mac-helper.h" |
| 22 #include "ns3/gateway-lora-phy.h" |
| 23 #include "ns3/lora-net-device.h" |
| 24 #include "ns3/log.h" |
| 25 |
| 26 namespace ns3 { |
| 27 |
| 28 NS_LOG_COMPONENT_DEFINE ("LoraMacHelper"); |
| 29 |
| 30 LoraMacHelper::LoraMacHelper () : |
| 31 m_region (LoraMacHelper::EU) |
| 32 { |
| 33 } |
| 34 |
| 35 void |
| 36 LoraMacHelper::Set (std::string name, const AttributeValue &v) |
| 37 { |
| 38 m_mac.Set (name, v); |
| 39 } |
| 40 |
| 41 void |
| 42 LoraMacHelper::SetDeviceType (enum DeviceType dt) |
| 43 { |
| 44 NS_LOG_FUNCTION (this << dt); |
| 45 switch (dt) |
| 46 { |
| 47 case GW: |
| 48 m_mac.SetTypeId ("ns3::GatewayLoraMac"); |
| 49 break; |
| 50 case ED: |
| 51 m_mac.SetTypeId ("ns3::EndDeviceLoraMac"); |
| 52 break; |
| 53 } |
| 54 m_deviceType = dt; |
| 55 } |
| 56 |
| 57 void |
| 58 LoraMacHelper::SetAddressGenerator (Ptr<LoraDeviceAddressGenerator> addrGen) |
| 59 { |
| 60 NS_LOG_FUNCTION (this); |
| 61 |
| 62 m_addrGen = addrGen; |
| 63 } |
| 64 |
| 65 void |
| 66 LoraMacHelper::SetRegion (enum LoraMacHelper::Regions region) |
| 67 { |
| 68 m_region = region; |
| 69 } |
| 70 |
| 71 Ptr<LoraMac> |
| 72 LoraMacHelper::Create (Ptr<Node> node, Ptr<NetDevice> device) const |
| 73 { |
| 74 Ptr<LoraMac> mac = m_mac.Create<LoraMac> (); |
| 75 mac->SetDevice (device); |
| 76 |
| 77 // If we are operating on an end device, add an address to it |
| 78 if (m_deviceType == ED && m_addrGen != 0) |
| 79 { |
| 80 mac->GetObject<EndDeviceLoraMac> ()->SetDeviceAddress |
| 81 (m_addrGen->NextAddress ()); |
| 82 } |
| 83 |
| 84 // Add a basic list of channels based on the region where the device is |
| 85 // operating |
| 86 if (m_deviceType == ED) |
| 87 { |
| 88 Ptr<EndDeviceLoraMac> edMac = mac->GetObject<EndDeviceLoraMac> (); |
| 89 switch (m_region) |
| 90 { |
| 91 case LoraMacHelper::EU: |
| 92 { |
| 93 ConfigureForEuRegion (edMac); |
| 94 break; |
| 95 } |
| 96 default: |
| 97 { |
| 98 NS_LOG_ERROR ("This region isn't supported yet!"); |
| 99 break; |
| 100 } |
| 101 } |
| 102 } |
| 103 else |
| 104 { |
| 105 Ptr<GatewayLoraMac> gwMac = mac->GetObject<GatewayLoraMac> (); |
| 106 switch (m_region) |
| 107 { |
| 108 case LoraMacHelper::EU: |
| 109 { |
| 110 ConfigureForEuRegion (gwMac); |
| 111 break; |
| 112 } |
| 113 default: |
| 114 { |
| 115 NS_LOG_ERROR ("This region isn't supported yet!"); |
| 116 break; |
| 117 } |
| 118 } |
| 119 } |
| 120 return mac; |
| 121 } |
| 122 |
| 123 void |
| 124 LoraMacHelper::ConfigureForEuRegion (Ptr<EndDeviceLoraMac> edMac) const |
| 125 { |
| 126 NS_LOG_FUNCTION_NOARGS (); |
| 127 |
| 128 ApplyCommonEuConfigurations (edMac); |
| 129 |
| 130 ///////////////////////////////////////////////////// |
| 131 // TxPower -> Transmission power in dBm conversion // |
| 132 ///////////////////////////////////////////////////// |
| 133 edMac->SetTxDbmForTxPower (std::vector<double> {20,14,11,8,5,2}); |
| 134 |
| 135 //////////////////////////////////////////////////////////// |
| 136 // Matrix to know which DataRate the GW will respond with // |
| 137 //////////////////////////////////////////////////////////// |
| 138 LoraMac::ReplyDataRateMatrix matrix = {{{{0,0,0,0,0,0}}, |
| 139 {{1,0,0,0,0,0}}, |
| 140 {{2,1,0,0,0,0}}, |
| 141 {{3,2,1,0,0,0}}, |
| 142 {{4,3,2,1,0,0}}, |
| 143 {{5,4,3,2,1,0}}, |
| 144 {{6,5,4,3,2,1}}, |
| 145 {{7,6,5,4,3,2}}}}; |
| 146 edMac->SetReplyDataRateMatrix (matrix); |
| 147 |
| 148 ///////////////////// |
| 149 // Preamble length // |
| 150 ///////////////////// |
| 151 edMac->SetNPreambleSymbols (8); |
| 152 |
| 153 ////////////////////////////////////// |
| 154 // Second receive window parameters // |
| 155 ////////////////////////////////////// |
| 156 edMac->SetSecondReceiveWindowDataRate (0); |
| 157 edMac->SetSecondReceiveWindowFrequency (869.525); |
| 158 } |
| 159 |
| 160 void |
| 161 LoraMacHelper::ConfigureForEuRegion (Ptr<GatewayLoraMac> gwMac) const |
| 162 { |
| 163 NS_LOG_FUNCTION_NOARGS (); |
| 164 |
| 165 /////////////////////////////// |
| 166 // ReceivePath configuration // |
| 167 /////////////////////////////// |
| 168 Ptr<GatewayLoraPhy> gwPhy = gwMac->GetDevice ()-> |
| 169 GetObject<LoraNetDevice> ()->GetPhy ()->GetObject<GatewayLoraPhy> (); |
| 170 |
| 171 ApplyCommonEuConfigurations (gwMac); |
| 172 |
| 173 if (gwPhy) // If cast is successful, there's a GatewayLoraPhy |
| 174 { |
| 175 NS_LOG_DEBUG ("Resetting reception paths"); |
| 176 gwPhy->ResetReceptionPaths (); |
| 177 |
| 178 std::vector<double> frequencies; |
| 179 frequencies.push_back (868.1); |
| 180 frequencies.push_back (868.3); |
| 181 frequencies.push_back (868.5); |
| 182 |
| 183 std::vector<double>::iterator it = frequencies.begin (); |
| 184 |
| 185 int receptionPaths = 0; |
| 186 int maxReceptionPaths = 8; |
| 187 while (receptionPaths < maxReceptionPaths) |
| 188 { |
| 189 if (it == frequencies.end ()) |
| 190 it = frequencies.begin (); |
| 191 gwPhy->GetObject<GatewayLoraPhy> ()->AddReceptionPath (*it); |
| 192 ++it; |
| 193 receptionPaths++; |
| 194 } |
| 195 } |
| 196 } |
| 197 |
| 198 void |
| 199 LoraMacHelper::ApplyCommonEuConfigurations (Ptr<LoraMac> loraMac) const |
| 200 { |
| 201 NS_LOG_FUNCTION_NOARGS (); |
| 202 |
| 203 ////////////// |
| 204 // SubBands // |
| 205 ////////////// |
| 206 |
| 207 LogicalLoraChannelHelper channelHelper; |
| 208 channelHelper.AddSubBand (868, 868.6, 0.01, 14); |
| 209 channelHelper.AddSubBand (868.7, 869.2, 0.001, 14); |
| 210 channelHelper.AddSubBand (869.4, 869.65, 0.1, 27); |
| 211 |
| 212 ////////////////////// |
| 213 // Default channels // |
| 214 ////////////////////// |
| 215 Ptr<LogicalLoraChannel> lc1 = CreateObject<LogicalLoraChannel> (868.1, 0, 5); |
| 216 Ptr<LogicalLoraChannel> lc2 = CreateObject<LogicalLoraChannel> (868.3, 0, 5); |
| 217 Ptr<LogicalLoraChannel> lc3 = CreateObject<LogicalLoraChannel> (868.5, 0, 5); |
| 218 channelHelper.AddChannel (lc1); |
| 219 channelHelper.AddChannel (lc2); |
| 220 channelHelper.AddChannel (lc3); |
| 221 |
| 222 loraMac->SetLogicalLoraChannelHelper (channelHelper); |
| 223 |
| 224 /////////////////////////////////////////////// |
| 225 // DataRate -> SF, DataRate -> Bandwidth // |
| 226 // and DataRate -> MaxAppPayload conversions // |
| 227 /////////////////////////////////////////////// |
| 228 loraMac->SetSfForDataRate (std::vector<uint8_t> {12,11,10,9,8,7,7}); |
| 229 loraMac->SetBandwidthForDataRate (std::vector<double> |
| 230 {125000,125000,125000,125000,125000,125000,2
50000}); |
| 231 loraMac->SetMaxAppPayloadForDataRate (std::vector<uint32_t> |
| 232 {59,59,59,123,230,230,230,230}); |
| 233 |
| 234 } |
| 235 |
| 236 void |
| 237 LoraMacHelper::SetSpreadingFactorsUp (NodeContainer endDevices, NodeContainer ga
teways, Ptr<LoraChannel> channel) |
| 238 { |
| 239 NS_LOG_FUNCTION_NOARGS (); |
| 240 |
| 241 for (NodeContainer::Iterator j = endDevices.Begin (); j != endDevices.End ();
++j) |
| 242 { |
| 243 Ptr<Node> object = *j; |
| 244 Ptr<MobilityModel> position = object->GetObject<MobilityModel> (); |
| 245 NS_ASSERT (position != 0); |
| 246 Ptr<NetDevice> netDevice = object->GetDevice (0); |
| 247 Ptr<LoraNetDevice> loraNetDevice = netDevice->GetObject<LoraNetDevice> (); |
| 248 NS_ASSERT (loraNetDevice != 0); |
| 249 Ptr<EndDeviceLoraMac> mac = loraNetDevice->GetMac ()->GetObject<EndDeviceL
oraMac> (); |
| 250 NS_ASSERT (mac != 0); |
| 251 |
| 252 // Try computing the distance from each gateway and find the best one |
| 253 Ptr<Node> bestGateway = gateways.Get (0); |
| 254 Ptr<MobilityModel> bestGatewayPosition = bestGateway->GetObject<MobilityMo
del> (); |
| 255 |
| 256 // Assume devices transmit at 14 dBm |
| 257 double highestRxPower = channel->GetRxPower (14, position, bestGatewayPosi
tion); |
| 258 |
| 259 for (NodeContainer::Iterator currentGw = gateways.Begin () + 1; |
| 260 currentGw != gateways.End (); ++currentGw) |
| 261 { |
| 262 // Compute the power received from the current gateway |
| 263 Ptr<Node> curr = *currentGw; |
| 264 Ptr<MobilityModel> currPosition = curr->GetObject<MobilityModel> (); |
| 265 double currentRxPower = channel->GetRxPower (14, position, currPositio
n); // dBm |
| 266 |
| 267 if (currentRxPower > highestRxPower) |
| 268 { |
| 269 bestGateway = curr; |
| 270 bestGatewayPosition = curr->GetObject<MobilityModel> (); |
| 271 highestRxPower = currentRxPower; |
| 272 } |
| 273 } |
| 274 |
| 275 // NS_LOG_DEBUG ("Rx Power: " << highestRxPower); |
| 276 double rxPower = highestRxPower; |
| 277 |
| 278 // Get the Gw sensitivity |
| 279 Ptr<NetDevice> gatewayNetDevice = bestGateway->GetDevice (0); |
| 280 Ptr<LoraNetDevice> gatewayLoraNetDevice = gatewayNetDevice->GetObject<Lora
NetDevice> (); |
| 281 Ptr<GatewayLoraPhy> gatewayPhy = gatewayLoraNetDevice->GetPhy ()->GetObjec
t<GatewayLoraPhy> (); |
| 282 const double *gwSensitivity = gatewayPhy->sensitivity; |
| 283 |
| 284 if(rxPower > *gwSensitivity) |
| 285 { |
| 286 mac->SetDataRate (5); |
| 287 } |
| 288 else if (rxPower > *(gwSensitivity+1)) |
| 289 { |
| 290 mac->SetDataRate (4); |
| 291 } |
| 292 else if (rxPower > *(gwSensitivity+2)) |
| 293 { |
| 294 mac->SetDataRate (3); |
| 295 } |
| 296 else if (rxPower > *(gwSensitivity+3)) |
| 297 { |
| 298 mac->SetDataRate (2); |
| 299 } |
| 300 else if (rxPower > *(gwSensitivity+4)) |
| 301 { |
| 302 mac->SetDataRate (1); |
| 303 } |
| 304 else if (rxPower > *(gwSensitivity+5)) |
| 305 { |
| 306 mac->SetDataRate (0); |
| 307 } |
| 308 else // Device is out of range. Assign SF12. |
| 309 { |
| 310 mac->SetDataRate (0); |
| 311 } |
| 312 } |
| 313 } |
| 314 } |
OLD | NEW |