diff --git a/ebpfcat/ethercat.py b/ebpfcat/ethercat.py index fa6edbfbd5d3e403ade068e00c5f2c227892dc4a..6d96de7be901ff357492c9d22e167cea70400159 100644 --- a/ebpfcat/ethercat.py +++ b/ebpfcat/ethercat.py @@ -26,34 +26,41 @@ class ECCmd(Enum): FRMW = 14 # Configured Read Multiple Write -class ECDatatype(Enum): - BOOLEAN = 0x1 - INTEGER8 = 0x2 - INTEGER16 = 0x3 - INTEGER32 = 0x4 - UNSIGNED8 = 0x5 - UNSIGNED16 = 0x6 - UNSIGNED32 = 0x7 - REAL32 = 0x8 - VISIBLE_STRING = 0x9 - OCTET_STRING = 0xA - UNICODE_STRING = 0xB - TIME_OF_DAY = 0xC - TIME_DIFFERENCE = 0xD - DOMAIN = 0xF - INTEGER24 = 0x10 - REAL64 = 0x11 - INTEGER64 = 0x15 - UNSIGNED24 = 0x16 - UNSIGNED64 = 0x1B - BIT1 = 0x30 - BIT2 = 0x31 - BIT3 = 0x32 - BIT4 = 0x33 - BIT5 = 0x34 - BIT6 = 0x35 - BIT7 = 0x36 - BIT8 = 0x37 +class ECDataType(Enum): + def __new__(cls, value, fmt): + obj = object.__new__(cls) + obj._value_ = value + obj.fmt = fmt + return obj + BOOLEAN = 0x1, "?" + INTEGER8 = 0x2, "b" + INTEGER16 = 0x3, "h" + INTEGER32 = 0x4, "i" + UNSIGNED8 = 0x5, "B" + UNSIGNED16 = 0x6, "H" + UNSIGNED32 = 0x7, "I" + REAL32 = 0x8, "f" + VISIBLE_STRING = 0x9, None + OCTET_STRING = 0xA, None + UNICODE_STRING = 0xB, None + TIME_OF_DAY = 0xC, "I" + TIME_DIFFERENCE = 0xD, "i" + DOMAIN = 0xF, "i" + INTEGER24 = 0x10, "i" + REAL64 = 0x11, "d" + INTEGER64 = 0x15, "q" + UNSIGNED24 = 0x16, "i" + UNSIGNED64 = 0x1B, "Q" + BIT1 = 0x30, "B" + BIT2 = 0x31, "B" + BIT3 = 0x32, "B" + BIT4 = 0x33, "B" + BIT5 = 0x34, "B" + BIT6 = 0x35, "B" + BIT7 = 0x36, "B" + BIT8 = 0x37, "B" + UNKNOWN1 = 2048, None + UNKNOWN2 = 2049, None class MBXType(Enum): ERR = 0 # Error @@ -102,11 +109,23 @@ class ODCmd(Enum): class ObjectDescription: - pass + def __init__(self, terminal): + self.terminal = terminal class ObjectEntry: - pass + def __init__(self, desc): + self.desc = desc + + async def read(self): + ret = await self.desc.terminal.sdo_read(self.desc.index, self.valueInfo) + if self.dataType in (ECDataType.VISIBLE_STRING, + ECDataType.UNICODE_STRING): + return ret.decode("utf8") + elif self.dataType.fmt is None: + return ret + else: + return unpack("<" + self.dataType.fmt, ret)[0] def datasize(args, data): @@ -550,9 +569,9 @@ class Terminal: for index in idxes: data = await self.coe_request(CoECmd.SDOINFO, ODCmd.OD_REQ, "H", index) - dtype, oc, ms = unpack("<HBB", data[:4]) + dtype, ms, oc = unpack("<HBB", data[:4]) - od = ObjectDescription() + od = ObjectDescription(self) od.index = index od.dataType = dtype # ECDataType(dtype) od.maxSub = ms @@ -561,16 +580,16 @@ class Terminal: for od in ret: od.entries = {} - for i in range(od.maxSub): - try: - data = await self.coe_request(CoECmd.SDOINFO, ODCmd.OE_REQ, - "HBB", od.index, i, 7) - except RuntimeError: - # many OEs just do not have more description - continue - oe = ObjectEntry() - oe.valueInfo, oe.dataType, oe.bitLength, oe.objectAccess = \ + for i in range(1 if od.maxSub > 0 else 0, od.maxSub + 1): + data = await self.coe_request(CoECmd.SDOINFO, ODCmd.OE_REQ, + "HBB", od.index, i, 7) + oe = ObjectEntry(od) + oe.valueInfo, dataType, oe.bitLength, oe.objectAccess = \ unpack("<HHHH", data[:8]) + if dataType == 0: + continue + assert i == oe.valueInfo + oe.dataType = ECDataType(dataType) oe.name = data[8:].decode("utf8") od.entries[i] = oe return ret @@ -596,14 +615,12 @@ async def main(): await tout.to_operational(), odlist = await tin.read_ODlist() for o in odlist: - print(o.index, o.name) + print(hex(o.index), o.name, o.maxSub) for i, p in o.entries.items(): - print(" ", i, p.name, p.valueInfo, p.dataType, p.bitLength, p.objectAccess) - try: - sdo = await tin.sdo_read(o.index, i) - print(" ", sdo) - except RuntimeError as e: - print(" ", e) + print(" ", i, p.name, "|", p.dataType, p.bitLength, p.objectAccess) + #sdo = await tin.sdo_read(o.index, i) + sdo = await p.read() + print(" ", sdo) print("tdigi") print("bla", lookup_elem(map_fd, b"AAAA", 4)) await tdigi.to_operational(),