~martijnbraam/pyatem

73972eda346039ea85ccb67cb1d73577c149401e — Martijn Braam a month ago 4eae33c 0.1.0
Drop retransmission packets of received packets

Sometimes the mixer will send data faster than python will ACK
it causing the hardware to send retransmissions with duplicate
data. This will keep track of the 128 last received packet ids
and drop the retransmission packets if we did actually retrieve
it correctly previously.

The number 128 was chosen because the hardware seems to allow
about 64 unacked frames in flight.
1 files changed, 13 insertions(+), 2 deletions(-)

M pyatem/transport.py
M pyatem/transport.py => pyatem/transport.py +13 -2
@@ 3,11 3,11 @@ import struct
import logging
import time
from queue import Queue, Empty
import collections
from urllib.parse import urlparse

import usb.core
import usb.util
from hexdump import hexdump


class Packet:


@@ 66,7 66,6 @@ class Packet:
        result = struct.pack('<I', data_len)
        if self.data:
            result += bytes(self.data)
        hexdump(result)
        return result

    def __repr__(self):


@@ 110,6 109,7 @@ class UdpProtocol:

        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.sock.settimeout(5)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 1024 * 1024 * 16)

        self.local_sequence_number = 0
        self.local_ack_number = 0


@@ 122,6 122,8 @@ class UdpProtocol:
        self.enable_ack = False
        self.had_traffic = False

        self.received_packets = collections.deque(maxlen=128)

    def _send_packet(self, packet):
        packet.session = self.session_id
        if not packet.flags & UdpProtocol.FLAG_ACK:


@@ 158,6 160,13 @@ class UdpProtocol:
        if self.session_id is None:
            self.session_id = packet.session

        is_retransmissions = packet.flags & UdpProtocol.FLAG_RETRANSMISSION
        if is_retransmissions:
            if self.remote_sequence_number in self.received_packets:
                return True

        self.received_packets.append(self.remote_sequence_number)

        if packet.flags & UdpProtocol.FLAG_RELIABLE and self.enable_ack:
            # This packet needs an ACK
            ack = Packet()


@@ 217,6 226,8 @@ class UdpProtocol:
    def receive_packet(self):
        while True:
            packet = self._receive_packet()
            if packet is True:
                continue
            if packet is None and not self.had_traffic:
                continue
            if packet is None and self.state == UdpProtocol.STATE_SYN_SENT: