Skip to content

Commit e0ff2e9

Browse files
committed
Restructure measurement handling logic
1 parent 57e60a2 commit e0ff2e9

File tree

8 files changed

+71
-41
lines changed

8 files changed

+71
-41
lines changed

examples/frame_detector.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@
1818
"""
1919

2020
import asyncio
21-
from zbnt import ZbntClient, TrafficGenerator, Devices, Properties, discover_devices
21+
from zbnt import ZbntClient, FrameDetector, TrafficGenerator, Devices, Properties, discover_devices
2222

2323
output_file = open("results.csv", "w")
2424

25-
def write_fd_measurement(dev_id, measurement_data):
26-
measurement_data = list(measurement_data)
27-
measurement_data[-1] = measurement_data[-1].hex()
25+
def handle_measurement(device, measurement):
26+
if isinstance(device, FrameDetector) and device.ports == [2, 3]:
27+
measurement.payload = measurement.payload.hex()
2828

29-
output_file.write(",".join(map(str, measurement_data)))
30-
output_file.write("\n")
29+
output_file.write(",".join(map(str, measurement.__dict__.values())))
30+
output_file.write("\n")
3131

3232
async def main():
3333
# Scan for devices, ask the user to select one if multiple devices are found
@@ -85,7 +85,7 @@ async def main():
8585

8686
# Set function to be called every time the server sends measurement data
8787

88-
fd0.measurement_handler = write_fd_measurement
88+
client.set_callback(handle_measurement)
8989

9090
# Tell the server to start the run, this will initialize the DMA core
9191

examples/traffic_generator.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,16 @@
1818
"""
1919

2020
import asyncio
21-
from zbnt import ZbntClient, TrafficGenerator, Devices, Properties, discover_devices
21+
from zbnt import ZbntClient, TrafficGenerator, StatsCollector, Devices, Properties, discover_devices
2222

2323
output_file = open("results.csv", "w")
2424

25-
def write_sc_measurement(dev_id, measurement_data):
26-
output_file.write(",".join(map(str, measurement_data)))
27-
output_file.write("\n")
25+
def handle_measurement(device, measurement):
26+
if isinstance(device, StatsCollector) and device.ports == [0]:
27+
output_file.write(",".join(map(str, measurement.__dict__.values())))
28+
output_file.write("\n")
2829

29-
print("\rTX: {0} bytes".format(measurement_data[1]), end="")
30+
print("\rTX: {0} bytes".format(measurement.tx_bytes), end="")
3031

3132
async def main():
3233
# Scan for devices, ask the user to select one if multiple devices are found
@@ -82,7 +83,7 @@ async def main():
8283

8384
# Set function to be called every time the server sends measurement data
8485

85-
sc0.measurement_handler = write_sc_measurement
86+
client.set_callback(handle_measurement)
8687

8788
# Tell the server to start the run, this will initialize the DMA core
8889

zbnt/AxiDevice.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,17 @@ def __init__(self, parent, dev_id, initial_props):
2727
self.id = dev_id
2828
self.ports = []
2929
self.client = parent
30-
self.measurement_handler = None
3130
self.valid_properties = list(self._property_encoding)
3231

3332
for prop_id, prop_bytes in initial_props:
3433
if prop_id == Properties.PROP_PORTS:
3534
self.ports = list(prop_bytes)
3635

3736
def __repr__(self):
38-
return "zbnt.{0}(dev_id={1}, ports={2})".format(self.__class__.__name__, self.id, str(self.ports))
37+
return f"{self.__class__.__name__}(id={self.id}, ports={self.ports})"
3938

4039
def receive_measurement(self, data):
41-
if self.measurement_handler != None:
42-
self.measurement_handler(self.id, data)
40+
return None
4341

4442
async def set_property(self, prop_id, value, params=dict()):
4543
prop_encoding = self._property_encoding.get(prop_id, None)

zbnt/FrameDetector.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ class FeatureBits(IntFlag):
7070
HAS_CSUM_UNIT = 4
7171
HAS_FPU = 8
7272

73+
class Frame:
74+
def __init__(self, time, number, direction, error, match, payload):
75+
self.time = time
76+
self.number = number
77+
self.direction = direction
78+
self.error = error
79+
self.match = match
80+
self.payload = payload
81+
82+
def __repr__(self):
83+
return f"FrameDetector.Frame(number={self.number}, time={self.time}, direction={self.direction}, match={self.match}, error={self.error}, captured_size={len(self.payload)})"
84+
7385
def __init__(self, parent, dev_id, initial_props):
7486
super().__init__(parent, dev_id, initial_props)
7587

@@ -92,25 +104,19 @@ def __init__(self, parent, dev_id, initial_props):
92104

93105
def receive_measurement(self, data):
94106
if len(data) < 15:
95-
return
96-
97-
if self.measurement_handler == None:
98-
return
107+
return None
99108

100109
time = decode_u64(data[0:8])
101110
number = decode_u32(data[8:12])
102-
match_dir = data[12] - 64
111+
direction = data[12] & 1
112+
error = data[12] >> 1
103113
log_width = data[13]
104114
match_mask = data[14]
105115

