1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Wireless Communications and Networking Group (WCNG),
4  * University of Rochester, Rochester, NY, USA.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Author: Cristiano Tapparello <cristiano.tapparello@rochester.edu>
20  */
21 
22 /**
23  *
24  * This example extends the energy model example by connecting a basic energy
25  * harvester to the nodes.
26  *
27  * The example considers a simple communication link between a source and a
28  * destination node, where the source node sends a packet to the destination
29  * every 1 second. Each node is powered by a BasicEnergySource, which is recharged
30  * by a BasicEnergyHarvester, and the WiFi radio consumes energy for the transmission/
31  * reception of the packets.
32  *
33  * For the receiver node, the example prints the energy consumption of the WiFi radio,
34  * the power harvested by the energy harvester and the residual energy in the
35  * energy source.
36  *
37  * The nodes initial energy is set to 1.0 J, the transmission and reception entail a
38  * current consumption of 0.0174 A and 0.0197 A, respectively (default values in
39  * WifiRadioEnergyModel). The energy harvester provides an amount of power that varies
40  * according to a random variable uniformly distributed in [0 0.1] W, and is updated
41  * every 1 s. The energy source voltage is 3 V (default value in BasicEnergySource) and
42  * the residual energy level is updated every 1 second (default value).
43  *
44  * The simulation start at time 0 and it is hard stopped at time 10 seconds. Given the
45  * packet size and the distance between the nodes, each transmission lasts 0.0023s.
46  * As a result, the destination node receives 10 messages.
47  *
48  */
49 
50 #include <iostream>
51 #include <fstream>
52 #include <vector>
53 #include <string>
54 #include "ns3/core-module.h"
55 #include "ns3/network-module.h"
56 #include "ns3/mobility-module.h"
57 #include "ns3/config-store-module.h"
58 #include "ns3/energy-module.h"
59 #include "ns3/internet-module.h"
60 #include "ns3/yans-wifi-helper.h"
61 #include "ns3/wifi-radio-energy-model-helper.h"
62 
63 using namespace ns3;
64 
65 NS_LOG_COMPONENT_DEFINE ("EnergyWithHarvestingExample");
66 
67 static inline std::string
PrintReceivedPacket(Address & from)68 PrintReceivedPacket (Address& from)
69 {
70   InetSocketAddress iaddr = InetSocketAddress::ConvertFrom (from);
71 
72   std::ostringstream oss;
73   oss << "--\nReceived one packet! Socket: " << iaddr.GetIpv4 ()
74       << " port: " << iaddr.GetPort ()
75       << " at time = " << Simulator::Now ().GetSeconds ()
76       << "\n--";
77 
78   return oss.str ();
79 }
80 
81 /**
82  * \param socket Pointer to socket.
83  *
84  * Packet receiving sink.
85  */
86 void
ReceivePacket(Ptr<Socket> socket)87 ReceivePacket (Ptr<Socket> socket)
88 {
89   Ptr<Packet> packet;
90   Address from;
91   while ((packet = socket->RecvFrom (from)))
92     {
93       if (packet->GetSize () > 0)
94         {
95           NS_LOG_UNCOND (PrintReceivedPacket (from));
96         }
97     }
98 }
99 
100 /**
101  * \param socket Pointer to socket.
102  * \param pktSize Packet size.
103  * \param n Pointer to node.
104  * \param pktCount Number of packets to generate.
105  * \param pktInterval Packet sending interval.
106  *
107  * Traffic generator.
108  */
109 static void
GenerateTraffic(Ptr<Socket> socket,uint32_t pktSize,Ptr<Node> n,uint32_t pktCount,Time pktInterval)110 GenerateTraffic (Ptr<Socket> socket, uint32_t pktSize, Ptr<Node> n,
111                  uint32_t pktCount, Time pktInterval)
112 {
113   if (pktCount > 0)
114     {
115       socket->Send (Create<Packet> (pktSize));
116       Simulator::Schedule (pktInterval, &GenerateTraffic, socket, pktSize, n,
117                            pktCount - 1, pktInterval);
118     }
119   else
120     {
121       socket->Close ();
122     }
123 }
124 
125 /// Trace function for remaining energy at node.
126 void
RemainingEnergy(double oldValue,double remainingEnergy)127 RemainingEnergy (double oldValue, double remainingEnergy)
128 {
129   NS_LOG_UNCOND (Simulator::Now ().GetSeconds ()
130                  << "s Current remaining energy = " << remainingEnergy << "J");
131 }
132 
133 /// Trace function for total energy consumption at node.
134 void
TotalEnergy(double oldValue,double totalEnergy)135 TotalEnergy (double oldValue, double totalEnergy)
136 {
137   NS_LOG_UNCOND (Simulator::Now ().GetSeconds ()
138                  << "s Total energy consumed by radio = " << totalEnergy << "J");
139 }
140 
141 /// Trace function for the power harvested by the energy harvester.
142 void
HarvestedPower(double oldValue,double harvestedPower)143 HarvestedPower (double oldValue, double harvestedPower)
144 {
145   NS_LOG_UNCOND (Simulator::Now ().GetSeconds ()
146                  << "s Current harvested power = " << harvestedPower << " W");
147 }
148 
149 /// Trace function for the total energy harvested by the node.
150 void
TotalEnergyHarvested(double oldValue,double TotalEnergyHarvested)151 TotalEnergyHarvested (double oldValue, double TotalEnergyHarvested)
152 {
153   NS_LOG_UNCOND (Simulator::Now ().GetSeconds ()
154                  << "s Total energy harvested by harvester = "
155                  << TotalEnergyHarvested << " J");
156 }
157 
158 
159 int
main(int argc,char * argv[])160 main (int argc, char *argv[])
161 {
162   std::string phyMode ("DsssRate1Mbps");
163   double Prss = -80;            // dBm
164   uint32_t PacketSize = 200;   // bytes
165   bool verbose = false;
166 
167   // simulation parameters
168   uint32_t numPackets = 10000;  // number of packets to send
169   double interval = 1;          // seconds
170   double startTime = 0.0;       // seconds
171   double distanceToRx = 100.0;  // meters
172 
173   // Energy Harvester variables
174   double harvestingUpdateInterval = 1;  // seconds
175 
176   CommandLine cmd (__FILE__);
177   cmd.AddValue ("phyMode", "Wifi Phy mode", phyMode);
178   cmd.AddValue ("Prss", "Intended primary RSS (dBm)", Prss);
179   cmd.AddValue ("PacketSize", "size of application packet sent", PacketSize);
180   cmd.AddValue ("numPackets", "Total number of packets to send", numPackets);
181   cmd.AddValue ("startTime", "Simulation start time", startTime);
182   cmd.AddValue ("distanceToRx", "X-Axis distance between nodes", distanceToRx);
183   cmd.AddValue ("verbose", "Turn on all device log components", verbose);
184   cmd.Parse (argc, argv);
185 
186   // Convert to time object
187   Time interPacketInterval = Seconds (interval);
188 
189   // disable fragmentation for frames below 2200 bytes
190   Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold",
191                       StringValue ("2200"));
192   // turn off RTS/CTS for frames below 2200 bytes
193   Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold",
194                       StringValue ("2200"));
195   // Fix non-unicast data rate to be the same as that of unicast
196   Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode",
197                       StringValue (phyMode));
198 
199   NodeContainer c;
200   c.Create (2);     // create 2 nodes
201   NodeContainer networkNodes;
202   networkNodes.Add (c.Get (0));
203   networkNodes.Add (c.Get (1));
204 
205   // The below set of helpers will help us to put together the wifi NICs we want
206   WifiHelper wifi;
207   if (verbose)
208     {
209       wifi.EnableLogComponents ();
210     }
211   wifi.SetStandard (WIFI_STANDARD_80211b);
212 
213   /** Wifi PHY **/
214   /***************************************************************************/
215   YansWifiPhyHelper wifiPhy;
216 
217   /** wifi channel **/
218   YansWifiChannelHelper wifiChannel;
219   wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
220   wifiChannel.AddPropagationLoss ("ns3::FriisPropagationLossModel");
221 
222   // create wifi channel
223   Ptr<YansWifiChannel> wifiChannelPtr = wifiChannel.Create ();
224   wifiPhy.SetChannel (wifiChannelPtr);
225 
226   /** MAC layer **/
227   // Add a MAC and disable rate control
228   WifiMacHelper wifiMac;
229   wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode",
230                                 StringValue (phyMode), "ControlMode",
231                                 StringValue (phyMode));
232   // Set it to ad-hoc mode
233   wifiMac.SetType ("ns3::AdhocWifiMac");
234 
235   /** install PHY + MAC **/
236   NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, networkNodes);
237 
238   /** mobility **/
239   MobilityHelper mobility;
240   Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
241   positionAlloc->Add (Vector (0.0, 0.0, 0.0));
242   positionAlloc->Add (Vector (2 * distanceToRx, 0.0, 0.0));
243   mobility.SetPositionAllocator (positionAlloc);
244   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
245   mobility.Install (c);
246 
247   /** Energy Model **/
248   /***************************************************************************/
249   /* energy source */
250   BasicEnergySourceHelper basicSourceHelper;
251   // configure energy source
252   basicSourceHelper.Set ("BasicEnergySourceInitialEnergyJ", DoubleValue (1.0));
253   // install source
254   EnergySourceContainer sources = basicSourceHelper.Install (c);
255   /* device energy model */
256   WifiRadioEnergyModelHelper radioEnergyHelper;
257   // configure radio energy model
258   radioEnergyHelper.Set ("TxCurrentA", DoubleValue (0.0174));
259   radioEnergyHelper.Set ("RxCurrentA", DoubleValue (0.0197));
260   // install device model
261   DeviceEnergyModelContainer deviceModels = radioEnergyHelper.Install (devices, sources);
262 
263   /* energy harvester */
264   BasicEnergyHarvesterHelper basicHarvesterHelper;
265   // configure energy harvester
266   basicHarvesterHelper.Set ("PeriodicHarvestedPowerUpdateInterval", TimeValue (Seconds (harvestingUpdateInterval)));
267   basicHarvesterHelper.Set ("HarvestablePower", StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=0.1]"));
268   // install harvester on all energy sources
269   EnergyHarvesterContainer harvesters = basicHarvesterHelper.Install (sources);
270   /***************************************************************************/
271 
272   /** Internet stack **/
273   InternetStackHelper internet;
274   internet.Install (networkNodes);
275 
276   Ipv4AddressHelper ipv4;
277   NS_LOG_INFO ("Assign IP Addresses.");
278   ipv4.SetBase ("10.1.1.0", "255.255.255.0");
279   Ipv4InterfaceContainer i = ipv4.Assign (devices);
280 
281   TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
282   Ptr<Socket> recvSink = Socket::CreateSocket (networkNodes.Get (1), tid);  // node 1, Destination
283   InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80);
284   recvSink->Bind (local);
285   recvSink->SetRecvCallback (MakeCallback (&ReceivePacket));
286 
287   Ptr<Socket> source = Socket::CreateSocket (networkNodes.Get (0), tid);    // node 0, Source
288   InetSocketAddress remote = InetSocketAddress (Ipv4Address::GetBroadcast (), 80);
289   source->SetAllowBroadcast (true);
290   source->Connect (remote);
291 
292   /** connect trace sources **/
293   /***************************************************************************/
294   // all traces are connected to node 1 (Destination)
295   // energy source
296   Ptr<BasicEnergySource> basicSourcePtr = DynamicCast<BasicEnergySource> (sources.Get (1));
297   basicSourcePtr->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback (&RemainingEnergy));
298   // device energy model
299   Ptr<DeviceEnergyModel> basicRadioModelPtr =
300     basicSourcePtr->FindDeviceEnergyModels ("ns3::WifiRadioEnergyModel").Get (0);
301   NS_ASSERT (basicRadioModelPtr != 0);
302   basicRadioModelPtr->TraceConnectWithoutContext ("TotalEnergyConsumption", MakeCallback (&TotalEnergy));
303   // energy harvester
304   Ptr<BasicEnergyHarvester> basicHarvesterPtr = DynamicCast<BasicEnergyHarvester> (harvesters.Get (1));
305   basicHarvesterPtr->TraceConnectWithoutContext ("HarvestedPower", MakeCallback (&HarvestedPower));
306   basicHarvesterPtr->TraceConnectWithoutContext ("TotalEnergyHarvested", MakeCallback (&TotalEnergyHarvested));
307   /***************************************************************************/
308 
309 
310   /** simulation setup **/
311   // start traffic
312   Simulator::Schedule (Seconds (startTime), &GenerateTraffic, source, PacketSize,
313                        networkNodes.Get (0), numPackets, interPacketInterval);
314 
315   Simulator::Stop (Seconds (10.0));
316   Simulator::Run ();
317 
318   for (DeviceEnergyModelContainer::Iterator iter = deviceModels.Begin (); iter != deviceModels.End (); iter ++)
319     {
320       double energyConsumed = (*iter)->GetTotalEnergyConsumption ();
321       NS_LOG_UNCOND ("End of simulation (" << Simulator::Now ().GetSeconds ()
322                      << "s) Total energy consumed by radio = " << energyConsumed << "J");
323       NS_ASSERT (energyConsumed <= 1.0);
324     }
325 
326   Simulator::Destroy ();
327 
328   return 0;
329 }
330