-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdata.py
231 lines (183 loc) · 8.54 KB
/
data.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
import logging
import netifaces
import os
from ipaddress import IPv6Address, IPv6Network, AddressValueError
from event_system import EventProducer, Event, EventListener
from packet import ContikiPacket
class PacketBuffEvent(Event):
def __init__(self, data: dict):
Event.__init__(self, data)
logging.debug("BRIDGE: new packet in buffer")
def __str__(self):
return "packet-buff-event"
class PacketBuffer(EventProducer, EventListener): # todo create packet buffer maximum limit
"""
Buffer which stores packets, which waits for routing decision received over serial line
"""
def __init__(self):
from serial_connection import SerialPacketToSendEvent
self.counter = 1
self.rpl_sent = 0
self.wifi_sent = 0
self.wrong = 0
self._packets = {}
EventListener.__init__(self)
EventProducer.__init__(self)
self.add_event_support(PacketBuffEvent)
self.add_event_support(SerialPacketToSendEvent)
def add_packet(self, packet: ContikiPacket):
self._packets.update({
self.counter: packet
})
self.notify_listeners(PacketBuffEvent({
"id": self.counter,
"packet": packet
}))
self.counter += 1
def handle_packet(self, id: int, response: bool):
from serial_connection import SerialPacketToSendEvent
if id in self._packets:
if response:
self.notify_listeners(SerialPacketToSendEvent(self._packets[id]))
self.wifi_sent += 1
else:
self.rpl_sent += 1
del self._packets[id]
else:
self.wrong += 1
def notify(self, event: Event):
from interface_listener import RootPacketForwardEvent
from serial_connection import ResponseToPacketRequest
if isinstance(event, RootPacketForwardEvent):
self.add_packet(event.get_event())
if isinstance(event, ResponseToPacketRequest):
self.handle_packet(event.get_event()["question_id"], event.get_event()["response"])
def __str__(self):
return "packet-buffer"
def print_buffer_stats(self):
print("Waiting packets: {}\nSent wifi: {}\nSent rpl: {}\nWrong: {}\n".format(
len(self._packets), self.wifi_sent, self.rpl_sent, self.wrong))
class ChangeModeEvent(Event):
def __init__(self, data: int):
Event.__init__(self, data)
logging.info('CONTIKI: sets node mode to "{}"'.format(data))
def __str__(self):
return "change-mode-event"
class Data(EventProducer):
"""
Provides simple place for storing base node data
"""
MODE_ROOT = 1
MODE_NODE = 2
def __init__(self, configuration):
EventProducer.__init__(self)
self.add_event_support(ChangeModeEvent)
self._mote_global_address = None
self._mote_link_local_address = None
self._wifi_global_address = None
self._wifi_l2_address = None
self._border_router_l2_address = None
self._mode = None
self._configuration = configuration
def set_border_router_l2_address(self, border_router_l2):
self._border_router_l2_address = border_router_l2
def get_border_router_l2_address(self):
return self._border_router_l2_address
def set_mode(self, mode: int):
if (mode == self.MODE_NODE or mode == self.MODE_ROOT) and mode != self._mode:
self._mode = mode
self.notify_listeners(ChangeModeEvent(mode))
def set_wifi_global_address(self, global_address):
self._wifi_global_address = global_address
def get_wifi_global_address(self):
return self._wifi_global_address
def set_wifi_l2_address(self, address):
self._wifi_l2_address = address
def get_wifi_l2_address(self):
return self._wifi_l2_address
def set_mote_global_address(self, global_address):
self._mote_global_address = global_address
def get_mote_global_address(self):
return self._mote_global_address
def set_mote_link_local_address(self, link_local_address):
self._mote_link_local_address = link_local_address
def get_mote_link_local_address(self):
return self._mote_link_local_address
def get_configuration(self):
return self._configuration
def get_mode(self):
return self._mode
def print_data(self):
print('Bridge mode: {}\nMote global IP: {:>30}\nMote local IP: {:>30}\nWifi global IP: {:>30}\nWifi MAC{:>30}\n'
'Root MAC{:>30}\n'.format("ROOT" if self._mode == self.MODE_ROOT else "NODE", self._mote_global_address,
self._mote_link_local_address, self._wifi_global_address, self._wifi_l2_address,
self._border_router_l2_address if self._border_router_l2_address else "None"))
class IpConfigurator(EventListener):
"""
Class responsible for interface configuration
"""
def __init__(self, data: Data, iface: str, prefix: str, root_address: str):
self._iface = iface
self._data = data
self._root_address = root_address
self._prefix = IPv6Network(prefix)
def _add_route(self, address: str):
logging.debug('BRIDGE:adding route to "{}" via "{}" interface'.format(address, self._iface))
os.system("ip -6 route add {} dev {}".format(address, self._iface))
def _remove_route(self, address: str):
logging.debug('BRIDGE:removing route to "{}" via "{}" interface'.format(address, self._iface))
os.system("ip -6 route del {} dev {}".format(address, self._iface))
def _set_address(self, address: str):
logging.debug('BRIDGE:adding address "{}" to "{}" interface'.format(address, self._iface))
os.system("ifconfig {} add {}".format(self._iface, address))
def _unset_address(self, address: str):
logging.debug('BRIDGE:removing address "{}" from "{}" interface'.format(address, self._iface))
os.system("ifconfig {} del {}".format(self._iface, address))
def _get_wifi_global_addressees(self):
interface = netifaces.ifaddresses(self._iface)
try:
return interface[netifaces.AF_INET6]
except KeyError:
logging.debug('BRIDGE:previous ipv6 address not configured for "{}" interface'.format(self._iface))
return []
def _remove_current_addresses_from_prefix(self, current_addresses: list):
for address in current_addresses:
try:
addr_obj = IPv6Address(address['addr'])
if addr_obj in self._prefix:
self._unset_address("{}/{}".format(str(addr_obj), self._prefix.prefixlen))
except AddressValueError:
logging.warning('BRIDGE:interface "{}" has not valid ipv6 address "{}"'.format(self._iface, address))
"""
Gets last ocet from mote global address and concatenates it with configured prefix (new wifi global IPv6 address).
If new address is same as previously configured address, ends. Else, removes old global IPv6 address. Result sets
up as wifi global IPv6 address, sets up routes.
"""
def set_wifi_ipv6_lobal_address(self, mote_global_address: str):
last_ocet = mote_global_address.split(":")[-1]
wifi_global_address = str(self._prefix).replace("::", "::{}".format(last_ocet))
if wifi_global_address == self._data.get_wifi_global_address():
return
current_addresses = self._get_wifi_global_addressees()
self._remove_current_addresses_from_prefix(current_addresses)
if wifi_global_address != self._data.get_wifi_global_address():
self._set_address(wifi_global_address)
self._data.set_wifi_global_address(wifi_global_address.split("/")[0])
self._add_route("default")
def load_wifi_l2_address(self):
l2_addr = netifaces.ifaddresses(self._iface)[netifaces.AF_LINK][0]['addr']
self._data.set_wifi_l2_address(l2_addr)
def notify(self, event: Event):
from serial_connection import MoteGlobalAddressEvent
if isinstance(event, MoteGlobalAddressEvent):
self.set_wifi_ipv6_lobal_address(event.get_event())
elif isinstance(event, ChangeModeEvent):
mode = event.get_event()
if mode == Data.MODE_NODE:
self._unset_address(self._root_address)
self._add_route(self._root_address)
elif mode == Data.MODE_ROOT:
self._set_address(self._root_address)
self._remove_route(self._root_address)
def __str__(self):
return "ip-configurator"