106116
ext_offset = ((log_width + 23) // log_width) * log_width - 8
107-
108-
if match_dir < 0 or match_dir > 1:
109-
return
110-
111117
ext_data = data[ext_offset:]
112118

113-
self.measurement_handler(self.id, (time, number, match_dir, match_mask, ext_data))
119+
return FrameDetector.Frame(time, number, direction, error, match_mask, ext_data)
114120

115121
def load_script(self, path):
116122
comparator_instr = [(0, 0)] * self.max_script_size

zbnt/LatencyMeasurer.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,24 @@ class LatencyMeasurer(AxiDevice):
4545
])
4646
}
4747

48+
class Measurement:
49+
def __init__(self, time, number, ping, pong, lost_pings, lost_pongs):
50+
self.time = time
51+
self.number = number
52+
self.ping = ping
53+
self.pong = pong
54+
self.lost_pings = lost_pings
55+
self.lost_pongs = lost_pongs
56+
57+
def __repr__(self):
58+
return f"LatencyMeasurer.Measurement(time={self.time}, number={self.number}, latency=({self.ping}, {self.pong}), lost=({self.lost_pings}, {self.lost_pongs}))"
59+
4860
def __init__(self, parent, dev_id, initial_props):
4961
super().__init__(parent, dev_id, initial_props)
5062

5163
def receive_measurement(self, data):
5264
if len(data) < 40:
53-
return
54-
55-
if self.measurement_handler == None:
56-
return
65+
return None
5766

5867
time = decode_u64(data[0:8])
5968

@@ -64,4 +73,4 @@ def receive_measurement(self, data):
6473
num_lost_pings = decode_u64(data[24:32])
6574
num_lost_pongs = decode_u64(data[32:40])
6675

67-
self.measurement_handler(self.id, (time, num_pings, ping_time, pong_time, num_lost_pings, num_lost_pongs))
76+
return LatencyMeasurer.Measurement(time, num_pings, ping_time, pong_time, num_lost_pings, num_lost_pongs)

zbnt/SimpleTimer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ def __init__(self, parent, dev_id, initial_props):
4040
self.freq = int.from_bytes(prop_bytes[:4], byteorder="little", signed=False)
4141

4242
def __repr__(self):
43-
return "zbnt.{0}(dev_id={1}, freq={2})".format(self.__class__.__name__, self.id, self.freq)
43+
return f"SimpleTimer(id={self.id}, freq={self.freq})"

zbnt/StatsCollector.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,25 @@ class StatsCollector(AxiDevice):
3030
Properties.PROP_OVERFLOW_COUNT: (None, decode_u64)
3131
}
3232

33+
class Statistics:
34+
def __init__(self, time, tx_bytes, tx_good, tx_bad, rx_bytes, rx_good, rx_bad):
35+
self.time = time
36+
self.tx_bytes = tx_bytes
37+
self.tx_good = tx_good
38+
self.tx_bad = tx_bad
39+
self.rx_bytes = rx_bytes
40+
self.rx_good = rx_good
41+
self.rx_bad = rx_bad
42+
43+
def __repr__(self):
44+
return f"StatsCollector.Statistics(time={self.time}, tx=({self.tx_bytes}, {self.tx_good}, {self.tx_bad}), rx=({self.rx_bytes}, {self.rx_good}, {self.rx_bad}))"
45+
3346
def __init__(self, parent, dev_id, initial_props):
3447
super().__init__(parent, dev_id, initial_props)
3548

3649
def receive_measurement(self, data):
3750
if len(data) < 56:
38-
return
39-
40-
if self.measurement_handler == None:
41-
return
51+
return None
4252

4353
time = decode_u64(data[0:8])
4454

@@ -50,4 +60,4 @@ def receive_measurement(self, data):
5060
rx_good = decode_u64(data[40:48])
5161
rx_bad = decode_u64(data[48:56])
5262

53-
self.measurement_handler(self.id, (time, tx_bytes, tx_good, tx_bad, rx_bytes, rx_good, rx_bad))
63+
return StatsCollector.Statistics(time, tx_bytes, tx_good, tx_bad, rx_bytes, rx_good, rx_bad)

zbnt/ZbntClient.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def __init__(self):
4242
self.connected = False
4343
self.disconnecting = False
4444
self.devices = dict()
45-
45+
self.callback = None
4646
self.pending_msg = None
4747

4848
@staticmethod
@@ -94,6 +94,9 @@ def disconnect(self):
9494
self.disconnecting = True
9595
self.transport.close()
9696

97+
def set_callback(self, callback):
98+
self.callback = callback
99+
97100
def send_message(self, msg_id, payload):
98101
self.transport.write(MessageReceiver.MSG_MAGIC_IDENTIFIER)
99102
self.transport.write(encode_u16(msg_id))
@@ -310,5 +313,8 @@ def message_received(self, msg_id, msg_payload):
310313
dev_id = msg_id & ~Messages.MSG_ID_MEASUREMENT
311314
dev_obj = self.devices.get(dev_id, None)
312315

313-
if dev_id != None and len(msg_payload) >= 8:
314-
dev_obj.receive_measurement(msg_payload)
316+
if dev_id != None and len(msg_payload) >= 8 and self.callback != None:
317+
meas_obj = dev_obj.receive_measurement(msg_payload)
318+
319+
if meas_obj != None:
320+
self.callback(dev_obj, meas_obj)

0 commit comments

Comments
 (0)