Skip to content
Snippets Groups Projects
Commit 8d38277b authored by Martin Teichmann's avatar Martin Teichmann
Browse files

factor out a Packet class

parent 81a268e9
No related branches found
No related tags found
No related merge requests found
...@@ -3,8 +3,6 @@ from enum import Enum ...@@ -3,8 +3,6 @@ from enum import Enum
from socket import socket, AF_PACKET, SOCK_DGRAM from socket import socket, AF_PACKET, SOCK_DGRAM
from struct import pack, unpack, calcsize from struct import pack, unpack, calcsize
MAXSIZE = 1000 # maximum size we use for an EtherCAT packet
class ECCmd(Enum): class ECCmd(Enum):
NOP = 0 # No Operation NOP = 0 # No Operation
APRD = 1 # Auto Increment Read APRD = 1 # Auto Increment Read
...@@ -114,6 +112,31 @@ def datasize(args, data): ...@@ -114,6 +112,31 @@ def datasize(args, data):
out += len(data) out += len(data)
return out return out
class Packet:
MAXSIZE = 1000 # maximum size we use for an EtherCAT packet
def __init__(self):
self.data = []
self.size = 2
def append(self, cmd, idx, pos, offset, data):
self.data.append((cmd, idx, pos, offset, data))
self.size += len(data) + 12
def assemble(self):
ret = [pack("<H", self.size | 0x1000)]
for i, (cmd, *dgram, data) in enumerate(self.data, start=1):
ret.append(pack("<BBhHHH", cmd.value, *dgram,
len(data) | ((i < len(self.data)) << 15), 0))
ret.append(data)
ret.append(b"\0\0")
return b"".join(ret)
def full(self):
return self.size > self.MAXSIZE
class AsyncBase: class AsyncBase:
async def __new__(cls, *args, **kwargs): async def __new__(cls, *args, **kwargs):
ret = super().__new__(cls) ret = super().__new__(cls)
...@@ -130,26 +153,18 @@ class EtherCat(Protocol, AsyncBase): ...@@ -130,26 +153,18 @@ class EtherCat(Protocol, AsyncBase):
lambda: self, family=AF_PACKET, proto=0xA488) lambda: self, family=AF_PACKET, proto=0xA488)
async def sendloop(self): async def sendloop(self):
ret = [None] packet = Packet()
size = 2
while True: while True:
*dgram, data, future = await self.send_queue.get() *dgram, future = await self.send_queue.get()
done = size > MAXSIZE or self.send_queue.empty() lastsize = packet.size
ret.append(pack("<BBhHHH", *dgram, packet.append(*dgram)
len(data) | ((not done) << 15), 0)) self.dgrams.append((lastsize + 10, packet.size - 2, future))
ret.append(data) if packet.full() or self.send_queue.empty():
ret.append(b"\0\0")
self.dgrams.append((size + 10, size + len(data) + 10, future))
size += len(data) + 12
if done:
ret[0] = pack("<H", size | 0x1000)
self.idle.clear() self.idle.clear()
self.transport.sendto(b"".join(ret), self.addr) self.transport.sendto(packet.assemble(), self.addr)
await self.idle.wait() await self.idle.wait()
assert len(self.dgrams) == 0 assert len(self.dgrams) == 0
packet = Packet()
ret = [None]
size = 2
async def roundtrip(self, cmd, pos, offset, *args, data=None, idx=0): async def roundtrip(self, cmd, pos, offset, *args, data=None, idx=0):
future = Future() future = Future()
...@@ -162,8 +177,7 @@ class EtherCat(Protocol, AsyncBase): ...@@ -162,8 +177,7 @@ class EtherCat(Protocol, AsyncBase):
out += b"\0" * data out += b"\0" * data
elif data is not None: elif data is not None:
out += data out += data
self.send_queue.put_nowait( self.send_queue.put_nowait((cmd, idx, pos, offset, out, future))
(cmd.value, idx, pos, offset, out, future))
ret = await future ret = await future
if data is None: if data is None:
return unpack(fmt, ret) return unpack(fmt, ret)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment