移动节点能量函数分析代码:
#include <stdarg.h>
#include <float.h>
#include "random.h"
#include "energy-model.h"
#include "mobilenode.h"
#include "god.h"
static class EnergyModelClass : public TclClass
{
public:
EnergyModelClass ():TclClass ("EnergyModel") {}
TclObject *create (int argc, const char *const *argv) {
if (argc == 8) {
MobileNode *n=(MobileNode*)TclObject::lookup(argv[4]);
return (new EnergyModel(n, atof(argv[5]),
atof(argv[6]), atof(argv[7])));
} else {
Tcl::instance().add_error("Wrong arguments to ErrorModel");
return 0;
}
}
} class_energy_model;
void EnergyModel::DecrTxEnergy(double txtime, double P_tx)
{
double dEng = P_tx * txtime;
if (energy_ <= dEng)
energy_ = 0.0;
else
energy_ = energy_ - dEng;
if (energy_ <= 0.0)
God::instance()->ComputeRoute();
}
void EnergyModel::DecrRcvEnergy(double rcvtime, double P_rcv)
{
double dEng = P_rcv * rcvtime;
if (energy_ <= dEng)
energy_ = 0.0;
else
energy_ = energy_ - dEng;
if (energy_ <= 0.0)
God::instance()->ComputeRoute();
}
void EnergyModel::DecrIdleEnergy(double idletime, double P_idle)
{
double dEng = P_idle * idletime;
if (energy_ <= dEng)
energy_ = 0.0;
else
energy_ = energy_ - dEng;
if (energy_ <= 0.0)
God::instance()->ComputeRoute();
}
// XXX Moved from node.cc. These wireless stuff should NOT stay in the
// base node.
void EnergyModel::start_powersaving()
{
snh_ = new SoftNeighborHandler(this);
snh_->start();
afe_ = new AdaptiveFidelityEntity(this);
afe_->start();
state_ = EnergyModel::POWERSAVING;
state_start_time_ = Scheduler::instance().clock();
}
void EnergyModel::set_node_sleep(int status)
{
Tcl& tcl=Tcl::instance();
//static float last_time_gosleep;
// status = 1 to set node into sleep mode
// status = 0 to put node back to idle mode.
// time in the sleep mode should be used as credit to idle
// time energy consumption
if (status) {
last_time_gosleep = Scheduler::instance().clock();
//printf("id=%d : put node into sleep at %f\n",
// address_,last_time_gosleep);
sleep_mode_ = status;
if (node_->exist_namchan())
tcl.evalf("%s add-mark m1 blue hexagon",node_->name());
} else {
sleep_mode_ = status;
if (node_->exist_namchan())
tcl.evalf("%s delete-mark m1", node_->name());
//printf("id= %d last_time_sleep = %f\n",
// address_, last_time_gosleep);
if (last_time_gosleep) {
total_sleeptime_ += Scheduler::instance().clock() -
last_time_gosleep;
last_time_gosleep = 0;
}
}
}
void EnergyModel::set_node_state(int state)
{
switch (state_) {
case POWERSAVING:
case WAITING:
state_ = state;
state_start_time_ = Scheduler::instance().clock();
break;
case INROUTE:
if (state == POWERSAVING) {
state_ = state;
} else if (state == INROUTE) {
// a data packet is forwarded, needs to reset
// state_start_time_
state_start_time_= Scheduler::instance().clock();
}
break;
default:
printf("Wrong state, quit...\n");
abort();
}
}
void EnergyModel::add_neighbor(u_int32_t nodeid)
{
neighbor_list_item *np;
np = neighbor_list.head;
for (; np; np = np->next) {
if (np->id == nodeid) {
np->ttl = maxttl_;
break;
}
}
if (!np) { // insert this new entry
np = new neighbor_list_item;
np->id = nodeid;
np->ttl = maxttl_;
np->next = neighbor_list.head;
neighbor_list.head = np;
neighbor_list.neighbor_cnt_++;
}
}
void EnergyModel::scan_neighbor()
{
neighbor_list_item *np, *lp;
if (neighbor_list.neighbor_cnt_ > 0) {
lp = neighbor_list.head;
np = lp->next;
for (; np; np = np->next) {
np->ttl--;
if (np->ttl <= 0){
lp->next = np->next;
delete np;
np = lp;
neighbor_list.neighbor_cnt_--;
}
lp = np;
}
// process the first element
np = neighbor_list.head;
np->ttl--;
if (np->ttl <= 0) {
neighbor_list.head = np->next;
delete np;
neighbor_list.neighbor_cnt_--;
}
}
}
void SoftNeighborHandler::start()
{
Scheduler::instance().schedule(this, &intr, CHECKFREQ);
}
void SoftNeighborHandler::handle(Event *)
{
Scheduler &s = Scheduler::instance();
nid_->scan_neighbor();
s.schedule(this, &intr, CHECKFREQ);
}
void AdaptiveFidelityEntity::start()
{
sleep_time_ = 2;
sleep_seed_ = 2;
idle_time_ = 10;
nid_->set_node_sleep(0);
Scheduler::instance().schedule(this, &intr,
Random::uniform(0, idle_time_));
}
void AdaptiveFidelityEntity::handle(Event *)
{
Scheduler &s = Scheduler::instance();
int node_state = nid_->state();
switch (node_state) {
case EnergyModel::POWERSAVING:
if (nid_->sleep()) {
// node is in sleep mode, wake it up
nid_->set_node_sleep(0);
adapt_it();
s.schedule(this, &intr, idle_time_);
} else {
// node is in idle mode, put it into sleep
nid_->set_node_sleep(1);
adapt_it();
s.schedule(this, &intr, sleep_time_);
}
break;
case EnergyModel::INROUTE:
// 100s is the maximum INROUTE time.
if (s.clock()-(nid_->state_start_time()) <
nid_->max_inroute_time()) {
s.schedule(this, &intr, idle_time_);
} else {
nid_->set_node_state(EnergyModel::POWERSAVING);
adapt_it();
nid_->set_node_sleep(1);
s.schedule(this, &intr, sleep_time_);
}
break;
case EnergyModel::WAITING:
// 10s is the maximum WAITING time
if (s.clock()-(nid_->state_start_time()) < MAX_WAITING_TIME) {
s.schedule(this, &intr, idle_time_);
} else {
nid_->set_node_state(EnergyModel::POWERSAVING);
adapt_it();
nid_->set_node_sleep(1);
s.schedule(this, &intr, sleep_time_);
}
break;
default:
fprintf(stderr, "Illegal Node State!");
abort();
}
}
void AdaptiveFidelityEntity::adapt_it()
{
float delay;
// use adaptive fidelity
if (nid_->adaptivefidelity()) {
int neighbors = nid_->getneighbors();
if (!neighbors)
neighbors = 1;
delay = sleep_seed_ * Random::uniform(1,neighbors);
set_sleeptime(delay);
}
}