-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcli.py
234 lines (194 loc) · 7.88 KB
/
cli.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
import json
class WiFiChannel:
"""This class represents a WiFi channel."""
def __init__(
self,
channelNumber,
usage,
interference,
noise,
transmissionPower,
channelWidth,
frequencyBand,
):
"""
Initializes a new instance of the WiFiAnalyzer class.
Args:
channelNumber (int): The channel number.
usage (float): The percentage of channel usage.
interference (float): The percentage of channel interference.
noise (float): The percentage of channel noise.
transmissionPower (float): The transmission power in dBm.
channelWidth (float): The channel width in MHz.
frequencyBand (str): The frequency band (e.g. 2.4 GHz, 5 GHz).
"""
self.channelNumber = channelNumber
self.usage = usage
self.interference = interference
self.noise = noise
self.transmissionPower = transmissionPower
self.channelWidth = channelWidth
self.frequencyBand = frequencyBand
def score(self):
"""Calculate a score based on various parameters."""
width_factor = (
1 if self.channelWidth == 20 else 1.5 if self.channelWidth == 40 else 2
)
return (
-self.usage - self.interference - self.noise + self.transmissionPower
) * width_factor
def update(self, **kwArgs):
"""Update channel parameters dynamically."""
for key, value in kwArgs.items():
if hasattr(self, key):
setattr(self, key, value)
def __str__(self):
return (
f"Channel {self.channelNumber} ({self.frequencyBand}GHz): Usage({self.usage}), "
f"Interference({self.interference}), Noise({self.noise}), Transmission Power({self.transmissionPower}), "
f"Channel Width({self.channelWidth}MHz)"
)
class WiFiAnalyzer:
"""
This class represents a WiFi analyzer.
Attributes:
channels (dict): A dictionary containing WiFi channels.
history (list): A list of actions performed by the analyzer.
"""
def __init__(self):
with open("channels.json", "r+", encoding="utf-8") as f:
loaded_channels = json.load(f)
# Convert dictionaries back to WiFiChannel objects
self.channels = {
(
int(key.strip("()").split(", ")[0]),
float(key.strip("()").split(", ")[1]),
): WiFiChannel(**value)
for key, value in loaded_channels.items()
}
# self.channels = {}
self.history = []
def save_channels_database(self):
"""Save the channels database to a JSON file."""
with open("channels.json", "w", encoding="utf-8") as file_key:
channels_dict = {}
for key, value in self.channels.items():
channels_dict[str(key)] = value.__dict__
json.dump(channels_dict, file_key, indent=4)
def add_or_update_channel(self, channelNumber, frequencyBand, **kwArgs):
"""Add or update a WiFi channel with dynamic parameters."""
channel_key = (channelNumber, frequencyBand)
if channel_key in self.channels:
self.channels[channel_key].update(**kwArgs)
self.log_action(f"Updated Channel {channelNumber} on {frequencyBand}GHz.")
self.save_channels_database()
else:
self.channels[channel_key] = WiFiChannel(
channelNumber, frequencyBand=frequencyBand, **kwArgs
)
self.log_action(f"Added Channel {channelNumber} on {frequencyBand}GHz.")
self.save_channels_database()
def remove_channel(self, channelNumber, frequencyBand):
"""Remove a channel."""
channel_key = (channelNumber, frequencyBand)
if channel_key in self.channels:
del self.channels[channel_key]
self.log_action(f"Removed Channel {channelNumber} on {frequencyBand}GHz.")
self.save_channels_database()
def display_channels(self):
"""Display channels sorted by their scores."""
sorted_channels = sorted(
self.channels.values(), key=lambda c: c.score(), reverse=True
)
for channel in sorted_channels:
print(channel)
def best_channel(self):
"""Determine the best channel based on the current data."""
best_channel = max(
self.channels.values(), key=lambda c: c.score(), default=None
)
return best_channel.channelNumber if best_channel else None
def best_channel_per_band(self):
"""Compute the best channel for each frequency band and return as JSON."""
best_channels = {"2.4GHz": None, "5GHz": None, "6GHz": None}
for (_, frequencyBand), channel in self.channels.items():
frequency_key = f"{frequencyBand}GHz"
if (
best_channels[frequency_key] is None
or channel.score() > best_channels[frequency_key].score()
):
best_channels[frequency_key] = channel
# Convert the results into a JSON-compatible format
json_output = {
frequency: channel if channel else None
for frequency, channel in best_channels.items()
}
return json.dumps(json_output, indent=4)
def log_action(self, message):
"""Log actions for history."""
self.history.append(message)
def display_history(self):
"""Display a log of all actions."""
for entry in self.history:
print(entry)
def summary(self):
"""Provide a summary of the best channel."""
best = self.best_channel()
if best:
print(f"\nThe best WiFi channel is {best}.\n")
else:
print("\nNo channel data available.\n")
def main():
"""This function provides a command-line interface for the WiFiAnalyzer class."""
analyzer = WiFiAnalyzer()
while True:
print("\nOptions:")
print("1. Add/Update Channel")
print("2. Remove Channel")
print("3. Display Channels")
print("4. Best Channel Summary")
print("5. Best Channels per Band (JSON output)")
print("6. Display History")
print("7. Exit")
choice = input("Enter your choice: ")
if choice == "1":
channelNumber = int(input("Enter channel number: "))
frequencyBand = float(
input("Choose frequency band (2.4, 5, or 6 in GHz): ")
)
usage = int(input("Enter usage: "))
interference = int(input("Enter interference: "))
noise = int(input("Enter noise: "))
transmissionPower = int(input("Enter transmission power: "))
channelWidth = int(
input("Enter channel width (20, 40, 80, or 160 in MHz): ")
)
analyzer.add_or_update_channel(
channelNumber,
frequencyBand,
usage=usage,
interference=interference,
noise=noise,
transmissionPower=transmissionPower,
channelWidth=channelWidth,
)
elif choice == "2":
channelNumber = int(input("Enter channel number to remove: "))
frequencyBand = float(
input("Enter frequency band for the channel (2.4, 5, or 6 in GHz): ")
)
analyzer.remove_channel(channelNumber, frequencyBand)
elif choice == "3":
analyzer.display_channels()
elif choice == "4":
analyzer.summary()
elif choice == "5":
print(analyzer.best_channel_per_band())
elif choice == "6":
analyzer.display_history()
elif choice == "7":
break
else:
print("Invalid choice. Please try again.")
if __name__ == "__main__":
main()