📄 ns-leach.tcl
字号:
set chID [$self nodeID]
set currentCH_ $chID
pp "Cluster Head $currentCH_ broadcasting ADV at time [$ns_ now]"
set mac_dst $MAC_BROADCAST
set link_dst $LINK_BROADCAST
set msg [list $currentCH_]
set datasize [expr $BYTES_ID * [llength $msg]]
# Send beacons opt(max_dist) meters so all nodes can hear.
$self send $mac_dst $link_dst $ADV_CH $msg $datasize $opt(max_dist) $code_
}
Application/LEACH instproc findBestCluster {} {
global ns_ opt
$self instvar now_ dist_ myADVnum_
$self instvar clusterChoices_ clusterDist_ currentCH_
set nodeID [$self nodeID]
set min_dist 100000
if [$self isClusterHead?] {
# If node is CH, determine code and create a TDMA schedule.
set dist_ $opt(max_dist)
set currentCH_ $nodeID
set myADVnum_ [[$self mac] set myADVnum_]
# There are opt(spreading) - 1 codes available b/c need 1 code
# for communication with the base station.
set numCodesAvail [expr 2 * $opt(spreading) - 1]
set ClusterCode [expr int(fmod($myADVnum_, $numCodesAvail)) + 1]
$ns_ at [expr $now_ + $opt(ra_adv_total) + $opt(ra_join)] \
"$self createSchedule"
} else {
# If node is not a CH, find the CH which allows minimum transmit
# power for communication. Set the code and "distance" parameters
# accordingly.
if {$clusterChoices_ == ""} {
puts "$nodeID: Warning!!! No Cluster Head ADVs were heard!"
set currentCH_ $opt(nn)
$self SendMyDataToBS
return
}
foreach element $clusterChoices_ {
set chID [lindex $element 0]
set clustID [lindex $element 2]
set ind [lsearch $clusterChoices_ $element]
set d [lindex $clusterDist_ $ind]
if {$d < $min_dist} {
set min_dist $d
set currentCH_ $chID
set numCodesAvail [expr 2 * $opt(spreading) - 1]
set ClusterCode [expr int(fmod($ind, $numCodesAvail)) + 1]
}
}
set dist_ $min_dist
set random_access [$self getRandomNumber 0 \
[expr $opt(ra_join) - $opt(ra_delay)]]
$ns_ at [expr $now_ + $opt(ra_adv_total) + $random_access] \
"$self informClusterHead"
$self GoToSleep
}
$self setCode $ClusterCode
puts "$nodeID: Current cluster-head is $currentCH_, code is $ClusterCode, \
dist is $dist_"
set clusterChoices_ ""
set clusterDist_ ""
}
Application/LEACH instproc informClusterHead {} {
global ns_ opt JOIN_REQ MAC_BROADCAST BYTES_ID
$self instvar currentCH_ dist_ code_
set nodeID [$self nodeID]
set chID $currentCH_
pp "$nodeID: sending Join-REQ to $chID (dist = $dist_) at time [$ns_ now]"
set mac_dst $MAC_BROADCAST
set link_dst $chID
set msg [list $nodeID]
set spreading_factor $opt(spreading)
set datasize [expr $spreading_factor * $BYTES_ID * [llength $msg]]
$self WakeUp
# NOTE!!!! Join-Req message sent with enough power so all nodes in
# the network can hear the message. This avoids the hidden terminal
# problem.
$self send $mac_dst $link_dst $JOIN_REQ $msg $datasize $opt(max_dist) $code_
}
Application/LEACH instproc createSchedule {} {
global ns_ opt ADV_SCH MAC_BROADCAST BYTES_ID
$self instvar clusterNodes_ TDMAschedule_
$self instvar dist_ code_ now_ beginningE_
set numNodes [llength $clusterNodes_]
set chID [$self nodeID]
if {$numNodes == 0} {
set xmitOrder ""
puts "Warning! There are no nodes in this cluster ($chID)!"
$self SendMyDataToBS
} else {
# Set the TDMA schedule and send it to all nodes in the cluster.
set xmitOrder $clusterNodes_
set msg [list $xmitOrder]
set spreading_factor $opt(spreading)
set datasize [expr $spreading_factor * $BYTES_ID * [llength $xmitOrder]]
pp "$chID sending TDMA schedule: $xmitOrder at time [$ns_ now]"
pp "Packet size is $datasize."
set mac_dst $MAC_BROADCAST
set link_dst $chID
$self send $mac_dst $link_dst $ADV_SCH $msg $datasize $dist_ $code_
}
set TDMAschedule_ $xmitOrder
set outf [open $opt(dirname)/TDMAschedule.$now_.txt a]
puts $outf "$chID\t$TDMAschedule_"
close $outf
set outf [open $opt(dirname)/startup.energy a]
puts $outf "[$ns_ now]\t$chID\t[expr $beginningE_ - [[$self getER] query]] "
close $outf
}
############################################################################
#
# Receiving Functions
#
############################################################################
Application/LEACH instproc recv {args} {
global ADV_CH JOIN_REQ ADV_SCH DATA ns_
$self instvar currentCH_
set msg_type [[$self agent] set packetMsg_]
set chID [lindex $args 0]
set sender [lindex $args 1]
set data_size [lindex $args 2]
set msg [lrange $args 3 end]
set nodeID [$self nodeID]
if {$msg_type == $ADV_CH && ![$self isClusterHead?]} {
$self recvADV_CH $msg
} elseif {$msg_type == $JOIN_REQ && $nodeID == $chID} {
$self recvJOIN_REQ $msg
} elseif {$msg_type == $ADV_SCH && $chID == $currentCH_} {
$self recvADV_SCH $msg
} elseif {$msg_type == $DATA && $nodeID == $chID} {
$self recvDATA $msg
}
}
Application/LEACH instproc recvADV_CH {msg} {
global ns_
$self instvar clusterChoices_ clusterDist_
set chID [lindex $msg 0]
set nodeID [$self nodeID]
pp "$nodeID rcvd ADV_CH from $chID at [$ns_ now]"
set clusterChoices_ [lappend clusterChoices_ $msg]
set clusterDist_ [lappend clusterDist_ [[$self agent] set distEst_]]
}
Application/LEACH instproc recvJOIN_REQ {nodeID} {
global ns_
$self instvar clusterNodes_
set chID [$self nodeID]
pp "$chID received notice of node $nodeID at time [$ns_ now]"
set clusterNodes_ [lappend clusterNodes_ $nodeID]
}
Application/LEACH instproc recvADV_SCH {order} {
global ns_ opt
$self instvar xmitTime_ next_change_time_ now_
$self instvar beginningE_ frame_time_ end_frm_time_
set nodeID [$self nodeID]
set ind [lsearch [join $order] $nodeID]
set outf [open $opt(dirname)/startup.energy a]
puts $outf "[$ns_ now]\t$nodeID\t[expr $beginningE_ - [[$self getER] query]]"
close $outf
if {$ind < 0} {
puts "Warning!!!! $nodeID does not have a transmit time!"
puts "Must send data directly to BS."
set outf [open $opt(dirname)/TDMAschedule.$now_.txt a]
puts -nonewline $outf "$nodeID\t"
close $outf
$self SendMyDataToBS
return
}
# Determine time for a single TDMA frame. Each node sends data once
# per frame in the specified slot.
set frame_time_ [expr [expr 5 + [llength [join $order]]] * $opt(ss_slot_time)]
set xmitTime_ [expr $opt(ss_slot_time) * $ind]
set end_frm_time_ [expr $frame_time_ - $xmitTime_]
set xmitat [expr [$ns_ now] + $xmitTime_]
pp "$nodeID scheduled to transmit at $xmitat. It is now [$ns_ now]."
if {[expr $xmitat + $end_frm_time_] < \
[expr $next_change_time_ - 10 * $opt(ss_slot_time)]} {
$ns_ at $xmitat "$self sendData"
}
$self GoToSleep
}
Application/LEACH instproc recvDATA {msg} {
global ns_ opt
$self instvar TDMAschedule_ receivedFrom_ dataReceived_
set chID [$self nodeID]
set nodeID [lindex $msg 0]
pp "CH $chID received data ($msg) from $nodeID at [$ns_ now]"
set receivedFrom_ [lappend receivedFrom_ $nodeID]
set last_node [expr [llength $TDMAschedule_] - 1]
if {$chID == [lindex $TDMAschedule_ $last_node]} {
set last_node [expr $last_node - 1]
}
if {$nodeID == [lindex $TDMAschedule_ $last_node]} {
# After an entire frame of data has been received, the cluster-head
# must perform data aggregation functions and transmit the aggregate
# signal to the base station.
pp "CH $chID must now perform comp and xmit to BS."
set num_sigs [llength $TDMAschedule_]
set compute_energy [bf $opt(sig_size) $num_sigs]
pp "\tcompute_energy = $compute_energy"
[$self getER] remove $compute_energy
set receivedFrom_ [lappend receivedFrom_ $chID]
set dataReceived_ $receivedFrom_
set receivedFrom_ ""
$self SendDataToBS
}
}
############################################################################
#
# Sending Functions
#
############################################################################
Application/LEACH instproc sendData {} {
global ns_ opt DATA MAC_BROADCAST BYTES_ID
$self instvar next_change_time_ frame_time_ end_frm_time_
$self instvar currentCH_ dist_ code_ alive_
set nodeID [$self nodeID]
set msg [list [list $nodeID , [$ns_ now]]]
# Use DS-SS to send data messages to avoid inter-cluster interference.
set spreading_factor $opt(spreading)
set datasize [expr $spreading_factor * \
[expr [expr $BYTES_ID * [llength $msg]] + $opt(sig_size)]]
$self WakeUp
pp "$nodeID sending data $msg to $currentCH_ at [$ns_ now] (dist = $dist_)"
set mac_dst $MAC_BROADCAST
set link_dst $currentCH_
$self send $mac_dst $link_dst $DATA $msg $datasize $dist_ $code_
# Must transmit data again during slot in next TDMA frame.
set xmitat [expr [$ns_ now] + $frame_time_]
if {$alive_ && [expr $xmitat + $end_frm_time_] < \
[expr $next_change_time_ - 10 * $opt(ss_slot_time)]} {
$ns_ at $xmitat "$self sendData"
}
set sense_energy [expr $opt(Esense) * $opt(sig_size) * 8]
pp "Node $nodeID removing sensing energy = $sense_energy J."
[$self getER] remove $sense_energy
if {$currentCH_ != $nodeID} {
$self GoToSleep
}
}
Application/LEACH instproc send {mac_dst link_dst type msg
data_size dist code} {
global ns_
$self instvar rng_
#set random_delay [expr 0.005 + [$rng_ uniform 0 0.005]]
#$ns_ at [expr [$ns_ now] + $random_delay] "$self send_now $mac_dst \
# $link_dst $type $msg $data_size $dist"
$ns_ at [$ns_ now] "$self send_now $mac_dst \
$link_dst $type $msg $data_size $dist $code"
}
Application/LEACH instproc send_now {mac_dst link_dst type msg \
data_size dist code} {
[$self agent] set packetMsg_ $type
[$self agent] set dst_addr $mac_dst
[$self agent] sendmsg $data_size $msg $mac_dst $link_dst $dist $code
}
Application/LEACH instproc SendDataToBS {} {
global ns_ opt bs MAC_BROADCAST DATA BYTES_ID
$self instvar code_ rng_ now_
# Data must be sent directly to the basestation.
set nodeID [$self nodeID]
set msg [list [list [list $nodeID , [$ns_ now]]]]
# Use DS-SS to send data messages to avoid inter-cluster interference.
set spreading_factor $opt(spreading)
set datasize [expr $spreading_factor * \
[expr $BYTES_ID * [llength $msg] + $opt(sig_size)]]
set dist [nodeToBSDist [$self node] $bs]
set mac_dst $MAC_BROADCAST
set link_dst $opt(bsID)
set random_delay [expr [$ns_ now] + [$rng_ uniform 0 0.01]]
pp "Node $nodeID sending $msg to BS at time $random_delay"
$ns_ at $random_delay "$self send $mac_dst $link_dst $DATA \
$msg $datasize $dist $opt(bsCode)"
}
Application/LEACH instproc SendMyDataToBS {} {
global ns_ opt
$self instvar next_change_time_ alive_
puts "Data being sent to the Base Station"
$self SendDataToBS
puts "Data was sent to the base station"
set xmitat [expr [$ns_ now] + $opt(frame_time)]
if {$alive_ && [expr $xmitat + $opt(frame_time)] < \
[expr $next_change_time_ - $opt(frame_time)]} {
$ns_ at $xmitat "$self SendMyDataToBS"
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -