diff options
| author | Loic Guegan <manzerbredes@mailbox.org> | 2022-06-14 17:13:46 +0200 |
|---|---|---|
| committer | Loic Guegan <manzerbredes@mailbox.org> | 2022-06-14 17:13:46 +0200 |
| commit | 7f13c95e16a802d0706e9f5a6d5d845d7fd67631 (patch) | |
| tree | 65cb3c0faec397cb1b06894645d060514f6b242d /plugins | |
| parent | b6877cb81e56c3991d0dbcf9fa579f627a4c2a29 (diff) | |
Major refactoring:
- Create pip package
- Reorganized source code
Diffstat (limited to 'plugins')
| -rw-r--r-- | plugins/__init__.py | 1 | ||||
| -rw-r--r-- | plugins/node_plugin.py | 29 | ||||
| -rw-r--r-- | plugins/operating_states.py | 66 | ||||
| -rw-r--r-- | plugins/power_states.py | 164 | ||||
| -rw-r--r-- | plugins/wireless_area.py | 72 |
5 files changed, 0 insertions, 332 deletions
diff --git a/plugins/__init__.py b/plugins/__init__.py deleted file mode 100644 index abb734a..0000000 --- a/plugins/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__all__ = [ "node_plugin", "power_states" ] diff --git a/plugins/node_plugin.py b/plugins/node_plugin.py deleted file mode 100644 index 325ff8a..0000000 --- a/plugins/node_plugin.py +++ /dev/null @@ -1,29 +0,0 @@ -class NodePlugin: - """ - Node plugins get register to the node API get notified when events occurs. - The call and return suffixes are used for methods that are called at the beginning - and the end, respectively, of API calls triggered by the node source code. - - Changing this API could brake most of the node plugins. - """ - - def __init__(self,plugin_name,api): - self.api=api - self.plugin_name=plugin_name - api.plugin_register(self) - - def on_send_call(self,interface,data,datasize,dst): - pass - - def on_send_return(self,interface,data,datasize,dst,code): - pass - - def on_receive_return(self,interface,data,start_at,end_at): - pass - - def on_terminated(self): - pass - - def log(self,msg): - self.api.log(self.plugin_name+"(NP) "+msg) - diff --git a/plugins/operating_states.py b/plugins/operating_states.py deleted file mode 100644 index 400aa1b..0000000 --- a/plugins/operating_states.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python - -from plugins.node_plugin import * - -###################### -# _ ____ ___ # -# / \ | _ \_ _| # -# / _ \ | |_) | | # -# / ___ \| __/| | # -# /_/ \_\_| |___| # -# # -###################### - -# import plugins.operating_states as op -# # Load the directional transition graph from graph.txt starting at the "vertex1" state -# opstate=op.OperatingStates(api,"graph.txt","vertex1") -# Format of the graph.txt file consists in one edge per line -# that consists on the source vertex and destination vertex sperated by a space -# As an example: -# vertex1 vertex2 -# vertex1 vertex3 -# vertex3 vertex2 -# vertex2 vertex1 -# -# opstate.register_callback(boom) -# # On each state transition boom will be called as boom(src_state,dst_state) -# # This way the boom callback can contains power_state transitions for examples -# opstate.goto("vertex2") # works -# opstate.goto("vertex3") # wont work -# opstate.goto("vertex1") # work since we are on vertex2 - -class OperatingStates(NodePlugin): - """ - OperatingStates plugin - """ - def __init__(self,api, state_file, initial_state): - self.transitions=list() - self.callbacks=list() - self.state=initial_state - with open(state_file) as fp: - for i, line in enumerate(fp): - self.transitions.append(line) - super().__init__("OperatingStates",api) - - def goto(self,state): - if (self.state+" "+state) in self.transitions: - old_state=self.state - self.state=state - for c in self.callbacks: - c(old_state,state) - else: - self.log("Invalid transition "+self.state+" => "+state) - - def get_state(self): - return(self.state) - - def register_callback(self,callback): - """ - The callback will be called on each state transition - Callback takes two arguments which are: - - The source state - - The destination state - """ - self.callbacks.append(callback) - - diff --git a/plugins/power_states.py b/plugins/power_states.py deleted file mode 100644 index be3d085..0000000 --- a/plugins/power_states.py +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env python - -from plugins.node_plugin import * - -# PowerStates allows you to measure the energy consumption of a -# node that go through several power states during the simulation -# Two version of Powerstates is provided by mean of two classes: -# - Powerstates: Allow you to set power to any user's defined values -# - PowerstatesFromFile: Allow you to set power from states defined in a file - -###################### -# _ ____ ___ # -# / \ | _ \_ _| # -# / _ \ | |_) | | # -# / ___ \| __/| | # -# /_/ \_\_| |___| # -# # -###################### - -# #Regarding PowerStates: -# import Powerstates as ps -# pstates=ps.PowerStates(<node>,<power_init>) -# pstates.set_power(<power>) # Switch the power consumption to <power> -# pstates.report_energy() # Display the current node energy consumption up to the current simulated time -# pstates.report_power_changes() # Display all the power changes up to the current simulated time - -# #Regarding PowerStatesFromFile: -# #Format of <file> is one <entry> per line that follow this format <state-0>:<state-1>:...:<state-n> -# #Each line can corresponds to one node -# import Powerstates as ps -# pstates=ps.PowerStatesFromFile(<node>,<file>,<entry-line>) # Create a power states on node <node> using line <entry-line> of file <file> -# pstates.set_state(<id>) # Switch to the <id> power states -# pstates.report_energy() # Display the current node energy consumption up to the current simulated time -# pstates.report_power_changes() # Display all the power changes up to the current simulated time -# pstates.report_state_changes() # Display all the states changes up to the current simulated time - - -class PowerStates(NodePlugin): - """ - PowerStates model the energy consumed by the various changes of power consumption of a node over time. - """ - def __init__(self,node,power_init): - self.node=node - self.clock=self.node.read("clock") - self.energy=0 - self.power=power_init - self.power_changes=dict() - self.set_power(power_init) - super().__init__("Powerstates",api) - - - def set_power(self,power_watt): - cur_clock=self.node.read("clock") - self.energy+=self.power*(cur_clock-self.clock) - self.clock=cur_clock - if self.power != power_watt: - self.power_changes[cur_clock]=power_watt - self.power=power_watt - return cur_clock - - def report_energy(self): - self.set_power(self.power) - self.node.log("[PowerStates Plugin] Consumed "+str(self.energy) +"J") - - def report_power_changes(self): - self.set_power(self.power) - for key in self.power_changes.keys(): - self.node.log("[PowerStates Plugin] At t="+str(key)+" power is "+str(self.power_changes[key])+"W") - - - -class PowerStatesFromFile(PowerStates): - """ - A version of Powerstates that load the power values from a file. - """ - def __init__(self,node,state_file,entry_line=1): - self.node=node - self.state_changes=dict() - self.states=[] - self.state=0 - with open(state_file) as fp: - for i, line in enumerate(fp): - if i+1 == entry_line: - self.states=line.split(":") - self.states=[float(i) for i in self.states] - assert len(self.states) > 0 - super().__init__(node,self.states[0]) - self.set_state(0) - - def set_state(self,state_id): - assert state_id < len(self.states) - clock=super().set_power(self.states[state_id]) - if self.state != state_id: - self.state_changes[clock]=state_id - self.state=state_id - - - def report_state_changes(self): - self.set_state(self.state) - for key in self.state_changes.keys(): - self.node.log("[PowerStates Plugin] At t="+str(key)+" state is "+str(self.state_changes[key])) - - -class PowerStatesComms(NodePlugin): - """ - Monitor the energy consumed by the network interfaces by mean of power states. - Note that for finer grained predictions, bytes and packet power consumption must be accounted. - Which is not the case with these power states. - """ - - def __init__(self,api): - super().__init__("PowerStatesComms",api) - self.energy_dynamic=0.0 # Store the dynamic part of the energy consumption - self.power=dict() # Store the power states - self.tx_clock=0 # Dynamic clock (store the time at which a the last tx starts - self.idle_clock=api.read("clock") # Store the start time (to compute the idle part of the energy consumption) - - def on_receive_return(self,interface,data,start_at,end_at): - duration=float(end_at)-float(start_at) - self.energy_dynamic+=self.power[interface]["rx"]*duration - - def on_send_call(self,interface,data,datasize,dst): - self.tx_clock=self.api.read("clock") - - def on_send_return(self,interface,data,datasize,dst,code): - clock=self.api.read("clock") - duration=(clock-float(self.tx_clock)) - self.energy_dynamic+=self.power[interface]["tx"]*duration - self.tx_clock=clock # Any value could be use here - - def set_power(self,interface,idle,tx,rx): - self.power[interface]=dict() - self.power[interface]["idle"]=idle - self.power[interface]["rx"]=rx - self.power[interface]["tx"]=tx - - def get_idle(self): - clock=self.api.read("clock") - idle=0 - for interface in self.power.keys(): - idle+=(clock-self.idle_clock)*self.power[interface]["idle"] - return idle - - def get_receive_queue_energy(self,interface): - """ - Not that call to on_receive_return may not have happened yet (or never). - Thus we should manually compute the energy consumption stored in each queues of the node. - """ - energy=0 - # For each interface we should check if there is received data that has not been consumed - for data in list(self.api["interfaces"][interface].queue): - start_at=float(data[1]) - end_at=float(data[2]) - energy+=(end_at-start_at)*self.power[interface]["rx"] - return energy - - def get_energy(self): - queue_energy=0 - for interface in self.power.keys(): - queue_energy+=self.get_receive_queue_energy(interface) - return self.get_idle()+self.energy_dynamic+queue_energy - - def report_energy(self): - self.log("Communications consumed "+str(round(self.get_energy(),2))+"J") diff --git a/plugins/wireless_area.py b/plugins/wireless_area.py deleted file mode 100644 index 958d4ba..0000000 --- a/plugins/wireless_area.py +++ /dev/null @@ -1,72 +0,0 @@ -import math -import numpy as np - -# This plugin is outdated -class WirelessArea: - - def __init__(self): - self.nodes=list() - - def dump_nodes(self): - i=0 - for node in self.nodes: - x,y,z,com_range=node - print("Node {} at ({},{},{}) with a communication range of {}m".format(i,x,y,z,com_range)) - i+=1 - - def dump_infos(self): - print("Number of nodes {}".format(len(self.nodes))) - adjacency=self.generate_adjacency_matrix(fill_diagonal=False) - print("Nodes average degree is {}".format(np.mean(np.sum(adjacency,axis=0)))) - x = [node[0] for node in self.nodes] - y = [node[1] for node in self.nodes] - z = [node[2] for node in self.nodes] - com_range = [node[3] for node in self.nodes] - print("Nodes locations ranges: x in [{},{}] y in [{},{}] z in [{},{}]".format(min(x),max(x),min(y),max(y),min(z),max(z))) - print("Node communication ranges in [{},{}]".format(min(com_range),max(com_range))) - - def add_node(self,x,y,z,com_range): - self.nodes.append((x,y,z,com_range)) - - def get_neighbours(self,node_id): - node=self.nodes[node_id] - neighbours=list() - for i in range(0,len(self.nodes)): - if i != node_id: - neighbour=self.nodes[i] - if math.dist(node[0:3],neighbour[0:3]) <= node[3]: - neighbours.append(i) - return neighbours - - def generate_dot(self,filepath): - is_strict=False - com_range=self.nodes[0][3] - for node in self.nodes: - if node[3] != com_range: - is_strict=True - break - - with open(filepath, "w") as f: - if is_strict: - f.write("digraph G {\n") - else: - f.write("strict graph G {\n") - for i in range(0,len(self.nodes)): - neighbours=self.get_neighbours(i) - for n in neighbours: - if is_strict: - f.write("{}->{}\n".format(i,n)) - else: - f.write("{}--{}\n".format(i,n)) - f.write("}") - - def generate_adjacency_matrix(self,fill_diagonal=True): - matrix=np.full((len(self.nodes),len(self.nodes)),0) - if fill_diagonal: - np.fill_diagonal(matrix,1) # Required by ESDS - for i in range(0,len(self.nodes)): - neighbours=self.get_neighbours(i) - for n in neighbours: - matrix[i,n]=1 - return matrix - |
