📄 ns-leach.tcl
字号:
############################################################################
#
# This code was developed as part of the MIT uAMPS project. (June, 2000)
#
############################################################################
# Message Constants
set ADV_CH 0
set JOIN_REQ 1
set ADV_SCH 2
set DATA 3
set MAC_BROADCAST 0xffffffff
set LINK_BROADCAST 0xffffffff
set BYTES_ID 2
############################################################################
#
# LEACH Application
#
############################################################################
Class Application/LEACH -superclass Application
Application/LEACH instproc init args {
global opt
$self instvar rng_ isch_ hasbeench_ next_change_time_ round_
$self instvar clusterChoices_ clusterDist_ clusterNodes_ currentCH_
$self instvar xmitTime_ TDMAschedule_ dist_ code_
$self instvar now_ alive_ frame_time_ end_frm_time_
$self instvar begin_idle_ begin_sleep_
$self instvar myADVnum_ receivedFrom_ dataReceived_
set rng_ [new RNG]
$rng_ seed 0
set isch_ 0
set hasbeench_ 0
set next_change_time_ 0
set round_ 0
set clusterChoices_ ""
set clusterDist_ ""
set clusterNodes_ ""
set currentCH_ ""
set xmitTime_ ""
set TDMAschedule_ ""
set dist_ 0
set code_ 0
set now_ 0
set alive_ 1
set frame_time_ $opt(frame_time)
set end_frm_time_ 0
set begin_idle_ 0
set begin_sleep_ 0
set myADVnum_ 0
set receivedFrom_ ""
set dataReceived_ ""
$self next $args
}
Application/LEACH instproc start {} {
[$self mac] set node_num_ [$self nodeID]
$self decideClusterHead
$self checkAlive
}
############################################################################
#
# Helper Functions
#
############################################################################
Application/LEACH instproc getRandomNumber {llim ulim} {
$self instvar rng_
return [$rng_ uniform $llim $ulim]
}
Application/LEACH instproc node {} {
return [[$self agent] set node_]
}
Application/LEACH instproc nodeID {} {
return [[$self node] id]
}
Application/LEACH instproc mac {} {
return [[$self node] set mac_(0)]
}
Application/LEACH instproc getX {} {
return [[$self node] set X_]
}
Application/LEACH instproc getY {} {
return [[$self node] set Y_]
}
Application/LEACH instproc getER {} {
set er [[$self node] getER]
return $er
}
Application/LEACH instproc GoToSleep {} {
global opt ns_
$self instvar begin_idle_ begin_sleep_
[[$self node] set netif_(0)] set sleep_ 1
# If node has been awake, remove idle energy (e.g., the amount of energy
# dissipated while the node is in the idle state). Otherwise, the node
# has been asleep and must remove sleep energy (e.g., the amount of
# energy dissipated while the node is in the sleep state).
if {$begin_idle_ > $begin_sleep_} {
set idle_energy [expr $opt(Pidle) * [expr [$ns_ now] - $begin_idle_]]
[$self getER] remove $idle_energy
} else {
set sleep_energy [expr $opt(Psleep) * [expr [$ns_ now] - $begin_sleep_]]
[$self getER] remove $sleep_energy
}
set begin_sleep_ [$ns_ now]
set begin_idle_ 0
}
Application/LEACH instproc WakeUp {} {
global opt ns_
$self instvar begin_idle_ begin_sleep_
[[$self node] set netif_(0)] set sleep_ 0
# If node has been asleep, remove sleep energy (e.g., the amount of energy
# dissipated while the node is in the sleep state). Otherwise, the node
# has been idling and must remove idle energy (e.g., the amount of
# energy dissipated while the node is in the idle state).
if {$begin_sleep_ > $begin_idle_} {
set sleep_energy [expr $opt(Psleep) * [expr [$ns_ now] - $begin_sleep_]]
[$self getER] remove $sleep_energy
} else {
set idle_energy [expr $opt(Pidle) * [expr [$ns_ now] - $begin_idle_]]
[$self getER] remove $idle_energy
}
set begin_idle_ [$ns_ now]
set begin_sleep_ 0
}
Application/LEACH instproc setCode code {
$self instvar code_
set code_ $code
[$self mac] set code_ $code
}
Application/LEACH instproc checkAlive {} {
global ns_ chan opt node_
$self instvar alive_ TDMAschedule_
$self instvar begin_idle_ begin_sleep_
# Check the alive status of the node. If the node has run out of
# energy, it no longer functions in the network.
set ISalive [[[$self node] set netif_(0)] set alive_]
if {$alive_ == 1} {
if {$ISalive == 0} {
puts "Node [$self nodeID] is DEAD!!!!"
$chan removeif [[$self node] set netif_(0)]
set alive_ 0
set opt(nn_) [expr $opt(nn_) - 1]
if {$opt(rcapp) == "LEACH-C/StatClustering" && \
[$self isClusterHead?]} {
foreach element $TDMAschedule_ {
if {$element != [$self nodeID]} {
puts "Node $element is effectively DEAD!!!!"
$chan removeif [$node_($element) set netif_(0)]
[$node_($element) set netif_(0)] set alive_ 0
[$node_($element) set rca_app_] set alive_ 0
set opt(nn_) [expr $opt(nn_) - 1]
}
}
}
$self GoToSleep
} else {
$ns_ at [expr [$ns_ now] + 0.1] "$self checkAlive"
if {$begin_idle_ >= $begin_sleep_} {
set idle_energy [expr $opt(Pidle) * [expr [$ns_ now] - $begin_idle_]]
[$self getER] remove $idle_energy
set begin_idle_ [$ns_ now]
} else {
set sleep_energy [expr $opt(Psleep) * [expr [$ns_ now] - $begin_sleep_]]
[$self getER] remove $sleep_energy
set begin_sleep_ [$ns_ now]
}
}
}
if {$opt(nn_) < $opt(num_clusters)} "sens_finish"
}
############################################################################
#
# Cluster Head Functions
#
############################################################################
Application/LEACH instproc isClusterHead? {} {
$self instvar isch_
return $isch_
}
Application/LEACH instproc hasbeenClusterHead? {} {
$self instvar hasbeench_
return $hasbeench_
}
Application/LEACH instproc hasnotbeenClusterHead {} {
$self instvar hasbeench_
set hasbeench_ 0
}
Application/LEACH instproc setClusterHead {} {
$self instvar isch_ hasbeench_
set isch_ 1
set hasbeench_ 1
return
}
Application/LEACH instproc unsetClusterHead {} {
$self instvar isch_
set isch_ 0
return
}
############################################################################
#
# Distributed Cluster Set-up Functions
#
############################################################################
Application/LEACH instproc decideClusterHead {} {
global chan ns_ opt node_
$self instvar next_change_time_ round_ clusterNodes_
$self instvar now_ TDMAschedule_ beginningE_ alive_
$self instvar myADVnum_ CHheard_
set CHheard_ 0
[$self mac] set CHheard_ $CHheard_
set myADVnum_ 0
[$self mac] set myADVnum_ $myADVnum_
# Check the alive status of the node. If the node has run out of
# energy, it no longer functions in the network.
set ISalive [[[$self node] set netif_(0)] set alive_]
if {$alive_ == 1 && $ISalive == 0} {
puts "Node [$self nodeID] is DEAD!!!! Energy = [[$self getER] query]"
$chan removeif [[$self node] set netif_(0)]
set alive_ 0
set opt(nn_) [expr $opt(nn_) - 1]
}
if {$alive_ == 0} {return}
set now_ [$ns_ now]
set nodeID [$self nodeID]
set beginningE_ [[$self getER] query]
$self setCode 0
$self WakeUp
set tot_rounds [expr int([expr $opt(nn_) / $opt(num_clusters)])]
if {$round_ >= $tot_rounds} {
set round_ 0
}
if {$opt(eq_energy) == 1} {
#
# Pi(t) = k / (N - k mod(r,N/k))
# where k is the expected number of clusters per round
# N is the total number of sensor nodes in the network
# and r is the number of rounds that have already passed.
#
set nn $opt(nn_)
set Etotal 0
for {set id 0} {$id < [expr $opt(nn)-1]} {incr id} {
set app [$node_($id) set rca_app_]
set E [[$app getER] query]
set Etotal [expr $Etotal + $E]
}
set aveE [expr $Etotal / $opt(nn)]
set E [[$self getER] query]
if {[expr $nn - $opt(num_clusters) * $round_] < 1} {
set thresh 1
} else {
set thresh [expr double($opt(num_clusters)) / \
[expr $nn - $opt(num_clusters) * $round_]]
# Whenever round_ is 0, all nodes are eligible to be cluster-head.
if {$round_ == 0} {
$self hasnotbeenClusterHead
}
}
# If node has been cluster-head in this group of rounds, it will not
# act as a cluster-head for this round.
if {[$self hasbeenClusterHead?]} {
set thresh 0
}
} else {
#
# Pi(t) = Ei(t) / Etotal(t) * k
# where k is the expected number of clusters per round,
# Ei(t) is the node's current energy, and Etotal(t) is the total
# energy from all nodes in the network.
#
set Etotal 0
# Note! In a real network, would need a routing protocol to get this
# information. Alternatively, each node could estimate Etotal(t) from
# the energy of nodes in its cluster.
for {set id 0} {$id < [expr $opt(nn)-1]} {incr id} {
set app [$node_($id) set rca_app_]
set E [[$app getER] query]
set Etotal [expr $Etotal + $E]
}
set E [[$self getER] query]
set thresh [expr double([expr $E * $opt(num_clusters)]) / $Etotal]
}
puts "THRESH = $thresh"
set clusterNodes_ ""
set TDMAschedule_ ""
if {[$self getRandomNumber 0 1] < $thresh && $E >= $aveE} {
puts "$nodeID: *******************************************"
puts "$nodeID: Is a cluster head at time [$ns_ now]"
$self setClusterHead
set random_access [$self getRandomNumber 0 $opt(ra_adv)]
$ns_ at [expr $now_ + $random_access] "$self advertiseClusterHead"
} else {
puts "$nodeID: *******************************************"
$self unsetClusterHead
}
incr round_
set next_change_time_ [expr $now_ + $opt(ch_change)]
$ns_ at $next_change_time_ "$self decideClusterHead"
$ns_ at [expr $now_ + $opt(ra_adv_total)] "$self findBestCluster"
}
Application/LEACH instproc advertiseClusterHead {} {
global ns_ opt ADV_CH MAC_BROADCAST LINK_BROADCAST BYTES_ID
$self instvar currentCH_ code_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -