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

add proper command line tools

parent 6b6f20d1
No related branches found
No related tags found
No related merge requests found
...@@ -128,8 +128,13 @@ class ObjectDescription: ...@@ -128,8 +128,13 @@ class ObjectDescription:
def __getitem__(self, idx): def __getitem__(self, idx):
return self.entries[idx] return self.entries[idx]
def __repr__(self):
return " ".join(f"[{k:X}: {v}]" for k, v in self.entries.items())
class ObjectEntry: class ObjectEntry:
name = None
def __init__(self, desc): def __init__(self, desc):
self.desc = desc self.desc = desc
...@@ -155,6 +160,13 @@ class ObjectEntry: ...@@ -155,6 +160,13 @@ class ObjectEntry:
return await self.desc.terminal.sdo_write(d, self.desc.index, return await self.desc.terminal.sdo_write(d, self.desc.index,
self.valueInfo) self.valueInfo)
def __repr__(self):
if self.name is None:
return "[unread ObjectEntry]"
return f'"{self.name}" {self.dataType}:{self.bitLength} ' \
f'{self.objectAccess:X}'
def datasize(args, data): def datasize(args, data):
out = calcsize("<" + "".join(arg for arg in args if isinstance(arg, str))) out = calcsize("<" + "".join(arg for arg in args if isinstance(arg, str)))
...@@ -221,11 +233,11 @@ class Packet: ...@@ -221,11 +233,11 @@ class Packet:
pos = 14 + self.DATAGRAM_HEADER pos = 14 + self.DATAGRAM_HEADER
ret = [] ret = []
for cmd, bits, *dgram in self.data: for cmd, bits, *dgram in self.data:
ret.append((data[pos-self.DATAGRAM_HEADER], ret.append(unpack("<Bxh6x", data[pos-self.DATAGRAM_HEADER:pos])
data[pos:pos+len(bits)], + (data[pos:pos+len(bits)],
unpack("<H", data[pos+len(bits):pos+len(bits)+2])[0])) unpack("<H", data[pos+len(bits):pos+len(bits)+2])[0]))
pos += self.DATAGRAM_HEADER + self.DATAGRAM_TAIL pos += self.DATAGRAM_HEADER + self.DATAGRAM_TAIL
return ''.join(f"{i}: {c} {f} {d}\n" for i, (c, d, f) in enumerate(ret)) return ''.join(f"{i}: {c} {a} {f} {d}\n" for i, (c, a, d, f) in enumerate(ret))
def full(self): def full(self):
"""Is the data limit reached?""" """Is the data limit reached?"""
...@@ -322,6 +334,7 @@ class EtherCat(Protocol): ...@@ -322,6 +334,7 @@ class EtherCat(Protocol):
out += b"\0" * data out += b"\0" * data
elif data is not None: elif data is not None:
out += data out += data
assert isinstance(pos, int) and isinstance(offset, int)
self.send_queue.put_nowait((cmd, out, idx, pos, offset, future)) self.send_queue.put_nowait((cmd, out, idx, pos, offset, future))
ret = await future ret = await future
if data is None: if data is None:
...@@ -333,6 +346,14 @@ class EtherCat(Protocol): ...@@ -333,6 +346,14 @@ class EtherCat(Protocol):
else: else:
return ret return ret
async def count(self):
"""Count the number of terminals on the bus"""
p = Packet()
p.append(ECCmd.APRD, b"\0\0", 0, 0, 0x10)
ret = await self.roundtrip_packet(p)
no, = unpack("<h", ret[16:18]) # number of terminals
return no
def connection_made(self, transport): def connection_made(self, transport):
"""start the send loop once the connection is made""" """start the send loop once the connection is made"""
transport.get_extra_info("socket").bind(self.addr) transport.get_extra_info("socket").bind(self.addr)
...@@ -473,7 +494,7 @@ class Terminal: ...@@ -473,7 +494,7 @@ class Terminal:
start, *args, **kwargs)) start, *args, **kwargs))
async def write(self, start, *args, **kwargs): async def write(self, start, *args, **kwargs):
"""write data from the terminal at offset `start` """write data to the terminal at offset `start`
see `EtherCat.roundtrip` for details on more parameters""" see `EtherCat.roundtrip` for details on more parameters"""
return (await self.ec.roundtrip(ECCmd.FPWR, self.position, return (await self.ec.roundtrip(ECCmd.FPWR, self.position,
...@@ -691,55 +712,3 @@ class Terminal: ...@@ -691,55 +712,3 @@ class Terminal:
oe.name = data[8:].decode("utf8") oe.name = data[8:].decode("utf8")
od.entries[i] = oe od.entries[i] = oe
return ret return ret
async def main():
from .bpf import lookup_elem
ec = EtherCat("eth0")
await ec.connect()
#map_fd = await install_ebpf2()
tin = Terminal()
tin.ec = ec
tout = Terminal()
tout.ec = ec
tdigi = Terminal()
tdigi.ec = ec
await gather(
tin.initialize(-4, 19),
tout.initialize(-2, 55),
tdigi.initialize(0, 22),
)
print("tin")
#await tin.to_operational()
await tin.set_state(2)
print("tout")
await tout.to_operational()
print("reading odlist")
odlist2, odlist = await gather(tin.read_ODlist(), tout.read_ODlist())
#oe = odlist[0x7001][1]
#await oe.write(1)
for o in odlist.values():
print(hex(o.index), o.name, o.maxSub)
for i, p in o.entries.items():
print(" ", i, p.name, "|", p.dataType, p.bitLength, p.objectAccess)
#sdo = await tin.sdo_read(o.index, i)
try:
sdo = await p.read()
if isinstance(sdo, int):
t = hex(sdo)
else:
t = ""
print(" ", sdo, t)
except RuntimeError as e:
print(" E", e)
print("set sdo")
oe = odlist[0x8010][7]
print("=", await oe.read())
await oe.write(1)
print("=", await oe.read())
print(tdigi.eeprom[10])
if __name__ == "__main__":
loop = get_event_loop()
loop.run_until_complete(main())
from argparse import ArgumentParser
import asyncio
from functools import wraps
from struct import unpack
import sys
from .ethercat import EtherCat, Terminal, ECCmd
def entrypoint(func):
@wraps(func)
def wrapper():
asyncio.run(func())
return wrapper
@entrypoint
async def scanbus():
ec = EtherCat(sys.argv[1])
await ec.connect()
no = await ec.count()
for i in range(no):
r, = await ec.roundtrip(ECCmd.APRD, -i, 0x10, "H", 44)
print(i, r)
@entrypoint
async def info():
parser = ArgumentParser(
prog = "ec-info",
description = "Retrieve information from an EtherCat bus")
parser.add_argument("interface")
parser.add_argument("-t", "--terminal", type=int)
parser.add_argument("-i", "--ids", action="store_true")
parser.add_argument("-n", "--names", action="store_true")
parser.add_argument("-s", "--sdo", action="store_true")
parser.add_argument("-v", "--values", action="store_true")
args = parser.parse_args()
ec = EtherCat(args.interface)
await ec.connect()
if args.terminal is None:
terminals = range(await ec.count())
else:
# print(await ec.roundtrip(ECCmd.FPRW, 7, 0x10, "H", 0))
terminals = [args.terminal]
terms = [Terminal() for t in terminals]
for t in terms:
t.ec = ec
await asyncio.gather(*(t.initialize(-i, i + 7)
for i, t in zip(terminals, terms)))
for i, t in enumerate(terms):
print(f"terminal no {i}")
if args.ids:
print(f"{t.vendorId:X}:{t.productCode:X} "
f"revision {t.revisionNo:X} serial {t.serialNo}")
if args.names:
infos = t.eeprom[10]
i = 1
while i < len(infos):
print(infos[i+1 : i+infos[i]+1].decode("ascii"))
i += infos[i] + 1
if args.sdo:
await t.to_operational()
ret = await t.read_ODlist()
for k, v in ret.items():
print(f"{k:X}:")
for kk, vv in v.entries.items():
print(f" {kk:X}: {vv}")
if args.values:
r = await vv.read()
if isinstance(r, int):
print(f" {r:10} {r:8X}")
else:
print(f" {r}")
[project]
name = "ebpfcat"
version = "0.0.1"
dependencies = []
[project.scripts]
ec-scanbus = "ebpfcat.scripts:scanbus"
ec-info = "ebpfcat.scripts:info"
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