pounder_test/hitl/streaming.py

98 lines
3.0 KiB
Python

#!/usr/bin/python3
"""
Author: Vertigo Designs, Ryan Summers
Description: Implements HITL testing of Stabilizer data livestream capabilities.
"""
import asyncio
import sys
import argparse
import socket
from miniconf import Miniconf
from stabilizer.stream import StabilizerStream
def _get_ip(broker):
""" Get the IP of the local device.
Args:
broker: The broker IP of the test. Used to select an interface to get the IP of.
Returns:
The IP as an array of integers.
"""
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
sock.connect((broker, 1883))
address = sock.getsockname()[0]
finally:
sock.close()
return list(map(int, address.split('.')))
def sequence_delta(previous_sequence, next_sequence):
""" Check the number of items between two sequence numbers. """
if previous_sequence is None:
return 0
delta = next_sequence - (previous_sequence + 1)
return delta & 0xFFFFFFFF
def main():
""" Main program entry point. """
parser = argparse.ArgumentParser(description='Loopback tests for Stabilizer HITL testing',)
parser.add_argument('prefix', type=str,
help='The MQTT topic prefix of the target')
parser.add_argument('--broker', '-b', default='mqtt', type=str,
help='The MQTT broker address')
parser.add_argument('--port', '-p', default=2000, type=int,
help='The UDP port to use for streaming')
args = parser.parse_args()
async def test():
""" The actual testing being completed. """
local_ip = _get_ip(args.broker)
interface = await Miniconf.create(args.prefix, args.broker)
stream = StabilizerStream(args.port, timeout=0.5)
# Configure the stream
print(f'Configuring stream to target {".".join(map(str, local_ip))}:{args.port}')
print('')
await interface.command('stream_target', {'ip': local_ip, 'port': args.port}, retain=False)
await interface.command('telemetry_period', 10, retain=False)
# Verify frame reception
print('Testing stream reception')
print('')
last_sequence = None
for _ in range(5000):
for (seqnum, _data) in stream.read_frame():
assert sequence_delta(last_sequence, seqnum) == 0, \
f'Frame drop detected: 0x{last_sequence:08X} -> 0x{seqnum:08X}'
last_sequence = seqnum
# Disable the stream.
print('Closing stream')
print('')
await interface.command('stream_target', {'ip': [0, 0, 0, 0], 'port': 0}, retain=False)
stream.clear()
print('Verifying no further data is received')
try:
for _ in stream.read_frame():
raise Exception('Unexpected data encountered on stream')
except socket.timeout:
pass
print('PASS')
loop = asyncio.get_event_loop()
sys.exit(loop.run_until_complete(test()))
if __name__ == '__main__':
main()